amduat-api/tests/test_amduatd_space_roots.c
Carl Niklas Rydberg e54a9009a6 Add GET /v1/space/mounts/resolve with local mount resolution tests
Add mount-aware v2 federation cursors with remote_space_id support
2026-01-24 19:50:13 +01:00

358 lines
11 KiB
C

#ifndef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200809L
#endif
#include "amduatd_space_roots.h"
#include "amduatd_fed_cursor.h"
#include "amduatd_space.h"
#include "amduatd_store.h"
#include "amduat/asl/asl_store_fs_meta.h"
#include "amduat/asl/asl_pointer_fs.h"
#include "amduat/asl/none.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static char *amduatd_test_make_temp_dir(void) {
char tmpl[] = "/tmp/amduatd-roots-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_list_contains(const amduatd_space_roots_list_t *list,
const char *name) {
if (list == NULL || name == NULL) {
return false;
}
for (size_t i = 0u; i < list->len; ++i) {
if (strcmp(list->names[i], name) == 0) {
return true;
}
}
return false;
}
static bool amduatd_list_sorted(const amduatd_space_roots_list_t *list) {
if (list == NULL || list->len < 2u) {
return true;
}
for (size_t i = 1u; i < list->len; ++i) {
if (strcmp(list->names[i - 1u], list->names[i]) > 0) {
return false;
}
}
return true;
}
static bool amduatd_build_collection_head_name(const char *name,
char **out_name) {
size_t name_len;
size_t total_len;
char *buffer;
size_t offset = 0u;
if (name == NULL || out_name == NULL) {
return false;
}
if (!amduat_asl_pointer_name_is_valid(name)) {
return false;
}
name_len = strlen(name);
total_len = 11u + name_len + 5u + 1u;
buffer = (char *)malloc(total_len);
if (buffer == NULL) {
return false;
}
memcpy(buffer + offset, "collection/", 11u);
offset += 11u;
memcpy(buffer + offset, name, name_len);
offset += name_len;
memcpy(buffer + offset, "/head", 5u);
offset += 5u;
buffer[offset] = '\0';
*out_name = buffer;
return true;
}
static bool amduatd_build_collection_log_head_name(const char *name,
char **out_name) {
size_t name_len;
size_t total_len;
char *buffer;
size_t offset = 0u;
if (name == NULL || out_name == NULL) {
return false;
}
if (!amduat_asl_pointer_name_is_valid(name)) {
return false;
}
name_len = strlen(name);
total_len = 4u + 11u + name_len + 4u + 5u + 1u;
buffer = (char *)malloc(total_len);
if (buffer == NULL) {
return false;
}
memcpy(buffer + offset, "log/", 4u);
offset += 4u;
memcpy(buffer + offset, "collection/", 11u);
offset += 11u;
memcpy(buffer + offset, name, name_len);
offset += name_len;
memcpy(buffer + offset, "/log", 4u);
offset += 4u;
memcpy(buffer + offset, "/head", 5u);
offset += 5u;
buffer[offset] = '\0';
*out_name = buffer;
return true;
}
static int amduatd_test_empty_store(void) {
char *root = amduatd_test_make_temp_dir();
amduat_asl_store_fs_config_t cfg;
amduat_asl_pointer_store_t pointer_store;
amduatd_space_t space;
amduatd_space_roots_list_t list;
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;
}
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, NULL, false)) {
fprintf(stderr, "failed to init space\n");
free(root);
return 1;
}
if (!amduatd_space_roots_list(root, &pointer_store, &space, &list)) {
fprintf(stderr, "roots list failed\n");
free(root);
return 1;
}
if (list.len != 3u ||
!amduatd_list_contains(&list, "daemon/edges/index/head") ||
!amduatd_list_contains(&list, "collection/daemon/edges/head") ||
!amduatd_list_contains(&list, "log/collection/daemon/edges/log/head") ||
!amduatd_list_sorted(&list)) {
fprintf(stderr, "unexpected empty-store roots list\n");
amduatd_space_roots_list_free(&list);
free(root);
return 1;
}
amduatd_space_roots_list_free(&list);
free(root);
return 0;
}
static int amduatd_test_cursor_roots(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_artifact_t none_artifact;
amduat_reference_t none_ref;
amduat_octets_t cursor_name = amduat_octets(NULL, 0u);
amduat_octets_t push_name = amduat_octets(NULL, 0u);
amduat_octets_t cursor_v2 = amduat_octets(NULL, 0u);
amduat_octets_t push_v2 = amduat_octets(NULL, 0u);
amduat_octets_t edges_collection = amduat_octets(NULL, 0u);
amduat_octets_t edges_index_head = amduat_octets(NULL, 0u);
char *collection_head = NULL;
char *collection_log_head = NULL;
amduatd_space_roots_list_t list;
bool swapped = false;
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 (!amduat_asl_none_artifact(&none_artifact)) {
fprintf(stderr, "failed to build none artifact\n");
free(root);
return 1;
}
if (amduat_asl_store_put(&store, none_artifact, &none_ref) !=
AMDUAT_ASL_STORE_OK) {
fprintf(stderr, "failed to store none artifact\n");
amduat_artifact_free(&none_artifact);
free(root);
return 1;
}
amduat_artifact_free(&none_artifact);
if (!amduatd_fed_cursor_pointer_name(&space, "peer-a", &cursor_name) ||
!amduatd_fed_push_cursor_pointer_name(&space, "peer-b", &push_name) ||
!amduatd_fed_cursor_pointer_name_v2(&space,
"peer-a",
"beta",
&cursor_v2) ||
!amduatd_fed_push_cursor_pointer_name_v2(&space,
"peer-b",
"beta",
&push_v2)) {
fprintf(stderr, "failed to build cursor names\n");
free(root);
return 1;
}
if (amduat_asl_pointer_cas(&pointer_store,
(const char *)cursor_name.data,
false,
NULL,
&none_ref,
&swapped) != AMDUAT_ASL_POINTER_OK || !swapped ||
amduat_asl_pointer_cas(&pointer_store,
(const char *)push_name.data,
false,
NULL,
&none_ref,
&swapped) != AMDUAT_ASL_POINTER_OK || !swapped ||
amduat_asl_pointer_cas(&pointer_store,
(const char *)cursor_v2.data,
false,
NULL,
&none_ref,
&swapped) != AMDUAT_ASL_POINTER_OK || !swapped ||
amduat_asl_pointer_cas(&pointer_store,
(const char *)push_v2.data,
false,
NULL,
&none_ref,
&swapped) != AMDUAT_ASL_POINTER_OK || !swapped) {
fprintf(stderr, "failed to seed cursor pointers\n");
amduat_octets_free(&cursor_name);
amduat_octets_free(&push_name);
amduat_octets_free(&cursor_v2);
amduat_octets_free(&push_v2);
free(root);
return 1;
}
if (!amduatd_space_roots_list(root, &pointer_store, &space, &list)) {
fprintf(stderr, "roots list failed\n");
amduat_octets_free(&cursor_name);
amduat_octets_free(&push_name);
amduat_octets_free(&cursor_v2);
amduat_octets_free(&push_v2);
free(root);
return 1;
}
if (!amduatd_space_edges_collection_name(&space, &edges_collection) ||
!amduatd_space_edges_index_head_name(&space, &edges_index_head) ||
!amduatd_build_collection_head_name(
(const char *)edges_collection.data, &collection_head) ||
!amduatd_build_collection_log_head_name(
(const char *)edges_collection.data, &collection_log_head)) {
fprintf(stderr, "failed to build static root names\n");
amduat_octets_free(&cursor_name);
amduat_octets_free(&push_name);
amduatd_space_roots_list_free(&list);
free(root);
return 1;
}
if (list.len != 7u ||
!amduatd_list_contains(&list, (const char *)cursor_name.data) ||
!amduatd_list_contains(&list, (const char *)push_name.data) ||
!amduatd_list_contains(&list, (const char *)cursor_v2.data) ||
!amduatd_list_contains(&list, (const char *)push_v2.data) ||
!amduatd_list_contains(&list, (const char *)edges_index_head.data) ||
!amduatd_list_contains(&list, collection_head) ||
!amduatd_list_contains(&list, collection_log_head) ||
!amduatd_list_sorted(&list)) {
fprintf(stderr, "unexpected cursor roots list\n");
amduat_octets_free(&cursor_name);
amduat_octets_free(&push_name);
amduat_octets_free(&cursor_v2);
amduat_octets_free(&push_v2);
amduat_octets_free(&edges_collection);
amduat_octets_free(&edges_index_head);
free(collection_head);
free(collection_log_head);
amduatd_space_roots_list_free(&list);
free(root);
return 1;
}
amduat_octets_free(&cursor_name);
amduat_octets_free(&push_name);
amduat_octets_free(&cursor_v2);
amduat_octets_free(&push_v2);
amduat_octets_free(&edges_collection);
amduat_octets_free(&edges_index_head);
free(collection_head);
free(collection_log_head);
amduatd_space_roots_list_free(&list);
free(root);
return 0;
}
int main(void) {
if (amduatd_test_empty_store() != 0) {
return 1;
}
if (amduatd_test_cursor_roots() != 0) {
return 1;
}
return 0;
}