Interaction Trees in Zig and simple benchmarks
This commit is contained in:
@@ -51,6 +51,68 @@ int main(void) {
|
||||
}
|
||||
printf("PASS: kernel loaded (root=%u)\n", kernel_root);
|
||||
|
||||
/* Test: tree inspection primitives */
|
||||
uint32_t l = arb_leaf(ctx);
|
||||
uint32_t s = arb_stem(ctx, l);
|
||||
uint32_t f = arb_fork(ctx, s, l);
|
||||
uint32_t a = arb_app(ctx, f, s);
|
||||
|
||||
if (!arb_is_leaf(ctx, l)) {
|
||||
fprintf(stderr, "FAIL: is_leaf on leaf\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
if (arb_is_leaf(ctx, s)) {
|
||||
fprintf(stderr, "FAIL: is_leaf on stem should be false\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
if (!arb_is_stem(ctx, s)) {
|
||||
fprintf(stderr, "FAIL: is_stem on stem\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
if (!arb_is_fork(ctx, f)) {
|
||||
fprintf(stderr, "FAIL: is_fork on fork\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
if (!arb_is_app(ctx, a)) {
|
||||
fprintf(stderr, "FAIL: is_app on app\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t child;
|
||||
if (!arb_get_stem_child(ctx, s, &child) || child != l) {
|
||||
fprintf(stderr, "FAIL: get_stem_child\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t left, right;
|
||||
if (!arb_get_fork_children(ctx, f, &left, &right) || left != s || right != l) {
|
||||
fprintf(stderr, "FAIL: get_fork_children\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t func, arg;
|
||||
if (!arb_get_app_func_arg(ctx, a, &func, &arg) || func != f || arg != s) {
|
||||
fprintf(stderr, "FAIL: get_app_func_arg\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Invalid index should return 0 */
|
||||
if (arb_is_leaf(ctx, 999999)) {
|
||||
fprintf(stderr, "FAIL: is_leaf on invalid index should be false\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("PASS: tree inspection primitives\n");
|
||||
|
||||
arboricx_free(ctx);
|
||||
printf("\nAll C ABI tests passed.\n");
|
||||
return 0;
|
||||
|
||||
223
ext/zig/tests/io_protocol_test.c
Normal file
223
ext/zig/tests/io_protocol_test.c
Normal file
@@ -0,0 +1,223 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "arboricx.h"
|
||||
|
||||
int main(void) {
|
||||
arb_ctx_t* ctx = arboricx_init();
|
||||
if (!ctx) {
|
||||
fprintf(stderr, "Failed to initialize Arboricx context\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Test: construct and verify pure action = Fork 0 Leaf */
|
||||
uint32_t leaf = arb_leaf(ctx);
|
||||
uint32_t zero = arb_of_number(ctx, 0);
|
||||
uint32_t pure_action = arb_fork(ctx, zero, leaf);
|
||||
|
||||
if (!arb_is_fork(ctx, pure_action)) {
|
||||
fprintf(stderr, "FAIL: pure action should be fork\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t tag, payload;
|
||||
if (!arb_get_fork_children(ctx, pure_action, &tag, &payload) ||
|
||||
tag != zero || payload != leaf) {
|
||||
fprintf(stderr, "FAIL: pure action children mismatch\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint64_t tag_num;
|
||||
if (!arb_to_number(ctx, tag, &tag_num) || tag_num != 0) {
|
||||
fprintf(stderr, "FAIL: pure action tag should be 0\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
printf("PASS: pure action shape\n");
|
||||
|
||||
/* Test: construct and verify bind action = Fork 1 (Fork left k) */
|
||||
uint32_t one = arb_of_number(ctx, 1);
|
||||
uint32_t left = arb_fork(ctx, zero, leaf); /* pure Leaf */
|
||||
uint32_t k = arb_fork(ctx, leaf, leaf); /* identity as Fork Leaf Leaf */
|
||||
uint32_t bind_pair = arb_fork(ctx, left, k);
|
||||
uint32_t bind_action = arb_fork(ctx, one, bind_pair);
|
||||
|
||||
if (!arb_get_fork_children(ctx, bind_action, &tag, &payload) ||
|
||||
!arb_to_number(ctx, tag, &tag_num) || tag_num != 1) {
|
||||
fprintf(stderr, "FAIL: bind action tag should be 1\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t bind_left, bind_k;
|
||||
if (!arb_get_fork_children(ctx, payload, &bind_left, &bind_k) ||
|
||||
bind_left != left || bind_k != k) {
|
||||
fprintf(stderr, "FAIL: bind payload should be Fork left k\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
printf("PASS: bind action shape\n");
|
||||
|
||||
/* Test: construct and verify IO sentinel = Fork "tricuIO" (Fork 1 action) */
|
||||
uint32_t sentinel_str = arb_of_string(ctx, "tricuIO");
|
||||
uint32_t version = arb_of_number(ctx, 1);
|
||||
uint32_t version_action_pair = arb_fork(ctx, version, pure_action);
|
||||
uint32_t io_sentinel = arb_fork(ctx, sentinel_str, version_action_pair);
|
||||
|
||||
if (!arb_is_fork(ctx, io_sentinel)) {
|
||||
fprintf(stderr, "FAIL: IO sentinel should be fork\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t sent_left, sent_right;
|
||||
if (!arb_get_fork_children(ctx, io_sentinel, &sent_left, &sent_right)) {
|
||||
fprintf(stderr, "FAIL: get_fork_children on IO sentinel\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Verify sentinel string */
|
||||
uint8_t* decoded_sentinel;
|
||||
size_t decoded_len;
|
||||
if (!arb_to_string(ctx, sent_left, &decoded_sentinel, &decoded_len) ||
|
||||
decoded_len != 7 || memcmp(decoded_sentinel, "tricuIO", 7) != 0) {
|
||||
fprintf(stderr, "FAIL: IO sentinel string mismatch\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
arboricx_free_buf(ctx, decoded_sentinel, decoded_len);
|
||||
|
||||
/* Verify version = 1 and action = pure */
|
||||
uint32_t ver, act;
|
||||
if (!arb_get_fork_children(ctx, sent_right, &ver, &act) ||
|
||||
!arb_to_number(ctx, ver, &tag_num) || tag_num != 1 ||
|
||||
act != pure_action) {
|
||||
fprintf(stderr, "FAIL: IO sentinel version/action mismatch\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
printf("PASS: IO sentinel shape\n");
|
||||
|
||||
/* Test: putStr action = Fork 10 string */
|
||||
uint32_t ten = arb_of_number(ctx, 10);
|
||||
uint32_t msg = arb_of_string(ctx, "hello");
|
||||
uint32_t putStr_action = arb_fork(ctx, ten, msg);
|
||||
|
||||
if (!arb_get_fork_children(ctx, putStr_action, &tag, &payload) ||
|
||||
!arb_to_number(ctx, tag, &tag_num) || tag_num != 10) {
|
||||
fprintf(stderr, "FAIL: putStr tag should be 10\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
printf("PASS: putStr action shape\n");
|
||||
|
||||
/* Test: getLine action = Fork 11 Leaf */
|
||||
uint32_t eleven = arb_of_number(ctx, 11);
|
||||
uint32_t getLine_action = arb_fork(ctx, eleven, leaf);
|
||||
|
||||
if (!arb_get_fork_children(ctx, getLine_action, &tag, &payload) ||
|
||||
!arb_to_number(ctx, tag, &tag_num) || tag_num != 11 ||
|
||||
payload != leaf) {
|
||||
fprintf(stderr, "FAIL: getLine tag should be 11 with Leaf payload\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
printf("PASS: getLine action shape\n");
|
||||
|
||||
/* Test: readFile action = Fork 20 path */
|
||||
uint32_t twenty = arb_of_number(ctx, 20);
|
||||
uint32_t path = arb_of_string(ctx, "/tmp/test.txt");
|
||||
uint32_t readFile_action = arb_fork(ctx, twenty, path);
|
||||
|
||||
if (!arb_get_fork_children(ctx, readFile_action, &tag, &payload) ||
|
||||
!arb_to_number(ctx, tag, &tag_num) || tag_num != 20) {
|
||||
fprintf(stderr, "FAIL: readFile tag should be 20\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
printf("PASS: readFile action shape\n");
|
||||
|
||||
/* Test: writeFile action = Fork 21 (Fork path contents) */
|
||||
uint32_t twenty_one = arb_of_number(ctx, 21);
|
||||
uint32_t contents = arb_of_string(ctx, "data");
|
||||
uint32_t write_pair = arb_fork(ctx, path, contents);
|
||||
uint32_t writeFile_action = arb_fork(ctx, twenty_one, write_pair);
|
||||
|
||||
if (!arb_get_fork_children(ctx, writeFile_action, &tag, &payload) ||
|
||||
!arb_to_number(ctx, tag, &tag_num) || tag_num != 21) {
|
||||
fprintf(stderr, "FAIL: writeFile tag should be 21\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t wf_path, wf_contents;
|
||||
if (!arb_get_fork_children(ctx, payload, &wf_path, &wf_contents) ||
|
||||
wf_path != path || wf_contents != contents) {
|
||||
fprintf(stderr, "FAIL: writeFile payload should be Fork path contents\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
printf("PASS: writeFile action shape\n");
|
||||
|
||||
/* Test: ok result = Fork (Stem Leaf) (Fork val Leaf) */
|
||||
uint32_t stem_leaf = arb_stem(ctx, leaf);
|
||||
uint32_t val_pair = arb_fork(ctx, msg, leaf);
|
||||
uint32_t ok_result = arb_fork(ctx, stem_leaf, val_pair);
|
||||
|
||||
if (!arb_is_fork(ctx, ok_result)) {
|
||||
fprintf(stderr, "FAIL: ok result should be fork\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t ok_tag, ok_rest;
|
||||
if (!arb_get_fork_children(ctx, ok_result, &ok_tag, &ok_rest) ||
|
||||
!arb_is_stem(ctx, ok_tag)) {
|
||||
fprintf(stderr, "FAIL: ok result left should be stem\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t ok_val, ok_leaf;
|
||||
if (!arb_get_fork_children(ctx, ok_rest, &ok_val, &ok_leaf) ||
|
||||
ok_val != msg || ok_leaf != leaf) {
|
||||
fprintf(stderr, "FAIL: ok result right should be Fork val Leaf\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
printf("PASS: ok result shape\n");
|
||||
|
||||
/* Test: err result = Fork Leaf (Fork code Leaf) */
|
||||
uint32_t err_code = arb_of_number(ctx, 42);
|
||||
uint32_t err_pair = arb_fork(ctx, err_code, leaf);
|
||||
uint32_t err_result = arb_fork(ctx, leaf, err_pair);
|
||||
|
||||
if (!arb_is_fork(ctx, err_result)) {
|
||||
fprintf(stderr, "FAIL: err result should be fork\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t err_tag, err_rest;
|
||||
if (!arb_get_fork_children(ctx, err_result, &err_tag, &err_rest) ||
|
||||
!arb_is_leaf(ctx, err_tag)) {
|
||||
fprintf(stderr, "FAIL: err result left should be leaf\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t err_c, err_l;
|
||||
if (!arb_get_fork_children(ctx, err_rest, &err_c, &err_l) ||
|
||||
err_c != err_code || err_l != leaf) {
|
||||
fprintf(stderr, "FAIL: err result right should be Fork code Leaf\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
printf("PASS: err result shape\n");
|
||||
|
||||
arboricx_free(ctx);
|
||||
printf("\nAll IO protocol tests passed.\n");
|
||||
return 0;
|
||||
}
|
||||
217
ext/zig/tests/io_run_test.c
Normal file
217
ext/zig/tests/io_run_test.c
Normal file
@@ -0,0 +1,217 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "arboricx.h"
|
||||
|
||||
static uint32_t make_pure(arb_ctx_t* ctx, uint32_t val) {
|
||||
uint32_t zero = arb_of_number(ctx, 0);
|
||||
return arb_fork(ctx, zero, val);
|
||||
}
|
||||
|
||||
static uint32_t make_io_sentinel(arb_ctx_t* ctx, uint32_t action) {
|
||||
uint32_t sentinel = arb_of_string(ctx, "tricuIO");
|
||||
uint32_t version = arb_of_number(ctx, 1);
|
||||
uint32_t version_action = arb_fork(ctx, version, action);
|
||||
return arb_fork(ctx, sentinel, version_action);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
arb_ctx_t* ctx = arboricx_init();
|
||||
if (!ctx) {
|
||||
fprintf(stderr, "Failed to initialize Arboricx context\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
arb_io_perms_t perms = { 0, 0 };
|
||||
|
||||
/* Test 1: pure "hello" wrapped in IO sentinel */
|
||||
{
|
||||
uint32_t hello = arb_of_string(ctx, "hello");
|
||||
uint32_t pure_hello = make_pure(ctx, hello);
|
||||
uint32_t program = make_io_sentinel(ctx, pure_hello);
|
||||
|
||||
uint32_t result = arb_run_io(ctx, program, &perms);
|
||||
if (result == 0) {
|
||||
fprintf(stderr, "FAIL: pure hello returned 0\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t* decoded;
|
||||
size_t decoded_len;
|
||||
if (!arb_to_string(ctx, result, &decoded, &decoded_len) ||
|
||||
decoded_len != 5 || memcmp(decoded, "hello", 5) != 0) {
|
||||
fprintf(stderr, "FAIL: pure hello result mismatch\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
arboricx_free_buf(ctx, decoded, decoded_len);
|
||||
printf("PASS: pure hello\n");
|
||||
}
|
||||
|
||||
/* Test 2: bind (pure "a") (\_ : pure "done") */
|
||||
{
|
||||
uint32_t a = arb_of_string(ctx, "a");
|
||||
uint32_t done = arb_of_string(ctx, "done");
|
||||
uint32_t pure_a = make_pure(ctx, a);
|
||||
uint32_t pure_done = make_pure(ctx, done);
|
||||
|
||||
/* K pure_done = Fork Leaf pure_done */
|
||||
uint32_t k = arb_fork(ctx, arb_leaf(ctx), pure_done);
|
||||
uint32_t bind_pair = arb_fork(ctx, pure_a, k);
|
||||
uint32_t one = arb_of_number(ctx, 1);
|
||||
uint32_t bind_action = arb_fork(ctx, one, bind_pair);
|
||||
uint32_t program = make_io_sentinel(ctx, bind_action);
|
||||
|
||||
uint32_t result = arb_run_io(ctx, program, &perms);
|
||||
if (result == 0) {
|
||||
fprintf(stderr, "FAIL: bind returned 0\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t* decoded;
|
||||
size_t decoded_len;
|
||||
if (!arb_to_string(ctx, result, &decoded, &decoded_len) ||
|
||||
decoded_len != 4 || memcmp(decoded, "done", 4) != 0) {
|
||||
fprintf(stderr, "FAIL: bind result mismatch\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
arboricx_free_buf(ctx, decoded, decoded_len);
|
||||
printf("PASS: bind pure\n");
|
||||
}
|
||||
|
||||
/* Test 3: putStr "test" (no permissions needed) */
|
||||
{
|
||||
uint32_t test = arb_of_string(ctx, "test");
|
||||
uint32_t ten = arb_of_number(ctx, 10);
|
||||
uint32_t putStr_action = arb_fork(ctx, ten, test);
|
||||
uint32_t program = make_io_sentinel(ctx, putStr_action);
|
||||
|
||||
printf("EXPECT: test\n");
|
||||
uint32_t result = arb_run_io(ctx, program, &perms);
|
||||
if (result == 0) {
|
||||
fprintf(stderr, "FAIL: putStr returned 0\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
if (!arb_is_leaf(ctx, result)) {
|
||||
fprintf(stderr, "FAIL: putStr should return Leaf\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
printf("PASS: putStr\n");
|
||||
}
|
||||
|
||||
/* Test 4: readFile without permission returns err */
|
||||
{
|
||||
uint32_t path = arb_of_string(ctx, "/etc/passwd");
|
||||
uint32_t twenty = arb_of_number(ctx, 20);
|
||||
uint32_t readFile_action = arb_fork(ctx, twenty, path);
|
||||
uint32_t program = make_io_sentinel(ctx, readFile_action);
|
||||
|
||||
uint32_t result = arb_run_io(ctx, program, &perms);
|
||||
if (result == 0) {
|
||||
fprintf(stderr, "FAIL: readFile denied returned 0\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Should be an err result: Fork Leaf (Fork code Leaf) */
|
||||
uint32_t left, right;
|
||||
if (!arb_get_fork_children(ctx, result, &left, &right) ||
|
||||
!arb_is_leaf(ctx, left)) {
|
||||
fprintf(stderr, "FAIL: readFile denied should be err result\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t code, rest;
|
||||
if (!arb_get_fork_children(ctx, right, &code, &rest) ||
|
||||
!arb_is_leaf(ctx, rest)) {
|
||||
fprintf(stderr, "FAIL: readFile denied err shape mismatch\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint64_t code_num;
|
||||
if (!arb_to_number(ctx, code, &code_num) || code_num != 20) {
|
||||
fprintf(stderr, "FAIL: readFile denied code should be 20, got %llu\n",
|
||||
(unsigned long long)code_num);
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
printf("PASS: readFile denied\n");
|
||||
}
|
||||
|
||||
/* Test 5: readFile with permission succeeds */
|
||||
{
|
||||
/* Create a temp file first */
|
||||
const char* tmp = "/tmp/tricu_io_test.txt";
|
||||
FILE* f = fopen(tmp, "w");
|
||||
if (!f) {
|
||||
fprintf(stderr, "FAIL: could not create temp file\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
fprintf(f, "hi");
|
||||
fclose(f);
|
||||
|
||||
arb_io_perms_t unsafe_perms = { 1, 0 };
|
||||
uint32_t path = arb_of_string(ctx, tmp);
|
||||
uint32_t twenty = arb_of_number(ctx, 20);
|
||||
uint32_t readFile_action = arb_fork(ctx, twenty, path);
|
||||
uint32_t program = make_io_sentinel(ctx, readFile_action);
|
||||
|
||||
uint32_t result = arb_run_io(ctx, program, &unsafe_perms);
|
||||
if (result == 0) {
|
||||
fprintf(stderr, "FAIL: readFile allowed returned 0\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Should be ok result: Fork (Stem Leaf) (Fork val Leaf) */
|
||||
uint32_t ok_tag, ok_rest;
|
||||
if (!arb_get_fork_children(ctx, result, &ok_tag, &ok_rest) ||
|
||||
!arb_is_stem(ctx, ok_tag)) {
|
||||
fprintf(stderr, "FAIL: readFile allowed should be ok result\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t val, leaf;
|
||||
if (!arb_get_fork_children(ctx, ok_rest, &val, &leaf) ||
|
||||
!arb_is_leaf(ctx, leaf)) {
|
||||
fprintf(stderr, "FAIL: readFile allowed ok shape mismatch\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t* decoded;
|
||||
size_t decoded_len;
|
||||
if (!arb_to_string(ctx, val, &decoded, &decoded_len) ||
|
||||
decoded_len != 2 || memcmp(decoded, "hi", 2) != 0) {
|
||||
fprintf(stderr, "FAIL: readFile allowed contents mismatch\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
arboricx_free_buf(ctx, decoded, decoded_len);
|
||||
printf("PASS: readFile allowed\n");
|
||||
}
|
||||
|
||||
/* Test 6: invalid sentinel returns 0 */
|
||||
{
|
||||
uint32_t bad = arb_fork(ctx, arb_leaf(ctx), arb_leaf(ctx));
|
||||
uint32_t result = arb_run_io(ctx, bad, &perms);
|
||||
if (result != 0) {
|
||||
fprintf(stderr, "FAIL: invalid sentinel should return 0\n");
|
||||
arboricx_free(ctx);
|
||||
return 1;
|
||||
}
|
||||
printf("PASS: invalid sentinel\n");
|
||||
}
|
||||
|
||||
arboricx_free(ctx);
|
||||
printf("\nAll IO run tests passed.\n");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user