source: web/old/remctl-2.14/tests/util/messages-t.c @ f6f3e91

web
Last change on this file since f6f3e91 was f6f3e91, checked in by Jessica B. Hamrick <jhamrick@…>, 15 years ago

Preserve directory hierarchy (not sure what happened to it)

  • Property mode set to 100644
File size: 7.1 KB
Line 
1/*
2 * Test suite for error handling routines.
3 *
4 * Written by Russ Allbery <rra@stanford.edu>
5 * Copyright 2009 Board of Trustees, Leland Stanford Jr. University
6 * Copyright (c) 2004, 2005, 2006
7 *     by Internet Systems Consortium, Inc. ("ISC")
8 * Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
9 *     2002, 2003 by The Internet Software Consortium and Rich Salz
10 *
11 * See LICENSE for licensing terms.
12 */
13
14#include <config.h>
15#include <portable/system.h>
16
17#include <errno.h>
18#include <fcntl.h>
19#include <sys/stat.h>
20#include <sys/wait.h>
21
22#include <tests/tap/basic.h>
23#include <util/util.h>
24
25#define END (char *) 0
26
27/* Test function type. */
28typedef void (*test_function_t)(void);
29
30
31/*
32 * Fork and execute the provided function, connecting stdout and stderr to a
33 * pipe.  Captures the output into the provided buffer and returns the exit
34 * status as a waitpid status value.
35 */
36static int
37run_test(test_function_t function, char *buf, size_t buflen)
38{
39    int fds[2];
40    pid_t child;
41    ssize_t count, status;
42    int rval;
43
44    /* Flush stdout before we start to avoid odd forking issues. */
45    fflush(stdout);
46
47    /* Set up the pipe and call the function, collecting its output. */
48    if (pipe(fds) == -1)
49        sysbail("can't create pipe");
50    child = fork();
51    if (child == (pid_t) -1) {
52        sysbail("can't fork");
53    } else if (child == 0) {
54        /* In child.  Set up our stdout and stderr. */
55        close(fds[0]);
56        if (dup2(fds[1], 1) == -1)
57            _exit(255);
58        if (dup2(fds[1], 2) == -1)
59            _exit(255);
60
61        /* Now, run the function and exit successfully if it returns. */
62        (*function)();
63        fflush(stdout);
64        _exit(0);
65    } else {
66        /*
67         * In the parent; close the extra file descriptor, read the output if
68         * any, and then collect the exit status.
69         */
70        close(fds[1]);
71        count = 0;
72        do {
73            status = read(fds[0], buf + count, buflen - count - 1);
74            if (status > 0)
75                count += status;
76        } while (status > 0);
77        buf[count < 0 ? 0 : count] = '\0';
78        if (waitpid(child, &rval, 0) == (pid_t) -1)
79            sysbail("waitpid failed");
80    }
81    return rval;
82}
83
84
85/*
86 * Test functions.
87 */
88static void test1(void) { warn("warning"); }
89static void test2(void) { die("fatal"); }
90static void test3(void) { errno = EPERM; syswarn("permissions"); }
91static void test4(void) { errno = EACCES; sysdie("fatal access"); }
92static void test5(void) {
93    message_program_name = "test5";
94    warn("warning");
95}
96static void test6(void) {
97    message_program_name = "test6";
98    die("fatal");
99}
100static void test7(void) {
101    message_program_name = "test7";
102    errno = EPERM;
103    syswarn("perms %d", 7);
104}
105static void test8(void) {
106    message_program_name = "test8";
107    errno = EACCES;
108    sysdie("%st%s", "fa", "al");
109}
110
111static int return10(void) { return 10; }
112
113static void test9(void) {
114    message_fatal_cleanup = return10;
115    die("fatal");
116}
117static void test10(void) {
118    message_program_name = 0;
119    message_fatal_cleanup = return10;
120    errno = EPERM;
121    sysdie("fatal perm");
122}
123static void test11(void) {
124    message_program_name = "test11";
125    message_fatal_cleanup = return10;
126    errno = EPERM;
127    fputs("1st ", stdout);
128    sysdie("fatal");
129}
130
131static void log_msg(int len, const char *format, va_list args, int error) {
132    fprintf(stderr, "%d %d ", len, error);
133    vfprintf(stderr, format, args);
134    fprintf(stderr, "\n");
135}
136
137static void test12(void) {
138    message_handlers_warn(1, log_msg);
139    warn("warning");
140}
141static void test13(void) {
142    message_handlers_die(1, log_msg);
143    die("fatal");
144}
145static void test14(void) {
146    message_handlers_warn(2, log_msg, log_msg);
147    errno = EPERM;
148    syswarn("warning");
149}
150static void test15(void) {
151    message_handlers_die(2, log_msg, log_msg);
152    message_fatal_cleanup = return10;
153    errno = EPERM;
154    sysdie("fatal");
155}
156static void test16(void) {
157    message_handlers_warn(2, message_log_stderr, log_msg);
158    message_program_name = "test16";
159    errno = EPERM;
160    syswarn("warning");
161}
162static void test17(void) { notice("notice"); }
163static void test18(void) {
164    message_program_name = "test18";
165    notice("notice");
166}
167static void test19(void) { debug("debug"); }
168static void test20(void) {
169    message_handlers_notice(1, log_msg);
170    notice("foo");
171}
172static void test21(void) {
173    message_handlers_debug(1, message_log_stdout);
174    message_program_name = "test23";
175    debug("baz");
176}
177static void test22(void) {
178    message_handlers_die(0);
179    die("hi mom!");
180}
181static void test23(void) {
182    message_handlers_warn(0);
183    warn("this is a test");
184}
185static void test24(void) {
186    notice("first");
187    message_handlers_notice(0);
188    notice("second");
189    message_handlers_notice(1, message_log_stdout);
190    notice("third");
191}
192
193
194/*
195 * Given the intended exit status and message and the function to run, check a
196 * message test.
197 */
198static void
199test_error(int status, const char *output, test_function_t function)
200{
201    int real_status;
202    char buf[256];
203
204    real_status = run_test(function, buf, sizeof(buf));
205    ok(WIFEXITED(real_status), "%d exited", testnum);
206    is_int(status, WEXITSTATUS(real_status), "...with right status");
207    is_string(output, buf, "...and right output");
208}
209
210
211/*
212 * Given the intended status, intended message sans the appended strerror
213 * output, errno, and the function to run, check the output.
214 */
215static void
216test_strerror(int status, const char *output, int error,
217              test_function_t function)
218{
219    char *full_output;
220
221    full_output = concat(output, ": ", strerror(error), "\n", END);
222    test_error(status, full_output, function);
223    free(full_output);
224}
225
226
227/*
228 * Run the tests.
229 */
230int
231main(void)
232{
233    char buff[32];
234
235    plan(24 * 3);
236
237    test_error(0, "warning\n", test1);
238    test_error(1, "fatal\n", test2);
239    test_strerror(0, "permissions", EPERM, test3);
240    test_strerror(1, "fatal access", EACCES, test4);
241    test_error(0, "test5: warning\n", test5);
242    test_error(1, "test6: fatal\n", test6);
243    test_strerror(0, "test7: perms 7", EPERM, test7);
244    test_strerror(1, "test8: fatal", EACCES, test8);
245    test_error(10, "fatal\n", test9);
246    test_strerror(10, "fatal perm", EPERM, test10);
247    test_strerror(10, "1st test11: fatal", EPERM, test11);
248    test_error(0, "7 0 warning\n", test12);
249    test_error(1, "5 0 fatal\n", test13);
250
251    sprintf(buff, "%d", EPERM);
252
253    test_error(0, concat("7 ", buff, " warning\n7 ", buff, " warning\n", END),
254               test14);
255    test_error(10, concat("5 ", buff, " fatal\n5 ", buff, " fatal\n", END),
256               test15);
257    test_error(0, concat("test16: warning: ", strerror(EPERM), "\n7 ", buff,
258                         " warning\n", END),
259               test16);
260
261    test_error(0, "notice\n", test17);
262    test_error(0, "test18: notice\n", test18);
263    test_error(0, "", test19);
264    test_error(0, "3 0 foo\n", test20);
265    test_error(0, "test23: baz\n", test21);
266
267    /* Make sure that it's possible to turn off a message type entirely. */ 
268    test_error(1, "", test22);
269    test_error(0, "", test23);
270    test_error(0, "first\nthird\n", test24);
271
272    return 0;
273}
Note: See TracBrowser for help on using the repository browser.