signal-logging.c revision 1b5d61b8
1/** 2 * Copyright © 2012 Canonical, Ltd. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24#ifdef HAVE_DIX_CONFIG_H 25#include <dix-config.h> 26#endif 27 28#include <stdint.h> 29#include <unistd.h> 30#include "assert.h" 31#include "misc.h" 32 33#include "tests-common.h" 34 35struct number_format_test { 36 uint64_t number; 37 char string[21]; 38 char hex_string[17]; 39}; 40 41struct signed_number_format_test { 42 int64_t number; 43 char string[21]; 44}; 45 46struct float_number_format_test { 47 double number; 48 char string[21]; 49}; 50 51static Bool 52check_signed_number_format_test(long int number) 53{ 54 char string[21]; 55 char expected[21]; 56 57 sprintf(expected, "%ld", number); 58 FormatInt64(number, string); 59 if(strncmp(string, expected, 21) != 0) { 60 fprintf(stderr, "Failed to convert %jd to decimal string (expected %s but got %s)\n", 61 (intmax_t) number, expected, string); 62 return FALSE; 63 } 64 65 return TRUE; 66} 67 68static Bool 69check_float_format_test(double number) 70{ 71 char string[21]; 72 char expected[21]; 73 74 /* we currently always print float as .2f */ 75 sprintf(expected, "%.2f", number); 76 77 FormatDouble(number, string); 78 if(strncmp(string, expected, 21) != 0) { 79 fprintf(stderr, "Failed to convert %f to string (%s vs %s)\n", 80 number, expected, string); 81 return FALSE; 82 } 83 84 return TRUE; 85} 86 87static Bool 88check_number_format_test(long unsigned int number) 89{ 90 char string[21]; 91 char expected[21]; 92 93 sprintf(expected, "%lu", number); 94 95 FormatUInt64(number, string); 96 if(strncmp(string, expected, 21) != 0) { 97 fprintf(stderr, "Failed to convert %ju to decimal string (%s vs %s)\n", 98 (intmax_t) number, expected, string); 99 return FALSE; 100 } 101 102 sprintf(expected, "%lx", number); 103 FormatUInt64Hex(number, string); 104 if(strncmp(string, expected, 17) != 0) { 105 fprintf(stderr, "Failed to convert %ju to hexadecimal string (%s vs %s)\n", 106 (intmax_t) number, expected, string); 107 return FALSE; 108 } 109 110 return TRUE; 111} 112 113/* FIXME: max range stuff */ 114double float_tests[] = { 0, 5, 0.1, 0.01, 5.2342, 10.2301, 115 -1, -2.00, -0.6023, -1203.30 116 }; 117 118#pragma GCC diagnostic push 119#pragma GCC diagnostic ignored "-Woverflow" 120 121static void 122number_formatting(void) 123{ 124 int i; 125 long unsigned int unsigned_tests[] = { 0,/* Zero */ 126 5, /* Single digit number */ 127 12, /* Two digit decimal number */ 128 37, /* Two digit hex number */ 129 0xC90B2, /* Large < 32 bit number */ 130 0x15D027BF211B37A, /* Large > 32 bit number */ 131 0xFFFFFFFFFFFFFFFF, /* Maximum 64-bit number */ 132 }; 133 134 long int signed_tests[] = { 0,/* Zero */ 135 5, /* Single digit number */ 136 12, /* Two digit decimal number */ 137 37, /* Two digit hex number */ 138 0xC90B2, /* Large < 32 bit number */ 139 0x15D027BF211B37A, /* Large > 32 bit number */ 140 0x7FFFFFFFFFFFFFFF, /* Maximum 64-bit signed number */ 141 -1, /* Single digit number */ 142 -12, /* Two digit decimal number */ 143 -0xC90B2, /* Large < 32 bit number */ 144 -0x15D027BF211B37A, /* Large > 32 bit number */ 145 -0x7FFFFFFFFFFFFFFF, /* Maximum 64-bit signed number */ 146 } ; 147 148 for (i = 0; i < ARRAY_SIZE(unsigned_tests); i++) 149 assert(check_number_format_test(unsigned_tests[i])); 150 151 for (i = 0; i < ARRAY_SIZE(signed_tests); i++) 152 assert(check_signed_number_format_test(signed_tests[i])); 153 154 for (i = 0; i < ARRAY_SIZE(float_tests); i++) 155 assert(check_float_format_test(float_tests[i])); 156} 157#pragma GCC diagnostic pop 158 159#pragma GCC diagnostic push 160#pragma GCC diagnostic ignored "-Wformat-security" 161#pragma GCC diagnostic ignored "-Wformat" 162#pragma GCC diagnostic ignored "-Wformat-extra-args" 163static void logging_format(void) 164{ 165 const char *log_file_path = "/tmp/Xorg-logging-test.log"; 166 const char *str = "%s %d %u %% %p %i"; 167 char buf[1024]; 168 int i; 169 unsigned int ui; 170 long li; 171 unsigned long lui; 172 FILE *f; 173 char read_buf[2048]; 174 char *logmsg; 175 uintptr_t ptr; 176 177 /* set up buf to contain ".....end" */ 178 memset(buf, '.', sizeof(buf)); 179 strcpy(&buf[sizeof(buf) - 4], "end"); 180 181 LogInit(log_file_path, NULL); 182 assert((f = fopen(log_file_path, "r"))); 183 184#define read_log_msg(msg) do { \ 185 msg = fgets(read_buf, sizeof(read_buf), f); \ 186 assert(msg != NULL); \ 187 msg = strchr(read_buf, ']'); \ 188 assert(msg != NULL); \ 189 assert(strlen(msg) > 2); \ 190 msg = msg + 2; /* advance past [time.stamp] */ \ 191 } while (0) 192 193 /* boring test message */ 194 LogMessageVerbSigSafe(X_ERROR, -1, "test message\n"); 195 read_log_msg(logmsg); 196 assert(strcmp(logmsg, "(EE) test message\n") == 0); 197 198 /* long buf is truncated to "....en\n" */ 199 LogMessageVerbSigSafe(X_ERROR, -1, buf); 200 read_log_msg(logmsg); 201 assert(strcmp(&logmsg[strlen(logmsg) - 3], "en\n") == 0); 202 203 /* same thing, this time as string substitution */ 204 LogMessageVerbSigSafe(X_ERROR, -1, "%s", buf); 205 read_log_msg(logmsg); 206 assert(strcmp(&logmsg[strlen(logmsg) - 3], "en\n") == 0); 207 208 /* strings containing placeholders should just work */ 209 LogMessageVerbSigSafe(X_ERROR, -1, "%s\n", str); 210 read_log_msg(logmsg); 211 assert(strcmp(logmsg, "(EE) %s %d %u %% %p %i\n") == 0); 212 213 /* literal % */ 214 LogMessageVerbSigSafe(X_ERROR, -1, "test %%\n"); 215 read_log_msg(logmsg); 216 assert(strcmp(logmsg, "(EE) test %\n") == 0); 217 218 /* character */ 219 LogMessageVerbSigSafe(X_ERROR, -1, "test %c\n", 'a'); 220 read_log_msg(logmsg); 221 assert(strcmp(logmsg, "(EE) test a\n") == 0); 222 223 /* something unsupported % */ 224 LogMessageVerbSigSafe(X_ERROR, -1, "test %Q\n"); 225 read_log_msg(logmsg); 226 assert(strstr(logmsg, "BUG") != NULL); 227 LogMessageVerbSigSafe(X_ERROR, -1, "\n"); 228 fseek(f, 0, SEEK_END); 229 230 /* string substitution */ 231 LogMessageVerbSigSafe(X_ERROR, -1, "%s\n", "substituted string"); 232 read_log_msg(logmsg); 233 assert(strcmp(logmsg, "(EE) substituted string\n") == 0); 234 235 /* Invalid format */ 236 LogMessageVerbSigSafe(X_ERROR, -1, "%4", 4); 237 read_log_msg(logmsg); 238 assert(strcmp(logmsg, "(EE) ") == 0); 239 LogMessageVerbSigSafe(X_ERROR, -1, "\n"); 240 fseek(f, 0, SEEK_END); 241 242 /* %hld is bogus */ 243 LogMessageVerbSigSafe(X_ERROR, -1, "%hld\n", 4); 244 read_log_msg(logmsg); 245 assert(strstr(logmsg, "BUG") != NULL); 246 LogMessageVerbSigSafe(X_ERROR, -1, "\n"); 247 fseek(f, 0, SEEK_END); 248 249 /* number substitution */ 250 ui = 0; 251 do { 252 char expected[30]; 253 sprintf(expected, "(EE) %u\n", ui); 254 LogMessageVerbSigSafe(X_ERROR, -1, "%u\n", ui); 255 read_log_msg(logmsg); 256 assert(strcmp(logmsg, expected) == 0); 257 258 sprintf(expected, "(EE) %x\n", ui); 259 LogMessageVerbSigSafe(X_ERROR, -1, "%x\n", ui); 260 read_log_msg(logmsg); 261 assert(strcmp(logmsg, expected) == 0); 262 263 if (ui == 0) 264 ui = 1; 265 else 266 ui <<= 1; 267 } while(ui); 268 269 lui = 0; 270 do { 271 char expected[30]; 272 sprintf(expected, "(EE) %lu\n", lui); 273 LogMessageVerbSigSafe(X_ERROR, -1, "%lu\n", lui); 274 read_log_msg(logmsg); 275 276 sprintf(expected, "(EE) %lld\n", (unsigned long long)ui); 277 LogMessageVerbSigSafe(X_ERROR, -1, "%lld\n", (unsigned long long)ui); 278 read_log_msg(logmsg); 279 assert(strcmp(logmsg, expected) == 0); 280 281 sprintf(expected, "(EE) %lx\n", lui); 282 printf("%s\n", expected); 283 LogMessageVerbSigSafe(X_ERROR, -1, "%lx\n", lui); 284 read_log_msg(logmsg); 285 assert(strcmp(logmsg, expected) == 0); 286 287 sprintf(expected, "(EE) %llx\n", (unsigned long long)ui); 288 LogMessageVerbSigSafe(X_ERROR, -1, "%llx\n", (unsigned long long)ui); 289 read_log_msg(logmsg); 290 assert(strcmp(logmsg, expected) == 0); 291 292 if (lui == 0) 293 lui = 1; 294 else 295 lui <<= 1; 296 } while(lui); 297 298 /* signed number substitution */ 299 i = 0; 300 do { 301 char expected[30]; 302 sprintf(expected, "(EE) %d\n", i); 303 LogMessageVerbSigSafe(X_ERROR, -1, "%d\n", i); 304 read_log_msg(logmsg); 305 assert(strcmp(logmsg, expected) == 0); 306 307 sprintf(expected, "(EE) %d\n", i | INT_MIN); 308 LogMessageVerbSigSafe(X_ERROR, -1, "%d\n", i | INT_MIN); 309 read_log_msg(logmsg); 310 assert(strcmp(logmsg, expected) == 0); 311 312 if (i == 0) 313 i = 1; 314 else 315 i <<= 1; 316 } while(i > INT_MIN); 317 318 li = 0; 319 do { 320 char expected[30]; 321 sprintf(expected, "(EE) %ld\n", li); 322 LogMessageVerbSigSafe(X_ERROR, -1, "%ld\n", li); 323 read_log_msg(logmsg); 324 assert(strcmp(logmsg, expected) == 0); 325 326 sprintf(expected, "(EE) %ld\n", li | LONG_MIN); 327 LogMessageVerbSigSafe(X_ERROR, -1, "%ld\n", li | LONG_MIN); 328 read_log_msg(logmsg); 329 assert(strcmp(logmsg, expected) == 0); 330 331 sprintf(expected, "(EE) %lld\n", (long long)li); 332 LogMessageVerbSigSafe(X_ERROR, -1, "%lld\n", (long long)li); 333 read_log_msg(logmsg); 334 assert(strcmp(logmsg, expected) == 0); 335 336 sprintf(expected, "(EE) %lld\n", (long long)(li | LONG_MIN)); 337 LogMessageVerbSigSafe(X_ERROR, -1, "%lld\n", (long long)(li | LONG_MIN)); 338 read_log_msg(logmsg); 339 assert(strcmp(logmsg, expected) == 0); 340 341 if (li == 0) 342 li = 1; 343 else 344 li <<= 1; 345 } while(li > LONG_MIN); 346 347 348 /* pointer substitution */ 349 /* we print a null-pointer differently to printf */ 350 LogMessageVerbSigSafe(X_ERROR, -1, "%p\n", NULL); 351 read_log_msg(logmsg); 352 assert(strcmp(logmsg, "(EE) 0x0\n") == 0); 353 354 ptr = 1; 355 do { 356 char expected[30]; 357#ifdef __sun /* Solaris doesn't autoadd "0x" to %p format */ 358 sprintf(expected, "(EE) 0x%p\n", (void*)ptr); 359#else 360 sprintf(expected, "(EE) %p\n", (void*)ptr); 361#endif 362 LogMessageVerbSigSafe(X_ERROR, -1, "%p\n", (void*)ptr); 363 read_log_msg(logmsg); 364 assert(strcmp(logmsg, expected) == 0); 365 ptr <<= 1; 366 } while(ptr); 367 368 369 for (i = 0; i < ARRAY_SIZE(float_tests); i++) { 370 double d = float_tests[i]; 371 char expected[30]; 372 sprintf(expected, "(EE) %.2f\n", d); 373 LogMessageVerbSigSafe(X_ERROR, -1, "%f\n", d); 374 read_log_msg(logmsg); 375 assert(strcmp(logmsg, expected) == 0); 376 377 /* test for length modifiers, we just ignore them atm */ 378 LogMessageVerbSigSafe(X_ERROR, -1, "%.3f\n", d); 379 read_log_msg(logmsg); 380 assert(strcmp(logmsg, expected) == 0); 381 382 LogMessageVerbSigSafe(X_ERROR, -1, "%3f\n", d); 383 read_log_msg(logmsg); 384 assert(strcmp(logmsg, expected) == 0); 385 386 LogMessageVerbSigSafe(X_ERROR, -1, "%.0f\n", d); 387 read_log_msg(logmsg); 388 assert(strcmp(logmsg, expected) == 0); 389 } 390 391 392 LogClose(EXIT_NO_ERROR); 393 unlink(log_file_path); 394 395#undef read_log_msg 396} 397#pragma GCC diagnostic pop /* "-Wformat-security" */ 398 399int 400signal_logging_test(void) 401{ 402 number_formatting(); 403 logging_format(); 404 405 return 0; 406} 407