Files
rose-ash/spec/tests/test-bytecode-serial.sx
giles bca0d8e4e5 Step 15: bytecode + CEK state serialization — 16 tests
bytecode-serialize/deserialize: sxbc v2 format wrapping compiled code
dicts. cek-serialize/deserialize: cek-state v1 format wrapping suspended
CEK state (phase, request, env, kont). Both use SX s-expression
round-trip via inspect/parse. lib/serialize.sx has pure SX versions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 08:19:16 +00:00

146 lines
5.0 KiB
Plaintext

;; Step 15: Bytecode + continuation serialization
;; Round-trip compiled code and suspended CEK state through strings.
;; ── Bytecode serialization ────────────────────────────────────────
(defsuite
"bytecode-serialize-basic"
(deftest
"compile and serialize round-trips"
(let
((code (compile "(+ 1 2)")))
(assert (not (nil? code)))
(let
((serialized (bytecode-serialize code)))
(assert (string? serialized))
(assert (> (string-length serialized) 0)))))
(deftest
"serialized format has sxbc header"
(let
((code (compile "(+ 1 2)")))
(let
((serialized (bytecode-serialize code)))
(assert (starts-with? serialized "(sxbc 2")))))
(deftest
"deserialized code has same structure"
(let
((code (compile "(+ 1 2)")))
(let
((serialized (bytecode-serialize code))
(restored (bytecode-deserialize serialized)))
(assert (not (nil? restored)))
(assert (dict? restored)))))
(deftest
"deserialized bytecode array matches"
(let
((code (compile "(+ 1 2)")))
(let
((serialized (bytecode-serialize code))
(restored (bytecode-deserialize serialized)))
(assert= (get restored "bytecode") (get code "bytecode")))))
(deftest
"deserialized constants match"
(let
((code (compile "(str \"hello\" \" \" \"world\")")))
(let
((serialized (bytecode-serialize code))
(restored (bytecode-deserialize serialized)))
(assert= (get restored "constants") (get code "constants"))))))
(defsuite
"bytecode-serialize-types"
(deftest
"number bytecodes round-trip"
(let
((code (compile "(+ 42 3)")))
(let
((restored (bytecode-deserialize (bytecode-serialize code))))
(assert= (get restored "bytecode") (get code "bytecode")))))
(deftest
"multiple expressions round-trip"
(let
((code (compile "(define x 1)")))
(let
((restored (bytecode-deserialize (bytecode-serialize code))))
(assert= (get restored "bytecode") (get code "bytecode"))
(assert= (get restored "constants") (get code "constants")))))
(deftest
"dict expression round-trips"
(let
((code (compile "(dict :a 1 :b 2)")))
(let
((restored (bytecode-deserialize (bytecode-serialize code))))
(assert= (get restored "constants") (get code "constants")))))
(deftest
"lambda expression round-trips"
(let
((code (compile "(fn (x) (+ x 1))")))
(let
((restored (bytecode-deserialize (bytecode-serialize code))))
(assert= (get restored "bytecode") (get code "bytecode")))))
(deftest
"invalid format raises error"
(let
((raised false))
(guard
(e (true (set! raised true)))
(bytecode-deserialize "not valid"))
(assert raised "should raise for invalid format"))))
;; ── CEK state serialization ───────────────────────────────────────
(defsuite
"cek-serialize-basic"
(deftest
"suspended state serializes"
(let
((state (make-cek-suspended {:op "test"} (dict) (list))))
(let
((serialized (cek-serialize state)))
(assert (string? serialized))
(assert (starts-with? serialized "(cek-state 1")))))
(deftest
"deserialized state preserves phase"
(let
((state (make-cek-suspended {:op "test"} (dict) (list))))
(let
((restored (cek-deserialize (cek-serialize state))))
(assert (cek-suspended? restored)))))
(deftest
"deserialized state preserves request"
(let
((state (make-cek-suspended {:url "/api" :op "fetch"} (dict) (list))))
(let
((restored (cek-deserialize (cek-serialize state))))
(let
((req (cek-io-request restored)))
(assert= (get req :op) "fetch")
(assert= (get req :url) "/api"))))))
(defsuite
"cek-serialize-values"
(deftest
"request with nested data round-trips"
(let
((req {:params {:ids (list 1 2 3) :name "test"} :op "query"}) (state (make-cek-suspended req (dict) (list))))
(let
((restored (cek-deserialize (cek-serialize state))))
(let
((rreq (cek-io-request restored)))
(assert= (get rreq :op) "query")
(assert= (get (get rreq :params) :name) "test")
(assert= (get (get rreq :params) :ids) (list 1 2 3))))))
(deftest
"string with special chars round-trips"
(let
((req {:op "test" :data "line1\nline2\ttab"}) (state (make-cek-suspended req (dict) (list))))
(let
((restored (cek-deserialize (cek-serialize state))))
(assert= (get (cek-io-request restored) :data) "line1\nline2\ttab"))))
(deftest
"invalid cek format raises error"
(let
((raised false))
(guard (e (true (set! raised true))) (cek-deserialize "garbage"))
(assert raised "should raise for invalid format"))))