Didier 'Ptitjes' <ptitjes <at> free.fr> writes: > > Hi Holger, > > First thanks for your support. > > Holger Blasum wrote: > > Hello Didier, > > > > On Sat, Sep 19, 2009 at 09:04:54PM +0200, Didier Ptitjes wrote: > >> GTest forks the test process in order to test for asserting tests. > >> Looking at the reports of lcov, it looks like there is absolutely no > >> information gathered about the child processes. > > ... > >> I already have seen this question asked two times on gcc-help but none > >> got a real answer: > >> http://gcc.gnu.org/ml/gcc-help/2009-07/msg00334.html > >> http://gcc.gnu.org/ml/gcc/2008-09/msg00490.html > > > > Hmm, I have no quick idea how to fix your problem, but it might be > > helpful to understand where it occurs (then one can think of a > > work-around): basically the gcov tools work in a way > > (1) that enabling -ftest-coverage will result in a different binary > > than the binary without -ftest-coverage (1.4.1 in [1]), this gives you > > *.gcno files > > (2) when the instrumented binary it is run you have a data > > collection (1.4.2 in [1]) phase where the binary adds up > > counters in memory whenever passing through C sequence points > > and then you have a reporting phase where the memory data is dumped > > into *.gcda files. > > (3) then there is a reporting phase (1.4.3 in [1]) where that *.gcda > > and *.gcno files are converted into *.gcov files > > > > The first thing to divide and conquer this would be to test and report > > * whether after the phase (1) all *.gcno files are built for both > > parent and child, > > * whether after the phase (2) all *.gcda files are built/modified > > for parent and child. > > OK, I can confirm that I actually have *.gcno and *.gcda files for every > of my library .c files. (I tried to build them for test cases themselves > without any change). > > You must note that the parent process and the child processes have the > exact same code. In fact, the parent process is just forked. > > For an example of the forking code you can look at: > http://git.gnome.org/cgit/libgee/tree/tests/testreadonlycollection.vala#n121 > > This is Vala code but it is just transformed into the following C code: > > <code> > if (g_test_trap_fork ((guint64) 0, G_TEST_TRAP_SILENCE_STDOUT | > G_TEST_TRAP_SILENCE_STDERR)) { > g_assert (gee_collection_add (self->ro_collection, "two")); > _g_object_unref0 (dummy); > return; > } > g_test_trap_assert_failed (); > g_assert (gee_collection_get_size (self->ro_collection) == 1); > g_assert (gee_collection_contains (self->ro_collection, "one")); > </code> > > g_test_trap_fork uses fork() to fork the process. > > Here is the g_test_trap_fork code if this can enlighten the problem: > http://git.gnome.org/cgit/glib/tree/glib/gtestutils.c#n1582 > > I did not yet resolve the problem. I hope I will be able with your help. > > Best regards, Didier. > > FWIW, I ran into the same issue and, since I only really care whether an assert (and thus an abort()) is getting called during a given test, I came up with the following. This approach doesn't require the forking of a child process as ASSERT_DEATH does, and so I was able to capture gcov data for the assert() statement. Note that simply catching SIGABRT wasn't enough, because abort() still terminates the program after the signal handler returns (which I don't want), hence the setjmp and longjmp. static jmp_buf jmpBuf; void abortHandler(int param) { abortCalled = true; void (*prev_handler)(int); prev_handler = signal(SIGABRT, abortHandler); longjmp(jmpBuf, 1); } #define ASSERT_ABORT(statement) \ abortCalled = false; \ \ signal(SIGABRT, abortHandler); \ \ if (!setjmp(jmpBuf)) \ { \ statement; \ } \ \ ASSERT_TRUE(abortCalled); You can use it it like any other gtest macro: ASSERT_ABORT(myObject.doSomething()); --Scott