查找未执行的c ++代码行

exa*_*ple 6 c++ macros code-coverage g++ c++11

作为我的单元测试的一部分,我想确保测试的代码覆盖率.目的是REQUIRE_TEST在代码中的某处放置类似宏的东西,并检查是否所有这些都被调用.

void foo(bool b) {
  if (b) {
    REQUIRE_TEST
    ...
  } else {
    REQUIRE_TEST
    ...
  }
}

void main() {
  foo(true);

  output_all_missed_REQUIRE_macros();
}
Run Code Online (Sandbox Code Playgroud)

理想情况下,输出将包括源文件和宏的行.

我最初的想法是让宏创建静态对象,这些对象会在某个映射中注册自己,然后检查是否所有这些都被调用

#define REQUIRE_TEST \
        do { \
            static ___RequiredTest requiredTest(__func__, __FILE__, __LINE__);\
            (void)requiredTest;\
            ___RequiredTest::increaseCounter(__func__, __FILE__, __LINE__);\
        } while(false)
Run Code Online (Sandbox Code Playgroud)

但静态对象仅在第一次调用代码时创建.因此,映射仅包含在下一行中计算的函数 - 找不到丢失的REQUIRE_TEST宏.在__attribute__((used))这种情况下被忽略.

gcc有一个很好的属性__attribute__((constructor)),但显然选择在放在这里时忽略它(代码而不是静态对象)

struct teststruct { \
  __attribute__((constructor)) static void bla() {\
    ___RequiredTest::register(__func__, __FILE__, __LINE__); \
  } \
};\
Run Code Online (Sandbox Code Playgroud)

以及

[]() __attribute__((constructor)) { \
  ___RequiredTest::register(__func__, __FILE__, __LINE__); \
};\
Run Code Online (Sandbox Code Playgroud)

我现在想到的唯一出路是a)手动(或通过脚本)分析常规编译之外的代码(uargh)或b)使用__COUNTER__宏来计算宏 - 但后来我不知道哪些特定的REQUIRE_TEST宏没有被称为......(如果其他人决定使用__COUNTER__宏,一切都会破裂......)

这个问题有没有合适的解决方案?我错过了什么?有一个宏可以附加当前行和文件,所以无论何时调用它都会有一些预处理器变量 - 但这是不可能的,对吧?有没有其他方法main()可以在功能体内完成之前注册要执行的内容?

Jer*_*emy 1

一种丑陋但简单的方法是REQUIRE_TEST使用__LINE____COUNTER__构造它所引用的唯一文件范围静态对象的名称,如果尚未声明,则会导致编译器错误。然后,您需要预先手动声明所有此类对象,每个对象一个REQUIRE_TEST- 但如果您没有这样做,至少会出现编译错误。

嘿嘿,我就说丑吧!