From 16428179faea149d553a4e6d7e30818cdf776d02 Mon Sep 17 00:00:00 2001 From: Yogthos Date: Fri, 5 Jun 2026 00:00:16 -0400 Subject: [PATCH] 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. --- .beads/interactions.jsonl | 1 + README.md | 20 ++++- test/{ => integration}/api-test.janet | 4 +- test/{ => integration}/bootstrap-test.janet | 8 +- .../{ => integration}/clojure-atom-test.janet | 2 +- .../clojure-control-test.janet | 2 +- test/{ => integration}/clojure-for-test.janet | 2 +- .../clojure-logic-test.janet | 2 +- .../clojure-macros-test.janet | 2 +- .../conformance-test.janet} | 2 +- test/{ => integration}/core-test.janet | 12 +-- test/{ => integration}/features-test.janet | 2 +- .../jank-conformance-test.janet} | 2 +- test/{ => integration}/logic-test.janet | 2 +- test/{ => integration}/namespace-test.janet | 6 +- .../ports}/cljs-collections-test.janet | 2 +- .../ports}/cljs-core-test.janet | 2 +- .../ports/cljs-port-1-test.janet} | 2 +- .../ports/cljs-port-10-test.janet} | 2 +- .../ports/cljs-port-1a-test.janet} | 2 +- .../ports/cljs-port-1b-test.janet} | 2 +- .../ports/cljs-port-2-test.janet} | 2 +- .../ports/cljs-port-3-test.janet} | 2 +- .../ports/cljs-port-3b-test.janet} | 2 +- .../ports/cljs-port-4-test.janet} | 2 +- .../ports/cljs-port-5-test.janet} | 2 +- .../ports/cljs-port-6-test.janet} | 2 +- .../ports/cljs-port-7-test.janet} | 2 +- .../ports/cljs-port-8-test.janet} | 2 +- .../ports/cljs-port-9-test.janet} | 2 +- .../ports}/cljs-port-test.janet | 2 +- .../ports}/phase10-test.janet | 6 +- .../ports}/phase12-test.janet | 2 +- .../ports}/phase13-test.janet | 6 +- .../{ => integration/ports}/phase5-test.janet | 2 +- .../ports/phase6-final-test.janet} | 2 +- .../{ => integration/ports}/phase6-test.janet | 2 +- .../{ => integration/ports}/phase7-test.janet | 2 +- .../{ => integration/ports}/phase8-test.janet | 2 +- .../sci-bootstrap-test.janet} | 8 +- .../sci-runtime-test.janet} | 8 +- .../systematic-coverage-test.janet} | 2 +- test/support/harness.janet | 82 +++++++++++++++++++ test/{ => unit}/compiler-test.janet | 20 ++--- test/{ => unit}/eval-test.janet | 2 +- test/{ => unit}/evaluator-test.janet | 8 +- test/{ => unit}/interop-test.janet | 2 +- .../lazy-seq-test.janet} | 2 +- test/{ => unit}/macro-test.janet | 6 +- .../persistent-map-test.janet} | 2 +- test/{ => unit}/reader-test.janet | 2 +- test/{ => unit}/types-test.janet | 2 +- 52 files changed, 185 insertions(+), 86 deletions(-) rename test/{ => integration}/api-test.janet (95%) rename test/{ => integration}/bootstrap-test.janet (84%) rename test/{ => integration}/clojure-atom-test.janet (99%) rename test/{ => integration}/clojure-control-test.janet (99%) rename test/{ => integration}/clojure-for-test.janet (97%) rename test/{ => integration}/clojure-logic-test.janet (99%) rename test/{ => integration}/clojure-macros-test.janet (98%) rename test/{conformance.janet => integration/conformance-test.janet} (99%) rename test/{ => integration}/core-test.janet (96%) rename test/{ => integration}/features-test.janet (99%) rename test/{jank-conformance.janet => integration/jank-conformance-test.janet} (98%) rename test/{ => integration}/logic-test.janet (99%) rename test/{ => integration}/namespace-test.janet (97%) rename test/{ => integration/ports}/cljs-collections-test.janet (98%) rename test/{ => integration/ports}/cljs-core-test.janet (99%) rename test/{cljs-port-1.janet => integration/ports/cljs-port-1-test.janet} (99%) rename test/{cljs-port-10.janet => integration/ports/cljs-port-10-test.janet} (96%) rename test/{cljs-port-1a.janet => integration/ports/cljs-port-1a-test.janet} (99%) rename test/{cljs-port-1b.janet => integration/ports/cljs-port-1b-test.janet} (98%) rename test/{cljs-port-2.janet => integration/ports/cljs-port-2-test.janet} (99%) rename test/{cljs-port-3.janet => integration/ports/cljs-port-3-test.janet} (97%) rename test/{cljs-port-3b.janet => integration/ports/cljs-port-3b-test.janet} (97%) rename test/{cljs-port-4.janet => integration/ports/cljs-port-4-test.janet} (98%) rename test/{cljs-port-5.janet => integration/ports/cljs-port-5-test.janet} (97%) rename test/{cljs-port-6.janet => integration/ports/cljs-port-6-test.janet} (97%) rename test/{cljs-port-7.janet => integration/ports/cljs-port-7-test.janet} (96%) rename test/{cljs-port-8.janet => integration/ports/cljs-port-8-test.janet} (97%) rename test/{cljs-port-9.janet => integration/ports/cljs-port-9-test.janet} (95%) rename test/{ => integration/ports}/cljs-port-test.janet (99%) rename test/{ => integration/ports}/phase10-test.janet (96%) rename test/{ => integration/ports}/phase12-test.janet (98%) rename test/{ => integration/ports}/phase13-test.janet (93%) rename test/{ => integration/ports}/phase5-test.janet (99%) rename test/{phase6-final.janet => integration/ports/phase6-final-test.janet} (99%) rename test/{ => integration/ports}/phase6-test.janet (97%) rename test/{ => integration/ports}/phase7-test.janet (97%) rename test/{ => integration/ports}/phase8-test.janet (98%) rename test/{test-load-sci.janet => integration/sci-bootstrap-test.janet} (96%) rename test/{test-sci-runtime.janet => integration/sci-runtime-test.janet} (97%) rename test/{systematic-coverage.janet => integration/systematic-coverage-test.janet} (99%) create mode 100644 test/support/harness.janet rename test/{ => unit}/compiler-test.janet (97%) rename test/{ => unit}/eval-test.janet (94%) rename test/{ => unit}/evaluator-test.janet (98%) rename test/{ => unit}/interop-test.janet (98%) rename test/{lazy-test.janet => unit/lazy-seq-test.janet} (98%) rename test/{ => unit}/macro-test.janet (98%) rename test/{hash-map-test.janet => unit/persistent-map-test.janet} (99%) rename test/{ => unit}/reader-test.janet (99%) rename test/{ => unit}/types-test.janet (99%) diff --git a/.beads/interactions.jsonl b/.beads/interactions.jsonl index 584eea4..3a37e4a 100644 --- a/.beads/interactions.jsonl +++ b/.beads/interactions.jsonl @@ -19,3 +19,4 @@ {"id":"int-0e80bc4f","kind":"field_change","created_at":"2026-06-04T20:23:37.457452Z","actor":"Yogthos","issue_id":"jolt-cn4","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Closed"}} {"id":"int-8cd2e476","kind":"field_change","created_at":"2026-06-04T21:28:16.906665Z","actor":"Yogthos","issue_id":"jolt-y29","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Closed"}} {"id":"int-6042189d","kind":"field_change","created_at":"2026-06-04T23:20:46.565771Z","actor":"Yogthos","issue_id":"jolt-ns4","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Done across 3 rounds (pushed a0c9696): build-time mutable/immutable toggle, structural-sharing persistent vectors (32-way trie), and persistent O(1)-prepend linked lists. Plus bit-clear/get-method and a batch of missing core fns. conformance 206/206, features 78/78, jank 120."}} +{"id":"int-80df5ed4","kind":"field_change","created_at":"2026-06-05T03:35:42.672628Z","actor":"Yogthos","issue_id":"jolt-i3g","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Done — SCI bootstrap now loads 422/422 with 0 failures. Fixed deftype protocol-method registration, with-meta on functions, select-keys over vectors, require :as+:refer, defmethod-on-fn; added clojure.set/join and host-module stubs. test-load-sci asserts 0 failures."}} diff --git a/README.md b/README.md index 7b51749..4111d93 100644 --- a/README.md +++ b/README.md @@ -87,10 +87,26 @@ Supported and Clojure-compatible: chars as a distinct type, lazy/infinite sequen ## Test ``` -jpm test # full test suite -janet test/conformance.janet # Clojure-conformance battery +jpm test # full suite (recurses test/) +janet test/spec/sequences-spec.janet # a single spec +janet test/integration/conformance-test.janet ``` +Tests are organized in three layers: + +- **`test/spec/`** — the contract. Black-box, behavior-defining tables (one file + per public API area) that collectively pin down Jolt's defined behavior. This + is the authoritative description of what Jolt promises. +- **`test/integration/`** — cross-cutting and regression batteries: the Clojure + conformance suite, SCI bootstrap/runtime loading, jank conformance, and ported + Clojure/CLJS test batches (`test/integration/ports/`). +- **`test/unit/`** — white-box tests for individual components (reader, + evaluator, types, persistent collections, regex, compiler). + +`test/support/harness.janet` provides the shared `defspec` table runner (cases +are `["label" expected actual]`, compared with Jolt's own `=`) plus +`expect=`/`expect-throws` for unit tests. + ## License [Eclipse Public License 1.0](https://opensource.org/licenses/EPL-1.0) diff --git a/test/api-test.janet b/test/integration/api-test.janet similarity index 95% rename from test/api-test.janet rename to test/integration/api-test.janet index 211f08c..25a7d6e 100644 --- a/test/api-test.janet +++ b/test/integration/api-test.janet @@ -1,5 +1,5 @@ -(use ../src/jolt/api) -(use ../src/jolt/types) +(use ../../src/jolt/api) +(use ../../src/jolt/types) (print "1: init creates context...") (let [ctx (init)] diff --git a/test/bootstrap-test.janet b/test/integration/bootstrap-test.janet similarity index 84% rename from test/bootstrap-test.janet rename to test/integration/bootstrap-test.janet index c1581ba..169d109 100644 --- a/test/bootstrap-test.janet +++ b/test/integration/bootstrap-test.janet @@ -1,7 +1,7 @@ -(use ../src/jolt/evaluator) -(use ../src/jolt/types) -(use ../src/jolt/reader) -(use ../src/jolt/api) +(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")) diff --git a/test/clojure-atom-test.janet b/test/integration/clojure-atom-test.janet similarity index 99% rename from test/clojure-atom-test.janet rename to test/integration/clojure-atom-test.janet index 1bf1b48..121bd41 100644 --- a/test/clojure-atom-test.janet +++ b/test/integration/clojure-atom-test.janet @@ -1,5 +1,5 @@ # Ported from clojure/test_clojure/atoms.clj + systematic atom tests -(use ../src/jolt/api) +(use ../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) (print "Ported Atom Tests") diff --git a/test/clojure-control-test.janet b/test/integration/clojure-control-test.janet similarity index 99% rename from test/clojure-control-test.janet rename to test/integration/clojure-control-test.janet index 78de060..0e557b8 100644 --- a/test/clojure-control-test.janet +++ b/test/integration/clojure-control-test.janet @@ -1,5 +1,5 @@ # Ported from clojure/test_clojure/control.clj -(use ../src/jolt/api) +(use ../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) (print "Ported Control Tests") diff --git a/test/clojure-for-test.janet b/test/integration/clojure-for-test.janet similarity index 97% rename from test/clojure-for-test.janet rename to test/integration/clojure-for-test.janet index 0bf3bf8..f313d41 100644 --- a/test/clojure-for-test.janet +++ b/test/integration/clojure-for-test.janet @@ -1,5 +1,5 @@ # Ported from clojure/test_clojure/for.clj -(use ../src/jolt/api) +(use ../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) (print "Ported For Tests") diff --git a/test/clojure-logic-test.janet b/test/integration/clojure-logic-test.janet similarity index 99% rename from test/clojure-logic-test.janet rename to test/integration/clojure-logic-test.janet index 934cf31..916cd77 100644 --- a/test/clojure-logic-test.janet +++ b/test/integration/clojure-logic-test.janet @@ -1,5 +1,5 @@ # Ported from clojure/test_clojure/logic.clj -(use ../src/jolt/api) +(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)") diff --git a/test/clojure-macros-test.janet b/test/integration/clojure-macros-test.janet similarity index 98% rename from test/clojure-macros-test.janet rename to test/integration/clojure-macros-test.janet index c98cecd..a5e4143 100644 --- a/test/clojure-macros-test.janet +++ b/test/integration/clojure-macros-test.janet @@ -1,5 +1,5 @@ # Ported from clojure/test_clojure/macros.clj -(use ../src/jolt/api) +(use ../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) (print "Ported Macros Tests") diff --git a/test/conformance.janet b/test/integration/conformance-test.janet similarity index 99% rename from test/conformance.janet rename to test/integration/conformance-test.janet index dfbf85f..fcccea8 100644 --- a/test/conformance.janet +++ b/test/integration/conformance-test.janet @@ -12,7 +12,7 @@ # 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) +(use ../../src/jolt/api) (def cases [ diff --git a/test/core-test.janet b/test/integration/core-test.janet similarity index 96% rename from test/core-test.janet rename to test/integration/core-test.janet index 311db98..989815b 100644 --- a/test/core-test.janet +++ b/test/integration/core-test.janet @@ -1,9 +1,9 @@ -(use ../src/jolt/types) -(use ../src/jolt/pv) -(use ../src/jolt/plist) -(use ../src/jolt/reader) -(use ../src/jolt/evaluator) -(use ../src/jolt/core) +(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. diff --git a/test/features-test.janet b/test/integration/features-test.janet similarity index 99% rename from test/features-test.janet rename to test/integration/features-test.janet index 0872e3f..bb255f2 100644 --- a/test/features-test.janet +++ b/test/integration/features-test.janet @@ -1,7 +1,7 @@ # 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) +(use ../../src/jolt/api) (var pass 0) (def fails @[]) diff --git a/test/jank-conformance.janet b/test/integration/jank-conformance-test.janet similarity index 98% rename from test/jank-conformance.janet rename to test/integration/jank-conformance-test.janet index 02baa77..cb53ccd 100644 --- a/test/jank-conformance.janet +++ b/test/integration/jank-conformance-test.janet @@ -6,7 +6,7 @@ # # 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) +(use ../../src/jolt/api) (def jank-dir (string (os/getenv "HOME") "/src/jank/compiler+runtime/test/jank")) diff --git a/test/logic-test.janet b/test/integration/logic-test.janet similarity index 99% rename from test/logic-test.janet rename to test/integration/logic-test.janet index ac30395..669b239 100644 --- a/test/logic-test.janet +++ b/test/integration/logic-test.janet @@ -1,4 +1,4 @@ -(use ../src/jolt/api) +(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)") diff --git a/test/namespace-test.janet b/test/integration/namespace-test.janet similarity index 97% rename from test/namespace-test.janet rename to test/integration/namespace-test.janet index 3c78ea7..67d4b5d 100644 --- a/test/namespace-test.janet +++ b/test/integration/namespace-test.janet @@ -1,6 +1,6 @@ -(use ../src/jolt/reader) -(use ../src/jolt/types) -(use ../src/jolt/evaluator) +(use ../../src/jolt/reader) +(use ../../src/jolt/types) +(use ../../src/jolt/evaluator) # Helper: parse and eval in a fresh ctx (defn eval-str [s] diff --git a/test/cljs-collections-test.janet b/test/integration/ports/cljs-collections-test.janet similarity index 98% rename from test/cljs-collections-test.janet rename to test/integration/ports/cljs-collections-test.janet index 1ea9f04..7d14f34 100644 --- a/test/cljs-collections-test.janet +++ b/test/integration/ports/cljs-collections-test.janet @@ -1,4 +1,4 @@ -(use ../src/jolt/api) +(use ../../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) (print "CLJS Collections Ported Tests") diff --git a/test/cljs-core-test.janet b/test/integration/ports/cljs-core-test.janet similarity index 99% rename from test/cljs-core-test.janet rename to test/integration/ports/cljs-core-test.janet index f722df1..f3596a9 100644 --- a/test/cljs-core-test.janet +++ b/test/integration/ports/cljs-core-test.janet @@ -1,4 +1,4 @@ -(use ../src/jolt/api) +(use ../../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) (print "CLJS Core Ported Tests") diff --git a/test/cljs-port-1.janet b/test/integration/ports/cljs-port-1-test.janet similarity index 99% rename from test/cljs-port-1.janet rename to test/integration/ports/cljs-port-1-test.janet index 98a0ca3..8c5edb9 100644 --- a/test/cljs-port-1.janet +++ b/test/integration/ports/cljs-port-1-test.janet @@ -1,4 +1,4 @@ -(use ../src/jolt/api) +(use ../../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) (print "=== CLJS Ported Part 1 ===") (print "1: core math...") diff --git a/test/cljs-port-10.janet b/test/integration/ports/cljs-port-10-test.janet similarity index 96% rename from test/cljs-port-10.janet rename to test/integration/ports/cljs-port-10-test.janet index 34e1387..7449a24 100644 --- a/test/cljs-port-10.janet +++ b/test/integration/ports/cljs-port-10-test.janet @@ -1,4 +1,4 @@ -(use ../src/jolt/api) +(use ../../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) (print "=== CLJS Ported Part 10 ===") diff --git a/test/cljs-port-1a.janet b/test/integration/ports/cljs-port-1a-test.janet similarity index 99% rename from test/cljs-port-1a.janet rename to test/integration/ports/cljs-port-1a-test.janet index cc56f2d..969f046 100644 --- a/test/cljs-port-1a.janet +++ b/test/integration/ports/cljs-port-1a-test.janet @@ -1,4 +1,4 @@ -(use ../src/jolt/api) +(use ../../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) (print "=== CLJS Ported Part 1 ===") (print "1: core math...") diff --git a/test/cljs-port-1b.janet b/test/integration/ports/cljs-port-1b-test.janet similarity index 98% rename from test/cljs-port-1b.janet rename to test/integration/ports/cljs-port-1b-test.janet index 9069015..22bdb56 100644 --- a/test/cljs-port-1b.janet +++ b/test/integration/ports/cljs-port-1b-test.janet @@ -1,4 +1,4 @@ -(use ../src/jolt/api) +(use ../../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) (print "=== CLJS Ported Part 1b ===") (print "7: seq operations...") diff --git a/test/cljs-port-2.janet b/test/integration/ports/cljs-port-2-test.janet similarity index 99% rename from test/cljs-port-2.janet rename to test/integration/ports/cljs-port-2-test.janet index 8496f20..558dd7c 100644 --- a/test/cljs-port-2.janet +++ b/test/integration/ports/cljs-port-2-test.janet @@ -1,4 +1,4 @@ -(use ../src/jolt/api) +(use ../../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) (print "=== CLJS Ported Part 2 ===") (print "12: atoms...") diff --git a/test/cljs-port-3.janet b/test/integration/ports/cljs-port-3-test.janet similarity index 97% rename from test/cljs-port-3.janet rename to test/integration/ports/cljs-port-3-test.janet index 0e0c09c..081ce40 100644 --- a/test/cljs-port-3.janet +++ b/test/integration/ports/cljs-port-3-test.janet @@ -1,4 +1,4 @@ -(use ../src/jolt/api) +(use ../../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) (print "=== CLJS Ported Part 3 ===") (print "16: destructuring...") diff --git a/test/cljs-port-3b.janet b/test/integration/ports/cljs-port-3b-test.janet similarity index 97% rename from test/cljs-port-3b.janet rename to test/integration/ports/cljs-port-3b-test.janet index 8573d60..3d13a71 100644 --- a/test/cljs-port-3b.janet +++ b/test/integration/ports/cljs-port-3b-test.janet @@ -1,4 +1,4 @@ -(use ../src/jolt/api) +(use ../../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) (print "=== CLJS Ported Part 3b ===") (print "21: clojure.string...") diff --git a/test/cljs-port-4.janet b/test/integration/ports/cljs-port-4-test.janet similarity index 98% rename from test/cljs-port-4.janet rename to test/integration/ports/cljs-port-4-test.janet index 086a668..f209600 100644 --- a/test/cljs-port-4.janet +++ b/test/integration/ports/cljs-port-4-test.janet @@ -1,4 +1,4 @@ -(use ../src/jolt/api) +(use ../../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) (print "=== CLJS Ported Part 4 ===") diff --git a/test/cljs-port-5.janet b/test/integration/ports/cljs-port-5-test.janet similarity index 97% rename from test/cljs-port-5.janet rename to test/integration/ports/cljs-port-5-test.janet index c1b2380..e615eb5 100644 --- a/test/cljs-port-5.janet +++ b/test/integration/ports/cljs-port-5-test.janet @@ -1,4 +1,4 @@ -(use ../src/jolt/api) +(use ../../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) (print "=== CLJS Ported Part 5 ===") (print "22: destructuring...") diff --git a/test/cljs-port-6.janet b/test/integration/ports/cljs-port-6-test.janet similarity index 97% rename from test/cljs-port-6.janet rename to test/integration/ports/cljs-port-6-test.janet index 7b03bd7..ee71b16 100644 --- a/test/cljs-port-6.janet +++ b/test/integration/ports/cljs-port-6-test.janet @@ -1,4 +1,4 @@ -(use ../src/jolt/api) +(use ../../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) (print "=== CLJS Ported Part 6 ===") diff --git a/test/cljs-port-7.janet b/test/integration/ports/cljs-port-7-test.janet similarity index 96% rename from test/cljs-port-7.janet rename to test/integration/ports/cljs-port-7-test.janet index 27724a4..79a6788 100644 --- a/test/cljs-port-7.janet +++ b/test/integration/ports/cljs-port-7-test.janet @@ -1,4 +1,4 @@ -(use ../src/jolt/api) +(use ../../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) (print "=== CLJS Ported Part 7 ===") diff --git a/test/cljs-port-8.janet b/test/integration/ports/cljs-port-8-test.janet similarity index 97% rename from test/cljs-port-8.janet rename to test/integration/ports/cljs-port-8-test.janet index d9912de..355b30f 100644 --- a/test/cljs-port-8.janet +++ b/test/integration/ports/cljs-port-8-test.janet @@ -1,4 +1,4 @@ -(use ../src/jolt/api) +(use ../../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) (print "=== CLJS Ported Part 8 ===") diff --git a/test/cljs-port-9.janet b/test/integration/ports/cljs-port-9-test.janet similarity index 95% rename from test/cljs-port-9.janet rename to test/integration/ports/cljs-port-9-test.janet index 72367e0..158a88c 100644 --- a/test/cljs-port-9.janet +++ b/test/integration/ports/cljs-port-9-test.janet @@ -1,4 +1,4 @@ -(use ../src/jolt/api) +(use ../../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) (print "=== CLJS Ported Part 9 ===") diff --git a/test/cljs-port-test.janet b/test/integration/ports/cljs-port-test.janet similarity index 99% rename from test/cljs-port-test.janet rename to test/integration/ports/cljs-port-test.janet index 00f9802..329fb3e 100644 --- a/test/cljs-port-test.janet +++ b/test/integration/ports/cljs-port-test.janet @@ -1,4 +1,4 @@ -(use ../src/jolt/api) +(use ../../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) (print "CLJS Ported Tests") diff --git a/test/phase10-test.janet b/test/integration/ports/phase10-test.janet similarity index 96% rename from test/phase10-test.janet rename to test/integration/ports/phase10-test.janet index e3da532..54352c3 100644 --- a/test/phase10-test.janet +++ b/test/integration/ports/phase10-test.janet @@ -1,6 +1,6 @@ -(use ../src/jolt/api) -(use ../src/jolt/reader) -(use ../src/jolt/evaluator) +(use ../../../src/jolt/api) +(use ../../../src/jolt/reader) +(use ../../../src/jolt/evaluator) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) diff --git a/test/phase12-test.janet b/test/integration/ports/phase12-test.janet similarity index 98% rename from test/phase12-test.janet rename to test/integration/ports/phase12-test.janet index b2e2e96..0728b6f 100644 --- a/test/phase12-test.janet +++ b/test/integration/ports/phase12-test.janet @@ -1,5 +1,5 @@ # Phase 12: Protocol System Tests -(use ../src/jolt/api) +(use ../../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) (print "35: defprotocol...") diff --git a/test/phase13-test.janet b/test/integration/ports/phase13-test.janet similarity index 93% rename from test/phase13-test.janet rename to test/integration/ports/phase13-test.janet index 9bdd567..915caa7 100644 --- a/test/phase13-test.janet +++ b/test/integration/ports/phase13-test.janet @@ -1,6 +1,6 @@ -(use ../src/jolt/api) -(use ../src/jolt/evaluator) -(use ../src/jolt/reader) +(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] diff --git a/test/phase5-test.janet b/test/integration/ports/phase5-test.janet similarity index 99% rename from test/phase5-test.janet rename to test/integration/ports/phase5-test.janet index 5003eaf..7bfc157 100644 --- a/test/phase5-test.janet +++ b/test/integration/ports/phase5-test.janet @@ -1,5 +1,5 @@ # Phase 5: Multimethods + Hierarchy Tests -(use ../src/jolt/api) +(use ../../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) # 22. Hierarchy diff --git a/test/phase6-final.janet b/test/integration/ports/phase6-final-test.janet similarity index 99% rename from test/phase6-final.janet rename to test/integration/ports/phase6-final-test.janet index a67cee6..439fd4b 100644 --- a/test/phase6-final.janet +++ b/test/integration/ports/phase6-final-test.janet @@ -1,4 +1,4 @@ -(use ../src/jolt/api) +(use ../../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) diff --git a/test/phase6-test.janet b/test/integration/ports/phase6-test.janet similarity index 97% rename from test/phase6-test.janet rename to test/integration/ports/phase6-test.janet index 178c6b5..845769f 100644 --- a/test/phase6-test.janet +++ b/test/integration/ports/phase6-test.janet @@ -1,5 +1,5 @@ # Phase 6: Reader Extensions Tests -(use ../src/jolt/api) +(use ../../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) (print "28: #inst tagged literal...") diff --git a/test/phase7-test.janet b/test/integration/ports/phase7-test.janet similarity index 97% rename from test/phase7-test.janet rename to test/integration/ports/phase7-test.janet index 7edb399..11d43b3 100644 --- a/test/phase7-test.janet +++ b/test/integration/ports/phase7-test.janet @@ -1,5 +1,5 @@ # Phase 7: LazySeq + PersistentHashSet completion -(use ../src/jolt/api) +(use ../../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) (print "32: lazy-seq...") diff --git a/test/phase8-test.janet b/test/integration/ports/phase8-test.janet similarity index 98% rename from test/phase8-test.janet rename to test/integration/ports/phase8-test.janet index 8f92cfc..16b4488 100644 --- a/test/phase8-test.janet +++ b/test/integration/ports/phase8-test.janet @@ -1,5 +1,5 @@ # Phase 8: Protocol System Tests -(use ../src/jolt/api) +(use ../../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) (print "35: defprotocol...") diff --git a/test/test-load-sci.janet b/test/integration/sci-bootstrap-test.janet similarity index 96% rename from test/test-load-sci.janet rename to test/integration/sci-bootstrap-test.janet index 35080e8..ddffd4b 100644 --- a/test/test-load-sci.janet +++ b/test/integration/sci-bootstrap-test.janet @@ -1,7 +1,7 @@ -(use ../src/jolt/evaluator) -(use ../src/jolt/types) -(use ../src/jolt/reader) -(use ../src/jolt/api) +(use ../../src/jolt/evaluator) +(use ../../src/jolt/types) +(use ../../src/jolt/reader) +(use ../../src/jolt/api) (def ctx (init)) diff --git a/test/test-sci-runtime.janet b/test/integration/sci-runtime-test.janet similarity index 97% rename from test/test-sci-runtime.janet rename to test/integration/sci-runtime-test.janet index 41a131e..a21bb27 100644 --- a/test/test-sci-runtime.janet +++ b/test/integration/sci-runtime-test.janet @@ -1,7 +1,7 @@ -(use ../src/jolt/evaluator) -(use ../src/jolt/types) -(use ../src/jolt/reader) -(use ../src/jolt/api) +(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)) diff --git a/test/systematic-coverage.janet b/test/integration/systematic-coverage-test.janet similarity index 99% rename from test/systematic-coverage.janet rename to test/integration/systematic-coverage-test.janet index 2468963..466f7bb 100644 --- a/test/systematic-coverage.janet +++ b/test/integration/systematic-coverage-test.janet @@ -1,5 +1,5 @@ # Systematic coverage tests for Clojure language features -(use ../src/jolt/api) +(use ../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) (print "Systematic Coverage Tests") diff --git a/test/support/harness.janet b/test/support/harness.janet new file mode 100644 index 0000000..4250c30 --- /dev/null +++ b/test/support/harness.janet @@ -0,0 +1,82 @@ +# Shared test harness for Jolt. +# +# Two complementary styles: +# +# defspec — data-driven behavioral tables, for spec/ and integration batteries. +# Each case is ["label" expected actual] where `expected` and `actual` are +# Clojure source strings. Equality is checked with Jolt's own `=`, so it is +# representation-agnostic (a vector result compares equal to a vector +# literal regardless of the underlying Janet type). Use the :throws sentinel +# in the `expected` position to assert that `actual` raises an error. +# +# (defspec "clojure.core / seq" +# ["first of vector" "1" "(first [1 2 3])"] +# ["rest is a seq" "(2 3)" "(rest [1 2 3])"] +# ["nth out of range" :throws "(nth [1] 5)"]) +# +# jeval / expect= / expect-throws — assertion helpers for white-box unit/ tests +# that probe a single component and want Janet-level assertions. +# +# A failing suite prints every failing behavior, then raises — so `jpm test` +# reports a non-zero exit and the offending behaviors are visible. + +(use ../../src/jolt/api) + +(defn jeval + "Evaluate a Clojure source string in a fresh context, normalizing persistent + vectors/lists to Janet tuples so results compare with `deep=`/tuple literals." + [s] + (normalize-pvecs (eval-string (init) s))) + +(defn- show [s] + (let [r (protect (eval-string (init) s))] + (if (= (r 0) true) + (string/format "%q" (normalize-pvecs (r 1))) + (string "")))) + +(defn run-spec + "Run a data-driven behavioral suite. See `defspec`." + [suite cases] + (var pass 0) + (def fails @[]) + (each case cases + (def label (in case 0)) + (def expected (in case 1)) + (def actual (in case 2)) + (if (= expected :throws) + (let [r (protect (eval-string (init) actual))] + (if (= (r 0) false) + (++ pass) + (array/push fails [label "expected an error, got a value"]))) + (let [r (protect (eval-string (init) (string "(= " expected " " actual ")")))] + (cond + (not= (r 0) true) (array/push fails [label (string "errored: " (r 1))]) + (= (r 1) true) (++ pass) + (array/push fails [label (string "want " expected ", got " (show actual))]))))) + (printf " %s: %d/%d" suite pass (length cases)) + (each [l m] fails (printf " FAIL [%s] %s" l m)) + (when (> (length fails) 0) + (error (string suite ": " (length fails) " failing behavior(s)"))) + pass) + +(defmacro defspec + "Define and immediately run a behavioral suite of [label expected actual] cases." + [suite & cases] + ~(,run-spec ,suite [,;cases])) + +# --- white-box assertion helpers (unit tests) --- + +(defn expect= + "Assert that evaluating Clojure `s` yields `expected` (a Janet value, compared + with deep= after normalizing persistent collections to tuples)." + [expected s] + (let [got (jeval s)] + (assert (deep= expected got) + (string "expected " (string/format "%q" expected) + ", got " (string/format "%q" got) " for: " s)))) + +(defn expect-throws + "Assert that evaluating Clojure `s` raises an error." + [s] + (let [r (protect (eval-string (init) s))] + (assert (= (r 0) false) (string "expected an error for: " s)))) diff --git a/test/compiler-test.janet b/test/unit/compiler-test.janet similarity index 97% rename from test/compiler-test.janet rename to test/unit/compiler-test.janet index 5e9531f..7de1183 100644 --- a/test/compiler-test.janet +++ b/test/unit/compiler-test.janet @@ -3,8 +3,8 @@ # Core ops: const, do, if, def, fn, let, invoke # Phase 2 adds: symbol classification with binding awareness -(use ../src/jolt/compiler) -(use ../src/jolt/reader) +(use ../../src/jolt/compiler) +(use ../../src/jolt/reader) (defn compile-str [s] (let [form (parse-string s)] @@ -98,7 +98,7 @@ # 9. Compile-and-eval round-trip (Phase 3) # ============================================================ (print "9: compile-and-eval...") -(use ../src/jolt/core) # need core fns in scope for eval +(use ../../src/jolt/core) # need core fns in scope for eval (defn compile-eval-str [s] (let [form (parse-string s)] @@ -121,7 +121,7 @@ # 10. Compile flag in context (Phase 3) # ============================================================ (print "10: compile flag...") -(use ../src/jolt/api) +(use ../../src/jolt/api) # Without compile flag (let [ctx (init)] @@ -146,7 +146,7 @@ # 11. Macro expansion (Phase 4) # ============================================================ (print "11: macro expansion...") -(use ../src/jolt/api) +(use ../../src/jolt/api) (let [ctx (init {:compile? true})] # defn expands via compiler, produces Janet def @@ -175,7 +175,7 @@ # 12. throw, try, loop*/recur (Phase 5) # ============================================================ (print "12: throw/try/loop...") -(use ../src/jolt/api) +(use ../../src/jolt/api) (let [ctx (init {:compile? true})] # throw/catch via compiler @@ -206,7 +206,7 @@ # 13. defn/def integration (Phase 0 fix) # ============================================================ (print "13: defn/def integration...") -(use ../src/jolt/api) +(use ../../src/jolt/api) (let [ctx (init {:compile? true})] # defn produces a resolvable var @@ -228,7 +228,7 @@ # 14. Phase 1: ns accessors + ns form extensions # ============================================================ (print "14: ns accessors...") -(use ../src/jolt/api) +(use ../../src/jolt/api) (let [ctx (init)] (eval-string ctx "(ns mytest.core)") @@ -255,7 +255,7 @@ # 17. Phase 3: Var system completion # ============================================================ (print "17: var system...") -(use ../src/jolt/api) +(use ../../src/jolt/api) (let [ctx (init)] (eval-string ctx "(def x-var-test 42)") @@ -292,7 +292,7 @@ # 19. Phase 4: deftype # ============================================================ (print "19: deftype...") -(use ../src/jolt/api) +(use ../../src/jolt/api) (let [ctx (init)] (eval-string ctx "(deftype Point [x y])") diff --git a/test/eval-test.janet b/test/unit/eval-test.janet similarity index 94% rename from test/eval-test.janet rename to test/unit/eval-test.janet index 2089f17..2e566ce 100644 --- a/test/eval-test.janet +++ b/test/unit/eval-test.janet @@ -1,4 +1,4 @@ -(use ../src/jolt/api) +(use ../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) (print "Eval Tests") diff --git a/test/evaluator-test.janet b/test/unit/evaluator-test.janet similarity index 98% rename from test/evaluator-test.janet rename to test/unit/evaluator-test.janet index 72e97fd..3b216a3 100644 --- a/test/evaluator-test.janet +++ b/test/unit/evaluator-test.janet @@ -1,7 +1,7 @@ -(use ../src/jolt/evaluator) -(use ../src/jolt/types) -(use ../src/jolt/reader) -(use ../src/jolt/api) +(use ../../src/jolt/evaluator) +(use ../../src/jolt/types) +(use ../../src/jolt/reader) +(use ../../src/jolt/api) # Helper: create a Jolt symbol (defn sym [name] diff --git a/test/interop-test.janet b/test/unit/interop-test.janet similarity index 98% rename from test/interop-test.janet rename to test/unit/interop-test.janet index 2513fdf..a06d8f3 100644 --- a/test/interop-test.janet +++ b/test/unit/interop-test.janet @@ -1,4 +1,4 @@ -(use ../src/jolt/api) +(use ../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) (print "Janet Interop Tests") diff --git a/test/lazy-test.janet b/test/unit/lazy-seq-test.janet similarity index 98% rename from test/lazy-test.janet rename to test/unit/lazy-seq-test.janet index f820230..4911642 100644 --- a/test/lazy-test.janet +++ b/test/unit/lazy-seq-test.janet @@ -1,4 +1,4 @@ -(use ../src/jolt/api) +(use ../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) (print "LazySeq Tests") diff --git a/test/macro-test.janet b/test/unit/macro-test.janet similarity index 98% rename from test/macro-test.janet rename to test/unit/macro-test.janet index 5eb6b66..7444a06 100644 --- a/test/macro-test.janet +++ b/test/unit/macro-test.janet @@ -1,6 +1,6 @@ -(use ../src/jolt/reader) -(use ../src/jolt/types) -(use ../src/jolt/evaluator) +(use ../../src/jolt/reader) +(use ../../src/jolt/types) +(use ../../src/jolt/evaluator) # Helper: create a Jolt symbol (defn sym [name] diff --git a/test/hash-map-test.janet b/test/unit/persistent-map-test.janet similarity index 99% rename from test/hash-map-test.janet rename to test/unit/persistent-map-test.janet index 2c760b1..9ccba03 100644 --- a/test/hash-map-test.janet +++ b/test/unit/persistent-map-test.janet @@ -1,7 +1,7 @@ # Phase 2: PersistentHashMap Tests # Uses Clojure = (core-=) for PHM-aware comparison -(use ../src/jolt/api) +(use ../../src/jolt/api) (defn ct-eval [ctx s] (normalize-pvecs (eval-string ctx s))) diff --git a/test/reader-test.janet b/test/unit/reader-test.janet similarity index 99% rename from test/reader-test.janet rename to test/unit/reader-test.janet index 55959a6..d5c6bc7 100644 --- a/test/reader-test.janet +++ b/test/unit/reader-test.janet @@ -1,4 +1,4 @@ -(use ../src/jolt/reader) +(use ../../src/jolt/reader) # Helper: create a symbol (defn sym [name] diff --git a/test/types-test.janet b/test/unit/types-test.janet similarity index 99% rename from test/types-test.janet rename to test/unit/types-test.janet index 674b636..aa35266 100644 --- a/test/types-test.janet +++ b/test/unit/types-test.janet @@ -1,4 +1,4 @@ -(use ../src/jolt/types) +(use ../../src/jolt/types) # ============================================================ # Var tests