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 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