包装 open() 进行单元测试将使 gcov 无法打开 gcda 文件

Wrapping open() for unit testing will make gcov not able to open gcda file

我正在为某些 C 程序实施使用测试。为此,我使用 GCC 的 -Wl,--wrap=open 来模拟 stdlib 的 open() 函数并检查它是否已使用正确的选项调用。

然而,这样做时 gcov 在写入其 .gcda 文件时遇到了一些问题。我想我定义的 mock 不仅被我的测试使用,也被 gcov 使用。下面是一个如何重现这个的小例子:

#include <stdio.h>

int __wrap_open(const char *path, int flags, int mode)
{
    printf("hello from __wrap_open\n");
    return -1;
}


int main(void)
{
    return 0;
}

并用gcc main.c -Wl,--wrap=open -fprofile-arcs -ftest-coverage -lgcov编译。为了使示例保持简单,我使用 CMocka 删除了单元测试部分,以显示我遇到的错误。

当 运行 可执行文件 a.out 我使用 GCC 和 gcov 6.3.0 得到以下输出:

$ ./a.out
hello from __wrap_open
hello from __wrap_open
profiling:/home/romain/wrap-bug/main.gcda:Cannot open

有没有办法为我的单元测试目的模拟 open() 函数 以便能够使用 gcov 来生成代码覆盖率数据?也许有办法告诉 gcov 使用 __real_open()?

一个简单的方法是:

  • 检查传递给 open() 的文件路径是否是您的分析文件
  • 如果是,将调用传递给 __real_open()

int __real_open(const char *path, int flags, int mode);

int __wrap_open(const char *path, int flags, int mode)
{
    if (strlen(path) > 5 && !strcmp(path + strlen(path) - 5, ".gcda"))
        return __real_open(path, flags, mode);
    printf("hello from __wrap_open\n");
    return -1;
}

使用这种方式,您当然可以轻松添加更多文件,这些文件不应被篡改。