;; ========================================================================== ;; test-sets.sx — Tests for set primitives ;; ========================================================================== ;; -------------------------------------------------------------------------- ;; make-set / set? ;; -------------------------------------------------------------------------- (defsuite "sets:create" (deftest "make-set returns a set" (assert (set? (make-set)))) (deftest "empty set has size 0" (assert= (set-size (make-set)) 0)) (deftest "make-set from list" (let ((s (make-set (list 1 2 3)))) (assert= (set-size s) 3))) (deftest "make-set deduplicates" (let ((s (make-set (list 1 2 2 3 3)))) (assert= (set-size s) 3))) (deftest "set? true for sets" (assert (set? (make-set)))) (deftest "set? false for list" (assert (not (set? (list 1 2 3))))) (deftest "set? false for nil" (assert (not (set? nil)))) (deftest "set? false for number" (assert (not (set? 42))))) ;; -------------------------------------------------------------------------- ;; set-add! / set-member? / set-remove! ;; -------------------------------------------------------------------------- (defsuite "sets:mutation" (deftest "set-add! increases size" (let ((s (make-set))) (set-add! s 1) (assert= (set-size s) 1))) (deftest "set-add! idempotent" (let ((s (make-set))) (set-add! s 1) (set-add! s 1) (assert= (set-size s) 1))) (deftest "set-member? true after add" (let ((s (make-set))) (set-add! s "hello") (assert (set-member? s "hello")))) (deftest "set-member? false for absent" (let ((s (make-set (list 1 2 3)))) (assert (not (set-member? s 99))))) (deftest "set-remove! reduces size" (let ((s (make-set (list 1 2 3)))) (set-remove! s 2) (assert= (set-size s) 2))) (deftest "set-remove! removes element" (let ((s (make-set (list 1 2 3)))) (set-remove! s 2) (assert (not (set-member? s 2))))) (deftest "set-remove! no-op for absent" (let ((s (make-set (list 1 2 3)))) (set-remove! s 99) (assert= (set-size s) 3))) (deftest "set handles strings" (let ((s (make-set))) (set-add! s "a") (set-add! s "b") (assert (and (set-member? s "a") (set-member? s "b"))))) (deftest "set handles symbols" (let ((s (make-set))) (set-add! s (quote foo)) (assert (set-member? s (quote foo)))))) ;; -------------------------------------------------------------------------- ;; set->list / list->set ;; -------------------------------------------------------------------------- (defsuite "sets:conversion" (deftest "list->set creates set" (let ((s (list->set (list 1 2 3)))) (assert (set? s)))) (deftest "list->set size" (let ((s (list->set (list 1 2 3)))) (assert= (set-size s) 3))) (deftest "list->set deduplicates" (let ((s (list->set (list 1 1 2)))) (assert= (set-size s) 2))) (deftest "set->list has all elements" (let ((s (make-set (list 1 2 3))) (lst (set->list s))) (assert= (length lst) 3))) (deftest "set->list round-trip membership" (let ((s (make-set (list 10 20 30))) (lst (set->list s))) (assert (and (set-member? (list->set lst) 10) (set-member? (list->set lst) 20) (set-member? (list->set lst) 30)))))) ;; -------------------------------------------------------------------------- ;; set-union / set-intersection / set-difference ;; -------------------------------------------------------------------------- (defsuite "sets:operations" (deftest "union size" (let ((a (make-set (list 1 2 3))) (b (make-set (list 3 4 5)))) (assert= (set-size (set-union a b)) 5))) (deftest "union contains all" (let ((u (set-union (make-set (list 1 2)) (make-set (list 3 4))))) (assert (and (set-member? u 1) (set-member? u 3) (set-member? u 4))))) (deftest "intersection size" (let ((a (make-set (list 1 2 3))) (b (make-set (list 2 3 4)))) (assert= (set-size (set-intersection a b)) 2))) (deftest "intersection contains overlap" (let ((i (set-intersection (make-set (list 1 2 3)) (make-set (list 2 3 4))))) (assert (and (set-member? i 2) (set-member? i 3) (not (set-member? i 1)))))) (deftest "intersection empty when disjoint" (let ((a (make-set (list 1 2))) (b (make-set (list 3 4)))) (assert= (set-size (set-intersection a b)) 0))) (deftest "difference size" (let ((a (make-set (list 1 2 3))) (b (make-set (list 2 3)))) (assert= (set-size (set-difference a b)) 1))) (deftest "difference keeps only a-exclusive" (let ((d (set-difference (make-set (list 1 2 3)) (make-set (list 2 3 4))))) (assert (and (set-member? d 1) (not (set-member? d 2)) (not (set-member? d 4)))))) (deftest "union does not mutate inputs" (let ((a (make-set (list 1 2))) (b (make-set (list 3 4)))) (set-union a b) (assert= (set-size a) 2)))) ;; -------------------------------------------------------------------------- ;; set-for-each / set-map ;; -------------------------------------------------------------------------- (defsuite "sets:higher-order" (deftest "set-for-each visits all" (let ((s (make-set (list 1 2 3))) (acc (list))) (set-for-each s (fn (v) (set! acc (cons v acc)))) (assert= (length acc) 3))) (deftest "set-map doubles values" (let ((s (make-set (list 1 2 3))) (s2 (set-map s (fn (v) (* v 2))))) (assert (and (set-member? s2 2) (set-member? s2 4) (set-member? s2 6))))) (deftest "set-map result is a set" (assert (set? (set-map (make-set (list 1 2)) (fn (v) v))))))