我有一个带有cmocka测试的C项目,它是使用CMake构建的。现在我尝试使用gcov来确定测试覆盖率并使用此CMake模块:https://github.com/bilke/cmake-modules/blob/master/CodeCoverage.cmake 该模块提供了一个make目标,它运行测试目标可执行文件(运行gcov),然后运行lcov和genhtml来生成报告。
现在,问题是,当执行测试目标时,它会创建仅具有所有者可执行位集的.gcda文件,即。即读取位丢失。随后,lcov无法读取这些文件并生成覆盖率为0%的报告。当我手动chmod u+r
gcda文件并手动运行测试后的lcov命令时,报告会成功生成(显示实际覆盖的内容)。因此,gcda文件已创建且有效,但它们具有不适当的权限集。
这个问题似乎源于包装(使用ld --wrap)open
函数,用于在测试用例中捕获返回的文件描述符。这是一个最小的编译示例:
/* wrapped_open.c */
int main(void)
{
return 0;
}
int __wrap_open(const char *filename, int flags)
{
return __real_open(filename, flags);
}
# CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(gcov-mvce C)
add_executable(wrapped_open wrapped_open.c)
target_link_libraries(wrapped_open
-Wl,--wrap=open
)
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_SOURCE_DIR}/cmake")
include(CodeCoverage)
set_target_properties(wrapped_open PROPERTIES
COMPILE_FLAGS "-g -O0 --coverage -fprofile-arcs -ftest-coverage"
LINK_FLAGS "-lgcov --coverage")
setup_target_for_coverage(wrapped_open_coverage wrapped_open "coverage")
# build like this:
cmake . -DCMAKE_BUILD_TYPE=Debug # in-source build
make
# receive coverage report like this
make wrapped_open_coverage
# simple gcc command line for compiling (no cmake required)
gcc -g -O0 --coverage -fprofile-arcs -ftest-coverage -lgcov -Wl,--wrap=open -o wrapped_open wrapped_open.c
当分别从链接器标志和代码中删除open和wrap函数定义的包装时,它可以工作。但是使用上面的文件,使用访问掩码0100创建文件wrapped_open.c.gcda
,并由lcov报告以下内容:
(bulid-directory)/CMakeFiles/wrapped_open.dir/wrapped_open.c.gcda:cannot open data file, assuming not executed
...导致覆盖0/4行和0/2函数。
为什么在打开函数像上面这样包装时访问位是错误的,即使每个路径仍然使用未修改的参数调用原始函数(至少这是它打算做的)?一个明显的解决方法是修改cmake模块为我做chmod,但我想更好地了解打开包装时出了什么问题。
请在评论中告诉我是否以及可能需要哪些其他信息来回答这个问题。
答案 0 :(得分:1)
正如评论中所指出的,open()
是一个带有可变参数的函数。如果创建了文件,则第三个参数是文件的模式。在我的__wrap_open
实现中,我省略了第三个参数,因为我没有想到其他代码而不是被测试的代码也会调用open()
。当然,gcov最终会创建它的gcda文件,因为我没有为__real_open
指定第三个参数,所以模式中存在一些未定义的内容。
因此,解决方案是始终在包装函数中包含所有可能的参数。