deps phases 3-4: uberscript bundling + conformance harness
Phase 3 — bundling. `jolt uberscript OUT -m NS` requires NS, uses the loader's recorded load order (a dep finishes loading before its requirer, so it's topological) to concatenate the used namespaces into one .clj that runs on a plain jolt with no deps/jpm. `jolt-deps uberscript` resolves first. The loader records loaded file paths when ctx env has :loaded-files. Phase 4 — conformance. deps-conformance-test resolves real pure-cljc git libs and reports load/run status, gated behind JOLT_CONFORMANCE so CI stays offline. First run: medley works; cuerdas hits a reader gap (filed); stuartsierra/ dependency uses Long/MAX_VALUE (JVM interop, out of scope). Tests: uberscript-test, deps-conformance-test (skips without the flag).
This commit is contained in:
parent
6a1706df10
commit
30c4bb0dc2
7 changed files with 174 additions and 8 deletions
54
test/integration/deps-conformance-test.janet
Normal file
54
test/integration/deps-conformance-test.janet
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
# Conformance pass for deps.edn-loaded libraries: resolve a few real, pure-cljc
|
||||
# git libraries and check that their namespaces load and a sample call works.
|
||||
#
|
||||
# Network-gated: set JOLT_CONFORMANCE=1 to run (it clones from GitHub). Skipped by
|
||||
# default so CI stays offline. Findings are summarized in doc/tools-deps.md.
|
||||
|
||||
(use ../../src/jolt/api)
|
||||
(use ../../src/jolt/types)
|
||||
(import ../../src/jolt/deps :as deps)
|
||||
|
||||
(unless (os/getenv "JOLT_CONFORMANCE")
|
||||
(print "deps-conformance: set JOLT_CONFORMANCE=1 to run (needs network) — skipped")
|
||||
(os/exit 0))
|
||||
|
||||
(def libs
|
||||
[{:name "medley" :url "https://github.com/weavejester/medley" :tag "1.4.0"
|
||||
:ns "medley.core" :check "(medley.core/find-first odd? [2 4 5])" :expect "5"}
|
||||
{:name "cuerdas" :url "https://github.com/funcool/cuerdas" :tag "2022.06.16-403"
|
||||
:ns "cuerdas.core" :check "(cuerdas.core/kebab \"helloWorld\")" :expect "hello-world"}
|
||||
{:name "dependency" :url "https://github.com/stuartsierra/dependency" :tag "dependency-1.0.0"
|
||||
:ns "com.stuartsierra.dependency"
|
||||
:check "(boolean (com.stuartsierra.dependency/graph))" :expect "true"}])
|
||||
|
||||
(def base (string (or (os/getenv "TMPDIR") "/tmp") "/jolt-conf-" (os/time)))
|
||||
(os/mkdir base)
|
||||
|
||||
(defn- try-lib [lib]
|
||||
(def dir (string base "/" (lib :name)))
|
||||
(os/mkdir dir)
|
||||
(spit (string dir "/deps.edn")
|
||||
(string "{:deps {the/lib {:git/url \"" (lib :url) "\" :git/tag \"" (lib :tag) "\"}}}"))
|
||||
(def prev (os/cwd))
|
||||
(defer (os/cd prev)
|
||||
(os/cd dir)
|
||||
(def r (protect (deps/resolve-deps "deps.edn")))
|
||||
(if (not (r 0))
|
||||
[:resolve-failed (string (r 1))]
|
||||
(let [ctx (init {:paths (r 1)})]
|
||||
(ctx-set-current-ns ctx "user")
|
||||
(def lr (protect (eval-string ctx (string "(require (quote [" (lib :ns) "]))"))))
|
||||
(if (not (lr 0))
|
||||
[:load-failed (string (lr 1))]
|
||||
(let [cr (protect (eval-string ctx (lib :check)))]
|
||||
(cond
|
||||
(not (cr 0)) [:check-error (string (cr 1))]
|
||||
(= (string (normalize-pvecs (cr 1))) (lib :expect)) [:ok nil]
|
||||
[:check-mismatch (string "got " (string (normalize-pvecs (cr 1))))])))))))
|
||||
|
||||
(print "deps conformance — pure-cljc git libs:\n")
|
||||
(each lib libs
|
||||
(def [status detail] (try (try-lib lib) ([err] [:crash (string err)])))
|
||||
(printf " %-12s %-16s %s" (lib :name) status (or detail "")))
|
||||
(print "")
|
||||
(os/exit 0)
|
||||
51
test/integration/uberscript-test.janet
Normal file
51
test/integration/uberscript-test.janet
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# `jolt uberscript` bundles a namespace and everything it requires into one .clj
|
||||
# that runs on a plain jolt with no JOLT_PATH / deps. Runs from source.
|
||||
|
||||
(defn- run [env-jolt-path & args]
|
||||
(if env-jolt-path (os/setenv "JOLT_PATH" env-jolt-path) (os/setenv "JOLT_PATH" nil))
|
||||
(def p (os/spawn ["janet" "src/jolt/main.janet" ;args] :p {:out :pipe :err :pipe}))
|
||||
(def out (:read (p :out) :all))
|
||||
(os/proc-wait p)
|
||||
(string (or out "")))
|
||||
|
||||
(defn- mkdirs [p]
|
||||
(var acc nil)
|
||||
(each seg (filter |(not= "" $) (string/split "/" p))
|
||||
(set acc (if (nil? acc) (if (string/has-prefix? "/" p) (string "/" seg) seg) (string acc "/" seg)))
|
||||
(unless (os/stat acc) (os/mkdir acc))))
|
||||
(defn- rmrf [p]
|
||||
(when (os/stat p)
|
||||
(if (= :directory (os/stat p :mode))
|
||||
(do (each e (os/dir p) (rmrf (string p "/" e))) (os/rmdir p))
|
||||
(os/rm p))))
|
||||
|
||||
(def base (string (or (os/getenv "TMPDIR") "/tmp") "/jolt-uber-" (os/time)))
|
||||
(rmrf base)
|
||||
(mkdirs (string base "/proj/src/app"))
|
||||
(mkdirs (string base "/lib/src/greet"))
|
||||
(spit (string base "/lib/src/greet/core.clj")
|
||||
"(ns greet.core)\n(defn hello [n] (str \"Hello, \" n \"!\"))\n")
|
||||
(spit (string base "/proj/src/app/core.clj")
|
||||
"(ns app.core (:require [greet.core :as g]))\n(defn -main [& args] (println (g/hello (or (first args) \"world\"))))\n")
|
||||
|
||||
(var fails 0)
|
||||
(defn check [label got pred]
|
||||
(if (pred got) (print " ok " label)
|
||||
(do (++ fails) (printf " FAIL %s: got %q" label got))))
|
||||
(defn- has [s] (fn [x] (string/find s x)))
|
||||
|
||||
(def roots (string base "/proj/src:" base "/lib/src"))
|
||||
(def out (string base "/out.clj"))
|
||||
|
||||
# build the uberscript with the dep roots on JOLT_PATH
|
||||
(run roots "uberscript" out "-m" "app.core")
|
||||
(check "uberscript written" (if (os/stat out) "yes" "no") (has "yes"))
|
||||
(check "bundles the dep ns" (slurp out) (has "(ns greet.core)"))
|
||||
|
||||
# run it standalone: no JOLT_PATH, so it only works if the dep was inlined
|
||||
(check "runs standalone" (run nil out "Bob") (has "Hello, Bob!"))
|
||||
|
||||
(rmrf base)
|
||||
(if (> fails 0)
|
||||
(error (string "uberscript-test: " fails " failing check(s)"))
|
||||
(print "\nAll uberscript tests passed!"))
|
||||
Loading…
Add table
Add a link
Reference in a new issue