Files
cproof-context/testing/stubs.md
jabber.developer2 22977846a3 docs: split context into layered, agent-oriented files
Replace the single file-structure.md with a stratified layout designed
for AI/agent skill consumption: tables and concrete identifiers over
prose, files loaded on demand, content separated by churn rate.

Layers:
- architecture/  stable structural reference (overview, source-map,
                 test-map, data-flow)
- patterns/      memory, commands, autocomplete, events, xmpp,
                 encryption, ui, plugins
- testing/       unit-tests, stubs, functional-tests, bench
- build/         local, docker, ci
- playbooks/     add-command, add-test, add-autocomplete,
                 add-event-handler, add-encryption
- gotchas.md     append-only dated entries (seven seed entries)
- wip/           branch-specific notes; deleted on merge to master

Stable layers describe cproof on master only. In-flight feature
branches (currently feat/ai) get a single file under wip/.

INDEX.md is the entry map with churn labels; SKILL.md is the
always-loaded skill hint pointing to it.
2026-04-30 20:52:06 +03:00

3.1 KiB

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/<module>/.

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_<module>.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.

void
chatlog_msg_in(...)
{
    // no-op
}

will_return-driven

The stub pops a value queued by the test:

jabber_conn_status_t
connection_get_status(void)
{
    return (jabber_conn_status_t)mock();
}

Test side:

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:

void
cons_bad_cmd_usage(const char* const cmd)
{
    check_expected(cmd);
}

Test side:

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.ctests/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/<module>/ 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.