test_projector_loop_stub
This commit is contained in:
parent
baa4794918
commit
7b3ef3eab4
|
|
@ -121,6 +121,21 @@ for (;;) {
|
|||
* Cursor paging boundaries MUST NOT affect results.
|
||||
* A checkpoint MUST allow resume without changing derived outcomes.
|
||||
|
||||
### 4.3 Implementation Slice (Checklist + Stub)
|
||||
|
||||
**Checklist (minimal, repo-aligned):**
|
||||
|
||||
* Choose a stable `projection_name`, `projection_schema_version`, and `builder_id`.
|
||||
* Read authoritative head state via `amduat_asl_index_current_state`.
|
||||
* Page log records with `amduat_asl_log_read_since` (cursor-driven).
|
||||
* Apply a deterministic projection step (even if it is just a counter in the stub).
|
||||
* Encode a checkpoint via `amduat_asl_projection_checkpoint_encode_v1`.
|
||||
* Store the checkpoint as an ASL record with schema `projection/checkpoint`.
|
||||
* Verify the stored checkpoint decodes and matches the last processed `log_position`.
|
||||
|
||||
**Repo stub:** `tests/asl/test_asl_projection_replay.c` includes
|
||||
`test_projector_loop_stub()` that runs the minimal loop and persists a checkpoint.
|
||||
|
||||
---
|
||||
|
||||
## 5. Projection Checkpoint Records
|
||||
|
|
|
|||
|
|
@ -351,6 +351,168 @@ cleanup_root:
|
|||
return exit_code;
|
||||
}
|
||||
|
||||
static int test_projector_loop_stub(void) {
|
||||
amduat_asl_store_config_t config;
|
||||
amduat_asl_store_index_fs_t fs;
|
||||
amduat_asl_store_t store;
|
||||
amduat_asl_index_state_t state;
|
||||
amduat_asl_log_record_t *page = NULL;
|
||||
size_t page_len = 0u;
|
||||
amduat_asl_log_position_t after = 0u;
|
||||
amduat_asl_log_position_t next = 0u;
|
||||
bool end = false;
|
||||
amduat_reference_t checkpoint_ref;
|
||||
amduat_asl_record_t checkpoint_record;
|
||||
amduat_asl_projection_checkpoint_v1_t checkpoint;
|
||||
amduat_asl_projection_checkpoint_v1_t decoded;
|
||||
amduat_octets_t checkpoint_bytes = amduat_octets(NULL, 0u);
|
||||
size_t projected_count = 0u;
|
||||
char *root;
|
||||
int exit_code = 1;
|
||||
|
||||
root = make_temp_root();
|
||||
if (root == NULL) {
|
||||
fprintf(stderr, "temp root failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(&config, 0, sizeof(config));
|
||||
config.encoding_profile_id = AMDUAT_ENC_ASL1_CORE_V1;
|
||||
config.hash_id = AMDUAT_HASH_ASL1_ID_SHA256;
|
||||
if (!amduat_asl_store_index_fs_init(&fs, config, root)) {
|
||||
fprintf(stderr, "index fs init failed\n");
|
||||
goto cleanup_root;
|
||||
}
|
||||
amduat_asl_store_init(&store, config, amduat_asl_store_index_fs_ops(), &fs);
|
||||
|
||||
{
|
||||
uint8_t payload_a[2] = {0x10, 0x20};
|
||||
uint8_t payload_b[2] = {0x30, 0x40};
|
||||
amduat_reference_t ref = amduat_reference(0u, amduat_octets(NULL, 0u));
|
||||
amduat_artifact_t artifact = amduat_artifact(amduat_octets(payload_a, sizeof(payload_a)));
|
||||
if (amduat_asl_store_put_indexed(&store, artifact, &ref, &state) !=
|
||||
AMDUAT_ASL_STORE_OK) {
|
||||
fprintf(stderr, "put_indexed A failed\n");
|
||||
amduat_reference_free(&ref);
|
||||
goto cleanup_root;
|
||||
}
|
||||
amduat_reference_free(&ref);
|
||||
|
||||
artifact = amduat_artifact(amduat_octets(payload_b, sizeof(payload_b)));
|
||||
ref = amduat_reference(0u, amduat_octets(NULL, 0u));
|
||||
if (amduat_asl_store_put_indexed(&store, artifact, &ref, &state) !=
|
||||
AMDUAT_ASL_STORE_OK) {
|
||||
fprintf(stderr, "put_indexed B failed\n");
|
||||
amduat_reference_free(&ref);
|
||||
goto cleanup_root;
|
||||
}
|
||||
amduat_reference_free(&ref);
|
||||
}
|
||||
|
||||
if (!amduat_asl_index_current_state(&store, &state)) {
|
||||
fprintf(stderr, "current_state failed\n");
|
||||
goto cleanup_root;
|
||||
}
|
||||
|
||||
checkpoint_ref = amduat_reference(0u, amduat_octets(NULL, 0u));
|
||||
while (!end) {
|
||||
if (!amduat_asl_log_read_since(&store,
|
||||
after,
|
||||
0u,
|
||||
&page,
|
||||
&page_len,
|
||||
&next,
|
||||
&end)) {
|
||||
fprintf(stderr, "projector log read failed\n");
|
||||
goto cleanup_checkpoint_ref;
|
||||
}
|
||||
|
||||
projected_count += page_len;
|
||||
|
||||
memset(&checkpoint, 0, sizeof(checkpoint));
|
||||
checkpoint.checkpoint_version = AMDUAT_ASL_PROJECTION_CHECKPOINT_VERSION_V1;
|
||||
checkpoint.projection_name =
|
||||
amduat_octets("projector-stub", strlen("projector-stub"));
|
||||
checkpoint.projection_schema_version = 1u;
|
||||
checkpoint.has_snapshot_id = true;
|
||||
checkpoint.snapshot_id = state.snapshot_id;
|
||||
checkpoint.log_position = next;
|
||||
checkpoint.created_at = 0u;
|
||||
checkpoint.builder_id =
|
||||
amduat_octets("test-projector", strlen("test-projector"));
|
||||
checkpoint.has_artifact_count = true;
|
||||
checkpoint.artifact_count = projected_count;
|
||||
|
||||
if (!amduat_asl_projection_checkpoint_encode_v1(&checkpoint,
|
||||
&checkpoint_bytes)) {
|
||||
fprintf(stderr, "checkpoint encode failed\n");
|
||||
amduat_enc_asl_log_free(page, page_len);
|
||||
goto cleanup_checkpoint_ref;
|
||||
}
|
||||
|
||||
amduat_reference_free(&checkpoint_ref);
|
||||
if (amduat_asl_record_store_put(
|
||||
&store,
|
||||
amduat_octets("projection/checkpoint",
|
||||
strlen("projection/checkpoint")),
|
||||
checkpoint_bytes,
|
||||
&checkpoint_ref) != AMDUAT_ASL_STORE_OK) {
|
||||
fprintf(stderr, "checkpoint store failed\n");
|
||||
amduat_octets_free(&checkpoint_bytes);
|
||||
amduat_enc_asl_log_free(page, page_len);
|
||||
goto cleanup_checkpoint_ref;
|
||||
}
|
||||
|
||||
amduat_octets_free(&checkpoint_bytes);
|
||||
amduat_enc_asl_log_free(page, page_len);
|
||||
after = next;
|
||||
}
|
||||
|
||||
if (amduat_asl_record_store_get(&store, checkpoint_ref, &checkpoint_record) !=
|
||||
AMDUAT_ASL_STORE_OK) {
|
||||
fprintf(stderr, "checkpoint record get failed\n");
|
||||
goto cleanup_checkpoint_ref;
|
||||
}
|
||||
|
||||
if (!amduat_octets_eq(
|
||||
checkpoint_record.schema,
|
||||
amduat_octets("projection/checkpoint",
|
||||
strlen("projection/checkpoint")))) {
|
||||
fprintf(stderr, "checkpoint schema mismatch\n");
|
||||
amduat_asl_record_free(&checkpoint_record);
|
||||
goto cleanup_checkpoint_ref;
|
||||
}
|
||||
|
||||
if (!amduat_asl_projection_checkpoint_decode_v1(
|
||||
checkpoint_record.payload, &decoded)) {
|
||||
fprintf(stderr, "checkpoint decode failed\n");
|
||||
amduat_asl_record_free(&checkpoint_record);
|
||||
goto cleanup_checkpoint_ref;
|
||||
}
|
||||
|
||||
if (decoded.log_position != state.log_position) {
|
||||
fprintf(stderr, "checkpoint log position mismatch\n");
|
||||
amduat_asl_projection_checkpoint_free(&decoded);
|
||||
amduat_asl_record_free(&checkpoint_record);
|
||||
goto cleanup_checkpoint_ref;
|
||||
}
|
||||
|
||||
amduat_asl_projection_checkpoint_free(&decoded);
|
||||
amduat_asl_record_free(&checkpoint_record);
|
||||
exit_code = 0;
|
||||
|
||||
cleanup_checkpoint_ref:
|
||||
amduat_octets_free(&checkpoint_bytes);
|
||||
amduat_reference_free(&checkpoint_ref);
|
||||
cleanup_root:
|
||||
if (!remove_tree(root)) {
|
||||
fprintf(stderr, "cleanup failed\n");
|
||||
exit_code = 1;
|
||||
}
|
||||
free(root);
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
if (test_cursor_deterministic_replay() != 0) {
|
||||
return 1;
|
||||
|
|
@ -358,5 +520,8 @@ int main(void) {
|
|||
if (test_checkpoint_resume() != 0) {
|
||||
return 1;
|
||||
}
|
||||
if (test_projector_loop_stub() != 0) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue