]> git.cworth.org Git - apitrace/blob - thirdparty/libbacktrace/btest.c
Update GLX attrib_list support from GLX 1.3 to 1.4.
[apitrace] / thirdparty / libbacktrace / btest.c
1 /* btest.c -- Test for libbacktrace library
2    Copyright (C) 2012-2013 Free Software Foundation, Inc.
3    Written by Ian Lance Taylor, Google.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9     (1) Redistributions of source code must retain the above copyright
10     notice, this list of conditions and the following disclaimer. 
11
12     (2) Redistributions in binary form must reproduce the above copyright
13     notice, this list of conditions and the following disclaimer in
14     the documentation and/or other materials provided with the
15     distribution.  
16     
17     (3) The name of the author may not be used to
18     endorse or promote products derived from this software without
19     specific prior written permission.
20
21 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30 IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 POSSIBILITY OF SUCH DAMAGE.  */
32
33 /* This program tests the externally visible interfaces of the
34    libbacktrace library.  */
35
36 #include <assert.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40
41 #include "filenames.h"
42
43 #include "backtrace.h"
44 #include "backtrace-supported.h"
45
46 /* Portable attribute syntax.  Actually some of these tests probably
47    won't work if the attributes are not recognized.  */
48
49 #ifndef GCC_VERSION
50 # define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
51 #endif
52
53 #if (GCC_VERSION < 2007)
54 # define __attribute__(x)
55 #endif
56
57 #ifndef ATTRIBUTE_UNUSED
58 # define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
59 #endif
60
61 /* Used to collect backtrace info.  */
62
63 struct info
64 {
65   char *filename;
66   int lineno;
67   char *function;
68 };
69
70 /* Passed to backtrace callback function.  */
71
72 struct bdata
73 {
74   struct info *all;
75   size_t index;
76   size_t max;
77   int failed;
78 };
79
80 /* Passed to backtrace_simple callback function.  */
81
82 struct sdata
83 {
84   uintptr_t *addrs;
85   size_t index;
86   size_t max;
87   int failed;
88 };
89
90 /* Passed to backtrace_syminfo callback function.  */
91
92 struct symdata
93 {
94   const char *name;
95   uintptr_t val;
96   int failed;
97 };
98
99 /* The backtrace state.  */
100
101 static void *state;
102
103 /* The number of failures.  */
104
105 static int failures;
106
107 /* Return the base name in a path.  */
108
109 static const char *
110 base (const char *p)
111 {
112   const char *last;
113   const char *s;
114
115   last = NULL;
116   for (s = p; *s != '\0'; ++s)
117     {
118       if (IS_DIR_SEPARATOR (*s))
119         last = s + 1;
120     }
121   return last != NULL ? last : p;
122 }
123
124 /* Check an entry in a struct info array.  */
125
126 static void
127 check (const char *name, int index, const struct info *all, int want_lineno,
128        const char *want_function, int *failed)
129 {
130   if (*failed)
131     return;
132   if (strcmp (base (all[index].filename), "btest.c") != 0)
133     {
134       fprintf (stderr, "%s: [%d]: got %s expected test.c\n", name, index,
135                all[index].filename);
136       *failed = 1;
137     }
138   if (all[index].lineno != want_lineno)
139     {
140       fprintf (stderr, "%s: [%d]: got %d expected %d\n", name, index,
141                all[index].lineno, want_lineno);
142       *failed = 1;
143     }
144   if (strcmp (all[index].function, want_function) != 0)
145     {
146       fprintf (stderr, "%s: [%d]: got %s expected %s\n", name, index,
147                all[index].function, want_function);
148       *failed = 1;
149     }
150 }
151
152 /* The backtrace callback function.  */
153
154 static int
155 callback_one (void *vdata, uintptr_t pc ATTRIBUTE_UNUSED,
156               const char *filename, int lineno, const char *function)
157 {
158   struct bdata *data = (struct bdata *) vdata;
159   struct info *p;
160
161   if (data->index >= data->max)
162     {
163       fprintf (stderr, "callback_one: callback called too many times\n");
164       data->failed = 1;
165       return 1;
166     }
167
168   p = &data->all[data->index];
169   if (filename == NULL)
170     p->filename = NULL;
171   else
172     {
173       p->filename = strdup (filename);
174       assert (p->filename != NULL);
175     }
176   p->lineno = lineno;
177   if (function == NULL)
178     p->function = NULL;
179   else
180     {
181       p->function = strdup (function);
182       assert (p->function != NULL);
183     }
184   ++data->index;
185
186   return 0;
187 }
188
189 /* An error callback passed to backtrace.  */
190
191 static void
192 error_callback_one (void *vdata, const char *msg, int errnum)
193 {
194   struct bdata *data = (struct bdata *) vdata;
195
196   fprintf (stderr, "%s", msg);
197   if (errnum > 0)
198     fprintf (stderr, ": %s", strerror (errnum));
199   fprintf (stderr, "\n");
200   data->failed = 1;
201 }
202
203 /* The backtrace_simple callback function.  */
204
205 static int
206 callback_two (void *vdata, uintptr_t pc)
207 {
208   struct sdata *data = (struct sdata *) vdata;
209
210   if (data->index >= data->max)
211     {
212       fprintf (stderr, "callback_two: callback called too many times\n");
213       data->failed = 1;
214       return 1;
215     }
216
217   data->addrs[data->index] = pc;
218   ++data->index;
219
220   return 0;
221 }
222
223 /* An error callback passed to backtrace_simple.  */
224
225 static void
226 error_callback_two (void *vdata, const char *msg, int errnum)
227 {
228   struct sdata *data = (struct sdata *) vdata;
229
230   fprintf (stderr, "%s", msg);
231   if (errnum > 0)
232     fprintf (stderr, ": %s", strerror (errnum));
233   fprintf (stderr, "\n");
234   data->failed = 1;
235 }
236
237 /* The backtrace_syminfo callback function.  */
238
239 static void
240 callback_three (void *vdata, uintptr_t pc ATTRIBUTE_UNUSED,
241                 const char *symname, uintptr_t symval)
242 {
243   struct symdata *data = (struct symdata *) vdata;
244
245   if (symname == NULL)
246     data->name = NULL;
247   else
248     {
249       data->name = strdup (symname);
250       assert (data->name != NULL);
251     }
252   data->val = symval;
253 }
254
255 /* The backtrace_syminfo error callback function.  */
256
257 static void
258 error_callback_three (void *vdata, const char *msg, int errnum)
259 {
260   struct symdata *data = (struct symdata *) vdata;
261
262   fprintf (stderr, "%s", msg);
263   if (errnum > 0)
264     fprintf (stderr, ": %s", strerror (errnum));
265   fprintf (stderr, "\n");
266   data->failed = 1;
267 }
268
269 /* Test the backtrace function with non-inlined functions.  */
270
271 static int test1 (void) __attribute__ ((noinline, unused));
272 static int f2 (int) __attribute__ ((noinline));
273 static int f3 (int, int) __attribute__ ((noinline));
274
275 static int
276 test1 (void)
277 {
278   /* Returning a value here and elsewhere avoids a tailcall which
279      would mess up the backtrace.  */
280   return f2 (__LINE__) + 1;
281 }
282
283 static int
284 f2 (int f1line)
285 {
286   return f3 (f1line, __LINE__) + 2;
287 }
288
289 static int
290 f3 (int f1line, int f2line)
291 {
292   struct info all[20];
293   struct bdata data;
294   int f3line;
295   int i;
296
297   data.all = &all[0];
298   data.index = 0;
299   data.max = 20;
300   data.failed = 0;
301
302   f3line = __LINE__ + 1;
303   i = backtrace_full (state, 0, callback_one, error_callback_one, &data);
304
305   if (i != 0)
306     {
307       fprintf (stderr, "test1: unexpected return value %d\n", i);
308       data.failed = 1;
309     }
310
311   check ("test1", 0, all, f3line, "f3", &data.failed);
312   check ("test1", 1, all, f2line, "f2", &data.failed);
313   check ("test1", 2, all, f1line, "test1", &data.failed);
314
315   printf ("%s: backtrace_full noinline\n", data.failed ? "FAIL" : "PASS");
316
317   if (data.failed)
318     ++failures;
319
320   return failures;
321 }
322
323 /* Test the backtrace function with inlined functions.  */
324
325 static inline int test2 (void) __attribute__ ((always_inline, unused));
326 static inline int f12 (int) __attribute__ ((always_inline));
327 static inline int f13 (int, int) __attribute__ ((always_inline));
328
329 static inline int
330 test2 (void)
331 {
332   return f12 (__LINE__) + 1;
333 }
334
335 static inline int
336 f12 (int f1line)
337 {
338   return f13 (f1line, __LINE__) + 2;
339 }
340
341 static inline int
342 f13 (int f1line, int f2line)
343 {
344   struct info all[20];
345   struct bdata data;
346   int f3line;
347   int i;
348
349   data.all = &all[0];
350   data.index = 0;
351   data.max = 20;
352   data.failed = 0;
353
354   f3line = __LINE__ + 1;
355   i = backtrace_full (state, 0, callback_one, error_callback_one, &data);
356
357   if (i != 0)
358     {
359       fprintf (stderr, "test2: unexpected return value %d\n", i);
360       data.failed = 1;
361     }
362
363   check ("test2", 0, all, f3line, "f13", &data.failed);
364   check ("test2", 1, all, f2line, "f12", &data.failed);
365   check ("test2", 2, all, f1line, "test2", &data.failed);
366
367   printf ("%s: backtrace_full inline\n", data.failed ? "FAIL" : "PASS");
368
369   if (data.failed)
370     ++failures;
371
372   return failures;
373 }
374
375 /* Test the backtrace_simple function with non-inlined functions.  */
376
377 static int test3 (void) __attribute__ ((noinline, unused));
378 static int f22 (int) __attribute__ ((noinline));
379 static int f23 (int, int) __attribute__ ((noinline));
380
381 static int
382 test3 (void)
383 {
384   return f22 (__LINE__) + 1;
385 }
386
387 static int
388 f22 (int f1line)
389 {
390   return f23 (f1line, __LINE__) + 2;
391 }
392
393 static int
394 f23 (int f1line, int f2line)
395 {
396   uintptr_t addrs[20];
397   struct sdata data;
398   int f3line;
399   int i;
400
401   data.addrs = &addrs[0];
402   data.index = 0;
403   data.max = 20;
404   data.failed = 0;
405
406   f3line = __LINE__ + 1;
407   i = backtrace_simple (state, 0, callback_two, error_callback_two, &data);
408
409   if (i != 0)
410     {
411       fprintf (stderr, "test3: unexpected return value %d\n", i);
412       data.failed = 1;
413     }
414
415   if (!data.failed)
416     {
417       struct info all[20];
418       struct bdata bdata;
419       int j;
420
421       bdata.all = &all[0];
422       bdata.index = 0;
423       bdata.max = 20;
424       bdata.failed = 0;
425
426       for (j = 0; j < 3; ++j)
427         {
428           i = backtrace_pcinfo (state, addrs[j], callback_one,
429                                 error_callback_one, &bdata);
430           if (i != 0)
431             {
432               fprintf (stderr,
433                        ("test3: unexpected return value "
434                         "from backtrace_pcinfo %d\n"),
435                        i);
436               bdata.failed = 1;
437             }
438           if (!bdata.failed && bdata.index != (size_t) (j + 1))
439             {
440               fprintf (stderr,
441                        ("wrong number of calls from backtrace_pcinfo "
442                         "got %u expected %d\n"),
443                        (unsigned int) bdata.index, j + 1);
444               bdata.failed = 1;
445             }
446         }      
447
448       check ("test3", 0, all, f3line, "f23", &bdata.failed);
449       check ("test3", 1, all, f2line, "f22", &bdata.failed);
450       check ("test3", 2, all, f1line, "test3", &bdata.failed);
451
452       if (bdata.failed)
453         data.failed = 1;
454
455       for (j = 0; j < 3; ++j)
456         {
457           struct symdata symdata;
458
459           symdata.name = NULL;
460           symdata.val = 0;
461           symdata.failed = 0;
462
463           i = backtrace_syminfo (state, addrs[j], callback_three,
464                                  error_callback_three, &symdata);
465           if (i == 0)
466             {
467               fprintf (stderr,
468                        ("test3: [%d]: unexpected return value "
469                         "from backtrace_syminfo %d\n"),
470                        j, i);
471               symdata.failed = 1;
472             }
473
474           if (!symdata.failed)
475             {
476               const char *expected;
477
478               switch (j)
479                 {
480                 case 0:
481                   expected = "f23";
482                   break;
483                 case 1:
484                   expected = "f22";
485                   break;
486                 case 2:
487                   expected = "test3";
488                   break;
489                 default:
490                   assert (0);
491                 }
492
493               if (symdata.name == NULL)
494                 {
495                   fprintf (stderr, "test3: [%d]: NULL syminfo name\n", j);
496                   symdata.failed = 1;
497                 }
498               /* Use strncmp, not strcmp, because GCC might create a
499                  clone.  */
500               else if (strncmp (symdata.name, expected, strlen (expected))
501                        != 0)
502                 {
503                   fprintf (stderr,
504                            ("test3: [%d]: unexpected syminfo name "
505                             "got %s expected %s\n"),
506                            j, symdata.name, expected);
507                   symdata.failed = 1;
508                 }
509             }
510
511           if (symdata.failed)
512             data.failed = 1;
513         }
514     }
515
516   printf ("%s: backtrace_simple noinline\n", data.failed ? "FAIL" : "PASS");
517
518   if (data.failed)
519     ++failures;
520
521   return failures;
522 }
523
524 /* Test the backtrace_simple function with inlined functions.  */
525
526 static inline int test4 (void) __attribute__ ((always_inline, unused));
527 static inline int f32 (int) __attribute__ ((always_inline));
528 static inline int f33 (int, int) __attribute__ ((always_inline));
529
530 static inline int
531 test4 (void)
532 {
533   return f32 (__LINE__) + 1;
534 }
535
536 static inline int
537 f32 (int f1line)
538 {
539   return f33 (f1line, __LINE__) + 2;
540 }
541
542 static inline int
543 f33 (int f1line, int f2line)
544 {
545   uintptr_t addrs[20];
546   struct sdata data;
547   int f3line;
548   int i;
549
550   data.addrs = &addrs[0];
551   data.index = 0;
552   data.max = 20;
553   data.failed = 0;
554
555   f3line = __LINE__ + 1;
556   i = backtrace_simple (state, 0, callback_two, error_callback_two, &data);
557
558   if (i != 0)
559     {
560       fprintf (stderr, "test3: unexpected return value %d\n", i);
561       data.failed = 1;
562     }
563
564   if (!data.failed)
565     {
566       struct info all[20];
567       struct bdata bdata;
568
569       bdata.all = &all[0];
570       bdata.index = 0;
571       bdata.max = 20;
572       bdata.failed = 0;
573
574       i = backtrace_pcinfo (state, addrs[0], callback_one, error_callback_one,
575                             &bdata);
576       if (i != 0)
577         {
578           fprintf (stderr,
579                    ("test4: unexpected return value "
580                     "from backtrace_pcinfo %d\n"),
581                    i);
582           bdata.failed = 1;
583         }
584
585       check ("test4", 0, all, f3line, "f33", &bdata.failed);
586       check ("test4", 1, all, f2line, "f32", &bdata.failed);
587       check ("test4", 2, all, f1line, "test4", &bdata.failed);
588
589       if (bdata.failed)
590         data.failed = 1;
591     }
592
593   printf ("%s: backtrace_simple inline\n", data.failed ? "FAIL" : "PASS");
594
595   if (data.failed)
596     ++failures;
597
598   return failures;
599 }
600
601 static void
602 error_callback_create (void *data ATTRIBUTE_UNUSED, const char *msg,
603                        int errnum)
604 {
605   fprintf (stderr, "%s", msg);
606   if (errnum > 0)
607     fprintf (stderr, ": %s", strerror (errnum));
608   fprintf (stderr, "\n");
609   exit (EXIT_FAILURE);
610 }
611
612 /* Run all the tests.  */
613
614 int
615 main (int argc ATTRIBUTE_UNUSED, char **argv)
616 {
617   state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,
618                                   error_callback_create, NULL);
619
620 #if BACKTRACE_SUPPORTED
621   test1 ();
622   test2 ();
623   test3 ();
624   test4 ();
625 #endif
626
627   exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);
628 }