25

今天我的任务是在我们的代码库中添加单元测试覆盖分析。今天也是 iOS 7.1 与 XCode 5.1 一起发布的日子。从发行说明:

重新实现了用于代码覆盖测试的 gcov 工具。新版本使用来自 LLVM 项目的 llvm-cov 工具。它在功能上等同于旧版本的所有重要特性。Xcode 中 gcov 的位置也移动了,使用 xcrun 调用它。如果您发现问题,请提交错误报告。对于此版本,您仍然可以使用来自 GCC 的旧版本 gcov,它以 gcov-4.2 的形式提供。11919694 更新

我只是在阅读了几篇指导性 博客 文章后才意识到这一点,正确设置了我的环境-在测试时在模拟器的构建文件夹中生成 .gcda/.gcno 文件-并让此处的报告生成工具尝试将它们解析为报告。(这是一个 ./getcov 脚本,它收集您的环境变量以传递给 lcov-1.10 脚本以生成报告)

第一个障碍是新的捆绑gcov程序不支持获取版本的参数,这是初始化-v的第一步。lcov似乎已经不是初学者了,但是阅读上面的发行说明,我修改了lcov脚本以使用旧gcov-4.2版本并解决了这个问题。

但是,lcov在处理我的覆盖数据文件时很早就出错了。这会生成一个报告,其中可能包含我项目中按字母顺序排列的前 10 个左右的文件。不是特别有用。错误输出也很小且无济于事:

geninfo: 错误: (build_artifacts)/(class_that_errored).gcda 的 GCOV 失败!

我修改了lcov脚本以打印它得到的错误(11不幸的是,它只产生了,在 gcov(-io).c 代码中找不到任何引用)并继续操作而不是退出,所以我留下了更多报告中的文件,但仍然可能有 85% 的源文件如上所述错误。

在报告中成功结束的文件和引发错误的文件之间,我能辨别的唯一模式是任何使用内联块声明的文件都失败了。没有以任何方式通过使用块的文件,并且我检查过的所有失败的文件都包含块。奇怪的。

然后我发现我可以打开CoverStory中的各个 .gcda 文件,包括那些在lcov脚本中出错的文件。在覆盖率报告下方的消息窗口中,所有出错的文件都有警告消息:

(class_that_errored).gcno: '__copy_helper_block_' 没有行

(class_that_errored).gcno: '__destroy_helper_block_' 没有行

在这一点上,我最好的假设是新的 XCode 5.1 正在生成旧gcov-4.2程序无法处理有关块声明的 .gcda 文件。

但是我已经用尽了所有我能想到的尝试,所以我在这里询问是否有人有我错过的知识,或者有任何想法来进一步调试工作。或者,如果自从今天的 XCode 5.1 更新后,有人成功地测量了测试覆盖率gcov,我也很想听听您必须做出的任何更改。

4

4 回答 4

13

问题出在 LCOV 1.10 geninfo脚本中。它测试当前版本的 gcov。它通过解析版本字符串来做到这一点。由于 gcov 现在指向 llvm-cov,版本字符串被错误地解析。

解决方法是修改geninfo的 get_gcov_version() 子程序。在第1868行,更改-v--version. 然后将第1874行替换为:

if ($version_string =~ m/LLVM/)
{
    info("Found llvm-cov\n");
    $result = 0x40201;
}
elsif ($version_string =~ /(\d+)\.(\d+)(\.(\d+))?/)

 

修改后的子程序应如下所示:

sub get_gcov_version()
{
    local *HANDLE;
    my $version_string;
    my $result;

    open(GCOV_PIPE, "-|", "$gcov_tool --version")
        or die("ERROR: cannot retrieve gcov version!\n");
    $version_string = <GCOV_PIPE>;
    close(GCOV_PIPE);

    $result = 0;
    if ($version_string =~ m/LLVM/)
    {
        info("Found llvm-cov\n");
        $result = 0x40201;
    }
    elsif ($version_string =~ /(\d+)\.(\d+)(\.(\d+))?/)
    {
        if (defined($4))
        {
            info("Found gcov version: $1.$2.$4\n");
            $result = $1 << 16 | $2 << 8 | $4;
        }
        else
        {
            info("Found gcov version: $1.$2\n");
            $result = $1 << 16 | $2 << 8;
        }
    }
    return ($result, $version_string);
}

 

注意:确保--gcov-tool设置gcov-4.2.

于 2014-03-14T12:06:58.467 回答
2

实际上,我注意到 lcov 正在使用 -b 选项调用 gcov,而 gcov-4.2 将在此选项上崩溃(引发分段错误)。如果我从 getinfo 中删除 -b 选项,那么即使它仍然显示一些错误信息,仍然可以生成 gcov 文件。

这可能就是为什么封面故事仍然可以提供报道输出的原因。所以我想解决方法是从lcov中删除-b选项。而且正如你所建议的,忽略 getinfo 中的错误

于 2014-03-19T23:22:56.797 回答
2

我没有修改,而是geninfo创建了一个llvm-cov-wrapper脚本并使用了 lcov 的--gcov-tool命令行选项:

#!/bin/bash
# llvm-cov wrapper to make it behave more like gcov

if [ "$1" = "-v" ]; then
    echo "llvm-cov-wrapper 4.2.1"
    exit 0
else
    /usr/bin/gcov $*
fi
于 2014-03-14T17:57:35.363 回答
0

对于此线程的新手,请注意 lcov-1.11 已发布。这消除了gcov -v兼容性问题。但是,我使用的是 XCode 6.1,但某些文件仍然出现错误。

geninfo: WARNING: /Users/XXX/MyFile.gcno: found unrecognized record format - skipping

请注意,您可以添加--ignore-errors graph以跳过这些错误,但问题并没有真正解决。

于 2015-02-16T01:46:43.430 回答