tests.c (5957B)
1 #include "tricu.h" 2 #include <assert.h> 3 #include <string.h> 4 #include <signal.h> 5 static volatile sig_atomic_t observed_signal; 6 static void host_signal(int sig) { observed_signal = sig; } 7 8 /* Independent constructor-level oracles for all reduction rules. */ 9 static tricu_handle stem(tricu_context ctx, tricu_handle x) { 10 tricu_handle out; 11 assert(tricu_stem(ctx, x, &out) == TRICU_OK); 12 return out; 13 } 14 static tricu_handle make_fork(tricu_context ctx, tricu_handle a, tricu_handle b) { 15 tricu_handle out; 16 assert(tricu_fork(ctx, a, b, &out) == TRICU_OK); 17 return out; 18 } 19 static tricu_handle app(tricu_context ctx, tricu_handle a, tricu_handle b) { 20 tricu_handle out; 21 assert(tricu_apply(ctx, a, b, &out) == TRICU_OK); 22 return out; 23 } 24 static void same(tricu_context ctx, tricu_handle a, tricu_handle b) { 25 uint32_t ka, kb; 26 assert(tricu_kind(ctx, a, &ka) == TRICU_OK); 27 assert(tricu_kind(ctx, b, &kb) == TRICU_OK); 28 assert(ka == kb); 29 for (uint32_t i = 0; i < ka; ++i) { 30 tricu_handle ca, cb; 31 assert(tricu_child(ctx, a, i, &ca) == TRICU_OK); 32 assert(tricu_child(ctx, b, i, &cb) == TRICU_OK); 33 same(ctx, ca, cb); 34 assert(tricu_release(ctx, ca) == TRICU_OK); 35 assert(tricu_release(ctx, cb) == TRICU_OK); 36 } 37 } 38 static void core_rules(tricu_context ctx) { 39 tricu_handle t; 40 assert(tricu_leaf(ctx, &t) == TRICU_OK); 41 tricu_handle tt = stem(ctx, t), k = make_fork(ctx, t, t); 42 same(ctx, app(ctx, t, tt), stem(ctx, tt)); 43 same(ctx, app(ctx, tt, k), make_fork(ctx, t, k)); 44 same(ctx, app(ctx, make_fork(ctx, t, tt), k), tt); 45 /* S (K t) t (t t) = t (t (t t)) */ 46 same(ctx, app(ctx, make_fork(ctx, stem(ctx, k), t), tt), stem(ctx, stem(ctx, tt))); 47 tricu_handle triage = make_fork(ctx, make_fork(ctx, tt, k), k); 48 same(ctx, app(ctx, triage, t), tt); 49 same(ctx, app(ctx, triage, stem(ctx, tt)), t); 50 same(ctx, app(ctx, triage, make_fork(ctx, t, tt)), stem(ctx, tt)); 51 tricu_handle marker = 987; 52 assert(tricu_child(ctx, t, 0, &marker) == TRICU_TYPE_ERROR && marker == 987); 53 tricu_context other; 54 assert(tricu_context_new(&other) == TRICU_OK); 55 assert(tricu_retain(other, t, &marker) == TRICU_INVALID_HANDLE && marker == 987); 56 assert(tricu_retain(ctx, other, &marker) == TRICU_INVALID_HANDLE && marker == 987); 57 assert(tricu_context_free(other) == TRICU_OK); 58 assert(tricu_leaf(other, &marker) == TRICU_INVALID_CONTEXT && marker == 987); 59 const uint8_t bad_utf8[] = {0xc0, 0x80}; 60 assert(tricu_from_utf8(ctx, bad_utf8, 2, &marker) == TRICU_INVALID_DATA && marker == 987); 61 uint8_t input[256], *output; 62 size_t length; 63 for (size_t i = 0; i < sizeof input; ++i) input[i] = (uint8_t)i; 64 assert(tricu_from_bytes(ctx, input, sizeof input, &marker) == TRICU_OK); 65 assert(tricu_to_bytes(ctx, marker, &output, &length) == TRICU_OK); 66 assert(length == sizeof input && memcmp(input, output, length) == 0); 67 tricu_buffer_free(output); 68 const uint8_t unicode[] = {'x', 0, 0xc3, 0xa9, 0xf0, 0x9f, 0x8c, 0xb3, 0xef, 0xbb, 0xbf}; 69 assert(tricu_from_utf8(ctx, unicode, sizeof unicode, &marker) == TRICU_OK); 70 assert(tricu_to_utf8(ctx, marker, &output, &length) == TRICU_OK); 71 assert(length == sizeof unicode && memcmp(unicode, output, length) == 0); 72 tricu_buffer_free(output); 73 tricu_handle invalid; 74 assert(tricu_from_u64(ctx, 256, &invalid) == TRICU_OK); 75 invalid = make_fork(ctx, invalid, t); 76 uint8_t sentinel, *unchanged = &sentinel; 77 size_t unchanged_length = 987; 78 assert(tricu_to_bytes(ctx, invalid, &unchanged, &unchanged_length) == TRICU_TYPE_ERROR); 79 assert(unchanged == &sentinel && unchanged_length == 987); 80 assert(tricu_from_u64(ctx, 0xd800, &invalid) == TRICU_OK); 81 invalid = make_fork(ctx, invalid, t); 82 assert(tricu_to_utf8(ctx, invalid, &unchanged, &unchanged_length) == TRICU_TYPE_ERROR); 83 assert(unchanged == &sentinel && unchanged_length == 987); 84 assert(tricu_from_bytes(ctx, NULL, 0, &marker) == TRICU_OK); 85 assert(tricu_to_bytes(ctx, marker, &output, &length) == TRICU_OK && length == 0); 86 tricu_buffer_free(output); 87 } 88 89 int main(void) { 90 signal(SIGINT, host_signal); 91 signal(SIGPIPE, host_signal); 92 tricu_init(); 93 tricu_init(); 94 raise(SIGINT); 95 assert(observed_signal == SIGINT); 96 raise(SIGPIPE); 97 assert(observed_signal == SIGPIPE); 98 assert(tricu_abi_version() == 1); 99 tricu_context ctx; 100 tricu_handle value, alias, result; 101 assert(tricu_context_new(&ctx) == TRICU_OK); 102 core_rules(ctx); 103 assert(tricu_from_u64(ctx, UINT64_MAX, &value) == TRICU_OK); 104 assert(tricu_retain(ctx, value, &alias) == TRICU_OK); 105 assert(value != alias); 106 assert(tricu_release(ctx, value) == TRICU_OK); 107 result = 123; 108 assert(tricu_reduce(ctx, value, &result) == TRICU_INVALID_HANDLE); 109 assert(result == 123); 110 uint32_t boolean = 999; 111 assert(tricu_to_bool(ctx, alias, &boolean) == TRICU_TYPE_ERROR); 112 assert(boolean == 999); 113 assert(tricu_leaf(ctx, &result) == TRICU_OK); 114 assert(tricu_to_bool(ctx, result, &boolean) == TRICU_OK && boolean == 0); 115 assert(tricu_stem(ctx, result, &value) == TRICU_OK); 116 assert(tricu_to_bool(ctx, value, &boolean) == TRICU_OK && boolean == 1); 117 uint64_t number; 118 assert(tricu_to_u64(ctx, alias, &number) == TRICU_OK); 119 assert(number == UINT64_MAX); 120 uint8_t *error; 121 size_t length; 122 assert(tricu_last_error(ctx, &error, &length) == TRICU_OK); 123 assert(length > 0); 124 tricu_buffer_free(error); 125 assert(tricu_from_utf8(ctx, (const uint8_t *)"a\0b", 3, &value) == TRICU_OK); 126 uint8_t *bytes; 127 assert(tricu_to_utf8(ctx, value, &bytes, &length) == TRICU_OK); 128 assert(length == 3 && memcmp(bytes, "a\0b", 3) == 0); 129 assert(tricu_context_free(ctx) == TRICU_OK); 130 assert(memcmp(bytes, "a\0b", 3) == 0); 131 tricu_buffer_free(bytes); 132 assert(tricu_context_free(ctx) == TRICU_INVALID_CONTEXT); 133 return 0; 134 }