对open()进行包装进行单元测试会导致gcov无法打开gcda文件。

4
我正在实施一些C程序的测试,需要涉及IT技术。为此,我使用GCC的-Wl,--wrap=open来模拟stdlib的open()函数,并检查是否使用了正确的选项。
然而,在这样做时,gcov在编写其.gcda文件时遇到了一些问题。我猜测我定义的模拟函数不仅被我的测试使用,还被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进行单元测试的部分,以显示我遇到的错误。

在使用GCC和gcov 6.3.0运行可执行文件a.out时,会得到以下输出:

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

有没有一种方法可以模拟open()函数来进行单元测试,并能够使用gcov生成代码覆盖率数据?也许有一种方法可以告诉gcov使用__real_open()
1个回答

3
实现该目标的简单方法如下:
  • 检查传递给 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;
}

通过这种方式,您当然可以轻松地添加更多不应被篡改的文件。


@MicroJoe 没问题,如果你感觉更好的话 ;) - Ctx
另外,如果我也包装close(),我应该担心什么吗?实际上,我正在包装open()和close(),但在__wrap_close中并没有实际关闭任何内容。我的覆盖率报告在不调用__real_close的情况下工作正常,我猜操作系统会在退出时自动关闭文件描述符? - MicroJoe
@MicroJoe 是的,这是正确的。但是为什么你要包装关闭呢?包装关闭有什么作用? - Ctx
如果我模拟一个错误,它只是检查是否正确调用了close。也许这是过度测试,如果操作系统确保在退出时关闭文件。 - MicroJoe
1
@MicroJoe 嗯,但是你也可以在那里调用__real_close(),使用给定的文件描述符句柄,这可能不会有影响。 - Ctx
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接