- Notifications
You must be signed in to change notification settings - Fork8
A solution of mocking glibc function with Google Test.
License
NotificationsYou must be signed in to change notification settings
lonnywong/glibcmock
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Welcome toglibc mock, a solution of mocking glibc function (open, read, write … etc.) withGoogle Test andGoogle Mock!
Mock glibc function by changing GOT value to custom static function address.
As we know, glibc function address is store in GOT (Global Offset Table).
Change the GOT value to a custom static function address, then the glibc call will call the custom static function actually.
In the custom static function, we make it to call a Google Mock method, then we have mocked the glibc function.
- Copy
got_hook.h
andgot_hook.cc
to your C++ test project. - Add
#include "got_hook.h"
to your test source code.
structMockMalloc {MOCK_METHOD1(Malloc,void *(size_t));};static MockMalloc *g_mock{nullptr};staticvoid *Malloc(size_t size) {return g_mock->Malloc(size);}static std::mutex g_test_mutex;TEST(MallocTest, ReturnNull) { std::lock_guard<std::mutex>lock(g_test_mutex);// not thread safe std::unique_ptr<MockMalloc>mock(g_mock =newMockMalloc()); testing::GotHook got_hook;ASSERT_NO_FATAL_FAILURE(got_hook.MockFunction("malloc", (void*)&Malloc));// ... do your test here, for example:EXPECT_CALL(*g_mock,Malloc(testing::_)).WillOnce(testing::Return(nullptr));EXPECT_EQ(nullptr,malloc(1));}
constexprkey_t shm_key =0x123;structTurtle {voidUseSharedMemory() {auto shm_id =shmget(shm_key,0,0);auto buffer =shmat(shm_id,nullptr,0);EXPECT_STREQ("a fake shm buffer", (char*)buffer);// ...shmdt(buffer); }};structMockTurtle : Turtle {MOCK_METHOD3(shmget,int(key_t,size_t,int));MOCK_METHOD3(shmat,void*(int,constvoid*,int));MOCK_METHOD1(shmdt,int(constvoid*));};static MockTurtle *g_turtle{nullptr};staticintmy_shmget(key_t key,size_t size,int shmflg) {return g_turtle->shmget(key, size, shmflg);}staticvoid *my_shmat(int shmid,constvoid *shmaddr,int shmflg) {return g_turtle->shmat(shmid, shmaddr, shmflg);}staticintmy_shmdt(constvoid *shmaddr) {return g_turtle->shmdt(shmaddr);}static std::mutex g_test_mutex;TEST(TurtleTest, FakeSharedMemory) { std::lock_guard<std::mutex>lock(g_test_mutex);// not thread safe std::unique_ptr<MockTurtle>turtle(g_turtle =newMockTurtle()); testing::GotHook got_hook;ASSERT_NO_FATAL_FAILURE({ got_hook.MockFunction("shmget", (void*)&my_shmget); got_hook.MockFunction("shmat", (void*)&my_shmat); got_hook.MockFunction("shmdt", (void*)&my_shmdt); });constexprint shm_id =100;char fake_shm_buffer[2000]{"a fake shm buffer"};// ...EXPECT_CALL(*g_turtle,shmget(shm_key, _, _)).WillOnce(Return(shm_id));EXPECT_CALL(*g_turtle,shmat(shm_id, _, _)).WillOnce(Return(fake_shm_buffer));EXPECT_CALL(*g_turtle,shmdt(fake_shm_buffer)).WillOnce(Return(0));// ... g_turtle->UseSharedMemory();// ...}
constexprconstchar *prod_file ="/usr/local/xxx";constexprconstchar *test_file ="/tmp/xxx";structPanda {voidOpenFile() {auto fd =open(prod_file, O_RDONLY);// ...close(fd); }};structMockPanda : Panda {MOCK_METHOD2(Open,int(constchar*,int));};static std::mutex g_test_mutex;static MockPanda *g_panda{nullptr};staticint (*libc_open)(constchar*,int, ...);structPandaTest : testing::Test { testing::GotHook *got_hook{nullptr};virtualvoidSetUp() { g_test_mutex.lock();// not thread safe g_panda =newMockPanda();ASSERT_NO_FATAL_FAILURE({ got_hook =newtesting::GotHook(); got_hook->MockFunction("open", (void*)&Open, (void**)&libc_open); });ON_CALL(*g_panda,Open(_, _)).WillByDefault(Invoke(libc_open));// ... }virtualvoidTearDown() {delete got_hook;delete g_panda; g_test_mutex.unlock(); }staticintOpen(constchar *pathname,int flags, ...) {if (strcmp(prod_file, pathname) ==0) {return g_panda->Open(test_file, flags); }else {if (flags & O_CREAT) {va_list arg;va_start(arg, flags);mode_t mode =va_arg(arg,mode_t);va_end(arg);returnlibc_open(pathname, flags, mode); }else {returnlibc_open(pathname, flags); } } }};TEST_F(PandaTest, OpenTestFile) {// ...EXPECT_CALL(*g_panda,Open(test_file, O_RDONLY));// ... g_panda->OpenFile();// ...}
For now support Linux64-bit only. If you need a32-bit version, contact melonnywang@qq.com.
- C++11 or newer
- Google Test
- Google Mock