#include "amduat/asl/asl_store_index_fs.h" #include "amduat/asl/store.h" #include "amduat/enc/asl1_core.h" #include "amduat/hash/asl1.h" #include #include #include #include #include #include #include #include #include #include static bool join_path(const char *base, const char *segment, char **out_path) { size_t base_len; size_t seg_len; bool needs_sep; size_t total_len; char *buffer; size_t offset; if (base == NULL || segment == NULL || out_path == NULL) { return false; } if (base[0] == '\0' || segment[0] == '\0') { return false; } base_len = strlen(base); seg_len = strlen(segment); needs_sep = base[base_len - 1u] != '/'; total_len = base_len + (needs_sep ? 1u : 0u) + seg_len + 1u; buffer = (char *)malloc(total_len); if (buffer == NULL) { return false; } offset = 0u; memcpy(buffer + offset, base, base_len); offset += base_len; if (needs_sep) { buffer[offset++] = '/'; } memcpy(buffer + offset, segment, seg_len); offset += seg_len; buffer[offset] = '\0'; *out_path = buffer; return true; } static bool remove_tree(const char *path) { struct stat st; DIR *dir; struct dirent *entry; if (path == NULL) { return false; } if (lstat(path, &st) != 0) { return errno == ENOENT; } if (!S_ISDIR(st.st_mode)) { return unlink(path) == 0; } dir = opendir(path); if (dir == NULL) { return false; } while ((entry = readdir(dir)) != NULL) { char *child = NULL; if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { continue; } if (!join_path(path, entry->d_name, &child)) { closedir(dir); return false; } if (!remove_tree(child)) { free(child); closedir(dir); return false; } free(child); } if (closedir(dir) != 0) { return false; } return rmdir(path) == 0; } static char *make_temp_root(void) { char *templ; const char template_prefix[] = "/tmp/amduat_test_asl_store_index_fs_XXXXXX"; templ = (char *)malloc(sizeof(template_prefix)); if (templ == NULL) { return NULL; } memcpy(templ, template_prefix, sizeof(template_prefix)); if (mkdtemp(templ) == NULL) { free(templ); return NULL; } return templ; } static int test_round_trip(void) { amduat_asl_store_config_t config; amduat_asl_store_index_fs_t fs; amduat_asl_store_t store; amduat_asl_store_error_t err; amduat_asl_index_state_t state; amduat_asl_index_state_t current_state; amduat_artifact_t artifact; amduat_artifact_t loaded; amduat_reference_t ref; uint8_t payload[6]; char *root; int exit_code = 1; root = make_temp_root(); if (root == NULL) { fprintf(stderr, "temp root failed\n"); return 1; } 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; } amduat_asl_store_init(&store, config, amduat_asl_store_index_fs_ops(), &fs); memset(payload, 0x5a, sizeof(payload)); artifact = amduat_artifact(amduat_octets(payload, sizeof(payload))); ref = amduat_reference(0u, amduat_octets(NULL, 0u)); err = amduat_asl_store_put_indexed(&store, artifact, &ref, &state); if (err != AMDUAT_ASL_STORE_OK) { fprintf(stderr, "put_indexed failed: %d\n", err); goto cleanup; } if (!amduat_asl_index_current_state(&store, ¤t_state)) { fprintf(stderr, "current_state failed\n"); goto cleanup; } if (current_state.log_position != state.log_position) { fprintf(stderr, "log position mismatch\n"); goto cleanup; } loaded = amduat_artifact(amduat_octets(NULL, 0u)); err = amduat_asl_store_get_indexed(&store, ref, state, &loaded); if (err != AMDUAT_ASL_STORE_OK) { fprintf(stderr, "get_indexed failed: %d\n", err); goto cleanup; } if (!amduat_artifact_eq(artifact, loaded)) { fprintf(stderr, "artifact mismatch\n"); amduat_artifact_free(&loaded); goto cleanup; } amduat_artifact_free(&loaded); if (state.log_position > 0u) { amduat_asl_index_state_t cutoff = state; cutoff.log_position = state.log_position - 1u; loaded = amduat_artifact(amduat_octets(NULL, 0u)); err = amduat_asl_store_get_indexed(&store, ref, cutoff, &loaded); if (err != AMDUAT_ASL_STORE_ERR_NOT_FOUND) { fprintf(stderr, "cutoff lookup expected not found: %d\n", err); amduat_artifact_free(&loaded); goto cleanup; } } exit_code = 0; cleanup: amduat_reference_free(&ref); if (!remove_tree(root)) { fprintf(stderr, "cleanup failed\n"); exit_code = 1; } free(root); return exit_code; } int main(void) { return test_round_trip(); }