# Stubs Unit tests link against the unit-under-test plus a parallel set of "stub" implementations of every dependency. Stubs are organised by module under `tests/unittests//`. ## Layout | Stub directory | Replaces | |---|---| | `tests/unittests/chatlog/` | `src/chatlog.c` | | `tests/unittests/command/` | parts of `src/command/` | | `tests/unittests/config/` | `src/config/` (accounts, cafile, ...) | | `tests/unittests/database/` | `src/database.c` | | `tests/unittests/event/` | `src/event/` | | `tests/unittests/log/` | `src/log.c` | | `tests/unittests/omemo/` | `src/omemo/` | | `tests/unittests/otr/` | `src/otr/` | | `tests/unittests/pgp/` | `src/pgp/` | | `tests/unittests/plugins/` | `src/plugins/` | | `tests/unittests/tools/` | `src/tools/` | | `tests/unittests/ui/` | `src/ui/` | | `tests/unittests/xmpp/` | `src/xmpp/` | | `tests/unittests/unittests/` | top-level utility stubs | Files are named `stub_.c` (sometimes split, e.g. `tests/unittests/config/stub_accounts.c`, `stub_cafile.c`). ## Two stub flavours ### Pass-through default Returns a benign default (NULL, FALSE, 0). Used when the test does not care about the call. ```c void chatlog_msg_in(...) { // no-op } ``` ### `will_return`-driven The stub pops a value queued by the test: ```c jabber_conn_status_t connection_get_status(void) { return (jabber_conn_status_t)mock(); } ``` Test side: ```c will_return(connection_get_status, JABBER_CONNECTED); ``` If the stub is `will_return`-driven, **every test** that exercises a code path through it must queue a value, or cmocka aborts. ### `expect_*`-driven The stub asserts argument values against expectations: ```c void cons_bad_cmd_usage(const char* const cmd) { check_expected(cmd); } ``` Test side: ```c expect_string(cons_bad_cmd_usage, cmd, CMD_ACCOUNT); ``` ## When to add a stub 1. You call a new function from production code, and the call site is reachable from a unit test. 2. `make check` link fails with an undefined-symbol error. Procedure: - Locate the matching stub module by callee path: `src/foo/bar.c` → `tests/unittests/foo/stub_bar.c`. Create the stub file if absent. - Stub the new function with the right flavour: - Pass-through if tests don't need to observe / drive it. - `mock()` if a test needs to inject a return value. - `check_expected()` if a test needs to assert an argument. - Wire the new stub `.c` into the build. See `tests/unittests/Makefile.am` (or whatever wires the stubs into the `unittests` target). ## When to extend an existing stub If a stub already pass-through and a test now needs to drive it, **change the stub to `mock()`**. Then every test (existing and new) reaching that stub must `will_return` — be ready to update unrelated tests. ## Convention notes - Stubs do **not** include real headers from `src//` if doing so would pull in the very symbol they replace. Forward-declare instead. - `tests/unittests/ui/stub_ai.c` is a UI-side stub for the AI client surface consumed by `src/ui/`. - The `tests/unittests/unittests/` directory holds top-level catch-alls that do not fit a single module.