Files
rose-ash/spec/tests/test-conditions.sx
giles ef34122a25 Fix 30 test failures: OCaml renderer primitives + condition signal rename
OCaml HTML renderer (sx_render.ml) silently returned "" when env_get
failed for primitive function calls (str, +, len, etc.) inside HTML
elements. The Eval_error catch now falls through to eval_expr which
resolves primitives correctly. Fixes 21 rendering tests.

Rename condition system special form from "signal" to "signal-condition"
in evaluator.sx, matching the OCaml bootstrapped evaluator (sx_ref.ml).
This avoids clashing with the reactive signal function. Fixes 9
condition system tests.

1166 passed, 0 failed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 18:08:47 +00:00

110 lines
3.3 KiB
Plaintext

(defsuite
"handler-bind-basic"
(deftest
"handler-bind returns body value when no signal"
(assert-equal
42
(handler-bind (((fn (c) true) (fn (c) "handled"))) 42)))
(deftest
"signal with matching handler returns handler value"
(assert-equal
"handled: boom"
(handler-bind
(((fn (c) true) (fn (c) (str "handled: " c))))
(signal-condition "boom"))))
(deftest
"signal without handler errors"
(assert-throws (fn () (signal-condition "unhandled"))))
(deftest
"signal returns handler value to call site"
(assert-equal
51
(handler-bind
(((fn (c) true) (fn (c) (* c 10))))
(+ 1 (signal-condition 5)))))
(deftest
"handler-bind multiple handlers picks first match"
(assert-equal
"got-b"
(handler-bind
(((fn (c) (= c "type-a")) (fn (c) "got-a"))
((fn (c) (= c "type-b")) (fn (c) "got-b")))
(signal-condition "type-b"))))
(deftest
"nested handler-bind inner takes precedence"
(assert-equal
"inner-handler"
(handler-bind
(((fn (c) true) (fn (c) "outer")))
(handler-bind
(((fn (c) (= c "inner")) (fn (c) "inner-handler")))
(signal-condition "inner")))))
(deftest
"handler-bind with multi-expression body"
(assert-equal
10
(handler-bind (((fn (c) true) (fn (c) c))) (+ 1 2) (* 2 5)))))
(defsuite
"restart-case-basic"
(deftest
"restart-case returns body value when no signal"
(assert-equal 3 (restart-case (+ 1 2) (use-default () 0))))
(deftest
"invoke-restart finds and runs restart"
(assert-equal
42
(handler-bind
(((fn (c) true) (fn (c) (invoke-restart (quote use-default)))))
(restart-case
(do (signal-condition "bad") "unreachable")
(use-default () 42)))))
(deftest
"invoke-restart with argument"
(assert-equal
99
(handler-bind
(((fn (c) true) (fn (c) (invoke-restart (quote use-value) 99))))
(restart-case
(do (signal-condition "bad") "unreachable")
(use-value (v) v)))))
(deftest
"invoke-restart unknown name errors"
(assert-throws (fn () (invoke-restart (quote nonexistent)))))
(deftest
"nested restart-case uses inner restart"
(assert-equal
"inner-fallback"
(handler-bind
(((fn (c) true) (fn (c) (invoke-restart (quote fallback)))))
(restart-case
(restart-case
(do (signal-condition "err") "unreachable")
(fallback () "inner-fallback"))
(fallback () "outer-fallback")))))
(deftest
"signal + restart computes replacement value"
(assert-equal
25
(handler-bind
(((fn (c) true) (fn (c) (invoke-restart (quote use-value) (* c 3)))))
(+ 10 (restart-case (signal-condition 5) (use-value (v) v)))))))
(defsuite
"comp-trace"
(deftest
"component call creates trace frame"
(defcomp ~trace-inner () "inner")
(assert-equal "inner" (~trace-inner)))
(deftest
"nested component calls work"
(defcomp ~trace-child () "child")
(defcomp ~trace-parent () (~trace-child))
(assert-equal "child" (~trace-parent)))
(deftest
"component error via cek-try"
(defcomp ~broken-comp () (error "deliberate"))
(let
((result (cek-try (fn () (~broken-comp)))))
(assert-true (= (type-of result) "list")))))