如何解决谷歌模拟 Linux 上的免费系统功能总是以内存泄漏结束
我正在尝试模拟 Linux 标准库中的一个简单函数。 strerror()
从 errno 返回错误消息。这是我的带有模拟功能的库:
~$ cat mylib.c
#include <string.h>
#include <stdio.h>
int myStrerror()
{
int error_number = 0;
char* buffer = strerror(error_number);
fprintf(stdout,"Returned string = '%s'\n",buffer);
return 0;
}
#if defined (EXECUTABLE)
int main(int argc,char **argv)
{
return myStrerror();
}
#endif
~$ g++ -pedantic-errors -Wall -c mylib.c
这是我的谷歌测试:
~$ cat test_mylib.cpp
#include "gtest/gtest.h"
#include "gmock/gmock.h"
int myStrerror();
class strerrorMock {
public:
MOCK_METHOD(char*,strerror,(int));
};
strerrorMock strerrorMockObj;
char *strerror(int error_number) {
return strerrorMockObj.strerror(error_number);
}
TEST(MockTestSuite,strerror)
{
using ::testing::Return;
char response[] = "mocked strerror function";
EXPECT_CALL(strerrorMockObj,strerror(0))
.WillOnce(Return(response));
EXPECT_EQ(myStrerror(),0);
::testing::Mock::VerifyAndClearExpectations(&strerrorMockObj);
}
int main(int argc,char **argv) {
::testing::InitGoogleTest(&argc,argv);
return RUN_ALL_TESTS();
}
~$ g++ -pedantic-errors -Wall \
-o test_mylib.a \
-I"$BUILD_DIR"/googletest-src/googletest/include \
-I"$BUILD_DIR"/googletest-src/googlemock/include \
test_mylib.cpp \
"$BUILD_DIR"/lib/libgtestd.a \
"$BUILD_DIR"/lib/libgmockd.a \
./mylib.o \
-lpthread
这是正常返回的:
~$ ./mylib.a
Returned string = 'Success'
并运行测试给出:
~$ ./test_mylib.a
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from MockTestSuite
[ RUN ] MockTestSuite.strerror
Returned string = 'mocked strerror function'
[ OK ] MockTestSuite.strerror (0 ms)
[----------] 1 test from MockTestSuite (0 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[ PASSED ] 1 test.
test_mylib.cpp:32: 错误:这个模拟对象(在测试 MockTestSuite.strerror 中使用)应该被删除,但永远不会被删除。它的地址是@0x56114aa239e0。
错误:在程序退出时发现 1 个泄漏的模拟对象。当对象被破坏时,验证对模拟对象的期望。泄漏一个模拟意味着它的期望没有得到验证,这通常是一个测试错误。如果你真的打算泄漏一个模拟,你可以使用 testing::Mock::AllowLeak(mock_object) 来抑制这个错误,或者你可以使用假或存根代替模拟。
我该怎么做才能避免内存泄漏?
解决方法
问题是我们使用了系统库中的免费全局函数 strerror()
。它并没有像往常一样被 Googlemock 的界面嘲笑。所以我们不需要接口。我们必须用一个自由函数来覆盖模拟函数,该函数必须是全局的,才能与系统函数处于同一范围内,因为它将替换它。这就是我们所做的:
strerrorMock strerrorMockObj;
char* strerror(int error_number) {
return strerrorMockObj.strerror(error_number);
}
这里模拟的实例 strerrorMockObj
也在全局范围内,可以在函数内调用。但显然 Googletest 无法删除错误消息中指出的全局模拟对象。我发现的一种解决方案是像往常一样在测试宏中实例化模拟对象并存储指向它的全局指针,以便函数可以对其进行寻址:
strerrorMock* ptrStrerrorMockObj;
char* strerror(int error_number) {
return ptrStrerrorMockObj->strerror(error_number);
}
TEST(MockTestSuite,strerror)
{
strerrorMock strerrorMockObj;
ptrStrerrorMockObj = &strerrorMockObj;
...
}
然后没有抱怨内存泄漏的完整测试程序如下所示:
~$ cat test_strerror.cpp
#include "gtest/gtest.h"
#include "gmock/gmock.h"
int myStrerror();
class strerrorMock {
public:
MOCK_METHOD(char*,strerror,(int));
};
strerrorMock* ptrStrerrorMockObj;
char* strerror(int error_number) {
return ptrStrerrorMockObj->strerror(error_number);
}
TEST(MockTestSuite,strerror)
{
using ::testing::Return;
strerrorMock strerrorMockObj;
ptrStrerrorMockObj = &strerrorMockObj;
char mockedstr[] = "mocked strerror function";
EXPECT_CALL(strerrorMockObj,strerror(0))
.WillOnce(Return(mockedstr));
EXPECT_EQ(myStrerror(),0);
}
int main(int argc,char **argv) {
::testing::InitGoogleTest(&argc,argv);
return RUN_ALL_TESTS();
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。