feat(ha-term-safety): add WAL_CONFIG_MARKER entry type + reference payload codec (task 4.1)
This commit is contained in:
parent
f1783f7952
commit
f447ad4183
5 changed files with 215 additions and 1 deletions
|
|
@ -504,6 +504,92 @@ static void test_conf_save_config_path_consistency(void)
|
|||
printf("test_conf_save_config_path_consistency: PASS\n");
|
||||
}
|
||||
|
||||
/* ── WAL_CONFIG_MARKER codec (ha-term-safety task 4.1) ───────────────
|
||||
* The config-change marker payload carries ONLY {version_tag, sha256} —
|
||||
* a reference, never the configuration bytes (R7.2/R7.4). These tests
|
||||
* exercise the fixed-size encode/decode codec that rides inside the
|
||||
* raft_entry_blob_t envelope with type == WAL_CONFIG_MARKER. */
|
||||
|
||||
/* Round-trip: encode {version_tag, sha256} then decode → identical, and the
|
||||
* encoded form is exactly the fixed marker size (tag + 32-byte hash) with NO
|
||||
* configuration bytes appended. */
|
||||
static void test_config_marker_encode_decode_roundtrip(void)
|
||||
{
|
||||
const uint64_t version_tag = 0x0123456789abcdefULL;
|
||||
uint8_t sha256[32];
|
||||
for (int i = 0; i < 32; i++)
|
||||
sha256[i] = (uint8_t)(0xA0 + i);
|
||||
|
||||
uint8_t buf[64];
|
||||
size_t enc_len = 0;
|
||||
int rc = config_marker_encode(version_tag, sha256, buf, sizeof(buf), &enc_len);
|
||||
TEST_ASSERT_EQUAL_INT(0, rc);
|
||||
|
||||
/* Encoded form carries NO config bytes: exactly 8 (tag) + 32 (sha256). */
|
||||
TEST_ASSERT_EQUAL_UINT(WAL_CONFIG_MARKER_PAYLOAD_LEN, enc_len);
|
||||
TEST_ASSERT_EQUAL_UINT(8u + 32u, enc_len);
|
||||
|
||||
uint64_t got_tag = 0;
|
||||
uint8_t got_sha[32];
|
||||
memset(got_sha, 0, sizeof(got_sha));
|
||||
rc = config_marker_decode(buf, enc_len, &got_tag, got_sha);
|
||||
TEST_ASSERT_EQUAL_INT(0, rc);
|
||||
|
||||
TEST_ASSERT_EQUAL_HEX64(version_tag, got_tag);
|
||||
TEST_ASSERT_EQUAL_HEX8_ARRAY(sha256, got_sha, 32);
|
||||
|
||||
printf("test_config_marker_encode_decode_roundtrip: PASS\n");
|
||||
}
|
||||
|
||||
/* The WAL entry type value must be exactly 50 and must not collide with the
|
||||
* neighbouring WAL_NOOP (40) or WAL_CHECKPOINT (100) types (design.md). */
|
||||
static void test_config_marker_enum_value_is_50(void)
|
||||
{
|
||||
TEST_ASSERT_EQUAL_INT(50, WAL_CONFIG_MARKER);
|
||||
TEST_ASSERT_NOT_EQUAL(WAL_NOOP, WAL_CONFIG_MARKER);
|
||||
TEST_ASSERT_NOT_EQUAL(WAL_CHECKPOINT, WAL_CONFIG_MARKER);
|
||||
/* Strictly between WAL_NOOP and WAL_CHECKPOINT. */
|
||||
TEST_ASSERT_TRUE(WAL_CONFIG_MARKER > WAL_NOOP);
|
||||
TEST_ASSERT_TRUE(WAL_CONFIG_MARKER < WAL_CHECKPOINT);
|
||||
printf("test_config_marker_enum_value_is_50: PASS\n");
|
||||
}
|
||||
|
||||
/* A truncated (short) buffer must fail cleanly with -EINVAL, never read past
|
||||
* the end of the supplied buffer. */
|
||||
static void test_config_marker_decode_truncated_fails(void)
|
||||
{
|
||||
uint8_t sha256[32];
|
||||
memset(sha256, 0x5c, sizeof(sha256));
|
||||
uint8_t buf[WAL_CONFIG_MARKER_PAYLOAD_LEN];
|
||||
size_t enc_len = 0;
|
||||
TEST_ASSERT_EQUAL_INT(0, config_marker_encode(0xdeadbeefcafef00dULL, sha256,
|
||||
buf, sizeof(buf), &enc_len));
|
||||
|
||||
uint64_t tag = 0;
|
||||
uint8_t sha_out[32];
|
||||
/* One byte short of a full marker payload → reject, no OOB read. */
|
||||
int rc = config_marker_decode(buf, enc_len - 1, &tag, sha_out);
|
||||
TEST_ASSERT_EQUAL_INT(-EINVAL, rc);
|
||||
|
||||
/* Zero-length buffer → reject. */
|
||||
rc = config_marker_decode(buf, 0, &tag, sha_out);
|
||||
TEST_ASSERT_EQUAL_INT(-EINVAL, rc);
|
||||
|
||||
printf("test_config_marker_decode_truncated_fails: PASS\n");
|
||||
}
|
||||
|
||||
/* A too-small output buffer must fail with -ENOSPC and not overflow. */
|
||||
static void test_config_marker_encode_short_buffer_fails(void)
|
||||
{
|
||||
uint8_t sha256[32];
|
||||
memset(sha256, 0x11, sizeof(sha256));
|
||||
uint8_t small[WAL_CONFIG_MARKER_PAYLOAD_LEN - 1];
|
||||
size_t enc_len = 123; /* sentinel — must be left untouched on failure */
|
||||
int rc = config_marker_encode(7, sha256, small, sizeof(small), &enc_len);
|
||||
TEST_ASSERT_EQUAL_INT(-ENOSPC, rc);
|
||||
printf("test_config_marker_encode_short_buffer_fails: PASS\n");
|
||||
}
|
||||
|
||||
/* ── wait_all_with_timeout (XCE_TESTING shim) ───── */
|
||||
|
||||
#ifdef XCE_TESTING
|
||||
|
|
@ -2260,6 +2346,11 @@ void test_config_repl(void)
|
|||
RUN_TEST(test_sanitise_cn_control_chars);
|
||||
RUN_TEST(test_sanitise_cn_truncated);
|
||||
RUN_TEST(test_conf_save_config_path_consistency);
|
||||
/* Task 4.1: WAL_CONFIG_MARKER type + reference-only codec */
|
||||
RUN_TEST(test_config_marker_enum_value_is_50);
|
||||
RUN_TEST(test_config_marker_encode_decode_roundtrip);
|
||||
RUN_TEST(test_config_marker_decode_truncated_fails);
|
||||
RUN_TEST(test_config_marker_encode_short_buffer_fails);
|
||||
#ifdef XCE_TESTING
|
||||
RUN_TEST(test_load_primary_config_missing_returns_error);
|
||||
RUN_TEST(test_wait_all_with_timeout_slow_threads);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue