Files
rose-ash/spec/tests/test-ports.sx
giles 3d8937d759
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
spec: string ports (open-input-string/open-output-string/read-char/etc)
Phase 14: port type + eof-object. Input ports track _pos cursor; output ports
accumulate _buffer. All 15 port primitives in spec/primitives.sx (stdlib.ports
module), platform.py (JS), and 39/39 tests in spec/tests/test-ports.sx.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 12:38:08 +00:00

233 lines
6.1 KiB
Plaintext

;; Phase 14 — String ports + eof-object
(deftest
"eof-object"
(deftest
"eof-object is eof"
(assert=
true
(eof-object? (eof-object))
"eof-object? returns true for eof-object"))
(deftest
"non-eof values are not eof"
(assert= false (eof-object? nil) "nil is not eof")
(assert= false (eof-object? "") "string is not eof")
(assert= false (eof-object? 0) "zero is not eof")
(assert= false (eof-object? false) "false is not eof"))
(deftest
"type-of eof-object"
(assert=
"eof-object"
(type-of (eof-object))
"type-of eof-object is eof-object")))
(deftest
"open-input-string"
(deftest
"creates input port"
(let
(p (open-input-string "hello"))
(assert= true (port? p) "is a port")
(assert= true (input-port? p) "is an input port")
(assert= false (output-port? p) "is not an output port")))
(deftest
"type-of input port"
(let
(p (open-input-string "x"))
(assert= "input-port" (type-of p) "type-of is input-port"))))
(deftest
"open-output-string"
(deftest
"creates output port"
(let
(p (open-output-string))
(assert= true (port? p) "is a port")
(assert= true (output-port? p) "is an output port")
(assert= false (input-port? p) "is not an input port")))
(deftest
"type-of output port"
(let
(p (open-output-string))
(assert= "output-port" (type-of p) "type-of is output-port"))))
(deftest
"read-char"
(deftest
"reads chars sequentially"
(let
(p (open-input-string "ab"))
(let
(c1 (read-char p))
(assert= true (char? c1) "first result is char")
(assert= 97 (char->integer c1) "first char is a"))))
(deftest
"reads second char"
(let
(p (open-input-string "ab"))
(read-char p)
(let
(c2 (read-char p))
(assert= true (char? c2) "second result is char")
(assert= 98 (char->integer c2) "second char is b"))))
(deftest
"returns eof at end"
(let
(p (open-input-string "x"))
(read-char p)
(assert= true (eof-object? (read-char p)) "eof after last char")))
(deftest
"empty string yields eof immediately"
(let
(p (open-input-string ""))
(assert= true (eof-object? (read-char p)) "eof from empty string"))))
(deftest
"peek-char"
(deftest
"peeks without consuming"
(let
(p (open-input-string "x"))
(let
(c1 (peek-char p))
(let
(c2 (peek-char p))
(assert=
(char->integer c1)
(char->integer c2)
"peek twice gives same char")))))
(deftest
"peek then read"
(let
(p (open-input-string "z"))
(let
(peeked (peek-char p))
(let
(read (read-char p))
(assert=
(char->integer peeked)
(char->integer read)
"peek and read agree")))))
(deftest
"peek at end returns eof"
(let
(p (open-input-string ""))
(assert= true (eof-object? (peek-char p)) "eof on empty peek"))))
(deftest
"read-line"
(deftest
"reads a single line"
(let
(p (open-input-string "hello"))
(assert= "hello" (read-line p) "reads whole string as line")))
(deftest
"reads line up to newline"
(let
(p (open-input-string "foo\nbar"))
(assert= "foo" (read-line p) "first line is foo")))
(deftest
"reads second line"
(let
(p (open-input-string "foo\nbar"))
(read-line p)
(assert= "bar" (read-line p) "second line is bar")))
(deftest
"returns eof on empty port"
(let
(p (open-input-string ""))
(assert= true (eof-object? (read-line p)) "eof on empty")))
(deftest
"returns eof after last line"
(let
(p (open-input-string "hi"))
(read-line p)
(assert= true (eof-object? (read-line p)) "eof after reading"))))
(deftest
"write-char and get-output-string"
(deftest
"write single char"
(let
(p (open-output-string))
(write-char (make-char 65) p)
(assert= "A" (get-output-string p) "write char A")))
(deftest
"write multiple chars"
(let
(p (open-output-string))
(write-char (make-char 72) p)
(write-char (make-char 105) p)
(assert= "Hi" (get-output-string p) "write Hi"))))
(deftest
"write-string"
(deftest
"write a string to port"
(let
(p (open-output-string))
(write-string "hello" p)
(assert= "hello" (get-output-string p) "write-string result")))
(deftest
"multiple writes concatenate"
(let
(p (open-output-string))
(write-string "foo" p)
(write-string "bar" p)
(assert= "foobar" (get-output-string p) "concatenated writes"))))
(deftest
"get-output-string idempotent"
(let
(p (open-output-string))
(write-string "test" p)
(assert= "test" (get-output-string p) "first call")
(assert= "test" (get-output-string p) "second call same result")))
(deftest
"char-ready?"
(deftest
"ready when chars available"
(let
(p (open-input-string "x"))
(assert= true (char-ready? p) "ready with content")))
(deftest
"not ready when empty"
(let
(p (open-input-string ""))
(assert= false (char-ready? p) "not ready when empty"))))
(deftest
"close-port"
(deftest
"close input port"
(let
(p (open-input-string "hello"))
(close-port p)
(assert= true (eof-object? (read-char p)) "read after close gives eof")))
(deftest
"close output port"
(let
(p (open-output-string))
(write-string "ok" p)
(close-port p)
(assert= "ok" (get-output-string p) "output preserved after close"))))
(deftest
"roundtrip string via ports"
(let
(in (open-input-string "abc"))
(let
(out (open-output-string))
(do
(let
(c1 (read-char in))
(when (not (eof-object? c1)) (write-char c1 out)))
(let
(c2 (read-char in))
(when (not (eof-object? c2)) (write-char c2 out)))
(let
(c3 (read-char in))
(when (not (eof-object? c3)) (write-char c3 out)))
(assert= "abc" (get-output-string out) "roundtrip via ports")))))