#ifndef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 200809L #endif #include "amduatd_space_workspace.h" #include "amduatd_fed_cursor.h" #include "amduatd_space.h" #include "amduatd_space_manifest.h" #include "amduatd_store.h" #include "amduat/asl/asl_pointer_fs.h" #include "amduat/asl/asl_store_fs_meta.h" #include "amduat/asl/record.h" #include "amduat/asl/ref_text.h" #include "amduat/hash/asl1.h" #include #include #include #include static int failures = 0; static void expect(bool cond, const char *msg) { if (!cond) { fprintf(stderr, "FAIL: %s\n", msg); failures++; } } static char *amduatd_test_make_temp_dir(void) { char tmpl[] = "/tmp/amduatd-space-workspace-XXXXXX"; char *dir = mkdtemp(tmpl); size_t len; char *copy; if (dir == NULL) { perror("mkdtemp"); return NULL; } len = strlen(dir); copy = (char *)malloc(len + 1u); if (copy == NULL) { fprintf(stderr, "failed to allocate temp dir copy\n"); return NULL; } memcpy(copy, dir, len + 1u); return copy; } static bool amduatd_make_test_ref(uint8_t fill, amduat_reference_t *out_ref) { uint8_t digest_bytes[32]; amduat_octets_t digest; if (out_ref == NULL) { return false; } memset(digest_bytes, fill, sizeof(digest_bytes)); if (!amduat_octets_clone(amduat_octets(digest_bytes, sizeof(digest_bytes)), &digest)) { return false; } *out_ref = amduat_reference(AMDUAT_HASH_ASL1_ID_SHA256, digest); return true; } static int amduatd_test_workspace_missing(void) { char *root = amduatd_test_make_temp_dir(); amduat_asl_store_fs_config_t cfg; amduatd_store_ctx_t store_ctx; amduat_asl_store_t store; amduat_asl_pointer_store_t pointer_store; amduatd_space_t space; amduatd_fed_cfg_t fed_cfg; char *workspace_json = NULL; size_t workspace_len = 0u; amduatd_space_workspace_status_t status; if (root == NULL) { return 1; } memset(&cfg, 0, sizeof(cfg)); if (!amduat_asl_store_fs_init_root(root, NULL, &cfg)) { fprintf(stderr, "failed to init store root\n"); free(root); return 1; } memset(&store_ctx, 0, sizeof(store_ctx)); memset(&store, 0, sizeof(store)); if (!amduatd_store_init(&store, &cfg, &store_ctx, root, AMDUATD_STORE_BACKEND_FS)) { fprintf(stderr, "failed to init store\n"); free(root); return 1; } if (!amduat_asl_pointer_store_init(&pointer_store, root)) { fprintf(stderr, "failed to init pointer store\n"); free(root); return 1; } if (!amduatd_space_init(&space, "alpha", false)) { fprintf(stderr, "failed to init space\n"); free(root); return 1; } amduatd_fed_cfg_init(&fed_cfg); status = amduatd_space_workspace_get(&store, &pointer_store, &space, &fed_cfg, AMDUATD_STORE_BACKEND_FS, &workspace_json, &workspace_len); expect(status == AMDUATD_SPACE_WORKSPACE_ERR_NOT_FOUND, "missing manifest returns not found"); expect(workspace_json == NULL, "workspace json unset on missing"); free(root); return failures == 0 ? 0 : 1; } static int amduatd_test_workspace_snapshot(void) { char *root = amduatd_test_make_temp_dir(); amduat_asl_store_fs_config_t cfg; amduatd_store_ctx_t store_ctx; amduat_asl_store_t store; amduat_asl_pointer_store_t pointer_store; amduatd_space_t space; amduat_reference_t pinned_ref; char *pinned_hex = NULL; char payload[512]; amduat_reference_t record_ref; amduat_octets_t pointer_name = amduat_octets(NULL, 0u); bool swapped = false; amduatd_fed_cursor_record_t cursor; amduat_reference_t cursor_ref; amduat_reference_t cursor_last_ref; char *cursor_last_hex = NULL; char *manifest_ref_hex = NULL; amduatd_fed_cfg_t fed_cfg; char *workspace_json = NULL; size_t workspace_len = 0u; char *workspace_json_2 = NULL; size_t workspace_len_2 = 0u; amduatd_space_workspace_status_t status; const char *m0 = NULL; const char *m1 = NULL; const char *m2 = NULL; if (root == NULL) { return 1; } memset(&cfg, 0, sizeof(cfg)); if (!amduat_asl_store_fs_init_root(root, NULL, &cfg)) { fprintf(stderr, "failed to init store root\n"); free(root); return 1; } memset(&store_ctx, 0, sizeof(store_ctx)); memset(&store, 0, sizeof(store)); if (!amduatd_store_init(&store, &cfg, &store_ctx, root, AMDUATD_STORE_BACKEND_FS)) { fprintf(stderr, "failed to init store\n"); free(root); return 1; } if (!amduat_asl_pointer_store_init(&pointer_store, root)) { fprintf(stderr, "failed to init pointer store\n"); free(root); return 1; } if (!amduatd_space_init(&space, "alpha", false)) { fprintf(stderr, "failed to init space\n"); free(root); return 1; } if (!amduatd_make_test_ref(0x11, &pinned_ref)) { fprintf(stderr, "failed to make pinned ref\n"); free(root); return 1; } if (!amduat_asl_ref_encode_hex(pinned_ref, &pinned_hex)) { fprintf(stderr, "failed to encode pinned ref\n"); amduat_reference_free(&pinned_ref); free(root); return 1; } { int n = snprintf( payload, sizeof(payload), "{" "\"version\":1," "\"mounts\":[" "{\"name\":\"beta\",\"peer_key\":\"peer-2\",\"space_id\":\"zeta\"," "\"mode\":\"track\"}," "{\"name\":\"alpha\",\"peer_key\":\"peer-1\",\"space_id\":\"zeta\"," "\"mode\":\"pinned\",\"pinned_root_ref\":\"%s\"}," "{\"name\":\"alpha\",\"peer_key\":\"peer-1\",\"space_id\":\"beta\"," "\"mode\":\"track\"}" "]" "}", pinned_hex); if (n <= 0 || (size_t)n >= sizeof(payload)) { fprintf(stderr, "failed to build manifest payload\n"); free(pinned_hex); amduat_reference_free(&pinned_ref); free(root); return 1; } } free(pinned_hex); if (amduat_asl_record_store_put( &store, amduat_octets(AMDUATD_SPACE_MANIFEST_1, strlen(AMDUATD_SPACE_MANIFEST_1)), amduat_octets((const uint8_t *)payload, strlen(payload)), &record_ref) != AMDUAT_ASL_STORE_OK) { fprintf(stderr, "failed to store manifest record\n"); amduat_reference_free(&pinned_ref); free(root); return 1; } if (!amduatd_space_scope_name(&space, "manifest/head", &pointer_name)) { fprintf(stderr, "failed to build manifest pointer name\n"); amduat_reference_free(&record_ref); amduat_reference_free(&pinned_ref); free(root); return 1; } if (amduat_asl_pointer_cas(&pointer_store, (const char *)pointer_name.data, false, NULL, &record_ref, &swapped) != AMDUAT_ASL_POINTER_OK || !swapped) { fprintf(stderr, "failed to set manifest pointer\n"); amduat_octets_free(&pointer_name); amduat_reference_free(&record_ref); amduat_reference_free(&pinned_ref); free(root); return 1; } amduat_octets_free(&pointer_name); if (!amduatd_make_test_ref(0x22, &cursor_last_ref)) { fprintf(stderr, "failed to make cursor ref\n"); amduat_reference_free(&record_ref); amduat_reference_free(&pinned_ref); free(root); return 1; } if (!amduat_asl_ref_encode_hex(cursor_last_ref, &cursor_last_hex)) { fprintf(stderr, "failed to encode cursor ref\n"); amduat_reference_free(&cursor_last_ref); amduat_reference_free(&record_ref); amduat_reference_free(&pinned_ref); free(root); return 1; } amduatd_fed_cursor_record_init(&cursor); cursor.peer_key = strdup("peer-1"); cursor.space_id = strdup("alpha"); cursor.has_logseq = true; cursor.last_logseq = 42u; cursor.has_record_ref = true; cursor.last_record_ref = cursor_last_ref; memset(&cursor_ref, 0, sizeof(cursor_ref)); if (amduatd_fed_cursor_cas_set_remote(&store, &pointer_store, &space, "peer-1", "beta", NULL, &cursor, &cursor_ref) != AMDUATD_FED_CURSOR_OK) { fprintf(stderr, "failed to set cursor\n"); amduatd_fed_cursor_record_free(&cursor); amduat_reference_free(&cursor_ref); amduat_reference_free(&record_ref); amduat_reference_free(&pinned_ref); free(cursor_last_hex); free(root); return 1; } amduatd_fed_cursor_record_free(&cursor); amduat_reference_free(&cursor_ref); if (!amduat_asl_ref_encode_hex(record_ref, &manifest_ref_hex)) { fprintf(stderr, "failed to encode manifest ref\n"); amduat_reference_free(&record_ref); amduat_reference_free(&pinned_ref); free(cursor_last_hex); free(root); return 1; } amduatd_fed_cfg_init(&fed_cfg); status = amduatd_space_workspace_get(&store, &pointer_store, &space, &fed_cfg, AMDUATD_STORE_BACKEND_FS, &workspace_json, &workspace_len); expect(status == AMDUATD_SPACE_WORKSPACE_OK, "workspace snapshot ok"); expect(workspace_json != NULL && workspace_len != 0u, "workspace json populated"); status = amduatd_space_workspace_get(&store, &pointer_store, &space, &fed_cfg, AMDUATD_STORE_BACKEND_FS, &workspace_json_2, &workspace_len_2); expect(status == AMDUATD_SPACE_WORKSPACE_OK, "workspace snapshot ok (repeat)"); expect(workspace_json_2 != NULL && workspace_len_2 != 0u, "workspace json populated (repeat)"); if (workspace_json != NULL && workspace_json_2 != NULL) { expect(workspace_len == workspace_len_2, "workspace output length deterministic"); if (workspace_len == workspace_len_2) { expect(memcmp(workspace_json, workspace_json_2, workspace_len) == 0, "workspace output deterministic"); } } if (workspace_json != NULL) { m0 = strstr( workspace_json, "\"name\":\"alpha\",\"peer_key\":\"peer-1\",\"remote_space_id\":\"beta\""); m1 = strstr( workspace_json, "\"name\":\"alpha\",\"peer_key\":\"peer-1\",\"remote_space_id\":\"zeta\""); m2 = strstr( workspace_json, "\"name\":\"beta\",\"peer_key\":\"peer-2\",\"remote_space_id\":\"zeta\""); expect(m0 != NULL && m1 != NULL && m2 != NULL, "workspace mounts include all entries"); if (m0 != NULL && m1 != NULL && m2 != NULL) { expect(m0 < m1 && m1 < m2, "workspace mounts are in canonical order"); } expect(strstr(workspace_json, "\"mode\":\"pinned\"") != NULL, "pinned mode present"); expect(strstr(workspace_json, "\"pinned_root_ref\":\"") != NULL, "pinned root ref present"); expect(strstr(workspace_json, "\"cursor_keying\":\"none\"") != NULL, "pinned cursor keying present"); expect(strstr(workspace_json, "\"cursor_keying\":\"v2\"") != NULL, "track cursor keying present"); expect(strstr(workspace_json, "\"pull_cursor\":{\"present\":true") != NULL, "track cursor present true"); expect(strstr(workspace_json, "\"pull_cursor\":{\"present\":false") != NULL, "pinned cursor present false"); expect(strstr(workspace_json, "\"last_logseq\":42") != NULL, "cursor last_logseq present"); expect(strstr(workspace_json, cursor_last_hex) != NULL, "cursor ref present"); expect(strstr(workspace_json, manifest_ref_hex) != NULL, "manifest ref present"); expect(strstr(workspace_json, "\"store_backend\":\"fs\"") != NULL, "store backend present"); expect(strstr(workspace_json, "\"transport\":\"stub\"") != NULL, "federation transport present"); expect(strstr(workspace_json, "\"supported_ops\":{\"put\":true,\"get\":true," "\"put_indexed\":false,\"get_indexed\":false," "\"tombstone\":false,\"tombstone_lift\":false," "\"log_scan\":false,\"current_state\":false," "\"validate_config\":true}") != NULL, "supported ops reflect fs backend"); } free(workspace_json); free(workspace_json_2); free(manifest_ref_hex); amduat_reference_free(&record_ref); amduat_reference_free(&pinned_ref); free(cursor_last_hex); free(root); return failures == 0 ? 0 : 1; } int main(void) { if (amduatd_test_workspace_missing() != 0) { return 1; } if (amduatd_test_workspace_snapshot() != 0) { return 1; } return failures == 0 ? 0 : 1; }