{"id":17982261,"url":"https://github.com/lonnywong/glibcmock","last_synced_at":"2025-03-25T19:30:56.820Z","repository":{"id":112097318,"uuid":"84514507","full_name":"lonnywong/glibcmock","owner":"lonnywong","description":"A solution of mocking glibc function with Google Test.","archived":false,"fork":false,"pushed_at":"2017-03-14T12:28:27.000Z","size":398,"stargazers_count":20,"open_issues_count":1,"forks_count":8,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-20T17:23:06.518Z","etag":null,"topics":["glibc","gmock","got","gtest","hook","libc","mock","plt","syscall","test","unittest"],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lonnywong.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-03-10T03:18:11.000Z","updated_at":"2024-05-19T20:45:31.000Z","dependencies_parsed_at":"2023-05-03T07:46:15.954Z","dependency_job_id":null,"html_url":"https://github.com/lonnywong/glibcmock","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lonnywong%2Fglibcmock","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lonnywong%2Fglibcmock/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lonnywong%2Fglibcmock/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lonnywong%2Fglibcmock/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lonnywong","download_url":"https://codeload.github.com/lonnywong/glibcmock/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245530076,"owners_count":20630493,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["glibc","gmock","got","gtest","hook","libc","mock","plt","syscall","test","unittest"],"created_at":"2024-10-29T18:13:34.704Z","updated_at":"2025-03-25T19:30:56.814Z","avatar_url":"https://github.com/lonnywong.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# glibc mock\n\n[![Build Status](https://travis-ci.org/lonnywang/glibcmock.svg?branch=master)](https://travis-ci.org/lonnywang/glibcmock)\n[![Coverage Status](https://coveralls.io/repos/github/lonnywang/glibcmock/badge.svg?branch=master)](https://coveralls.io/github/lonnywang/glibcmock?branch=master)\n[![Coverage Status](https://img.shields.io/codecov/c/github/lonnywang/glibcmock/master.svg)](https://codecov.io/gh/lonnywang/glibcmock)\n[![Code Health](https://landscape.io/github/lonnywang/glibcmock/master/landscape.svg?style=flat)](https://landscape.io/github/lonnywang/glibcmock/master)\n[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](../master/LICENSE)\n  \nWelcome to **glibc mock**, a solution of mocking glibc function (open, read, write … etc.) with [Google Test](https://github.com/google/googletest) and [Google Mock](https://github.com/google/googletest/blob/master/googlemock/README.md)!  \n  \n*Mock glibc function by changing GOT value to custom static function address.*  \n  \nAs we know, glibc function address is store in GOT (Global Offset Table).  \nChange the GOT value to a custom static function address, then the glibc call will call the custom static function actually.  \nIn the custom static function, we make it to call a Google Mock method, then we have mocked the glibc function.\n\n## Usage\n1. Copy `got_hook.h` and `got_hook.cc` to your C++ test project.\n2. Add `#include \"got_hook.h\"` to your test source code.\n\n## Sample 1\n```c++  \nstruct MockMalloc {\n    MOCK_METHOD1(Malloc, void *(size_t));\n};\n\nstatic MockMalloc *g_mock{nullptr};\n\nstatic void *Malloc(size_t size) {\n    return g_mock-\u003eMalloc(size);\n}\n\nstatic std::mutex g_test_mutex;\n\nTEST(MallocTest, ReturnNull) {\n    std::lock_guard\u003cstd::mutex\u003e lock(g_test_mutex); // not thread safe\n    std::unique_ptr\u003cMockMalloc\u003e mock(g_mock = new MockMalloc());\n    testing::GotHook got_hook;\n    ASSERT_NO_FATAL_FAILURE(got_hook.MockFunction(\"malloc\", (void*)\u0026Malloc));\n    // ... do your test here, for example:\n    EXPECT_CALL(*g_mock, Malloc(testing::_)).WillOnce(testing::Return(nullptr));\n    EXPECT_EQ(nullptr, malloc(1));\n}\n```\n\n## Sample 2\n\n```c++  \nconstexpr key_t shm_key = 0x123;\n\nstruct Turtle {\n    void UseSharedMemory() {\n        auto shm_id = shmget(shm_key, 0, 0);\n        auto buffer = shmat(shm_id, nullptr, 0);\n        EXPECT_STREQ(\"a fake shm buffer\", (char*)buffer);\n        // ...\n        shmdt(buffer);\n    }\n};\n\nstruct MockTurtle : Turtle {\n    MOCK_METHOD3(shmget, int(key_t, size_t, int));\n    MOCK_METHOD3(shmat, void*(int, const void*, int));\n    MOCK_METHOD1(shmdt, int(const void*));\n};\n\nstatic MockTurtle *g_turtle{nullptr};\n\nstatic int my_shmget(key_t key, size_t size, int shmflg) {\n    return g_turtle-\u003eshmget(key, size, shmflg);\n}\n\nstatic void *my_shmat(int shmid, const void *shmaddr, int shmflg) {\n    return g_turtle-\u003eshmat(shmid, shmaddr, shmflg);\n}\n\nstatic int my_shmdt(const void *shmaddr) {\n    return g_turtle-\u003eshmdt(shmaddr);\n}\n\nstatic std::mutex g_test_mutex;\n\nTEST(TurtleTest, FakeSharedMemory) {\n    std::lock_guard\u003cstd::mutex\u003e lock(g_test_mutex); // not thread safe\n    std::unique_ptr\u003cMockTurtle\u003e turtle(g_turtle = new MockTurtle());\n    testing::GotHook got_hook;\n    ASSERT_NO_FATAL_FAILURE({\n        got_hook.MockFunction(\"shmget\", (void*)\u0026my_shmget);\n        got_hook.MockFunction(\"shmat\", (void*)\u0026my_shmat);\n        got_hook.MockFunction(\"shmdt\", (void*)\u0026my_shmdt);\n    });\n    constexpr int shm_id = 100;\n    char fake_shm_buffer[2000]{\"a fake shm buffer\"};\n    // ...\n    EXPECT_CALL(*g_turtle, shmget(shm_key, _, _)).WillOnce(Return(shm_id));\n    EXPECT_CALL(*g_turtle, shmat(shm_id, _, _)).WillOnce(Return(fake_shm_buffer));\n    EXPECT_CALL(*g_turtle, shmdt(fake_shm_buffer)).WillOnce(Return(0));\n    // ...\n    g_turtle-\u003eUseSharedMemory();\n    // ...\n}\n```  \n\n## Sample 3\n```c++  \nconstexpr const char *prod_file = \"/usr/local/xxx\";\nconstexpr const char *test_file = \"/tmp/xxx\";\n\nstruct Panda {\n    void OpenFile() {\n        auto fd = open(prod_file, O_RDONLY);\n        // ...\n        close(fd);\n    }\n};\n\nstruct MockPanda : Panda {\n    MOCK_METHOD2(Open, int(const char*, int));\n};\n\nstatic std::mutex g_test_mutex;\n\nstatic MockPanda *g_panda{nullptr};\n\nstatic int (*libc_open)(const char*, int, ...);\n\nstruct PandaTest : testing::Test {\n    testing::GotHook *got_hook{nullptr};\n\n    virtual void SetUp() {\n        g_test_mutex.lock(); // not thread safe\n        g_panda = new MockPanda();\n        ASSERT_NO_FATAL_FAILURE({\n            got_hook = new testing::GotHook();\n            got_hook-\u003eMockFunction(\"open\", (void*)\u0026Open, (void**)\u0026libc_open);\n        });\n        ON_CALL(*g_panda, Open(_, _)).WillByDefault(Invoke(libc_open));\n        // ...\n    }\n\n    virtual void TearDown() {\n        delete got_hook;\n        delete g_panda;\n        g_test_mutex.unlock();\n    }\n\n    static int Open(const char *pathname, int flags, ...) {\n        if (strcmp(prod_file, pathname) == 0) {\n            return g_panda-\u003eOpen(test_file, flags);\n        } else {\n            if (flags \u0026 O_CREAT) {\n                va_list arg;\n                va_start(arg, flags);\n                mode_t mode = va_arg(arg, mode_t);\n                va_end(arg);\n                return libc_open(pathname, flags, mode);\n            } else {\n                return libc_open(pathname, flags);\n            }\n        }\n    }\n};\n\nTEST_F(PandaTest, OpenTestFile) {\n    // ...\n    EXPECT_CALL(*g_panda, Open(test_file, O_RDONLY));\n    // ...\n    g_panda-\u003eOpenFile();\n    // ...\n}\n```  \n\n# Requirements\nFor now support Linux **64-bit** only. If you need a **32-bit** version, contact me [lonnywang@qq.com](mailto:lonnywang@qq.com).\n  * C++11 or newer\n  * Google Test\n  * Google Mock\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flonnywong%2Fglibcmock","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flonnywong%2Fglibcmock","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flonnywong%2Fglibcmock/lists"}