5

I have the following code:

bool f()
{
  command = "mkdir -p /\/\/";
  result = aSystemCall(command);
  if (result == ...
}

BOOST_AUTO_TEST_CASE(BadDir)
{
  BOOST_CHECK_EQUAL(false, f());
}

If I execute command in command line, I get a permission denied error. I'm aware of this. That's exactly what I want to test.
aSystemCall executes the command as a child process. As the child exits with a nonzero error for this command, aSystemCall returns an error. It doesn't throw.
If I run BadDir test case in command line, the code after aSystemCall is never executed, and the test fails, with the following output:

mkdir: cannot create directory '/\/\/': Permission denied
unknown location(0): fatal error in "BadDir": child has exited; pid: 25356; uid: 19753;   exit value: 1
test.cpp(100): last checkpoint
Leaving test case "BadDir"; testing time: 10ms
Leaving test suite "Test"
Leaving test suite "Master Test Suite"

If I run BadDir test case within gdb, aSystemCall returns, the result can be checked, and the test passes.

Is there a way to telling boost::unit_test to filter out possible errors like this one, so that execution can continue? I've tried BOOST_AUTO_TEST_CASE_EXPECTED_FAILURE(blah, 1), but this is just to tell boost::unit_test that you are expecting a failure. It reports failure detected (failure expected) in test. I would like a passed test situation instead.

rturrado
  • 7,699
  • 6
  • 42
  • 62
  • 1
    Does the aSystemCall return, or throw an exception? – Arafangion Mar 16 '11 at 12:40
  • Side-note: To check for boolean values, use `BOOST_CHECK` instead of `BOOST_CHECK_EQUAL`. It's more concise. – Björn Pollex Mar 16 '11 at 12:45
  • If the test passes in the debugger, *what* doesn't work when running the test normally? Maybe provide the error output from Boost.Test. – Martin Ba Mar 16 '11 at 13:24
  • @Arafangion - aSystemCall spanws a new process, which exits with nonzero. But the parent process just returns an error code. @Space_C0wb0y - Doesn't BOOST_CHECK_EQUAL gives you output information of the kind false=...? @Martin - I think boost just complains of a child process exiting with a nonzero code. – rturrado Mar 16 '11 at 14:20

5 Answers5

4

First of all i get this odd behavior only on Linux.

I've found that Boost.Test changes the way it handles child exit codes with the deploy model you choose. If you are using static linking of boost libraries or the "all in one" header boost/test/included/unit_test.hpp inserting a define:

#define BOOST_TEST_IGNORE_NON_ZERO_CHILD_CODE

before any include directive solves the problem.

If you are using dynamic linking, this isn't enough. You have either to call the resulting test with the command line option "--catch_system_errors=no" or define the following environment variable.

export BOOST_TEST_CATCH_SYSTEM_ERRORS="no"

I'm using boost 1.52 and 1.57, GCC 4.7.2, on a debian wheezy.

Here is the reference to deploy models of Boost.Test

see also this question: how-to-cancel-fatal-error-detection-in-boost-test

Community
  • 1
  • 1
Gab
  • 756
  • 11
  • 23
  • 1
    This does not appear to work on Boost 1.55. `--catch_system_errors=no` does appear to work, as mentioned in another answer. – Steve Aug 19 '14 at 13:18
1

This is resolved in later version of Boost.Test

Gennadiy Rozental
  • 1,905
  • 2
  • 13
  • 17
  • Thanks Gennadiy, always good knowing first hand from a boost developer :) So I understand there is no way of achieving what I want with the current boost test implementation. – rturrado Mar 16 '11 at 16:13
  • Not sure what you mean by "current". This is resolved several boost releases ago. If you are talking about your local verison, and you have boost sources, you can disable SIGCHLD handler in execution monitor yourself. – Gennadiy Rozental Mar 16 '11 at 16:40
  • OK, I had understood "This is resolved in an upcoming version of Boost.Test". I am using 1.44. Is disabling SIGCHLD the only way of getting the behaviour I expect? – rturrado Mar 16 '11 at 16:48
  • 5
    This answer is not well explained. – Jesus Fernandez Mar 17 '11 at 08:53
  • 3
    @Gennadiy I got the expected behaviour using '#define BOOST_TEST_IGNORE_NON_ZERO_CHILD_CODE' before the unit_test.hpp include. Is that flag, and others, defined somewhere within boost test doc? Can you def/undef that for a test, or just for a whole run? – rturrado Mar 17 '11 at 08:54
  • @rturrado BOOST_TEST_IGNORE_NON_ZERO_CHILD_CODE should work, but I pretty sure SIGCHLD handler disabled completely in trunk for quite some time. There is small chance I did not move the changes into the release brunch. I'll follow up. – Gennadiy Rozental Mar 22 '11 at 19:16
  • 3
    @Gennadiy Setting this answer as my accepted answer, but I would appreciate a more detailed explanation from your side, and the outcome of your follow up. – rturrado Apr 08 '11 at 15:58
1

Adding --catch_system_errors=no at run-time also works.

I would prefer to be able to handle this with a a macro similar to BOOST_CHECK_THROW or a #define that doesn't require recompiling unit_test, but at least there's a solution in place.

  • This does appear to work on Boost 1.55, `#define BOOST_TEST_IGNORE_NON_ZERO_CHILD_CODE` as mentioned in another answer doesn't appear to work. – Steve Aug 19 '14 at 13:18
  • Unfortunately only when linking staticly – jhasse Oct 21 '16 at 19:07
0

If you run your test from terminal you should set to "no" Boost environment variable catch_system_errors. In case Ubuntu OS, you have to type next command in terminal before test execution:

export BOOST_TEST_CATCH_SYSTEM_ERRORS="no"
Ivan_a_bit_Ukrainivan
  • 808
  • 1
  • 10
  • 27
0

Expanding a bit on Chip Christian's answer: (re)compiling boost.test with the BOOST_TEST_IGNORE_NON_ZERO_CHILD_CODE flag works (tested for boost 1.53). On the bjam command line, add:

cxxflags="-DBOOST_TEST_IGNORE_NON_ZERO_CHILD_CODE"

Note that adding this flag did not always seem to force a recompile, so I did the following to force recompiling:

touch boost/test/impl/execution_monitor.ipp
Community
  • 1
  • 1
Adversus
  • 2,166
  • 20
  • 23