Promotes defio from native OCaml special form to spec-level CEK evaluator feature. The IO registry is now the contract layer between evaluator and platform. Evaluator additions (spec/evaluator.sx): - *io-registry* mutable dict global (like *library-registry*) - io-register!, io-registered?, io-lookup, io-names accessors - defio-parse-kwargs! recursive keyword parser - sf-defio processes (defio "name" :category :data :params (...) ...) - "defio" dispatch in step-eval-list - step-sf-io: the contract function — validates against registry, then delegates to perform for IO suspension - "io" dispatch in step-eval-list Native OCaml defio handlers removed from: - sx_server.ml (~20 lines) - sx_browser.ml (~20 lines) - run_tests.ml (~18 lines) All replaced with __io-registry alias to spec's *io-registry*. IO accessor functions bound in run_tests.ml env so tests can call io-registered?, io-lookup, io-names. 10 new tests (spec/tests/test-io-registry.sx): - defio populates registry - io-lookup returns spec with name/category/returns/doc - io-registered?/io-names work correctly - kwargs parsing (batchable, cacheable, params) - io contract rejects unregistered ops - io contract passes validation for registered ops 2608/2608 tests passing (+10 new). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
102 lines
2.7 KiB
Plaintext
102 lines
2.7 KiB
Plaintext
;; IO registry tests — defio, *io-registry*, accessor functions, io contract
|
|
(defsuite
|
|
"io-registry-basic"
|
|
(deftest
|
|
"defio registers an IO operation"
|
|
(defio
|
|
"test-io-basic"
|
|
:category :data
|
|
:params ()
|
|
:returns "string"
|
|
:doc "Basic test op.")
|
|
(assert (io-registered? "test-io-basic")))
|
|
(deftest
|
|
"io-lookup returns spec dict"
|
|
(defio
|
|
"test-io-lookup"
|
|
:category :effect
|
|
:params (x)
|
|
:returns "nil"
|
|
:doc "Test effect.")
|
|
(let
|
|
((spec (io-lookup "test-io-lookup")))
|
|
(assert= (get spec "name") "test-io-lookup")
|
|
(assert= (keyword-name (get spec "category")) "effect")
|
|
(assert= (get spec "returns") "nil")
|
|
(assert= (get spec "doc") "Test effect.")))
|
|
(deftest
|
|
"io-registered? returns false for unknown"
|
|
(assert (not (io-registered? "nonexistent-io-op"))))
|
|
(deftest
|
|
"io-names includes registered ops"
|
|
(defio
|
|
"test-io-names"
|
|
:category :data
|
|
:params ()
|
|
:returns "any"
|
|
:doc "Names test.")
|
|
(assert (contains? (io-names) "test-io-names")))
|
|
(deftest
|
|
"defio returns the spec dict"
|
|
(let
|
|
((result (defio "test-io-ret" :category :code :params (a b) :returns "string" :doc "Return test.")))
|
|
(assert= (get result "name") "test-io-ret")
|
|
(assert= (keyword-name (get result "category")) "code"))))
|
|
|
|
(defsuite
|
|
"io-registry-kwargs"
|
|
(deftest
|
|
"defio parses batchable flag"
|
|
(defio
|
|
"test-io-batch"
|
|
:category :code
|
|
:params (code lang)
|
|
:returns "string"
|
|
:batchable true
|
|
:doc "Batchable op.")
|
|
(assert= (get (io-lookup "test-io-batch") "batchable") true))
|
|
(deftest
|
|
"defio parses cacheable flag"
|
|
(defio
|
|
"test-io-cache"
|
|
:category :data
|
|
:params ()
|
|
:returns "list"
|
|
:cacheable true
|
|
:doc "Cacheable op.")
|
|
(assert= (get (io-lookup "test-io-cache") "cacheable") true))
|
|
(deftest
|
|
"defio parses params list"
|
|
(defio
|
|
"test-io-params"
|
|
:category :data
|
|
:params (a b c)
|
|
:returns "list"
|
|
:doc "Multi param.")
|
|
(assert= (len (get (io-lookup "test-io-params") "params")) 3)))
|
|
|
|
(defsuite
|
|
"io-contract"
|
|
(deftest
|
|
"io rejects unregistered operations"
|
|
(let
|
|
((caught false))
|
|
(try-catch
|
|
(fn () (io "totally-unknown-op-xyz"))
|
|
(fn (err) (set! caught true)))
|
|
(assert caught)))
|
|
(deftest
|
|
"io suspends for registered operations"
|
|
(defio
|
|
"test-io-contract"
|
|
:category :data
|
|
:params ()
|
|
:returns "string"
|
|
:doc "Contract test.")
|
|
(let
|
|
((caught-msg ""))
|
|
(try-catch
|
|
(fn () (io "test-io-contract"))
|
|
(fn (err) (set! caught-msg err)))
|
|
(assert (not (string-contains? caught-msg "unknown operation"))))))
|