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
35 struct number_format_test {
36 uint64_t number;
37 char string[21];
38 char hex_string[17];
39 };
40
41 struct signed_number_format_test {
42 int64_t number;
43 char string[21];
44 };
45
46 struct float_number_format_test {
47 double number;
48 char string[21];
49 };
50
51 static Bool
check_signed_number_format_test(long int number)52 check_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
68 static Bool
check_float_format_test(double number)69 check_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
87 static Bool
check_number_format_test(long unsigned int number)88 check_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 */
114 double 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
121 static void
number_formatting(void)122 number_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"
logging_format(void)163 static 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
399 int
signal_logging_test(void)400 signal_logging_test(void)
401 {
402 number_formatting();
403 logging_format();
404
405 return 0;
406 }
407