Testing

Real I/O is a poor foundation for unit tests. Network operations are slow, non-deterministic, and do not fail on demand — so error-handling paths go untested until production breaks them. Capy replaces the transport with in-memory mocks. Because each mock satisfies the same concept as its production counterpart, test code reads the same as production code. The only difference is the type of the stream you pass in.

What This Section Covers

  • Driving Tests — run_blocking drives a coroutine to completion on the calling thread without a real executor. fuse runs the test body repeatedly, injecting an error at each maybe_fail() site in turn until every failure path is covered. The thread_name header’s set_current_thread_name function labels worker threads so that failures in multi-threaded tests are easier to attribute.

  • Mock Streams — read_stream, write_stream, and stream (a connected pair) implement the partial-I/O concepts from Streams. Use them to test protocol logic that calls read_some and write_some without touching a socket.

  • Buffer Inspection — bufgrind iterates every split point of a buffer sequence, exercising every chunk-boundary condition; buffer_to_string concatenates buffer sequences into a std::string for easy assertion.

How the Pieces Fit

A typical test constructs one or more mocks, arms a fuse, and hands the mocks to the code under test inside a run_blocking call. The fuse repeats the test body automatically in two full sweeps — error-code mode, then exception mode. Buffer utilities such as bufgrind and buffer_to_string wrap the mock data for assertions. They let you verify that every split of an input buffer produces the same correct output.