PHPUnit Segmentation fault
I've had an issue with PHPUnit segfaulting and had trouble finding an answer, so hopefully this helps someone with the same issue later.
PHPUnit was segfaulting, but only:
- If there was an error (or more than one)
- After all tests had run but before the errors were printed
After a while I realized that it was due to failures on tests that used data providers, and specifically for data providers that passed objects with lots of recursive references. A bell finally went off and I did some digging: the problem is that when you're using data providers and a test fails, PHPUnit tries to create a string representation of the provided arguments for the failure description to tell you what failed, but this is problematic when one of the arguments has some infinite recursion. In fact, what PHPUnit does in PHPUnit_Framework_TestCase::dataToString()
(around line 1612) is print out all the arguments provided by the data provider using print_r
, which causes the segfault when PHP tries to create a string representation of the infinitely recursive object.
The solution I came to was:
- Use a single base class for all my test classes (which fortunately I was already doing)
- Override
dataToString()
in my test base class, to check for these kinds of objects in the data array (which is possible in my case because I know what these objects look like). If the object is present, I return some special value, if not I just pass it along to the parent method.
Next to what cweiske suggested, if upgrading PHP is not an option for you and you have problems to locate the source of the segfault, you can use a debugger to find out more.
You can launch gdb this way to debug a PHPUnit session:
gdb --args php /usr/bin/phpunit quiz_service_Test.php
Then type in r
to run the program and/or set environment variables first.
set env MALLOC_CHECK_=3
r
You might also consider to install the debugging symbols for PHP on the system to get better results for debugging. gdb checks this on startup for you and leaves a notice how you can do so.