;; ========================================================================== ;; test-read-write.sx — Tests for read / write / display / newline ;; ========================================================================== ;; -------------------------------------------------------------------------- ;; read — parse one datum from an input port ;; -------------------------------------------------------------------------- (defsuite "read:basics" (deftest "read integer" (let ((p (open-input-string "42"))) (assert= (read p) 42))) (deftest "read float" (let ((p (open-input-string "3.14"))) (assert= (read p) 3.14))) (deftest "read string" (let ((p (open-input-string "\"hello\""))) (assert= (read p) "hello"))) (deftest "read boolean true" (let ((p (open-input-string "#t"))) (assert (read p)))) (deftest "read boolean false" (let ((p (open-input-string "#f"))) (assert (not (read p))))) (deftest "read nil" (let ((p (open-input-string "()"))) (assert-nil (read p)))) (deftest "read list" (let ((p (open-input-string "(1 2 3)"))) (assert= (read p) (list 1 2 3)))) (deftest "read nested list" (let ((p (open-input-string "(+ 1 (* 2 3))"))) (assert= (read p) (list (quote +) 1 (list (quote *) 2 3)))))) ;; -------------------------------------------------------------------------- ;; read — eof and multi-read ;; -------------------------------------------------------------------------- (defsuite "read:eof" (deftest "read eof returns eof-object" (let ((p (open-input-string ""))) (assert (eof-object? (read p))))) (deftest "read whitespace-only returns eof" (let ((p (open-input-string " "))) (assert (eof-object? (read p))))) (deftest "read two forms" (let ((p (open-input-string "1 2"))) (let ((a (read p)) (b (read p))) (assert (and (= a 1) (= b 2)))))) (deftest "read returns eof after last form" (let ((p (open-input-string "42"))) (read p) (assert (eof-object? (read p)))))) ;; -------------------------------------------------------------------------- ;; write — serialize with quoting ;; -------------------------------------------------------------------------- (defsuite "write:basics" (deftest "write integer" (assert= (write-to-string 42) "42")) (deftest "write negative integer" (assert= (write-to-string -5) "-5")) (deftest "write float" (assert= (write-to-string 3.14) "3.14")) (deftest "write true" (assert= (write-to-string true) "#t")) (deftest "write false" (assert= (write-to-string false) "#f")) (deftest "write nil" (assert= (write-to-string nil) "()")) (deftest "write string quotes" (assert= (write-to-string "hello") "\"hello\"")) (deftest "write string with escapes" (assert= (write-to-string "a\"b") "\"a\\\"b\"")) (deftest "write list" (assert= (write-to-string (list 1 2 3)) "(1 2 3)")) (deftest "write nested list" (assert= (write-to-string (list 1 (list 2 3))) "(1 (2 3))")) (deftest "write symbol" (assert= (write-to-string (quote foo)) "foo")) (deftest "write rational" (assert= (write-to-string 1/3) "1/3"))) ;; -------------------------------------------------------------------------- ;; display — serialize without quoting ;; -------------------------------------------------------------------------- (defsuite "display:basics" (deftest "display integer" (assert= (display-to-string 42) "42")) (deftest "display string no quotes" (assert= (display-to-string "hello") "hello")) (deftest "display true" (assert= (display-to-string true) "#t")) (deftest "display nil" (assert= (display-to-string nil) "()")) (deftest "display list" (assert= (display-to-string (list 1 2 3)) "(1 2 3)"))) ;; -------------------------------------------------------------------------- ;; write vs display distinction ;; -------------------------------------------------------------------------- (defsuite "write-vs-display" (deftest "write quotes string, display does not" (let ((s "hello")) (assert (and (= (write-to-string s) "\"hello\"") (= (display-to-string s) "hello"))))) (deftest "write and display same for numbers" (assert= (write-to-string 42) (display-to-string 42))) (deftest "write and display same for lists" (assert= (write-to-string (list 1 2)) (display-to-string (list 1 2))))) ;; -------------------------------------------------------------------------- ;; write/display/newline to port ;; -------------------------------------------------------------------------- (defsuite "write-to-port" (deftest "write to output port" (let ((p (open-output-string))) (write 42 p) (assert= (get-output-string p) "42"))) (deftest "display to output port" (let ((p (open-output-string))) (display "hi" p) (assert= (get-output-string p) "hi"))) (deftest "newline to output port" (let ((p (open-output-string))) (newline p) (assert= (get-output-string p) "\n"))) (deftest "write then newline" (let ((p (open-output-string))) (write "hello" p) (newline p) (assert= (get-output-string p) "\"hello\"\n"))) (deftest "display multiple values" (let ((p (open-output-string))) (display 1 p) (display " " p) (display 2 p) (assert= (get-output-string p) "1 2")))) ;; -------------------------------------------------------------------------- ;; write round-trip ;; -------------------------------------------------------------------------- (defsuite "write:round-trip" (deftest "integer round-trips" (let ((p (open-input-string (write-to-string 42)))) (assert= (read p) 42))) (deftest "string round-trips" (let ((p (open-input-string (write-to-string "hello world")))) (assert= (read p) "hello world"))) (deftest "list round-trips" (let ((p (open-input-string (write-to-string (list 1 2 3))))) (assert= (read p) (list 1 2 3)))) (deftest "boolean true round-trips" (let ((p (open-input-string (write-to-string true)))) (assert (read p)))) (deftest "boolean false round-trips" (let ((p (open-input-string (write-to-string false)))) (assert (not (read p))))))