Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to catch segmentation fault with Google Test?

How do I test that a function won't produce a segmentation fault?

Here what I know right now, I can do:

EXPECT_DEATH(foo(nullParameter))

In side the function, a segmentation fault is produce which is the behavior that I want to make fail. The snippet above will make the test pass because that is what is expected, the death of the process.

Now, how can I make it fail?

like image 453
Daniel Santos Avatar asked Nov 30 '17 22:11

Daniel Santos


2 Answers

Here's a function that will segfault if passed a null pointer argument and otherwise not:

int deref(int * pint)
{
    return *pint;
}

And here is a googletest program that tests that behaviour:

main.cpp

#include <gtest/gtest.h>

int deref(int * pint)
{
    return *pint;
}


TEST(test_deref_1,will_segfault)
{
    ASSERT_EXIT((deref(nullptr),exit(0)),::testing::KilledBySignal(SIGSEGV),".*");
}


TEST(test_dref_2,will_not_segfault)
{
    int i = 42;
    ASSERT_EXIT((deref(&i),exit(0)),::testing::ExitedWithCode(0),".*");
}


int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

Compile and link:

$ g++ -Wall -Wextra -pedantic -o tester main.cpp -pthread -lgtest

Run:

$ ./tester 
[==========] Running 2 tests from 2 test cases.
[----------] Global test environment set-up.
[----------] 1 test from test_deref_1
[ RUN      ] test_deref_1.will_segfault
[       OK ] test_deref_1.will_segfault (168 ms)
[----------] 1 test from test_deref_1 (168 ms total)

[----------] 1 test from test_dref_2
[ RUN      ] test_dref_2.will_not_segfault
[       OK ] test_dref_2.will_not_segfault (1 ms)
[----------] 1 test from test_dref_2 (1 ms total)

[----------] Global test environment tear-down
[==========] 2 tests from 2 test cases ran. (169 ms total)
[  PASSED  ] 2 tests.

As far as I can imagine, TEST(test_deref_1,will_segfault) is a pointless test, because I cannot think of any circumstances in which I would want to assure myself that a program will segfault as a result of making a certain call to a function I have written.

TEST(test_dref_2,will_not_segfault) is possibly a useful kind of test. In effect, it is a test that the program:

int main()
{
    int i = 42;
    defref(&i);
    exit(0);
}

will terminate by exit(0) rather than in any premature abnormal way. A better name for this test would probably be TEST(test_dref,does_not_crash), or similar.

It is a possibly useful kind of test because there could be a significant risk of it failing, if defref was some sufficiently complicated code, and the test suite could report that failure without crashing itself. We can force a failure by rewriting it:

TEST(test_dref_2,will_not_segfault)
{
    ASSERT_EXIT((deref(nullptr),exit(0)),::testing::ExitedWithCode(0),".*");
}

and then test test report is:

$ ./tester
[==========] Running 2 tests from 2 test cases.
[----------] Global test environment set-up.
[----------] 1 test from test_deref_1
[ RUN      ] test_deref_1.will_segfault
[       OK ] test_deref_1.will_segfault (147 ms)
[----------] 1 test from test_deref_1 (147 ms total)

[----------] 1 test from test_dref_2
[ RUN      ] test_dref_2.will_not_segfault
main.cpp:25: Failure
Death test: (deref(nullptr),exit(0))
    Result: died but not with expected exit code:
            Terminated by signal 11 (core dumped)
Actual msg:
[  DEATH   ] 
[  FAILED  ] test_dref_2.will_not_segfault (90 ms)
[----------] 1 test from test_dref_2 (90 ms total)

[----------] Global test environment tear-down
[==========] 2 tests from 2 test cases ran. (237 ms total)
[  PASSED  ] 1 test.
[  FAILED  ] 1 test, listed below:
[  FAILED  ] test_dref_2.will_not_segfault

 1 FAILED TEST

See the documentation of {ASSERT|EXPECT}_EXIT to understand these macros.

like image 168
Mike Kinghan Avatar answered Nov 07 '22 01:11

Mike Kinghan


Tests which crash are already failures (presumably you don't want any of your code to segfault). Just test for the behavior you expect, as with any other test.

like image 24
Sneftel Avatar answered Nov 07 '22 02:11

Sneftel