检查函数是否在 gtest 中被调用过

Har*_*old 3 c++ googletest

在gtest框架中,有没有办法检查一个函数是否被调用?(没有 gmock,仅使用 gtest)例如:

class a
{
    public: 
    void dd() {...};
    void cc() {...};
    void bb() {...};
    void aa()
    {
        bb(cc(dd()));
    }
};

void main ()
{
    a dut;
    dut.aa();
}
Run Code Online (Sandbox Code Playgroud)

我不在乎函数输入,甚至输出的正确性。我只想知道该函数(例如 aa())是否已被触发。有什么解决办法吗?提前谢谢了!

Tam*_*lei 6

没有 gmock,只使用 gtest

这是一个非常严格的限制。通常,您无法判断函数是否被调用。Gmock 通过生成记录调用、参数的模拟函数来解决这个问题,并且可以根据运行时参数伪造行为。

没有这个,你只有两个选择:

观察相关函数的副作用。

这很简单,但很脆弱:如果您知道该函数有一个可观察到的副作用,您可以检查:

class a
{
public: 
    a() : aa_flag(false) {}

    void aa()
    {
        aa_flag = true;
    }

    bool aa_flag;
};

TEST(FuncCalled, CheckSideEffectFlag)
{
    a dut;
    dut.aa();
    EXPECT_TRUE(dut.aa_flag);
}
Run Code Online (Sandbox Code Playgroud)

您不需要将自己限制在函数设置的标志上。日志消息和其他副作用也是可行的。

class a
{
public: 
    a() : aa_flag(false) {}

    void aa()
    {
        LOG_INFO("aa called");
    }

    bool aa_flag;
};

TEST(FuncCalled, CheckSideEffectLog)
{
    a dut;
    dut.aa();
    EXPECT_TRUE(LogContains("aa called"));
}
Run Code Online (Sandbox Code Playgroud)

如上所述,这是一个脆弱的解决方案,因为您可能正在检查将来随机变化的副作用。然而,有时这已经足够了。

Hotpatch 函数以跟踪调用

这很糟糕,我无法提供完整的示例,因为执行此操作的方法取决于您的编译器和目标。基本上,您指示编译器生成以一些无操作(不一定是 NOP)指令开头的函数。这允许您获取函数的地址,更改这些指令以跳转到某处然后返回。这非常有用,因为您可以调用注册返回地址的函数,并从中可以判断函数是否被调用。如果返回地址aa()已注册,则调用它。

您将需要特定于操作系统的调用来热修补您的代码以及您正在运行的 CPU 指令的一些知识。你显然失去了便携性。我也不知道您的要求,但这可能不值得麻烦。


总而言之,如果您想保持在标准的范围内,最好的选择是 gmock。虚拟函数是动态调度的标准方式(如果你正在热修补你的图像,你会这样做)。