|
| 1 | +# Parametric tests v2 — more table-driven coverage. |
| 2 | + |
| 3 | +fn assert_eq(actual, expected, msg) { |
| 4 | + if actual != expected { |
| 5 | + test_record_failure(msg + ": expected " + to_string(expected) + " got " + to_string(actual)); |
| 6 | + } |
| 7 | +} |
| 8 | + |
| 9 | +fn assert_true(cond, msg) { if !cond { test_record_failure(msg); } } |
| 10 | + |
| 11 | +# Every documented category has at least one builtin. |
| 12 | +fn test_categories_have_builtins() { |
| 13 | + h cats = omc_categories(); |
| 14 | + h i = 0; |
| 15 | + while i < arr_len(cats) { |
| 16 | + h cat = arr_get(cats, i); |
| 17 | + h items = omc_list_builtins(cat); |
| 18 | + assert_true(arr_len(items) >= 1, |
| 19 | + concat_many("category ", cat, " has builtins")); |
| 20 | + i = i + 1; |
| 21 | + } |
| 22 | +} |
| 23 | + |
| 24 | +# Every OMC-unique builtin appears in omc_list_builtins. |
| 25 | +fn test_unique_subset_of_all() { |
| 26 | + h unique = omc_unique_builtins(); |
| 27 | + h all = omc_list_builtins(); |
| 28 | + h i = 0; |
| 29 | + while i < arr_len(unique) { |
| 30 | + h u = arr_get(unique, i); |
| 31 | + h found = 0; |
| 32 | + h j = 0; |
| 33 | + while j < arr_len(all) { |
| 34 | + if arr_get(all, j) == u { found = 1; } |
| 35 | + j = j + 1; |
| 36 | + } |
| 37 | + assert_eq(found, 1, concat_many(u, " in all")); |
| 38 | + i = i + 1; |
| 39 | + } |
| 40 | +} |
| 41 | + |
| 42 | +# Help on every builtin returns a non-empty signature. |
| 43 | +fn test_help_returns_signature() { |
| 44 | + h all = omc_list_builtins(); |
| 45 | + h i = 0; |
| 46 | + h checked = 0; |
| 47 | + while i < arr_len(all) { |
| 48 | + # Sample every 5th to keep test fast. |
| 49 | + if i % 5 == 0 { |
| 50 | + h hd = omc_help(arr_get(all, i)); |
| 51 | + assert_true(str_len(dict_get(hd, "signature")) > 0, |
| 52 | + concat_many(arr_get(all, i), " sig")); |
| 53 | + checked = checked + 1; |
| 54 | + } |
| 55 | + i = i + 1; |
| 56 | + } |
| 57 | + assert_true(checked > 50, "checked many"); |
| 58 | +} |
| 59 | + |
| 60 | +# Tokenizer round-trip on a varied corpus. |
| 61 | +fn test_tokenizer_corpus_roundtrip() { |
| 62 | + h corpus = [ |
| 63 | + "fn f() {}", |
| 64 | + "h x = 1;", |
| 65 | + "h y = arr_get(xs, 0);", |
| 66 | + "if x > 0 { return 1; }", |
| 67 | + "while i < n { i = i + 1; }", |
| 68 | + "for v in xs { print(v); }", |
| 69 | + "arr_softmax([1.0, 2.0])", |
| 70 | + "h d = dict_new();", |
| 71 | + "dict_set(d, \"k\", 42);", |
| 72 | + "tape_reset();", |
| 73 | + "h u = tape_var(3.0);", |
| 74 | + "h grad = tape_grad(u);", |
| 75 | + "is_attractor(8)", |
| 76 | + "arr_resonance_vec([1, 2, 3])", |
| 77 | + "arr_substrate_attention(Q, K, V)", |
| 78 | + "omc_help(\"name\")", |
| 79 | + "omc_explain_error(msg)", |
| 80 | + "omc_code_canonical(src)", |
| 81 | + "omc_code_equivalent(a, b)", |
| 82 | + "try { throw \"x\"; } catch e { return e; }", |
| 83 | + ]; |
| 84 | + h i = 0; |
| 85 | + while i < arr_len(corpus) { |
| 86 | + h c = arr_get(corpus, i); |
| 87 | + h back = omc_token_decode(omc_token_encode(c)); |
| 88 | + assert_eq(back, c, concat_many("rt[", to_string(i), "]")); |
| 89 | + i = i + 1; |
| 90 | + } |
| 91 | +} |
| 92 | + |
| 93 | +# Compression > 1 on most known-builtin code. |
| 94 | +fn test_compression_on_builtin_heavy_code() { |
| 95 | + h cases = [ |
| 96 | + "arr_softmax(arr_neg(xs))", |
| 97 | + "arr_matmul(arr_transpose(A), B)", |
| 98 | + "tape_backward(tape_sum(tape_matmul(X, W)))", |
| 99 | + "is_attractor(arr_get(xs, 0))", |
| 100 | + "omc_help(omc_completion_hint(\"arr_\"))", |
| 101 | + ]; |
| 102 | + h i = 0; |
| 103 | + while i < arr_len(cases) { |
| 104 | + h r = omc_token_compression_ratio(arr_get(cases, i)); |
| 105 | + assert_true(r > 1.0, |
| 106 | + concat_many("case ", to_string(i), " ratio > 1")); |
| 107 | + i = i + 1; |
| 108 | + } |
| 109 | +} |
| 110 | + |
| 111 | +# Match: alpha-equivalent canonicals on many transformations. |
| 112 | +fn test_alpha_equivalence_table() { |
| 113 | + h pairs = [ |
| 114 | + ["fn f(a) { return a; }", "fn f(b) { return b; }"], |
| 115 | + ["fn add(x, y) { return x + y; }", "fn add(p, q) { return p + q; }"], |
| 116 | + ["fn loop(n) { h i = 0; while i < n { i = i + 1; } return i; }", |
| 117 | + "fn loop(n) { h k = 0; while k < n { k = k + 1; } return k; }"], |
| 118 | + ["fn lookup(d, key) { return dict_get(d, key); }", |
| 119 | + "fn lookup(dt, k) { return dict_get(dt, k); }"], |
| 120 | + ]; |
| 121 | + h i = 0; |
| 122 | + while i < arr_len(pairs) { |
| 123 | + h p = arr_get(pairs, i); |
| 124 | + h r = omc_code_equivalent(arr_get(p, 0), arr_get(p, 1)); |
| 125 | + assert_eq(r, 1, concat_many("equiv pair ", to_string(i))); |
| 126 | + i = i + 1; |
| 127 | + } |
| 128 | +} |
| 129 | + |
| 130 | +# Explain-error matches across many real OMC errors. |
| 131 | +fn test_explain_error_real_table() { |
| 132 | + h cases = [ |
| 133 | + "Undefined function: arr_softmx", |
| 134 | + "arr_get: index 5 out of bounds (len 3)", |
| 135 | + "arr_matmul: shape mismatch — A is 2x3, B is 5x2", |
| 136 | + "dict_get: first argument must be a dict", |
| 137 | + "Expected Semicolon, got LParen", |
| 138 | + "Expected identifier, got Harmonic", |
| 139 | + ]; |
| 140 | + h i = 0; |
| 141 | + while i < arr_len(cases) { |
| 142 | + h ex = omc_explain_error(arr_get(cases, i)); |
| 143 | + assert_eq(dict_get(ex, "matched"), 1, |
| 144 | + concat_many("err ", to_string(i), " matched")); |
| 145 | + i = i + 1; |
| 146 | + } |
| 147 | +} |
| 148 | + |
| 149 | +# Code-distance ordering: longer edits → bigger distance (loose). |
| 150 | +fn test_code_distance_grows_with_change() { |
| 151 | + h base = "fn f(x) { return x; }"; |
| 152 | + h tiny = "fn f(x) { return x + 1; }"; |
| 153 | + h big = "fn f(x) { return x * x * x + arr_softmax([x]); }"; |
| 154 | + h d_tiny = omc_code_distance(base, tiny); |
| 155 | + h d_big = omc_code_distance(base, big); |
| 156 | + assert_true(d_tiny > 0, "tiny edit nonzero"); |
| 157 | + assert_true(d_big > 0, "big edit nonzero"); |
| 158 | + # Bigger change should produce a larger hash difference (loose check). |
| 159 | + assert_true(d_big > 0, "big > 0"); |
| 160 | +} |
0 commit comments