;; lib/ruby/tests/runtime.sx — Tests for lib/ruby/runtime.sx (define rb-test-pass 0) (define rb-test-fail 0) (define rb-test-fails (list)) (define (rb-test name got expected) (if (= got expected) (set! rb-test-pass (+ rb-test-pass 1)) (begin (set! rb-test-fail (+ rb-test-fail 1)) (set! rb-test-fails (append rb-test-fails (list {:got got :expected expected :name name})))))) ;; --------------------------------------------------------------------------- ;; 1. Hash ;; --------------------------------------------------------------------------- (define h1 (rb-hash-new)) (rb-test "hash? new" (rb-hash? h1) true) (rb-test "hash? non-hash" (rb-hash? 42) false) (rb-test "hash size empty" (rb-hash-size h1) 0) (rb-hash-at-put! h1 "a" 1) (rb-hash-at-put! h1 "b" 2) (rb-hash-at-put! h1 "c" 3) (rb-test "hash at a" (rb-hash-at h1 "a") 1) (rb-test "hash at b" (rb-hash-at h1 "b") 2) (rb-test "hash at missing" (rb-hash-at h1 "z") nil) (rb-test "hash at-or default" (rb-hash-at-or h1 "z" 99) 99) (rb-test "hash has-key yes" (rb-hash-has-key? h1 "a") true) (rb-test "hash has-key no" (rb-hash-has-key? h1 "z") false) (rb-test "hash size after inserts" (rb-hash-size h1) 3) (rb-hash-at-put! h1 "a" 10) (rb-test "hash at-put update" (rb-hash-at h1 "a") 10) (rb-test "hash size unchanged after update" (rb-hash-size h1) 3) (rb-hash-delete! h1 "b") (rb-test "hash delete" (rb-hash-has-key? h1 "b") false) (rb-test "hash size after delete" (rb-hash-size h1) 2) (rb-test "hash keys" (rb-hash-keys h1) (list "a" "c")) (rb-test "hash values" (rb-hash-values h1) (list 10 3)) (define h2 (rb-list->hash (list (list "x" 7) (list "y" 8)))) (rb-test "list->hash x" (rb-hash-at h2 "x") 7) (rb-test "list->hash y" (rb-hash-at h2 "y") 8) (define h3 (rb-hash-merge h1 h2)) (rb-test "hash-merge a" (rb-hash-at h3 "a") 10) (rb-test "hash-merge x" (rb-hash-at h3 "x") 7) (rb-test "hash-merge size" (rb-hash-size h3) 4) ;; --------------------------------------------------------------------------- ;; 2. Set ;; --------------------------------------------------------------------------- (define s1 (rb-set-new)) (rb-test "set? new" (rb-set? s1) true) (rb-test "set? non-set" (rb-set? "hello") false) (rb-test "set size empty" (rb-set-size s1) 0) (rb-set-add! s1 1) (rb-set-add! s1 2) (rb-set-add! s1 3) (rb-set-add! s1 2) (rb-test "set include yes" (rb-set-include? s1 1) true) (rb-test "set include no" (rb-set-include? s1 9) false) (rb-test "set size dedup" (rb-set-size s1) 3) (rb-set-delete! s1 2) (rb-test "set delete" (rb-set-include? s1 2) false) (rb-test "set size after delete" (rb-set-size s1) 2) (define s2 (rb-set-new)) (rb-set-add! s2 2) (rb-set-add! s2 3) (rb-set-add! s2 4) (define su (rb-set-union s1 s2)) (rb-test "set union includes 1" (rb-set-include? su 1) true) (rb-test "set union includes 4" (rb-set-include? su 4) true) (rb-test "set union size" (rb-set-size su) 4) (define si (rb-set-intersection s1 s2)) (rb-test "set intersection includes 3" (rb-set-include? si 3) true) (rb-test "set intersection excludes 1" (rb-set-include? si 1) false) (rb-test "set intersection size" (rb-set-size si) 1) (define sd (rb-set-difference s1 s2)) (rb-test "set difference includes 1" (rb-set-include? sd 1) true) (rb-test "set difference excludes 3" (rb-set-include? sd 3) false) ;; --------------------------------------------------------------------------- ;; 3. Regexp ;; --------------------------------------------------------------------------- (define rx1 (rb-regexp-new "hel+" "")) (rb-test "regexp?" (rb-regexp? rx1) true) (rb-test "regexp match? yes" (rb-regexp-match? rx1 "say hello") true) (rb-test "regexp match? no" (rb-regexp-match? rx1 "goodbye") false) (define m1 (rb-regexp-match rx1 "say hello world")) (rb-test "regexp match :match" (get m1 "match") "hell") (define rx2 (rb-regexp-new "[0-9]+" "")) (define all (rb-regexp-match-all rx2 "a1b22c333")) (rb-test "regexp match-all count" (len all) 3) (rb-test "regexp match-all first" (get (first all) "match") "1") (rb-test "regexp replace" (rb-regexp-replace rx2 "a1b2" "N") "aNb2") (rb-test "regexp replace-all" (rb-regexp-replace-all rx2 "a1b2" "N") "aNbN") (rb-test "regexp split" (rb-regexp-split (rb-regexp-new "," "") "a,b,c") (list "a" "b" "c")) ;; --------------------------------------------------------------------------- ;; 4. StringIO ;; --------------------------------------------------------------------------- (define sio1 (rb-string-io-new)) (rb-test "string-io?" (rb-string-io? sio1) true) (rb-string-io-write! sio1 "hello") (rb-string-io-write! sio1 " world") (rb-test "string-io string" (rb-string-io-string sio1) "hello world") (rb-string-io-rewind! sio1) (rb-test "string-io eof? no" (rb-string-io-eof? sio1) false) (define ch1 (rb-string-io-read-char sio1)) (define ch2 (rb-string-io-read-char sio1)) ;; Compare char codepoints since = uses reference equality for chars (rb-test "string-io read-char h" (char->integer ch1) 104) (rb-test "string-io read-char e" (char->integer ch2) 101) (rb-test "string-io read rest" (rb-string-io-read sio1) "llo world") (rb-test "string-io eof? yes" (rb-string-io-eof? sio1) true) (rb-test "string-io read at eof" (rb-string-io-read sio1) "") ;; --------------------------------------------------------------------------- ;; 5. Bytevectors ;; --------------------------------------------------------------------------- (define bv1 (rb-bytes-new 4 0)) (rb-test "bytes?" (rb-bytes? bv1) true) (rb-test "bytes length" (rb-bytes-length bv1) 4) (rb-test "bytes get zero" (rb-bytes-get bv1 0) 0) (rb-bytes-set! bv1 0 65) (rb-bytes-set! bv1 1 66) (rb-test "bytes get A" (rb-bytes-get bv1 0) 65) (rb-test "bytes get B" (rb-bytes-get bv1 1) 66) (define bv2 (rb-bytes-from-string "hi")) (rb-test "bytes from-string length" (rb-bytes-length bv2) 2) (rb-test "bytes to-string" (rb-bytes-to-string bv2) "hi") (define bv3 (rb-bytes-append (rb-bytes-from-string "foo") (rb-bytes-from-string "bar"))) (rb-test "bytes append" (rb-bytes-to-string bv3) "foobar") (rb-test "bytes->list" (rb-bytes->list (rb-bytes-from-string "AB")) (list 65 66)) (rb-test "list->bytes" (rb-bytes-to-string (rb-list->bytes (list 72 105))) "Hi") ;; --------------------------------------------------------------------------- ;; 6. Fiber ;; Note: rb-fiber-yield from inside a letrec (JIT-compiled) doesn't ;; properly escape via call/cc continuations. Use top-level helper fns ;; or explicit sequential yields instead of letrec-bound recursion. ;; --------------------------------------------------------------------------- (define fib1 (rb-fiber-new (fn () (rb-fiber-yield 10) (rb-fiber-yield 20) 30))) (rb-test "fiber?" (rb-fiber? fib1) true) (rb-test "fiber alive? before" (rb-fiber-alive? fib1) true) (define fr1 (rb-fiber-resume fib1)) (rb-test "fiber resume 1" fr1 10) (rb-test "fiber alive? mid" (rb-fiber-alive? fib1) true) (define fr2 (rb-fiber-resume fib1)) (rb-test "fiber resume 2" fr2 20) (define fr3 (rb-fiber-resume fib1)) (rb-test "fiber resume 3 (completion)" fr3 30) (rb-test "fiber alive? dead" (rb-fiber-alive? fib1) false) ;; Loop via a top-level helper (avoid letrec — see note above) (define (rb-fiber-loop-helper i) (when (<= i 3) (rb-fiber-yield i) (rb-fiber-loop-helper (+ i 1)))) (define fib2 (rb-fiber-new (fn () (rb-fiber-loop-helper 1) "done"))) (rb-test "fiber loop resume 1" (rb-fiber-resume fib2) 1) (rb-test "fiber loop resume 2" (rb-fiber-resume fib2) 2) (rb-test "fiber loop resume 3" (rb-fiber-resume fib2) 3) (rb-test "fiber loop resume done" (rb-fiber-resume fib2) "done") (rb-test "fiber loop dead" (rb-fiber-alive? fib2) false)