{"id":19512515,"url":"https://github.com/vberlier/narmock","last_synced_at":"2025-10-17T14:12:57.459Z","repository":{"id":35025840,"uuid":"195640034","full_name":"vberlier/narmock","owner":"vberlier","description":"A minimal mocking utility for C projects.","archived":false,"fork":false,"pushed_at":"2023-03-01T03:59:39.000Z","size":341,"stargazers_count":6,"open_issues_count":7,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-17T14:19:31.450Z","etag":null,"topics":["c","mocking","narwhal","tests"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vberlier.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","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},"funding":{"github":["vberlier"]}},"created_at":"2019-07-07T10:51:39.000Z","updated_at":"2023-04-15T10:24:06.000Z","dependencies_parsed_at":"2024-11-10T23:37:00.048Z","dependency_job_id":null,"html_url":"https://github.com/vberlier/narmock","commit_stats":{"total_commits":132,"total_committers":3,"mean_commits":44.0,"dds":0.1515151515151515,"last_synced_commit":"baca1f61c2683c9ed7831c312e34a67c8856665a"},"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vberlier%2Fnarmock","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vberlier%2Fnarmock/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vberlier%2Fnarmock/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vberlier%2Fnarmock/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vberlier","download_url":"https://codeload.github.com/vberlier/narmock/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250931025,"owners_count":21509802,"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":["c","mocking","narwhal","tests"],"created_at":"2024-11-10T23:26:28.545Z","updated_at":"2025-10-17T14:12:52.416Z","avatar_url":"https://github.com/vberlier.png","language":"C","funding_links":["https://github.com/sponsors/vberlier"],"categories":[],"sub_categories":[],"readme":"# 🎣 narmock\n\n[![GitHub Actions](https://github.com/vberlier/narmock/workflows/CI/badge.svg)](https://github.com/vberlier/narmock/actions)\n[![PyPI](https://img.shields.io/pypi/v/narmock.svg)](https://pypi.org/project/narmock/)\n[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/narmock.svg)](https://pypi.org/project/narmock/)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)\n\n\u003e A minimal mocking utility for C projects.\n\nNarmock finds the functions mocked in your tests and generates mocks with a slick API.\n\n```c\n#include \u003ctime.h\u003e\n\n#include \"__mocks__.h\"\n#include \"narwhal.h\"\n\nTEST(example)\n{\n    MOCK(time)-\u003emock_return(42);\n\n    ASSERT_EQ(time(NULL), 42);\n}\n```\n\n\u003e This example is a test written with [Narwhal](https://github.com/vberlier/narwhal) but Narmock can be used with other test frameworks and anywhere in regular source code.\n\n## Installation\n\nThe package can be installed with `pip`.\n\n```bash\n$ pip install narmock\n```\n\n## Getting started\n\nThe command-line utility provides two essential commands that should make it possible to integrate Narmock in any kind of build system.\n\n```\nusage: narmock [-h] (-g [\u003ccode\u003e] | -f) [-d \u003cdirectory\u003e] [-k [\u003cregex\u003e]] [-s \u003csize\u003e]\n\nA minimal mocking utility for C projects.\n\noptional arguments:\n  -h, --help      show this help message and exit\n  -g [\u003ccode\u003e]     generate mocks\n  -f              output linker flags\n  -d \u003cdirectory\u003e  mocks directory\n  -k [\u003cregex\u003e]    keep argument names\n  -s \u003csize\u003e       stack size used to forward variadic arguments\n```\n\n\u003e Check out the [basic example](https://github.com/vberlier/narmock/tree/master/examples/basic) for a simple Makefile that integrates both [Narwhal](https://github.com/vberlier/narwhal) and Narmock.\n\n### Generating mocks\n\nThe `narmock -g` command finds the functions mocked in your code and generates a `__mocks__.c` file and a `__mocks__.h` file that respectively define and declare all the required mocks.\n\n```bash\n$ gcc -E *.c | narmock -g\n```\n\nNarmock requires source code to be expanded by the preprocessor. You can directly pipe the output of `gcc -E` to the command-line utility.\n\nBy default, `__mocks__.c` and `__mocks__.h` will be created in the current directory. You can specify a different output directory with the `-d` option.\n\n```bash\n$ gcc -E tests/*.c | narmock -g -d tests\n```\n\n### Retrieving linker flags\n\nThe `narmock -f` command reads the generated `__mocks__.h` file and outputs the necessary linker flags for linking all your source files together.\n\n```bash\n$ gcc $(narmock -f) *.c\n```\n\nBy default, the command looks for `__mocks__.h` in the current directory. You can specify a different directory with the `-d` option.\n\n```bash\n$ gcc $(narmock -f -d tests) tests/*.c\n```\n\n## Mock API\n\nThe `MOCK` macro returns a pointer to the mock API of a given function.\n\n```c\nMOCK(time);\n```\n\n### Mocking the returned value\n\nYou can make a function return a specific value without calling its original implementation.\n\n```c\nMOCK(time)-\u003emock_return(42);\n\nprintf(\"%ld\\n\", time(NULL));  // Outputs 42\n```\n\n### Mocking the implementation\n\nYou can switch the implementation of a function.\n\n```c\ntime_t time_stub(time_t *timer)\n{\n    return 42;\n}\n\nMOCK(time)-\u003emock_implementation(time_stub);\n\nprintf(\"%ld\\n\", time(NULL));  // Outputs 42\n```\n\n### Mocking errno\n\nYou can make a function set `errno` to a specific value.\n\n```c\nMOCK(malloc)-\u003emock_return(NULL)-\u003emock_errno(ENOMEM);\n\nchar *ptr = malloc(42);\n\nprintf(\"%d\\n\", errno == ENOMEM);  // Outputs 1\n```\n\n### Disabling the mock\n\nYou can disable the mock and make the function call its original implementation.\n\n```c\nMOCK(time)-\u003edisable_mock();\n\nprintf(\"%ld\\n\", time(NULL));  // Outputs the current time\n```\n\n### Counting and inspecting calls\n\nNarmock keeps track of the number of times mocked functions are called.\n\n```c\nprintf(\"%ld\\n\", time(NULL));  // Outputs the current time\n\nprintf(\"%ld\\n\", MOCK(time)-\u003ecall_count);  // Outputs 1\n```\n\nYou can also inspect the last call of a function. Note that the `last_call` pointer is `NULL` until the function gets called for the first time.\n\n```c\nprintf(\"%ld\\n\", time(NULL));  // Outputs the current time\n\nprintf(\"%p\\n\", MOCK(time)-\u003elast_call-\u003earg1);           // Outputs (nil)\nprintf(\"%ld\\n\", MOCK(time)-\u003elast_call-\u003ereturn_value);  // Outputs the current time\n```\n\nThe value of `errno` is captured and saved in the `errsv` attribute.\n\n```c\nfopen(\"does_not_exist.txt\", \"r\");\n\nprintf(\"%d\\n\", MOCK(fopen)-\u003elast_call-\u003eerrsv == ENOENT);  // Outputs 1\n```\n\nBy default, the arguments are accessible through the sequential `arg1`, `arg2`, `...`, `argN` attributes. If you want to keep the original name of the arguments for a set of specific functions you can use the `-k` option when generating the mocks.\n\n```bash\n$ gcc -E *.c | narmock -g -k \"myprefix_.*\"\n```\n\nThe option takes a regular expression and generates mocks that use the original argument names for all the functions that match the regex.\n\n```bash\n$ gcc -E *.c | narmock -g -k\n```\n\nNote that the default regex is `.*` so here every function would be affected.\n\n### Variadic functions\n\nNarmock can mock functions with variadic arguments. The generated code uses the GNU extension for [constructing function calls](https://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Constructing-Calls.html) to forward the arguments. If GNU extensions are unavailable the mock will simply ignore the variadic arguments and only forward the fixed arguments.\n\n```c\nMOCK(open)-\u003emock_return(1);\n\nASSERT_EQ(open(\"a\", 0), 1);\n```\n\n\u003e `open()` is variadic because of the optional `mode` argument.\n\nThe functions provided by the GNU extension need to reserve some fixed space on the stack. By default, Narmock uses 512 bytes but you can specify a custom size by using the `-s` command-line argument when generating the mocks.\n\n```bash\n$ gcc -E *.c | narmock -g -s 1024\n```\n\n### Resetting everything\n\nYou can reset the mock to its initial state. This will make the function use its original implementation and reset `call_count` to `0` and `last_call` to `NULL`.\n\n```c\nMOCK(time)-\u003emock_return(42);\n\nprintf(\"%ld\\n\", time(NULL));  // Outputs 42\n\nMOCK(time)-\u003ereset();\n\nprintf(\"%ld\\n\", MOCK(time)-\u003ecall_count);  // Outputs 0\nprintf(\"%p\\n\", MOCK(time)-\u003elast_call);    // Outputs (nil)\nprintf(\"%ld\\n\", time(NULL));              // Outputs the current time\n```\n\nYou can also call the `narmock_reset_all_mocks` function to reset all the mock.\n\n```c\nnarmock_reset_all_mocks();\n```\n\n## Contributing\n\nContributions are welcome. Feel free to open issues and suggest improvements. This project uses [poetry](https://poetry.eustace.io/) so you'll need to install it first if you want to be able to work with the project locally.\n\n```bash\n$ curl -sSL https://raw.githubusercontent.com/sdispater/poetry/master/get-poetry.py | python\n```\n\nYou should now be able to install the required dependencies.\n\n```bash\n$ poetry install\n```\n\nThe code follows the [black](https://github.com/ambv/black) code style.\n\n```bash\n$ poetry run black narmock\n```\n\nYou can run the tests with `poetry run make -C tests`. The test suite is built with [Narwhal](https://github.com/vberlier/narwhal).\n\n```bash\n$ poetry run make -C tests\n```\n\n---\n\nLicense - [MIT](https://github.com/vberlier/narmock/blob/master/LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvberlier%2Fnarmock","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvberlier%2Fnarmock","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvberlier%2Fnarmock/lists"}