241 lines
7.7 KiB
C
241 lines
7.7 KiB
C
#ifndef _POSIX_C_SOURCE
|
|
#define _POSIX_C_SOURCE 200809L
|
|
#endif
|
|
|
|
#include "amduatd_fed_cursor.h"
|
|
#include "amduatd_store.h"
|
|
|
|
#include "amduat/asl/asl_store_fs_meta.h"
|
|
#include "amduat/hash/asl1.h"
|
|
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
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-fed-cursor-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;
|
|
}
|
|
|
|
int main(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;
|
|
amduatd_fed_cursor_record_t cursor;
|
|
amduatd_fed_cursor_record_t fetched;
|
|
amduat_reference_t record_ref;
|
|
amduat_reference_t wrong_ref;
|
|
amduat_reference_t new_ref;
|
|
amduat_reference_t get_ref;
|
|
amduatd_fed_cursor_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);
|
|
expect(amduatd_fed_cursor_check_enabled(&fed_cfg) ==
|
|
AMDUATD_FED_CURSOR_ERR_DISABLED,
|
|
"disabled federation status");
|
|
|
|
amduatd_fed_cursor_record_init(&fetched);
|
|
memset(&get_ref, 0, sizeof(get_ref));
|
|
status = amduatd_fed_cursor_get(&store,
|
|
&pointer_store,
|
|
&space,
|
|
"peer-a",
|
|
&fetched,
|
|
&get_ref);
|
|
expect(status == AMDUATD_FED_CURSOR_ERR_NOT_FOUND, "empty cursor not found");
|
|
amduatd_fed_cursor_record_free(&fetched);
|
|
|
|
amduatd_fed_cursor_record_init(&cursor);
|
|
cursor.peer_key = strdup("peer-a");
|
|
cursor.space_id = strdup("alpha");
|
|
if (cursor.peer_key == NULL || cursor.space_id == NULL) {
|
|
fprintf(stderr, "failed to allocate cursor identifiers\n");
|
|
amduatd_fed_cursor_record_free(&cursor);
|
|
free(root);
|
|
return 1;
|
|
}
|
|
cursor.has_logseq = true;
|
|
cursor.last_logseq = 42u;
|
|
if (!amduatd_make_test_ref(0x11, &record_ref)) {
|
|
fprintf(stderr, "failed to make record ref\n");
|
|
amduatd_fed_cursor_record_free(&cursor);
|
|
free(root);
|
|
return 1;
|
|
}
|
|
cursor.has_record_ref = true;
|
|
cursor.last_record_ref = record_ref;
|
|
|
|
memset(&new_ref, 0, sizeof(new_ref));
|
|
status = amduatd_fed_cursor_cas_set(&store,
|
|
&pointer_store,
|
|
&space,
|
|
"peer-a",
|
|
NULL,
|
|
&cursor,
|
|
&new_ref);
|
|
expect(status == AMDUATD_FED_CURSOR_OK, "cursor set ok");
|
|
|
|
amduatd_fed_cursor_record_init(&fetched);
|
|
memset(&get_ref, 0, sizeof(get_ref));
|
|
status = amduatd_fed_cursor_get(&store,
|
|
&pointer_store,
|
|
&space,
|
|
"peer-a",
|
|
&fetched,
|
|
&get_ref);
|
|
expect(status == AMDUATD_FED_CURSOR_OK, "cursor get ok");
|
|
expect(strcmp(fetched.peer_key, "peer-a") == 0, "peer key match");
|
|
expect(fetched.space_id != NULL && strcmp(fetched.space_id, "alpha") == 0,
|
|
"space match");
|
|
expect(fetched.has_logseq && fetched.last_logseq == 42u, "logseq match");
|
|
expect(fetched.has_record_ref &&
|
|
amduat_reference_eq(fetched.last_record_ref, record_ref),
|
|
"record ref match");
|
|
expect(amduat_reference_eq(get_ref, new_ref), "pointer ref match");
|
|
amduatd_fed_cursor_record_free(&fetched);
|
|
amduat_reference_free(&get_ref);
|
|
|
|
if (!amduatd_make_test_ref(0x22, &wrong_ref)) {
|
|
fprintf(stderr, "failed to make wrong ref\n");
|
|
amduat_reference_free(&new_ref);
|
|
amduatd_fed_cursor_record_free(&cursor);
|
|
free(root);
|
|
return 1;
|
|
}
|
|
status = amduatd_fed_cursor_cas_set(&store,
|
|
&pointer_store,
|
|
&space,
|
|
"peer-a",
|
|
&wrong_ref,
|
|
&cursor,
|
|
NULL);
|
|
expect(status == AMDUATD_FED_CURSOR_ERR_CONFLICT, "cursor cas conflict");
|
|
amduat_reference_free(&wrong_ref);
|
|
|
|
amduatd_fed_cursor_record_free(&cursor);
|
|
amduat_reference_free(&new_ref);
|
|
|
|
{
|
|
amduat_octets_t name = amduat_octets(NULL, 0u);
|
|
bool ok = amduatd_fed_cursor_pointer_name(&space,
|
|
"bad peer",
|
|
&name);
|
|
expect(!ok, "peer validation rejects invalid key");
|
|
amduat_octets_free(&name);
|
|
}
|
|
|
|
{
|
|
amduat_octets_t name = amduat_octets(NULL, 0u);
|
|
bool ok = amduatd_fed_cursor_pointer_name_v2(&space,
|
|
"peer-a",
|
|
"beta",
|
|
&name);
|
|
expect(ok, "v2 cursor pointer name ok");
|
|
expect(strcmp((const char *)name.data,
|
|
"space/alpha/fed/cursor/peer-a/beta/head") == 0,
|
|
"v2 cursor pointer name matches");
|
|
amduat_octets_free(&name);
|
|
}
|
|
|
|
{
|
|
amduat_octets_t name = amduat_octets(NULL, 0u);
|
|
bool ok = amduatd_fed_push_cursor_pointer_name_v2(&space,
|
|
"peer-a",
|
|
"beta",
|
|
&name);
|
|
expect(ok, "v2 push cursor pointer name ok");
|
|
expect(strcmp((const char *)name.data,
|
|
"space/alpha/fed/push_cursor/peer-a/beta/head") == 0,
|
|
"v2 push cursor pointer name matches");
|
|
amduat_octets_free(&name);
|
|
}
|
|
|
|
{
|
|
amduat_octets_t name = amduat_octets(NULL, 0u);
|
|
bool ok = amduatd_fed_cursor_pointer_name_v2(&space,
|
|
"peer-a",
|
|
"bad/space",
|
|
&name);
|
|
expect(!ok, "remote space validation rejects invalid id");
|
|
amduat_octets_free(&name);
|
|
}
|
|
|
|
free(root);
|
|
return failures == 0 ? 0 : 1;
|
|
}
|