The check testing framework uses fork calls in order to create the processes used to run the single tests. This makes possible to catch unexpected process terminations such as a segmentation fault or a division by zero.
Sometimes we want to debug those failure conditions using gdb. Unfortunately the GNU debugger cannot catch the unexpected termination of the child processess.
The check implementor foresaw this and provides a workaround: to
define the CK_FORK environment variable to "no" and launch
the debugger.
The test driver torture/unit/runtests is a shell script generated by libtool. This means that it is not possible to run it invoking gdb from the command line, as in:
$ gdb torture/unit/runtests
A solution for this problem is to edit the torture/unit/runtests and hack it so it will call gdb instead of the program in .libs/. Just find the line containing something like:
exec "$progdir/$program" ${1+"$@"}
and change it to something like:
exec gdb --return-child-result --quiet --args "$progdir/$program" ${1+"$@"}
Note that you need to repeat this change every time torture/unit/runtests is rebuilt by make.
The second alternative is to run gdb on the real binary using:
$ LD_LIBRARY_PATH=/path/to/libgnupdf/src/.libs:$LD_LIBRARY_PATH gdb torture/unit/.libs/runtests
When debugging failing tests you may find it useful to set breakpoint
to _fail_unless function:
$ ( export CK_FORK='no'; make check ) # you can use 'make check FUNCTION=...' as well
...
(gdb) break _fail_unless
Breakpoint 1 at 0x804ac44
(gdb) run
...
Breakpoint 1, _fail_unless (result=1, file=0x80b2f94 "base/alloc/pdf-alloc.c",
line=47, expr=0x80aac30 "Failure 'data == NULL' occured") at check.c:237
237 send_loc_info (file, line);
...
(gdb) list
232 void _fail_unless (int result, const char *file,
233 int line, const char *expr, ...)
234 {
235 const char *msg;
236
237 send_loc_info (file, line);
238 if (!result) {
239 va_list ap;
240 char buf[BUFSIZ];
241
(gdb) break check.c:238 if (!result)
Breakpoint 2 at 0xb7ea4a7c: file check.c, line 238.
(gdb) delete 1
(gdb) continue
Continuing.
...
Breakpoint 2, _fail_unless (result=0,
file=0x80a7ef8 "base/text/pdf-text-new-destroy.c", line=44,
expr=0x80a7f1c "Assertion 'pdf_text_new (&newtext) == PDF_EBADCONTEXT' failed")
at check.c:238
238 if (!result) {
(gdb) finish
Run till exit from #0 _fail_unless (result=0,
file=0x80a7ef8 "base/text/pdf-text-new-destroy.c", line=44,
expr=0x80a7f1c "Assertion 'pdf_text_new (&newtext) == PDF_EBADCONTEXT' failed")
at check.c:238
pdf_text_new_destroy_001 (_i=0) at base/text/pdf-text-new-destroy.c:46
46 END_TEST
(gdb) list
41 {
42 pdf_text_t newtext = NULL;
43
44 fail_unless(pdf_text_new (&newtext) == PDF_EBADCONTEXT);
45 }
46 END_TEST
47
48 /*
49 * Test: pdf_text_new_destroy_002
50 * Description:
(gdb) ...