/* P0-15e: Cap'n Proto partial merge semantics * * Verifies that the three persistence Cap'n Proto mapped types * (capnp_persist_cfg_t, capnp_snap_hdr_t, capnp_repl_envelope_t) * and the generated struct PersistConfig / SnapshotHeader / ReplEnvelope * round-trip through their C struct representations correctly. * * These are structural/compile-time + value round-trip tests that span * the Cap'n Proto schema generation (P0-C) and the typemap.h definitions. */ #include #include #include #include #include "config.h" #include "controller.capnp.h" #include "persist.h" /* ------------------------------------------------------------------ */ /* Helpers: persist_config_t → capnp_persist_cfg_t round-trip */ /* ------------------------------------------------------------------ */ /* Manually map persist_config_t fields to capnp_persist_cfg_t, matching the * field mapping in the persist.c checkpoint serialisation path. */ static capnp_persist_cfg_t cfg_to_capnp(const persist_config_t* c) { capnp_persist_cfg_t out; memset(&out, 0, sizeof(out)); out.walSyncMs = c->wal_sync_ms; out.snapIntervalS = c->snap_interval_s; out.snapWalSizeMb = c->snap_wal_size_mb; out.snapKeepN = c->snap_keep_n; out.transientJobTimeoutS = c->transient_job_timeout_s; out.finishedRetainS = c->finished_retain_s; out.workerRetainS = c->worker_retain_s; out.syncTimeoutMs = c->sync_timeout_ms; return out; } /* ------------------------------------------------------------------ */ /* Test 1: persist_config_t → capnp_persist_cfg_t round-trip */ /* ------------------------------------------------------------------ */ static void test_persist_config_capnp_round_trip(void) { persist_config_t src = persist_config_defaults(); /* Override to known values for deterministic checking */ src.wal_sync_ms = 42u; src.snap_interval_s = 120u; src.snap_wal_size_mb = 128u; src.snap_keep_n = 3u; src.transient_job_timeout_s = 600u; src.finished_retain_s = 7200u; src.worker_retain_s = 172800u; src.sync_timeout_ms = 100u; capnp_persist_cfg_t out = cfg_to_capnp(&src); TEST_ASSERT_EQUAL_UINT32(src.wal_sync_ms, out.walSyncMs); TEST_ASSERT_EQUAL_UINT32(src.snap_interval_s, out.snapIntervalS); TEST_ASSERT_EQUAL_UINT32(src.snap_wal_size_mb, out.snapWalSizeMb); TEST_ASSERT_EQUAL_UINT32(src.snap_keep_n, out.snapKeepN); TEST_ASSERT_EQUAL_UINT32(src.transient_job_timeout_s, out.transientJobTimeoutS); TEST_ASSERT_EQUAL_UINT32(src.finished_retain_s, out.finishedRetainS); TEST_ASSERT_EQUAL_UINT32(src.worker_retain_s, out.workerRetainS); TEST_ASSERT_EQUAL_UINT32(src.sync_timeout_ms, out.syncTimeoutMs); printf("test_persist_config_capnp_round_trip: PASS\n"); } /* ------------------------------------------------------------------ */ /* Test 2: SnapshotHeader struct fields and version default */ /* ------------------------------------------------------------------ */ static void test_snapshot_header_capnp_fields(void) { /* Verify struct size constant matches the documented schema */ TEST_ASSERT_EQUAL_INT(48, (int)SnapshotHeader_struct_bytes_count); /* Populate a capnp_snap_hdr_t with known values and check them */ capnp_snap_hdr_t hdr; memset(&hdr, 0, sizeof(hdr)); hdr.lsn = 12345ULL; hdr.term = 2ULL; hdr.timestamp = 999999ULL; hdr.version = 1u; hdr.nJobs = 10u; hdr.nQueues = 3u; hdr.nWorkers = 5u; hdr.checksum = 0xDEADBEEFu; hdr.headerChecksum = 0xCAFEBABEu; TEST_ASSERT_EQUAL_UINT64(12345ULL, hdr.lsn); TEST_ASSERT_EQUAL_UINT64(2ULL, hdr.term); TEST_ASSERT_EQUAL_UINT64(999999ULL, hdr.timestamp); TEST_ASSERT_EQUAL_UINT32(1u, hdr.version); TEST_ASSERT_EQUAL_UINT32(10u, hdr.nJobs); TEST_ASSERT_EQUAL_UINT32(3u, hdr.nQueues); TEST_ASSERT_EQUAL_UINT32(5u, hdr.nWorkers); TEST_ASSERT_EQUAL_UINT32(0xDEADBEEFu, hdr.checksum); TEST_ASSERT_EQUAL_UINT32(0xCAFEBABEu, hdr.headerChecksum); printf("test_snapshot_header_capnp_fields: PASS\n"); } /* ------------------------------------------------------------------ */ /* Test 3: ReplEnvelope struct fields accessible */ /* ------------------------------------------------------------------ */ static void test_repl_envelope_capnp_fields(void) { /* Verify struct size constant */ TEST_ASSERT_EQUAL_INT(40, (int)ReplEnvelope_struct_bytes_count); capnp_repl_envelope_t env; memset(&env, 0, sizeof(env)); env.term = 7ULL; env.lsn = 100ULL; env.entryType = (uint32_t)WAL_JOB_SUBMIT; env.payload = NULL; /* optional data pointer */ env.crc = 0x12345678u; env.prevCrc = WAL_CRC_NONE; TEST_ASSERT_EQUAL_UINT64(7ULL, env.term); TEST_ASSERT_EQUAL_UINT64(100ULL, env.lsn); TEST_ASSERT_EQUAL_UINT32(WAL_JOB_SUBMIT, env.entryType); TEST_ASSERT_EQUAL_UINT32(0x12345678u, env.crc); TEST_ASSERT_EQUAL_UINT32(WAL_CRC_NONE, env.prevCrc); printf("test_repl_envelope_capnp_fields: PASS\n"); } /* ------------------------------------------------------------------ */ /* Suite entry point */ /* ------------------------------------------------------------------ */ void test_e2e_capnp(void) { printf("\n>> P0-15e: Cap'n Proto partial merge semantics\n\n"); RUN_TEST(test_persist_config_capnp_round_trip); RUN_TEST(test_snapshot_header_capnp_fields); RUN_TEST(test_repl_envelope_capnp_fields); }