Home | History | Annotate | Line # | Download | only in libbacktrace
      1   1.1  mrg /* btest.c -- Test for libbacktrace library
      2  1.10  mrg    Copyright (C) 2012-2022 Free Software Foundation, Inc.
      3   1.1  mrg    Written by Ian Lance Taylor, Google.
      4   1.1  mrg 
      5   1.1  mrg Redistribution and use in source and binary forms, with or without
      6   1.1  mrg modification, are permitted provided that the following conditions are
      7   1.1  mrg met:
      8   1.1  mrg 
      9   1.1  mrg     (1) Redistributions of source code must retain the above copyright
     10   1.6  mrg     notice, this list of conditions and the following disclaimer.
     11   1.1  mrg 
     12   1.1  mrg     (2) Redistributions in binary form must reproduce the above copyright
     13   1.1  mrg     notice, this list of conditions and the following disclaimer in
     14   1.1  mrg     the documentation and/or other materials provided with the
     15   1.6  mrg     distribution.
     16   1.6  mrg 
     17   1.1  mrg     (3) The name of the author may not be used to
     18   1.1  mrg     endorse or promote products derived from this software without
     19   1.1  mrg     specific prior written permission.
     20   1.1  mrg 
     21   1.1  mrg THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     22   1.1  mrg IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     23   1.1  mrg WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     24   1.1  mrg DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
     25   1.1  mrg INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     26   1.1  mrg (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     27   1.1  mrg SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28   1.1  mrg HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     29   1.1  mrg STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     30   1.1  mrg IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     31   1.1  mrg POSSIBILITY OF SUCH DAMAGE.  */
     32   1.1  mrg 
     33   1.1  mrg /* This program tests the externally visible interfaces of the
     34   1.1  mrg    libbacktrace library.  */
     35   1.1  mrg 
     36   1.1  mrg #include <assert.h>
     37   1.1  mrg #include <stdio.h>
     38   1.1  mrg #include <stdlib.h>
     39   1.1  mrg #include <string.h>
     40   1.7  mrg #include <unistd.h>
     41  1.10  mrg #include <sys/stat.h>
     42   1.1  mrg 
     43   1.1  mrg #include "filenames.h"
     44   1.1  mrg 
     45   1.1  mrg #include "backtrace.h"
     46   1.1  mrg #include "backtrace-supported.h"
     47   1.1  mrg 
     48   1.7  mrg #include "testlib.h"
     49   1.1  mrg 
     50   1.1  mrg /* Test the backtrace function with non-inlined functions.  */
     51   1.1  mrg 
     52   1.8  mrg static int test1 (void) __attribute__ ((noinline, noclone, unused));
     53   1.8  mrg static int f2 (int) __attribute__ ((noinline, noclone));
     54   1.8  mrg static int f3 (int, int) __attribute__ ((noinline, noclone));
     55   1.1  mrg 
     56   1.1  mrg static int
     57   1.1  mrg test1 (void)
     58   1.1  mrg {
     59   1.1  mrg   /* Returning a value here and elsewhere avoids a tailcall which
     60   1.1  mrg      would mess up the backtrace.  */
     61   1.1  mrg   return f2 (__LINE__) + 1;
     62   1.1  mrg }
     63   1.1  mrg 
     64   1.1  mrg static int
     65   1.1  mrg f2 (int f1line)
     66   1.1  mrg {
     67   1.1  mrg   return f3 (f1line, __LINE__) + 2;
     68   1.1  mrg }
     69   1.1  mrg 
     70   1.1  mrg static int
     71   1.1  mrg f3 (int f1line, int f2line)
     72   1.1  mrg {
     73   1.1  mrg   struct info all[20];
     74   1.1  mrg   struct bdata data;
     75   1.1  mrg   int f3line;
     76   1.1  mrg   int i;
     77   1.1  mrg 
     78   1.1  mrg   data.all = &all[0];
     79   1.1  mrg   data.index = 0;
     80   1.1  mrg   data.max = 20;
     81   1.1  mrg   data.failed = 0;
     82   1.1  mrg 
     83   1.1  mrg   f3line = __LINE__ + 1;
     84   1.1  mrg   i = backtrace_full (state, 0, callback_one, error_callback_one, &data);
     85   1.1  mrg 
     86   1.1  mrg   if (i != 0)
     87   1.1  mrg     {
     88   1.1  mrg       fprintf (stderr, "test1: unexpected return value %d\n", i);
     89   1.1  mrg       data.failed = 1;
     90   1.1  mrg     }
     91   1.1  mrg 
     92   1.3  mrg   if (data.index < 3)
     93   1.3  mrg     {
     94   1.3  mrg       fprintf (stderr,
     95   1.3  mrg 	       "test1: not enough frames; got %zu, expected at least 3\n",
     96   1.3  mrg 	       data.index);
     97   1.3  mrg       data.failed = 1;
     98   1.3  mrg     }
     99   1.3  mrg 
    100   1.7  mrg   check ("test1", 0, all, f3line, "f3", "btest.c", &data.failed);
    101   1.7  mrg   check ("test1", 1, all, f2line, "f2", "btest.c", &data.failed);
    102   1.7  mrg   check ("test1", 2, all, f1line, "test1", "btest.c", &data.failed);
    103   1.1  mrg 
    104   1.1  mrg   printf ("%s: backtrace_full noinline\n", data.failed ? "FAIL" : "PASS");
    105   1.1  mrg 
    106   1.1  mrg   if (data.failed)
    107   1.1  mrg     ++failures;
    108   1.1  mrg 
    109   1.1  mrg   return failures;
    110   1.1  mrg }
    111   1.1  mrg 
    112   1.1  mrg /* Test the backtrace function with inlined functions.  */
    113   1.1  mrg 
    114   1.1  mrg static inline int test2 (void) __attribute__ ((always_inline, unused));
    115   1.1  mrg static inline int f12 (int) __attribute__ ((always_inline));
    116   1.1  mrg static inline int f13 (int, int) __attribute__ ((always_inline));
    117   1.1  mrg 
    118   1.1  mrg static inline int
    119   1.1  mrg test2 (void)
    120   1.1  mrg {
    121   1.1  mrg   return f12 (__LINE__) + 1;
    122   1.1  mrg }
    123   1.1  mrg 
    124   1.1  mrg static inline int
    125   1.1  mrg f12 (int f1line)
    126   1.1  mrg {
    127   1.1  mrg   return f13 (f1line, __LINE__) + 2;
    128   1.1  mrg }
    129   1.1  mrg 
    130   1.1  mrg static inline int
    131   1.1  mrg f13 (int f1line, int f2line)
    132   1.1  mrg {
    133   1.1  mrg   struct info all[20];
    134   1.1  mrg   struct bdata data;
    135   1.1  mrg   int f3line;
    136   1.1  mrg   int i;
    137   1.1  mrg 
    138   1.1  mrg   data.all = &all[0];
    139   1.1  mrg   data.index = 0;
    140   1.1  mrg   data.max = 20;
    141   1.1  mrg   data.failed = 0;
    142   1.1  mrg 
    143   1.1  mrg   f3line = __LINE__ + 1;
    144   1.1  mrg   i = backtrace_full (state, 0, callback_one, error_callback_one, &data);
    145   1.1  mrg 
    146   1.1  mrg   if (i != 0)
    147   1.1  mrg     {
    148   1.1  mrg       fprintf (stderr, "test2: unexpected return value %d\n", i);
    149   1.1  mrg       data.failed = 1;
    150   1.1  mrg     }
    151   1.1  mrg 
    152   1.7  mrg   check ("test2", 0, all, f3line, "f13", "btest.c", &data.failed);
    153   1.7  mrg   check ("test2", 1, all, f2line, "f12", "btest.c", &data.failed);
    154   1.7  mrg   check ("test2", 2, all, f1line, "test2", "btest.c", &data.failed);
    155   1.1  mrg 
    156   1.1  mrg   printf ("%s: backtrace_full inline\n", data.failed ? "FAIL" : "PASS");
    157   1.1  mrg 
    158   1.1  mrg   if (data.failed)
    159   1.1  mrg     ++failures;
    160   1.1  mrg 
    161   1.1  mrg   return failures;
    162   1.1  mrg }
    163   1.1  mrg 
    164   1.1  mrg /* Test the backtrace_simple function with non-inlined functions.  */
    165   1.1  mrg 
    166   1.8  mrg static int test3 (void) __attribute__ ((noinline, noclone, unused));
    167   1.8  mrg static int f22 (int) __attribute__ ((noinline, noclone));
    168   1.8  mrg static int f23 (int, int) __attribute__ ((noinline, noclone));
    169   1.1  mrg 
    170   1.1  mrg static int
    171   1.1  mrg test3 (void)
    172   1.1  mrg {
    173   1.1  mrg   return f22 (__LINE__) + 1;
    174   1.1  mrg }
    175   1.1  mrg 
    176   1.1  mrg static int
    177   1.1  mrg f22 (int f1line)
    178   1.1  mrg {
    179   1.1  mrg   return f23 (f1line, __LINE__) + 2;
    180   1.1  mrg }
    181   1.1  mrg 
    182   1.1  mrg static int
    183   1.1  mrg f23 (int f1line, int f2line)
    184   1.1  mrg {
    185   1.1  mrg   uintptr_t addrs[20];
    186   1.1  mrg   struct sdata data;
    187   1.1  mrg   int f3line;
    188   1.1  mrg   int i;
    189   1.1  mrg 
    190   1.1  mrg   data.addrs = &addrs[0];
    191   1.1  mrg   data.index = 0;
    192   1.1  mrg   data.max = 20;
    193   1.1  mrg   data.failed = 0;
    194   1.1  mrg 
    195   1.1  mrg   f3line = __LINE__ + 1;
    196   1.1  mrg   i = backtrace_simple (state, 0, callback_two, error_callback_two, &data);
    197   1.1  mrg 
    198   1.1  mrg   if (i != 0)
    199   1.1  mrg     {
    200   1.1  mrg       fprintf (stderr, "test3: unexpected return value %d\n", i);
    201   1.1  mrg       data.failed = 1;
    202   1.1  mrg     }
    203   1.1  mrg 
    204   1.1  mrg   if (!data.failed)
    205   1.1  mrg     {
    206   1.1  mrg       struct info all[20];
    207   1.1  mrg       struct bdata bdata;
    208   1.1  mrg       int j;
    209   1.1  mrg 
    210   1.1  mrg       bdata.all = &all[0];
    211   1.1  mrg       bdata.index = 0;
    212   1.1  mrg       bdata.max = 20;
    213   1.1  mrg       bdata.failed = 0;
    214   1.1  mrg 
    215   1.1  mrg       for (j = 0; j < 3; ++j)
    216   1.1  mrg 	{
    217   1.1  mrg 	  i = backtrace_pcinfo (state, addrs[j], callback_one,
    218   1.1  mrg 				error_callback_one, &bdata);
    219   1.1  mrg 	  if (i != 0)
    220   1.1  mrg 	    {
    221   1.1  mrg 	      fprintf (stderr,
    222   1.1  mrg 		       ("test3: unexpected return value "
    223   1.1  mrg 			"from backtrace_pcinfo %d\n"),
    224   1.1  mrg 		       i);
    225   1.1  mrg 	      bdata.failed = 1;
    226   1.1  mrg 	    }
    227   1.1  mrg 	  if (!bdata.failed && bdata.index != (size_t) (j + 1))
    228   1.1  mrg 	    {
    229   1.1  mrg 	      fprintf (stderr,
    230   1.1  mrg 		       ("wrong number of calls from backtrace_pcinfo "
    231   1.1  mrg 			"got %u expected %d\n"),
    232   1.1  mrg 		       (unsigned int) bdata.index, j + 1);
    233   1.1  mrg 	      bdata.failed = 1;
    234   1.1  mrg 	    }
    235   1.6  mrg 	}
    236   1.1  mrg 
    237   1.7  mrg       check ("test3", 0, all, f3line, "f23", "btest.c", &bdata.failed);
    238   1.7  mrg       check ("test3", 1, all, f2line, "f22", "btest.c", &bdata.failed);
    239   1.7  mrg       check ("test3", 2, all, f1line, "test3", "btest.c", &bdata.failed);
    240   1.1  mrg 
    241   1.1  mrg       if (bdata.failed)
    242   1.1  mrg 	data.failed = 1;
    243   1.1  mrg 
    244   1.1  mrg       for (j = 0; j < 3; ++j)
    245   1.1  mrg 	{
    246   1.1  mrg 	  struct symdata symdata;
    247   1.1  mrg 
    248   1.1  mrg 	  symdata.name = NULL;
    249   1.1  mrg 	  symdata.val = 0;
    250   1.3  mrg 	  symdata.size = 0;
    251   1.1  mrg 	  symdata.failed = 0;
    252   1.1  mrg 
    253   1.1  mrg 	  i = backtrace_syminfo (state, addrs[j], callback_three,
    254   1.1  mrg 				 error_callback_three, &symdata);
    255   1.1  mrg 	  if (i == 0)
    256   1.1  mrg 	    {
    257   1.1  mrg 	      fprintf (stderr,
    258   1.1  mrg 		       ("test3: [%d]: unexpected return value "
    259   1.1  mrg 			"from backtrace_syminfo %d\n"),
    260   1.1  mrg 		       j, i);
    261   1.1  mrg 	      symdata.failed = 1;
    262   1.1  mrg 	    }
    263   1.1  mrg 
    264   1.1  mrg 	  if (!symdata.failed)
    265   1.1  mrg 	    {
    266   1.1  mrg 	      const char *expected;
    267   1.1  mrg 
    268   1.1  mrg 	      switch (j)
    269   1.1  mrg 		{
    270   1.1  mrg 		case 0:
    271   1.1  mrg 		  expected = "f23";
    272   1.1  mrg 		  break;
    273   1.1  mrg 		case 1:
    274   1.1  mrg 		  expected = "f22";
    275   1.1  mrg 		  break;
    276   1.1  mrg 		case 2:
    277   1.1  mrg 		  expected = "test3";
    278   1.1  mrg 		  break;
    279   1.1  mrg 		default:
    280   1.1  mrg 		  assert (0);
    281   1.1  mrg 		}
    282   1.1  mrg 
    283   1.1  mrg 	      if (symdata.name == NULL)
    284   1.1  mrg 		{
    285   1.1  mrg 		  fprintf (stderr, "test3: [%d]: NULL syminfo name\n", j);
    286   1.1  mrg 		  symdata.failed = 1;
    287   1.1  mrg 		}
    288   1.1  mrg 	      /* Use strncmp, not strcmp, because GCC might create a
    289   1.1  mrg 		 clone.  */
    290   1.1  mrg 	      else if (strncmp (symdata.name, expected, strlen (expected))
    291   1.1  mrg 		       != 0)
    292   1.1  mrg 		{
    293   1.1  mrg 		  fprintf (stderr,
    294   1.1  mrg 			   ("test3: [%d]: unexpected syminfo name "
    295   1.1  mrg 			    "got %s expected %s\n"),
    296   1.1  mrg 			   j, symdata.name, expected);
    297   1.1  mrg 		  symdata.failed = 1;
    298   1.1  mrg 		}
    299   1.1  mrg 	    }
    300   1.1  mrg 
    301   1.1  mrg 	  if (symdata.failed)
    302   1.1  mrg 	    data.failed = 1;
    303   1.1  mrg 	}
    304   1.1  mrg     }
    305   1.1  mrg 
    306   1.1  mrg   printf ("%s: backtrace_simple noinline\n", data.failed ? "FAIL" : "PASS");
    307   1.1  mrg 
    308   1.1  mrg   if (data.failed)
    309   1.1  mrg     ++failures;
    310   1.1  mrg 
    311   1.1  mrg   return failures;
    312   1.1  mrg }
    313   1.1  mrg 
    314   1.1  mrg /* Test the backtrace_simple function with inlined functions.  */
    315   1.1  mrg 
    316   1.1  mrg static inline int test4 (void) __attribute__ ((always_inline, unused));
    317   1.1  mrg static inline int f32 (int) __attribute__ ((always_inline));
    318   1.1  mrg static inline int f33 (int, int) __attribute__ ((always_inline));
    319   1.1  mrg 
    320   1.1  mrg static inline int
    321   1.1  mrg test4 (void)
    322   1.1  mrg {
    323   1.1  mrg   return f32 (__LINE__) + 1;
    324   1.1  mrg }
    325   1.1  mrg 
    326   1.1  mrg static inline int
    327   1.1  mrg f32 (int f1line)
    328   1.1  mrg {
    329   1.1  mrg   return f33 (f1line, __LINE__) + 2;
    330   1.1  mrg }
    331   1.1  mrg 
    332   1.1  mrg static inline int
    333   1.1  mrg f33 (int f1line, int f2line)
    334   1.1  mrg {
    335   1.1  mrg   uintptr_t addrs[20];
    336   1.1  mrg   struct sdata data;
    337   1.1  mrg   int f3line;
    338   1.1  mrg   int i;
    339   1.1  mrg 
    340   1.1  mrg   data.addrs = &addrs[0];
    341   1.1  mrg   data.index = 0;
    342   1.1  mrg   data.max = 20;
    343   1.1  mrg   data.failed = 0;
    344   1.1  mrg 
    345   1.1  mrg   f3line = __LINE__ + 1;
    346   1.1  mrg   i = backtrace_simple (state, 0, callback_two, error_callback_two, &data);
    347   1.1  mrg 
    348   1.1  mrg   if (i != 0)
    349   1.1  mrg     {
    350   1.1  mrg       fprintf (stderr, "test3: unexpected return value %d\n", i);
    351   1.1  mrg       data.failed = 1;
    352   1.1  mrg     }
    353   1.1  mrg 
    354   1.1  mrg   if (!data.failed)
    355   1.1  mrg     {
    356   1.1  mrg       struct info all[20];
    357   1.1  mrg       struct bdata bdata;
    358   1.1  mrg 
    359   1.1  mrg       bdata.all = &all[0];
    360   1.1  mrg       bdata.index = 0;
    361   1.1  mrg       bdata.max = 20;
    362   1.1  mrg       bdata.failed = 0;
    363   1.1  mrg 
    364   1.1  mrg       i = backtrace_pcinfo (state, addrs[0], callback_one, error_callback_one,
    365   1.1  mrg 			    &bdata);
    366   1.1  mrg       if (i != 0)
    367   1.1  mrg 	{
    368   1.1  mrg 	  fprintf (stderr,
    369   1.1  mrg 		   ("test4: unexpected return value "
    370   1.1  mrg 		    "from backtrace_pcinfo %d\n"),
    371   1.1  mrg 		   i);
    372   1.1  mrg 	  bdata.failed = 1;
    373   1.1  mrg 	}
    374   1.1  mrg 
    375   1.7  mrg       check ("test4", 0, all, f3line, "f33", "btest.c", &bdata.failed);
    376   1.7  mrg       check ("test4", 1, all, f2line, "f32", "btest.c", &bdata.failed);
    377   1.7  mrg       check ("test4", 2, all, f1line, "test4", "btest.c", &bdata.failed);
    378   1.1  mrg 
    379   1.1  mrg       if (bdata.failed)
    380   1.1  mrg 	data.failed = 1;
    381   1.1  mrg     }
    382   1.1  mrg 
    383   1.1  mrg   printf ("%s: backtrace_simple inline\n", data.failed ? "FAIL" : "PASS");
    384   1.1  mrg 
    385   1.1  mrg   if (data.failed)
    386   1.1  mrg     ++failures;
    387   1.1  mrg 
    388   1.1  mrg   return failures;
    389   1.1  mrg }
    390   1.1  mrg 
    391   1.6  mrg static int test5 (void) __attribute__ ((unused));
    392   1.4  mrg 
    393   1.3  mrg int global = 1;
    394   1.3  mrg 
    395   1.3  mrg static int
    396   1.3  mrg test5 (void)
    397   1.3  mrg {
    398   1.3  mrg   struct symdata symdata;
    399   1.3  mrg   int i;
    400   1.3  mrg   uintptr_t addr = (uintptr_t) &global;
    401   1.3  mrg 
    402   1.3  mrg   if (sizeof (global) > 1)
    403   1.3  mrg     addr += 1;
    404   1.3  mrg 
    405   1.3  mrg   symdata.name = NULL;
    406   1.3  mrg   symdata.val = 0;
    407   1.3  mrg   symdata.size = 0;
    408   1.3  mrg   symdata.failed = 0;
    409   1.3  mrg 
    410   1.3  mrg   i = backtrace_syminfo (state, addr, callback_three,
    411   1.3  mrg 			 error_callback_three, &symdata);
    412   1.3  mrg   if (i == 0)
    413   1.3  mrg     {
    414   1.3  mrg       fprintf (stderr,
    415   1.3  mrg 	       "test5: unexpected return value from backtrace_syminfo %d\n",
    416   1.3  mrg 	       i);
    417   1.3  mrg       symdata.failed = 1;
    418   1.3  mrg     }
    419   1.3  mrg 
    420   1.3  mrg   if (!symdata.failed)
    421   1.3  mrg     {
    422   1.3  mrg       if (symdata.name == NULL)
    423   1.3  mrg 	{
    424   1.3  mrg 	  fprintf (stderr, "test5: NULL syminfo name\n");
    425   1.3  mrg 	  symdata.failed = 1;
    426   1.3  mrg 	}
    427   1.8  mrg       else if (!(strncmp (symdata.name, "global", 6) == 0
    428   1.8  mrg 		 && (symdata.name[6] == '\0'|| symdata.name[6] == '.')))
    429   1.3  mrg 	{
    430   1.3  mrg 	  fprintf (stderr,
    431   1.3  mrg 		   "test5: unexpected syminfo name got %s expected %s\n",
    432   1.3  mrg 		   symdata.name, "global");
    433   1.3  mrg 	  symdata.failed = 1;
    434   1.3  mrg 	}
    435   1.3  mrg       else if (symdata.val != (uintptr_t) &global)
    436   1.3  mrg 	{
    437   1.3  mrg 	  fprintf (stderr,
    438   1.3  mrg 		   "test5: unexpected syminfo value got %lx expected %lx\n",
    439   1.3  mrg 		   (unsigned long) symdata.val,
    440   1.3  mrg 		   (unsigned long) (uintptr_t) &global);
    441   1.3  mrg 	  symdata.failed = 1;
    442   1.3  mrg 	}
    443   1.3  mrg       else if (symdata.size != sizeof (global))
    444   1.3  mrg 	{
    445   1.3  mrg 	  fprintf (stderr,
    446   1.3  mrg 		   "test5: unexpected syminfo size got %lx expected %lx\n",
    447   1.3  mrg 		   (unsigned long) symdata.size,
    448   1.3  mrg 		   (unsigned long) sizeof (global));
    449   1.3  mrg 	  symdata.failed = 1;
    450   1.3  mrg 	}
    451   1.3  mrg     }
    452   1.3  mrg 
    453   1.3  mrg   printf ("%s: backtrace_syminfo variable\n",
    454   1.3  mrg 	  symdata.failed ? "FAIL" : "PASS");
    455   1.3  mrg 
    456   1.3  mrg   if (symdata.failed)
    457   1.3  mrg     ++failures;
    458   1.3  mrg 
    459   1.3  mrg   return failures;
    460   1.3  mrg }
    461   1.3  mrg 
    462  1.10  mrg #define MIN_DESCRIPTOR 3
    463  1.10  mrg #define MAX_DESCRIPTOR 10
    464  1.10  mrg 
    465  1.10  mrg static int fstat_status[MAX_DESCRIPTOR];
    466  1.10  mrg 
    467  1.10  mrg /* Check files that are available.  */
    468  1.10  mrg 
    469  1.10  mrg static void
    470  1.10  mrg check_available_files (void)
    471  1.10  mrg {
    472  1.10  mrg   struct stat s;
    473  1.10  mrg   for (unsigned i = MIN_DESCRIPTOR; i < MAX_DESCRIPTOR; i++)
    474  1.10  mrg     fstat_status[i] = fstat (i, &s);
    475  1.10  mrg }
    476  1.10  mrg 
    477   1.7  mrg /* Check that are no files left open.  */
    478   1.7  mrg 
    479   1.1  mrg static void
    480   1.7  mrg check_open_files (void)
    481   1.1  mrg {
    482  1.10  mrg   for (unsigned i = MIN_DESCRIPTOR; i < MAX_DESCRIPTOR; i++)
    483   1.7  mrg     {
    484  1.10  mrg       if (fstat_status[i] != 0 && close (i) == 0)
    485   1.7  mrg 	{
    486   1.7  mrg 	  fprintf (stderr,
    487   1.7  mrg 		   "ERROR: descriptor %d still open after tests complete\n",
    488   1.7  mrg 		   i);
    489   1.7  mrg 	  ++failures;
    490   1.7  mrg 	}
    491   1.7  mrg     }
    492   1.1  mrg }
    493   1.1  mrg 
    494   1.1  mrg /* Run all the tests.  */
    495   1.1  mrg 
    496   1.1  mrg int
    497   1.1  mrg main (int argc ATTRIBUTE_UNUSED, char **argv)
    498   1.1  mrg {
    499  1.10  mrg   check_available_files ();
    500  1.10  mrg 
    501   1.1  mrg   state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,
    502   1.1  mrg 				  error_callback_create, NULL);
    503   1.1  mrg 
    504   1.1  mrg #if BACKTRACE_SUPPORTED
    505   1.1  mrg   test1 ();
    506   1.1  mrg   test2 ();
    507   1.1  mrg   test3 ();
    508   1.1  mrg   test4 ();
    509   1.4  mrg #if BACKTRACE_SUPPORTS_DATA
    510   1.3  mrg   test5 ();
    511   1.1  mrg #endif
    512   1.4  mrg #endif
    513   1.1  mrg 
    514   1.7  mrg   check_open_files ();
    515   1.7  mrg 
    516   1.1  mrg   exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);
    517   1.1  mrg }
    518