Hi Collin,

> I've pushed a basic test for execinfo. Since BSD needs to link to
> -lexecinfo unlike glibc. Should catch any bugs that occur there or if
> another system adds it as a library.

Thanks.

Reading through your test, I notice that when size == 0 && symbols != NULL,
the symbols pointer is not freed. So I went to look deeper.

Reading through the documentation at
https://www.gnu.org/software/libc/manual/html_node/Backtraces.html
I found the following opportunities that can be tested in a unit test:
  - backtrace: "The return value is the actual number of entries of buffer
    that are obtained, and is at most size." This is something that can be 
tested.
  - backtrace_symbols: "The return value of backtrace_symbols is a pointer 
obtained
    via the malloc function ... The return value is NULL if sufficient memory 
for
    the strings cannot be obtained." Since in unit tests, out-of-memory can be
    assumed to not happen, we can check that the return value is != NULL.
  - backtrace_symbols: "The return value is a pointer to an array of strings,
    which has size entries just like the array buffer" This sounds like we can
    pass a too-small buffer, and the stack trace will be truncated. This can be
    tested as well.
  - The third function, backtrace_symbols_fd, is not tested.

So, this is what I am committing.

Note the change in the module description. If we want to verify that there is
an AC_SUBST for LIB_EXECINFO, the way to do it is to write @LIB_EXECINFO@.
If the AC_SUBST was missing, $(LIB_EXECINFO) would come out as empty whereas
@LIB_EXECINFO@ would lead to a build failure.


2024-05-12  Bruno Haible  <br...@clisp.org>

        execinfo tests: Strengthen tests.
        * tests/test-execinfo.c (test_backtrace): Add an argument. Check the
        return value of backtrace(). Check that backtrace_symbols_fd is defined.
        Check the return value of backtrace_symbols().
        (main): Test also the case of a short buffer.
        * modules/execinfo-tests (Makefile.am): Verify that LIB_EXECINFO is
        defined.

diff --git a/modules/execinfo-tests b/modules/execinfo-tests
index 191345cd5c..5d6a28c69b 100644
--- a/modules/execinfo-tests
+++ b/modules/execinfo-tests
@@ -9,4 +9,4 @@ configure.ac:
 Makefile.am:
 TESTS += test-execinfo
 check_PROGRAMS += test-execinfo
-test_execinfo_LDADD = $(LDADD) $(LIB_EXECINFO)
+test_execinfo_LDADD = $(LDADD) @LIB_EXECINFO@
diff --git a/tests/test-execinfo.c b/tests/test-execinfo.c
index af457c468f..5745306ed5 100644
--- a/tests/test-execinfo.c
+++ b/tests/test-execinfo.c
@@ -27,17 +27,28 @@
 #include "macros.h"
 
 static void
-test_backtrace (void)
+test_backtrace (int pass)
 {
   void *buffer[10];
-  char **symbols;
+  int max_size;
   int size;
+  char **symbols;
+
+  max_size = (pass == 0 ? SIZEOF (buffer) : 1);
+  size = backtrace (buffer, max_size);
+  ASSERT (size >= 0 && size <= max_size);
+
+  /* Print the backtrace to a file descriptor.  */
+  backtrace_symbols_fd (buffer, size, 1);
+  printf ("\n");
 
-  size = backtrace (buffer, SIZEOF (buffer));
   symbols = backtrace_symbols (buffer, size);
+  if (size > 0)
+    /* We have enough memory available.  */
+    ASSERT (symbols != NULL);
 
   /* Print the backtrace if possible.  */
-  if (0 < size && symbols != NULL)
+  if (symbols != NULL)
     {
       for (int i = 0; i < size; ++i)
         printf ("%s\n", symbols[i]);
@@ -48,7 +59,10 @@ test_backtrace (void)
 int
 main (void)
 {
-  test_backtrace ();
+  printf ("Full stack trace:\n"); fflush (stdout);
+  test_backtrace (0);
+  printf ("\nTruncated stack trace:\n"); fflush (stdout);
+  test_backtrace (1);
 
   return 0;
 }




Reply via email to