Add tgk store fs adapter and tests
This commit is contained in:
parent
257280934f
commit
05baf8e847
|
|
@ -251,6 +251,16 @@ target_link_libraries(amduat_test_tgk_store_mem
|
|||
)
|
||||
add_test(NAME tgk_store_mem COMMAND amduat_test_tgk_store_mem)
|
||||
|
||||
add_executable(amduat_test_tgk_store_fs tests/tgk/test_tgk_store_fs.c)
|
||||
target_include_directories(amduat_test_tgk_store_fs
|
||||
PRIVATE ${AMDUAT_INTERNAL_DIR}
|
||||
PRIVATE ${AMDUAT_INCLUDE_DIR}
|
||||
)
|
||||
target_link_libraries(amduat_test_tgk_store_fs
|
||||
PRIVATE amduat_tgk_store_fs
|
||||
)
|
||||
add_test(NAME tgk_store_fs COMMAND amduat_test_tgk_store_fs)
|
||||
|
||||
add_executable(amduat_test_tgk_prov tests/tgk/test_tgk_prov.c)
|
||||
target_include_directories(amduat_test_tgk_prov
|
||||
PRIVATE ${AMDUAT_INTERNAL_DIR}
|
||||
|
|
|
|||
|
|
@ -3,4 +3,50 @@
|
|||
|
||||
/* Filesystem-backed TGK store adapter public API. */
|
||||
|
||||
#include "amduat/asl/asl_store_fs.h"
|
||||
#include "amduat/asl/store.h"
|
||||
#include "amduat/format/ref.h"
|
||||
#include "amduat/tgk/store.h"
|
||||
#include "amduat/tgk/tgk_store_mem.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Manifest contract:
|
||||
* - AMDUAT_FORMAT_REF_HEX: ASCII hex tokens of ASL1 ReferenceBytes,
|
||||
* separated by whitespace.
|
||||
* - AMDUAT_FORMAT_REF_BYTES: raw concatenation of ASL1 ReferenceBytes
|
||||
* (hash_id big-endian + digest). */
|
||||
typedef struct {
|
||||
amduat_tgk_store_mem_t mem;
|
||||
amduat_tgk_store_mem_artifact_t *artifacts;
|
||||
size_t artifacts_len;
|
||||
} amduat_tgk_store_fs_t;
|
||||
|
||||
bool amduat_tgk_store_fs_init(amduat_tgk_store_fs_t *fs,
|
||||
amduat_tgk_store_config_t config,
|
||||
const char *manifest_path,
|
||||
amduat_format_ref_format_t manifest_format,
|
||||
amduat_asl_store_t *asl_store);
|
||||
|
||||
bool amduat_tgk_store_fs_init_with_asl_fs(
|
||||
amduat_tgk_store_fs_t *fs,
|
||||
amduat_tgk_store_config_t config,
|
||||
const char *manifest_path,
|
||||
amduat_format_ref_format_t manifest_format,
|
||||
amduat_asl_store_config_t asl_config,
|
||||
const char *asl_root_path);
|
||||
|
||||
void amduat_tgk_store_fs_free(amduat_tgk_store_fs_t *fs);
|
||||
|
||||
amduat_tgk_store_ops_t amduat_tgk_store_fs_ops(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* AMDUAT_TGK_TGK_STORE_FS_H */
|
||||
|
|
|
|||
|
|
@ -1,3 +1,268 @@
|
|||
#include "amduat/tgk/tgk_store_fs.h"
|
||||
|
||||
/* TODO: implement filesystem-backed TGK store adapter. */
|
||||
#include "amduat/asl/io.h"
|
||||
#include "amduat/asl/ref_io.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static void amduat_tgk_store_fs_reference_free(amduat_reference_t *ref) {
|
||||
if (ref == NULL) {
|
||||
return;
|
||||
}
|
||||
free((void *)ref->digest.data);
|
||||
ref->digest.data = NULL;
|
||||
ref->digest.len = 0;
|
||||
}
|
||||
|
||||
static void amduat_tgk_store_fs_artifact_bytes_free(
|
||||
amduat_tgk_store_mem_artifact_t *artifact) {
|
||||
if (artifact == NULL) {
|
||||
return;
|
||||
}
|
||||
free((void *)artifact->artifact.bytes.data);
|
||||
artifact->artifact.bytes.data = NULL;
|
||||
artifact->artifact.bytes.len = 0;
|
||||
artifact->artifact.has_type_tag = false;
|
||||
artifact->artifact.type_tag.tag_id = 0;
|
||||
}
|
||||
|
||||
static void amduat_tgk_store_fs_artifact_full_free(
|
||||
amduat_tgk_store_mem_artifact_t *artifact) {
|
||||
if (artifact == NULL) {
|
||||
return;
|
||||
}
|
||||
amduat_tgk_store_fs_artifact_bytes_free(artifact);
|
||||
amduat_tgk_store_fs_reference_free(&artifact->ref);
|
||||
}
|
||||
|
||||
static bool amduat_tgk_store_fs_load_manifest(
|
||||
const char *manifest_path,
|
||||
amduat_format_ref_format_t manifest_format,
|
||||
amduat_reference_t **out_refs,
|
||||
size_t *out_len) {
|
||||
uint8_t *bytes = NULL;
|
||||
size_t len = 0;
|
||||
bool ok;
|
||||
|
||||
if (out_refs == NULL || out_len == NULL || manifest_path == NULL) {
|
||||
return false;
|
||||
}
|
||||
*out_refs = NULL;
|
||||
*out_len = 0;
|
||||
|
||||
if (!amduat_asl_read_path(manifest_path, &bytes, &len)) {
|
||||
free(bytes);
|
||||
return false;
|
||||
}
|
||||
ok = amduat_asl_ref_list_parse(amduat_octets(bytes, len), manifest_format,
|
||||
out_refs, out_len);
|
||||
free(bytes);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static bool amduat_tgk_store_fs_get_config(void *ctx,
|
||||
amduat_tgk_store_config_t *out_config) {
|
||||
amduat_tgk_store_fs_t *fs = (amduat_tgk_store_fs_t *)ctx;
|
||||
amduat_tgk_store_ops_t mem_ops = amduat_tgk_store_mem_ops();
|
||||
|
||||
if (fs == NULL || mem_ops.get_config == NULL) {
|
||||
return false;
|
||||
}
|
||||
return mem_ops.get_config(&fs->mem, out_config);
|
||||
}
|
||||
|
||||
static amduat_tgk_graph_error_t amduat_tgk_store_fs_resolve_edge(
|
||||
void *ctx,
|
||||
amduat_reference_t ref,
|
||||
amduat_tgk_edge_body_t *out_body) {
|
||||
amduat_tgk_store_fs_t *fs = (amduat_tgk_store_fs_t *)ctx;
|
||||
amduat_tgk_store_ops_t mem_ops = amduat_tgk_store_mem_ops();
|
||||
|
||||
if (fs == NULL || mem_ops.resolve_edge == NULL) {
|
||||
return GS_ERR_UNSUPPORTED;
|
||||
}
|
||||
return mem_ops.resolve_edge(&fs->mem, ref, out_body);
|
||||
}
|
||||
|
||||
static bool amduat_tgk_store_fs_edges_from(
|
||||
void *ctx,
|
||||
amduat_reference_t node,
|
||||
amduat_tgk_edge_type_filter_t type_filter,
|
||||
amduat_tgk_graph_edge_view_list_t *out_edges) {
|
||||
amduat_tgk_store_fs_t *fs = (amduat_tgk_store_fs_t *)ctx;
|
||||
amduat_tgk_store_ops_t mem_ops = amduat_tgk_store_mem_ops();
|
||||
|
||||
if (fs == NULL || mem_ops.edges_from == NULL) {
|
||||
return false;
|
||||
}
|
||||
return mem_ops.edges_from(&fs->mem, node, type_filter, out_edges);
|
||||
}
|
||||
|
||||
static bool amduat_tgk_store_fs_edges_to(
|
||||
void *ctx,
|
||||
amduat_reference_t node,
|
||||
amduat_tgk_edge_type_filter_t type_filter,
|
||||
amduat_tgk_graph_edge_view_list_t *out_edges) {
|
||||
amduat_tgk_store_fs_t *fs = (amduat_tgk_store_fs_t *)ctx;
|
||||
amduat_tgk_store_ops_t mem_ops = amduat_tgk_store_mem_ops();
|
||||
|
||||
if (fs == NULL || mem_ops.edges_to == NULL) {
|
||||
return false;
|
||||
}
|
||||
return mem_ops.edges_to(&fs->mem, node, type_filter, out_edges);
|
||||
}
|
||||
|
||||
static bool amduat_tgk_store_fs_edges_incident(
|
||||
void *ctx,
|
||||
amduat_reference_t node,
|
||||
amduat_tgk_edge_type_filter_t type_filter,
|
||||
amduat_tgk_graph_edge_view_list_t *out_edges) {
|
||||
amduat_tgk_store_fs_t *fs = (amduat_tgk_store_fs_t *)ctx;
|
||||
amduat_tgk_store_ops_t mem_ops = amduat_tgk_store_mem_ops();
|
||||
|
||||
if (fs == NULL || mem_ops.edges_incident == NULL) {
|
||||
return false;
|
||||
}
|
||||
return mem_ops.edges_incident(&fs->mem, node, type_filter, out_edges);
|
||||
}
|
||||
|
||||
static bool amduat_tgk_store_fs_scan_edges(
|
||||
void *ctx,
|
||||
amduat_tgk_edge_type_filter_t type_filter,
|
||||
amduat_octets_t page_token,
|
||||
bool has_page_token,
|
||||
amduat_tgk_graph_scan_result_t *out_scan) {
|
||||
amduat_tgk_store_fs_t *fs = (amduat_tgk_store_fs_t *)ctx;
|
||||
amduat_tgk_store_ops_t mem_ops = amduat_tgk_store_mem_ops();
|
||||
|
||||
if (fs == NULL || mem_ops.scan_edges == NULL) {
|
||||
return false;
|
||||
}
|
||||
return mem_ops.scan_edges(&fs->mem, type_filter, page_token, has_page_token,
|
||||
out_scan);
|
||||
}
|
||||
|
||||
static bool amduat_tgk_store_fs_neighbors(
|
||||
void *ctx,
|
||||
amduat_reference_t node,
|
||||
amduat_tgk_edge_type_filter_t type_filter,
|
||||
amduat_tgk_graph_direction_t direction,
|
||||
amduat_tgk_node_list_t *out_nodes) {
|
||||
amduat_tgk_store_fs_t *fs = (amduat_tgk_store_fs_t *)ctx;
|
||||
amduat_tgk_store_ops_t mem_ops = amduat_tgk_store_mem_ops();
|
||||
|
||||
if (fs == NULL || mem_ops.neighbors == NULL) {
|
||||
return false;
|
||||
}
|
||||
return mem_ops.neighbors(&fs->mem, node, type_filter, direction, out_nodes);
|
||||
}
|
||||
|
||||
bool amduat_tgk_store_fs_init(amduat_tgk_store_fs_t *fs,
|
||||
amduat_tgk_store_config_t config,
|
||||
const char *manifest_path,
|
||||
amduat_format_ref_format_t manifest_format,
|
||||
amduat_asl_store_t *asl_store) {
|
||||
amduat_reference_t *refs = NULL;
|
||||
size_t refs_len = 0;
|
||||
amduat_tgk_store_mem_artifact_t *artifacts = NULL;
|
||||
size_t i;
|
||||
|
||||
if (fs == NULL || manifest_path == NULL || asl_store == NULL) {
|
||||
return false;
|
||||
}
|
||||
memset(fs, 0, sizeof(*fs));
|
||||
|
||||
if (!amduat_tgk_store_fs_load_manifest(manifest_path,
|
||||
manifest_format,
|
||||
&refs,
|
||||
&refs_len)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (refs_len != 0u) {
|
||||
artifacts = (amduat_tgk_store_mem_artifact_t *)calloc(
|
||||
refs_len, sizeof(*artifacts));
|
||||
if (artifacts == NULL) {
|
||||
amduat_asl_ref_list_free(refs, refs_len);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < refs_len; ++i) {
|
||||
amduat_asl_store_error_t err;
|
||||
artifacts[i].ref = refs[i];
|
||||
artifacts[i].artifact = amduat_artifact(amduat_octets(NULL, 0));
|
||||
err = amduat_asl_store_get(asl_store, refs[i], &artifacts[i].artifact);
|
||||
if (err != AMDUAT_ASL_STORE_OK) {
|
||||
size_t j;
|
||||
for (j = 0; j < i; ++j) {
|
||||
amduat_tgk_store_fs_artifact_bytes_free(&artifacts[j]);
|
||||
}
|
||||
amduat_asl_ref_list_free(refs, refs_len);
|
||||
free(artifacts);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
free(refs);
|
||||
fs->artifacts = artifacts;
|
||||
fs->artifacts_len = refs_len;
|
||||
|
||||
if (!amduat_tgk_store_mem_init(&fs->mem, config, fs->artifacts,
|
||||
fs->artifacts_len)) {
|
||||
amduat_tgk_store_fs_free(fs);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool amduat_tgk_store_fs_init_with_asl_fs(
|
||||
amduat_tgk_store_fs_t *fs,
|
||||
amduat_tgk_store_config_t config,
|
||||
const char *manifest_path,
|
||||
amduat_format_ref_format_t manifest_format,
|
||||
amduat_asl_store_config_t asl_config,
|
||||
const char *asl_root_path) {
|
||||
amduat_asl_store_fs_t asl_fs;
|
||||
amduat_asl_store_t store;
|
||||
|
||||
if (fs == NULL || manifest_path == NULL || asl_root_path == NULL) {
|
||||
return false;
|
||||
}
|
||||
if (!amduat_asl_store_fs_init(&asl_fs, asl_config, asl_root_path)) {
|
||||
return false;
|
||||
}
|
||||
amduat_asl_store_init(&store, asl_config, amduat_asl_store_fs_ops(), &asl_fs);
|
||||
return amduat_tgk_store_fs_init(fs, config, manifest_path, manifest_format,
|
||||
&store);
|
||||
}
|
||||
|
||||
void amduat_tgk_store_fs_free(amduat_tgk_store_fs_t *fs) {
|
||||
size_t i;
|
||||
|
||||
if (fs == NULL) {
|
||||
return;
|
||||
}
|
||||
amduat_tgk_store_mem_free(&fs->mem);
|
||||
for (i = 0; i < fs->artifacts_len; ++i) {
|
||||
amduat_tgk_store_fs_artifact_full_free(&fs->artifacts[i]);
|
||||
}
|
||||
free(fs->artifacts);
|
||||
fs->artifacts = NULL;
|
||||
fs->artifacts_len = 0;
|
||||
}
|
||||
|
||||
amduat_tgk_store_ops_t amduat_tgk_store_fs_ops(void) {
|
||||
amduat_tgk_store_ops_t ops;
|
||||
|
||||
memset(&ops, 0, sizeof(ops));
|
||||
ops.get_config = amduat_tgk_store_fs_get_config;
|
||||
ops.resolve_edge = amduat_tgk_store_fs_resolve_edge;
|
||||
ops.edges_from = amduat_tgk_store_fs_edges_from;
|
||||
ops.edges_to = amduat_tgk_store_fs_edges_to;
|
||||
ops.edges_incident = amduat_tgk_store_fs_edges_incident;
|
||||
ops.scan_edges = amduat_tgk_store_fs_scan_edges;
|
||||
ops.neighbors = amduat_tgk_store_fs_neighbors;
|
||||
return ops;
|
||||
}
|
||||
|
|
|
|||
392
tests/tgk/test_tgk_store_fs.c
Normal file
392
tests/tgk/test_tgk_store_fs.c
Normal file
|
|
@ -0,0 +1,392 @@
|
|||
#include "amduat/asl/asl_store_fs.h"
|
||||
#include "amduat/asl/ref_text.h"
|
||||
#include "amduat/enc/asl1_core.h"
|
||||
#include "amduat/enc/tgk1_edge.h"
|
||||
#include "amduat/hash/asl1.h"
|
||||
#include "amduat/tgk/store.h"
|
||||
#include "amduat/tgk/tgk_store_fs.h"
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void fill_digest(uint8_t *out, uint8_t value) {
|
||||
memset(out, value, 32);
|
||||
}
|
||||
|
||||
static amduat_reference_t make_ref(uint8_t value, uint8_t *storage) {
|
||||
fill_digest(storage, value);
|
||||
return amduat_reference(AMDUAT_HASH_ASL1_ID_SHA256,
|
||||
amduat_octets(storage, 32));
|
||||
}
|
||||
|
||||
static void free_ref(amduat_reference_t *ref) {
|
||||
if (ref == NULL) {
|
||||
return;
|
||||
}
|
||||
free((void *)ref->digest.data);
|
||||
ref->digest.data = NULL;
|
||||
ref->digest.len = 0;
|
||||
}
|
||||
|
||||
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_tgk_store_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 bool write_manifest(const char *path,
|
||||
const amduat_reference_t *refs,
|
||||
size_t refs_len) {
|
||||
FILE *stream;
|
||||
size_t i;
|
||||
|
||||
if (path == NULL || (refs_len != 0 && refs == NULL)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
stream = fopen(path, "wb");
|
||||
if (stream == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < refs_len; ++i) {
|
||||
char *hex = NULL;
|
||||
if (!amduat_asl_ref_encode_hex(refs[i], &hex)) {
|
||||
fclose(stream);
|
||||
return false;
|
||||
}
|
||||
if (fprintf(stream, "%s\n", hex) < 0) {
|
||||
free(hex);
|
||||
fclose(stream);
|
||||
return false;
|
||||
}
|
||||
free(hex);
|
||||
}
|
||||
|
||||
return fclose(stream) == 0;
|
||||
}
|
||||
|
||||
static int test_manifest_load(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[2];
|
||||
amduat_reference_t ref_edge1;
|
||||
amduat_reference_t ref_edge2;
|
||||
amduat_reference_t node_a;
|
||||
amduat_reference_t node_b;
|
||||
amduat_reference_t node_c;
|
||||
amduat_reference_t payload1;
|
||||
amduat_reference_t payload2;
|
||||
uint8_t digest_node_a[32];
|
||||
uint8_t digest_node_b[32];
|
||||
uint8_t digest_node_c[32];
|
||||
uint8_t digest_payload1[32];
|
||||
uint8_t digest_payload2[32];
|
||||
amduat_tgk_graph_edge_view_list_t edges;
|
||||
amduat_tgk_edge_body_t body;
|
||||
amduat_tgk_edge_body_t edge1;
|
||||
amduat_tgk_edge_body_t edge2;
|
||||
amduat_reference_t edge1_from[1];
|
||||
amduat_reference_t edge1_to[1];
|
||||
amduat_reference_t edge2_from[1];
|
||||
amduat_reference_t edge2_to[1];
|
||||
char *root = NULL;
|
||||
char *manifest_path = NULL;
|
||||
int exit_code = 1;
|
||||
bool fs_ready = false;
|
||||
|
||||
memset(&edges, 0, sizeof(edges));
|
||||
memset(&body, 0, sizeof(body));
|
||||
edge_bytes[0] = amduat_octets(NULL, 0);
|
||||
edge_bytes[1] = amduat_octets(NULL, 0);
|
||||
memset(&ref_edge1, 0, sizeof(ref_edge1));
|
||||
memset(&ref_edge2, 0, sizeof(ref_edge2));
|
||||
memset(&fs, 0, sizeof(fs));
|
||||
|
||||
root = make_temp_root();
|
||||
if (root == NULL) {
|
||||
fprintf(stderr, "temp root failed\n");
|
||||
goto cleanup;
|
||||
}
|
||||
if (!join_path(root, "manifest.txt", &manifest_path)) {
|
||||
fprintf(stderr, "manifest path 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, "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;
|
||||
|
||||
memset(&tgk_config, 0, sizeof(tgk_config));
|
||||
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;
|
||||
|
||||
node_a = make_ref(0xa1, digest_node_a);
|
||||
node_b = make_ref(0xb1, digest_node_b);
|
||||
node_c = make_ref(0xc1, digest_node_c);
|
||||
payload1 = make_ref(0xe1, digest_payload1);
|
||||
payload2 = make_ref(0xe2, digest_payload2);
|
||||
|
||||
memset(&edge1, 0, sizeof(edge1));
|
||||
edge1.type = 0x10;
|
||||
edge1_from[0] = node_a;
|
||||
edge1.from = edge1_from;
|
||||
edge1.from_len = 1;
|
||||
edge1_to[0] = node_b;
|
||||
edge1.to = edge1_to;
|
||||
edge1.to_len = 1;
|
||||
edge1.payload = payload1;
|
||||
|
||||
memset(&edge2, 0, sizeof(edge2));
|
||||
edge2.type = 0x10;
|
||||
edge2_from[0] = node_a;
|
||||
edge2.from = edge2_from;
|
||||
edge2.from_len = 1;
|
||||
edge2_to[0] = node_c;
|
||||
edge2.to = edge2_to;
|
||||
edge2.to_len = 1;
|
||||
edge2.payload = payload2;
|
||||
|
||||
if (!amduat_enc_tgk1_edge_encode_v1(&edge1, &edge_bytes[0]) ||
|
||||
!amduat_enc_tgk1_edge_encode_v1(&edge2, &edge_bytes[1])) {
|
||||
fprintf(stderr, "edge encode failed\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (amduat_asl_store_put(
|
||||
&asl_store,
|
||||
amduat_artifact_with_type(edge_bytes[0],
|
||||
amduat_type_tag(TYPE_TAG_TGK1_EDGE_V1)),
|
||||
&ref_edge1) != AMDUAT_ASL_STORE_OK ||
|
||||
amduat_asl_store_put(
|
||||
&asl_store,
|
||||
amduat_artifact_with_type(edge_bytes[1],
|
||||
amduat_type_tag(TYPE_TAG_TGK1_EDGE_V1)),
|
||||
&ref_edge2) != AMDUAT_ASL_STORE_OK) {
|
||||
fprintf(stderr, "asl store put failed\n");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
{
|
||||
amduat_reference_t refs[2];
|
||||
refs[0] = ref_edge1;
|
||||
refs[1] = ref_edge2;
|
||||
if (!write_manifest(manifest_path, refs, 2)) {
|
||||
fprintf(stderr, "manifest write failed\n");
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
if (!amduat_tgk_store_fs_init(&fs, tgk_config, manifest_path,
|
||||
AMDUAT_FORMAT_REF_HEX, &asl_store)) {
|
||||
fprintf(stderr, "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_resolve_edge(&store, ref_edge1, &body) != 0) {
|
||||
fprintf(stderr, "resolve_edge failed\n");
|
||||
goto cleanup;
|
||||
}
|
||||
if (body.type != 0x10 || body.from_len != 1 || body.to_len != 1 ||
|
||||
!amduat_reference_eq(body.from[0], node_a) ||
|
||||
!amduat_reference_eq(body.to[0], node_b)) {
|
||||
fprintf(stderr, "resolve_edge mismatch\n");
|
||||
amduat_tgk_edge_body_free(&body);
|
||||
goto cleanup;
|
||||
}
|
||||
amduat_tgk_edge_body_free(&body);
|
||||
memset(&body, 0, sizeof(body));
|
||||
|
||||
{
|
||||
amduat_tgk_edge_type_filter_t filter;
|
||||
amduat_tgk_edge_type_id_t types[1] = {0x10};
|
||||
size_t seen_b = 0;
|
||||
size_t seen_c = 0;
|
||||
size_t i;
|
||||
|
||||
filter.types = types;
|
||||
filter.types_len = 1;
|
||||
if (!amduat_tgk_store_edges_from(&store, node_a, filter, &edges)) {
|
||||
fprintf(stderr, "edges_from failed\n");
|
||||
goto cleanup;
|
||||
}
|
||||
if (edges.len != 2) {
|
||||
fprintf(stderr, "edges_from len mismatch\n");
|
||||
goto cleanup;
|
||||
}
|
||||
for (i = 0; i < edges.len; ++i) {
|
||||
const amduat_tgk_graph_edge_view_t *edge = &edges.edges[i];
|
||||
if (edge->body.type != 0x10 || edge->body.from_len != 1 ||
|
||||
edge->body.to_len != 1 ||
|
||||
!amduat_reference_eq(edge->body.from[0], node_a)) {
|
||||
fprintf(stderr, "edges_from body mismatch\n");
|
||||
goto cleanup;
|
||||
}
|
||||
if (amduat_reference_eq(edge->body.to[0], node_b)) {
|
||||
seen_b++;
|
||||
} else if (amduat_reference_eq(edge->body.to[0], node_c)) {
|
||||
seen_c++;
|
||||
} else {
|
||||
fprintf(stderr, "edges_from unexpected endpoint\n");
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
if (seen_b != 1 || seen_c != 1) {
|
||||
fprintf(stderr, "edges_from endpoints mismatch\n");
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
exit_code = 0;
|
||||
|
||||
cleanup:
|
||||
amduat_tgk_graph_edge_view_list_free(&edges);
|
||||
amduat_tgk_edge_body_free(&body);
|
||||
if (fs_ready) {
|
||||
amduat_tgk_store_fs_free(&fs);
|
||||
}
|
||||
free((void *)edge_bytes[0].data);
|
||||
free((void *)edge_bytes[1].data);
|
||||
free_ref(&ref_edge1);
|
||||
free_ref(&ref_edge2);
|
||||
free(manifest_path);
|
||||
if (root != NULL) {
|
||||
remove_tree(root);
|
||||
}
|
||||
free(root);
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
return test_manifest_load();
|
||||
}
|
||||
|
|
@ -21,6 +21,7 @@ typedef struct {
|
|||
amduat_reference_t ref_edge3;
|
||||
amduat_reference_t ref_edge_bad;
|
||||
amduat_reference_t ref_non_edge;
|
||||
amduat_reference_t ref_missing;
|
||||
amduat_reference_t node_a;
|
||||
amduat_reference_t node_b;
|
||||
amduat_reference_t node_c;
|
||||
|
|
@ -33,6 +34,7 @@ typedef struct {
|
|||
uint8_t digest_edge3[32];
|
||||
uint8_t digest_edge_bad[32];
|
||||
uint8_t digest_non_edge[32];
|
||||
uint8_t digest_missing[32];
|
||||
uint8_t digest_node_a[32];
|
||||
uint8_t digest_node_b[32];
|
||||
uint8_t digest_node_c[32];
|
||||
|
|
@ -105,6 +107,7 @@ static bool init_env(test_env_t *env) {
|
|||
env->ref_edge3 = make_ref(0x30, env->digest_edge3);
|
||||
env->ref_edge_bad = make_ref(0x40, env->digest_edge_bad);
|
||||
env->ref_non_edge = make_ref(0x50, env->digest_non_edge);
|
||||
env->ref_missing = make_ref(0x60, env->digest_missing);
|
||||
|
||||
env->node_a = make_ref(0xa1, env->digest_node_a);
|
||||
env->node_b = make_ref(0xb1, env->digest_node_b);
|
||||
|
|
@ -236,6 +239,65 @@ static int test_resolve_edge_not_edge(const test_env_t *env) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int test_resolve_edge_missing(const test_env_t *env) {
|
||||
amduat_tgk_edge_body_t body;
|
||||
amduat_tgk_graph_error_t err;
|
||||
|
||||
err = amduat_tgk_store_resolve_edge((amduat_tgk_store_t *)&env->store,
|
||||
env->ref_missing, &body);
|
||||
if (err != GS_ERR_ARTIFACT_ERROR) {
|
||||
fprintf(stderr, "resolve_edge missing mismatch: %d\n", err);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool make_ref_for_hash(amduat_hash_id_t hash_id,
|
||||
uint8_t value,
|
||||
amduat_reference_t *out_ref) {
|
||||
const amduat_hash_asl1_desc_t *desc;
|
||||
uint8_t *digest;
|
||||
|
||||
if (out_ref == NULL) {
|
||||
return false;
|
||||
}
|
||||
desc = amduat_hash_asl1_desc_lookup(hash_id);
|
||||
if (desc == NULL || desc->digest_len == 0) {
|
||||
return false;
|
||||
}
|
||||
digest = (uint8_t *)malloc(desc->digest_len);
|
||||
if (digest == NULL) {
|
||||
return false;
|
||||
}
|
||||
memset(digest, value, desc->digest_len);
|
||||
*out_ref = amduat_reference(hash_id, amduat_octets(digest, desc->digest_len));
|
||||
return true;
|
||||
}
|
||||
|
||||
static int test_resolve_edge_unsupported(const test_env_t *env) {
|
||||
amduat_reference_t ref;
|
||||
amduat_tgk_edge_body_t body;
|
||||
amduat_tgk_graph_error_t err;
|
||||
int exit_code = 1;
|
||||
|
||||
if (!make_ref_for_hash(0x0002, 0x6au, &ref)) {
|
||||
fprintf(stderr, "unsupported ref alloc failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
err = amduat_tgk_store_resolve_edge((amduat_tgk_store_t *)&env->store, ref,
|
||||
&body);
|
||||
if (err != GS_ERR_UNSUPPORTED) {
|
||||
fprintf(stderr, "resolve_edge unsupported mismatch: %d\n", err);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
exit_code = 0;
|
||||
cleanup:
|
||||
free_ref(&ref);
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
static int test_type_filter(const test_env_t *env) {
|
||||
amduat_tgk_edge_type_id_t types[1] = {0x10};
|
||||
amduat_tgk_edge_type_filter_t filter;
|
||||
|
|
@ -419,6 +481,8 @@ int main(void) {
|
|||
|
||||
if (test_resolve_edge_ok(&env) != 0 ||
|
||||
test_resolve_edge_not_edge(&env) != 0 ||
|
||||
test_resolve_edge_missing(&env) != 0 ||
|
||||
test_resolve_edge_unsupported(&env) != 0 ||
|
||||
test_type_filter(&env) != 0 ||
|
||||
test_ordering(&env) != 0 ||
|
||||
test_adjacency(&env) != 0 ||
|
||||
|
|
|
|||
Loading…
Reference in a new issue