8d87f2ad889b020b8690f7495378fc45a17a5094
[senf.git] / run-test-gdb.sh
1 #!/bin/sh
2
3 # This script helps finding the origin of unhandled exceptions in the
4 # unit tests. The unit test framework will tell, that an exception has
5 # been caught by the test driver but will not tell, where in the code
6 # it has occured.
7 #
8 # This script will run the .test.bin test driver within gdb and will
9 # create a backtrace for every exception caught by the test driver.
10 #
11 # NOTE: If your unit test (excplicitly) writes output to stderr, this
12 # output will be lost
13 #
14 # NOTE: This works by setting a breakpoint in the std::exception
15 # constructor. This is, where the backtrace is created from. If you do
16 # some funky manipulations with your exceptions, the backtrace might
17 # not point to the throw statement, however this is very unusual. Of
18 # course, this only works, if all your exceptions are derived from
19 # std::exception but that should always be the case.
20
21 trap 'rm -f .run-test-gdb.cmd' 0 1 2 15
22
23 # This gdb script will set the breakpoint and will then run the test
24 # driver. Whenever the execution stops, it will print a backtrace and
25 # will then continue execution. This will produce superflous
26 # backtraces for exceptions which are handled correctly. These will be
27 # filtered out later.
28 cat >.run-test-gdb.cmd <<EOF
29 break std::exception::exception()
30 run --build_info=yes --log_level=test_suite
31 while 1
32   bt
33   c
34 end
35 EOF
36
37 # The perl script will filter out exceptions which are handled
38 # correctly (cought before the reach the unit test driver). It will
39 # also truncate the backtrace at the first stackframe within the unit
40 # test subsystem since we are only interested in the user code.
41 gdb -batch -x .run-test-gdb.cmd ./.test.bin 2>/dev/null | perl -e '
42   $mode=0;
43   while (<STDIN>) {
44     if ($mode==0) {
45       if (/^$/) {
46         $mode=1;
47       } else {
48         print;
49       }
50     }
51     elsif ($mode==1) {
52       if (/^Breakpoint 1, exception/) {
53         $mode=2;
54         @l=();
55       } else {
56         print "\n";
57         print;
58         $mode=0;
59       }
60     }
61     elsif ($mode==2) {
62       if (/^(#?[0-9]| )/) {
63         push @l,$_ if /^#/;
64         $l[$#l] .= $_ if @l && /^ /;
65       } elsif (/^Current language:  auto;/) {
66         ;
67       } else {
68         $mode=0;
69         if (/: fatal error in /) {
70           for (@l[1..$#l]) {
71              last if /^#[0-9]+ +0x[0-9a-f]+ in boost::unit_test::ut_detail::invoker/;
72              print;
73           }
74           print;
75         } else {
76           redo;
77         }
78       }
79     }
80   }
81 '