1 /* $NetBSD: log_test.c,v 1.6 2014/12/10 04:37:53 christos Exp $ */
2
3 /*
4 * Copyright (C) 2004, 2007, 2011, 2014 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2001 Internet Software Consortium.
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 /* Id: log_test.c,v 1.29 2011/08/28 23:46:51 marka Exp */
21
22 /* Principal Authors: DCL */
23
24 #include <config.h>
25
26 #include <stdlib.h>
27 #include <unistd.h>
28
29 #include <isc/commandline.h>
30 #include <isc/mem.h>
31 #include <isc/string.h>
32 #include <isc/util.h>
33
34 #include <dns/log.h>
35
36 #define TEST_FILE "/tmp/test_log"
37 #define SYSLOG_FILE "/var/log/daemon.log"
38 #define FILE_VERSIONS 10
39
40 char usage[] = "Usage: %s [-m] [-s syslog_logfile] [-r file_versions]\n";
41
42 #define CHECK(expr) result = expr; \
43 if (result != ISC_R_SUCCESS) { \
44 fprintf(stderr, "%s: " #expr "%s: exiting\n", \
45 progname, isc_result_totext(result)); \
46 }
47
48 int
main(int argc,char ** argv)49 main(int argc, char **argv) {
50 const char *progname, *syslog_file, *message;
51 int ch, i, file_versions, stderr_line;
52 isc_boolean_t show_final_mem = ISC_FALSE;
53 isc_log_t *lctx;
54 isc_logconfig_t *lcfg;
55 isc_mem_t *mctx;
56 isc_result_t result;
57 isc_logdestination_t destination;
58 const isc_logcategory_t *category;
59 const isc_logmodule_t *module;
60
61 progname = strrchr(*argv, '/');
62 if (progname != NULL)
63 progname++;
64 else
65 progname = *argv;
66
67 syslog_file = SYSLOG_FILE;
68 file_versions = FILE_VERSIONS;
69
70 while ((ch = isc_commandline_parse(argc, argv, "ms:r:")) != -1) {
71 switch (ch) {
72 case 'm':
73 show_final_mem = ISC_TRUE;
74 break;
75 case 's':
76 syslog_file = isc_commandline_argument;
77 break;
78 case 'r':
79 file_versions = atoi(isc_commandline_argument);
80 if (file_versions < 0 &&
81 file_versions != ISC_LOG_ROLLNEVER &&
82 file_versions != ISC_LOG_ROLLINFINITE) {
83 fprintf(stderr, "%s: file rotations must be "
84 "%d (ISC_LOG_ROLLNEVER),\n\t"
85 "%d (ISC_LOG_ROLLINFINITE) "
86 "or > 0\n", progname,
87 ISC_LOG_ROLLNEVER,
88 ISC_LOG_ROLLINFINITE);
89 exit(1);
90 }
91 break;
92 case '?':
93 fprintf(stderr, usage, progname);
94 exit(1);
95 }
96 }
97
98 argc -= isc_commandline_index;
99 argv += isc_commandline_index;
100 POST(argv);
101
102 if (argc > 0) {
103 fprintf(stderr, usage, progname);
104 exit(1);
105 }
106
107 fprintf(stderr, "EXPECT:\n%s%d%s%s%s",
108 "8 lines to stderr (first 4 numbered, #3 repeated)\n",
109 file_versions == 0 || file_versions == ISC_LOG_ROLLNEVER ? 1 :
110 file_versions > 0 ? file_versions + 1 : FILE_VERSIONS + 1,
111 " " TEST_FILE " files, and\n",
112 "2 lines to syslog\n",
113 "lines ending with exclamation marks are errors\n\n");
114
115 isc_log_opensyslog(progname, LOG_PID, LOG_DAEMON);
116
117 mctx = NULL;
118 lctx = NULL;
119 lcfg = NULL;
120
121 CHECK(isc_mem_create(0, 0, &mctx));
122 CHECK(isc_log_create(mctx, &lctx, &lcfg));
123
124 CHECK(isc_log_settag(lcfg, progname));
125
126 isc_log_setcontext(lctx);
127 dns_log_init(lctx);
128 dns_log_setcontext(lctx);
129
130 /*
131 * Test isc_log_categorybyname and isc_log_modulebyname.
132 */
133 category = isc_log_categorybyname(lctx, "notify");
134 if (category != NULL)
135 fprintf(stderr, "%s category found. (expected)\n",
136 category->name);
137 else
138 fprintf(stderr, "notify category not found!\n");
139
140 module = isc_log_modulebyname(lctx, "xyzzy");
141 if (module != NULL)
142 fprintf(stderr, "%s module found!\n", module->name);
143 else
144 fprintf(stderr, "xyzzy module not found. (expected)\n");
145
146 /*
147 * Create a file channel to test file opening, size limiting and
148 * version rolling.
149 */
150
151 destination.file.name = TEST_FILE;
152 destination.file.maximum_size = 1;
153 destination.file.versions = file_versions;
154
155 CHECK(isc_log_createchannel(lcfg, "file_test", ISC_LOG_TOFILE,
156 ISC_LOG_INFO, &destination,
157 ISC_LOG_PRINTTIME|
158 ISC_LOG_PRINTTAG|
159 ISC_LOG_PRINTLEVEL|
160 ISC_LOG_PRINTCATEGORY|
161 ISC_LOG_PRINTMODULE));
162
163 /*
164 * Create a dynamic debugging channel to a file descriptor.
165 */
166 destination.file.stream = stderr;
167
168 CHECK(isc_log_createchannel(lcfg, "debug_test", ISC_LOG_TOFILEDESC,
169 ISC_LOG_DYNAMIC, &destination,
170 ISC_LOG_PRINTTIME|
171 ISC_LOG_PRINTLEVEL|
172 ISC_LOG_DEBUGONLY));
173
174 /*
175 * Test the usability of the four predefined logging channels.
176 */
177 CHECK(isc_log_usechannel(lcfg, "default_syslog",
178 DNS_LOGCATEGORY_DATABASE,
179 DNS_LOGMODULE_CACHE));
180 CHECK(isc_log_usechannel(lcfg, "default_stderr",
181 DNS_LOGCATEGORY_DATABASE,
182 DNS_LOGMODULE_CACHE));
183 CHECK(isc_log_usechannel(lcfg, "default_debug",
184 DNS_LOGCATEGORY_DATABASE,
185 DNS_LOGMODULE_CACHE));
186 CHECK(isc_log_usechannel(lcfg, "null",
187 DNS_LOGCATEGORY_DATABASE,
188 NULL));
189
190 /*
191 * Use the custom channels.
192 */
193 CHECK(isc_log_usechannel(lcfg, "file_test",
194 DNS_LOGCATEGORY_GENERAL,
195 DNS_LOGMODULE_DB));
196
197 CHECK(isc_log_usechannel(lcfg, "debug_test",
198 DNS_LOGCATEGORY_GENERAL,
199 DNS_LOGMODULE_RBTDB));
200
201 fprintf(stderr, "\n==> stderr begin\n");
202
203 /*
204 * Write to the internal default by testing both a category for which
205 * no channel has been specified and a category which was specified
206 * but not with the named module.
207 */
208 stderr_line = 1;
209
210 isc_log_write(lctx, DNS_LOGCATEGORY_SECURITY, DNS_LOGMODULE_RBT,
211 ISC_LOG_CRITICAL, "%s (%d)",
212 "Unspecified category and unspecified module to stderr",
213 stderr_line++);
214 isc_log_write(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBT,
215 ISC_LOG_CRITICAL, "%s (%d)",
216 "Specified category and unspecified module to stderr",
217 stderr_line++);
218
219 /*
220 * Write to default_syslog, default_stderr and default_debug.
221 */
222 isc_log_write(lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_CACHE,
223 ISC_LOG_WARNING, "%s (%d twice)",
224 "Using the predefined channels to syslog+stderr",
225 stderr_line++);
226
227 /*
228 * Write to predefined null channel.
229 */
230 isc_log_write(lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_RBTDB,
231 ISC_LOG_INFO, "This is to null and should not appear!");
232
233 /*
234 * Reset the internal default to use syslog instead of stderr,
235 * and test it.
236 */
237 CHECK(isc_log_usechannel(lcfg, "default_syslog",
238 ISC_LOGCATEGORY_DEFAULT, NULL));
239 isc_log_write(lctx, DNS_LOGCATEGORY_SECURITY, DNS_LOGMODULE_RBT,
240 ISC_LOG_ERROR, "%s%s",
241 "This message to the redefined default category should ",
242 "be second in syslog");
243 /*
244 * Write to the file channel.
245 */
246 if (file_versions >= 0 || file_versions == ISC_LOG_ROLLINFINITE) {
247
248 /*
249 * If file_versions is 0 or ISC_LOG_ROLLINFINITE, write
250 * the "should not appear" and "should be in file" messages
251 * to ensure they get rolled.
252 */
253 if (file_versions <= 0)
254 file_versions = FILE_VERSIONS;
255
256 else
257 isc_log_write(lctx, DNS_LOGCATEGORY_GENERAL,
258 DNS_LOGMODULE_DB, ISC_LOG_NOTICE,
259 "This should be rolled over "
260 "and not appear!");
261
262 for (i = file_versions - 1; i >= 0; i--)
263 isc_log_write(lctx, DNS_LOGCATEGORY_GENERAL,
264 DNS_LOGMODULE_DB, ISC_LOG_NOTICE,
265 "should be in file %d/%d", i,
266 file_versions - 1);
267
268 isc_log_write(lctx, DNS_LOGCATEGORY_GENERAL,
269 DNS_LOGMODULE_DB, ISC_LOG_NOTICE,
270 "should be in base file");
271 } else {
272 file_versions = FILE_VERSIONS;
273 for (i = 1; i <= file_versions; i++)
274 isc_log_write(lctx, DNS_LOGCATEGORY_GENERAL,
275 DNS_LOGMODULE_DB, ISC_LOG_NOTICE,
276 "This is message %d in the log file", i);
277 }
278
279
280 /*
281 * Write a debugging message to a category that has no
282 * debugging channels for the named module.
283 */
284 isc_log_write(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_DB,
285 ISC_LOG_DEBUG(1),
286 "This debug message should not appear!");
287
288 /*
289 * Write debugging messages to a dynamic debugging channel.
290 */
291 isc_log_write(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBTDB,
292 ISC_LOG_CRITICAL, "This critical message should "
293 "not appear because the debug level is 0!");
294
295 isc_log_setdebuglevel(lctx, 3);
296
297 isc_log_write(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBTDB,
298 ISC_LOG_DEBUG(1), "%s (%d)",
299 "Dynamic debugging to stderr", stderr_line++);
300 isc_log_write(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBTDB,
301 ISC_LOG_DEBUG(5),
302 "This debug level is too high and should not appear!");
303
304 /*
305 * Test out the duplicate filtering using the debug_test channel.
306 */
307 isc_log_setduplicateinterval(lcfg, 10);
308 message = "This message should appear only once on stderr";
309
310 isc_log_write1(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBTDB,
311 ISC_LOG_CRITICAL, "%s", message);
312 isc_log_write1(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBTDB,
313 ISC_LOG_CRITICAL, "%s", message);
314
315 isc_log_setduplicateinterval(lcfg, 1);
316 message = "This message should appear twice on stderr";
317
318 isc_log_write1(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBTDB,
319 ISC_LOG_CRITICAL, "%s", message);
320 sleep(2);
321 isc_log_write1(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBTDB,
322 ISC_LOG_CRITICAL, "%s", message);
323
324 /*
325 * Review where everything went.
326 * XXXDCL NT
327 */
328 fputc('\n', stderr);
329 if (system("head " TEST_FILE "*; rm -f " TEST_FILE "*") != 0) {
330 fprintf(stderr, "system(\"head " TEST_FILE "*; rm -f "
331 TEST_FILE "*\") failed\n");
332 goto cleanup;
333 }
334
335 /* This is highly system specific. */
336 if (freopen(syslog_file, "r", stdin) == NULL) {
337 fprintf(stderr, "freopen(%s, \"r\", stdin) failed\n",
338 syslog_file);
339 goto cleanup;
340 }
341 fprintf(stderr, "\n==> %s <==\n", syslog_file);
342 if (system("tail -2") != 0) {
343 fprintf(stderr, "system(\"tail -2\") failed\n");
344 goto cleanup;
345 }
346 fputc('\n', stderr);
347
348 cleanup:
349 isc_log_destroy(&lctx);
350
351 if (show_final_mem)
352 isc_mem_stats(mctx, stderr);
353
354 return (0);
355 }
356