Testing¶
QS-Bridge has 7 test suites with 860+ assertions. Tests cover BSATN serialisation, protocol framing, server message parsing, bridge orchestration, and end-to-end SpacetimeDB interaction.
Test Summary¶
| Suite | File | Tests | Assertions | Focus |
|---|---|---|---|---|
| BSATN Round-Trip | test_table_roundtrip.cpp |
88 | 131 | All 44 table types — default + value round-trips |
| HMAC-SHA256 | test_hmac.cpp |
8 | 8 | RFC 4231 test vectors |
| Mock Adapter | test_mock_adapter.cpp |
17 | 17 | Headless engine adapter lifecycle |
| Protocol Framing | test_protocol_framing.cpp |
26 | 26 | STDB v2 wire format |
| Server Messages | test_server_messages.cpp |
30 | 108 | Server→client message parsing |
| Integration Pipeline | test_integration_pipeline.cpp |
45 | 554 | Full bridge orchestration |
| E2E SpacetimeDB | test_e2e_stdb.cpp |
6 | 16 | Live STDB v2 (CI-safe) |
| Total | 7 files | 220 | 860+ |
Test Framework¶
Tests use Catch2 v3, fetched via CMake FetchContent. No external test dependencies.
# Build and run all tests
cmake -B build -DQSB_BUILD_TESTS=ON
cmake --build build -j$(nproc)
cd build && ctest --output-on-failure
# Run a specific suite
./build/test_table_roundtrip
./build/test_integration_pipeline
# Run with verbose output
./build/test_integration_pipeline -v
# Run a specific test case
./build/test_integration_pipeline "game factory registration"
Suite 1 — BSATN Round-Trip (131 assertions)¶
Tests that every table type can serialise to BSATN and deserialise back identically.
What it tests: - Default-constructed row → write → read → compare (44 tables) - Value-constructed row → write → read → compare (44 tables) - Various field types: String, u32, u64, f32, f64, bool, Timestamp, Option, Vec - Nested types and enums
TEST_CASE("PlayerPosition round-trip") {
PlayerPosition original{};
original.player_id = "Steam:76561198012345678";
original.x = 1234.5f;
original.y = -567.8f;
original.z = 90.0f;
BsatnWriter writer;
original.serialize(writer);
BsatnReader reader(writer.data());
auto deserialized = PlayerPosition::deserialize(reader);
CHECK(deserialized.player_id == original.player_id);
CHECK(deserialized.x == original.x);
CHECK(deserialized.y == original.y);
CHECK(deserialized.z == original.z);
}
Suite 2 — HMAC-SHA256 (8 assertions)¶
Validates the HMAC implementation against RFC 4231 test vectors.
What it tests: - Standard test vectors from RFC 4231 - Empty message - Known key + message → expected HMAC output - Used to verify reducer call signing
Suite 3 — Mock Adapter (17 assertions)¶
Tests the headless engine adapter used for CI testing without a game server.
What it tests:
- Adapter init/shutdown lifecycle
- Mock player add/remove
- Player ID extraction
- get_connected_players() returns correct list
- RPC simulation dispatch
Suite 4 — Protocol Framing (26 assertions)¶
Tests STDB v2 binary protocol message construction and parsing.
What it tests: - Subscribe message serialisation - CallReducer message serialisation with BSATN-encoded arguments - InitialConnection parsing (Identity extraction) - SubscribeApplied parsing - ReducerResult parsing (all 4 outcomes: committed, failed, out-of-energy, timed-out) - Wire format byte order (little-endian) - UTF-8 string encoding in messages
Suite 5 — Server Messages (108 assertions, 30 tests)¶
Comprehensive tests for parsing server-to-client messages.
What it tests:
- InitialConnection — Identity bytes, protocol version
- SubscribeApplied — 2 tables, initial row data, request_id
- TransactionUpdate — inserts and deletes, table_id matching
- ReducerResult — all 4 outcome variants, error messages, timestamps
- SubscriptionError — error string extraction
- Edge cases: empty tables, unicode in strings, large payloads (>64 KB)
- Malformed messages: truncated, wrong tags, zero-length
Suite 6 — Integration Pipeline (554 assertions, 45 tests)¶
The largest test suite. Validates the full bridge orchestration pipeline end-to-end (in-process, no network).
What it tests:
- Game Factory — registration, creation, duplicate rejection, unknown module
- GameInterface — lifecycle callbacks (init, tick, player_join, player_leave)
- RPC Dispatcher — handler registration, dispatch, unknown RPC handling
- StdbConnection — outbound message serialisation, inbound message parsing, callback delivery for SubscribeApplied/TransactionUpdate/ReducerResult
- GameAction Queue — all 5 variant types, enqueue/dequeue, multi-threaded safety (producer + consumer threads), 10K throughput benchmark
- Full Orchestration — replicates
entry.cppinit_thread_func()flow: create adapter → create connection → create game → register hooks → connect → subscribe → handle callbacks - Multi-Instance Isolation — two separate connection + game instances don't interfere
- Edge Cases — null pointers, empty strings, maximum values, rapid connect/disconnect
TEST_CASE("Full orchestration sequence") {
// Replicate the real init_thread_func() flow
MockAdapter adapter;
REQUIRE(adapter.init());
StdbConnection conn("ws://test:3000", "test-module");
HumanitZGame game;
game.on_init(&conn);
game.register_hooks(&adapter);
// Simulate SubscribeApplied
auto msg = build_subscribe_applied(/*...*/);
conn.handle_message(msg);
// Verify game state updated
CHECK(game.is_initialized());
CHECK(adapter.hook_count() > 0);
}
Uses: tests/test_stubs.cpp — linker stubs for UE4 engine symbols (allows testing without game server binary).
Suite 7 — E2E SpacetimeDB (16 assertions)¶
Full real-world test against a live SpacetimeDB v2 instance.
What it tests:
1. WebSocket connection establishment
2. Identity receipt (32-byte InitialConnection)
3. Subscribe to 2 tables
4. Receive SubscribeApplied with initial rows
5. Call "ping" reducer
6. Receive ReducerResult with timestamp
7. Receive incremental TransactionUpdate (delete old + insert new)
CI Safety: Gracefully skips when SpacetimeDB is not running. Not a CI blocker, but validates the complete network path when available.
# Run E2E test (requires running SpacetimeDB)
spacetime start
spacetime publish test-module
./build/test_e2e_stdb
Test Coverage Goals¶
| Component | Current | Target |
|---|---|---|
| BSATN codec | ✅ All types | Maintain 100% |
| Protocol framing | ✅ All messages | Maintain 100% |
| Bridge core | ✅ Full pipeline | Add fuzz testing |
| Engine adapter | ✅ Mock adapter | Add UE4 adapter unit tests |
| Game module | ⚠️ Via integration | Add per-reducer unit tests |
| STDB module (Rust) | ⚠️ types.rs only | Add reducer logic tests |
Related Pages¶
- Build System — CMake config, CI pipeline
- Bridge Internals — what's being tested
- Tech Stack — test framework details