handles_test.c (3203B)
1 #include "arboricx.h" 2 #include <assert.h> 3 #include <stdio.h> 4 #include <string.h> 5 6 #define OK(call) assert((call) == ARB_OK) 7 8 int main(void) { 9 assert(arb_abi_version() == 2); 10 arb_ctx_t *ctx = arboricx_init(), *other = arboricx_init(); 11 assert(ctx && other); 12 assert(arb_set_gc_policy(ctx, 0, 1) == ARB_INVALID_DATA); 13 assert(arb_set_gc_policy(ctx, 1, 0) == ARB_INVALID_DATA); 14 OK(arb_set_gc_policy(ctx, 1, 1)); /* stress safepoints, including codecs */ 15 arb_handle_t leaf, alias, stem, child, app, result; 16 OK(arb_leaf(ctx, &leaf)); 17 OK(arb_retain(ctx, leaf, &alias)); 18 assert(leaf != alias); 19 OK(arb_stem(ctx, leaf, &stem)); 20 OK(arb_release(ctx, leaf)); 21 assert(arb_release(ctx, leaf) == ARB_INVALID_HANDLE); 22 arb_handle_t untouched = 123; 23 assert(arb_stem(ctx, leaf, &untouched) == ARB_INVALID_HANDLE); 24 assert(untouched == 123); 25 assert(arb_retain(other, alias, &untouched) == ARB_INVALID_HANDLE); 26 assert(untouched == 123); 27 OK(arb_collect(ctx)); 28 int yes; 29 OK(arb_is_leaf(ctx, alias, &yes)); assert(yes); 30 OK(arb_get_stem_child(ctx, stem, &child)); 31 OK(arb_release(ctx, stem)); 32 OK(arb_release(ctx, alias)); 33 OK(arb_collect(ctx)); 34 OK(arb_is_leaf(ctx, child, &yes)); assert(yes); 35 36 OK(arb_app(ctx, child, child, &app)); 37 assert(arb_reduce(ctx, app, 0, &untouched) == ARB_FUEL_EXHAUSTED); 38 assert(untouched == 123); 39 OK(arb_reduce(ctx, app, 1, &result)); 40 OK(arb_is_stem(ctx, app, &yes)); assert(yes); /* update visible to alias */ 41 OK(arb_release(ctx, app)); 42 OK(arb_collect(ctx)); 43 OK(arb_is_stem(ctx, result, &yes)); assert(yes); 44 arb_handle_t a = 123, b = 456; 45 assert(arb_get_fork_children(ctx, result, &a, &b) == ARB_TYPE_MISMATCH); 46 assert(a == 123 && b == 456); 47 OK(arb_release(ctx, result)); 48 OK(arb_release(ctx, child)); 49 50 /* Released slot reuse must never resurrect a stale generation. */ 51 for (int i = 0; i < 10000; ++i) { 52 OK(arb_leaf(ctx, &a)); 53 assert(a != leaf); 54 assert(arb_retain(ctx, leaf, &untouched) == ARB_INVALID_HANDLE); 55 OK(arb_release(ctx, a)); 56 } 57 OK(arb_collect(ctx)); 58 59 /* A nested selected result retains only its live spine; releasing inputs 60 and collecting repeatedly must not damage the eventual result. */ 61 OK(arb_leaf(ctx, &leaf)); 62 OK(arb_of_string(ctx, "survives collection", &a)); 63 for (int i = 0; i < 10000; ++i) { 64 OK(arb_fork(ctx, leaf, a, &b)); 65 OK(arb_release(ctx, a)); 66 OK(arb_app(ctx, b, leaf, &a)); 67 OK(arb_release(ctx, b)); 68 if (i % 1000 == 0) OK(arb_collect(ctx)); 69 } 70 OK(arb_reduce(ctx, a, 100000, &result)); 71 OK(arb_release(ctx, a)); 72 OK(arb_collect(ctx)); 73 uint8_t *bytes; size_t len; 74 OK(arb_to_string(ctx, result, &bytes, &len)); 75 assert(len == strlen("survives collection")); 76 assert(memcmp(bytes, "survives collection", len) == 0); 77 arboricx_free_buf(ctx, bytes, len); 78 OK(arb_release(ctx, result)); 79 OK(arb_release(ctx, leaf)); 80 OK(arb_collect(ctx)); 81 arboricx_free(other); 82 arboricx_free(ctx); 83 puts("Owned handles, stale/cross-context rejection, in-place evaluation and GC passed"); 84 }