检查该函数是否已在 gtest 中调用
Check if the function has been called in gtest
在gtest框架中,有什么方法可以检查函数是否被调用? (没有 gmock,仅使用 gtest)
例如:
class a
{
public:
void dd() {...};
void cc() {...};
void bb() {...};
void aa()
{
bb(cc(dd()));
}
};
void main ()
{
a dut;
dut.aa();
}
我不关心函数输入甚至输出的正确性。
我只想知道函数(例如 aa())是否已被触发。
有什么解决办法吗?非常感谢!
without gmock, use gtest only
这是一个非常严格的限制。通常,您无法判断函数是否被调用。 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);
}
您不需要将自己局限于函数设置的标志。日志消息和其他副作用也是可行的。
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"));
}
如上所述,这是一个脆弱的解决方案,因为您可能正在检查未来随机变化的副作用。然而,有时这已经足够了。
热修补函数以跟踪调用
这很讨厌,我无法提供完整的示例,因为执行此操作的方法取决于您的编译器和目标。基本上,您指示编译器生成以一些无操作(不一定是 NOP)指令开头的函数。这允许您获取函数的地址,更改这些指令以跳转到某个地方然后返回。这非常有用,因为您可以调用一个注册了 return 地址的函数,您可以从中判断函数是否被调用。它被称为 iif aa()
的 return 地址已注册。
您将需要 OS 特定的调用来热修补您的代码,并且需要了解您正在 运行 使用的 CPU 指令。你显然失去了便携性。我也不知道你的要求,但这可能不值得。
总而言之,如果您想保持在标准范围内,最好的选择是 gmock。虚函数是动态调度的标准方式(如果你正在热修补你的图像,你就会这样做)。
在gtest框架中,有什么方法可以检查函数是否被调用? (没有 gmock,仅使用 gtest) 例如:
class a
{
public:
void dd() {...};
void cc() {...};
void bb() {...};
void aa()
{
bb(cc(dd()));
}
};
void main ()
{
a dut;
dut.aa();
}
我不关心函数输入甚至输出的正确性。 我只想知道函数(例如 aa())是否已被触发。 有什么解决办法吗?非常感谢!
without gmock, use gtest only
这是一个非常严格的限制。通常,您无法判断函数是否被调用。 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);
}
您不需要将自己局限于函数设置的标志。日志消息和其他副作用也是可行的。
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"));
}
如上所述,这是一个脆弱的解决方案,因为您可能正在检查未来随机变化的副作用。然而,有时这已经足够了。
热修补函数以跟踪调用
这很讨厌,我无法提供完整的示例,因为执行此操作的方法取决于您的编译器和目标。基本上,您指示编译器生成以一些无操作(不一定是 NOP)指令开头的函数。这允许您获取函数的地址,更改这些指令以跳转到某个地方然后返回。这非常有用,因为您可以调用一个注册了 return 地址的函数,您可以从中判断函数是否被调用。它被称为 iif aa()
的 return 地址已注册。
您将需要 OS 特定的调用来热修补您的代码,并且需要了解您正在 运行 使用的 CPU 指令。你显然失去了便携性。我也不知道你的要求,但这可能不值得。
总而言之,如果您想保持在标准范围内,最好的选择是 gmock。虚函数是动态调度的标准方式(如果你正在热修补你的图像,你就会这样做)。