我有一些测试可以测试clang的地址清洁剂是否存在特殊错误。 (我想确保我对它可以捕获的错误类型的理解是正确的,并且未来版本继续捕获我期望它们的错误类型。)这意味着我有几个测试失败了OTHER_FAULT
,这似乎是clang运行时报告错误的固定方式。
我为这些测试设置了WILL_FAIL
标志为TRUE
,但这似乎只是检查成功的,无异常失败的返回值。如果进程以异常终止,则cmake仍将其归类为失败。
我还尝试使用PASS_REGULAR_EXPRESSION
来监视发生此错误时打印出来的区别消息,但同样,如果cmake以异常终止,它似乎将测试归类为失败。
我能做些什么来解决这个问题吗?
(特定于clang的答案也是一种选择! - 但我怀疑这是我最后一次需要测试这样的东西,所以我更愿意知道如何使用cmake,如果可能的话)
答案 0 :(得分:3)
CTest仅为测试程序的结果提供基本的,常用的解释器。为了实现其他解释器,您可以编写简单的程序/脚本,它根据需要包装测试并解释其结果。例如。 C程序(适用于Linux):
<强> test_that_crash.c 强>:
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
int main(int argc, char** argv)
{
pid_t pid = fork();
if(pid == -1)
{
// fork fails
return 1;
}
else if(pid)
{
// Parent - wait child and interpret its result
int status = 0;
wait(&status);
if(WIFSIGNALED(status)) return 0; // Signal-terminated means success
else return 1;
}
else
{
// Child - execute wrapped command
execvp(argv[1], argv + 1);
exit(1);
}
}
该程序可以在CMake中使用如下:
<强>的CMakeLists.txt 强>:
# Compile our wrapper
add_executable(test_that_crash test_that_crash.c)
# Similar to add_test(name command), but test is assumed successfull only if it is crashed(signalled)
macro(add_test_crashed name command)
# Use generic flow of add_test() command for automatically recognize our executable target
add_test(NAME ${name} COMMAND test_that_crash ${command} ${ARGN})
endmacro(add_test_crashed)
# ...
# Add some test, which should crash
add_test_crashed(clang.crash.1 <clang-executable> <clang-args>)
答案 1 :(得分:0)
还有一个特定于clang的解决方案:使用ASAN_OPTIONS
环境变量配置其退出方式。 (请参阅https://github.com/google/sanitizers/wiki/AddressSanitizerFlags。)为此,请将ASAN_OPTIONS
环境变量设置为abort_on_error=0
。当地址清理程序检测到问题时,该过程将执行_exit(1)
而不是(可能)abort()
,因此似乎已完全终止。然后,您可以使用cmake的WILL_FAIL
机制进行选择。 (目前还不清楚为什么OS X和Linux在这方面有所不同 - 但是你去了。)
作为奖励,测试失败的速度要快得多。
(通过cmake运行时可以改善周转时间的另一个方便选项是将ASAN_SYMBOLIZER_PATH
设置为空值,这会停止地址清理程序,表示堆栈跟踪。符号化需要一点时间,但有一些通过cmake运行时没有意义,因为你无法看到输出。)
我没有手动执行此操作,而是创建了一个Python脚本,在OS X上适当地设置环境(在Linux上不执行任何操作),并调用测试。然后我按照Tsyvarev的答案使用宏添加每个asan测试。
macro(add_asan_test basename)
add_executable(${basename} ${basename}.c)
add_test(NAME test/${basename} COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/wrap_clang_sanitizer_test.py -a $<TARGET_FILE:${basename}>)
set_tests_properties(test/${basename} PROPERTIES WILL_FAIL TRUE)
endmacro()
这样可以尽快完成简单的通过/失败。我习惯于通过手工运行有问题的测试并检查输出来调查失败,在这种情况下,我得到正常的堆栈跟踪(并且abort
退出的事实是有点慢是一个问题)。
(其他消毒杀菌剂有类似的选择,但我还没有调查过它们。)