|
| 1 | +# Tests for v1.3.1 builtins: substrate_embed, omc_spawn, omc_pipe, llm_tools |
| 2 | +# substrate_embed: always works (offline, pure math) |
| 3 | +# omc_spawn / omc_pipe: always work (shell commands) |
| 4 | +# llm_tools: requires ANTHROPIC_API_KEY (arg-validation only without key) |
| 5 | + |
| 6 | +fn assert_eq(actual, expected, msg) { |
| 7 | + if actual != expected { |
| 8 | + test_record_failure(msg + ": expected " + to_string(expected) + " got " + to_string(actual)) |
| 9 | + } |
| 10 | +} |
| 11 | + |
| 12 | +fn assert_true(cond, msg) { if !cond { test_record_failure(msg) } } |
| 13 | +fn assert_false(cond, msg) { if cond { test_record_failure(msg) } } |
| 14 | +fn assert_null(v, msg) { if v != null { test_record_failure(msg + ": expected null") } } |
| 15 | + |
| 16 | +# ── substrate_embed ─────────────────────────────────────────────────────────── |
| 17 | + |
| 18 | +fn test_substrate_embed_returns_array() { |
| 19 | + h v = substrate_embed("hello world", 16) |
| 20 | + assert_eq(type_of(v), "array", "returns array") |
| 21 | + assert_eq(arr_len(v), 16, "length 16") |
| 22 | +} |
| 23 | + |
| 24 | +fn test_substrate_embed_default_dims() { |
| 25 | + h v = substrate_embed("test") |
| 26 | + assert_eq(arr_len(v), 16, "default 16 dims") |
| 27 | +} |
| 28 | + |
| 29 | +fn test_substrate_embed_custom_dims() { |
| 30 | + h v = substrate_embed("test", 32) |
| 31 | + assert_eq(arr_len(v), 32, "custom 32 dims") |
| 32 | +} |
| 33 | + |
| 34 | +fn test_substrate_embed_values_are_floats() { |
| 35 | + h v = substrate_embed("hello", 8) |
| 36 | + h i = 0 |
| 37 | + while i < arr_len(v) { |
| 38 | + h t = type_of(v[i]) |
| 39 | + assert_true(t == "float" or t == "int", "element is numeric") |
| 40 | + i = i + 1 |
| 41 | + } |
| 42 | +} |
| 43 | + |
| 44 | +fn test_substrate_embed_is_normalized() { |
| 45 | + h v = substrate_embed("normalize me", 16) |
| 46 | + h dot = 0.0 |
| 47 | + h i = 0 |
| 48 | + while i < arr_len(v) { |
| 49 | + dot = dot + v[i] * v[i] |
| 50 | + i = i + 1 |
| 51 | + } |
| 52 | + assert_true(dot > 0.9 and dot < 1.1, "L2 norm ≈ 1.0") |
| 53 | +} |
| 54 | + |
| 55 | +fn test_substrate_embed_different_texts_differ() { |
| 56 | + h v1 = substrate_embed("cat", 8) |
| 57 | + h v2 = substrate_embed("dog", 8) |
| 58 | + h same = true |
| 59 | + h i = 0 |
| 60 | + while i < 8 { |
| 61 | + if v1[i] != v2[i] { same = false } |
| 62 | + i = i + 1 |
| 63 | + } |
| 64 | + assert_false(same, "different texts produce different embeddings") |
| 65 | +} |
| 66 | + |
| 67 | +fn test_substrate_embed_same_text_identical() { |
| 68 | + h v1 = substrate_embed("repeat", 8) |
| 69 | + h v2 = substrate_embed("repeat", 8) |
| 70 | + h i = 0 |
| 71 | + while i < 8 { |
| 72 | + assert_eq(v1[i], v2[i], "same text → same vector element") |
| 73 | + i = i + 1 |
| 74 | + } |
| 75 | +} |
| 76 | + |
| 77 | +fn test_substrate_embed_empty_string() { |
| 78 | + h v = substrate_embed("", 4) |
| 79 | + assert_eq(arr_len(v), 4, "empty string → length 4") |
| 80 | +} |
| 81 | + |
| 82 | +fn test_substrate_embed_requires_text() { |
| 83 | + h err = "" |
| 84 | + try { substrate_embed() } catch e { err = e } |
| 85 | + assert_true(str_len(err) > 0, "no args → error") |
| 86 | +} |
| 87 | + |
| 88 | +# ── omc_spawn ───────────────────────────────────────────────────────────────── |
| 89 | + |
| 90 | +fn test_omc_spawn_echo() { |
| 91 | + h r = omc_spawn("echo", ["hello"]) |
| 92 | + assert_true(dict_has(r, "stdout"), "has stdout") |
| 93 | + assert_true(dict_has(r, "stderr"), "has stderr") |
| 94 | + assert_true(dict_has(r, "exit_code"), "has exit_code") |
| 95 | + assert_true(dict_has(r, "ok"), "has ok") |
| 96 | + assert_eq(r["exit_code"], 0, "echo exits 0") |
| 97 | + assert_eq(r["ok"], true, "echo ok=true") |
| 98 | + assert_true(str_contains(r["stdout"], "hello"), "stdout contains hello") |
| 99 | +} |
| 100 | + |
| 101 | +fn test_omc_spawn_exit_code() { |
| 102 | + h r = omc_spawn("false", []) |
| 103 | + assert_false(r["ok"], "false → ok=false") |
| 104 | + assert_true(r["exit_code"] != 0, "false → non-zero exit") |
| 105 | +} |
| 106 | + |
| 107 | +fn test_omc_spawn_true_command() { |
| 108 | + h r = omc_spawn("true", []) |
| 109 | + assert_eq(r["exit_code"], 0, "true exits 0") |
| 110 | + assert_eq(r["ok"], true, "true ok=true") |
| 111 | +} |
| 112 | + |
| 113 | +fn test_omc_spawn_no_args_uses_empty_array() { |
| 114 | + h r = omc_spawn("echo", null) |
| 115 | + assert_true(dict_has(r, "ok"), "null args accepted") |
| 116 | +} |
| 117 | + |
| 118 | +fn test_omc_spawn_captures_stderr() { |
| 119 | + h r = omc_spawn("sh", ["-c", "echo error >&2; exit 1"]) |
| 120 | + assert_true(str_contains(r["stderr"], "error"), "stderr captured") |
| 121 | + assert_false(r["ok"], "failed exit code") |
| 122 | +} |
| 123 | + |
| 124 | +fn test_omc_spawn_multiarg_echo() { |
| 125 | + h r = omc_spawn("echo", ["one", "two", "three"]) |
| 126 | + assert_true(str_contains(r["stdout"], "one"), "first arg in stdout") |
| 127 | + assert_true(str_contains(r["stdout"], "three"), "third arg in stdout") |
| 128 | +} |
| 129 | + |
| 130 | +# ── omc_pipe ────────────────────────────────────────────────────────────────── |
| 131 | + |
| 132 | +fn test_omc_pipe_basic() { |
| 133 | + h r = omc_pipe([["echo", "hello world"], ["grep", "hello"]]) |
| 134 | + assert_true(dict_has(r, "stdout"), "has stdout") |
| 135 | + assert_eq(r["ok"], true, "pipe ok") |
| 136 | + assert_true(str_contains(r["stdout"], "hello"), "piped output contains hello") |
| 137 | +} |
| 138 | + |
| 139 | +fn test_omc_pipe_single_command() { |
| 140 | + h r = omc_pipe([["echo", "single"]]) |
| 141 | + assert_eq(r["ok"], true, "single command pipe ok") |
| 142 | + assert_true(str_contains(r["stdout"], "single"), "single output") |
| 143 | +} |
| 144 | + |
| 145 | +fn test_omc_pipe_count_lines() { |
| 146 | + h r = omc_pipe([["printf", "a\nb\nc\n"], ["wc", "-l"]]) |
| 147 | + assert_eq(r["ok"], true, "wc pipe ok") |
| 148 | + assert_true(str_contains(str_trim(r["stdout"]), "3"), "3 lines counted") |
| 149 | +} |
| 150 | + |
| 151 | +fn test_omc_pipe_requires_array() { |
| 152 | + h err = "" |
| 153 | + try { omc_pipe("not an array") } catch e { err = e } |
| 154 | + assert_true(str_len(err) > 0, "non-array → error") |
| 155 | +} |
| 156 | + |
| 157 | +# ── llm_tools ───────────────────────────────────────────────────────────────── |
| 158 | + |
| 159 | +fn test_llm_tools_requires_two_args() { |
| 160 | + h err = "" |
| 161 | + try { llm_tools() } catch e { err = e } |
| 162 | + assert_true(str_len(err) > 0, "no args → error") |
| 163 | +} |
| 164 | + |
| 165 | +fn test_llm_tools_requires_messages_and_tools() { |
| 166 | + h err = "" |
| 167 | + try { llm_tools([]) } catch e { err = e } |
| 168 | + assert_true(str_len(err) > 0, "one arg → error") |
| 169 | +} |
| 170 | + |
| 171 | +fn test_llm_tools_conditional() { |
| 172 | + h err = "" |
| 173 | + h result = null |
| 174 | + try { |
| 175 | + h messages = [{role: "user", content: "What is 2+2?"}] |
| 176 | + h tools = [{ |
| 177 | + name: "calculator", |
| 178 | + description: "Performs arithmetic", |
| 179 | + input_schema: {type: "object", properties: {expr: {type: "string"}}} |
| 180 | + }] |
| 181 | + result = llm_tools(messages, tools, null) |
| 182 | + } catch e { |
| 183 | + err = e |
| 184 | + } |
| 185 | + # Without API key: error is expected. With key: result should be a dict. |
| 186 | + if result != null { |
| 187 | + assert_true(type_of(result) == "dict", "result is dict") |
| 188 | + } |
| 189 | + assert_true(true, "llm_tools callable") |
| 190 | +} |
0 commit comments