gpt4 book ai didi

c++ - 为什么链接顺序会影响使用宏的测试的测试结果?

转载 作者:行者123 更新时间:2023-11-30 03:54:21 24 4
gpt4 key购买 nike

我使用 Google Test 和 Google Mock 通过测试驱动开发编写代码。我正在为 Google Test 编写一个小的“插件”。为了确保测试会在预期的正确消息时失败,我创建了一个简单的 FailureReporter 类,我将对其进行子类化并在插件中注入(inject)模拟版本以捕获结果并与预期值进行比较.

本着 TDD 极端主义的精神,我还编写了一个测试来确保 FailureReporter 正常工作。为此,我“替换”了 FAIL() 宏,以便不导致失败但捕获生成的错误消息。然而,这就是事情变得奇怪的地方。它在一台机器上工作,但在另一台机器上不工作。在寻找原因时,我发现可以通过更改链接顺序来修复它。这看起来很奇怪,因为“修复”是使用宏完成的,我认为它会在编译时进行硬编码,并且链接它不会有什么不同。

我发现:单独链接测试不会造成任何问题。仅当另一个测试链接在 FailureReporterTest 之后时,将其与使用 FailureReporter 模拟版本的测试链接才有效。 为什么会发生这种情况?

失败报告者.hpp:

#ifndef FAILURE_REPORTER_H
#define FAILURE_REPORTER_H

#include "gtest/gtest.h"

class FailureReporter {
public:
virtual void fail(const char* errorMessage) {
FAIL() << errorMessage;
}
};

#endif

FailureReporterTest.cpp:

#include <sstream>

#include "gtest/gtest.h"

static std::stringstream* failStream;

#ifdef FAIL
#undef FAIL
#endif

#define FAIL() *failStream << ""

#include "FailureReporter.hpp"

TEST(FailureReporterTest, failMethod) {
const char* errorMessage = "Test error message";
FailureReporter *reporter;
std::stringstream stream;

failStream = &stream;

reporter = new FailureReporter();

reporter->fail(errorMessage);

EXPECT_STREQ(errorMessage, stream.str().c_str());

delete reporter;
}

MockFailureReporter.cpp

#ifndef MOCK_FAILURE_REPORTER_HPP
#define MOCK_FAILURE_REPORTER_HPP

#include "gmock/gmock.h"

#include "FailureReporter.hpp"

class MockFailureReporter : public FailureReporter {
public:
MOCK_METHOD1(fail, void(const char*));
};

#endif

DummyTest.cpp

#include "gtest/gtest.h"

#include "MockFailureReporter.hpp"

TEST(DummyTest, dummy) {
new MockFailureReporter();
SUCCEED();
}

编译源代码

g++ -c DummyTest.cpp
g++ -c FailureReporterTest.cpp

并将它们链接到

g++ DummyTest.o FailureReporterTest.o -pthread -lgtest -lgmock -lgmock_main

生成一个未通过 failMethod 测试的 a.out 可执行文件,同时将它们链接到

g++ FailureReporterTest.o DummyTest.o -pthread -lgtest -lgmock -lgmock_main

生成一个成功通过两个测试的 a.out 可执行文件。为什么?

最佳答案

class FailureReporter {
public:
virtual void fail(const char* errorMessage) {
/* code */

创建 FailureReporter::fail 的隐式内联实现。

inline 函数被导出。如果链接器看到两个具有相同名称和类型的 inline 函数,它会默默地丢弃一个。如果它们实际上不相同,那么您的程序格式不正确,并且不需要诊断。

当您仅在一个编译单元中重新定义 FAIL() 并将其与其他编译单元链接时,您最终会得到 FailureReporter::fail 的两个定义。他们链接,并导致未定义的行为。在您的情况下,您可以在两种情况下运行其中一个,确定链接器选择丢弃内联冲突的任意规则。这看起来像是“保留我看到的第一个”。

关于c++ - 为什么链接顺序会影响使用宏的测试的测试结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29591478/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com