【问题标题】:boost::unit_test case fails because a child process exits with nonzeroboost::unit_test 案例失败,因为子进程以非零值退出
【发布时间】:2011-07-16 13:28:58
【问题描述】:

我有以下代码:

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

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

如果我在命令行中执行command,我会收到权限被拒绝错误。我知道这一点。这正是我想要测试的。
aSystemCall 将命令作为子进程执行。当子进程以非零错误退出此命令时,aSystemCall 返回错误。它不会抛出。
如果我在命令行中运行BadDir 测试用例,aSystemCall 之后的代码永远不会执行,并且测试失败,输出如下:

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"

如果我在gdb中运行BadDir测试用例,aSystemCall返回,可以检查结果,测试通过。

有没有办法告诉 boost::unit_test 过滤掉像这样的可能错误,以便继续执行?我试过BOOST_AUTO_TEST_CASE_EXPECTED_FAILURE(blah, 1),但这只是告诉 boost::unit_test 你期待失败。它报告在测试中检测到失败(预期失败)。我想要一个通过的测试情况。

【问题讨论】:

  • aSystemCall 是返回还是抛出异常?
  • 旁注:要检查布尔值,请使用BOOST_CHECK 而不是BOOST_CHECK_EQUAL。更简洁。
  • 如果在调试器中测试通过,正常运行测试时什么不起作用?也许提供 Boost.Test 的错误输出。
  • @Arafangion - aSystemCall 生成一个新进程,该进程以非零值退出。但是父进程只是返回一个错误代码。 @Space_C0wb0y - BOOST_CHECK_EQUAL 不会为您提供 false=... 的输出信息吗? @Martin - 我认为 boost 只是抱怨一个子进程以非零代码退出。

标签: c++ unit-testing boost


【解决方案1】:

首先,我只在 Linux 上得到这种奇怪的行为。

我发现 Boost.Test 通过您选择的部署模型改变了它处理子退出代码的方式。 如果您使用的是 boost 库的静态链接或“一体化”标头 boost/test/included/unit_test.hpp 插入定义:

#define BOOST_TEST_IGNORE_NON_ZERO_CHILD_CODE

在任何包含指令解决问题之前。

如果您使用的是动态链接,这还不够。您必须使用命令行选项 "--catch_system_errors=no" 调用生成的测试,或者定义以下环境变量。

export BOOST_TEST_CATCH_SYSTEM_ERRORS="no"

我在 debian wheezy 上使用 boost 1.52 和 1.57,GCC 4.7.2。

这里引用deploy models of Boost.Test

另请参阅此问题:how-to-cancel-fatal-error-detection-in-boost-test

【讨论】:

  • 这似乎不适用于 Boost 1.55。 --catch_system_errors=no 似乎确实有效,如另一个答案中所述。
【解决方案2】:

这已在更高版本的 Boost.Test 中解决

【讨论】:

  • 感谢 Gennadiy,从 boost 开发人员那里了解第一手资料总是很不错的 :) 所以我知道当前的 boost 测试实现无法实现我想要的。
  • 不确定您所说的“当前”是什么意思。这在几个增强版本前已解决。如果您正在谈论您的本地版本,并且您有提升源,您可以自己在执行监视器中禁用 SIGCHLD 处理程序。
  • 这个答案解释得不好。
  • @Gennadiy 我在 unit_test.hpp 包含之前使用“#define BOOST_TEST_IGNORE_NON_ZERO_CHILD_CODE”得到了预期的行为。该标志和其他标志是否在 boost 测试文档中的某个地方定义?你可以为测试定义/取消定义,还是只为整个运行?
  • @Gennadiy 将此答案设置为我接受的答案,但我希望您能提供更详细的解释,以及您跟进的结果。
【解决方案3】:

在运行时添加 --catch_system_errors=no 也可以。

我希望能够使用类似于 BOOST_CHECK_THROW 的宏或不需要重新编译 unit_test 的 #define 来处理这个问题,但至少有一个解决方案。

【讨论】:

  • 这似乎适用于 Boost 1.55,#define BOOST_TEST_IGNORE_NON_ZERO_CHILD_CODE 如另一个答案中提到的似乎不起作用。
  • 不幸的是,只有在静态链接时
【解决方案4】:

如果您从终端运行测试,您应该将 Boost 环境变量设置为“no”catch_system_errors。 如果是 Ubuntu 操作系统,您必须在测试执行前在终端中输入下一条命令:

export BOOST_TEST_CATCH_SYSTEM_ERRORS="no"

【讨论】:

    【解决方案5】:

    在 Chip Christian 的 answer 上扩展一点:(重新)使用 BOOST_TEST_IGNORE_NON_ZERO_CHILD_CODE 标志编译 boost.test 有效(针对 boost 1.53 进行了测试)。在 bjam 命令行中,添加:

    cxxflags="-DBOOST_TEST_IGNORE_NON_ZERO_CHILD_CODE"
    

    请注意,添加此标志似乎并不总是强制重新编译,因此我执行了以下操作来强制重新编译:

    touch boost/test/impl/execution_monitor.ipp
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-28
      • 2021-05-10
      • 1970-01-01
      • 2017-03-08
      • 1970-01-01
      • 1970-01-01
      • 2019-06-08
      • 1970-01-01
      相关资源
      最近更新 更多