Added targeted ingest/remove + epoch tests in test_tgk_store_mem.c

Added the FS ingest/remove + epoch test in test_tgk_store_fs.c and fixed the missing ref_edge initialization
This commit is contained in:
Carl Niklas Rydberg 2025-12-21 21:23:55 +01:00
parent 8bbadd602c
commit d3224b26ac
2 changed files with 326 additions and 1 deletions

View file

@ -469,6 +469,7 @@ static int test_manifest_duplicate_refs(void) {
uint8_t digest_node_a[32]; uint8_t digest_node_a[32];
uint8_t digest_node_b[32]; uint8_t digest_node_b[32];
uint8_t digest_payload[32]; uint8_t digest_payload[32];
uint8_t digest_edge[32];
amduat_tgk_graph_scan_result_t scan; amduat_tgk_graph_scan_result_t scan;
amduat_tgk_edge_body_t body; amduat_tgk_edge_body_t body;
amduat_tgk_edge_body_t edge; amduat_tgk_edge_body_t edge;
@ -522,6 +523,7 @@ static int test_manifest_duplicate_refs(void) {
node_a = make_ref(0xa1, digest_node_a); node_a = make_ref(0xa1, digest_node_a);
node_b = make_ref(0xb1, digest_node_b); node_b = make_ref(0xb1, digest_node_b);
payload = make_ref(0xe1, digest_payload); payload = make_ref(0xe1, digest_payload);
ref_edge = make_ref(0x71, digest_edge);
memset(&edge, 0, sizeof(edge)); memset(&edge, 0, sizeof(edge));
edge.type = 0x10; edge.type = 0x10;
@ -601,10 +603,188 @@ cleanup:
return exit_code; return exit_code;
} }
static int test_ingest_remove_epoch(void) {
amduat_asl_store_config_t asl_config;
amduat_asl_store_fs_t asl_fs;
amduat_asl_store_t asl_store;
amduat_tgk_store_config_t tgk_config;
amduat_tgk_store_t store;
amduat_tgk_store_fs_t fs;
amduat_tgk_identity_domain_t domains[1];
uint32_t edge_tags[1];
amduat_tgk_edge_type_id_t edge_types[1];
amduat_asl_encoding_profile_id_t encodings[1];
amduat_octets_t edge_bytes;
amduat_reference_t ref_edge;
amduat_reference_t node_a;
amduat_reference_t node_b;
amduat_reference_t payload;
uint8_t digest_node_a[32];
uint8_t digest_node_b[32];
uint8_t digest_payload[32];
amduat_tgk_edge_body_t edge;
amduat_reference_t edge_from[1];
amduat_reference_t edge_to[1];
amduat_tgk_snapshot_id_t epoch_before = 0;
amduat_tgk_snapshot_id_t epoch_after = 0;
amduat_tgk_graph_scan_result_t scan;
char *root = NULL;
char *manifest_path = NULL;
int exit_code = 1;
bool fs_ready = false;
memset(&tgk_config, 0, sizeof(tgk_config));
memset(&fs, 0, sizeof(fs));
memset(&edge, 0, sizeof(edge));
edge_bytes = amduat_octets(NULL, 0);
root = make_temp_root();
if (root == NULL) {
fprintf(stderr, "fs epoch temp root failed\n");
goto cleanup;
}
if (!join_path(root, "manifest.txt", &manifest_path)) {
fprintf(stderr, "fs epoch manifest path failed\n");
goto cleanup;
}
if (!write_manifest(manifest_path, NULL, 0)) {
fprintf(stderr, "fs epoch manifest write failed\n");
goto cleanup;
}
asl_config.encoding_profile_id = AMDUAT_ENC_ASL1_CORE_V1;
asl_config.hash_id = AMDUAT_HASH_ASL1_ID_SHA256;
if (!amduat_asl_store_fs_init(&asl_fs, asl_config, root)) {
fprintf(stderr, "fs epoch asl store fs init failed\n");
goto cleanup;
}
amduat_asl_store_init(&asl_store, asl_config, amduat_asl_store_fs_ops(),
&asl_fs);
domains[0].encoding_profile = AMDUAT_ENC_ASL1_CORE_V1;
domains[0].hash_id = AMDUAT_HASH_ASL1_ID_SHA256;
edge_tags[0] = TYPE_TAG_TGK1_EDGE_V1;
edge_types[0] = 0x10;
encodings[0] = TGK1_EDGE_ENC_V1;
tgk_config.id_space.domains = domains;
tgk_config.id_space.domains_len = 1;
tgk_config.artifact_scope.description = amduat_octets(NULL, 0);
tgk_config.tgk_profiles.edge_tags = edge_tags;
tgk_config.tgk_profiles.edge_tags_len = 1;
tgk_config.tgk_profiles.edge_types = edge_types;
tgk_config.tgk_profiles.edge_types_len = 1;
tgk_config.tgk_profiles.encodings = encodings;
tgk_config.tgk_profiles.encodings_len = 1;
if (!amduat_tgk_store_fs_init(&fs, tgk_config, manifest_path,
AMDUAT_FORMAT_REF_HEX, &asl_store)) {
fprintf(stderr, "fs epoch tgk store fs init failed\n");
goto cleanup;
}
fs_ready = true;
amduat_tgk_store_init(&store, tgk_config, amduat_tgk_store_fs_ops(), &fs);
if (!amduat_tgk_store_snapshot_id(&store, &epoch_before)) {
fprintf(stderr, "fs epoch get failed\n");
goto cleanup;
}
node_a = make_ref(0xa1, digest_node_a);
node_b = make_ref(0xb1, digest_node_b);
payload = make_ref(0xe1, digest_payload);
edge.type = 0x10;
edge_from[0] = node_a;
edge.from = edge_from;
edge.from_len = 1;
edge_to[0] = node_b;
edge.to = edge_to;
edge.to_len = 1;
edge.payload = payload;
if (!amduat_enc_tgk1_edge_encode_v1(&edge, &edge_bytes)) {
fprintf(stderr, "fs epoch edge encode failed\n");
goto cleanup;
}
if (!amduat_tgk_store_ingest_artifact(
&store, ref_edge,
amduat_artifact_with_type(edge_bytes,
amduat_type_tag(TYPE_TAG_TGK1_EDGE_V1)))) {
fprintf(stderr, "fs epoch ingest failed\n");
goto cleanup;
}
if (!amduat_tgk_store_snapshot_id(&store, &epoch_after)) {
fprintf(stderr, "fs epoch get after ingest failed\n");
goto cleanup;
}
if (epoch_after != epoch_before + 1u) {
fprintf(stderr, "fs epoch did not increment on ingest\n");
goto cleanup;
}
if (!amduat_tgk_store_scan_edges(&store,
(amduat_tgk_edge_type_filter_t){0},
amduat_octets(NULL, 0), false, &scan)) {
fprintf(stderr, "fs epoch scan failed\n");
goto cleanup;
}
if (scan.edges.len != 1) {
fprintf(stderr, "fs epoch scan count mismatch\n");
amduat_tgk_graph_scan_result_free(&scan);
goto cleanup;
}
amduat_tgk_graph_scan_result_free(&scan);
if (!amduat_tgk_store_remove_artifact(&store, ref_edge)) {
fprintf(stderr, "fs epoch remove failed\n");
goto cleanup;
}
if (!amduat_tgk_store_snapshot_id(&store, &epoch_after)) {
fprintf(stderr, "fs epoch get after remove failed\n");
goto cleanup;
}
if (epoch_after != epoch_before + 2u) {
fprintf(stderr, "fs epoch did not increment on remove\n");
goto cleanup;
}
if (!amduat_tgk_store_scan_edges(&store,
(amduat_tgk_edge_type_filter_t){0},
amduat_octets(NULL, 0), false, &scan)) {
fprintf(stderr, "fs epoch scan after remove failed\n");
goto cleanup;
}
if (scan.edges.len != 0) {
fprintf(stderr, "fs epoch scan not empty after remove\n");
amduat_tgk_graph_scan_result_free(&scan);
goto cleanup;
}
amduat_tgk_graph_scan_result_free(&scan);
exit_code = 0;
cleanup:
if (fs_ready) {
amduat_tgk_store_fs_free(&fs);
}
free((void *)edge_bytes.data);
free_ref(&ref_edge);
free(manifest_path);
if (root != NULL) {
remove_tree(root);
}
free(root);
return exit_code;
}
int main(void) { int main(void) {
if (test_manifest_load() != 0 || if (test_manifest_load() != 0 ||
test_init_rejects_duplicate_hash_id() != 0 || test_init_rejects_duplicate_hash_id() != 0 ||
test_manifest_duplicate_refs() != 0) { test_manifest_duplicate_refs() != 0 ||
test_ingest_remove_epoch() != 0) {
return 1; return 1;
} }
return 0; return 0;

View file

@ -774,6 +774,150 @@ cleanup:
return exit_code; return exit_code;
} }
static int test_ingest_remove_epoch(void) {
amduat_tgk_store_mem_t mem;
amduat_tgk_store_t store;
amduat_tgk_store_config_t config;
amduat_tgk_identity_domain_t domains[1];
uint32_t edge_tags[1];
amduat_tgk_edge_type_id_t edge_types[1];
amduat_asl_encoding_profile_id_t encodings[1];
amduat_tgk_store_mem_artifact_t artifacts[1];
amduat_octets_t edge_bytes;
amduat_reference_t ref_edge;
amduat_reference_t node_a;
amduat_reference_t node_b;
amduat_reference_t payload;
uint8_t digest_edge[32];
uint8_t digest_a[32];
uint8_t digest_b[32];
uint8_t digest_payload[32];
amduat_tgk_edge_body_t edge;
amduat_reference_t edge_from[1];
amduat_reference_t edge_to[1];
amduat_tgk_snapshot_id_t epoch_before = 0;
amduat_tgk_snapshot_id_t epoch_after = 0;
amduat_tgk_graph_scan_result_t scan;
int exit_code = 1;
memset(&mem, 0, sizeof(mem));
memset(&config, 0, sizeof(config));
memset(&edge, 0, sizeof(edge));
edge_bytes = amduat_octets(NULL, 0);
domains[0].encoding_profile = AMDUAT_ENC_ASL1_CORE_V1;
domains[0].hash_id = AMDUAT_HASH_ASL1_ID_SHA256;
edge_tags[0] = TYPE_TAG_TGK1_EDGE_V1;
edge_types[0] = 0x10;
encodings[0] = TGK1_EDGE_ENC_V1;
config.id_space.domains = domains;
config.id_space.domains_len = 1;
config.tgk_profiles.edge_tags = edge_tags;
config.tgk_profiles.edge_tags_len = 1;
config.tgk_profiles.edge_types = edge_types;
config.tgk_profiles.edge_types_len = 1;
config.tgk_profiles.encodings = encodings;
config.tgk_profiles.encodings_len = 1;
ref_edge = make_ref(0x71, digest_edge);
node_a = make_ref(0xa1, digest_a);
node_b = make_ref(0xb1, digest_b);
payload = make_ref(0xe1, digest_payload);
edge.type = 0x10;
edge_from[0] = node_a;
edge.from = edge_from;
edge.from_len = 1;
edge_to[0] = node_b;
edge.to = edge_to;
edge.to_len = 1;
edge.payload = payload;
if (!amduat_enc_tgk1_edge_encode_v1(&edge, &edge_bytes)) {
fprintf(stderr, "epoch encode failed\n");
return 1;
}
artifacts[0].ref = ref_edge;
artifacts[0].artifact =
amduat_artifact_with_type(edge_bytes,
amduat_type_tag(TYPE_TAG_TGK1_EDGE_V1));
if (!amduat_tgk_store_mem_init(&mem, config, artifacts, 1)) {
fprintf(stderr, "epoch init failed\n");
goto cleanup;
}
amduat_tgk_store_init(&store, config, amduat_tgk_store_mem_ops(), &mem);
if (!amduat_tgk_store_snapshot_id(&store, &epoch_before)) {
fprintf(stderr, "epoch get failed\n");
goto cleanup_mem;
}
if (!amduat_tgk_store_ingest_artifact(&store, ref_edge,
artifacts[0].artifact)) {
fprintf(stderr, "epoch ingest failed\n");
goto cleanup_mem;
}
if (!amduat_tgk_store_snapshot_id(&store, &epoch_after)) {
fprintf(stderr, "epoch get after ingest failed\n");
goto cleanup_mem;
}
if (epoch_after != epoch_before) {
fprintf(stderr, "epoch changed on no-op ingest\n");
goto cleanup_mem;
}
if (!amduat_tgk_store_remove_artifact(&store, ref_edge)) {
fprintf(stderr, "epoch remove failed\n");
goto cleanup_mem;
}
if (!amduat_tgk_store_snapshot_id(&store, &epoch_after)) {
fprintf(stderr, "epoch get after remove failed\n");
goto cleanup_mem;
}
if (epoch_after != epoch_before + 1u) {
fprintf(stderr, "epoch did not increment on remove\n");
goto cleanup_mem;
}
if (!amduat_tgk_store_scan_edges(&store,
(amduat_tgk_edge_type_filter_t){0},
amduat_octets(NULL, 0), false, &scan)) {
fprintf(stderr, "epoch scan failed\n");
goto cleanup_mem;
}
if (scan.edges.len != 0) {
fprintf(stderr, "epoch scan not empty after remove\n");
amduat_tgk_graph_scan_result_free(&scan);
goto cleanup_mem;
}
amduat_tgk_graph_scan_result_free(&scan);
if (!amduat_tgk_store_ingest_artifact(&store, ref_edge,
artifacts[0].artifact)) {
fprintf(stderr, "epoch re-ingest failed\n");
goto cleanup_mem;
}
if (!amduat_tgk_store_snapshot_id(&store, &epoch_after)) {
fprintf(stderr, "epoch get after re-ingest failed\n");
goto cleanup_mem;
}
if (epoch_after != epoch_before + 2u) {
fprintf(stderr, "epoch did not increment on ingest\n");
goto cleanup_mem;
}
exit_code = 0;
cleanup_mem:
amduat_tgk_store_mem_free(&mem);
cleanup:
free((void *)edge_bytes.data);
return exit_code;
}
static int test_resolve_edge_unsupported(const test_env_t *env) { static int test_resolve_edge_unsupported(const test_env_t *env) {
amduat_reference_t ref; amduat_reference_t ref;
amduat_tgk_edge_body_t body; amduat_tgk_edge_body_t body;
@ -989,6 +1133,7 @@ int main(void) {
test_duplicate_edge_ref_same_artifact() != 0 || test_duplicate_edge_ref_same_artifact() != 0 ||
test_duplicate_edge_ref_conflict() != 0 || test_duplicate_edge_ref_conflict() != 0 ||
test_scan_edges_pagination() != 0 || test_scan_edges_pagination() != 0 ||
test_ingest_remove_epoch() != 0 ||
test_type_filter(&env) != 0 || test_type_filter(&env) != 0 ||
test_ordering(&env) != 0 || test_ordering(&env) != 0 ||
test_adjacency(&env) != 0 || test_adjacency(&env) != 0 ||