test: restructure into unit / integration / spec layers + shared harness
Reorganize the flat 49-file test/ into three layers (jpm test recurses, so all
are still discovered):
- test/unit/ white-box component tests (reader, evaluator, types,
persistent-map, lazy-seq, macro, interop, compiler)
- test/integration/ cross-cutting + regression batteries (conformance, jank,
sci-bootstrap/runtime, features, systematic-coverage, api,
core, namespaces, ported clojure suites) and
.../ports/ ported clojure/cljs test batches pending consolidation
- test/spec/ the behavioral contract (built out in following commits)
- test/support/harness.janet shared defspec table runner (cases compared via
Jolt's own =, with a :throws sentinel) + expect= helpers
Files moved with git mv (history preserved) and import paths fixed for depth.
jpm test green. README Test section updated.
Next: build out test/spec/ to cover the public API area-by-area, mining the
integration batteries and filling gaps.
This commit is contained in:
parent
1898308926
commit
16428179fa
52 changed files with 185 additions and 86 deletions
38
test/integration/api-test.janet
Normal file
38
test/integration/api-test.janet
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
(use ../../src/jolt/api)
|
||||
(use ../../src/jolt/types)
|
||||
|
||||
(print "1: init creates context...")
|
||||
(let [ctx (init)]
|
||||
(assert (ctx? ctx) "init returns context")
|
||||
(let [ns (ctx-find-ns ctx "clojure.core")]
|
||||
(assert (ns? ns) "clojure.core namespace exists")
|
||||
(assert (ns-find ns "nil?") "nil? is interned")
|
||||
(assert (ns-find ns "+") "+ is interned")))
|
||||
(print " passed")
|
||||
|
||||
(print "2: eval-string basics...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 42 (eval-string ctx "42")) "eval integer")
|
||||
(assert (= true (eval-string ctx "true")) "eval bool")
|
||||
(assert (= 3 (eval-string ctx "(+ 1 2)")) "eval list"))
|
||||
(print " passed")
|
||||
|
||||
(print "3: eval-string with core fns...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (eval-string ctx "(nil? nil)")) "nil?")
|
||||
(assert (deep= [2 3 4] (normalize-pvecs (eval-string ctx "(map inc [1 2 3])"))) "map+inc")
|
||||
(assert (= 6 (eval-string ctx "(reduce + [1 2 3])")) "reduce"))
|
||||
(print " passed")
|
||||
|
||||
(print "4: eval-string with def...")
|
||||
(let [ctx (init)]
|
||||
(eval-string ctx "(def x 42)")
|
||||
(assert (= 42 (eval-string ctx "x")) "def then resolve"))
|
||||
(print " passed")
|
||||
|
||||
(print "5: eval-string* with bindings...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 99 (eval-string* ctx "y" @{"y" 99})) "bound variable"))
|
||||
(print " passed")
|
||||
|
||||
(print "\nAll API tests passed!")
|
||||
28
test/integration/bootstrap-test.janet
Normal file
28
test/integration/bootstrap-test.janet
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
(use ../../src/jolt/evaluator)
|
||||
(use ../../src/jolt/types)
|
||||
(use ../../src/jolt/reader)
|
||||
(use ../../src/jolt/api)
|
||||
|
||||
(def ctx (init))
|
||||
(def source (slurp "/Users/yogthos/src/sci/src/sci/impl/macros.cljc"))
|
||||
(var s source)
|
||||
(var count 0)
|
||||
|
||||
(while (> (length (string/trim s)) 0)
|
||||
(def [form rest] (parse-next s))
|
||||
(set s rest)
|
||||
(++ count)
|
||||
(if (not (nil? form))
|
||||
(do
|
||||
(printf "eval form %d..." count)
|
||||
(flush)
|
||||
(eval-form ctx @{} form)
|
||||
(printf " OK\n"))))
|
||||
|
||||
(printf "\n%d forms processed\n" count)
|
||||
(printf "ns: %s\n" (ctx-current-ns ctx))
|
||||
|
||||
(let [ns (ctx-find-ns ctx "sci.impl.macros")]
|
||||
(printf "sci.impl.macros bindings:\n")
|
||||
(loop [[name v] :pairs (ns :mappings)]
|
||||
(printf " %s: macro=%q\n" name (v :macro))))
|
||||
154
test/integration/clojure-atom-test.janet
Normal file
154
test/integration/clojure-atom-test.janet
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
# Ported from clojure/test_clojure/atoms.clj + systematic atom tests
|
||||
(use ../../src/jolt/api)
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
|
||||
(print "Ported Atom Tests")
|
||||
|
||||
# --- atom creation ---
|
||||
(print "test atom creation...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(atom? (atom 0))")) "atom?")
|
||||
(assert (= false (ct-eval ctx "(atom? nil)")) "atom? nil")
|
||||
(assert (= false (ct-eval ctx "(atom? 42)")) "atom? number")
|
||||
(assert (= false (ct-eval ctx "(atom? \"x\")")) "atom? string")
|
||||
(assert (= 42 (ct-eval ctx "(deref (atom 42))")) "deref atom")
|
||||
(assert (= 99 (ct-eval ctx "(let [a (atom 99)] @a)")) "@ deref macro"))
|
||||
(print " ok")
|
||||
|
||||
# --- deref on non-atoms ---
|
||||
(print "test deref...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 1 (ct-eval ctx "(deref 1)")) "deref non-atom passes through")
|
||||
(assert (= "x" (ct-eval ctx "(deref \"x\")")) "deref string passes through")
|
||||
(assert (= nil (ct-eval ctx "(deref nil)")) "deref nil"))
|
||||
(print " ok")
|
||||
|
||||
# --- reset! ---
|
||||
(print "test reset!...")
|
||||
(let [ctx (init)]
|
||||
(assert (= :b (ct-eval ctx "(let [a (atom :a)] (reset! a :b))")) "reset! returns new")
|
||||
(assert (= 42 (ct-eval ctx "(let [a (atom 0)] (reset! a 42) @a)")) "reset! updates value")
|
||||
(assert (= true (ct-eval ctx "(= [1 1] (let [a (atom 0)] [(reset! a 1) @a]))")) "reset! returns new, value changed"))
|
||||
(print " ok")
|
||||
|
||||
# --- swap! ---
|
||||
(print "test swap!...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 1 (ct-eval ctx "(let [a (atom 0)] (swap! a inc))")) "swap! inc returns new")
|
||||
(assert (= 2 (ct-eval ctx "(let [a (atom 0)] (swap! a + 2))")) "swap! + 2")
|
||||
(assert (= 3 (ct-eval ctx "(let [a (atom 0)] (swap! a + 1 2) @a)")) "swap! + 1 2")
|
||||
(assert (= 6 (ct-eval ctx "(let [a (atom 0)] (swap! a + 1 2 3) @a)")) "swap! + 1 2 3")
|
||||
(assert (= 10 (ct-eval ctx "(let [a (atom 0)] (swap! a + 1 2 3 4) @a)")) "swap! + 1 2 3 4"))
|
||||
(print " ok")
|
||||
|
||||
# --- swap-vals! (returns [old new]) ---
|
||||
(print "test swap-vals!...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx
|
||||
"(= [0 1] (let [a (atom 0)] (swap-vals! a inc)))")) "swap-vals! inc")
|
||||
(assert (= true (ct-eval ctx
|
||||
"(= [1 2] (let [a (atom 1)] (swap-vals! a inc)))")) "swap-vals! inc from 1")
|
||||
(assert (= 2 (ct-eval ctx
|
||||
"(let [a (atom 1)] (swap-vals! a inc) @a)")) "swap-vals! updates value"))
|
||||
(print " ok")
|
||||
|
||||
# --- swap-vals! with extra args ---
|
||||
(print "test swap-vals! arities...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx
|
||||
"(= [0 1] (let [a (atom 0)] (swap-vals! a + 1)))")) "swap-vals! + 1")
|
||||
(assert (= true (ct-eval ctx
|
||||
"(= [1 3] (let [a (atom 0)] (swap-vals! a + 1) (swap-vals! a + 1 1)))")) "swap-vals! + 1 1")
|
||||
(assert (= true (ct-eval ctx
|
||||
"(= [3 6] (let [a (atom 0)] (swap-vals! a + 1) (swap-vals! a + 1 1) (swap-vals! a + 1 1 1)))")) "swap-vals! + 1 1 1")
|
||||
(assert (= true (ct-eval ctx
|
||||
"(= [6 10] (let [a (atom 0)] (swap-vals! a + 1) (swap-vals! a + 1 1) (swap-vals! a + 1 1 1) (swap-vals! a + 1 1 1 1)))")) "swap-vals! + 1 1 1 1"))
|
||||
(print " ok")
|
||||
|
||||
# --- reset-vals! (returns [old new]) ---
|
||||
(print "test reset-vals!...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx
|
||||
"(= [0 :b] (let [a (atom 0)] (reset-vals! a :b)))")) "reset-vals! returns old new")
|
||||
(assert (= true (ct-eval ctx
|
||||
"(= [:b 42] (let [a (atom 0)] (reset-vals! a :b) (reset-vals! a 42)))")) "reset-vals! chain")
|
||||
(assert (= 42 (ct-eval ctx
|
||||
"(let [a (atom 0)] (reset-vals! a :b) (reset-vals! a 42) @a)")) "reset-vals! updates value"))
|
||||
(print " ok")
|
||||
|
||||
# --- compare-and-set! ---
|
||||
(print "test compare-and-set!...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx
|
||||
"(let [a (atom 0)] (compare-and-set! a 0 1))")) "CAS true match")
|
||||
(assert (= true (ct-eval ctx
|
||||
"(= [true 1] (let [a (atom 0)] [(compare-and-set! a 0 1) @a]))")) "CAS true + value changed")
|
||||
(assert (= true (ct-eval ctx
|
||||
"(= [false 0] (let [a (atom 0)] [(compare-and-set! a 1 2) @a]))")) "CAS false no match")
|
||||
(assert (= true (ct-eval ctx
|
||||
"(= [false 1] (let [a (atom 0)] (compare-and-set! a 0 1) [(compare-and-set! a 0 2) @a]))")) "CAS false after change"))
|
||||
(print " ok")
|
||||
|
||||
# --- validator ---
|
||||
(print "test validator...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 42 (ct-eval ctx
|
||||
"(let [a (atom 0 :validator pos?)] (reset! a 42) @a)")) "validator passes")
|
||||
(assert (= true (ct-eval ctx
|
||||
"(= false (try (let [a (atom 0 :validator pos?)] (reset! a -1) true) (catch Exception e false)))")) "validator blocks invalid reset!")
|
||||
(assert (= true (ct-eval ctx
|
||||
"(= false (try (let [a (atom 0 :validator pos?)] (swap! a (fn [x] -1)) true) (catch Exception e false)))")) "validator blocks invalid swap!")
|
||||
(assert (= nil (ct-eval ctx "(set-validator! (atom 0) pos?)")) "set-validator! returns nil")
|
||||
(assert (= nil (ct-eval ctx "(get-validator (atom 0))")) "get-validator nil default")
|
||||
(assert (= true (ct-eval ctx
|
||||
"(= even? (do (def a (atom 0)) (set-validator! a even?) (get-validator a)))")) "get-validator returns set fn"))
|
||||
(print " ok")
|
||||
|
||||
# --- watches ---
|
||||
(print "test watches...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx
|
||||
"(empty? (:watches (atom 0)))")) "atom starts with empty watches")
|
||||
(assert (= true (ct-eval ctx
|
||||
"(= [0 42] (let [a (atom 0)
|
||||
w (atom nil)]
|
||||
(add-watch a :my-key (fn [k ref old new] (reset! w [old new])))
|
||||
(swap! a + 42)
|
||||
@w))")) "add-watch triggers on swap!")
|
||||
(assert (= true (ct-eval ctx
|
||||
"(= :unchanged (let [a (atom 0)
|
||||
w (atom :unchanged)]
|
||||
(add-watch a :x (fn [_ _ _ _] (reset! w :fired)))
|
||||
(remove-watch a :x)
|
||||
(swap! a inc)
|
||||
@w))")) "remove-watch stops notification")
|
||||
(assert (= true (ct-eval ctx
|
||||
"(= 2 (let [a (atom 0)]
|
||||
(add-watch a :foo (fn [_ _ _ _] nil))
|
||||
(add-watch a :bar (fn [_ _ _ _] nil))
|
||||
(count (:watches a))))")) "multiple watches")
|
||||
(assert (= true (ct-eval ctx
|
||||
"(= 0 (let [a (atom 0)]
|
||||
(add-watch a :foo (fn [_ _ _ _] nil))
|
||||
(remove-watch a :foo)
|
||||
(count (:watches a))))")) "remove-watch clears count")
|
||||
(assert (= true (ct-eval ctx
|
||||
"(= 2 (let [a (atom 0)
|
||||
fired (atom [])]
|
||||
(add-watch a :w1 (fn [_ _ o n] (swap! fired conj [:w1 o n])))
|
||||
(add-watch a :w2 (fn [_ _ o n] (swap! fired conj [:w2 o n])))
|
||||
(reset! a 99)
|
||||
(count @fired)))")) "multiple watches both fire"))
|
||||
(print " ok")
|
||||
|
||||
# --- metadata on atoms ---
|
||||
(print "test atom metadata...")
|
||||
(let [ctx (init)]
|
||||
(assert (= nil (ct-eval ctx "(meta (atom 0))")) "atom meta nil by default")
|
||||
(assert (= true (ct-eval ctx
|
||||
"(= {:foo \"bar\"} (meta (atom 0 :meta {:foo \"bar\"})))")) "atom with :meta")
|
||||
(assert (= true (ct-eval ctx
|
||||
"(= {:validated true} (meta (atom 0 :validator pos? :meta {:validated true})))")) "atom with validator and meta"))
|
||||
(print " ok")
|
||||
|
||||
(print "\nAll Ported Atom tests passed!")
|
||||
151
test/integration/clojure-control-test.janet
Normal file
151
test/integration/clojure-control-test.janet
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
# Ported from clojure/test_clojure/control.clj
|
||||
(use ../../src/jolt/api)
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
|
||||
(print "Ported Control Tests")
|
||||
|
||||
# --- test-do ---
|
||||
(print "test-do...")
|
||||
(let [ctx (init)]
|
||||
(assert (= nil (ct-eval ctx "(do)")) "do empty -> nil")
|
||||
(assert (= 1 (ct-eval ctx "(do 1)")) "do returns last")
|
||||
(assert (= 2 (ct-eval ctx "(do 1 2)")) "do returns last")
|
||||
(assert (= 5 (ct-eval ctx "(do 1 2 3 4 5)")) "do returns last"))
|
||||
(print " ok")
|
||||
|
||||
# --- test-loop ---
|
||||
(print "test-loop...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 1 (ct-eval ctx "(loop [] 1)")) "loop body")
|
||||
(assert (= 3 (ct-eval ctx "(loop [a 1] (if (< a 3) (recur (inc a)) a))")) "loop recur")
|
||||
(assert (= true (ct-eval ctx
|
||||
"(= [6 4 2] (loop [a () b [1 2 3]]
|
||||
(if (seq b)
|
||||
(recur (conj a (* 2 (first b))) (next b))
|
||||
a)))")) "loop accum list")
|
||||
(assert (= true (ct-eval ctx
|
||||
"(= [2 4 6] (loop [a [] b [1 2 3]]
|
||||
(if (seq b)
|
||||
(recur (conj a (* 2 (first b))) (next b))
|
||||
a)))")) "loop accum vector"))
|
||||
(print " ok")
|
||||
|
||||
# --- test-when ---
|
||||
(print "test-when...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 1 (ct-eval ctx "(when true 1)")) "when true")
|
||||
(assert (= nil (ct-eval ctx "(when true)")) "when true no body")
|
||||
(assert (= nil (ct-eval ctx "(when false)")) "when false")
|
||||
(assert (= nil (ct-eval ctx "(when false 1)")) "when false with body"))
|
||||
(print " ok")
|
||||
|
||||
# --- test-when-not ---
|
||||
(print "test-when-not...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 1 (ct-eval ctx "(when-not false 1)")) "when-not false")
|
||||
(assert (= nil (ct-eval ctx "(when-not true)")) "when-not true no body")
|
||||
(assert (= nil (ct-eval ctx "(when-not false)")) "when-not false no body")
|
||||
(assert (= nil (ct-eval ctx "(when-not true 1)")) "when-not true with body"))
|
||||
(print " ok")
|
||||
|
||||
# --- test-if-not ---
|
||||
(print "test-if-not...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 1 (ct-eval ctx "(if-not false 1)")) "if-not false")
|
||||
(assert (= 1 (ct-eval ctx "(if-not false 1 2)")) "if-not false with else")
|
||||
(assert (= nil (ct-eval ctx "(if-not true 1)")) "if-not true")
|
||||
(assert (= 2 (ct-eval ctx "(if-not true 1 2)")) "if-not true with else"))
|
||||
(print " ok")
|
||||
|
||||
# --- test-when-let ---
|
||||
(print "test-when-let...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 1 (ct-eval ctx "(when-let [a 1] a)")) "when-let simple")
|
||||
(assert (= 2 (ct-eval ctx "(when-let [[a b] '(1 2)] b)")) "when-let destructure")
|
||||
(assert (= nil (ct-eval ctx "(when-let [a false] 1)")) "when-let false"))
|
||||
(print " ok")
|
||||
|
||||
# --- test-if-let ---
|
||||
(print "test-if-let...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 1 (ct-eval ctx "(if-let [a 1] a)")) "if-let simple")
|
||||
(assert (= 2 (ct-eval ctx "(if-let [[a b] '(1 2)] b)")) "if-let destructure")
|
||||
(assert (= nil (ct-eval ctx "(if-let [a false] 1)")) "if-let false")
|
||||
(assert (= 1 (ct-eval ctx "(if-let [a false] a 1)")) "if-let false with else"))
|
||||
(print " ok")
|
||||
|
||||
# --- test-if-some ---
|
||||
(print "test-if-some...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 1 (ct-eval ctx "(if-some [a 1] a)")) "if-some simple")
|
||||
(assert (= false (ct-eval ctx "(if-some [a false] a)")) "if-some false is some")
|
||||
(assert (= nil (ct-eval ctx "(if-some [a nil] 1)")) "if-some nil")
|
||||
(assert (= 3 (ct-eval ctx "(if-some [[a b] [1 2]] (+ a b))")) "if-some destructure"))
|
||||
(print " ok")
|
||||
|
||||
# --- test-when-some ---
|
||||
(print "test-when-some...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 1 (ct-eval ctx "(when-some [a 1] a)")) "when-some simple")
|
||||
(assert (= 2 (ct-eval ctx "(when-some [[a b] [1 2]] b)")) "when-some destructure")
|
||||
(assert (= false (ct-eval ctx "(when-some [a false] a)")) "when-some false is some")
|
||||
(assert (= nil (ct-eval ctx "(when-some [a nil] 1)")) "when-some nil"))
|
||||
(print " ok")
|
||||
|
||||
# --- test-cond ---
|
||||
(print "test-cond...")
|
||||
(let [ctx (init)]
|
||||
(assert (= nil (ct-eval ctx "(cond)")) "cond empty -> nil")
|
||||
(assert (= nil (ct-eval ctx "(cond nil true)")) "cond nil -> nil")
|
||||
(assert (= nil (ct-eval ctx "(cond false true)")) "cond false -> nil")
|
||||
(assert (= 1 (ct-eval ctx "(cond true 1)")) "cond true -> 1")
|
||||
(assert (= 3 (ct-eval ctx "(cond nil 1 false 2 true 3 true 4)")) "cond third branch")
|
||||
(assert (= :b (ct-eval ctx "(cond false :a true :b)")) "cond skips false")
|
||||
(assert (= :a (ct-eval ctx "(cond true :a true :b)")) "cond takes first true"))
|
||||
(print " ok")
|
||||
|
||||
# --- test-condp ---
|
||||
(print "test-condp...")
|
||||
(let [ctx (init)]
|
||||
(assert (= :pass (ct-eval ctx "(condp = 1 1 :pass 2 :fail)")) "condp match first")
|
||||
(assert (= :pass (ct-eval ctx "(condp = 1 2 :fail 1 :pass)")) "condp match second")
|
||||
(assert (= :pass (ct-eval ctx "(condp = 1 2 :fail :pass)")) "condp default"))
|
||||
(print " ok")
|
||||
|
||||
# --- test-dotimes ---
|
||||
(print "test-dotimes...")
|
||||
(let [ctx (init)]
|
||||
(assert (= nil (ct-eval ctx "(dotimes [n 1] n)")) "dotimes returns nil")
|
||||
(assert (= 3 (ct-eval ctx
|
||||
"(let [a (atom 0)]
|
||||
(dotimes [n 3] (swap! a inc))
|
||||
@a)")) "dotimes 3 iterations")
|
||||
(assert (= [0 1 2] (ct-eval ctx
|
||||
"(let [a (atom [])]
|
||||
(dotimes [n 3] (swap! a conj n))
|
||||
@a)")) "dotimes with index"))
|
||||
(print " ok")
|
||||
|
||||
# --- test-while ---
|
||||
(print "test-while...")
|
||||
(let [ctx (init)]
|
||||
(assert (= nil (ct-eval ctx "(while nil 1)")) "while nil returns nil")
|
||||
(assert (= true (ct-eval ctx
|
||||
"(= [0 nil]
|
||||
(let [a (atom 3)
|
||||
w (while (pos? @a) (swap! a dec))]
|
||||
[@a w]))")) "while dec to 0"))
|
||||
(print " ok")
|
||||
|
||||
# --- test-case ---
|
||||
(print "test-case...")
|
||||
(let [ctx (init)]
|
||||
(assert (= :number (ct-eval ctx "(case 1 1 :number :default)")) "case match 1")
|
||||
(assert (= :string (ct-eval ctx "(case \"foo\" \"foo\" :string :default)")) "case match string")
|
||||
(assert (= :kw (ct-eval ctx "(case :zap :zap :kw :default)")) "case match keyword")
|
||||
(assert (= :symbol (ct-eval ctx "(case 'pow pow :symbol :default)")) "case match symbol")
|
||||
(assert (= :default (ct-eval ctx "(case 99 1 :number :default)")) "case default")
|
||||
(assert (= :matched (ct-eval ctx "(case 2 (2 3 4) :matched :default)")) "case one-of-many"))
|
||||
(print " ok")
|
||||
|
||||
(print "\nAll Ported Control tests passed!")
|
||||
35
test/integration/clojure-for-test.janet
Normal file
35
test/integration/clojure-for-test.janet
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# Ported from clojure/test_clojure/for.clj
|
||||
(use ../../src/jolt/api)
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
|
||||
(print "Ported For Tests")
|
||||
|
||||
# --- When ---
|
||||
(print "test-for :when...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx
|
||||
"(= (for [x (range 10) :when (odd? x)] x)
|
||||
(quote (1 3 5 7 9)))")) "for :when odd?")
|
||||
(assert (= true (ct-eval ctx
|
||||
"(= (for [x (range 4) y (range 4) :when (odd? y)] [x y])
|
||||
(quote ([0 1] [0 3] [1 1] [1 3] [2 1] [2 3] [3 1] [3 3])))")) "for nested :when"))
|
||||
(print " ok")
|
||||
|
||||
# --- Let ---
|
||||
(print "test-for :let...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx
|
||||
"(= (for [x (range 3) y (range 3) :let [z (+ x y)] :when (odd? z)] [x y z])
|
||||
(quote ([0 1 1] [1 0 1] [1 2 3] [2 1 3])))")) "for :let :when"))
|
||||
(print " ok")
|
||||
|
||||
# --- Nesting ---
|
||||
(print "test-for nesting...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx
|
||||
"(= (for [x (quote (a b)) y (interpose x (quote (1 2))) z (list x y)] [x y z])
|
||||
(quote ([a 1 a] [a 1 1] [a a a] [a a a] [a 2 a] [a 2 2]
|
||||
[b 1 b] [b 1 1] [b b b] [b b b] [b 2 b] [b 2 2])))")) "for nested interpose"))
|
||||
(print " ok")
|
||||
|
||||
(print "\nAll Ported For tests passed!")
|
||||
127
test/integration/clojure-logic-test.janet
Normal file
127
test/integration/clojure-logic-test.janet
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
# Ported from clojure/test_clojure/logic.clj
|
||||
(use ../../src/jolt/api)
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
|
||||
(print "Ported Logic Tests (from clojure/test-clojure/logic.clj)")
|
||||
|
||||
# --- test-if ---
|
||||
(print "test-if: true/false/nil...")
|
||||
(let [ctx (init)]
|
||||
(assert (= :t (ct-eval ctx "(if true :t)")) "if true")
|
||||
(assert (= :t (ct-eval ctx "(if true :t :f)")) "if true with else")
|
||||
(assert (= nil (ct-eval ctx "(if false :t)")) "if false no else")
|
||||
(assert (= :f (ct-eval ctx "(if false :t :f)")) "if false with else")
|
||||
(assert (= nil (ct-eval ctx "(if nil :t)")) "if nil no else")
|
||||
(assert (= :f (ct-eval ctx "(if nil :t :f)")) "if nil with else"))
|
||||
(print " ok")
|
||||
|
||||
(print "test-if: zero/empty is true...")
|
||||
(let [ctx (init)]
|
||||
(assert (= :t (ct-eval ctx "(if 0 :t :f)")) "0 is true")
|
||||
(assert (= :t (ct-eval ctx "(if 0.0 :t :f)")) "0.0 is true")
|
||||
(assert (= :t (ct-eval ctx "(if \"\" :t :f)")) "empty string is true")
|
||||
(assert (= :t (ct-eval ctx "(if () :t :f)")) "empty list is true")
|
||||
(assert (= :t (ct-eval ctx "(if [] :t :f)")) "empty vector is true")
|
||||
(assert (= :t (ct-eval ctx "(if {} :t :f)")) "empty map is true")
|
||||
(assert (= :t (ct-eval ctx "(if #{} :t :f)")) "empty set is true"))
|
||||
(print " ok")
|
||||
|
||||
(print "test-if: anything except nil/false is true...")
|
||||
(let [ctx (init)]
|
||||
(assert (= :t (ct-eval ctx "(if 42 :t :f)")) "42 is true")
|
||||
(assert (= :t (ct-eval ctx "(if 1.2 :t :f)")) "1.2 is true")
|
||||
(assert (= :t (ct-eval ctx "(if \"abc\" :t :f)")) "string is true")
|
||||
(assert (= :t (ct-eval ctx "(if 'abc :t :f)")) "symbol is true")
|
||||
(assert (= :t (ct-eval ctx "(if :kw :t :f)")) "keyword is true")
|
||||
(assert (= :t (ct-eval ctx "(if '(1 2) :t :f)")) "list is true")
|
||||
(assert (= :t (ct-eval ctx "(if [1 2] :t :f)")) "vector is true")
|
||||
(assert (= :t (ct-eval ctx "(if {:a 1 :b 2} :t :f)")) "map is true")
|
||||
(assert (= :t (ct-eval ctx "(if #{1 2} :t :f)")) "set is true"))
|
||||
(print " ok")
|
||||
|
||||
# --- test-nil-punning ---
|
||||
(print "test-nil-punning...")
|
||||
(let [ctx (init)]
|
||||
(assert (= :yes (ct-eval ctx "(if (first []) :no :yes)")) "first [] nil")
|
||||
(assert (= :yes (ct-eval ctx "(if (next [1]) :no :yes)")) "next [1] nil")
|
||||
(assert (= :no (ct-eval ctx "(if (rest [1]) :no :yes)")) "rest [1] non-nil")
|
||||
(assert (= :yes (ct-eval ctx "(if (seq nil) :no :yes)")) "seq nil")
|
||||
(assert (= :yes (ct-eval ctx "(if (seq []) :no :yes)")) "seq [] nil")
|
||||
(assert (= :no (ct-eval ctx "(if (lazy-seq nil) :no :yes)")) "lazy-seq nil non-nil")
|
||||
(assert (= :no (ct-eval ctx "(if (lazy-seq []) :no :yes)")) "lazy-seq [] non-nil")
|
||||
(assert (= :no (ct-eval ctx "(if (filter (fn [x] (> x 10)) [1 2 3]) :no :yes)")) "filter non-match non-nil")
|
||||
(assert (= :no (ct-eval ctx "(if (map identity []) :no :yes)")) "map empty non-nil")
|
||||
(assert (= :no (ct-eval ctx "(if (apply concat []) :no :yes)")) "apply concat [] non-nil")
|
||||
(assert (= :no (ct-eval ctx "(if (concat) :no :yes)")) "concat empty non-nil")
|
||||
(assert (= :no (ct-eval ctx "(if (concat []) :no :yes)")) "concat [] non-nil")
|
||||
(assert (= :no (ct-eval ctx "(if (reverse nil) :no :yes)")) "reverse nil non-nil")
|
||||
(assert (= :no (ct-eval ctx "(if (reverse []) :no :yes)")) "reverse [] non-nil")
|
||||
(assert (= :no (ct-eval ctx "(if (sort nil) :no :yes)")) "sort nil non-nil")
|
||||
(assert (= :no (ct-eval ctx "(if (sort []) :no :yes)")) "sort [] non-nil"))
|
||||
(print " ok")
|
||||
|
||||
# --- test-and ---
|
||||
(print "test-and...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(and)")) "and empty")
|
||||
(assert (= true (ct-eval ctx "(and true)")) "and true")
|
||||
(assert (= nil (ct-eval ctx "(and nil)")) "and nil")
|
||||
(assert (= false (ct-eval ctx "(and false)")) "and false")
|
||||
(assert (= nil (ct-eval ctx "(and true nil)")) "and true nil")
|
||||
(assert (= false (ct-eval ctx "(and true false)")) "and true false")
|
||||
(assert (= "abc" (ct-eval ctx "(and 1 true :kw 'abc \"abc\")")) "and chain last")
|
||||
(assert (= nil (ct-eval ctx "(and 1 true :kw nil 'abc \"abc\")")) "and chain nil")
|
||||
(assert (= false (ct-eval ctx "(and 1 true :kw 'abc \"abc\" false)")) "and chain false"))
|
||||
(print " ok")
|
||||
|
||||
# --- test-or ---
|
||||
(print "test-or...")
|
||||
(let [ctx (init)]
|
||||
(assert (= nil (ct-eval ctx "(or)")) "or empty")
|
||||
(assert (= true (ct-eval ctx "(or true)")) "or true")
|
||||
(assert (= nil (ct-eval ctx "(or nil)")) "or nil")
|
||||
(assert (= false (ct-eval ctx "(or false)")) "or false")
|
||||
(assert (= true (ct-eval ctx "(or nil false true)")) "or nil false true")
|
||||
(assert (= 1 (ct-eval ctx "(or nil false 1 2)")) "or picks first truthy")
|
||||
(assert (= "abc" (ct-eval ctx "(or nil false \"abc\" :kw)")) "or picks string")
|
||||
(assert (= nil (ct-eval ctx "(or false nil)")) "or false nil -> nil")
|
||||
(assert (= false (ct-eval ctx "(or nil false)")) "or nil false -> false")
|
||||
(assert (= false (ct-eval ctx "(or nil nil nil false)")) "or chain to false")
|
||||
(assert (= true (ct-eval ctx "(or nil true false)")) "or nil true false"))
|
||||
(print " ok")
|
||||
|
||||
# --- test-not ---
|
||||
(print "test-not...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(not nil)")) "not nil")
|
||||
(assert (= true (ct-eval ctx "(not false)")) "not false")
|
||||
(assert (= false (ct-eval ctx "(not true)")) "not true")
|
||||
(assert (= false (ct-eval ctx "(not 0)")) "not 0")
|
||||
(assert (= false (ct-eval ctx "(not 0.0)")) "not 0.0")
|
||||
(assert (= false (ct-eval ctx "(not 42)")) "not 42")
|
||||
(assert (= false (ct-eval ctx "(not 1.2)")) "not 1.2")
|
||||
(assert (= false (ct-eval ctx "(not \"\")")) "not empty string")
|
||||
(assert (= false (ct-eval ctx "(not \"abc\")")) "not string")
|
||||
(assert (= false (ct-eval ctx "(not 'abc)")) "not symbol")
|
||||
(assert (= false (ct-eval ctx "(not :kw)")) "not keyword")
|
||||
(assert (= false (ct-eval ctx "(not ())")) "not empty list")
|
||||
(assert (= false (ct-eval ctx "(not '(1 2))")) "not list")
|
||||
(assert (= false (ct-eval ctx "(not []))")) "not empty vector")
|
||||
(assert (= false (ct-eval ctx "(not [1 2])")) "not vector")
|
||||
(assert (= false (ct-eval ctx "(not {})")) "not empty map")
|
||||
(assert (= false (ct-eval ctx "(not {:a 1 :b 2})")) "not map")
|
||||
(assert (= false (ct-eval ctx "(not #{})")) "not empty set")
|
||||
(assert (= false (ct-eval ctx "(not #{1 2})")) "not set"))
|
||||
(print " ok")
|
||||
|
||||
# --- test-some? ---
|
||||
(print "test-some?...")
|
||||
(let [ctx (init)]
|
||||
(assert (= false (ct-eval ctx "(some? nil)")) "some? nil")
|
||||
(assert (= true (ct-eval ctx "(some? false)")) "some? false")
|
||||
(assert (= true (ct-eval ctx "(some? 0)")) "some? 0")
|
||||
(assert (= true (ct-eval ctx "(some? \"abc\")")) "some? string")
|
||||
(assert (= true (ct-eval ctx "(some? [])")) "some? empty vec"))
|
||||
(print " ok")
|
||||
|
||||
(print "\nAll Ported Logic tests passed!")
|
||||
63
test/integration/clojure-macros-test.janet
Normal file
63
test/integration/clojure-macros-test.janet
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
# Ported from clojure/test_clojure/macros.clj
|
||||
(use ../../src/jolt/api)
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
|
||||
(print "Ported Macros Tests")
|
||||
|
||||
# --- -> and ->> threading ---
|
||||
(print "test -> and ->>...")
|
||||
(let [ctx (init)]
|
||||
(ct-eval ctx "(defmacro c [arg] (if (= 'b (first arg)) :foo :bar))")
|
||||
(ct-eval ctx "(def a 2)")
|
||||
(ct-eval ctx "(def b identity)")
|
||||
(assert (= :foo (ct-eval ctx "(-> a b c)")) "-> threading")
|
||||
(assert (= :foo (ct-eval ctx "(->> a b c)")) "->> threading"))
|
||||
(print " ok")
|
||||
|
||||
# --- some-> ---
|
||||
(print "test some->...")
|
||||
(let [ctx (init)]
|
||||
(assert (= nil (ct-eval ctx "(some-> nil)")) "some-> nil")
|
||||
(assert (= 0 (ct-eval ctx "(some-> 0)")) "some-> 0")
|
||||
(assert (= -1 (ct-eval ctx "(some-> 1 (- 2))")) "some-> with form")
|
||||
(ct-eval ctx "(defn const-nil [_] nil)")
|
||||
(assert (= nil (ct-eval ctx "(some-> 1 const-nil (- 2))")) "some-> stop at nil"))
|
||||
(print " ok")
|
||||
|
||||
# --- some->> ---
|
||||
(print "test some->>...")
|
||||
(let [ctx (init)]
|
||||
(assert (= nil (ct-eval ctx "(some->> nil)")) "some->> nil")
|
||||
(assert (= 0 (ct-eval ctx "(some->> 0)")) "some->> 0")
|
||||
(assert (= 1 (ct-eval ctx "(some->> 1 (- 2))")) "some->> with form")
|
||||
(ct-eval ctx "(defn const-nil2 [_] nil)")
|
||||
(assert (= nil (ct-eval ctx "(some->> 1 const-nil2 (- 2))")) "some->> stop at nil"))
|
||||
(print " ok")
|
||||
|
||||
# --- cond-> ---
|
||||
(print "test cond->...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 0 (ct-eval ctx "(cond-> 0)")) "cond-> single")
|
||||
(assert (= -1 (ct-eval ctx "(cond-> 0 true inc true (- 2))")) "cond-> with tests")
|
||||
(assert (= 0 (ct-eval ctx "(cond-> 0 false inc)")) "cond-> false test")
|
||||
(assert (= -1 (ct-eval ctx "(cond-> 1 true (- 2) false inc)")) "cond-> mix"))
|
||||
(print " ok")
|
||||
|
||||
# --- cond->> ---
|
||||
(print "test cond->>...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 0 (ct-eval ctx "(cond->> 0)")) "cond->> single")
|
||||
(assert (= 1 (ct-eval ctx "(cond->> 0 true inc true (- 2))")) "cond->> with tests")
|
||||
(assert (= 0 (ct-eval ctx "(cond->> 0 false inc)")) "cond->> false test")
|
||||
(assert (= 1 (ct-eval ctx "(cond->> 1 true (- 2) false inc)")) "cond->> mix"))
|
||||
(print " ok")
|
||||
|
||||
# --- as-> ---
|
||||
(print "test as->...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 0 (ct-eval ctx "(as-> 0 x)")) "as-> single")
|
||||
(assert (= 1 (ct-eval ctx "(as-> 0 x (inc x))")) "as-> one form")
|
||||
(assert (= 2 (ct-eval ctx "(as-> [0 1] x (map inc x) (reverse x) (first x))")) "as-> chain"))
|
||||
(print " ok")
|
||||
|
||||
(print "\nAll Ported Macros tests passed!")
|
||||
325
test/integration/conformance-test.janet
Normal file
325
test/integration/conformance-test.janet
Normal file
|
|
@ -0,0 +1,325 @@
|
|||
# Clojure conformance harness (phase 1: extracted assertion pairs).
|
||||
#
|
||||
# Each case is [name expected-clj actual-clj]. The harness evaluates the
|
||||
# single Clojure program (= <expected> <actual>) inside a fresh jolt ctx
|
||||
# and asserts it returns boolean true. Comparison therefore uses jolt's OWN
|
||||
# `=`, which implements Clojure sequential/collection equality -- so results
|
||||
# reflect real Clojure semantics rather than Janet-level identity.
|
||||
#
|
||||
# `actual` may be a multi-form body; wrap such cases in (do ...).
|
||||
#
|
||||
# Source of truth: ~/src/clojure/test/clojure/test_clojure/*.clj
|
||||
# These pairs are hand-extracted from those files (and canonical idioms)
|
||||
# until a minimal clojure.test lets us load the real files directly.
|
||||
|
||||
(use ../../src/jolt/api)
|
||||
|
||||
(def cases
|
||||
[
|
||||
### ---- CRITICAL: lazy sequences ----
|
||||
["self-ref lazy-cat fib"
|
||||
"(quote (0 1 1 2 3 5 8 13 21 34))"
|
||||
"(do (def fib-seq (lazy-cat [0 1] (map + (rest fib-seq) fib-seq))) (take 10 fib-seq))"]
|
||||
["self-ref lazy-seq ones"
|
||||
"(quote (1 1 1 1 1))"
|
||||
"(do (def ones (lazy-seq (cons 1 ones))) (take 5 ones))"]
|
||||
["self-ref lazy-seq nats"
|
||||
"(quote (0 1 2 3 4))"
|
||||
"(do (def nats (lazy-cat [0] (map inc nats))) (take 5 nats))"]
|
||||
|
||||
### ---- CRITICAL: multi-collection map ----
|
||||
["map two colls" "(quote (11 22 33))" "(map + [1 2 3] [10 20 30])"]
|
||||
["map three colls" "(quote (12 24 36))" "(map + [1 2 3] [10 20 30] [1 2 3])"]
|
||||
["map uneven (shortest)" "(quote ([1 :a] [2 :b]))" "(map vector [1 2 3] [:a :b])"]
|
||||
["map over range+vec" "(quote (1 3 5))" "(map + (range 3) [1 2 3])"]
|
||||
["map fn list arg" "(quote (2 3 4))" "(map inc (list 1 2 3))"]
|
||||
|
||||
### ---- CRITICAL: iterate / infinite seqs ----
|
||||
["iterate" "(quote (0 1 2 3 4))" "(take 5 (iterate inc 0))"]
|
||||
["iterate double" "(quote (1 2 4 8 16))" "(take 5 (iterate (fn [x] (* 2 x)) 1))"]
|
||||
["range over inf map" "(quote (1 2 3))" "(take 3 (map inc (range)))"]
|
||||
["count of take" "100" "(count (take 100 (range)))"]
|
||||
["last of take" "5" "(last (take 5 (iterate inc 1)))"]
|
||||
|
||||
### ---- CRITICAL: collections as IFn ----
|
||||
["vector as fn" ":b" "([:a :b :c] 1)"]
|
||||
["map as fn" "1" "({:a 1} :a)"]
|
||||
["map as fn miss" "nil" "({:a 1} :z)"]
|
||||
["map as fn default" "99" "({:a 1} :z 99)"]
|
||||
["set as fn" "2" "(#{1 2 3} 2)"]
|
||||
["set as fn miss" "nil" "(#{1 2 3} 9)"]
|
||||
["keyword as fn" "1" "(:a {:a 1})"]
|
||||
["map fn over coll" "(quote (1 3))" "(map {:a 1 :b 3} [:a :b])"]
|
||||
|
||||
### ---- CRITICAL: vec / into over lazy + maps ----
|
||||
["vec of map-result" "[2 3 4]" "(vec (map inc [1 2 3]))"]
|
||||
["vec of range" "[0 1 2 3 4]" "(vec (range 5))"]
|
||||
["into vec" "[1 2 3 4 5 6]" "(into [1 2 3] [4 5 6])"]
|
||||
["into vec from lazy" "[2 3 4]" "(into [] (map inc [1 2 3]))"]
|
||||
["into map pairs" "{:a 1 :b 2}" "(into {} [[:a 1] [:b 2]])"]
|
||||
["into map onto map" "{:a 1 :b 2 :c 3}" "(into {:a 1} [[:b 2] [:c 3]])"]
|
||||
["into list" "(quote (3 2 1))" "(into (list) [1 2 3])"]
|
||||
|
||||
### ---- HIGH: destructuring ----
|
||||
["destr nested seq" "[1 2 3]" "(let [[a [b c]] [1 [2 3]]] [a b c])"]
|
||||
["destr rest+as" "[1 (quote (2 3)) [1 2 3]]" "(let [[a & r :as all] [1 2 3]] [a r all])"]
|
||||
["destr map :keys" "[1 2]" "(let [{:keys [a b]} {:a 1 :b 2}] [a b])"]
|
||||
["destr map :or" "[1 99]" "(let [{:keys [a b] :or {b 99}} {:a 1}] [a b])"]
|
||||
["destr map :strs" "[1 2]" "(let [{:strs [a b]} {\"a\" 1 \"b\" 2}] [a b])"]
|
||||
["destr map :as" "[1 {:a 1}]" "(let [{:keys [a] :as m} {:a 1}] [a m])"]
|
||||
["destr nested map" "5" "(let [{{:keys [x]} :pos} {:pos {:x 5}}] x)"]
|
||||
["destr fn-param seq" "7" "((fn [[a b]] (+ a b)) [3 4])"]
|
||||
["destr fn-param map" "3" "((fn [{:keys [a b]}] (+ a b)) {:a 1 :b 2})"]
|
||||
["destr let map key" "1" "(let [{a :a} {:a 1}] a)"]
|
||||
|
||||
### ---- HIGH: update / assoc-in on map literals ----
|
||||
["update inc" "{:a 2}" "(update {:a 1} :a inc)"]
|
||||
["update extra args" "{:a 111}" "(update {:a 1} :a + 10 100)"]
|
||||
["update-in" "{:a {:b 2}}" "(update-in {:a {:b 1}} [:a :b] inc)"]
|
||||
["assoc-in" "{:a {:b 1 :c 2}}" "(assoc-in {:a {:b 1}} [:a :c] 2)"]
|
||||
["assoc-in create" "{:a {:b 1}}" "(assoc-in {} [:a :b] 1)"]
|
||||
["update-in fnil" "{:a {:b 1}}" "(update-in {} [:a :b] (fnil inc 0))"]
|
||||
["get-in" "1" "(get-in {:a {:b {:c 1}}} [:a :b :c])"]
|
||||
|
||||
### ---- HIGH: str semantics ----
|
||||
["str nil empty" "\"\"" "(str nil)"]
|
||||
["str concat nil" "\"a1\"" "(str \"a\" 1 nil)"]
|
||||
["str keyword" "\":b\"" "(str :b)"]
|
||||
["str symbol" "\"foo\"" "(str (quote foo))"]
|
||||
["str mixed" "\"a:b1\"" "(str \"a\" :b 1)"]
|
||||
["str seq" "\"[1 2 3]\"" "(str [1 2 3])"]
|
||||
|
||||
### ---- HIGH: dispatch ----
|
||||
["multimethod" "9" "(do (defmulti area :shape) (defmethod area :sq [s] (* (:s s) (:s s))) (area {:shape :sq :s 3}))"]
|
||||
["multimethod default" ":def" "(do (defmulti f identity) (defmethod f :default [x] :def) (f 99))"]
|
||||
["protocol on record" "16" "(do (defprotocol Sh (ar [s])) (defrecord Sq [side] Sh (ar [_] (* side side))) (ar (->Sq 4)))"]
|
||||
["reify dispatch" "42" "(do (defprotocol P (m [_])) (m (reify P (m [_] 42))))"]
|
||||
|
||||
### ---- HIGH: aliased namespace calls ----
|
||||
["require :as alias" "\"1,2,3\"" "(do (require (quote [clojure.string :as s])) (s/join \",\" [1 2 3]))"]
|
||||
|
||||
### ---- MED: missing core fns ----
|
||||
["peek vec" "3" "(peek [1 2 3])"]
|
||||
["peek list" "1" "(peek (list 1 2 3))"]
|
||||
["pop vec" "[1 2]" "(pop [1 2 3])"]
|
||||
["pop list" "(quote (2 3))" "(pop (list 1 2 3))"]
|
||||
["subvec" "[2 3]" "(subvec [1 2 3 4 5] 1 3)"]
|
||||
["subvec to-end" "[3 4 5]" "(subvec [1 2 3 4 5] 2)"]
|
||||
["reduce-kv" "{:a 2 :b 3}" "(reduce-kv (fn [m k v] (assoc m k (inc v))) {} {:a 1 :b 2})"]
|
||||
|
||||
### ---- iterating maps yields entries ----
|
||||
["map over map" "true" "(= #{1 2} (set (map val {:a 1 :b 2})))"]
|
||||
["map keys over map" "true" "(= #{:a :b} (set (map key {:a 1 :b 2})))"]
|
||||
["first of map" "true" "(let [e (first {:a 1})] (and (= (key e) :a) (= (val e) 1)))"]
|
||||
["vec of map" "[[:a 1]]" "(vec {:a 1})"]
|
||||
["reduce over map" "6" "(reduce (fn [a [k v]] (+ a v)) 0 {:a 1 :b 2 :c 3})"]
|
||||
["into transform map" "{:a 2 :b 3}" "(into {} (map (fn [[k v]] [k (inc v)]) {:a 1 :b 2}))"]
|
||||
["filter over map" "true" "(= [[:b 2]] (filterv (fn [[k v]] (> v 1)) {:a 1 :b 2}))"]
|
||||
["doall realizes" "(quote (2 3 4))" "(doall (map inc [1 2 3]))"]
|
||||
["tree-seq" "(quote (1 2 3))" "(map (fn [x] x) (filter (complement coll?) (tree-seq coll? seq [1 [2 [3]]])))"]
|
||||
["key/val" "true" "(let [e [:k 9]] (and (= :k (key e)) (= 9 (val e))))"]
|
||||
["nat-int?" "true" "(and (nat-int? 0) (nat-int? 5) (not (nat-int? -1)))"]
|
||||
["list* prepend" "(quote (1 2 3 4))" "(list* 1 2 [3 4])"]
|
||||
["cycle" "(quote (1 2 3 1 2 3 1))" "(take 7 (cycle [1 2 3]))"]
|
||||
["partition-all" "(quote ((1 2) (3 4) (5)))" "(partition-all 2 [1 2 3 4 5])"]
|
||||
["reductions" "(quote (1 3 6 10))" "(reductions + [1 2 3 4])"]
|
||||
["reductions init" "(quote (0 1 3 6))" "(reductions + 0 [1 2 3])"]
|
||||
["dedupe" "(quote (1 2 3 1))" "(dedupe [1 1 2 3 3 1])"]
|
||||
["keep-indexed" "(quote (:b :d))" "(keep-indexed (fn [i x] (if (odd? i) x)) [:a :b :c :d])"]
|
||||
["map-indexed" "(quote ([0 :a] [1 :b]))" "(map-indexed (fn [i x] [i x]) [:a :b])"]
|
||||
["trampoline" ":done" "(do (defn a [n] (if (zero? n) :done (fn [] (a (dec n))))) (trampoline a 5))"]
|
||||
["format" "\"1-x\"" "(format \"%d-%s\" 1 \"x\")"]
|
||||
["read-string" "(quote (+ 1 2))" "(read-string \"(+ 1 2)\")"]
|
||||
["letfn mutual" "true" "(letfn [(ev? [n] (if (= n 0) true (od? (dec n)))) (od? [n] (if (= n 0) false (ev? (dec n))))] (ev? 10))"]
|
||||
["doseq side" "[1 2 3]" "(do (def a (atom [])) (doseq [x [1 2 3]] (swap! a conj x)) @a)"]
|
||||
["doseq nested" "4" "(do (def c (atom 0)) (doseq [x [1 2] y [10 20]] (swap! c inc)) @c)"]
|
||||
|
||||
### ---- MED: lazy filter / take-while over infinite seqs ----
|
||||
["lazy filter inf" "(quote (1 3 5 7 9))" "(take 5 (filter odd? (range)))"]
|
||||
["lazy take-while inf" "(quote (0 1 2 3 4))" "(take-while (fn [x] (< x 5)) (range))"]
|
||||
["lazy remove inf" "(quote (0 2 4 6 8))" "(take 5 (remove odd? (range)))"]
|
||||
["filter finite" "(quote (2 4))" "(filter even? [1 2 3 4 5])"]
|
||||
|
||||
### ==== atoms (full support) ====
|
||||
["swap! args" "7" "(do (def a (atom 1)) (swap! a + 2 4) @a)"]
|
||||
["reset! ret" "9" "(do (def a (atom 1)) (reset! a 9))"]
|
||||
["compare-and-set!" "true" "(do (def a (atom 1)) (compare-and-set! a 1 2))"]
|
||||
["compare-and-set! no" "false" "(do (def a (atom 1)) (compare-and-set! a 5 2))"]
|
||||
["swap-vals!" "[1 2]" "(do (def a (atom 1)) (swap-vals! a inc))"]
|
||||
["reset-vals!" "[1 9]" "(do (def a (atom 1)) (reset-vals! a 9))"]
|
||||
["atom map swap" "{:a 1 :b 2}" "(do (def a (atom {:a 1})) (swap! a assoc :b 2) @a)"]
|
||||
["add-watch" "[:k 1 2]" "(do (def lg (atom nil)) (def a (atom 1)) (add-watch a :k (fn [k r o n] (reset! lg [k o n]))) (swap! a inc) @lg)"]
|
||||
["atom validator" "5" "(do (def a (atom 1 :validator pos?)) (reset! a 5) @a)"]
|
||||
["instance? Atom" "true" "(instance? clojure.lang.Atom (atom 1))"]
|
||||
|
||||
### ==== volatiles / delays ====
|
||||
["volatile" "2" "(do (def v (volatile! 1)) (vreset! v 2) @v)"]
|
||||
["vswap!" "2" "(do (def v (volatile! 1)) (vswap! v inc) @v)"]
|
||||
["volatile?" "true" "(volatile? (volatile! 1))"]
|
||||
["delay force" "3" "(force (delay (+ 1 2)))"]
|
||||
["delay deref once" "1" "(do (def c (atom 0)) (def d (delay (swap! c inc))) @d @d @c)"]
|
||||
["realized? delay" "true" "(do (def d (delay 1)) @d (realized? d))"]
|
||||
["realized? not" "false" "(realized? (delay 1))"]
|
||||
|
||||
### ==== numbers / math ====
|
||||
["quot neg" "-2" "(quot -7 3)"]
|
||||
["rem neg" "-1" "(rem -7 3)"]
|
||||
["mod neg" "2" "(mod -7 3)"]
|
||||
["bit ops" "[4 14 10]" "[(bit-and 12 6) (bit-or 12 6) (bit-xor 12 6)]"]
|
||||
["bit-shift" "[8 2]" "[(bit-shift-left 1 3) (bit-shift-right 8 2)]"]
|
||||
["Math/sqrt" "3.0" "(Math/sqrt 9)"]
|
||||
["Math/pow" "8.0" "(Math/pow 2 3)"]
|
||||
["min-key" "1" "(min-key abs 1 -2 3)"]
|
||||
["max-key" "-4" "(max-key abs 1 -2 -4 3)"]
|
||||
|
||||
### ==== strings (clojure.string) ====
|
||||
["str/trim" "\"hi\"" "(do (require (quote [clojure.string :as s])) (s/trim \" hi \"))"]
|
||||
["str/split regex" "[\"a\" \"b\" \"c\"]" "(do (require (quote [clojure.string :as s])) (s/split \"a,b,c\" #\",\"))"]
|
||||
["str/split ws" "[\"a\" \"b\" \"c\"]" "(do (require (quote [clojure.string :as s])) (s/split \"a b c\" #\"\\s+\"))"]
|
||||
["str/replace" "\"hexxo\"" "(do (require (quote [clojure.string :as s])) (s/replace \"hello\" \"ll\" \"xx\"))"]
|
||||
["str/replace regex" "\"ab\"" "(do (require (quote [clojure.string :as s])) (s/replace \"a1b2\" #\"[0-9]\" \"\"))"]
|
||||
["str/includes?" "true" "(do (require (quote [clojure.string :as s])) (s/includes? \"hello\" \"ell\"))"]
|
||||
["str/reverse" "\"cba\"" "(do (require (quote [clojure.string :as s])) (s/reverse \"abc\"))"]
|
||||
["subs" "\"ell\"" "(subs \"hello\" 1 4)"]
|
||||
|
||||
### ==== regex ====
|
||||
["re-find" "\"123\"" "(re-find #\"[0-9]+\" \"abc123def\")"]
|
||||
["re-matches" "\"abc\"" "(re-matches #\"a.c\" \"abc\")"]
|
||||
["re-matches no" "nil" "(re-matches #\"a.c\" \"abcd\")"]
|
||||
["re-seq" "(quote (\"12\" \"34\"))" "(re-seq #\"[0-9]+\" \"a12b34\")"]
|
||||
|
||||
### ==== sequences ====
|
||||
["split-at" "[[1 2] [3 4 5]]" "(split-at 2 [1 2 3 4 5])"]
|
||||
["split-with" "[[1 2] [3 4 1]]" "(split-with (fn [x] (< x 3)) [1 2 3 4 1])"]
|
||||
["interpose" "(quote (1 0 2 0 3))" "(interpose 0 [1 2 3])"]
|
||||
["partition step" "(quote ((1 2) (3 4)))" "(partition 2 2 [1 2 3 4 5])"]
|
||||
["not-every?" "true" "(not-every? pos? [1 -2 3])"]
|
||||
["not-any?" "true" "(not-any? neg? [1 2 3])"]
|
||||
["take-nth" "(quote (0 2 4))" "(take-nth 2 [0 1 2 3 4])"]
|
||||
["butlast" "(quote (1 2))" "(butlast [1 2 3])"]
|
||||
["filterv" "[2 4]" "(filterv even? [1 2 3 4])"]
|
||||
["mapv" "[2 3 4]" "(mapv inc [1 2 3])"]
|
||||
["reduced early" "3" "(reduce (fn [a x] (if (> a 2) (reduced a) (+ a x))) 0 [1 2 3 4 5])"]
|
||||
["sort cmp" "[3 2 1]" "(sort > [1 3 2])"]
|
||||
["frequencies" "{1 2 2 1}" "(frequencies [1 1 2])"]
|
||||
["empty" "[]" "(empty [1 2 3])"]
|
||||
["not-empty" "nil" "(not-empty [])"]
|
||||
["rseq" "(quote (3 2 1))" "(rseq [1 2 3])"]
|
||||
["replace map" "[:a :b :a]" "(replace {1 :a 2 :b} [1 2 1])"]
|
||||
|
||||
### ==== data structures ====
|
||||
["sorted-map seq" "(quote ([:a 1] [:b 2] [:c 3]))" "(seq (sorted-map :c 3 :a 1 :b 2))"]
|
||||
["sorted-set seq" "(quote (1 2 3))" "(seq (sorted-set 3 1 2))"]
|
||||
["assoc vector" "[1 9 3]" "(assoc [1 2 3] 1 9)"]
|
||||
["update vector" "[1 3 3]" "(update [1 2 3] 1 inc)"]
|
||||
["coll? set" "true" "(coll? #{1 2})"]
|
||||
["find entry" "[:a 1]" "(find {:a 1} :a)"]
|
||||
["conj map entry" "{:a 1 :b 2}" "(conj {:a 1} [:b 2])"]
|
||||
["conj list prepend" "(quote (0 1 2))" "(conj (list 1 2) 0)"]
|
||||
|
||||
### ==== keywords / symbols ====
|
||||
["keyword ns" ":a/b" "(keyword \"a\" \"b\")"]
|
||||
["name ns-kw" "\"b\"" "(name :a/b)"]
|
||||
["namespace" "\"a\"" "(namespace :a/b)"]
|
||||
["namespace none" "nil" "(namespace :a)"]
|
||||
|
||||
### ==== metadata / vars ====
|
||||
["vary-meta" "{:x 2}" "(meta (vary-meta (with-meta [1] {:x 1}) update :x inc))"]
|
||||
["defonce no-redef" "1" "(do (defonce dv1 1) (defonce dv1 2) dv1)"]
|
||||
["binding dynamic" "10" "(do (def ^:dynamic *x* 1) (binding [*x* 10] *x*))"]
|
||||
|
||||
### ==== try / catch ====
|
||||
["try catch" ":caught" "(try (throw (ex-info \"e\" {})) (catch :default e :caught))"]
|
||||
["ex-data" "{:a 1}" "(try (throw (ex-info \"m\" {:a 1})) (catch :default e (ex-data e)))"]
|
||||
["ex-message" "\"m\"" "(try (throw (ex-info \"m\" {})) (catch :default e (ex-message e)))"]
|
||||
|
||||
### ==== macros ====
|
||||
["macroexpand-1" "true" "(do (defmacro mm [x] (list (quote inc) x)) (= (quote (inc 5)) (macroexpand-1 (quote (mm 5)))))"]
|
||||
["doto" "{:a 1}" "(deref (doto (atom {}) (swap! assoc :a 1)))"]
|
||||
|
||||
### ==== printing ====
|
||||
["pr-str vec" "\"[1 2 3]\"" "(pr-str [1 2 3])"]
|
||||
["prn-str" "\"1\\n\"" "(prn-str 1)"]
|
||||
|
||||
### ==== characters ====
|
||||
["char?" "true" "(char? \\a)"]
|
||||
["char not string" "false" "(= \\a \"a\")"]
|
||||
["char eq" "true" "(= \\a \\a)"]
|
||||
["int of char" "97" "(int \\a)"]
|
||||
["char of int" "true" "(= \\A (char 65))"]
|
||||
["str of chars" "\"abc\"" "(str \\a \\b \\c)"]
|
||||
["seq of string" "(quote (\\a \\b))" "(seq \"ab\")"]
|
||||
["first of string" "\\h" "(first \"hello\")"]
|
||||
["nth of string" "\\e" "(nth \"hello\" 1)"]
|
||||
["char newline" "10" "(int \\newline)"]
|
||||
["char space" "32" "(int \\space)"]
|
||||
["char unicode" "65" "(int \\u0041)"]
|
||||
["pr-str char" "\"\\\\a\"" "(pr-str \\a)"]
|
||||
["chars in vec" "[\\a \\b]" "[\\a \\b]"]
|
||||
["apply str chars" "\"hi\"" "(apply str [\\h \\i])"]
|
||||
|
||||
### ==== transducers ====
|
||||
["transduce map" "9" "(transduce (map inc) + 0 [1 2 3])"]
|
||||
["transduce comp" "12" "(transduce (comp (map inc) (filter even?)) + 0 [1 2 3 4 5])"]
|
||||
["transduce conj" "[2 3 4]" "(transduce (map inc) conj [] [1 2 3])"]
|
||||
["into xform" "[2 3 4]" "(into [] (map inc) [1 2 3])"]
|
||||
["into comp xform" "[1 9 25]" "(into [] (comp (filter odd?) (map (fn [x] (* x x)))) [1 2 3 4 5])"]
|
||||
["into take xform" "[0 1 2]" "(into [] (take 3) (range 100))"]
|
||||
["sequence xform" "(quote (2 3 4))" "(sequence (map inc) [1 2 3])"]
|
||||
["transduce no-init" "6" "(transduce (map inc) + [0 1 2])"]
|
||||
["transduce drop" "[3 4 5]" "(into [] (drop 2) [1 2 3 4 5])"]
|
||||
["transduce remove" "[1 3 5]" "(into [] (remove even?) [1 2 3 4 5])"]
|
||||
["transduce take-while" "[1 2]" "(into [] (take-while (fn [x] (< x 3))) [1 2 3 4 1])"]
|
||||
["transduce map-indexed" "[[0 :a] [1 :b]]" "(into [] (map-indexed (fn [i x] [i x])) [:a :b])"]
|
||||
|
||||
### ==== regex (capturing groups, backtracking, flags, lookahead) ====
|
||||
["re-find groups" "[\"12-34\" \"12\" \"34\"]" "(re-find #\"(\\d+)-(\\d+)\" \"x12-34y\")"]
|
||||
["re-find no-groups" "\"123\"" "(re-find #\"\\d+\" \"ab123\")"]
|
||||
["re-matches groups" "[\"1.2\" \"1\" \"2\"]" "(re-matches #\"(\\d+)\\.(\\d+)\" \"1.2\")"]
|
||||
["re-matches no" "nil" "(re-matches #\"a.c\" \"abcd\")"]
|
||||
["re-seq" "[\"foo\" \"bar\"]" "(re-seq #\"\\w+\" \"foo bar\")"]
|
||||
["greedy backtrack" "\"xxfoo\"" "(re-find #\".*foo\" \"xxfoo\")"]
|
||||
["greedy thru group" "[\"a,b,c\" \"a,b\" \"c\"]" "(re-find #\"(.*),(.*)\" \"a,b,c\")"]
|
||||
["lazy quantifier" "[\"<a>\" \"a\"]" "(re-find #\"<(.+?)>\" \"<a><b>\")"]
|
||||
["flag case-insens" "\"CAT\"" "(re-find #\"(?i)cat\" \"a CAT\")"]
|
||||
["lookahead" "\"foo\"" "(re-find #\"foo(?=bar)\" \"foobar\")"]
|
||||
["neg-lookahead" "\"foo\"" "(re-find #\"foo(?!bar)\" \"foobaz\")"]
|
||||
["word-boundary" "\"word\"" "(re-find #\"\\bword\\b\" \"a word!\")"]
|
||||
["word-boundary no" "nil" "(re-find #\"\\bword\\b\" \"swordfish\")"]
|
||||
["optional group" "[\"1.2.3\" \"1\" \"2\" \"3\" nil]" "(re-find #\"(\\d+)\\.(\\d+)\\.(\\d+)(?:-([a-z]+))?\" \"1.2.3\")"]
|
||||
["alternation" "\"dog\"" "(re-find #\"cat|dog\" \"a dog cat\")"]
|
||||
["str/replace $1" "\"he[ll]o\"" "(do (require (quote [clojure.string :as s])) (s/replace \"hello\" #\"(l+)\" \"[$1]\"))"]
|
||||
["str/replace regex" "\"X-X\"" "(do (require (quote [clojure.string :as s])) (s/replace \"a-b\" #\"[a-z]\" \"X\"))"]
|
||||
|
||||
### ==== map literals evaluate their values ====
|
||||
["map literal expr" "{:a 3}" "{:a (+ 1 2)}"]
|
||||
["map literal var" "{:k 5}" "(let [x 5] {:k x})"]
|
||||
["map literal nested" "{:a {:b 2}}" "(let [y 2] {:a {:b y}})"]
|
||||
["map literal keyfn" "{:x 1}" "(let [k :x] {k 1})"]
|
||||
["map literal in fn" "6" "(do (defn mk [a b] {:sum (+ a b)}) (:sum (mk 2 4)))"]
|
||||
])
|
||||
|
||||
(var pass 0)
|
||||
(def fails @[])
|
||||
(each [name expected actual] cases
|
||||
(def ctx (init))
|
||||
(def prog (string "(= " expected " " actual ")"))
|
||||
(def res (protect (eval-string ctx prog)))
|
||||
(cond
|
||||
(not= (res 0) true)
|
||||
(array/push fails [name "ERROR" (string (res 1))])
|
||||
(= (res 1) true)
|
||||
(++ pass)
|
||||
# not equal: re-eval actual alone to show what we got
|
||||
(let [got (protect (eval-string (init) actual))]
|
||||
(array/push fails [name "MISMATCH"
|
||||
(string "want=" expected
|
||||
" got=" (if (= (got 0) true) (string/format "%q" (got 1)) (string "ERR:" (got 1))))]))))
|
||||
|
||||
(printf "\n=== CONFORMANCE: %d/%d passed ===" pass (length cases))
|
||||
(unless (empty? fails)
|
||||
(print "\n--- Failures ---")
|
||||
(each [name kind detail] fails
|
||||
(printf "[%s] %s: %s" kind name detail)))
|
||||
(print)
|
||||
(when (pos? (length fails)) (os/exit 1))
|
||||
122
test/integration/core-test.janet
Normal file
122
test/integration/core-test.janet
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
(use ../../src/jolt/types)
|
||||
(use ../../src/jolt/pv)
|
||||
(use ../../src/jolt/plist)
|
||||
(use ../../src/jolt/reader)
|
||||
(use ../../src/jolt/evaluator)
|
||||
(use ../../src/jolt/core)
|
||||
|
||||
# Normalize jolt collection results to Janet tuples so Janet-level deep=/= can
|
||||
# compare against tuple literals regardless of the (pvec/plist) representation.
|
||||
(defn norm [x]
|
||||
(cond
|
||||
(pvec? x) (tuple ;(map norm (pv->array x)))
|
||||
(plist? x) (tuple ;(map norm (pl->array x)))
|
||||
(tuple? x) (tuple ;(map norm x))
|
||||
(array? x) (tuple ;(map norm x))
|
||||
x))
|
||||
|
||||
# Helper: create a fresh bootstrapped context
|
||||
(defn make-boot-ctx []
|
||||
(let [ctx (make-ctx)]
|
||||
(init-core! ctx)
|
||||
ctx))
|
||||
|
||||
# Helper: parse + eval
|
||||
(defn eval-str [ctx s]
|
||||
(let [form (parse-string s)]
|
||||
(norm (eval-form ctx @{} form))))
|
||||
|
||||
(print "1: predicates...")
|
||||
(let [ctx (make-boot-ctx)]
|
||||
(assert (= true (eval-str ctx "(nil? nil)")) "nil?")
|
||||
(assert (= false (eval-str ctx "(nil? 1)")) "nil? false")
|
||||
(assert (= true (eval-str ctx "(string? \"hello\")")) "string?")
|
||||
(assert (= true (eval-str ctx "(number? 42)")) "number?")
|
||||
(assert (= true (eval-str ctx "(fn? inc)")) "fn?")
|
||||
(assert (= true (eval-str ctx "(keyword? :foo)")) "keyword?")
|
||||
(assert (= false (eval-str ctx "(keyword? 1)")) "keyword? false")
|
||||
(assert (= true (eval-str ctx "(zero? 0)")) "zero?")
|
||||
(assert (= true (eval-str ctx "(pos? 1)")) "pos?")
|
||||
(assert (= true (eval-str ctx "(neg? -1)")) "neg?")
|
||||
(assert (= true (eval-str ctx "(even? 2)")) "even?")
|
||||
(assert (= true (eval-str ctx "(odd? 1)")) "odd?")
|
||||
(assert (= true (eval-str ctx "(empty? [])")) "empty? vector")
|
||||
(assert (= false (eval-str ctx "(empty? [1])")) "empty? non-empty"))
|
||||
(print " passed")
|
||||
|
||||
(print "2: math...")
|
||||
(let [ctx (make-boot-ctx)]
|
||||
(assert (= 0 (eval-str ctx "(+)")) "+ 0 args")
|
||||
(assert (= 5 (eval-str ctx "(+ 2 3)")) "+ 2 args")
|
||||
(assert (= 10 (eval-str ctx "(+ 1 2 3 4)")) "+ varargs")
|
||||
(assert (= -5 (eval-str ctx "(- 5)")) "- unary")
|
||||
(assert (= 2 (eval-str ctx "(- 5 3)")) "- binary")
|
||||
(assert (= 6 (eval-str ctx "(* 2 3)")) "*")
|
||||
(assert (= 1 (eval-str ctx "(*)")) "* 0 args")
|
||||
(assert (= 42 (eval-str ctx "(inc 41)")) "inc")
|
||||
(assert (= 40 (eval-str ctx "(dec 41)")) "dec")
|
||||
(assert (= 4 (eval-str ctx "(max 1 4 2)")) "max"))
|
||||
(print " passed")
|
||||
|
||||
(print "3: comparison...")
|
||||
(let [ctx (make-boot-ctx)]
|
||||
(assert (= true (eval-str ctx "(= 1 1)")) "= same")
|
||||
(assert (= false (eval-str ctx "(= 1 2)")) "= diff")
|
||||
(assert (= true (eval-str ctx "(= 1 1 1)")) "= multi same")
|
||||
(assert (= false (eval-str ctx "(= 1 2 1)")) "= multi diff")
|
||||
(assert (= true (eval-str ctx "(not= 1 2)")) "not="))
|
||||
(print " passed")
|
||||
|
||||
(print "4: collections...")
|
||||
(let [ctx (make-boot-ctx)]
|
||||
(assert (= 3 (eval-str ctx "(count [1 2 3])")) "count vector")
|
||||
(assert (= 1 (eval-str ctx "(first [1 2 3])")) "first")
|
||||
(assert (deep= [2 3] (eval-str ctx "(rest [1 2 3])")) "rest")
|
||||
(assert (= nil (eval-str ctx "(next [1])")) "next singleton")
|
||||
(assert (deep= [1 2 3] (eval-str ctx "(conj [1 2] 3)")) "conj vector")
|
||||
(assert (= 1 (eval-str ctx "(get {:a 1} :a)")) "get map")
|
||||
(assert (= 2 (eval-str ctx "(get [1 2 3] 1)")) "get vector")
|
||||
(assert (= :default (eval-str ctx "(get {:a 1} :b :default)")) "get default")
|
||||
(assert (deep= {:a 1 :c 3} (eval-str ctx "(assoc {:a 1} :c 3)")) "assoc")
|
||||
(assert (deep= {:a 1} (eval-str ctx "(dissoc {:a 1 :b 2} :b)")) "dissoc"))
|
||||
(print " passed")
|
||||
|
||||
(print "5: seq ops...")
|
||||
(let [ctx (make-boot-ctx)]
|
||||
(assert (deep= [2 3 4] (eval-str ctx "(map inc [1 2 3])")) "map")
|
||||
(assert (deep= [2 4] (eval-str ctx "(filter even? [1 2 3 4])")) "filter")
|
||||
(assert (= 6 (eval-str ctx "(reduce + [1 2 3])")) "reduce")
|
||||
(assert (= 10 (eval-str ctx "(reduce + 4 [1 2 3])")) "reduce with val")
|
||||
(assert (deep= [1 2] (eval-str ctx "(take 2 [1 2 3 4])")) "take")
|
||||
(assert (deep= [3 4] (eval-str ctx "(drop 2 [1 2 3 4])")) "drop")
|
||||
(assert (deep= [1 2] (eval-str ctx "(take-while (fn* [x] (<= x 2)) [1 2 3 4])")) "take-while"))
|
||||
(print " passed")
|
||||
|
||||
(print "6: range...")
|
||||
(let [ctx (make-boot-ctx)]
|
||||
(assert (deep= [0 1 2 3 4] (eval-str ctx "(range 5)")) "range end")
|
||||
(assert (deep= [2 3 4] (eval-str ctx "(range 2 5)")) "range start end"))
|
||||
(print " passed")
|
||||
|
||||
(print "7: higher-order...")
|
||||
(let [ctx (make-boot-ctx)]
|
||||
(assert (= 42 (eval-str ctx "(identity 42)")) "identity")
|
||||
(assert (= 42 (eval-str ctx "(let* [f (constantly 42)] (f))")) "constantly")
|
||||
(assert (= 3 (eval-str ctx "(let* [f (comp inc inc)] (f 1))")) "comp")
|
||||
(assert (deep= [2 0] (eval-str ctx "(let* [f (juxt inc dec)] (f 1))")) "juxt"))
|
||||
(print " passed")
|
||||
|
||||
(print "8: str...")
|
||||
(let [ctx (make-boot-ctx)]
|
||||
(assert (= "hello" (eval-str ctx "(str \"hello\")")) "str")
|
||||
(assert (= "hello42" (eval-str ctx "(str \"hello\" 42)")) "str concat"))
|
||||
(print " passed")
|
||||
|
||||
(print "9: atom...")
|
||||
(let [ctx (make-boot-ctx)]
|
||||
(assert (= 1 (eval-str ctx "(let* [a (atom 1)] (deref a))")) "atom + deref")
|
||||
(assert (= 42 (eval-str ctx "(let* [a (atom 1)] (reset! a 42) (deref a))")) "reset!")
|
||||
(assert (= 2 (eval-str ctx "(let* [a (atom 1)] (swap! a inc) (deref a))")) "swap!"))
|
||||
(print " passed")
|
||||
|
||||
(print "\nAll core tests passed!")
|
||||
153
test/integration/features-test.janet
Normal file
153
test/integration/features-test.janet
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
# Regression tests mirroring clojure-features.clj, plus expanded coverage of
|
||||
# related features. Each case asserts (= expected actual) evaluated inside Jolt
|
||||
# (so comparisons use Jolt's own Clojure-semantics =). Run via `jpm test`.
|
||||
(use ../../src/jolt/api)
|
||||
|
||||
(var pass 0)
|
||||
(def fails @[])
|
||||
|
||||
(defn check [label expected actual]
|
||||
# evaluate (= expected actual) in a fresh ctx; expects boolean true
|
||||
(def ctx (init))
|
||||
(def res (protect (eval-string ctx (string "(= " expected " " actual ")"))))
|
||||
(cond
|
||||
(not= (res 0) true)
|
||||
(array/push fails [label "ERROR" (string (res 1))])
|
||||
(= (res 1) true)
|
||||
(++ pass)
|
||||
(let [got (protect (eval-string (init) actual))]
|
||||
(array/push fails [label "NEQ"
|
||||
(string "want=" expected " got="
|
||||
(if (= (got 0) true) (string/format "%q" (got 1)) (string "ERR:" (got 1))))]))))
|
||||
|
||||
(def cases
|
||||
[
|
||||
### 1. Destructuring
|
||||
["destr seq" "[10 20 30]" "(let [[a b c] [10 20 30]] [a b c])"]
|
||||
["destr map :or" "[\"Alice\" 30 \"Unknown\"]"
|
||||
"(let [{:keys [name age city] :or {city \"Unknown\"}} {:name \"Alice\" :age 30}] [name age city])"]
|
||||
["destr nested map" "[1.0 2.5]" "(let [{[x y] :coords} {:coords [1.0 2.5]}] [x y])"]
|
||||
["destr :as" "[1 [1 2 3]]" "(let [[a :as all] [1 2 3]] [a all])"]
|
||||
["destr & rest" "[1 (quote (2 3))]" "(let [[a & r] [1 2 3]] [a r])"]
|
||||
["destr :strs" "[1 2]" "(let [{:strs [a b]} {\"a\" 1 \"b\" 2}] [a b])"]
|
||||
["destr fn-param" "7" "((fn [{:keys [a b]}] (+ a b)) {:a 3 :b 4})"]
|
||||
|
||||
### 2. Atoms
|
||||
["atom swap! inc" "1" "(do (def a (atom 0)) (swap! a inc) @a)"]
|
||||
["atom reset!" "100" "(do (def a (atom 0)) (reset! a 100) @a)"]
|
||||
["atom CAS ok" "true" "(do (def a (atom 5)) (compare-and-set! a 5 10))"]
|
||||
["atom CAS no" "false" "(do (def a (atom 5)) (compare-and-set! a 9 10))"]
|
||||
["atom thread-first swap!" "213" "(do (def a (atom 100)) (swap! a #(-> % (* 2) (+ 3))) (swap! a #(-> % (* 1) (+ 10))) @a)"]
|
||||
["atom swap! args" "10" "(do (def a (atom 1)) (swap! a + 2 3 4) @a)"]
|
||||
["atom swap-vals!" "[1 2]" "(do (def a (atom 1)) (swap-vals! a inc))"]
|
||||
["atom watch" "[1 2]" "(do (def lg (atom nil)) (def a (atom 1)) (add-watch a :k (fn [k r o n] (reset! lg [o n]))) (swap! a inc) @lg)"]
|
||||
["atom validator" "5" "(do (def a (atom 1 :validator pos?)) (reset! a 5) @a)"]
|
||||
|
||||
### 3. Lazy sequences
|
||||
["lazy filter inf" "(quote (0 2 4 6 8 10 12 14 16 18))" "(take 10 (filter even? (iterate inc 0)))"]
|
||||
["lazy take-while sq" "(quote (0 1 4 9 16 25 36 49))" "(take-while #(< % 50) (map #(* % %) (range)))"]
|
||||
["lazy cycle" "(quote (:a :b :c :a :b :c :a :b :c :a))" "(take 10 (cycle [:a :b :c]))"]
|
||||
["lazy-seq cons self" "(quote (1 2 4 8 16 32 64 128))"
|
||||
"(do (defn my-it [f x] (lazy-seq (cons x (my-it f (f x))))) (take 8 (my-it #(* 2 %) 1)))"]
|
||||
["lazy self-ref fib" "(quote (0 1 1 2 3 5 8 13 21 34))"
|
||||
"(do (def fib (lazy-cat [0 1] (map + (rest fib) fib))) (take 10 fib))"]
|
||||
["repeatedly" "(quote (1 1 1))" "(repeatedly 3 (fn [] 1))"]
|
||||
["range step" "(quote (0 2 4 6 8))" "(range 0 10 2)"]
|
||||
|
||||
### 4. Transducers
|
||||
["xf comp into" "[1 3 5 7 9]" "(into [] (comp (map inc) (filter odd?)) (range 10))"]
|
||||
["xf sequence" "(quote (1 3 5 7 9))" "(sequence (comp (map inc) (filter odd?)) (range 10))"]
|
||||
["xf transduce" "25" "(transduce (comp (map inc) (filter odd?)) + 0 (range 10))"]
|
||||
["xf take" "[0 1 2]" "(into [] (take 3) (range 100))"]
|
||||
["xf remove" "[1 3 5]" "(into [] (remove even?) [1 2 3 4 5])"]
|
||||
|
||||
### 5. Protocols & Records
|
||||
["record area circle" "78" "(do (defprotocol Sh (ar [t])) (defrecord Ci [r] Sh (ar [_] (int (* 3.14159 r r)))) (int (ar (->Ci 5))))"]
|
||||
["record field" "5" "(do (defrecord Ci [r]) (:r (->Ci 5)))"]
|
||||
["record map->" "3" "(do (defrecord P [x y]) (:x (map->P {:x 3 :y 4})))"]
|
||||
["protocol 2 methods" "[16 \"sq\"]" "(do (defprotocol Sh (ar [t]) (nm [t])) (defrecord Sq [s] Sh (ar [_] (* s s)) (nm [_] \"sq\")) (let [x (->Sq 4)] [(ar x) (nm x)]))"]
|
||||
["extend-protocol" "6" "(do (defprotocol G (g [x])) (extend-protocol G java.lang.Long (g [x] (inc x))) (g 5))"]
|
||||
["reify" "42" "(do (defprotocol P (m [_])) (m (reify P (m [_] 42))))"]
|
||||
["record equality" "true" "(do (defrecord R [a]) (= (->R 1) (->R 1)))"]
|
||||
|
||||
### 6. Multimethods
|
||||
["mm dispatch circle" "\"round\"" "(do (defmulti st :kind) (defmethod st :circle [_] \"round\") (defmethod st :default [_] \"unknown\") (st {:kind :circle}))"]
|
||||
["mm default" "\"unknown\"" "(do (defmulti st :kind) (defmethod st :circle [_] \"round\") (defmethod st :default [_] \"unknown\") (st {:kind :triangle}))"]
|
||||
["mm multi-arity" "[1 3]" "(do (defmulti f (fn [& a] (first a))) (defmethod f :x ([_ y] y) ([_ y z] (+ y z))) [(f :x 1) (f :x 1 2)])"]
|
||||
|
||||
### 7. Macros
|
||||
["macro log-call" "6" "(do (defmacro lc [e] `(let [r# ~e] r#)) (lc (* 2 3)))"]
|
||||
["macro quote arg" "(quote (* 2 3))" "(do (defmacro qa [e] `(quote ~e)) (qa (* 2 3)))"]
|
||||
["macroexpand-1" "true" "(do (defmacro mm [x] (list 'inc x)) (= '(inc 5) (macroexpand-1 '(mm 5))))"]
|
||||
["gensym distinct" "false" "(= (gensym) (gensym))"]
|
||||
["syntax-quote splice" "[1 2 3]" "(let [xs [1 2 3]] `[~@xs])"]
|
||||
["syntax-quote unquote" "(quote (+ 1 5))" "(let [x 5] `(+ 1 ~x))"]
|
||||
|
||||
### 8. Recursion
|
||||
["recursion fact" "120" "(do (defn fact [n] (if (<= n 1) 1 (* n (fact (dec n))))) (fact 5))"]
|
||||
["recursion loop" "120" "(loop [i 5 acc 1] (if (zero? i) acc (recur (dec i) (* acc i))))"]
|
||||
["mutual recursion" "true" "(letfn [(ev? [n] (if (zero? n) true (od? (dec n)))) (od? [n] (if (zero? n) false (ev? (dec n))))] (ev? 6))"]
|
||||
["trampoline" ":done" "(do (defn a [n] (if (zero? n) :done (fn [] (a (dec n))))) (trampoline a 8))"]
|
||||
|
||||
### 9. Higher-order functions
|
||||
["partial" "15" "((partial + 5) 10)"]
|
||||
["comp" "8" "((comp #(* 2 %) inc) 3)"]
|
||||
["juxt" "[5 6 4]" "((juxt identity inc dec) 5)"]
|
||||
["every-pred" "true" "((every-pred pos? even?) 2 4 6)"]
|
||||
["some-fn" "true" "((some-fn even? neg?) 3 4)"]
|
||||
["fnil" "1" "((fnil inc 0) nil)"]
|
||||
["complement" "true" "((complement nil?) 1)"]
|
||||
|
||||
### 10. Threading macros
|
||||
["->> pipeline" "75" "(->> (range 20) (filter odd?) (map #(* % 3)) (take 5) (reduce +))"]
|
||||
["-> sqrt long" "15" "(-> 25 Math/sqrt long (+ 10))"]
|
||||
["some->" "2" "(some-> {:a {:b 1}} :a :b inc)"]
|
||||
["some-> nil" "nil" "(some-> {:a nil} :a :b)"]
|
||||
["cond->" "4" "(cond-> 1 true inc false (* 100) true (* 2))"]
|
||||
["as->" "20" "(as-> 1 x (inc x) (* x 10))"]
|
||||
|
||||
### 11. Exception handling
|
||||
["ex catch" "\"caught\"" "(try (throw (ex-info \"x\" {})) (catch :default e \"caught\"))"]
|
||||
["ex-message" "\"broke\"" "(try (throw (ex-info \"broke\" {:code 42})) (catch :default e (ex-message e)))"]
|
||||
["ex-data" "{:code 42}" "(try (throw (ex-info \"broke\" {:code 42})) (catch :default e (ex-data e)))"]
|
||||
["try finally" "[:body :fin]" "(do (def lg (atom [])) (try (swap! lg conj :body) (finally (swap! lg conj :fin))) @lg)"]
|
||||
|
||||
### 12. For comprehension
|
||||
["for nested :when" "(quote ([0 1] [0 2] [1 0] [1 2] [2 0] [2 1]))"
|
||||
"(for [x (range 3) y (range 3) :when (not= x y)] [x y])"]
|
||||
["for :let" "(quote (1 4 9))" "(for [x [1 2 3] :let [sq (* x x)]] sq)"]
|
||||
["for :while" "(quote (0 1 2))" "(for [x (range 10) :while (< x 3)] x)"]
|
||||
|
||||
### 13b. Persistent lists — O(1) conj-prepend, immutable, value semantics
|
||||
["list conj prepends" "(quote (0 1 2 3))" "(conj (list 1 2 3) 0)"]
|
||||
["list conj multi" "(quote (:c :b :a))" "(conj (quote ()) :a :b :c)"]
|
||||
["list immutable" "true" "(let [l (list 1 2 3) l2 (conj l 9)] (and (= l (quote (1 2 3))) (= l2 (quote (9 1 2 3)))))"]
|
||||
["list? after conj" "true" "(list? (conj (list 1 2) 0))"]
|
||||
["list = vector elts" "true" "(= (quote (1 2 3)) [1 2 3])"]
|
||||
["reduce conj list" "(quote (2 1 0))" "(reduce conj (list) (range 3))"]
|
||||
["cons onto list" "(quote (0 1 2 3))" "(cons 0 (list 1 2 3))"]
|
||||
|
||||
### 14. Janet interop
|
||||
["interop method" "\"v=41\"" "(. {:value 41 :describe (fn [self] (str \"v=\" (:value self)))} describe)"]
|
||||
["interop field" "41" "(.-value {:value 41})"]
|
||||
# vectors are persistent vectors (Janet tables); lists are Janet arrays
|
||||
["interop janet-type" ":array" "(do (require '[jolt.interop :as j]) (j/janet-type (list 1 2 3)))"]
|
||||
])
|
||||
|
||||
(each [label expected actual] cases (check label expected actual))
|
||||
|
||||
(printf "\n=== features-test: %d/%d passed ===" pass (length cases))
|
||||
(unless (empty? fails)
|
||||
(print "--- Failures ---")
|
||||
(each [label kind detail] fails (printf "[%s] %s: %s" kind label detail)))
|
||||
(when (pos? (length fails))
|
||||
(error (string (length fails) " feature regression(s)")))
|
||||
(print "All feature tests passed!")
|
||||
|
||||
# Smoke test: the demo file itself loads and runs end-to-end without error.
|
||||
(when (os/stat "clojure-features.clj")
|
||||
(print "\n--- running clojure-features.clj (smoke test) ---")
|
||||
(def res (protect (load-string (init) (slurp "clojure-features.clj"))))
|
||||
(unless (= (res 0) true)
|
||||
(error (string "clojure-features.clj failed to run: " (res 1))))
|
||||
(print "--- clojure-features.clj ran cleanly ---"))
|
||||
54
test/integration/jank-conformance-test.janet
Normal file
54
test/integration/jank-conformance-test.janet
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
# jank conformance: runs the Clojure-language pass-tests from a local jank
|
||||
# checkout (https://github.com/jank-lang/jank, MPL-2.0) against Jolt and asserts
|
||||
# the number that pass stays at/above a baseline. This does NOT vendor jank's
|
||||
# sources (license differs) — it references ~/src/jank if present and SKIPS
|
||||
# cleanly when absent, so it is a local/dev regression aid.
|
||||
#
|
||||
# Each jank pass-test is an assertion script ending in `:success`. We load it in
|
||||
# a fresh context and count it as passing when it returns :success.
|
||||
(use ../../src/jolt/api)
|
||||
|
||||
(def jank-dir (string (os/getenv "HOME") "/src/jank/compiler+runtime/test/jank"))
|
||||
|
||||
# Baseline: the number of pass-tests Jolt currently handles. Raise this as Jolt
|
||||
# gains features so regressions (a previously-passing test breaking) are caught.
|
||||
(def baseline 120)
|
||||
|
||||
# Tests that loop forever under Jolt's eager evaluation (skipped to avoid hangs;
|
||||
# tracked as known gaps — variadic-recur arity selection and var-quote calls).
|
||||
(def skip-patterns ["/cpp/" "var-quote" "fn/recur/pass-variadic-position"])
|
||||
|
||||
(defn- skip? [path]
|
||||
(var s false)
|
||||
(each p skip-patterns (when (string/find p path) (set s true)))
|
||||
s)
|
||||
|
||||
(defn- walk [dir acc]
|
||||
(each e (os/dir dir)
|
||||
(def p (string dir "/" e))
|
||||
(case ((os/stat p) :mode)
|
||||
:directory (walk p acc)
|
||||
:file (when (and (string/has-suffix? ".jank" p)
|
||||
(string/find "/pass-" p)
|
||||
(not (skip? p)))
|
||||
(array/push acc p))))
|
||||
acc)
|
||||
|
||||
(if (not (os/stat jank-dir))
|
||||
(print "jank-conformance: ~/src/jank not present — skipped")
|
||||
(do
|
||||
(def files (sort (walk jank-dir @[])))
|
||||
(var pass 0)
|
||||
(def fails @[])
|
||||
(each f files
|
||||
# A pass-test passes when no assertion throws (assert now errors on failure).
|
||||
(def res (protect (load-string (init) (slurp f))))
|
||||
(if (= (res 0) true)
|
||||
(++ pass)
|
||||
(array/push fails (string/slice f (+ 1 (length jank-dir))))))
|
||||
(printf "jank-conformance: %d/%d pass-tests pass (baseline %d)" pass (length files) baseline)
|
||||
(when (< pass baseline)
|
||||
(print "--- regressions (now failing, were within baseline) ---")
|
||||
(each rel fails (print " " rel))
|
||||
(error (string "jank conformance dropped to " pass " (baseline " baseline ")")))
|
||||
(printf "jank conformance OK (%d known gaps)" (length fails))))
|
||||
100
test/integration/logic-test.janet
Normal file
100
test/integration/logic-test.janet
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
(use ../../src/jolt/api)
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
(print "Ported Logic Tests (from clojure/test-clojure/logic.clj)")
|
||||
|
||||
(print "1: test-if true/false/nil...")
|
||||
(let [ctx (init)]
|
||||
(assert (= :t (ct-eval ctx "(if true :t)")) "if true")
|
||||
(assert (= :t (ct-eval ctx "(if true :t :f)")) "if true with else")
|
||||
(assert (= nil (ct-eval ctx "(if false :t)")) "if false no else")
|
||||
(assert (= :f (ct-eval ctx "(if false :t :f)")) "if false with else")
|
||||
(assert (= nil (ct-eval ctx "(if nil :t)")) "if nil no else")
|
||||
(assert (= :f (ct-eval ctx "(if nil :t :f)")) "if nil with else"))
|
||||
(print " ok")
|
||||
|
||||
(print "2: test-if zero/empty is true...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(= :t (if 0 :t :f))")) "0 is true")
|
||||
(assert (= true (ct-eval ctx "(= :t (if 0.0 :t :f))")) "0.0 is true")
|
||||
(assert (= true (ct-eval ctx "(= :t (if \"\" :t :f))")) "empty string is true")
|
||||
(assert (= true (ct-eval ctx "(= :t (if () :t :f))")) "empty list is true")
|
||||
(assert (= true (ct-eval ctx "(= :t (if [] :t :f))")) "empty vector is true")
|
||||
(assert (= true (ct-eval ctx "(= :t (if {} :t :f))")) "empty map is true")
|
||||
(assert (= true (ct-eval ctx "(= :t (if #{} :t :f))")) "empty set is true"))
|
||||
(print " ok")
|
||||
|
||||
(print "3: test-if anything except nil/false is true...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(= :t (if 42 :t :f))")) "42 is true")
|
||||
(assert (= true (ct-eval ctx "(= :t (if 1.5 :t :f))")) "float is true")
|
||||
(assert (= true (ct-eval ctx "(= :t (if \"abc\" :t :f))")) "string is true")
|
||||
(assert (= true (ct-eval ctx "(= :t (if 'abc :t :f))")) "symbol is true")
|
||||
(assert (= true (ct-eval ctx "(= :t (if :kw :t :f))")) "keyword is true")
|
||||
(assert (= true (ct-eval ctx "(= :t (if '(1 2) :t :f))")) "list is true")
|
||||
(assert (= true (ct-eval ctx "(= :t (if [1 2] :t :f))")) "vector is true")
|
||||
(assert (= true (ct-eval ctx "(= :t (if {:a 1 :b 2} :t :f))")) "map is true")
|
||||
(assert (= true (ct-eval ctx "(= :t (if #{1 2} :t :f))")) "set is true"))
|
||||
(print " ok")
|
||||
|
||||
(print "4: test-nil-punning...")
|
||||
(let [ctx (init)]
|
||||
(assert (= :yes (ct-eval ctx "(if (first []) :no :yes)")) "first [] nil")
|
||||
(assert (= :yes (ct-eval ctx "(if (next [1]) :no :yes)")) "next [1] nil")
|
||||
(assert (= :no (ct-eval ctx "(if (rest [1]) :no :yes)")) "rest [1] non-nil")
|
||||
(assert (= :yes (ct-eval ctx "(if (seq nil) :no :yes)")) "seq nil")
|
||||
(assert (= :yes (ct-eval ctx "(if (seq []) :no :yes)")) "seq [] nil")
|
||||
(assert (= :no (ct-eval ctx "(if (lazy-seq nil) :no :yes)")) "lazy-seq nil non-nil")
|
||||
(assert (= :no (ct-eval ctx "(if (lazy-seq []) :no :yes)")) "lazy-seq [] non-nil"))
|
||||
(print " ok")
|
||||
|
||||
(print "5: test-and...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(and)")) "and empty")
|
||||
(assert (= true (ct-eval ctx "(and true)")) "and true")
|
||||
(assert (= nil (ct-eval ctx "(and nil)")) "and nil")
|
||||
(assert (= false (ct-eval ctx "(and false)")) "and false")
|
||||
(assert (ct-eval ctx "(= \"abc\" (and 1 true :kw 'abc \"abc\"))") "and chain last")
|
||||
(assert (= nil (ct-eval ctx "(and 1 true nil 'abc \"abc\")")) "and chain nil")
|
||||
(assert (= false (ct-eval ctx "(and 1 true 'abc \"abc\" false)")) "and chain false"))
|
||||
(print " ok")
|
||||
|
||||
(print "6: test-or...")
|
||||
(let [ctx (init)]
|
||||
(assert (= nil (ct-eval ctx "(or)")) "or empty")
|
||||
(assert (= true (ct-eval ctx "(or true)")) "or true")
|
||||
(assert (= nil (ct-eval ctx "(or nil)")) "or nil")
|
||||
(assert (= false (ct-eval ctx "(or false)")) "or false")
|
||||
(assert (= true (ct-eval ctx "(or nil false true)")) "or nil false true")
|
||||
(assert (= 1 (ct-eval ctx "(or nil false 1 2)")) "or picks first truthy")
|
||||
(assert (ct-eval ctx "(= \"abc\" (or nil false \"abc\" :kw))") "or picks string")
|
||||
(assert (= nil (ct-eval ctx "(or false nil)")) "or false nil -> nil")
|
||||
(assert (= false (ct-eval ctx "(or nil false)")) "or nil false -> false")
|
||||
(assert (= false (ct-eval ctx "(or nil nil nil false)")) "or chain to false")
|
||||
(assert (= true (ct-eval ctx "(or nil true false)")) "or nil true false"))
|
||||
(print " ok")
|
||||
|
||||
(print "7: test-not...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(not nil)")) "not nil")
|
||||
(assert (= true (ct-eval ctx "(not false)")) "not false")
|
||||
(assert (= false (ct-eval ctx "(not true)")) "not true")
|
||||
(assert (= false (ct-eval ctx "(not 0)")) "not 0")
|
||||
(assert (= false (ct-eval ctx "(not 42)")) "not 42")
|
||||
(assert (= false (ct-eval ctx "(not \"\")")) "not empty string")
|
||||
(assert (= false (ct-eval ctx "(not \"abc\")")) "not string")
|
||||
(assert (= false (ct-eval ctx "(not ())")) "not empty list")
|
||||
(assert (= false (ct-eval ctx "(not [])")) "not empty vector")
|
||||
(assert (= false (ct-eval ctx "(not {})")) "not empty map")
|
||||
(assert (= false (ct-eval ctx "(not #{})")) "not empty set"))
|
||||
(print " ok")
|
||||
|
||||
(print "8: test-some?...")
|
||||
(let [ctx (init)]
|
||||
(assert (= false (ct-eval ctx "(some? nil)")) "some? nil")
|
||||
(assert (= true (ct-eval ctx "(some? false)")) "some? false")
|
||||
(assert (= true (ct-eval ctx "(some? 0)")) "some? 0")
|
||||
(assert (= true (ct-eval ctx "(some? \"abc\")")) "some? string")
|
||||
(assert (= true (ct-eval ctx "(some? [])")) "some? empty vec"))
|
||||
(print " ok")
|
||||
|
||||
(print "\nAll Ported Logic tests passed!")
|
||||
92
test/integration/namespace-test.janet
Normal file
92
test/integration/namespace-test.janet
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
(use ../../src/jolt/reader)
|
||||
(use ../../src/jolt/types)
|
||||
(use ../../src/jolt/evaluator)
|
||||
|
||||
# Helper: parse and eval in a fresh ctx
|
||||
(defn eval-str [s]
|
||||
(let [ctx (make-ctx)
|
||||
form (parse-string s)]
|
||||
(eval-form ctx @{} form)))
|
||||
|
||||
(print "1: in-ns...")
|
||||
(let [ctx (make-ctx)]
|
||||
(def form (parse-string "(in-ns my.app)"))
|
||||
(eval-form ctx @{} form)
|
||||
(assert (= "my.app" (ctx-current-ns ctx)) "in-ns switches namespace"))
|
||||
(print " passed")
|
||||
|
||||
(print "2: def in different namespace...")
|
||||
(let [ctx (make-ctx)]
|
||||
(eval-form ctx @{} (parse-string "(in-ns my.app)"))
|
||||
(eval-form ctx @{} (parse-string "(def x 42)"))
|
||||
(let [ns (ctx-find-ns ctx "my.app")
|
||||
v (ns-find ns "x")]
|
||||
(assert (= 42 (var-get v)) "def works in new namespace")))
|
||||
(print " passed")
|
||||
|
||||
(print "3: ns form...")
|
||||
(let [ctx (make-ctx)]
|
||||
(eval-form ctx @{} (parse-string "(ns my.lib)"))
|
||||
(assert (= "my.lib" (ctx-current-ns ctx)) "ns sets current namespace"))
|
||||
(print " passed")
|
||||
|
||||
(print "4: ns with require...")
|
||||
(let [ctx (make-ctx)]
|
||||
# Set up a namespace with some vars
|
||||
(let [other-ns (ctx-find-ns ctx "other.lib")]
|
||||
(ns-intern other-ns "f" (fn [x] (inc x))))
|
||||
# Now ns with require
|
||||
(eval-form ctx @{} (parse-string "(ns my.app (:require [other.lib :as o]))"))
|
||||
# current-ns should be my.app
|
||||
(assert (= "my.app" (ctx-current-ns ctx)) "ns with require sets current namespace")
|
||||
# Alias should be registered
|
||||
(let [ns (ctx-find-ns ctx "my.app")
|
||||
aliased (ns-import-lookup ns "o")]
|
||||
(assert (= "other.lib" aliased) "alias o -> other.lib registered")))
|
||||
(print " passed")
|
||||
|
||||
(print "5: require form (standalone)...")
|
||||
(let [ctx (make-ctx)]
|
||||
(eval-form ctx @{} (parse-string "(require '[other.lib :as o])"))
|
||||
(let [ns (ctx-find-ns ctx "user")
|
||||
aliased (ns-import-lookup ns "o")]
|
||||
(assert (= "other.lib" aliased) "standalone require registers alias")))
|
||||
(print " passed")
|
||||
|
||||
(print "6: qualified symbol via alias...")
|
||||
(let [ctx (make-ctx)]
|
||||
# Set up target ns
|
||||
(let [target (ctx-find-ns ctx "other.lib")]
|
||||
(ns-intern target "f" (fn [x] (inc x))))
|
||||
# Register alias
|
||||
(let [ns (ctx-find-ns ctx "user")]
|
||||
(ns-import ns "o" "other.lib"))
|
||||
# Resolve o/f and call it
|
||||
(let [form (parse-string "(o/f 41)")
|
||||
result (eval-form ctx @{} form)]
|
||||
(assert (= 42 result) "qualified call via alias works")))
|
||||
(print " passed")
|
||||
|
||||
(print "7: require then use alias...")
|
||||
(let [ctx (make-ctx)]
|
||||
# Set up target ns
|
||||
(let [target (ctx-find-ns ctx "math.lib")]
|
||||
(ns-intern target "add" (fn [a b] (+ a b))))
|
||||
# require + use
|
||||
(eval-form ctx @{} (parse-string "(require '[math.lib :as m])"))
|
||||
(let [result (eval-form ctx @{} (parse-string "(m/add 1 2)"))]
|
||||
(assert (= 3 result) "require + alias + call chain works")))
|
||||
(print " passed")
|
||||
|
||||
(print "8: ns form requires multiple...")
|
||||
(let [ctx (make-ctx)]
|
||||
(let [ns1 (ctx-find-ns ctx "a.lib")]
|
||||
(ns-intern ns1 "f" (fn [x] (inc x))))
|
||||
(let [ns2 (ctx-find-ns ctx "b.lib")]
|
||||
(ns-intern ns2 "g" (fn [x] (dec x))))
|
||||
(eval-form ctx @{} (parse-string "(ns user (:require [a.lib :as a] [b.lib :as b]))"))
|
||||
(assert (= 43 (eval-form ctx @{} (parse-string "(a/f 42)"))) "alias a works")
|
||||
(assert (= 41 (eval-form ctx @{} (parse-string "(b/g 42)"))) "alias b works"))
|
||||
(print " passed")
|
||||
|
||||
(print "\nAll namespace tests passed!")
|
||||
42
test/integration/ports/cljs-collections-test.janet
Normal file
42
test/integration/ports/cljs-collections-test.janet
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
(use ../../../src/jolt/api)
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
(print "CLJS Collections Ported Tests")
|
||||
|
||||
(print "1: dissoc...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(= {:a :b} (dissoc {:a :b :c :d} :c))")) "dissoc")
|
||||
(assert (= true (ct-eval ctx "(= {} (dissoc {1 2 3 4} 1 3))")) "dissoc multi"))
|
||||
(print " ok")
|
||||
|
||||
(print "2: assoc...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(= {1 2 3 4} (assoc {} 1 2 3 4))")) "assoc multi")
|
||||
(assert (= true (ct-eval ctx "(= {1 2} (assoc {} 1 2))")) "assoc single"))
|
||||
(print " ok")
|
||||
|
||||
(print "3: set operations...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(set? (set []))")) "set empty")
|
||||
(assert (= true (ct-eval ctx "(= #{\"foo\"} (set [\"foo\"]))")) "set from vec")
|
||||
(assert (= true (ct-eval ctx "(= #{1 2 3} #{1 3 2})")) "set order")
|
||||
(assert (= true (ct-eval ctx "(= #{1 2 3} (disj #{1 2 3}))")) "disj none")
|
||||
(assert (= true (ct-eval ctx "(= #{1 2} (disj #{1 2 3} 3))")) "disj one")
|
||||
(assert (= true (ct-eval ctx "(= #{1} (disj #{1 2 3} 2 3))")) "disj multi")
|
||||
(assert (= true (ct-eval ctx "(= 4 (get #{1 2 3 4} 4))")) "get set")
|
||||
(assert (= true (ct-eval ctx "(contains? #{1 2 3 4} 4)")) "contains? set"))
|
||||
(print " ok")
|
||||
|
||||
(print "4: vector nth...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(= :a (nth [:a :b :c :d] 0))")) "nth")
|
||||
(assert (= true (ct-eval ctx "(= :c (nth [:a :b :c :d] 2 0.1))")) "nth float"))
|
||||
(print " ok")
|
||||
|
||||
(print "5: range...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(= 0 (count (range 10 0 1)))")) "range empty")
|
||||
(assert (= true (ct-eval ctx "(= 4 (count (range 0 10 3)))")) "range count")
|
||||
(assert (= true (ct-eval ctx "(= 1 (count (range 0 1 1)))")) "range single"))
|
||||
(print " ok")
|
||||
|
||||
(print "\nAll CLJS Collections Ported tests passed!")
|
||||
90
test/integration/ports/cljs-core-test.janet
Normal file
90
test/integration/ports/cljs-core-test.janet
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
(use ../../../src/jolt/api)
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
(print "CLJS Core Ported Tests")
|
||||
|
||||
(print "1: metadata on maps...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(= {:foo \"bar\"} (meta (with-meta {:a 1} {:foo \"bar\"})))")) "with-meta on map"))
|
||||
(print " ok")
|
||||
|
||||
(print "2: atoms...")
|
||||
(let [ctx (init)]
|
||||
(ct-eval ctx "(def a (atom 0))")
|
||||
(assert (= true (ct-eval ctx "(= 0 (deref a))")) "deref")
|
||||
(assert (= true (ct-eval ctx "(= 1 (swap! a inc))")) "swap! inc")
|
||||
(ct-eval ctx "(def b (atom 0))")
|
||||
(assert (= true (ct-eval ctx "(= 1 (swap! b + 1))")) "swap! + 1")
|
||||
(assert (= true (ct-eval ctx "(= 4 (swap! b + 1 2))")) "swap! + 1 2")
|
||||
(assert (= true (ct-eval ctx "(= 10 (swap! b + 1 2 3))")) "swap! + 1 2 3")
|
||||
(assert (= true (ct-eval ctx "(= 20 (swap! b + 1 2 3 4))")) "swap! + 1 2 3 4")
|
||||
(assert (= true (ct-eval ctx "(atom? (atom 0))")) "atom?")
|
||||
(assert (= true (ct-eval ctx "(nil? (meta (atom 0)))")) "atom meta nil"))
|
||||
(print " ok")
|
||||
|
||||
(print "3: contains?...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(contains? {:a 1 :b 2} :a)")) "contains? map key")
|
||||
(assert (= true (ct-eval ctx "(not (contains? {:a 1 :b 2} :z))")) "contains? missing")
|
||||
(assert (= true (ct-eval ctx "(contains? [5 6 7] 1)")) "contains? vector index")
|
||||
(assert (= true (ct-eval ctx "(contains? [5 6 7] 2)")) "contains? vector index 2")
|
||||
(assert (= true (ct-eval ctx "(not (contains? [5 6 7] 3))")) "contains? vector oob")
|
||||
(assert (= true (ct-eval ctx "(not (contains? nil 42))")) "contains? nil"))
|
||||
(print " ok")
|
||||
|
||||
(print "4: get-in...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(= 1 (get-in {:foo 1 :bar 2} [:foo]))")) "get-in flat")
|
||||
(assert (= true (ct-eval ctx "(= 2 (get-in {:foo {:bar 2}} [:foo :bar]))")) "get-in nested"))
|
||||
(print " ok")
|
||||
|
||||
(print "5: multimethods...")
|
||||
(let [ctx (init)]
|
||||
(ct-eval ctx "(defmulti greet (fn [x] (:lang x)))")
|
||||
(ct-eval ctx "(defmethod greet :en [_] \"hello\")")
|
||||
(ct-eval ctx "(defmethod greet :fr [_] \"bonjour\")")
|
||||
(assert (= true (ct-eval ctx "(= \"hello\" (greet {:lang :en}))")) "dispatch :en")
|
||||
(assert (= true (ct-eval ctx "(= \"bonjour\" (greet {:lang :fr}))")) "dispatch :fr"))
|
||||
(print " ok")
|
||||
|
||||
(print "6: sequential equality...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(= (list 3 2 1) [3 2 1])")) "list = vector")
|
||||
(assert (= true (ct-eval ctx "(= () (rest nil))")) "rest nil")
|
||||
(assert (= true (ct-eval ctx "(= () (rest [1]))")) "rest [1]")
|
||||
(assert (= true (ct-eval ctx "(= () (rest ()))")) "rest empty"))
|
||||
(print " ok")
|
||||
|
||||
(print "7: seq operations...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(nil? (seq []))")) "seq empty vec"))
|
||||
(print " ok")
|
||||
|
||||
(print "8: empty and empty?...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(empty? nil)")) "empty? nil")
|
||||
(assert (= true (ct-eval ctx "(empty? ())")) "empty? ()")
|
||||
(assert (= true (ct-eval ctx "(empty? [])")) "empty? []")
|
||||
(assert (= true (ct-eval ctx "(empty? {})")) "empty? {}")
|
||||
(assert (= true (ct-eval ctx "(empty? #{})")) "empty? #{}")
|
||||
(assert (= true (ct-eval ctx "(empty? \"\")")) "empty? empty string")
|
||||
(assert (= true (ct-eval ctx "(not (empty? [1 2]))")) "empty? non-empty")
|
||||
(assert (= true (ct-eval ctx "(not (empty? {:a 1}))")) "empty? non-empty map"))
|
||||
(print " ok")
|
||||
|
||||
(print "9: distinct...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(= 0 (count (distinct ())))")) "distinct empty")
|
||||
(assert (= true (ct-eval ctx "(= 1 (count (distinct '(1))))")) "distinct single")
|
||||
(assert (= true (ct-eval ctx "(= 3 (count (distinct '(1 2 3 1 1 1))))")) "distinct multi count")
|
||||
(assert (= true (ct-eval ctx "(= 1 (count (distinct [42 42])))")) "distinct nums count"))
|
||||
(print " ok")
|
||||
|
||||
(print "10: some and some?...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(some? 1)")) "some? 1")
|
||||
(assert (= true (ct-eval ctx "(not (some? nil))")) "some? nil")
|
||||
(assert (= true (ct-eval ctx "(some even? [1 2 3])")) "some even?")
|
||||
(assert (= true (ct-eval ctx "(nil? (some even? [1 3 5]))")) "some even? nil"))
|
||||
(print " ok")
|
||||
|
||||
(print "\nAll CLJS Core Ported tests passed!")
|
||||
110
test/integration/ports/cljs-port-1-test.janet
Normal file
110
test/integration/ports/cljs-port-1-test.janet
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
(use ../../../src/jolt/api)
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
(print "=== CLJS Ported Part 1 ===")
|
||||
(print "1: core math...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 3 (ct-eval ctx "(+ 1 2)")) "+")
|
||||
(assert (= 0 (ct-eval ctx "(+)")) "+ zero")
|
||||
(assert (= 1 (ct-eval ctx "(- 3 2)")) "-")
|
||||
(assert (= 6 (ct-eval ctx "(* 2 3)")) "*")
|
||||
(assert (= 2 (ct-eval ctx "(/ 4 2)")) "/")
|
||||
(assert (= 3 (ct-eval ctx "(inc 2)")) "inc")
|
||||
(assert (= 1 (ct-eval ctx "(dec 2)")) "dec")
|
||||
(assert (= 1 (ct-eval ctx "(quot 5 3)")) "quot")
|
||||
(assert (= 2 (ct-eval ctx "(rem 5 3)")) "rem")
|
||||
(assert (= 2 (ct-eval ctx "(mod 5 3)")) "mod")
|
||||
(assert (= 3 (ct-eval ctx "(max 1 2 3)")) "max")
|
||||
(assert (= 1 (ct-eval ctx "(min 1 2 3)")) "min"))
|
||||
(print " passed")
|
||||
(print "2: predicates...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(nil? nil)")) "nil?")
|
||||
(assert (= false (ct-eval ctx "(nil? 1)")) "nil? false")
|
||||
(assert (= false (ct-eval ctx "(not true)")) "not")
|
||||
(assert (= true (ct-eval ctx "(not false)")) "not false")
|
||||
(assert (= true (ct-eval ctx "(some? 1)")) "some?")
|
||||
(assert (= true (ct-eval ctx "(string? \"hello\")")) "string?")
|
||||
(assert (= true (ct-eval ctx "(number? 42)")) "number?")
|
||||
(assert (= true (ct-eval ctx "(fn? inc)")) "fn?")
|
||||
(assert (= true (ct-eval ctx "(keyword? :foo)")) "keyword?")
|
||||
(assert (= true (ct-eval ctx "(map? {:a 1})")) "map?")
|
||||
(assert (= true (ct-eval ctx "(zero? 0)")) "zero?")
|
||||
(assert (= true (ct-eval ctx "(pos? 5)")) "pos?")
|
||||
(assert (= true (ct-eval ctx "(neg? -1)")) "neg?")
|
||||
(assert (= true (ct-eval ctx "(even? 4)")) "even?")
|
||||
(assert (= true (ct-eval ctx "(odd? 3)")) "odd?"))
|
||||
(print " passed")
|
||||
(print "3: comparison...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(= 1 1)")) "=")
|
||||
(assert (= false (ct-eval ctx "(= 1 2)")) "= false")
|
||||
(assert (= true (ct-eval ctx "(= 1 1 1)")) "= three")
|
||||
(assert (= false (ct-eval ctx "(not= 1 1)")) "not= false")
|
||||
(assert (= true (ct-eval ctx "(not= 1 2)")) "not= true")
|
||||
(assert (= true (ct-eval ctx "(< 1 2)")) "<")
|
||||
(assert (= true (ct-eval ctx "(> 2 1)")) ">")
|
||||
(assert (= true (ct-eval ctx "(<= 1 1)")) "<=")
|
||||
(assert (= true (ct-eval ctx "(>= 2 2)")) ">="))
|
||||
(print " passed")
|
||||
(print "4: vectors...")
|
||||
(let [ctx (init)]
|
||||
(assert (= :a (ct-eval ctx "(nth [:a :b :c :d] 0)")) "nth")
|
||||
(assert (= [1 2 3 4] (ct-eval ctx "(conj [1 2 3] 4)")) "conj")
|
||||
(assert (= 1 (ct-eval ctx "(first [1 2 3])")) "first")
|
||||
(assert (= [2 3] (ct-eval ctx "(rest [1 2 3])")) "rest")
|
||||
(assert (= 3 (ct-eval ctx "(count [1 2 3])")) "count"))
|
||||
(print " passed")
|
||||
(print "5: maps...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 1 (ct-eval ctx "(get {:a 1} :a)")) "get")
|
||||
(assert (= nil (ct-eval ctx "(get {:a 1} :z)")) "get missing")
|
||||
(assert (= :d (ct-eval ctx "(get {:a 1} :z :d)")) "get default")
|
||||
(assert (= {:a 1 :b 2} (ct-eval ctx "(assoc {:a 1} :b 2)")) "assoc")
|
||||
(assert (= {:b 2} (ct-eval ctx "(dissoc {:a 1 :b 2} :a)")) "dissoc")
|
||||
(assert (= true (ct-eval ctx "(contains? {:a 1} :a)")) "contains?")
|
||||
(assert (= 3 (ct-eval ctx "(count {:a 1 :b 2 :c 3})")) "count")
|
||||
(assert (= 2 (ct-eval ctx "(count (keys {:a 1 :b 2}))")) "keys count"))
|
||||
(print " passed")
|
||||
(print "6: sets...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(set? #{1 2 3})")) "set?")
|
||||
(assert (= 4 (ct-eval ctx "(count (conj #{1 2 3} 4))")) "conj")
|
||||
(assert (= 2 (ct-eval ctx "(count (disj #{1 2 3} 3))")) "disj")
|
||||
(assert (= 3 (ct-eval ctx "(count #{1 2 3})")) "count")
|
||||
(assert (= true (ct-eval ctx "(= #{1 2 3} #{3 2 1})")) "= order-independent"))
|
||||
(print " passed")
|
||||
(print "7: seq operations...")
|
||||
(let [ctx (init)]
|
||||
(assert (= nil (ct-eval ctx "(seq [])")) "seq empty")
|
||||
(assert (= [2 3 4] (ct-eval ctx "(map inc [1 2 3])")) "map")
|
||||
(assert (= 2 (ct-eval ctx "(count (filter odd? [1 2 3 4]))")) "filter")
|
||||
(assert (= 6 (ct-eval ctx "(reduce + [1 2 3])")) "reduce")
|
||||
(assert (= [1 2 3] (ct-eval ctx "(take 3 [1 2 3 4 5])")) "take")
|
||||
(assert (= [4 5] (ct-eval ctx "(drop 3 [1 2 3 4 5])")) "drop")
|
||||
(assert (= [3 2 1] (ct-eval ctx "(reverse [1 2 3])")) "reverse")
|
||||
(assert (= true (ct-eval ctx "(every? even? [2 4 6])")) "every?"))
|
||||
(print " passed")
|
||||
(print "8: printing...")
|
||||
(let [ctx (init)]
|
||||
(assert (= "hello" (ct-eval ctx "(str \"hello\")")) "str")
|
||||
(assert (= "ab" (ct-eval ctx "(str \"a\" \"b\")")) "str two")
|
||||
(assert (= "42" (ct-eval ctx "(str 42)")) "str number")
|
||||
(assert (= "" (ct-eval ctx "(str nil)")) "str nil -> empty string (Clojure semantics)")
|
||||
(assert (= "a" (ct-eval ctx "(name :a)")) "name"))
|
||||
(print " passed")
|
||||
(print "9: apply...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 3 (ct-eval ctx "(apply + [1 2])")) "apply +")
|
||||
(assert (= 3 (ct-eval ctx "(apply max [1 3 2])")) "apply max"))
|
||||
(print " passed")
|
||||
(print "10: equality across types...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(= {:a 1 :b 2} {:b 2 :a 1})")) "map order-independent"))
|
||||
(print " passed")
|
||||
(print "11: higher-order fns...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 3 (ct-eval ctx "((comp inc inc) 1)")) "comp")
|
||||
(assert (function? (ct-eval ctx "(partial + 1 2)")) "partial returns fn")
|
||||
(assert (= 3 (ct-eval ctx "(identity 3)")) "identity"))
|
||||
(print " passed")
|
||||
(print "\nAll CLJS Ported Part 1 tests passed!")
|
||||
25
test/integration/ports/cljs-port-10-test.janet
Normal file
25
test/integration/ports/cljs-port-10-test.janet
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
(use ../../../src/jolt/api)
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
(print "=== CLJS Ported Part 10 ===")
|
||||
|
||||
(print "43: when/when-not...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 42 (ct-eval ctx "(when true 42)")) "when true")
|
||||
(assert (= nil (ct-eval ctx "(when false 42)")) "when false")
|
||||
(assert (= 42 (ct-eval ctx "(when-not false 42)")) "when-not false"))
|
||||
(print " ok")
|
||||
|
||||
(print "44: if-let/when-let...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 2 (ct-eval ctx "(if-let [x 1] (inc x) 0)")) "if-let true")
|
||||
(assert (= 0 (ct-eval ctx "(if-let [x nil] (inc x) 0)")) "if-let nil")
|
||||
(assert (= 2 (ct-eval ctx "(when-let [x 1] (inc x))")) "when-let"))
|
||||
(print " ok")
|
||||
|
||||
(print "45: doto...")
|
||||
(let [ctx (init)]
|
||||
(ct-eval ctx "(def x (atom []))")
|
||||
(assert (= nil (ct-eval ctx "(doto nil)")) "doto nil returns nil"))
|
||||
(print " ok")
|
||||
|
||||
(print "\nAll CLJS Ported Part 10 tests passed!\n")
|
||||
77
test/integration/ports/cljs-port-1a-test.janet
Normal file
77
test/integration/ports/cljs-port-1a-test.janet
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
(use ../../../src/jolt/api)
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
(print "=== CLJS Ported Part 1 ===")
|
||||
(print "1: core math...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 3 (ct-eval ctx "(+ 1 2)")) "+")
|
||||
(assert (= 0 (ct-eval ctx "(+)")) "+ zero")
|
||||
(assert (= 1 (ct-eval ctx "(- 3 2)")) "-")
|
||||
(assert (= 6 (ct-eval ctx "(* 2 3)")) "*")
|
||||
(assert (= 2 (ct-eval ctx "(/ 4 2)")) "/")
|
||||
(assert (= 3 (ct-eval ctx "(inc 2)")) "inc")
|
||||
(assert (= 1 (ct-eval ctx "(dec 2)")) "dec")
|
||||
(assert (= 1 (ct-eval ctx "(quot 5 3)")) "quot")
|
||||
(assert (= 2 (ct-eval ctx "(rem 5 3)")) "rem")
|
||||
(assert (= 2 (ct-eval ctx "(mod 5 3)")) "mod")
|
||||
(assert (= 3 (ct-eval ctx "(max 1 2 3)")) "max")
|
||||
(assert (= 1 (ct-eval ctx "(min 1 2 3)")) "min"))
|
||||
(print " passed")
|
||||
(print "2: predicates...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(nil? nil)")) "nil?")
|
||||
(assert (= false (ct-eval ctx "(nil? 1)")) "nil? false")
|
||||
(assert (= false (ct-eval ctx "(not true)")) "not")
|
||||
(assert (= true (ct-eval ctx "(not false)")) "not false")
|
||||
(assert (= true (ct-eval ctx "(some? 1)")) "some?")
|
||||
(assert (= true (ct-eval ctx "(string? \"hello\")")) "string?")
|
||||
(assert (= true (ct-eval ctx "(number? 42)")) "number?")
|
||||
(assert (= true (ct-eval ctx "(fn? inc)")) "fn?")
|
||||
(assert (= true (ct-eval ctx "(keyword? :foo)")) "keyword?")
|
||||
(assert (= true (ct-eval ctx "(map? {:a 1})")) "map?")
|
||||
(assert (= true (ct-eval ctx "(zero? 0)")) "zero?")
|
||||
(assert (= true (ct-eval ctx "(pos? 5)")) "pos?")
|
||||
(assert (= true (ct-eval ctx "(neg? -1)")) "neg?")
|
||||
(assert (= true (ct-eval ctx "(even? 4)")) "even?")
|
||||
(assert (= true (ct-eval ctx "(odd? 3)")) "odd?"))
|
||||
(print " passed")
|
||||
(print "3: comparison...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(= 1 1)")) "=")
|
||||
(assert (= false (ct-eval ctx "(= 1 2)")) "= false")
|
||||
(assert (= true (ct-eval ctx "(= 1 1 1)")) "= three")
|
||||
(assert (= false (ct-eval ctx "(not= 1 1)")) "not= false")
|
||||
(assert (= true (ct-eval ctx "(not= 1 2)")) "not= true")
|
||||
(assert (= true (ct-eval ctx "(< 1 2)")) "<")
|
||||
(assert (= true (ct-eval ctx "(> 2 1)")) ">")
|
||||
(assert (= true (ct-eval ctx "(<= 1 1)")) "<=")
|
||||
(assert (= true (ct-eval ctx "(>= 2 2)")) ">="))
|
||||
(print " passed")
|
||||
(print "4: vectors...")
|
||||
(let [ctx (init)]
|
||||
(assert (= :a (ct-eval ctx "(nth [:a :b :c :d] 0)")) "nth")
|
||||
(assert (= [1 2 3 4] (ct-eval ctx "(conj [1 2 3] 4)")) "conj")
|
||||
(assert (= 1 (ct-eval ctx "(first [1 2 3])")) "first")
|
||||
(assert (= [2 3] (ct-eval ctx "(rest [1 2 3])")) "rest")
|
||||
(assert (= 3 (ct-eval ctx "(count [1 2 3])")) "count"))
|
||||
(print " passed")
|
||||
(print "5: maps...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 1 (ct-eval ctx "(get {:a 1} :a)")) "get")
|
||||
(assert (= nil (ct-eval ctx "(get {:a 1} :z)")) "get missing")
|
||||
(assert (= :d (ct-eval ctx "(get {:a 1} :z :d)")) "get default")
|
||||
(assert (= {:a 1 :b 2} (ct-eval ctx "(assoc {:a 1} :b 2)")) "assoc")
|
||||
(assert (= {:b 2} (ct-eval ctx "(dissoc {:a 1 :b 2} :a)")) "dissoc")
|
||||
(assert (= true (ct-eval ctx "(contains? {:a 1} :a)")) "contains?")
|
||||
(assert (= 3 (ct-eval ctx "(count {:a 1 :b 2 :c 3})")) "count")
|
||||
(assert (= 2 (ct-eval ctx "(count (keys {:a 1 :b 2}))")) "keys count"))
|
||||
(print " passed")
|
||||
(print "6: sets...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(set? #{1 2 3})")) "set?")
|
||||
(assert (= 4 (ct-eval ctx "(count (conj #{1 2 3} 4))")) "conj count")
|
||||
(assert (= 2 (ct-eval ctx "(count (disj #{1 2 3} 3))")) "disj count")
|
||||
(assert (= 3 (ct-eval ctx "(count #{1 2 3})")) "count")
|
||||
(assert (= true (ct-eval ctx "(= #{1 2 3} #{3 2 1})")) "= order-independent"))
|
||||
(print " passed")
|
||||
(print "\nAll CLJS Ported Part 1a tests passed!")
|
||||
|
||||
37
test/integration/ports/cljs-port-1b-test.janet
Normal file
37
test/integration/ports/cljs-port-1b-test.janet
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
(use ../../../src/jolt/api)
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
(print "=== CLJS Ported Part 1b ===")
|
||||
(print "7: seq operations...")
|
||||
(let [ctx (init)]
|
||||
(assert (= nil (ct-eval ctx "(seq [])")) "seq empty")
|
||||
(assert (= [2 3 4] (ct-eval ctx "(map inc [1 2 3])")) "map")
|
||||
(assert (= [1 3] (ct-eval ctx "(filter odd? [1 2 3 4])")) "filter")
|
||||
(assert (= 6 (ct-eval ctx "(reduce + [1 2 3])")) "reduce")
|
||||
(assert (= [1 2 3] (ct-eval ctx "(take 3 [1 2 3 4 5])")) "take")
|
||||
(assert (= [4 5] (ct-eval ctx "(drop 3 [1 2 3 4 5])")) "drop")
|
||||
(assert (= [3 2 1] (ct-eval ctx "(reverse [1 2 3])")) "reverse")
|
||||
(assert (= true (ct-eval ctx "(every? even? [2 4 6])")) "every?"))
|
||||
(print " passed")
|
||||
(print "8: printing...")
|
||||
(let [ctx (init)]
|
||||
(assert (= "hello" (ct-eval ctx "(str \"hello\")")) "str")
|
||||
(assert (= "ab" (ct-eval ctx "(str \"a\" \"b\")")) "str two")
|
||||
(assert (= "42" (ct-eval ctx "(str 42)")) "str number")
|
||||
(assert (= "a" (ct-eval ctx "(name :a)")) "name"))
|
||||
(print " passed")
|
||||
(print "9: apply...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 3 (ct-eval ctx "(apply + [1 2])")) "apply +")
|
||||
(assert (= 3 (ct-eval ctx "(apply max [1 3 2])")) "apply max"))
|
||||
(print " passed")
|
||||
(print "10: equality...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(= {:a 1 :b 2} {:b 2 :a 1})")) "map order"))
|
||||
(print " passed")
|
||||
(print "11: higher-order fns...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 3 (ct-eval ctx "((comp inc inc) 1)")) "comp")
|
||||
(assert (function? (ct-eval ctx "(partial + 1 2)")) "partial returns fn")
|
||||
(assert (= 3 (ct-eval ctx "(identity 3)")) "identity"))
|
||||
(print " passed")
|
||||
(print "\nAll CLJS Ported Part 1b tests passed!")
|
||||
77
test/integration/ports/cljs-port-2-test.janet
Normal file
77
test/integration/ports/cljs-port-2-test.janet
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
(use ../../../src/jolt/api)
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
(print "=== CLJS Ported Part 2 ===")
|
||||
(print "12: atoms...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 0 (ct-eval ctx "(deref (atom 0))")) "deref")
|
||||
(assert (= 1 (ct-eval ctx "(let [a (atom 0)] (swap! a inc) (deref a))")) "swap!")
|
||||
(assert (= true (ct-eval ctx "(atom? (atom 0))")) "atom?"))
|
||||
(print " ok")
|
||||
(print "13: special forms...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 30 (ct-eval ctx "(let [x 10 y 20] (+ x y))")) "let")
|
||||
(assert (= :a (ct-eval ctx "(if true :a :b)")) "if true")
|
||||
(assert (= :b (ct-eval ctx "(if false :a :b)")) "if false")
|
||||
(assert (= 2 (ct-eval ctx "(do 1 2)")) "do")
|
||||
(assert (= 3 (ct-eval ctx "(loop [x 0] (if (< x 3) (recur (inc x)) x))")) "loop")
|
||||
(assert (= "caught" (ct-eval ctx "(try (throw 42) (catch Exception e \"caught\"))")) "try catch"))
|
||||
(print " ok")
|
||||
(print "14: macros...")
|
||||
(let [ctx (init)]
|
||||
(ct-eval ctx "(defn add [a b] (+ a b))")
|
||||
(assert (= 7 (ct-eval ctx "(add 3 4)")) "defn")
|
||||
(assert (= 42 (ct-eval ctx "(when true 42)")) "when")
|
||||
(assert (= 3 (ct-eval ctx "(and 1 2 3)")) "and")
|
||||
(assert (= 1 (ct-eval ctx "(or 1 2 3)")) "or")
|
||||
(assert (= 49 (ct-eval ctx "((fn [x] (* x x)) 7)")) "fn"))
|
||||
(print " ok")
|
||||
(print "15: constructors...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 3 (ct-eval ctx "(count (vector 1 2 3))")) "vector count")
|
||||
(assert (= 2 (ct-eval ctx "(count (hash-map :a 1 :b 2))")) "hash-map count")
|
||||
(assert (= 3 (ct-eval ctx "(count (hash-set 1 2 3))")) "hash-set count")
|
||||
(assert (= 3 (ct-eval ctx "(count (zipmap [:a :b :c] [1 2 3]))")) "zipmap count"))
|
||||
(print " ok")
|
||||
(print "16: printing...")
|
||||
(let [ctx (init)]
|
||||
(assert (= "hello" (ct-eval ctx "(str \"hello\")")) "str")
|
||||
(assert (= "42" (ct-eval ctx "(str 42)")) "str number")
|
||||
(assert (= "a" (ct-eval ctx "(name :a)")) "name")
|
||||
(assert (= ":hello" (ct-eval ctx "(pr-str :hello)")) "pr-str keyword"))
|
||||
(print " ok")
|
||||
(print "17: apply...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 3 (ct-eval ctx "(apply + [1 2])")) "apply +")
|
||||
(assert (= 3 (ct-eval ctx "(apply max [1 3 2])")) "apply max"))
|
||||
(print " ok")
|
||||
(print "18: equality...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(= {:a 1 :b 2} {:b 2 :a 1})")) "map order-independent")
|
||||
(assert (= false (ct-eval ctx "(= {:a 1} {:a 2})")) "map different values")
|
||||
(assert (= 1 (ct-eval ctx "(:a (with-meta {:a 1} {:c 3}))")) "with-meta preserves value")
|
||||
(assert (= 3 (ct-eval ctx "(:c (with-meta {:a 1} {:c 3}))")) "with-meta preserves meta via get"))
|
||||
(print " ok")
|
||||
(print "19: higher-order...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 3 (ct-eval ctx "((comp inc inc) 1)")) "comp")
|
||||
(assert (function? (ct-eval ctx "(partial + 1 2)")) "partial returns fn")
|
||||
(assert (= 3 (ct-eval ctx "(identity 3)")) "identity"))
|
||||
(print " ok")
|
||||
(print "20: seq edge cases...")
|
||||
(let [ctx (init)]
|
||||
(assert (= nil (ct-eval ctx "(seq [])")) "seq empty")
|
||||
(assert (= nil (ct-eval ctx "(seq nil)")) "seq nil")
|
||||
(assert (= nil (ct-eval ctx "(first nil)")) "first nil")
|
||||
(assert (= 1 (ct-eval ctx "(first [1 2 3])")) "first vector"))
|
||||
(print " ok")
|
||||
(print "21: atoms extended...")
|
||||
(let [ctx (init)]
|
||||
(ct-eval ctx "(def a (atom 10))")
|
||||
(assert (= 10 (ct-eval ctx "(deref a)")) "deref")
|
||||
(ct-eval ctx "(reset! a 42)")
|
||||
(assert (= 42 (ct-eval ctx "(deref a)")) "reset!")
|
||||
(ct-eval ctx "(swap! a inc)")
|
||||
(assert (= 43 (ct-eval ctx "(deref a)")) "swap! inc")
|
||||
(assert (= 43 (ct-eval ctx "@a")) "@ deref macro"))
|
||||
(print " ok")
|
||||
(print "\nAll CLJS Ported Part 2 tests passed!")
|
||||
32
test/integration/ports/cljs-port-3-test.janet
Normal file
32
test/integration/ports/cljs-port-3-test.janet
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
(use ../../../src/jolt/api)
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
(print "=== CLJS Ported Part 3 ===")
|
||||
(print "16: destructuring...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 1 (ct-eval ctx "(let [[x] [1 2 3]] x)")) "seq destructure")
|
||||
(assert (= 2 (ct-eval ctx "(let [[_ y] [1 2 3]] y)")) "seq destructure rest")
|
||||
(assert (= 3 (ct-eval ctx "(let [[_ _ z] [1 2 3]] z)")) "seq destructure last"))
|
||||
(print " passed")
|
||||
(print "17: set operations...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(set? #{1 2 3})")) "set?")
|
||||
(assert (= 3 (ct-eval ctx "(count #{1 2 3})")) "set count")
|
||||
(assert (= true (ct-eval ctx "(contains? #{1 2} 1)")) "contains? set")
|
||||
(assert (= 1 (ct-eval ctx "(get #{1 2 3} 1)")) "get set"))
|
||||
(print " passed")
|
||||
(print "18: reader literals...")
|
||||
(let [ctx (init)]
|
||||
(assert (= [1 2 3] (ct-eval ctx "[1 2 3]")) "vector literal")
|
||||
(assert (= {:a 1} (ct-eval ctx "{:a 1}")) "map literal")
|
||||
(assert (= true (ct-eval ctx "true")) "true literal")
|
||||
(assert (= nil (ct-eval ctx "nil")) "nil literal")
|
||||
(assert (= 42 (ct-eval ctx "42")) "number literal"))
|
||||
(print " passed")
|
||||
(print "19: syntax-quote...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(= '(1 2 3) '(1 2 3))")) "sq basic list"))
|
||||
(print " passed")
|
||||
(print "20: walk...")
|
||||
(print " skipped (clojure.walk needs IFn protocol)")
|
||||
|
||||
(print "\nAll CLJS Ported Part 3 tests passed!")
|
||||
22
test/integration/ports/cljs-port-3b-test.janet
Normal file
22
test/integration/ports/cljs-port-3b-test.janet
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
(use ../../../src/jolt/api)
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
(print "=== CLJS Ported Part 3b ===")
|
||||
(print "21: clojure.string...")
|
||||
(let [ctx (init)]
|
||||
(load-string ctx (slurp "src/jolt/clojure/string.clj"))
|
||||
(assert (= true (ct-eval ctx "(blank? nil)")) "blank? nil")
|
||||
(assert (= true (ct-eval ctx "(blank? \" \")")) "blank? spaces")
|
||||
(assert (= "Abc" (ct-eval ctx "(capitalize \"abc\")")) "capitalize")
|
||||
(assert (= "hello" (ct-eval ctx "(lower-case \"HELLO\")")) "lower-case")
|
||||
(assert (= "hello" (ct-eval ctx "(trim \" hello \")")) "trim"))
|
||||
(print " passed")
|
||||
(print "22: clojure.set...")
|
||||
(let [ctx (init)]
|
||||
(load-string ctx (slurp "src/jolt/clojure/set.clj"))
|
||||
(assert (= 3 (ct-eval ctx "(count (union #{1 2} #{2 3}))")) "union")
|
||||
(assert (= 1 (ct-eval ctx "(count (intersection #{1 2} #{2 3}))")) "intersection")
|
||||
(assert (= 1 (ct-eval ctx "(count (difference #{1 2} #{2 3}))")) "difference"))
|
||||
(print " passed")
|
||||
(print "\nAll CLJS Ported Part 3 tests passed!")
|
||||
|
||||
(print "\nAll CLJS Ported Part 3b tests passed!")
|
||||
48
test/integration/ports/cljs-port-4-test.janet
Normal file
48
test/integration/ports/cljs-port-4-test.janet
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
(use ../../../src/jolt/api)
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
(print "=== CLJS Ported Part 4 ===")
|
||||
|
||||
(print "23: deftype/defrecord...")
|
||||
(let [ctx (init)]
|
||||
(ct-eval ctx "(deftype Point [x y])")
|
||||
(assert (= true (ct-eval ctx "(instance? Point (Point. 3 4))")) "instance? true")
|
||||
(assert (= 3 (ct-eval ctx "(. (Point. 3 4) x)")) ".field access")
|
||||
(ct-eval ctx "(defrecord Person [name age])")
|
||||
(assert (= true (ct-eval ctx "(map? (Person. \"A\" 30))")) "record is map?")
|
||||
(assert (= "Alice" (ct-eval ctx "(:name (Person. \"Alice\" 30))")) "record keyword access"))
|
||||
(print " ok")
|
||||
|
||||
(print "24: multimethods...")
|
||||
(let [ctx (init)]
|
||||
(ct-eval ctx "(defmulti greet (fn [x] (:lang x)))")
|
||||
(ct-eval ctx "(defmethod greet :en [_] \"hello\")")
|
||||
(ct-eval ctx "(defmethod greet :fr [_] \"bonjour\")")
|
||||
(assert (= "hello" (ct-eval ctx "(greet {:lang :en})")) "dispatch :en")
|
||||
(assert (= "bonjour" (ct-eval ctx "(greet {:lang :fr})")) "dispatch :fr"))
|
||||
(print " ok")
|
||||
|
||||
(print "25: protocols...")
|
||||
(let [ctx (init)]
|
||||
(ct-eval ctx "(defprotocol Greet (g [this]))")
|
||||
(ct-eval ctx "(deftype Dog [name])")
|
||||
(ct-eval ctx "(extend-type Dog Greet (g [this] (str \"woof \" (.-name this))))")
|
||||
(assert (= "woof Rex" (ct-eval ctx "(g (Dog. \"Rex\"))")) "extend-type"))
|
||||
(print " ok")
|
||||
|
||||
(print "26: var system...")
|
||||
(let [ctx (init)]
|
||||
(ct-eval ctx "(def xv 42)")
|
||||
(assert (= true (ct-eval ctx "(var? (var xv))")) "var?")
|
||||
(assert (= 42 (ct-eval ctx "(var-get (var xv))")) "var-get")
|
||||
(ct-eval ctx "(var-set (var xv) 99)")
|
||||
(assert (= 99 (ct-eval ctx "(var-get (var xv))")) "var-set"))
|
||||
(print " ok")
|
||||
|
||||
(print "27: range/into/concat...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 5 (ct-eval ctx "(count (range 5))")) "range count")
|
||||
(assert (= [0 1 2 3 4] (ct-eval ctx "(into [] (range 5))")) "range into vec")
|
||||
(assert (= 4 (ct-eval ctx "(count (concat [1 2] [3 4]))")) "concat count"))
|
||||
(print " ok")
|
||||
|
||||
(print "\nAll CLJS Ported Part 4 tests passed!")
|
||||
22
test/integration/ports/cljs-port-5-test.janet
Normal file
22
test/integration/ports/cljs-port-5-test.janet
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
(use ../../../src/jolt/api)
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
(print "=== CLJS Ported Part 5 ===")
|
||||
(print "22: destructuring...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 1 (ct-eval ctx "(let [[x] [1 2 3]] x)")) "seq destructure")
|
||||
(assert (= 2 (ct-eval ctx "(let [[_ y] [1 2 3]] y)")) "seq destructure rest"))
|
||||
(print " ok")
|
||||
(print "23: metadata...")
|
||||
(let [ctx (init)]
|
||||
(ct-eval ctx "(def ^:dynamic *dyn* 42)")
|
||||
(assert (= true (ct-eval ctx "(var-dynamic? (var *dyn*))")) "dynamic metadata")
|
||||
(assert (= 1 (ct-eval ctx "(:a (with-meta {:a 1} {:c 3}))")) "with-meta preserves"))
|
||||
(print " ok")
|
||||
(print "24: function composition...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "((complement odd?) 2)")) "complement")
|
||||
(assert (= 5 (ct-eval ctx "((constantly 5) :anything)")) "constantly")
|
||||
(assert (= true (ct-eval ctx "((every-pred number? even?) 4)")) "every-pred")
|
||||
(assert (= ":hello" (ct-eval ctx "(pr-str :hello)")) "pr-str keyword"))
|
||||
(print " ok")
|
||||
(print "\nAll CLJS Ported Part 5 tests passed!")
|
||||
30
test/integration/ports/cljs-port-6-test.janet
Normal file
30
test/integration/ports/cljs-port-6-test.janet
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
(use ../../../src/jolt/api)
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
(print "=== CLJS Ported Part 6 ===")
|
||||
|
||||
(print "28: anon fn #()...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 6 (ct-eval ctx "(#(+ % 5) 1)")) "#() %")
|
||||
(assert (= 0 (ct-eval ctx "(#(do 0))")) "#() do body"))
|
||||
(print " ok")
|
||||
|
||||
(print "29: symbol operations...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(symbol? 'foo)")) "symbol?")
|
||||
(assert (= "foo" (ct-eval ctx "(name 'foo)")) "name symbol")
|
||||
(assert (= "bar" (ct-eval ctx "(name :bar)")) "name keyword"))
|
||||
(print " ok")
|
||||
|
||||
(print "30: keyword operations...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(keyword? :foo)")) "keyword?")
|
||||
(assert (= :foo (ct-eval ctx "(keyword \"foo\")")) "keyword string"))
|
||||
(print " ok")
|
||||
|
||||
(print "31: list operations...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 3 (ct-eval ctx "(count (list 3 2 1))")) "list count")
|
||||
(assert (= 1 (ct-eval ctx "(first '(1 2 3))")) "first list"))
|
||||
(print " ok")
|
||||
|
||||
(print "\nAll CLJS Ported Part 6 tests passed!\n")
|
||||
20
test/integration/ports/cljs-port-7-test.janet
Normal file
20
test/integration/ports/cljs-port-7-test.janet
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
(use ../../../src/jolt/api)
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
(print "=== CLJS Ported Part 7 ===")
|
||||
|
||||
(print "32: seq destructuring...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 1 (ct-eval ctx "(let [[x] [1 2 3]] x)")) "seq destructure")
|
||||
(assert (= 2 (ct-eval ctx "(let [[_ y] [1 2 3]] y)")) "seq destructure skip")
|
||||
(assert (= 3 (ct-eval ctx "(let [[_ _ z] [1 2 3]] z)")) "seq destructure end"))
|
||||
(print " ok")
|
||||
|
||||
(print "33: & rest args...")
|
||||
(let [ctx (init)]
|
||||
(ct-eval ctx "(defn sum [& xs] (apply + xs))")
|
||||
(assert (= 6 (ct-eval ctx "(sum 1 2 3)")) "& rest sum")
|
||||
(ct-eval ctx "(defn first-two [a b & rest] (count rest))")
|
||||
(assert (= 2 (ct-eval ctx "(first-two 1 2 3 4)")) "& rest after fixed"))
|
||||
(print " ok")
|
||||
|
||||
(print "\nAll CLJS Ported Part 7 tests passed!\n")
|
||||
35
test/integration/ports/cljs-port-8-test.janet
Normal file
35
test/integration/ports/cljs-port-8-test.janet
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
(use ../../../src/jolt/api)
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
(print "=== CLJS Ported Part 8 ===")
|
||||
|
||||
(print "35: range and repeat...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 5 (ct-eval ctx "(count (range 5))")) "range")
|
||||
(assert (= 4 (ct-eval ctx "(count (repeat 4 :x))")) "repeat")
|
||||
(assert (= 3 (ct-eval ctx "(count (repeatedly 3 (constantly :y)))")) "repeatedly"))
|
||||
(print " ok")
|
||||
|
||||
(print "36: concat and into...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 4 (ct-eval ctx "(count (concat [1 2] [3 4]))")) "concat")
|
||||
(assert (= 4 (ct-eval ctx "(count (into [] (range 4)))")) "into"))
|
||||
(print " ok")
|
||||
|
||||
(print "37: take-while/drop-while...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 2 (ct-eval ctx "(count (take-while even? [2 4 3 5]))")) "take-while")
|
||||
(assert (= 2 (ct-eval ctx "(count (drop-while even? [2 4 3 5]))")) "drop-while"))
|
||||
(print " ok")
|
||||
|
||||
(print "38: partition...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 2 (ct-eval ctx "(count (partition 2 [1 2 3 4]))")) "partition 2"))
|
||||
(print " ok")
|
||||
|
||||
(print "39: sorting...")
|
||||
(let [ctx (init)]
|
||||
(assert (= [1 2 3] (ct-eval ctx "(sort [3 1 2])")) "sort")
|
||||
(assert (= [1 2 3] (ct-eval ctx "(distinct [1 2 1 3 2])")) "distinct"))
|
||||
(print " ok")
|
||||
|
||||
(print "\nAll CLJS Ported Part 8 tests passed!\n")
|
||||
18
test/integration/ports/cljs-port-9-test.janet
Normal file
18
test/integration/ports/cljs-port-9-test.janet
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
(use ../../../src/jolt/api)
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
(print "=== CLJS Ported Part 9 ===")
|
||||
|
||||
(print "40: seq predicates...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(empty? [])")) "empty? true")
|
||||
(assert (= false (ct-eval ctx "(empty? [1])")) "empty? false")
|
||||
(assert (= true (ct-eval ctx "(every? pos? [1 2 3])")) "every? pos"))
|
||||
(print " ok")
|
||||
|
||||
(print "41: complement...")
|
||||
(let [ctx (init)]
|
||||
(assert (= false (ct-eval ctx "((complement pos?) 1)")) "complement pos")
|
||||
(assert (= true (ct-eval ctx "((complement pos?) -1)")) "complement neg"))
|
||||
(print " ok")
|
||||
|
||||
(print "\nAll CLJS Ported Part 9 tests passed!\n")
|
||||
131
test/integration/ports/cljs-port-test.janet
Normal file
131
test/integration/ports/cljs-port-test.janet
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
(use ../../../src/jolt/api)
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
(print "CLJS Ported Tests")
|
||||
|
||||
(print "1: math...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 3 (ct-eval ctx "(+ 1 2)")) "+")
|
||||
(assert (= 1 (ct-eval ctx "(- 3 2)")) "-")
|
||||
(assert (= 6 (ct-eval ctx "(* 2 3)")) "*")
|
||||
(assert (= 3 (ct-eval ctx "(inc 2)")) "inc")
|
||||
(assert (= 1 (ct-eval ctx "(dec 2)")) "dec")
|
||||
(assert (= 1 (ct-eval ctx "(quot 5 3)")) "quot")
|
||||
(assert (= 2 (ct-eval ctx "(rem 5 3)")) "rem")
|
||||
(assert (= 2 (ct-eval ctx "(mod 5 3)")) "mod")
|
||||
(assert (= 3 (ct-eval ctx "(max 1 2 3)")) "max")
|
||||
(assert (= 1 (ct-eval ctx "(min 1 2 3)")) "min"))
|
||||
(print " ok")
|
||||
|
||||
(print "2: predicates...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(nil? nil)")) "nil?")
|
||||
(assert (= false (ct-eval ctx "(nil? 1)")) "nil? false")
|
||||
(assert (= false (ct-eval ctx "(not true)")) "not")
|
||||
(assert (= true (ct-eval ctx "(not false)")) "not false")
|
||||
(assert (= true (ct-eval ctx "(some? 1)")) "some?")
|
||||
(assert (= true (ct-eval ctx "(number? 42)")) "number?")
|
||||
(assert (= true (ct-eval ctx "(fn? inc)")) "fn?")
|
||||
(assert (= true (ct-eval ctx "(keyword? :foo)")) "keyword?")
|
||||
(assert (= true (ct-eval ctx "(zero? 0)")) "zero?")
|
||||
(assert (= true (ct-eval ctx "(pos? 5)")) "pos?")
|
||||
(assert (= true (ct-eval ctx "(neg? -1)")) "neg?")
|
||||
(assert (= true (ct-eval ctx "(even? 4)")) "even?")
|
||||
(assert (= true (ct-eval ctx "(odd? 3)")) "odd?"))
|
||||
(print " ok")
|
||||
|
||||
(print "3: comparison...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(= 1 1)")) "=")
|
||||
(assert (= true (ct-eval ctx "(not= 1 2)")) "not= true")
|
||||
(assert (= true (ct-eval ctx "(< 1 2)")) "<")
|
||||
(assert (= true (ct-eval ctx "(> 2 1)")) ">")
|
||||
(assert (= true (ct-eval ctx "(<= 1 1)")) "<=")
|
||||
(assert (= true (ct-eval ctx "(>= 2 2)")) ">="))
|
||||
(print " ok")
|
||||
|
||||
(print "4: vectors...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(= :a (nth [:a :b :c :d] 0))")) "nth")
|
||||
(assert (= true (ct-eval ctx "(= 4 (count (conj [1 2 3] 4)))")) "conj count")
|
||||
(assert (= true (ct-eval ctx "(= 1 (first [1 2 3]))")) "first")
|
||||
(assert (= true (ct-eval ctx "(= 2 (count (rest [1 2 3])))")) "rest count")
|
||||
(assert (= true (ct-eval ctx "(= 3 (count [1 2 3]))")) "count"))
|
||||
(print " ok")
|
||||
|
||||
(print "5: maps...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(= 1 (get {:a 1} :a))")) "get")
|
||||
(assert (= true (ct-eval ctx "(nil? (get {:a 1} :z))")) "get missing")
|
||||
(assert (= true (ct-eval ctx "(= :d (get {:a 1} :z :d))")) "get default")
|
||||
(assert (= true (ct-eval ctx "(= 2 (count (assoc {:a 1} :b 2)))")) "assoc count")
|
||||
(assert (= true (ct-eval ctx "(= 1 (count (dissoc {:a 1 :b 2} :a)))")) "dissoc count")
|
||||
(assert (= true (ct-eval ctx "(contains? {:a 1} :a)")) "contains?")
|
||||
(assert (= true (ct-eval ctx "(= 3 (count {:a 1 :b 2 :c 3}))")) "count")
|
||||
(assert (= true (ct-eval ctx "(= 2 (count (keys {:a 1 :b 2})))")) "keys"))
|
||||
(print " ok")
|
||||
|
||||
(print "6: sets...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(set? #{1 2 3})")) "set?")
|
||||
(assert (= true (ct-eval ctx "(= 4 (count (conj #{1 2 3} 4)))")) "conj count")
|
||||
(assert (= true (ct-eval ctx "(= 2 (count (disj #{1 2 3} 3)))")) "disj count")
|
||||
(assert (= true (ct-eval ctx "(= 3 (count #{1 2 3}))")) "count")
|
||||
(assert (= true (ct-eval ctx "(= #{1 2 3} #{3 2 1})")) "= order"))
|
||||
(print " ok")
|
||||
|
||||
(print "7: seq ops...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(nil? (seq []))")) "seq empty")
|
||||
(assert (= true (ct-eval ctx "(= 3 (count (map inc [1 2 3])))")) "map count")
|
||||
(assert (= true (ct-eval ctx "(= 2 (count (filter odd? [1 2 3 4])))")) "filter count")
|
||||
(assert (= true (ct-eval ctx "(= 6 (reduce + [1 2 3]))")) "reduce")
|
||||
(assert (= true (ct-eval ctx "(= 3 (count (take 3 [1 2 3 4 5])))")) "take count")
|
||||
(assert (= true (ct-eval ctx "(= 2 (count (drop 3 [1 2 3 4 5])))")) "drop count")
|
||||
(assert (= true (ct-eval ctx "(= 3 (count (reverse [1 2 3])))")) "reverse count")
|
||||
(assert (= true (ct-eval ctx "(every? even? [2 4 6])")) "every?"))
|
||||
(print " ok")
|
||||
|
||||
(print "8: atoms...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(= 0 (deref (atom 0)))")) "deref")
|
||||
(assert (= true (ct-eval ctx "(= 1 (let [a (atom 0)] (swap! a inc) (deref a)))")) "swap!")
|
||||
(assert (= true (ct-eval ctx "(atom? (atom 0))")) "atom?"))
|
||||
(print " ok")
|
||||
|
||||
(print "9: special forms...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(= 30 (let [x 10 y 20] (+ x y)))")) "let")
|
||||
(assert (= true (ct-eval ctx "(= :a (if true :a :b))")) "if true")
|
||||
(assert (= true (ct-eval ctx "(= :b (if false :a :b))")) "if false")
|
||||
(assert (= true (ct-eval ctx "(= 2 (do 1 2))")) "do")
|
||||
(assert (= true (ct-eval ctx "(= 3 (loop [x 0] (if (< x 3) (recur (inc x)) x)))")) "loop")
|
||||
(assert (= true (ct-eval ctx "(= :caught (try (throw 42) (catch Exception e :caught)))")) "try"))
|
||||
(print " ok")
|
||||
|
||||
(print "10: macros...")
|
||||
(let [ctx (init)]
|
||||
(ct-eval ctx "(defn add [a b] (+ a b))")
|
||||
(assert (= true (ct-eval ctx "(= 7 (add 3 4))")) "defn")
|
||||
(assert (= true (ct-eval ctx "(= 42 (when true 42))")) "when")
|
||||
(assert (= true (ct-eval ctx "(= 3 (and 1 2 3))")) "and")
|
||||
(assert (= true (ct-eval ctx "(= 1 (or 1 2 3))")) "or")
|
||||
(assert (= true (ct-eval ctx "(= 49 ((fn [x] (* x x)) 7))")) "fn"))
|
||||
(print " ok")
|
||||
|
||||
(print "11: higher-order...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(= 3 ((comp inc inc) 1))")) "comp")
|
||||
(assert (= true (ct-eval ctx "(= 3 ((partial + 1 2)))")) "partial")
|
||||
(assert (= true (ct-eval ctx "(= 5 ((constantly 5) :anything))")) "constantly")
|
||||
(assert (= true (ct-eval ctx "(= 3 (identity 3))")) "identity"))
|
||||
(print " ok")
|
||||
|
||||
(print "12: constructors...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(= 3 (count (vector 1 2 3)))")) "vector count")
|
||||
(assert (= true (ct-eval ctx "(= 2 (count (hash-map :a 1 :b 2)))")) "hash-map count")
|
||||
(assert (= true (ct-eval ctx "(= 3 (count (hash-set 1 2 3)))")) "hash-set count")
|
||||
(assert (= true (ct-eval ctx "(= 3 (count (zipmap [:a :b :c] [1 2 3])))")) "zipmap count"))
|
||||
(print " ok")
|
||||
|
||||
(print "\nAll CLJS Ported Tests passed!")
|
||||
59
test/integration/ports/phase10-test.janet
Normal file
59
test/integration/ports/phase10-test.janet
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
(use ../../../src/jolt/api)
|
||||
(use ../../../src/jolt/reader)
|
||||
(use ../../../src/jolt/evaluator)
|
||||
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
|
||||
(defn load-clj [ctx filepath]
|
||||
(def source (slurp filepath))
|
||||
(var remaining source)
|
||||
(while (> (length (string/trim remaining)) 0)
|
||||
(def fr (parse-next remaining))
|
||||
(def form (fr 0))
|
||||
(set remaining (fr 1))
|
||||
(when (not (nil? form))
|
||||
(eval-form ctx @{} form))))
|
||||
|
||||
(print "40: clojure.string...")
|
||||
(let [ctx (init)]
|
||||
(load-clj ctx "src/jolt/clojure/string.clj")
|
||||
(assert (= true (ct-eval ctx "(blank? nil)")) "blank? nil")
|
||||
(assert (= true (ct-eval ctx "(blank? \" \")")) "blank? whitespace")
|
||||
(assert (= false (ct-eval ctx "(blank? \"a\")")) "blank? non-empty")
|
||||
(assert (= "Abc" (ct-eval ctx "(capitalize \"abc\")")) "capitalize")
|
||||
(assert (= "hello" (ct-eval ctx "(lower-case \"HELLO\")")) "lower-case")
|
||||
(assert (= "HELLO" (ct-eval ctx "(upper-case \"hello\")")) "upper-case")
|
||||
(assert (= true (ct-eval ctx "(includes? \"hello\" \"ell\")")) "includes? true")
|
||||
(assert (= "foo" (ct-eval ctx "(trim \"foo\")")) "trim")
|
||||
(assert (= true (ct-eval ctx "(starts-with? \"hello\" \"he\")")) "starts-with? true")
|
||||
(assert (= true (ct-eval ctx "(ends-with? \"hello\" \"lo\")")) "ends-with? true"))
|
||||
(print " passed")
|
||||
|
||||
(print "41: clojure.set...")
|
||||
(let [ctx (init)]
|
||||
(load-clj ctx "src/jolt/clojure/set.clj")
|
||||
(assert (= 3 (ct-eval ctx "(count (union #{1 2} #{2 3}))")) "union")
|
||||
(assert (= 1 (ct-eval ctx "(count (intersection #{1 2} #{2 3}))")) "intersection")
|
||||
(assert (= 1 (ct-eval ctx "(count (difference #{1 2} #{2 3}))")) "difference")
|
||||
(assert (= true (ct-eval ctx "(subset? #{1} #{1 2 3})")) "subset? true")
|
||||
(assert (= true (ct-eval ctx "(superset? #{1 2 3} #{1})")) "superset? true"))
|
||||
(print " passed")
|
||||
|
||||
(print "42: clojure.walk/zip — modules loadable")
|
||||
(let [ctx (init)] (load-clj ctx "src/jolt/clojure/walk.clj") (print " walk: loaded"))
|
||||
(let [ctx (init)] (load-clj ctx "src/jolt/clojure/zip.clj") (print " zip: loaded"))
|
||||
(print " passed")
|
||||
|
||||
(print "43: stdlib summary")
|
||||
(print " clojure.string — 19 functions")
|
||||
(print " clojure.set — 10 functions")
|
||||
(print " clojure.walk — 7 functions")
|
||||
(print " clojure.zip — zipper data structure")
|
||||
(print " clojure.edn — EDN reader/writer stubs")
|
||||
(print " clojure.java-io — file I/O wrappers")
|
||||
(print " jolt.interop — Janet interop")
|
||||
(print " jolt.shell — shell command execution")
|
||||
(print " jolt.http — HTTP client")
|
||||
(print " passed")
|
||||
|
||||
(print "All Phase 10 tests passed!")
|
||||
50
test/integration/ports/phase12-test.janet
Normal file
50
test/integration/ports/phase12-test.janet
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
# Phase 12: Protocol System Tests
|
||||
(use ../../../src/jolt/api)
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
|
||||
(print "35: defprotocol...")
|
||||
(let [ctx (init)]
|
||||
(ct-eval ctx "(defprotocol Greet (greet [this]))")
|
||||
(let [p (ct-eval ctx "Greet")]
|
||||
(assert (not (nil? p)) "protocol var exists")
|
||||
(assert (= :jolt/protocol (get p :jolt/type)) "protocol type tag")
|
||||
(assert (get (get p :methods) :greet) "protocol has greet method"))
|
||||
(assert (or (function? (ct-eval ctx "greet")) (cfunction? (ct-eval ctx "greet"))) "method fn exists"))
|
||||
(print " passed")
|
||||
|
||||
(print "36: extend-type...")
|
||||
(let [ctx (init)]
|
||||
(ct-eval ctx "(deftype Person [name])")
|
||||
(ct-eval ctx "(defprotocol Namable (get-name [this]))")
|
||||
(ct-eval ctx "(extend-type Person Namable (get-name [this] (.-name this)))")
|
||||
(assert (= "Alice" (ct-eval ctx "(get-name (Person. \"Alice\"))")) "extend-type works"))
|
||||
(print " passed")
|
||||
|
||||
(print "37: extend-protocol...")
|
||||
(let [ctx (init)]
|
||||
(ct-eval ctx "(deftype Dog [breed])")
|
||||
(ct-eval ctx "(deftype Cat [color])")
|
||||
(ct-eval ctx "(defprotocol Animal (speak [this]))")
|
||||
(ct-eval ctx "(extend-protocol Animal
|
||||
Dog (speak [this] (str \"woof from \" (.-breed this)))
|
||||
Cat (speak [this] (str \"meow from \" (.-color this))))")
|
||||
(assert (= "woof from poodle" (ct-eval ctx "(speak (Dog. \"poodle\"))")) "dog speak")
|
||||
(assert (= "meow from black" (ct-eval ctx "(speak (Cat. \"black\"))")) "cat speak"))
|
||||
(print " passed")
|
||||
|
||||
(print "38: satisfies?...")
|
||||
(let [ctx (init)]
|
||||
(ct-eval ctx "(deftype Point [x y])")
|
||||
(ct-eval ctx "(defprotocol Locatable (location [this]))")
|
||||
(ct-eval ctx "(extend-type Point Locatable (location [this] [(.-x this) (.-y this)]))")
|
||||
(assert (= true (ct-eval ctx "(satisfies? Locatable (Point. 3 4))")) "satisfies? true")
|
||||
(assert (= false (ct-eval ctx "(satisfies? Locatable {:x 1})")) "satisfies? false"))
|
||||
(print " passed")
|
||||
|
||||
(print "39: reify...")
|
||||
(let [ctx (init)]
|
||||
(ct-eval ctx "(defprotocol Stringable (to-str [this]))")
|
||||
(assert (= "works" (ct-eval ctx "(to-str (reify Stringable (to-str [this] \"works\")))")) "reify single method"))
|
||||
(print " passed")
|
||||
|
||||
(print "\nAll Phase 12 tests passed!")
|
||||
44
test/integration/ports/phase13-test.janet
Normal file
44
test/integration/ports/phase13-test.janet
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
(use ../../../src/jolt/api)
|
||||
(use ../../../src/jolt/evaluator)
|
||||
(use ../../../src/jolt/reader)
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
|
||||
(defn load-clj [ctx filepath]
|
||||
(var s (slurp filepath))
|
||||
(while (> (length (string/trim s)) 0)
|
||||
(def [form rest] (parse-next s))
|
||||
(set s rest)
|
||||
(when (not (nil? form))
|
||||
(eval-form ctx @{} form))))
|
||||
|
||||
(print "=== Phase 13: Protocol Completion ===")
|
||||
|
||||
(print "28: reify dispatch...")
|
||||
(let [ctx (init)]
|
||||
(ct-eval ctx "(defprotocol Greeter (say-hello [this]))")
|
||||
(ct-eval ctx "(def r (reify Greeter (say-hello [this] \"hello reify\")))")
|
||||
(assert (= "hello reify" (ct-eval ctx "(say-hello r)")) "reify dispatch"))
|
||||
(print " ok")
|
||||
|
||||
(print "29: #() anon-fn reader...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 2 (ct-eval ctx "(#(inc %) 1)")) "anon fn %")
|
||||
(assert (= 3 (ct-eval ctx "(#(+ %1 %2) 1 2)")) "anon fn %1 %2")
|
||||
(assert (= [1 2 3] (ct-eval ctx "(map #(inc %) [0 1 2])")) "anon fn map"))
|
||||
(print " ok")
|
||||
|
||||
(print "30: extend-type full dispatch...")
|
||||
(let [ctx (init)]
|
||||
(ct-eval ctx "(defprotocol Greet (g [this]))")
|
||||
(ct-eval ctx "(deftype Dog [name])")
|
||||
(ct-eval ctx "(extend-type Dog Greet (g [this] (str \"woof \" (.-name this))))")
|
||||
(assert (= "woof Rex" (ct-eval ctx "(g (Dog. \"Rex\"))")) "extend-type dog"))
|
||||
(print " ok")
|
||||
|
||||
(print "31: clojure.walk loading...")
|
||||
(let [ctx (init)]
|
||||
(load-clj ctx "src/jolt/clojure/walk.clj")
|
||||
(assert (function? (ct-eval ctx "keywordize-keys")) "keywordize-keys is fn"))
|
||||
(print " ok")
|
||||
|
||||
(print "\nAll Phase 13 tests passed!")
|
||||
74
test/integration/ports/phase5-test.janet
Normal file
74
test/integration/ports/phase5-test.janet
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
# Phase 5: Multimethods + Hierarchy Tests
|
||||
(use ../../../src/jolt/api)
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
|
||||
# 22. Hierarchy
|
||||
(print "22: hierarchy...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(map? (make-hierarchy))")) "make-hierarchy returns map")
|
||||
# 2-arity derive/isa? just returns nil/false (no global hierarchy)
|
||||
(ct-eval ctx "(derive ::square ::shape)")
|
||||
(assert (= false (ct-eval ctx "(isa? ::square ::shape)")) "isa? 2-arity always false"))
|
||||
(print " passed")
|
||||
|
||||
# 23. Multimethods — basic dispatch
|
||||
(print "23: basic multimethod dispatch...")
|
||||
(let [ctx (init)]
|
||||
(ct-eval ctx "(defmulti greet (fn [x] (:lang x)))")
|
||||
(ct-eval ctx "(defmethod greet :en [_] \"hello\")")
|
||||
(ct-eval ctx "(defmethod greet :fr [_] \"bonjour\")")
|
||||
(assert (= "hello" (ct-eval ctx "(greet {:lang :en})")) "dispatch :en")
|
||||
(assert (= "bonjour" (ct-eval ctx "(greet {:lang :fr})")) "dispatch :fr")
|
||||
(assert (ct-eval ctx "(try (greet {:lang :es}) (catch Exception e true))") "missing dispatch errors"))
|
||||
(print " passed")
|
||||
|
||||
# 24. Multimethods — :default dispatch
|
||||
(print "24: :default dispatch...")
|
||||
(let [ctx (init)]
|
||||
(ct-eval ctx "(defmulti classify :type :default :unknown)")
|
||||
(ct-eval ctx "(defmethod classify :a [_] :alpha)")
|
||||
# :default :unknown renames the catch-all dispatch key; a method must be
|
||||
# registered under it (Clojure semantics).
|
||||
(ct-eval ctx "(defmethod classify :unknown [_] :unknown)")
|
||||
(assert (= :alpha (ct-eval ctx "(classify {:type :a})")) "known dispatch")
|
||||
(assert (= :unknown (ct-eval ctx "(classify {:type :z})")) "default fallback"))
|
||||
(print " passed")
|
||||
|
||||
# 25. Multimethods — hierarchy dispatch
|
||||
(print "25: hierarchy dispatch...")
|
||||
(let [ctx (init)]
|
||||
(ct-eval ctx "(def h (make-hierarchy))")
|
||||
(ct-eval ctx "(def h (derive h ::dog ::mammal))")
|
||||
(ct-eval ctx "(def h (derive h ::mammal ::animal))")
|
||||
(ct-eval ctx "(defmulti animal-sound (fn [x] x) :default :unknown :hierarchy h)")
|
||||
(ct-eval ctx "(defmethod animal-sound ::animal [_] \"rawr\")")
|
||||
(ct-eval ctx "(defmethod animal-sound ::dog [_] \"woof\")")
|
||||
# catch-all method registered under the renamed default key :unknown
|
||||
(ct-eval ctx "(defmethod animal-sound :unknown [_] :unknown)")
|
||||
(assert (= "woof" (ct-eval ctx "(animal-sound ::dog)")) "direct dispatch")
|
||||
(assert (= "rawr" (ct-eval ctx "(animal-sound ::mammal)")) "hierarchy fallback")
|
||||
(assert (= :unknown (ct-eval ctx "(animal-sound ::rock)")) "default fallback"))
|
||||
(print " passed")
|
||||
|
||||
# 26. remove-method
|
||||
(print "26: remove-method...")
|
||||
(let [ctx (init)]
|
||||
(ct-eval ctx "(defmulti rmtest :k)")
|
||||
(ct-eval ctx "(defmethod rmtest :a [_] 1)")
|
||||
(ct-eval ctx "(defmethod rmtest :b [_] 2)")
|
||||
(assert (= 1 (ct-eval ctx "(rmtest {:k :a})")) "before remove")
|
||||
(ct-eval ctx "(remove-method (var rmtest) :a)")
|
||||
(assert (ct-eval ctx "(try (rmtest {:k :a}) (catch Exception e true))") "removed method errors"))
|
||||
(print " passed")
|
||||
|
||||
# 27. remove-all-methods
|
||||
(print "27: remove-all-methods...")
|
||||
(let [ctx (init)]
|
||||
(ct-eval ctx "(defmulti alltest :k)")
|
||||
(ct-eval ctx "(defmethod alltest :a [_] 1)")
|
||||
(ct-eval ctx "(defmethod alltest :b [_] 2)")
|
||||
(ct-eval ctx "(remove-all-methods (var alltest))")
|
||||
(assert (ct-eval ctx "(try (alltest {:k :a}) (catch Exception e true))") "all methods removed errors"))
|
||||
(print " passed")
|
||||
|
||||
(print "\nAll Phase 5 tests passed!")
|
||||
82
test/integration/ports/phase6-final-test.janet
Normal file
82
test/integration/ports/phase6-final-test.janet
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
(use ../../../src/jolt/api)
|
||||
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
|
||||
(print "Phase 6: comprehensive compile-mode tests...")
|
||||
(let [ctx (init {:compile? true})]
|
||||
|
||||
(print " collections...")
|
||||
(assert (= :a (ct-eval ctx "(nth [:a :b :c :d] 0)")) "nth")
|
||||
(assert (= true (ct-eval ctx "(vector? [1 2])")) "vector?")
|
||||
(assert (= true (ct-eval ctx "(map? {:a 1})")) "map?")
|
||||
(assert (= true (ct-eval ctx "(fn? inc)")) "fn?")
|
||||
(assert (= [1 2 3 4] (ct-eval ctx "(conj [1 2 3] 4)")) "conj")
|
||||
(assert (= 1 (ct-eval ctx "(first [1 2 3])")) "first")
|
||||
(assert (= [2 3] (ct-eval ctx "(rest [1 2 3])")) "rest")
|
||||
(assert (= 1 (ct-eval ctx "(get {:a 1 :b 2} :a)")) "get map")
|
||||
(assert (= nil (ct-eval ctx "(get {:a 1} :z)")) "get missing")
|
||||
(assert (= 3 (ct-eval ctx "(count {:a 1 :b 2 :c 3})")) "count map")
|
||||
(assert (= [1 2 3] (ct-eval ctx "(into [1] [2 3])")) "into")
|
||||
|
||||
(print " core math...")
|
||||
(assert (= 3 (ct-eval ctx "(+ 1 2)")) "+")
|
||||
(assert (= 1 (ct-eval ctx "(- 3 2)")) "-")
|
||||
(assert (= 6 (ct-eval ctx "(* 2 3)")) "*")
|
||||
(assert (= 2 (ct-eval ctx "(/ 4 2)")) "/")
|
||||
(assert (= 3 (ct-eval ctx "(inc 2)")) "inc")
|
||||
(assert (= 1 (ct-eval ctx "(dec 2)")) "dec")
|
||||
(assert (= 1 (ct-eval ctx "(quot 5 3)")) "quot")
|
||||
(assert (= 2 (ct-eval ctx "(rem 5 3)")) "rem")
|
||||
(assert (= 2 (ct-eval ctx "(mod 5 3)")) "mod")
|
||||
(assert (= 3 (ct-eval ctx "(max 1 2 3)")) "max")
|
||||
(assert (= 1 (ct-eval ctx "(min 1 2 3)")) "min")
|
||||
|
||||
(print " predicates...")
|
||||
(assert (= true (ct-eval ctx "(nil? nil)")) "nil?")
|
||||
(assert (= false (ct-eval ctx "(nil? 1)")) "nil? false")
|
||||
(assert (= true (ct-eval ctx "(zero? 0)")) "zero?")
|
||||
(assert (= true (ct-eval ctx "(pos? 5)")) "pos?")
|
||||
(assert (= true (ct-eval ctx "(neg? -1)")) "neg?")
|
||||
(assert (= true (ct-eval ctx "(even? 4)")) "even?")
|
||||
(assert (= true (ct-eval ctx "(odd? 3)")) "odd?")
|
||||
(assert (= false (ct-eval ctx "(not true)")) "not")
|
||||
(assert (= true (ct-eval ctx "(some? 1)")) "some?")
|
||||
(assert (= true (ct-eval ctx "(string? \"hello\")")) "string?")
|
||||
(assert (= true (ct-eval ctx "(number? 42)")) "number?")
|
||||
(assert (= true (ct-eval ctx "(keyword? :foo)")) "keyword?")
|
||||
(assert (= true (ct-eval ctx "(= 1 1)")) "=")
|
||||
(assert (= true (ct-eval ctx "(< 1 2)")) "<")
|
||||
(assert (= true (ct-eval ctx "(> 2 1)")) ">")
|
||||
(assert (= true (ct-eval ctx "(<= 1 1)")) "<=")
|
||||
(assert (= true (ct-eval ctx "(>= 2 2)")) ">=")
|
||||
|
||||
(print " seq operations...")
|
||||
(assert (= [2 3 4] (ct-eval ctx "(map inc [1 2 3])")) "map")
|
||||
(assert (= [2 4] (ct-eval ctx "(filter even? [1 2 3 4])")) "filter")
|
||||
(assert (= [1 3] (ct-eval ctx "(remove even? [1 2 3 4])")) "remove")
|
||||
(assert (= 6 (ct-eval ctx "(reduce + [1 2 3])")) "reduce")
|
||||
(assert (= [1 2 3] (ct-eval ctx "(take 3 [1 2 3 4 5])")) "take")
|
||||
(assert (= [4 5] (ct-eval ctx "(drop 3 [1 2 3 4 5])")) "drop")
|
||||
|
||||
(print " special forms...")
|
||||
(assert (= 30 (ct-eval ctx "(let [x 10 y 20] (+ x y))")) "let")
|
||||
(assert (= :a (ct-eval ctx "(if true :a :b)")) "if true")
|
||||
(assert (= :b (ct-eval ctx "(if false :a :b)")) "if false")
|
||||
(assert (= 3 (ct-eval ctx "(loop [x 0] (if (< x 3) (recur (inc x)) x))")) "loop")
|
||||
(assert (= "caught" (ct-eval ctx "(try (throw 42) (catch Exception e \"caught\"))")) "try")
|
||||
(assert (= 42 (ct-eval ctx "'42")) "quote literal")
|
||||
|
||||
(print " macros...")
|
||||
(ct-eval ctx "(defn add [a b] (+ a b))")
|
||||
(assert (= 7 (ct-eval ctx "(add 3 4)")) "defn")
|
||||
(assert (= 42 (ct-eval ctx "(when true 42)")) "when true")
|
||||
(assert (= 3 (ct-eval ctx "(and 1 2 3)")) "and")
|
||||
(assert (= 1 (ct-eval ctx "(or 1 2 3)")) "or")
|
||||
(assert (= 49 (ct-eval ctx "((fn [x] (* x x)) 7)")) "fn macro")
|
||||
(assert (= 2 (ct-eval ctx "(if-let [x 1] (inc x) 0)")) "if-let")
|
||||
|
||||
(print " complex...")
|
||||
(assert (= 6 (ct-eval ctx "(let [f (fn [n] (loop [i 0 acc 0] (if (< i n) (recur (inc i) (+ acc i)) acc)))] (f 4))")) "nested")
|
||||
(assert (= 15 (ct-eval ctx "(reduce + (map inc [0 1 2 3 4]))")) "reduce+map"))
|
||||
|
||||
(print "\nAll Phase 6 tests passed!")
|
||||
36
test/integration/ports/phase6-test.janet
Normal file
36
test/integration/ports/phase6-test.janet
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
# Phase 6: Reader Extensions Tests
|
||||
(use ../../../src/jolt/api)
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
|
||||
(print "28: #inst tagged literal...")
|
||||
(let [ctx (init)]
|
||||
(let [val (ct-eval ctx "#inst \"2024-01-15\"")]
|
||||
(assert (= "2024-01-15" val) "#inst string"))
|
||||
(let [val (ct-eval ctx "#inst \"2024-01-15T10:30:00Z\"")]
|
||||
(assert (= "2024-01-15T10:30:00Z" val) "#inst timestamp")))
|
||||
(print " passed")
|
||||
|
||||
(print "29: #uuid tagged literal...")
|
||||
(let [ctx (init)]
|
||||
(let [val (ct-eval ctx "#uuid \"550e8400-e29b-41d4-a716-446655440000\"")]
|
||||
(assert (= "550e8400-e29b-41d4-a716-446655440000" val) "#uuid string")))
|
||||
(print " passed")
|
||||
|
||||
(print "30: #? reader conditionals...")
|
||||
(let [ctx (init)]
|
||||
(assert (= :yes (ct-eval ctx "#?(:clj :yes :cljs :no)")) "#? selects :clj")
|
||||
(assert (= :yes (ct-eval ctx "#?(:cljs :no :default :yes)")) "#? :default fallback")
|
||||
(assert (= nil (ct-eval ctx "#?(:cljs :no)")) "#? nil on no match"))
|
||||
(print " passed")
|
||||
|
||||
(print "31: #?@ splicing...")
|
||||
(let [ctx (init)]
|
||||
(assert (= [1 2 3] (ct-eval ctx "[#?@(:clj [1 2 3] :cljs [4 5 6])]"))
|
||||
"#?@ splices :clj")
|
||||
(assert (= [99] (ct-eval ctx "[#?@(:cljs [1] :default [99])]"))
|
||||
"#?@ :default fallback")
|
||||
(assert (= [] (ct-eval ctx "[#?@(:cljs [1 2])]"))
|
||||
"#?@ nothing on no match"))
|
||||
(print " passed")
|
||||
|
||||
(print "\nAll Phase 6 tests passed!")
|
||||
25
test/integration/ports/phase7-test.janet
Normal file
25
test/integration/ports/phase7-test.janet
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# Phase 7: LazySeq + PersistentHashSet completion
|
||||
(use ../../../src/jolt/api)
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
|
||||
(print "32: lazy-seq...")
|
||||
(let [ctx (init)]
|
||||
(let [ls (ct-eval ctx "(lazy-seq (cons 1 (lazy-seq (cons 2 nil))))")]
|
||||
(assert (not (nil? ls)) "lazy-seq returns non-nil")
|
||||
(assert (= 1 (ct-eval ctx "(first (lazy-seq (cons 1 nil)))")) "first of lazy"))
|
||||
(assert (= true (ct-eval ctx "(= [1 2 3] (seq (lazy-seq [1 2 3])))")) "seq forces lazy")
|
||||
(eval-string ctx "(def counter (atom 0))")
|
||||
(def val (ct-eval ctx "(let [ls (lazy-seq (do (swap! counter inc) [1 2 3]))] (seq ls) (seq ls) @counter)"))
|
||||
(assert (= 1 val) "realized once"))
|
||||
(print " passed")
|
||||
|
||||
(print "33: PersistentHashSet...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(set? #{1 2 3})")) "set? true")
|
||||
(assert (= false (ct-eval ctx "(set? [1 2 3])")) "set? false")
|
||||
(assert (= 4 (ct-eval ctx "(count (conj #{1 2 3} 4))")) "conj add")
|
||||
(assert (= 2 (ct-eval ctx "(count (disj #{1 2 3} 3))")) "disj")
|
||||
(assert (= 3 (ct-eval ctx "(count #{1 2 3})")) "count")
|
||||
(assert (= true (ct-eval ctx "(= #{1 2 3} #{3 2 1})")) "= order-independent"))
|
||||
|
||||
(print "\nAll Phase 7 tests passed!")
|
||||
44
test/integration/ports/phase8-test.janet
Normal file
44
test/integration/ports/phase8-test.janet
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
# Phase 8: Protocol System Tests
|
||||
(use ../../../src/jolt/api)
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
|
||||
(print "35: defprotocol...")
|
||||
(let [ctx (init)]
|
||||
(ct-eval ctx "(defprotocol Greet (greet [this]))")
|
||||
(let [p (ct-eval ctx "Greet")]
|
||||
(assert (not (nil? p)) "protocol var exists")
|
||||
(assert (= :jolt/protocol (get p :jolt/type)) "protocol type tag")
|
||||
(assert (get (get p :methods) :greet) "protocol has greet method"))
|
||||
(assert (or (function? (ct-eval ctx "greet")) (cfunction? (ct-eval ctx "greet"))) "method fn exists"))
|
||||
(print " passed")
|
||||
|
||||
(print "36: extend-type...")
|
||||
(let [ctx (init)]
|
||||
(ct-eval ctx "(deftype Person [name])")
|
||||
(ct-eval ctx "(defprotocol Namable (get-name [this]))")
|
||||
(ct-eval ctx "(extend-type Person Namable (get-name [this] (.-name this)))")
|
||||
(assert (= "Alice" (ct-eval ctx "(get-name (Person. \"Alice\"))")) "extend-type works"))
|
||||
(print " passed")
|
||||
|
||||
(print "37: extend-protocol...")
|
||||
(let [ctx (init)]
|
||||
(ct-eval ctx "(deftype Dog [breed])")
|
||||
(ct-eval ctx "(deftype Cat [color])")
|
||||
(ct-eval ctx "(defprotocol Animal (speak [this]))")
|
||||
(ct-eval ctx "(extend-protocol Animal
|
||||
Dog (speak [this] (str \"woof from \" (.-breed this)))
|
||||
Cat (speak [this] (str \"meow from \" (.-color this))))")
|
||||
(assert (= "woof from poodle" (ct-eval ctx "(speak (Dog. \"poodle\"))")) "dog speak")
|
||||
(assert (= "meow from black" (ct-eval ctx "(speak (Cat. \"black\"))")) "cat speak"))
|
||||
(print " passed")
|
||||
|
||||
(print "38: satisfies?...")
|
||||
(let [ctx (init)]
|
||||
(ct-eval ctx "(deftype Point [x y])")
|
||||
(ct-eval ctx "(defprotocol Locatable (location [this]))")
|
||||
(ct-eval ctx "(extend-type Point Locatable (location [this] [(.-x this) (.-y this)]))")
|
||||
(assert (= true (ct-eval ctx "(satisfies? Locatable (Point. 3 4))")) "satisfies? true")
|
||||
(assert (= false (ct-eval ctx "(satisfies? Locatable {:x 1})")) "satisfies? false"))
|
||||
(print " passed")
|
||||
|
||||
(print "\nAll Phase 8 tests passed!")
|
||||
112
test/integration/sci-bootstrap-test.janet
Normal file
112
test/integration/sci-bootstrap-test.janet
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
(use ../../src/jolt/evaluator)
|
||||
(use ../../src/jolt/types)
|
||||
(use ../../src/jolt/reader)
|
||||
(use ../../src/jolt/api)
|
||||
|
||||
(def ctx (init))
|
||||
|
||||
(printf "Loading SCI stubs...\n")
|
||||
(defn load-stubs [ctx filepath]
|
||||
(var s (slurp filepath))
|
||||
(var count 0)
|
||||
(while (> (length (string/trim s)) 0)
|
||||
(def [form rest] (parse-next s))
|
||||
(set s rest)
|
||||
(++ count)
|
||||
(when (not (nil? form))
|
||||
(eval-form ctx @{} form)))
|
||||
(printf " Loaded %d stub forms\n" count))
|
||||
|
||||
(load-stubs ctx "src/jolt/clojure/sci/lang_stubs.clj")
|
||||
(load-stubs ctx "src/jolt/clojure/sci/io_stubs.clj")
|
||||
(load-stubs ctx "src/jolt/clojure/sci/host_stubs.clj")
|
||||
|
||||
# namespaces.cljc copies vars out of Jolt's own clojure.string/set/walk/edn, so
|
||||
# make sure those are loaded before it runs.
|
||||
(each lib ["clojure.string" "clojure.set" "clojure.walk" "clojure.edn"]
|
||||
(protect (eval-form ctx @{} (first (parse-next (string "(require '[" lib "])"))))))
|
||||
|
||||
(defn load-file [ctx path]
|
||||
(var s (slurp path))
|
||||
(var count 0)
|
||||
(var ok 0)
|
||||
(var fail 0)
|
||||
(var failures @[])
|
||||
(while (> (length (string/trim s)) 0)
|
||||
(def [form rest] (parse-next s))
|
||||
(set s rest)
|
||||
(++ count)
|
||||
(if (not (nil? form))
|
||||
(do
|
||||
(printf "eval form %d..." count)
|
||||
(flush)
|
||||
(if (try
|
||||
(do (eval-form ctx @{} form) true)
|
||||
([err fib]
|
||||
(printf " FAIL: %q\n" err)
|
||||
(when (os/getenv "SCI_TRACE") (debug/stacktrace fib ""))
|
||||
(array/push failures {:form-number count :error (string err) :form (string form)})
|
||||
false))
|
||||
(do
|
||||
(printf " OK\n")
|
||||
(++ ok))
|
||||
(++ fail)))))
|
||||
{:ok ok :fail fail :total count :failures failures})
|
||||
|
||||
(def sci-base "vendor/sci/src/sci")
|
||||
|
||||
(def load-order @[
|
||||
["impl/macros.cljc" nil]
|
||||
["impl/protocols.cljc" nil]
|
||||
["impl/types.cljc" nil]
|
||||
["impl/unrestrict.cljc" nil]
|
||||
["impl/vars.cljc" nil]
|
||||
["lang.cljc" nil]
|
||||
["impl/utils.cljc" nil]
|
||||
["ctx_store.cljc" nil]
|
||||
["impl/deftype.cljc" nil]
|
||||
["impl/records.cljc" nil]
|
||||
["impl/core_protocols.cljc" nil]
|
||||
["impl/hierarchies.cljc" nil]
|
||||
# pure-Clojure macro/expander modules (loadable from SCI's real source)
|
||||
["impl/destructure.cljc" nil]
|
||||
["impl/doseq_macro.cljc" nil]
|
||||
["impl/for_macro.cljc" nil]
|
||||
["impl/fns.cljc" nil]
|
||||
["impl/multimethods.cljc" nil]
|
||||
["impl/namespaces.cljc" nil]
|
||||
["core.cljc" nil]
|
||||
])
|
||||
|
||||
(var total-ok 0)
|
||||
(var total-fail 0)
|
||||
(var all-failures @[])
|
||||
|
||||
(each [file expected-ns] load-order
|
||||
(def path (string sci-base "/" file))
|
||||
(printf "\n=== Loading %s ===\n" file)
|
||||
(def result (load-file ctx path))
|
||||
(printf " Result: %d ok, %d fail, %d total\n" (result :ok) (result :fail) (result :total))
|
||||
(+= total-ok (result :ok))
|
||||
(+= total-fail (result :fail))
|
||||
(each f (result :failures)
|
||||
(array/push all-failures {:file file :form-number (f :form-number) :error (f :error) :form (f :form)})))
|
||||
|
||||
(printf "\n==============================\n")
|
||||
(printf "TOTAL: %d ok, %d fail, %d total\n" total-ok total-fail (+ total-ok total-fail))
|
||||
(printf "==============================\n")
|
||||
|
||||
(printf "\ncurrent ns: %s\n" (ctx-current-ns ctx))
|
||||
(printf "sci.core exists: %q\n" (not (nil? (ctx-find-ns ctx "sci.core"))))
|
||||
(printf "total namespaces: %d\n" (length (keys ((ctx :env) :namespaces))))
|
||||
|
||||
(when (> (length all-failures) 0)
|
||||
(printf "\n=== FAILURES ===\n")
|
||||
(each f all-failures
|
||||
(printf "[%s:%d] %s\n" (f :file) (f :form-number) (f :error))
|
||||
(printf " form: %s\n" (f :form))))
|
||||
|
||||
# Regression guard: every form in the loaded SCI modules must evaluate cleanly.
|
||||
(assert (= 0 total-fail)
|
||||
(string total-fail " SCI form(s) failed to load (see FAILURES above)"))
|
||||
(print "\nAll SCI bootstrap forms loaded successfully.")
|
||||
95
test/integration/sci-runtime-test.janet
Normal file
95
test/integration/sci-runtime-test.janet
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
(use ../../src/jolt/evaluator)
|
||||
(use ../../src/jolt/types)
|
||||
(use ../../src/jolt/reader)
|
||||
(use ../../src/jolt/api)
|
||||
|
||||
(defn- load-stubs [ctx filepath]
|
||||
(var s (slurp filepath))
|
||||
(while (> (length (string/trim s)) 0)
|
||||
(def [form rest] (parse-next s))
|
||||
(set s rest)
|
||||
(when (not (nil? form))
|
||||
(protect (eval-form ctx @{} form)))))
|
||||
|
||||
(defn- load-file [ctx path]
|
||||
(var s (slurp path))
|
||||
(while (> (length (string/trim s)) 0)
|
||||
(def [form rest] (parse-next s))
|
||||
(set s rest)
|
||||
(when (not (nil? form))
|
||||
# Tolerant: SCI's clojure.core registration maps reference the full
|
||||
# clojure.core surface (redundant for Jolt's native core); skip forms
|
||||
# that don't resolve rather than aborting the bootstrap.
|
||||
(protect (eval-form ctx @{} form)))))
|
||||
|
||||
# Run from project root so paths resolve
|
||||
(def root (if (has-value? (dyn :syspath) 0) (first (dyn :syspath)) "."))
|
||||
|
||||
(def ctx (init))
|
||||
|
||||
(load-stubs ctx (string root "/src/jolt/clojure/sci/lang_stubs.clj"))
|
||||
(load-stubs ctx (string root "/src/jolt/clojure/sci/io_stubs.clj"))
|
||||
|
||||
(def sci-base (string root "/vendor/sci/src/sci"))
|
||||
(each file ["impl/macros.cljc" "impl/protocols.cljc" "impl/types.cljc"
|
||||
"impl/unrestrict.cljc" "impl/vars.cljc" "lang.cljc"
|
||||
"impl/utils.cljc" "ctx_store.cljc" "impl/deftype.cljc"
|
||||
"impl/records.cljc" "impl/core_protocols.cljc" "impl/hierarchies.cljc"
|
||||
"impl/namespaces.cljc" "core.cljc"]
|
||||
(load-file ctx (string sci-base "/" file)))
|
||||
|
||||
# ── Verify sci.lang NS and Type ─────────────────────────────────
|
||||
(assert (not (nil? (ctx-find-ns ctx "sci.lang")))
|
||||
"sci.lang namespace exists")
|
||||
(assert (not (nil? (ctx-find-ns ctx "sci.core")))
|
||||
"sci.core namespace exists")
|
||||
|
||||
# sci.lang has Type constructor
|
||||
(def sci-lang (ctx-find-ns ctx "sci.lang"))
|
||||
(def type-var (ns-find sci-lang "Type"))
|
||||
(assert (not (nil? type-var)) "sci.lang/Type var exists")
|
||||
(def ->Type (ns-find sci-lang "->Type"))
|
||||
(assert (not (nil? ->Type)) "sci.lang/->Type constructor exists")
|
||||
|
||||
# Instantiate a Type and check field access
|
||||
(def type-inst ((var-get type-var) {:sci.impl/type-name "user.Foo"}))
|
||||
(assert (table? type-inst) "Type instance is a table")
|
||||
(assert (not (nil? (get type-inst :jolt/deftype))) "Type instance has deftype tag")
|
||||
(assert (= "user.Foo" (get (get type-inst :data) :sci.impl/type-name)) "Type field access via data")
|
||||
|
||||
# ── Verify sci.lang/Var ─────────────────────────────────────────
|
||||
(def var-ctor-var (ns-find sci-lang "Var"))
|
||||
(assert (not (nil? var-ctor-var)) "sci.lang/Var constructor exists")
|
||||
|
||||
(def test-var ((var-get var-ctor-var) 42 'my-var nil nil nil nil nil))
|
||||
(assert (table? test-var) "Var instance is a table")
|
||||
(assert (= 42 (get test-var :root)) "Var deref")
|
||||
|
||||
# var? check — SCI Var is not a Jolt var but is a table with proper fields
|
||||
(assert (not (nil? test-var)) "Var instance is not nil")
|
||||
|
||||
# ── Verify sci.impl.types/IBox protocol ─────────────────────────
|
||||
(def types-ns (ctx-find-ns ctx "sci.impl.types"))
|
||||
(def vars-ns (ctx-find-ns ctx "sci.impl.vars"))
|
||||
(assert (not (nil? types-ns)) "sci.impl.types namespace exists")
|
||||
(assert (not (nil? vars-ns)) "sci.impl.vars namespace exists")
|
||||
|
||||
(def ibox-getVal (ns-find types-ns "getVal"))
|
||||
(def ibox-setVal (ns-find types-ns "setVal"))
|
||||
(assert (not (nil? ibox-getVal)) "sci.impl.types/getVal exists")
|
||||
(assert (not (nil? ibox-setVal)) "sci.impl.types/setVal exists")
|
||||
|
||||
# Test IBox setVal/getVal exist but skip dispatch (SCI protocol machinery not fully booted)
|
||||
(assert (function? (var-get ibox-setVal)) "sci.impl.types/setVal is callable")
|
||||
(assert (function? (var-get ibox-getVal)) "sci.impl.types/getVal is callable")
|
||||
|
||||
# ── Verify sci.impl.vars/IVar protocol methods exist ─────────────
|
||||
(def ivar-toSymbol (ns-find vars-ns "toSymbol"))
|
||||
(def ivar-hasRoot (ns-find vars-ns "hasRoot"))
|
||||
(assert (not (nil? ivar-toSymbol)) "sci.impl.vars/toSymbol exists")
|
||||
(assert (not (nil? ivar-hasRoot)) "sci.impl.vars/hasRoot exists")
|
||||
|
||||
# ── Verify SCI eval function exists ─────────────────────────────
|
||||
(def sci-core (ctx-find-ns ctx "sci.core"))
|
||||
(assert (not (nil? sci-core)) "sci.core namespace exists")
|
||||
(printf "\nAll SCI runtime tests passed!\n")
|
||||
212
test/integration/systematic-coverage-test.janet
Normal file
212
test/integration/systematic-coverage-test.janet
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
# Systematic coverage tests for Clojure language features
|
||||
(use ../../src/jolt/api)
|
||||
(defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s)))
|
||||
|
||||
(print "Systematic Coverage Tests")
|
||||
|
||||
# --- Type Predicates ---
|
||||
(print "1: type predicates...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(integer? 0)")) "integer? 0")
|
||||
(assert (= true (ct-eval ctx "(integer? 1)")) "integer? 1")
|
||||
(assert (= true (ct-eval ctx "(integer? -5)")) "integer? negative")
|
||||
(assert (= false (ct-eval ctx "(integer? 1.5)")) "integer? float")
|
||||
(assert (= false (ct-eval ctx "(integer? nil)")) "integer? nil")
|
||||
(assert (= false (ct-eval ctx "(integer? \"abc\")")) "integer? string")
|
||||
(assert (= true (ct-eval ctx "(boolean? true)")) "boolean? true")
|
||||
(assert (= true (ct-eval ctx "(boolean? false)")) "boolean? false")
|
||||
(assert (= false (ct-eval ctx "(boolean? 1)")) "boolean? falsy")
|
||||
(assert (= false (ct-eval ctx "(boolean? nil)")) "boolean? nil")
|
||||
(assert (= true (ct-eval ctx "(nil? nil)")) "nil? nil")
|
||||
(assert (= false (ct-eval ctx "(nil? false)")) "nil? false")
|
||||
(assert (= false (ct-eval ctx "(nil? 0)")) "nil? 0")
|
||||
(assert (= false (ct-eval ctx "(nil? [])")) "nil? empty vec")
|
||||
(assert (= false (ct-eval ctx "(some? nil)")) "some? nil")
|
||||
(assert (= true (ct-eval ctx "(some? false)")) "some? false")
|
||||
(assert (= true (ct-eval ctx "(some? 0)")) "some? 0")
|
||||
(assert (= true (ct-eval ctx "(some? [])")) "some? empty vec")
|
||||
(assert (= true (ct-eval ctx "(string? \"hello\")")) "string?")
|
||||
(assert (= false (ct-eval ctx "(string? 42)")) "string? false")
|
||||
(assert (= true (ct-eval ctx "(string? \"\")")) "string? empty")
|
||||
(assert (= true (ct-eval ctx "(number? 42)")) "number? int")
|
||||
(assert (= true (ct-eval ctx "(number? 3.14)")) "number? float")
|
||||
(assert (= false (ct-eval ctx "(number? \"42\")")) "number? string")
|
||||
(assert (= true (ct-eval ctx "(fn? inc)")) "fn? builtin")
|
||||
(assert (= false (ct-eval ctx "(fn? 42)")) "fn? false")
|
||||
(assert (= true (ct-eval ctx "(keyword? :foo)")) "keyword?")
|
||||
(assert (= false (ct-eval ctx "(keyword? \"foo\")")) "keyword? false")
|
||||
(assert (= true (ct-eval ctx "(symbol? 'abc)")) "symbol?")
|
||||
(assert (= false (ct-eval ctx "(symbol? :abc)")) "symbol? false")
|
||||
(assert (= true (ct-eval ctx "(map? {:a 1})")) "map?")
|
||||
(assert (= false (ct-eval ctx "(map? [1 2])")) "map? false")
|
||||
(assert (= true (ct-eval ctx "(set? #{1 2})")) "set?")
|
||||
(assert (= false (ct-eval ctx "(set? [1 2])")) "set? false")
|
||||
(assert (= true (ct-eval ctx "(seq? '(1 2))")) "seq? list")
|
||||
(assert (= true (ct-eval ctx "(seq? [1 2])")) "seq? vector")
|
||||
(assert (= true (ct-eval ctx "(coll? [1 2])")) "coll? vec")
|
||||
(assert (= true (ct-eval ctx "(coll? '(1 2))")) "coll? list")
|
||||
(assert (= true (ct-eval ctx "(coll? {})")) "coll? map")
|
||||
(assert (= true (ct-eval ctx "(true? true)")) "true? true")
|
||||
(assert (= false (ct-eval ctx "(true? 1)")) "true? 1")
|
||||
(assert (= true (ct-eval ctx "(false? false)")) "false? false")
|
||||
(assert (= false (ct-eval ctx "(false? nil)")) "false? nil")
|
||||
(assert (= true (ct-eval ctx "(identical? 42 42)")) "identical? same value"))
|
||||
(print " ok")
|
||||
|
||||
# --- Number Predicates ---
|
||||
(print "2: number predicates...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(zero? 0)")) "zero? 0")
|
||||
(assert (= false (ct-eval ctx "(zero? 1)")) "zero? 1")
|
||||
(assert (= false (ct-eval ctx "(zero? nil)")) "zero? nil")
|
||||
(assert (= true (ct-eval ctx "(pos? 1)")) "pos?")
|
||||
(assert (= false (ct-eval ctx "(pos? 0)")) "pos? 0")
|
||||
(assert (= false (ct-eval ctx "(pos? -1)")) "pos? -1")
|
||||
(assert (= true (ct-eval ctx "(neg? -1)")) "neg?")
|
||||
(assert (= false (ct-eval ctx "(neg? 0)")) "neg? 0")
|
||||
(assert (= false (ct-eval ctx "(neg? 1)")) "neg? 1")
|
||||
(assert (= true (ct-eval ctx "(even? 0)")) "even? 0")
|
||||
(assert (= true (ct-eval ctx "(even? 2)")) "even? 2")
|
||||
(assert (= false (ct-eval ctx "(even? 1)")) "even? 1")
|
||||
(assert (= true (ct-eval ctx "(odd? 1)")) "odd? 1")
|
||||
(assert (= true (ct-eval ctx "(odd? 3)")) "odd? 3")
|
||||
(assert (= false (ct-eval ctx "(odd? 2)")) "odd? 2"))
|
||||
(print " ok")
|
||||
|
||||
# --- Math ---
|
||||
(print "3: math operations...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 0 (ct-eval ctx "(+)")) "+ 0 args")
|
||||
(assert (= 5 (ct-eval ctx "(+ 2 3)")) "+ 2 args")
|
||||
(assert (= 10 (ct-eval ctx "(+ 1 2 3 4)")) "+ varargs")
|
||||
(assert (= -5 (ct-eval ctx "(- 5)")) "- unary")
|
||||
(assert (= 2 (ct-eval ctx "(- 5 3)")) "- binary")
|
||||
(assert (= 1 (ct-eval ctx "(*)")) "* 0 args")
|
||||
(assert (= 6 (ct-eval ctx "(* 2 3)")) "*")
|
||||
(assert (= 0.5 (ct-eval ctx "(/ 2)")) "/ unary reciprocal")
|
||||
(assert (= 2 (ct-eval ctx "(/ 4 2)")) "/ binary")
|
||||
(assert (= 2 (ct-eval ctx "(quot 5 2)")) "quot")
|
||||
(assert (= 1 (ct-eval ctx "(rem 5 2)")) "rem")
|
||||
(assert (= 1 (ct-eval ctx "(mod 5 2)")) "mod")
|
||||
(assert (= 43 (ct-eval ctx "(inc 42)")) "inc")
|
||||
(assert (= 41 (ct-eval ctx "(dec 42)")) "dec")
|
||||
(assert (= 3 (ct-eval ctx "(max 1 2 3)")) "max")
|
||||
(assert (= 1 (ct-eval ctx "(min 1 2 3)")) "min")
|
||||
(assert (= 5 (ct-eval ctx "(abs -5)")) "abs negative")
|
||||
(assert (= 5 (ct-eval ctx "(abs 5)")) "abs positive")
|
||||
(assert (= 0 (ct-eval ctx "(abs 0)")) "abs 0")
|
||||
(assert (= 3.14 (ct-eval ctx "(abs -3.14)")) "abs float")
|
||||
(assert (= true (ct-eval ctx "(< (rand) 1)")) "rand < 1")
|
||||
(assert (= true (ct-eval ctx "(number? (rand-int 10))")) "rand-int type"))
|
||||
(print " ok")
|
||||
|
||||
# --- Comparison ---
|
||||
(print "4: comparison...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(= 1 1)")) "= same")
|
||||
(assert (= true (ct-eval ctx "(= 1 1 1)")) "= multi same")
|
||||
(assert (= false (ct-eval ctx "(= 1 2)")) "= different")
|
||||
(assert (= true (ct-eval ctx "(not= 1 2)")) "not= different")
|
||||
(assert (= false (ct-eval ctx "(not= 1 1)")) "not= same")
|
||||
(assert (= true (ct-eval ctx "(< 1 2)")) "<")
|
||||
(assert (= false (ct-eval ctx "(< 2 1)")) "< false")
|
||||
(assert (= true (ct-eval ctx "(> 2 1)")) ">")
|
||||
(assert (= true (ct-eval ctx "(<= 1 1)")) "<=")
|
||||
(assert (= true (ct-eval ctx "(>= 2 2)")) ">="))
|
||||
(print " ok")
|
||||
|
||||
# --- Boolean logic ---
|
||||
(print "5: boolean logic...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(and)")) "and empty")
|
||||
(assert (= true (ct-eval ctx "(and true)")) "and true")
|
||||
(assert (= nil (ct-eval ctx "(and nil)")) "and nil")
|
||||
(assert (= false (ct-eval ctx "(and false)")) "and false")
|
||||
(assert (= 3 (ct-eval ctx "(and 1 2 3)")) "and last")
|
||||
(assert (= nil (ct-eval ctx "(and 1 nil 3)")) "and short-circuit")
|
||||
(assert (= nil (ct-eval ctx "(or)")) "or empty")
|
||||
(assert (= true (ct-eval ctx "(or true)")) "or true")
|
||||
(assert (= nil (ct-eval ctx "(or nil)")) "or nil")
|
||||
(assert (= false (ct-eval ctx "(or false)")) "or false")
|
||||
(assert (= 1 (ct-eval ctx "(or nil false 1 2)")) "or first truthy")
|
||||
(assert (= false (ct-eval ctx "(or nil false)")) "or all falsy")
|
||||
(assert (= false (ct-eval ctx "(not true)")) "not true")
|
||||
(assert (= true (ct-eval ctx "(not nil)")) "not nil")
|
||||
(assert (= true (ct-eval ctx "(not false)")) "not false"))
|
||||
(print " ok")
|
||||
|
||||
# --- Collections ---
|
||||
(print "6: collections...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(empty? nil)")) "empty? nil")
|
||||
(assert (= true (ct-eval ctx "(empty? [])")) "empty? []")
|
||||
(assert (= true (ct-eval ctx "(empty? ())")) "empty? ()")
|
||||
(assert (= true (ct-eval ctx "(empty? {})")) "empty? {}")
|
||||
(assert (= true (ct-eval ctx "(empty? #{})")) "empty? #{}")
|
||||
(assert (= true (ct-eval ctx "(empty? \"\")")) "empty? empty string")
|
||||
(assert (= false (ct-eval ctx "(empty? [1])")) "empty? non-empty")
|
||||
(assert (= true (ct-eval ctx "(every? even? [2 4 6])")) "every? true")
|
||||
(assert (= false (ct-eval ctx "(every? even? [2 3 4])")) "every? false")
|
||||
(assert (= 3 (ct-eval ctx "(count [1 2 3])")) "count vector")
|
||||
(assert (= 2 (ct-eval ctx "(count {:a 1 :b 2})")) "count map")
|
||||
(assert (= 3 (ct-eval ctx "(count #{1 2 3})")) "count set")
|
||||
(assert (= 3 (ct-eval ctx "(count \"abc\")")) "count string"))
|
||||
(print " ok")
|
||||
|
||||
# --- Sequence Operations ---
|
||||
(print "7: sequence operations...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 1 (ct-eval ctx "(first [1 2 3])")) "first")
|
||||
(assert (= nil (ct-eval ctx "(first [])")) "first empty")
|
||||
(assert (= nil (ct-eval ctx "(first nil)")) "first nil")
|
||||
(assert (= :a (ct-eval ctx "(nth [:a :b :c] 0)")) "nth 0")
|
||||
(assert (= :c (ct-eval ctx "(nth [:a :b :c] 2)")) "nth 2")
|
||||
(assert (= :d (ct-eval ctx "(nth [:a :b :c] 3 :d)")) "nth default")
|
||||
(assert (= nil (ct-eval ctx "(seq [])")) "seq empty -> nil")
|
||||
(assert (= nil (ct-eval ctx "(seq nil)")) "seq nil -> nil")
|
||||
(assert (= true (ct-eval ctx "(= [2 3 4] (map inc [1 2 3]))")) "map")
|
||||
(assert (= true (ct-eval ctx "(= [2 4] (filter even? [1 2 3 4]))")) "filter")
|
||||
(assert (= 6 (ct-eval ctx "(reduce + [1 2 3])")) "reduce")
|
||||
(assert (= 10 (ct-eval ctx "(reduce + 4 [1 2 3])")) "reduce init")
|
||||
(assert (= true (ct-eval ctx "(= [1 2] (take 2 [1 2 3 4]))")) "take")
|
||||
(assert (= true (ct-eval ctx "(= [3 4] (drop 2 [1 2 3 4]))")) "drop")
|
||||
(assert (= true (ct-eval ctx "(= [3 2 1] (reverse [1 2 3]))")) "reverse")
|
||||
(assert (= true (ct-eval ctx "(= 3 (count (distinct [1 1 2 2 3 3])))")) "distinct"))
|
||||
(print " ok")
|
||||
|
||||
# --- Collections: conj, assoc, dissoc, get ---
|
||||
(print "8: collection mutation...")
|
||||
(let [ctx (init)]
|
||||
(assert (= true (ct-eval ctx "(= [1 2 3] (conj [1 2] 3))")) "conj vector")
|
||||
(assert (= true (ct-eval ctx "(= (quote (0 1 2)) (conj (quote (1 2)) 0))")) "conj list prepend")
|
||||
(assert (= true (ct-eval ctx "(= {:a 1 :b 2} (assoc {:a 1} :b 2))")) "assoc")
|
||||
(assert (= true (ct-eval ctx "(= {:a 1} (dissoc {:a 1 :b 2} :b))")) "dissoc")
|
||||
(assert (= 1 (ct-eval ctx "(get {:a 1} :a)")) "get")
|
||||
(assert (= nil (ct-eval ctx "(get {:a 1} :z)")) "get missing")
|
||||
(assert (= :d (ct-eval ctx "(get {:a 1} :z :d)")) "get default")
|
||||
(assert (= true (ct-eval ctx "(contains? {:a 1} :a)")) "contains? map")
|
||||
(assert (= false (ct-eval ctx "(contains? {:a 1} :z)")) "contains? missing")
|
||||
(assert (= true (ct-eval ctx "(contains? [5 6 7] 1)")) "contains? vector")
|
||||
(assert (= false (ct-eval ctx "(contains? [5 6 7] 3)")) "contains? vector oob"))
|
||||
(print " ok")
|
||||
|
||||
# --- Higher-order functions ---
|
||||
(print "9: higher-order functions...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 3 (ct-eval ctx "((comp inc inc) 1)")) "comp")
|
||||
(assert (= 42 (ct-eval ctx "(identity 42)")) "identity")
|
||||
(assert (= 99 (ct-eval ctx "((constantly 99) :anything)")) "constantly")
|
||||
(assert (= true (ct-eval ctx "(= 10 ((partial + 3 7)))")) "partial")
|
||||
(assert (= true (ct-eval ctx "((every-pred even? pos?) 4)")) "every-pred true")
|
||||
(assert (= false (ct-eval ctx "((every-pred even? pos?) -4)")) "every-pred false")
|
||||
(assert (= false (ct-eval ctx "((complement even?) 2)")) "complement"))
|
||||
(print " ok")
|
||||
|
||||
# --- Destructuring ---
|
||||
(print "10: destructuring...")
|
||||
(let [ctx (init)]
|
||||
(assert (= 1 (ct-eval ctx "(let [[x] [1 2 3]] x)")) "seq destructure first")
|
||||
(assert (= 2 (ct-eval ctx "(let [[_ y] [1 2 3]] y)")) "seq destructure second"))
|
||||
(print " ok")
|
||||
|
||||
(print "\nAll Systematic Coverage tests passed!")
|
||||
Loading…
Add table
Add a link
Reference in a new issue