{"id":18913567,"url":"https://github.com/eerimoq/nala","last_synced_at":"2025-08-23T06:03:42.148Z","repository":{"id":45677919,"uuid":"221039536","full_name":"eerimoq/nala","owner":"eerimoq","description":"🦁 Nala - A delightful test framework for C projects.","archived":false,"fork":false,"pushed_at":"2022-07-15T04:13:52.000Z","size":2607,"stargazers_count":67,"open_issues_count":2,"forks_count":4,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-06-29T09:07:33.234Z","etag":null,"topics":["c","mocking","test"],"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/eerimoq.png","metadata":{"files":{"readme":"README.rst","changelog":null,"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},"funding":{"github":"eerimoq"}},"created_at":"2019-11-11T18:00:56.000Z","updated_at":"2025-05-18T11:47:40.000Z","dependencies_parsed_at":"2022-07-26T15:32:29.539Z","dependency_job_id":null,"html_url":"https://github.com/eerimoq/nala","commit_stats":null,"previous_names":[],"tags_count":213,"template":false,"template_full_name":null,"purl":"pkg:github/eerimoq/nala","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eerimoq%2Fnala","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eerimoq%2Fnala/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eerimoq%2Fnala/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eerimoq%2Fnala/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eerimoq","download_url":"https://codeload.github.com/eerimoq/nala/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eerimoq%2Fnala/sbom","scorecard":{"id":367993,"data":{"date":"2025-08-11","repo":{"name":"github.com/eerimoq/nala","commit":"1ed122b5b7401f328be29358394cafedec247827"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.2,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/test.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":0,"reason":"Found 1/29 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":6,"reason":"binaries present in source code","details":["Warn: binary detected: tests/files/wrap_internal_symbols/test.o:1","Warn: binary detected: tests/files/wrap_internal_symbols/test.wrapped.o:1","Warn: binary detected: tests/files/wrap_internal_symbols/test_function_sections.o:1","Warn: binary detected: tests/files/wrap_internal_symbols/test_function_sections.wrapped.o:1"],"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/eerimoq/nala/test.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/eerimoq/nala/test.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:36: update your workflow using https://app.stepsecurity.io/secureworkflow/eerimoq/nala/test.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:38: update your workflow using https://app.stepsecurity.io/secureworkflow/eerimoq/nala/test.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/test.yml:49: update your workflow using https://app.stepsecurity.io/secureworkflow/eerimoq/nala/test.yml/master?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/test.yml:20","Warn: pipCommand not pinned by hash: .github/workflows/test.yml:21","Warn: pipCommand not pinned by hash: .github/workflows/test.yml:43","Info:   0 out of   4 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned","Info:   0 out of   3 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":1,"reason":"9 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: PYSEC-2019-217 / GHSA-462w-v97r-4m45","Warn: Project is vulnerable to: PYSEC-2014-8 / GHSA-8r7q-cvjq-x353","Warn: Project is vulnerable to: GHSA-cpwx-vrp4-4pq7","Warn: Project is vulnerable to: PYSEC-2014-82 / GHSA-fqh9-2qgg-h84h","Warn: Project is vulnerable to: PYSEC-2021-66 / GHSA-g3rq-g295-4j3m","Warn: Project is vulnerable to: GHSA-h5c8-rqwp-cp95","Warn: Project is vulnerable to: GHSA-h75v-3vvj-5mfj","Warn: Project is vulnerable to: PYSEC-2019-220 / GHSA-hj2j-77xm-mc5v","Warn: Project is vulnerable to: GHSA-q2x7-8rv6-6q7h"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 2 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-18T12:19:28.763Z","repository_id":45677919,"created_at":"2025-08-18T12:19:28.763Z","updated_at":"2025-08-18T12:19:28.763Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271745659,"owners_count":24813515,"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","status":"online","status_checked_at":"2025-08-23T02:00:09.327Z","response_time":69,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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","test"],"created_at":"2024-11-08T10:08:16.461Z","updated_at":"2025-08-23T06:03:42.117Z","avatar_url":"https://github.com/eerimoq.png","language":"C","funding_links":["https://github.com/sponsors/eerimoq"],"categories":["Testing","测试"],"sub_categories":["YAML"],"readme":"|buildstatus|_\n|coverage|_\n|codecov|_\n\n🦁 Nala\n=======\n\nA delightful test framework for `C` projects.\n\nBased on `Narwhal`_ and `Narmock`_.\n\nFeatures\n========\n\n- Automatic test discovery\n- Use the same generic assertions everywhere\n- Assertion failures reported as diffs\n- Powerful mocking\n- Easy-to-use output capturing utilities\n- Traceback(s) on failure\n- Works well with errors reported by sanitizers\n- Test isolation with ``fork()``\n- Only run tests matching given pattern\n- Automatic build and run on file change\n- Optional parallel test execution to save time\n- Amalgamated source and header files ready to drop in your project\n- JSON test report\n\nInstallation\n============\n\nIt's recommended to install `Nala` with ``pip``. Only Python 3 is\nsupported.\n\n.. code-block:: bash\n\n   $ pip install nala\n\nAlternatively, if mocking is not needed, you can download the\n`amalgamated`_ header and source files:\n\n- `nala.h`_\n- `nala.c`_\n\nDrop the two files in your project, make sure ``nala.c`` is compiled\nand linked just like the other source files of your test program and\nyou should be good to go.\n\nGetting started\n===============\n\n|tryit|_\n\nUse ``nala init foo`` to create a folder ``foo`` with two test files,\n``test_assertions.c`` and ``test_time.c``. The first uses all\nassertions and captures output, and the second mocks the time\nfunction.\n\n.. code-block:: bash\n\n   $ nala init foo\n   Run 'make -C foo' to build and run all tests!\n\nThe assertions tests looks like this:\n\n.. code-block:: c\n\n   #include \"nala.h\"\n\n   TEST(assertions)\n   {\n       int i;\n       int array[] = { 1, 5, 2 };\n\n       ASSERT_EQ(NULL, NULL);\n       ASSERT_NE(1, 2);\n       ASSERT_LT(1.0, 2.0);\n       ASSERT_LE(1, 1);\n       ASSERT_GT(2L, 1L);\n       ASSERT_GE(1, 1);\n       ASSERT_TRUE(true);\n       ASSERT_FALSE(false);\n       ASSERT_SUBSTRING(\"12345\", \"34\");\n       ASSERT_NOT_SUBSTRING(\"12345\", \"4567\");\n       ASSERT_MEMORY_EQ(\"abcd\", \"abcd\", 5);\n       ASSERT_FILE_EQ(\"test_assertions.c\", \"test_assertions.c\");\n       ASSERT_ARRAY_EQ(array, array, sizeof(array));\n       ASSERT_FUNCTION_POINTER_EQ(assertions, assertions);\n       ASSERT_FUNCTION_POINTER_NE(assertions, NULL);\n       ASSERT(1 == 1);\n\n       CAPTURE_OUTPUT(output, errput) {\n           printf(\"output!\\n\");\n           fprintf(stderr, \"errput!\\n\");\n       }\n\n       ASSERT_EQ(output, \"output!\\n\");\n       ASSERT_EQ(errput, \"errput!\\n\");\n\n       for (i = 0; i \u003c 3; i++) {\n           WITH_MESSAGE(\"i: %d\", i) {\n               ASSERT_EQ(array[i], array[i]);\n           }\n       }\n   }\n\nAnd the time tests:\n\n.. code-block:: c\n\n   #include \u003ctime.h\u003e\n   #include \"nala.h\"\n\n   TEST(mock_time)\n   {\n       time_mock_once(42);\n\n       ASSERT_EQ(time(NULL), 42);\n   }\n\nBuild and run all tests with ``make -s -C foo``.\n\n.. image:: https://github.com/eerimoq/nala/raw/master/docs/build-and-run.png\n\nBuild all tests but only run those whose name contains ``time``. This\nis done by giving ``ARGS=time``.\n\n.. image:: https://github.com/eerimoq/nala/raw/master/docs/build-and-run-one-test.png\n\nRun ``make -s -C foo auto`` to build and run all tests automatically\nwhen any source file in your project is modified. With the command\nrunning, make the time test fail by returning ``41`` instead of ``42``\nfrom the time mock.\n\n.. code-block:: c\n\n   #include \u003ctime.h\u003e\n   #include \"nala.h\"\n\n   TEST(mock_time)\n   {\n       time_mock_once(41);\n\n       ASSERT_EQ(time(NULL), 42);\n   }\n\nNotice how the test is built and run automatically.\n\n.. image:: https://github.com/eerimoq/nala/raw/master/docs/build-and-run-assert-eq-fail.png\n\nCreate a code coverage report and open it with Firefox.\n\n.. code-block::\n\n   $ make -s -C foo coverage\n   Code coverage report: /home/erik/workspace/nala/foo/build/coverage/index.html\n   $ firefox /home/erik/workspace/nala/foo/build/coverage/index.html\n\nAPI\n===\n\nBelow is a list of all macros and functions in the API. They are all\ndefined/declared in `include/nala.h`_.\n\nAssertions\n----------\n\n.. code-block:: c\n\n   ASSERT_EQ(actual, expected);                  // Assert that given characters, numbers, pointers or\n                                                 // strings are equal.\n   ASSERT_NE(actual, expected);                  // Assert that given characters, numbers, pointers or\n                                                 // strings are not equal.\n   ASSERT_LT(actual, expected);                  // Assert that actual is less than expected.\n   ASSERT_LE(actual, expected);                  // Assert that actual is less than or equal to expected.\n   ASSERT_GT(actual, expected);                  // Assert that actual is greater than expected.\n   ASSERT_GE(actual, expected);                  // Assert that actual is greater than or equal to\n                                                 // expected.\n   ASSERT_TRUE(actual);                          // Assert that given value is true.\n   ASSERT_FALSE(actual);                         // Assert that given value is false.\n   ASSERT_SUBSTRING(haystack, needle);           // Assert that given haystack string contains given\n                                                 // needle string.\n   ASSERT_NOT_SUBSTRING(haystack, needle);       // Assert that given haystack string does not contain\n                                                 // given needle string.\n   ASSERT_MEMORY_EQ(actual, expected, size);     // Assert that given memory regions are equal.\n   ASSERT_FILE_EQ(actual, expected);             // Assert that given files are equal.\n   ASSERT_ARRAY_EQ(actual, expected, size);      // Assert that given arrays are equal.\n   ASSERT_FUNCTION_POINTER_EQ(actual, expected); // Assert that given function pointers are equal.\n   ASSERT_FUNCTION_POINTER_NE(actual, expected); // Assert that given function pointers are not equal.\n   ASSERT(cond);                                 // Assert that given condition is true.\n\nOther macros\n------------\n\n.. code-block:: c\n\n   FAIL(message);                                // Fail current test with given message.\n   CAPTURE_OUTPUT(stdout_name, stderr_name);     // A capture output block.\n   WITH_MESSAGE(format, ...);                    // Additional message on error block. May be nested.\n\nFunctions\n---------\n\n.. code-block:: c\n\n   void *nala_alloc(size_t size);                // Allocate a memory buffer of given size that is\n                                                 // automatically freed after the test. Always returns\n                                                 // a valid pointer.\n   void nala_auto_free(void *buf_p);             // Automatically free given buffer after the test.\n                                                 // free() is called to free the buffer.\n   void nala_exit(int status);                   // Performs post-test checks and cleanup, and then\n                                                 // exits with status 0. The status parameter is\n                                                 // ignored.\n\nMocking\n=======\n\nGenerating mocks\n----------------\n\nThe ``nala generate_mocks`` command finds mocked functions in your\ntest code and generates ``nala_mocks.h``, ``nala_mocks.c`` and\n``nala_mocks.ldflags``. The first two files declare and define mocks,\nwhile the last file contains linker flags.\n\nUse ``--rename-parameters-file`` to rename function parameters, often\nuseful when mocking standard library functions. If not given, Nala\nrenames `a few function parameters`_ by default. Also, any\n``__``-prefix is removed from all parameters.\n\nUse ``--no-rename-parameters`` not to rename any function\nparameters. Overrides ``--rename-parameters-file``.\n\nUse ``--no-implementation`` when the implementation of functions\nmatching given Unix shell-style wildcards pattern are not available in\nthe binary (and therefore should not be called by the generated code,\nas the linker would give a relocation error). This option may be given\nmultipe times. An alternative to using this option is to manually\nimplement the missing functions. Here is an example implementation of\n``foo()`` that makes the test fail if called.\n\n.. code-block:: c\n\n   int foo()\n   {\n       FAIL(\"No real implementation available!\\n\");\n\n       return (0);\n   }\n\nUse ``--no-real-variadic-functions`` not to add any real variadic\nfunctions. Nala adds `a few variadic functions`_ by default, given\nthat they are mocked.\n\nHere is an example of how to generate mocks:\n\n.. code-block:: bash\n\n   $ nala cat *.c | gcc -DNALA_GENERATE_MOCKS -x c -E - | nala generate_mocks\n\n``nala cat *.c`` should only concatenate test source files, not any\nother source files in your project.\n\nNala requires test source code to be expanded by the preprocessor. You\ncan directly pipe the output of ``gcc -DNALA_GENERATE_MOCKS -x c -E\n-`` to the command-line utility.\n\nMocking object-internal function calls\n--------------------------------------\n\nThe GNU linker ``ld`` wrap feature (``--wrap=\u003csymbol\u003e``) does not wrap\nobject-internal function calls. As Nala implements mocking by wrapping\nfunctions, object-internal function calls can't be mocked just using\nthe linker. To mock these, after compilation, run ``nala\nwrap_internal_symbols ...`` for each object file, and then pass them\nto the linker.\n\nAlso, local (``static``) functions can't be mocked, only global\nfunctions can!\n\n.. code-block:: Makefile\n\n   %.o: %.c\n           $(CC) -o $@ $\u003c\n           nala wrap_internal_symbols nala_mocks.ldflags $@\n\nMock API\n--------\n\nA function mock will call the real implementation by default. Use the\nfunctions below to control mock object behaviour.\n\nVariadic functions will *not* call the real implementation by\ndefault. Give ``--implementation`` to ``nala generate_mocks`` to\ngenerate calls to the real function (taking a ``va_list`` instead of\n``...``).\n\nThere are plenty of mock-examples in the `examples folder`_. All\ninline examples below can also be found in the `mock_api_examples`_\nexample.\n\nFor all functions\n^^^^^^^^^^^^^^^^^\n\n``\u003cparams\u003e`` is all char-pointer (string) and primitive type\nparameters of the mocked function.\n\nSame behaviour for every call.\n\n.. code-block:: c\n\n   void FUNC_mock(\u003cparams\u003e, \u003cres\u003e);     // check parameters and return\n   void FUNC_mock_ignore_in(\u003cres\u003e);     // ignore parameters and return\n   void FUNC_mock_none();               // no calls allowed\n   void FUNC_mock_implementation(*);    // replace implementation\n   void FUNC_mock_real();               // real implementation\n\nAn example:\n\n.. code-block:: c\n\n   /* int foo(int value); */\n\n   TEST(foo_every_call)\n   {\n       foo_mock(1, 2);\n\n       /* All calls to foo() expects its parameter to be 1 and returns 2. */\n       ASSERT_EQ(foo(1), 2);\n       ASSERT_EQ(foo(1), 2);\n   }\n\nPer call control.\n\n.. code-block:: c\n\n   int FUNC_mock_once(\u003cparams\u003e, \u003cres\u003e); // check parameters and return once (per call)\n                                        // returns a mock instance handle\n   int FUNC_mock_ignore_in_once(\u003cres\u003e); // ignore parameters and return once (per call)\n                                        // returns a mock instance handle\n   void FUNC_mock_real_once();          // real implementation once (per call)\n\nAn example:\n\n.. code-block:: c\n\n   /* int foo(int value); */\n\n   TEST(foo_per_call)\n   {\n       foo_mock_once(1, 2);\n       foo_mock_once(4, 5);\n\n       /* First call to foo() expects its parameter to be 1 and returns 2. */\n       ASSERT_EQ(foo(1), 2);\n\n       /* Second call to foo() expects its parameter to be 4 and returns 5. */\n       ASSERT_EQ(foo(4), 5);\n\n       /* Third call will fail and the test will end. */\n       foo(10);\n   }\n\nChanges the behaviour of currect mock object (most recent ``*_mock()``\nor ``*_mock_once()`` call). Works for both per call and every call\nfunctions above.\n\n.. code-block:: c\n\n   void FUNC_mock_set_errno(int);       // errno on return, 0 by default\n   void FUNC_mock_set_callback(*);      // additional checks and/or actions\n                                        // called just before returning from the mock\n\nAn example:\n\n.. code-block:: c\n\n   /* int foo(int value); */\n\n   TEST(foo_set_errno)\n   {\n       foo_mock_once(1, 2);\n       foo_mock_set_errno(EINVAL);\n\n       ASSERT_EQ(foo(1), 2);\n       ASSERT_EQ(errno, EINVAL);\n   }\n\nGet per call input parameters.\n\n.. code-block:: c\n\n   *FUNC_mock_get_params_in(int);       // get input parameters for given mock instance\n                                        // handle\n\nAn example:\n\n.. code-block:: c\n\n   /* typedef void (*callback_t)(void); */\n   /* void bar(callback_t callback); */\n\n   static void fie(void)\n   {\n       printf(\"fie() called!\\n\");\n   }\n\n   TEST(bar_get_params_call_callback)\n   {\n       int handle;\n\n       handle = bar_mock_once();\n\n       bar(fie);\n\n       /* Call the callback (calls fie()). */\n       bar_mock_get_params_in(handle)-\u003ecallback();\n   }\n\nFor pointer and array function parameters\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nChanges the behaviour of currect mock (most recent ``*_mock()`` or\n``*_mock_once()`` call). Works for both per call and every call\nfunctions above.\n\n.. code-block:: c\n\n   void FUNC_mock_set_PARAM_in(*, size_t);  // check on input\n   void FUNC_mock_set_PARAM_in_assert(*);   // custom assert function on input\n   void FUNC_mock_set_PARAM_in_pointer(*);  // check pointer (the address) on input\n   void FUNC_mock_set_PARAM_out(*, size_t); // value on return\n   void FUNC_mock_set_PARAM_out_copy(*);    // custom output copy function\n\nAn example:\n\n.. code-block:: c\n\n   /* struct foo_t { char *string_p }; */\n\n   /* void fum(int *value_p, struct foo_t *foo_p); */\n\n   static void assert_foo_string(struct foo_t *actual_p,\n                                 struct foo_t *expected_p,\n                                 size_t size)\n   {\n       ASSERT_EQ(size, sizeof(*expected_p));\n       ASSERT_EQ(actual_p-\u003estring_p, expected_p-\u003estring_p);\n   }\n\n   TEST(fum_in_out)\n   {\n       int value;\n       struct foo_t foo;\n\n       fum_mock_once();\n\n       /* Expect *value_p to be 1 when fum() is called, and assign 2 to\n          it before returning. */\n       value = 1;\n       fum_mock_set_value_p_in(\u0026value, sizeof(value));\n       value = 2;\n       fum_mock_set_value_p_out(\u0026value, sizeof(value));\n\n       /* Use a custom parameter assert function to check that\n          foo_p-\u003estring_p is \"Hello!\"  when fum() is called. */\n       foo.string_p = \"Hello!\";\n       fum_mock_set_foo_p_in(\u0026foo, sizeof(foo));\n       fum_mock_set_foo_p_in_assert(assert_foo_string);\n\n       value = 1;\n       foo.string_p = \"Hello!\";\n       fum(\u0026value, \u0026foo);\n       ASSERT_EQ(value, 2);\n   }\n\nFor function parameters part of \u003cparams\u003e\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nChanges the behaviour of currect mock object (most recent ``*_mock()``\nor ``*_mock_once()`` call). Works for both per call and every call\nfunctions above.\n\n.. code-block:: c\n\n   void FUNC_mock_ignore_PARAM_in();        // ignore on input\n\nAn example:\n\n.. code-block:: c\n\n   /* void foo(int value); */\n\n   TEST(foo_ignore_value)\n   {\n       foo_mock_once(1, 2);\n       foo_mock_ignore_value_in();\n\n       ASSERT_EQ(foo(9), 2);\n   }\n\nFor variadic functions\n^^^^^^^^^^^^^^^^^^^^^^\n\nVariadic function mocks are slightly different from the above. Their\nparameter list is extended with a format string (``format``) and an\nellipsis (``...``), as shown below.\n\n.. code-block:: c\n\n   void FUNC_mock(\u003cparams\u003e, \u003cres\u003e, format, ...);\n   void FUNC_mock_once(\u003cparams\u003e, \u003cres\u003e, format, ...);\n   void FUNC_mock_ignore_in(\u003cres\u003e, format);\n   void FUNC_mock_ignore_in_once(\u003cres\u003e, format);\n\nThe format string supports the following specifiers.\n\n.. code-block::\n\n   %d  - signed integer\n   %u  - unsigned integer\n   %ld - signed long integer\n   %lu - unsigned long integer\n   %p  - pointer address\n   %s  - string\n\nThe ``%p`` specifier takes no value when calling the mock function,\njust like pointers are not part of the mock function parameters\nlist. Instead, set pointers after the mock call.\n\n.. code-block:: c\n\n   foo_mock(3, \"%d%p%s\", 5, \"the-string\");\n   foo_mock_set_va_arg_in_pointer_at(1, NULL);\n\nThe variadic parameters are controlled by index instead of name.\n\n.. code-block:: c\n\n   void FUNC_mock_ignore_va_arg_in_at(uint);          // ignore on input\n   void FUNC_mock_set_va_arg_in_at(uint, *, size_t);  // check on input\n   void FUNC_mock_set_va_arg_in_assert_at(uint, *);   // custom assert function on input\n   void FUNC_mock_set_va_arg_in_pointer_at(uint, *);  // check pointer (the address) on input\n   void FUNC_mock_set_va_arg_out_at(uint, *, size_t); // value on return\n   void FUNC_mock_set_va_arg_out_copy_at(uint, *);    // custom output copy function\n\nLimitations\n-----------\n\n- Structs and unions passed by value are ignored.\n\n- ``va_list`` parameters are ignored.\n\n- ``malloc()`` and ``free()`` can't be mocked if forking and using\n  gcov. They probably can if wrapping ``__gcov_fork()`` in an\n  suspend/resume-block.\n\n- ``static`` functions can't be mocked.\n\n- Only primitive data type members are asserted when comparing\n  structs. Pointer and union members are not asserted, and probably\n  never will be.\n\nDebugging tips\n==============\n\nNala executes each test in its own process. This means that following\nthe execution of a test with a debugger can be a bit tricky because\ndebuggers like `GDB`_ can only follow a single process at a time.\n\nIf you're using `GDB`, set a breakpoint at ``\u003ctest\u003e_before_fork`` and\nthen run the program until it stops at the breakpoint. Before\ncontinuing the program execution, tell `GDB` to follow the forked test\nprocess by setting ``follow-fork-mode`` to ``child``.\n\nBelow are all commands to debug the ``assertions`` test in the example\nabove.\n\n.. code-block::\n\n   $ gdb foo/build/app\n   (gdb) b assertions_before_fork\n   (gdb) r\n   (gdb) set follow-fork-mode child\n   (gdb) c\n\nThe ``gdb`` make target starts `GDB` and runs all commmands listed\nabove. Set the ``TEST`` make variable to the test to debug. Both\n``TEST=test_assertions::assertions`` and ``TEST=assertions`` are\naccepted. The test name may be partialy given, as long as it only\nmatches one test.\n\n.. code-block::\n\n   $ make -s -C foo gdb TEST=assertions\n\nThe test program takes optional arguments as below, which also can be\nhelpful when debugging, especially ``--print-all-calls``.\n\n.. code-block::\n\n   $ foo/build/app --help\n   usage: foo/build/app [-h] [-v] [-c] [-a] [-r] [-f] [-j] [\u003ctest-pattern\u003e]\n\n   Run tests.\n\n   positional arguments:\n     test-pattern                  Only run tests matching given pattern. '^' matches\n                                   the beginning and '$' matches the end of the test\n                                   name.\n\n   optional arguments:\n     -h, --help                    Show this help message and exit.\n     -v, --version                 Print version information.\n     -c, --continue-on-failure     Continue on test failure.\n     -a, --print-all-calls         Print all calls to ease debugging.\n     -r, --report-json-file        JSON test report file (default: report.json).\n     -f, --print-test-file-func    Print file:function for exactly one test.\n     -j, --jobs                    Run given number of tests in parallel\n                                   (default: 1).\n\nCompiler flags\n==============\n\nPass ``-no-pie -g -O0 -fsanitize=address`` to the compiler for better\nerror reporting.\n\nRead more about sanitizers here: https://en.wikipedia.org/wiki/AddressSanitizer\n\nOther unit test frameworks\n==========================\n\nOther C unit test frameworks with similar feature set as Nala.\n\n- `CMock`_ + `Unity`_\n\n- `cmocka`_\n\nIdeas\n=====\n\nNew set of generated parameter functions where ``_in()`` functions are\nrenamed to ``_in_buffer()``. New ``_in()`` functions are added,\nwithout the size parameter. Also remove the size parameter from the\nassert function, as it is seldom used.\n\n.. code-block:: c\n\n   void FUNC_mock_set_PARAM_in(*);                 // check on input\n   void FUNC_mock_set_PARAM_in_buffer(*, size_t);  // check on input\n   void FUNC_mock_set_PARAM_in_assert(*);          // custom assert function on input\n   void FUNC_mock_set_PARAM_in_pointer(*);         // check pointer (the address) on input\n   void FUNC_mock_set_PARAM_out(*);                // value on return\n   void FUNC_mock_set_PARAM_out_buffer(*, size_t); // value on return\n   void FUNC_mock_set_PARAM_out_copy(*);           // custom output copy function\n\nAn example:\n\n.. code-block:: c\n\n   /* struct foo_t { char *string_p }; */\n\n   /* void fum(int *value_p, struct foo_t *foo_p); */\n\n   static void assert_foo_string(struct foo_t *actual_p, struct foo_t *expected_p)\n   {\n       /* Is size is needed (which is seldom is). */\n       ASSERT_EQ(nala_mock_get_param_in_size(), sizeof(*expected_p));\n       ASSERT_EQ(actual_p-\u003estring_p, expected_p-\u003estring_p);\n   }\n\n   TEST(fum_in_out)\n   {\n       int value;\n       struct foo_t foo;\n\n       fum_mock_once();\n\n       /* Expect *value_p to be 1 when fum() is called, and assign 2 to\n          it before returning. */\n       value = 1;\n       fum_mock_set_value_p_in(\u0026value);\n       value = 2;\n       fum_mock_set_value_p_out(\u0026value);\n\n       /* Use a custom parameter assert function to check that\n          foo_p-\u003estring_p is \"Hello!\"  when fum() is called. */\n       foo.string_p = \"Hello!\";\n       fum_mock_set_foo_p_in(\u0026foo);\n       fum_mock_set_foo_p_in_assert(assert_foo_string);\n\n       value = 1;\n       foo.string_p = \"Hello!\";\n       fum(\u0026value, \u0026foo);\n       ASSERT_EQ(value, 2);\n   }\n\n.. |buildstatus| image:: https://travis-ci.org/eerimoq/nala.svg?branch=master\n.. _buildstatus: https://travis-ci.org/eerimoq/nala\n\n.. |coverage| image:: https://coveralls.io/repos/github/eerimoq/nala/badge.svg?branch=master\n.. _coverage: https://coveralls.io/github/eerimoq/nala\n\n.. |codecov| image:: https://codecov.io/gh/eerimoq/nala/branch/master/graph/badge.svg\n.. _codecov: https://codecov.io/gh/eerimoq/nala\n\n.. _Narwhal: https://github.com/vberlier/narwhal\n.. _Narmock: https://github.com/vberlier/narmock\n\n.. |tryit| image:: https://img.shields.io/badge/try-online-f34b7d.svg\n.. _tryit: https://repl.it/@eerimoq/nala\n\n.. _amalgamated: https://sqlite.org/amalgamation.html\n.. _nala.h: https://raw.githubusercontent.com/eerimoq/nala/master/nala/dist/nala.h\n.. _nala.c: https://raw.githubusercontent.com/eerimoq/nala/master/nala/dist/nala.c\n\n.. _a few function parameters: https://github.com/eerimoq/nala/blob/master/nala/rename_parameters.txt\n\n.. _a few variadic functions: https://github.com/eerimoq/nala/blob/master/nala/real_variadic_functions.c\n\n.. _include/nala.h: https://github.com/eerimoq/nala/blob/master/include/nala.h\n\n.. _GDB: https://www.gnu.org/software/gdb/\n\n.. _CMock: https://github.com/ThrowTheSwitch/CMock\n\n.. _Unity: https://github.com/ThrowTheSwitch/Unity\n\n.. _cmocka: https://cmocka.org/\n\n.. _examples folder: https://github.com/eerimoq/nala/tree/master/examples\n\n.. _mock_api_examples: https://github.com/eerimoq/nala/tree/master/examples/mock_api_examples\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feerimoq%2Fnala","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feerimoq%2Fnala","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feerimoq%2Fnala/lists"}