From dfbbd4fda50ce3b7eb4e6f56a585ca2e21a9678d Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Thu, 17 Jun 2021 18:19:40 +0200 Subject: [PATCH 01/65] sci [skip ci] --- sci | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sci b/sci index 79376504..b211667c 160000 --- a/sci +++ b/sci @@ -1 +1 @@ -Subproject commit 7937650453b7ba9eb9ee43ea30b333b5950dc21e +Subproject commit b211667c006b7e69115ad1b86f953612ccfbf932 From e056cb96aa06cab69661a6543fdd08604dd29893 Mon Sep 17 00:00:00 2001 From: Bob Date: Thu, 17 Jun 2021 13:43:43 -0400 Subject: [PATCH 02/65] add more windows testing (#891) - add `normalize` call to `bb-native` output - add `escape-file-paths` function to double up backslashes for Windows paths passed as strings - add :windows selector to about 10 more tests, along with various small changes for Windows testing - update test.bat to more closely mirror the Linux/Mac test script --- script/test.bat | 10 ++++++ test/babashka/main_test.clj | 63 ++++++++++++++++++--------------- test/babashka/scripts/System.bb | 2 +- test/babashka/test_utils.clj | 7 +++- 4 files changed, 51 insertions(+), 31 deletions(-) diff --git a/script/test.bat b/script/test.bat index ba69e4ec..4a86f522 100755 --- a/script/test.bat +++ b/script/test.bat @@ -8,4 +8,14 @@ echo "BABASHKA_TEST_ENV: %BABASHKA_TEST_ENV%" set JAVA_HOME=%GRAALVM_HOME% set PATH=%GRAALVM_HOME%\bin;%PATH% +set BABASHKA_PRELOADS= +set BABASHKA_CLASSPATH= +set BABASHKA_PRELOADS_TEST= + +echo "running tests part 1" call lein do clean, test :windows + +set BABASHKA_PRELOADS=(defn __bb__foo [] "foo") (defn __bb__bar [] "bar") +set BABASHKA_PRELOADS_TEST=true +echo "running tests part 2" +call lein test :only babashka.main-test/preloads-test diff --git a/test/babashka/main_test.clj b/test/babashka/main_test.clj index a56bfc87..b296eacf 100644 --- a/test/babashka/main_test.clj +++ b/test/babashka/main_test.clj @@ -66,7 +66,7 @@ (is (thrown-with-msg? Exception #"java.lang.NullPointerException" (bb nil "(subs nil 0 0)")))) -(deftest input-test +(deftest ^:windows input-test (testing "-io behaves as identity" (is (= "foo\nbar\n" (test-utils/bb "foo\nbar\n" "-io" "*input*")))) (testing "if and when" @@ -120,12 +120,12 @@ (is (= "localhost" (bb "#ordered/map ([:test \"localhost\"])" "(:test *input*)")))) (testing "bb doesn't wait for input if *input* isn't used" - (is (= "2\n" (with-out-str (main/main "(inc 1)")))))) + (is (= "2\n" (test-utils/normalize (with-out-str (main/main "(inc 1)"))))))) -(deftest println-test +(deftest ^:windows println-test (is (= "hello\n" (test-utils/bb nil "(println \"hello\")")))) -(deftest System-test +(deftest ^:windows System-test (let [res (bb nil "-f" "test/babashka/scripts/System.bb")] (is (= "bar" (second res))) (doseq [s res] @@ -135,11 +135,11 @@ (is (thrown-with-msg? Exception #"File does not exist: non-existing" (bb nil "-f" "non-existing")))) -(deftest ssl-test +(deftest ^:windows ssl-test (let [resp (bb nil "(slurp \"https://www.google.com\")")] (is (re-find #"doctype html" resp)))) -(deftest stream-test +(deftest ^:windows stream-test (is (= "2\n3\n4\n" (test-utils/bb "1 2 3" "--stream" "(inc *input*)"))) (is (= "2\n3\n4\n" (test-utils/bb "{:x 2} {:x 3} {:x 4}" "--stream" "(:x *input*)"))) (let [x "foo\n\bar\n"] @@ -147,18 +147,18 @@ (let [x "f\n\b\n"] (is (= x (test-utils/bb x "--stream" "-io" "(subs *input* 0 1)"))))) -(deftest load-file-test +(deftest ^:windows load-file-test (let [tmp (java.io.File/createTempFile "script" ".clj")] (.deleteOnExit tmp) (spit tmp "(ns foo) (defn foo [x y] (+ x y)) (defn bar [x y] (* x y))") (is (= "120\n" (test-utils/bb nil (format "(load-file \"%s\") (foo/bar (foo/foo 10 30) 3)" - (.getPath tmp))))) + (test-utils/escape-file-paths (.getPath tmp)))))) (testing "namespace is restored after load file" (is (= 'start-ns (bb nil (format "(ns start-ns) (load-file \"%s\") (ns-name *ns*)" - (.getPath tmp)))))))) + (test-utils/escape-file-paths (.getPath tmp))))))))) -(deftest repl-source-test +(deftest ^:windows repl-source-test (let [tmp (java.io.File/createTempFile "lib" ".clj") name (str/replace (.getName tmp) ".clj" "") dir (.getParent tmp)] @@ -170,32 +170,33 @@ (defn foo [x y] (+ x y))" name)) (is (= "(defn foo [x y]\n (+ x y))\n" - (bb nil (format " + (test-utils/normalize + (bb nil (format " (load-file \"%s\") (require '[clojure.repl :refer [source]]) (with-out-str (source %s/foo))" - (.getPath tmp) - name))))) + (test-utils/escape-file-paths (.getPath tmp)) + name)))))) (testing "print source from file on classpath" (is (= "(defn foo [x y]\n (+ x y))\n" (test-utils/normalize - (bb nil - "-cp" dir - "-e" (format "(require '[clojure.repl :refer [source]] '[%s])" name) - "-e" (format "(with-out-str (source %s/foo))" name)))))))) + (bb nil + "-cp" dir + "-e" (format "(require '[clojure.repl :refer [source]] '[%s])" name) + "-e" (format "(with-out-str (source %s/foo))" name)))))))) -(deftest eval-test +(deftest ^:windows eval-test (is (= "120\n" (test-utils/bb nil "(eval '(do (defn foo [x y] (+ x y)) (defn bar [x y] (* x y)) (bar (foo 10 30) 3)))")))) -(deftest preloads-test +(deftest ^:windows preloads-test ;; THIS TEST REQUIRES: ;; export BABASHKA_PRELOADS='(defn __bb__foo [] "foo") (defn __bb__bar [] "bar")' (when (System/getenv "BABASHKA_PRELOADS_TEST") (is (= "foobar" (bb nil "(str (__bb__foo) (__bb__bar))"))))) -(deftest io-test +(deftest ^:windows io-test (is (true? (bb nil "(.exists (io/file \"README.md\"))"))) (is (true? (bb nil "(.canWrite (io/file \"README.md\"))")))) @@ -222,18 +223,21 @@ out (edn/read-string out)] (is (= '("y" "y") out))))) -(deftest future-test +(deftest ^:windows future-test (is (= 6 (bb nil "@(future (+ 1 2 3))")))) -(deftest promise-test +(deftest ^:windows promise-test (is (= :timeout (bb nil "(deref (promise) 1 :timeout)"))) (is (= :ok (bb nil "(let [x (promise)] (deliver x :ok) @x)")))) -(deftest process-builder-test - (is (str/includes? (bb nil " -(def pb (ProcessBuilder. [\"ls\"])) +(deftest ^:windows process-builder-test + (let [cmd-line (if main/windows? + "[\"cmd\" \"/c\" \"dir\" ]" + "[\"ls\"]")] + (is (str/includes? (bb nil (str " +(def pb (ProcessBuilder. " cmd-line ")) (def env (.environment pb)) (.put env \"FOO\" \"BAR\") ;; test for issue 460 (def ls (-> pb (.start))) @@ -241,14 +245,15 @@ (.write (io/writer input) \"hello\") ;; dummy test just to see if this works (def output (.getInputStream ls)) (assert (int? (.waitFor ls))) -(slurp output)") - "LICENSE")) +(slurp output)")) + "LICENSE"))) (testing "bb is able to kill subprocesses created by ProcessBuilder" (when test-utils/native? - (let [output (test-utils/bb nil (io/file "test" "babashka" "scripts" "kill_child_processes.bb")) + (let [process-count (if main/windows? 6 3) + output (test-utils/bb nil (io/file "test" "babashka" "scripts" "kill_child_processes.bb")) parsed (edn/read-string (format "[%s]" output))] (is (every? number? parsed)) - (is (= 3 (count parsed))))))) + (is (= process-count (count parsed))))))) (deftest create-temp-file-test (let [temp-dir-path (System/getProperty "java.io.tmpdir")] diff --git a/test/babashka/scripts/System.bb b/test/babashka/scripts/System.bb index bb9916cb..7fa71e5f 100644 --- a/test/babashka/scripts/System.bb +++ b/test/babashka/scripts/System.bb @@ -1,5 +1,5 @@ [(System/getProperty "user.dir") (System/getProperty "foo" "bar") - (System/getenv "HOME") + (or (System/getenv "HOME") (System/getenv "HOMEPATH")) (System/getProperties) (System/getenv)] diff --git a/test/babashka/test_utils.clj b/test/babashka/test_utils.clj index 79cd85c2..ca2ca749 100644 --- a/test/babashka/test_utils.clj +++ b/test/babashka/test_utils.clj @@ -19,6 +19,11 @@ (str/replace s "\r\n" "\n") s)) +(defn escape-file-paths [s] + (if main/windows? + (str/replace s "\\" "\\\\") + s)) + (def ^:dynamic *bb-edn-path* nil) (defmethod clojure.test/report :begin-test-var [m] @@ -86,7 +91,7 @@ exit (:exit res) error? (pos? exit)] (if error? (throw (ex-info (or (:err res) "") {})) - (:out res)))) + (normalize (:out res))))) (def bb (case (System/getenv "BABASHKA_TEST_ENV") From ce4702318a9afc31d747c2d13bd9cf0c238f58f2 Mon Sep 17 00:00:00 2001 From: Bob Date: Fri, 18 Jun 2021 17:51:46 -0400 Subject: [PATCH 03/65] add more windows testing (#894) - just handling line endings and escaping backslashes in file paths --- script/test.bat | 5 ++ test/babashka/main_test.clj | 133 +++++++++++++++++++----------------- 2 files changed, 75 insertions(+), 63 deletions(-) diff --git a/script/test.bat b/script/test.bat index 4a86f522..a29c6ffa 100755 --- a/script/test.bat +++ b/script/test.bat @@ -19,3 +19,8 @@ set BABASHKA_PRELOADS=(defn __bb__foo [] "foo") (defn __bb__bar [] "bar") set BABASHKA_PRELOADS_TEST=true echo "running tests part 2" call lein test :only babashka.main-test/preloads-test + +set BABASHKA_PRELOADS=(defn ithrow [] (/ 1 0)) +set BABASHKA_PRELOADS_TEST=true +echo "running tests part 3" +call lein test :only babashka.main-test/preloads-file-location-test diff --git a/test/babashka/main_test.clj b/test/babashka/main_test.clj index b296eacf..8b456e57 100644 --- a/test/babashka/main_test.clj +++ b/test/babashka/main_test.clj @@ -265,7 +265,7 @@ (.exists tfile))" temp-dir-path)))))) -(deftest wait-for-port-test +(deftest ^:windows wait-for-port-test (let [server (test-utils/start-server! 1777)] (is (= 1777 (:port (bb nil "(wait/wait-for-port \"127.0.0.1\" 1777)")))) (test-utils/stop-server! server) @@ -298,10 +298,10 @@ {:default :timed-out :timeout 100}))" temp-dir-path)))))) -(deftest tools-cli-test +(deftest ^:windows tools-cli-test (is (= {:result 8080} (bb nil "test/babashka/scripts/tools.cli.bb")))) -(deftest try-catch-test +(deftest ^:windows try-catch-test (is (zero? (bb nil "(try (/ 1 0) (catch ArithmeticException _ 0))"))) (is (= :got-it (bb nil " (defn foo [] @@ -315,29 +315,29 @@ (bar) ")))) -(deftest reader-conditionals-test +(deftest ^:windows reader-conditionals-test (is (= :hello (bb nil "#?(:bb :hello :default :bye)"))) (is (= :hello (bb nil "#? (:bb :hello :default :bye)"))) (is (= :hello (bb nil "#?(:clj :hello :bb :bye)"))) (is (= [1 2] (bb nil "[1 2 #?@(:bb [] :clj [1])]")))) -(deftest csv-test +(deftest ^:windows csv-test (is (= '(["Adult" "87727"] ["Elderly" "43914"] ["Child" "33411"] ["Adolescent" "29849"] ["Infant" "15238"] ["Newborn" "10050"] ["In Utero" "1198"]) (bb nil (.getPath (io/file "test" "babashka" "scripts" "csv.bb")))))) -(deftest assert-test ;; assert was first implemented in bb but moved to sci later +(deftest ^:windows assert-test ;; assert was first implemented in bb but moved to sci later (is (thrown-with-msg? Exception #"should-be-true" (bb nil "(def should-be-true false) (assert should-be-true)")))) -(deftest Pattern-test +(deftest ^:windows Pattern-test (is (= ["1" "2" "3"] (bb nil "(vec (.split (java.util.regex.Pattern/compile \"f\") \"1f2f3\"))"))) (is (true? (bb nil "(some? java.util.regex.Pattern/CANON_EQ)")))) -(deftest writer-test +(deftest ^:windows writer-test (let [tmp-file (java.io.File/createTempFile "bbb" "bbb") - path (.getPath tmp-file)] + path (test-utils/escape-file-paths (.getPath tmp-file))] (bb nil (format "(with-open [w (io/writer \"%s\")] (.write w \"foobar\n\") (.append w \"barfoo\n\") @@ -345,21 +345,23 @@ path)) (is (= "foobar\nbarfoo\n" (slurp path))))) -(deftest binding-test - (is (= 6 (bb nil "(def w (java.io.StringWriter.)) +(deftest ^:windows binding-test + (is (= (if main/windows? 7 6) + (bb nil "(def w (java.io.StringWriter.)) (binding [clojure.core/*out* w] (println \"hello\")) (count (str w))")))) -(deftest with-out-str-test - (is (= 6 (bb nil "(count (with-out-str (println \"hello\")))")))) +(deftest ^:windows with-out-str-test + (is (= (if main/windows? 7 6) + (bb nil "(count (with-out-str (println \"hello\")))")))) -(deftest with-in-str-test +(deftest ^:windows with-in-str-test (is (= 5 (bb nil "(count (with-in-str \"hello\" (read-line)))")))) -(deftest java-nio-test +(deftest ^:windows java-nio-test (let [f (java.io.File/createTempFile "foo" "bar") - temp-path (.getPath f) + temp-path (test-utils/escape-file-paths (.getPath f)) p (.toPath (io/file f)) p' (.resolveSibling p "f2") f2 (.toFile p')] @@ -379,59 +381,62 @@ (is (vector? v)) (is (.exists (io/file (first v))))))) -(deftest future-print-test +(deftest ^:windows future-print-test (testing "the root binding of sci/*out*" (is (= "hello" (bb nil "@(future (prn \"hello\"))"))))) -(deftest Math-test +(deftest ^:windows Math-test (is (== 8.0 (bb nil "(Math/pow 2 3)")))) -(deftest Base64-test +(deftest ^:windows Base64-test (is (= "babashka" (bb nil "(String. (.decode (java.util.Base64/getDecoder) (.encode (java.util.Base64/getEncoder) (.getBytes \"babashka\"))))")))) -(deftest Thread-test +(deftest ^:windows Thread-test (is (= "hello" (bb nil "(doto (java.lang.Thread. (fn [] (prn \"hello\"))) (.start) (.join)) nil")))) -(deftest dynvar-test +(deftest ^:windows dynvar-test (is (= 1 (bb nil "(binding [*command-line-args* 1] *command-line-args*)")))) -(deftest file-in-error-msg-test +(deftest ^:windows file-in-error-msg-test (is (thrown-with-msg? Exception #"error.bb" (bb nil (.getPath (io/file "test" "babashka" "scripts" "error.bb")))))) -(deftest compatibility-test +(deftest ^:windows compatibility-test (is (true? (bb nil "(set! *warn-on-reflection* true)")))) -(deftest clojure-main-repl-test - (is (= "\"> foo!\\nnil\\n> \"\n" (test-utils/bb nil " +(deftest ^:windows clojure-main-repl-test + (let [expected-outcome (if main/windows? + "\"> foo!\\r\\nnil\\r\\n> \"\n" + "\"> foo!\\nnil\\n> \"\n")] + (is (= expected-outcome (test-utils/bb nil " (defn foo [] (println \"foo!\")) (with-out-str (with-in-str \"(foo)\" - (clojure.main/repl :init (fn []) :prompt (fn [] (print \"> \")))))")))) + (clojure.main/repl :init (fn []) :prompt (fn [] (print \"> \")))))"))))) -(deftest command-line-args-test +(deftest ^:windows command-line-args-test (is (true? (bb nil "(nil? *command-line-args*)"))) (is (= ["1" "2" "3"] (bb nil "*command-line-args*" "1" "2" "3")))) -(deftest constructors-test +(deftest ^:windows constructors-test (testing "the clojure.lang.Delay constructor works" (is (= 1 (bb nil "@(delay 1)")))) (testing "the clojure.lang.MapEntry constructor works" (is (true? (bb nil "(= (first {1 2}) (clojure.lang.MapEntry. 1 2))"))))) -(deftest clojure-data-xml-test +(deftest ^:windows clojure-data-xml-test (is (= "12" (bb nil "(let [xml (xml/parse-str \"12\")] (xml/emit-str xml))"))) (is (= "0.0.87-SNAPSHOT" (bb nil "examples/pom_version_get.clj" (.getPath (io/file "test-resources" "pom.xml")))))) -(deftest uberscript-test +(deftest ^:windows uberscript-test (let [tmp-file (java.io.File/createTempFile "uberscript" ".clj")] (.deleteOnExit tmp-file) - (is (empty? (bb nil "--uberscript" (.getPath tmp-file) "-e" "(System/exit 1)"))) + (is (empty? (bb nil "--uberscript" (test-utils/escape-file-paths (.getPath tmp-file)) "-e" "(System/exit 1)"))) (is (= "(System/exit 1)" (slurp tmp-file))))) -(deftest unrestricted-access +(deftest ^:windows unrestricted-access (testing "babashka is allowed to mess with built-in vars" (is (= {} (bb nil " (def assoc2 assoc) (alter-var-root #'clojure.core/assoc (constantly dissoc)) @@ -439,27 +444,29 @@ (alter-var-root #'clojure.core/assoc (constantly assoc2)) res)"))))) -(deftest pprint-test +(deftest ^:windows pprint-test (testing "writer" (is (string? (bb nil "(let [sw (java.io.StringWriter.)] (clojure.pprint/pprint (range 10) sw) (str sw))")))) (testing "*print-right-margin*" - (is (= "(0\n 1\n 2\n 3\n 4\n 5\n 6\n 7\n 8\n 9)\n" (bb nil " + (is (= "(0\n 1\n 2\n 3\n 4\n 5\n 6\n 7\n 8\n 9)\n" + (test-utils/normalize (bb nil " (let [sw (java.io.StringWriter.)] (binding [clojure.pprint/*print-right-margin* 5] - (clojure.pprint/pprint (range 10) sw)) (str sw))"))) - (is (= "(0 1 2 3 4 5 6 7 8 9)\n" (bb nil " + (clojure.pprint/pprint (range 10) sw)) (str sw))")))) + (is (= "(0 1 2 3 4 5 6 7 8 9)\n" + (test-utils/normalize (bb nil " (let [sw (java.io.StringWriter.)] (binding [clojure.pprint/*print-right-margin* 50] - (clojure.pprint/pprint (range 10) sw)) (str sw))")))) + (clojure.pprint/pprint (range 10) sw)) (str sw))"))))) (testing "print-table writes to sci/out" (is (str/includes? (test-utils/bb "(with-out-str (clojure.pprint/print-table [{:a 1} {:a 2}]))") "----")))) -(deftest read-string-test +(deftest ^:windows read-string-test (testing "namespaced keyword via alias" (is (= :clojure.string/foo (bb nil "(ns foo (:require [clojure.string :as str])) (read-string \"::str/foo\")"))))) -(deftest available-stream-test +(deftest ^:windows available-stream-test (is (= 0 (bb nil "(.available System/in)")))) (deftest file-reader-test @@ -476,41 +483,41 @@ (catch Exception e (is (str/includes? (str e) "timed out")))))) -(deftest get-message-on-exception-info-test +(deftest ^:windows get-message-on-exception-info-test (is "foo" (bb nil "(try (throw (ex-info \"foo\" {})) (catch Exception e (.getMessage e)))"))) -(deftest pushback-reader-test +(deftest ^:windows pushback-reader-test (is (= "foo" (bb nil " (require '[clojure.java.io :as io]) (let [pb (java.io.PushbackInputStream. (java.io.ByteArrayInputStream. (.getBytes \"foo\")))] (.unread pb (.read pb)) (slurp pb))")))) -(deftest delete-on-exit-test +(deftest ^:windows delete-on-exit-test (when test-utils/native? (let [f (java.io.File/createTempFile "foo" "bar") - p (.getPath f)] + p (test-utils/escape-file-paths (.getPath f))] (bb nil (format "(.deleteOnExit (io/file \"%s\"))" p)) (is (false? (.exists f)))))) -(deftest yaml-test +(deftest ^:windows yaml-test (is (str/starts-with? (bb nil "(yaml/generate-string [{:name \"John Smith\", :age 33} {:name \"Mary Smith\", :age 27}])") "-"))) -(deftest arrays-copy-of-test +(deftest ^:windows arrays-copy-of-test (is (= "foo" (bb nil "(String. (java.util.Arrays/copyOf (.getBytes \"foo\") 3))")))) -(deftest data-readers-test +(deftest ^:windows data-readers-test (is (= 2 (bb nil "(set! *data-readers* {'t/tag inc}) #t/tag 1")))) -(deftest ordered-test +(deftest ^:windows ordered-test (is (= (ordered-map :a 1 :b 2) (bb nil "(flatland.ordered.map/ordered-map :a 1 :b 2)")))) -(deftest data-diff-test +(deftest ^:windows data-diff-test (is (= [[nil 1] [nil 2] [1 nil 2]] (bb nil "(require '[clojure.data :as d]) (d/diff [1 1 2] [1 2 2])")))) -(deftest version-property-test +(deftest ^:windows version-property-test (is (= "true\ntrue\nfalse\n" (test-utils/bb nil (.getPath (io/file "test-resources" "babashka" "version.clj")))))) @@ -520,13 +527,13 @@ (clojure.test/do-report {:type :pass, :message ~msg, :expected :success, :actual :success})))) -(deftest empty-expressions-test +(deftest ^:windows empty-expressions-test (testing "bb executes the empty file and doesn't start a REPL" (is (working? (test-utils/bb nil (.getPath (io/file "test-resources" "babashka" "empty.clj")))))) (testing "bb executes the empty expression and doesn't start a REPL" (is (working? (test-utils/bb nil "-e" ""))))) -(deftest file-property-test +(deftest ^:windows file-property-test (is (= "true\nfalse\n" (test-utils/bb nil (.getPath (io/file "test-resources" "babashka" "file_property1.clj"))))) (is (= "true\n" @@ -538,18 +545,18 @@ (is (apply = res)) (is (str/includes? (first res) "..")))) -(deftest file-location-test +(deftest ^:windows file-location-test (is (thrown-with-msg? Exception #"file_location2.clj" (test-utils/bb nil (.getPath (io/file "test-resources" "babashka" "file_location1.clj")))))) -(deftest preloads-file-location-test +(deftest ^:windows preloads-file-location-test (when (System/getenv "BABASHKA_PRELOADS_TEST") (is (thrown-with-msg? Exception #"preloads" (test-utils/bb nil (.getPath (io/file "test-resources" "babashka" "file_location_preloads.clj"))))))) -(deftest repl-test +(deftest ^:windows repl-test (is (str/includes? (test-utils/bb "(ns foo) ::foo" "--repl") ":foo/foo")) (is (str/includes? (test-utils/bb "[*warn-on-reflection* (set! *warn-on-reflection* true) *warn-on-reflection*]") "[false true true]")) @@ -559,14 +566,14 @@ (test-utils/bb {:in "x" :err sw} "--repl")) (is (str/includes? (str sw) "Could not resolve symbol: x [at :1:1]"))))) -(deftest java-stream-test +(deftest ^:windows java-stream-test (is (every? number? (bb nil "(take 2 (iterator-seq (.iterator (.doubles (java.util.Random.)))))")))) -(deftest read+string-test +(deftest ^:windows read+string-test (is (= '[:user/foo "::foo"] (bb nil "(read+string (clojure.lang.LineNumberingPushbackReader. (java.io.StringReader. \"::foo\")))")))) -(deftest iterable-test +(deftest ^:windows iterable-test (is (true? (bb nil " (defn iter [coll] (if (instance? java.lang.Iterable coll) @@ -576,16 +583,16 @@ (= [1 2 3] (iterator-seq (iter [1 2 3])))")))) -(deftest var-print-method-test +(deftest ^:windows var-print-method-test (when test-utils/native? (is (bb nil "(defmethod print-method sci.lang.IVar [o w] (.write w (str :foo (symbol o)))) (def x 1) (= \":foouser/x\" (pr-str #'x))")) (is (= :foouser/x (bb nil "(defmethod print-method sci.lang.IVar [o w] (.write w (str :foo (symbol o)))) (def x 1)"))))) -(deftest stdout-interop-test +(deftest ^:windows stdout-interop-test (when test-utils/native? (is (= 'Something (bb nil "(.print (System/out) \"Something\")"))))) -(deftest byte-buffer-test +(deftest ^:windows byte-buffer-test (testing "interop with HeapByteBuffer" (is (= 42 (bb nil "(count (.array (java.nio.ByteBuffer/allocate 42)))")))) (testing "interop with HeapByteByfferR" @@ -611,7 +618,7 @@ true")) (.force view) true"))) -(deftest secure-random-test +(deftest ^:windows secure-random-test (let [prog '(do (import 'java.security.SecureRandom 'java.util.Base64) (let [random (SecureRandom.) @@ -623,7 +630,7 @@ true"))) (generate-token))] (is (string? (bb nil (str prog)))))) -(deftest with-precision-test +(deftest ^:windows with-precision-test (is (= 0.33333333333333333333M (bb nil "(with-precision 20 (/ 1M 3))"))) (is (= 0.33333333333333333334M (bb nil "(with-precision 20 :rounding CEILING (/ 1M 3))")))) @@ -652,7 +659,7 @@ true"))) (bb nil "-e" "(.get (.command (.info (java.lang.ProcessHandle/current))))") "bb")))) -(deftest interop-concurrency-test +(deftest ^:windows interop-concurrency-test (is (= ["true" 3] (last (bb nil "-e" " (def f (fn [_] From cacb516e48cb3636ff91fa458eafcb453b56ed06 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Sat, 19 Jun 2021 14:00:12 +0200 Subject: [PATCH 04/65] sci: get rid of needs-ctx in evaluator --- sci | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sci b/sci index b211667c..9b1e2b03 160000 --- a/sci +++ b/sci @@ -1 +1 @@ -Subproject commit b211667c006b7e69115ad1b86f953612ccfbf932 +Subproject commit 9b1e2b03ee087241f66dc4cd74ecc317c75530b1 From 99c01b72616370807bc7691773f04f6b316a5745 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Sat, 19 Jun 2021 16:32:58 +0200 Subject: [PATCH 05/65] Add normalize-keywords example [skip ci] --- examples/README.md | 17 +++++++++++++++ examples/normalize-keywords.clj | 38 +++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 examples/normalize-keywords.clj diff --git a/examples/README.md b/examples/README.md index 37553d7a..e03d01d0 100644 --- a/examples/README.md +++ b/examples/README.md @@ -464,3 +464,20 @@ STDIN is TTY?: true STDOUT is TTY?: true STDERR is TTY?: false ``` + +## [normalize-keywords.clj](normalize-keywords.clj) + +Provide a Clojure file to the script and it will print the Clojure file with +auto-resolved keywords normalized to fully qualified ones: `::set/foo` becomes `:clojure.set/foo`. + +``` clojure +$ cat /tmp/test.clj +(ns test (:require [clojure.set :as set])) + +[::set/foo ::bar] + +$ bb examples/normalize-keywords.clj /tmp/test.clj +(ns test (:require [clojure.set :as set])) + +[:clojure.set/foo :test/bar] +``` diff --git a/examples/normalize-keywords.clj b/examples/normalize-keywords.clj new file mode 100644 index 00000000..b4b455c7 --- /dev/null +++ b/examples/normalize-keywords.clj @@ -0,0 +1,38 @@ +(ns normalize-keywords + (:require [babashka.pods :as pods] + [rewrite-clj.node :as node] + [rewrite-clj.zip :as z])) + +(pods/load-pod 'borkdude/clj-kondo "2021.06.18") + +(require '[pod.borkdude.clj-kondo :as clj-kondo]) + +(def code (first *command-line-args*)) + +(def findings + (->> (with-in-str code + (clj-kondo/run! {:lint [code] + :config {:output {:analysis {:keywords true}}}})) + :analysis + :keywords + (filter (some-fn :alias :auto-resolved)))) + +(defn finding->keyword [{:keys [:ns :name]}] + (keyword (str ns) (str name))) + +(defn remove-locs [zloc findings] + (loop [zloc zloc + findings (seq findings)] + (if findings + (let [{:keys [:row :col] :as finding} (first findings) + node (z/node zloc) + m (meta node)] + (if (and (= row (:row m)) + (= col (:col m))) + (let [k (finding->keyword finding) + zloc (z/replace zloc (node/coerce k))] + (recur zloc (next findings))) + (recur (z/next zloc) findings))) + (println (str (z/root zloc)))))) + +(remove-locs (z/of-file code) findings) From f6cd060c83af95d312672083d136587015b443a7 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Sat, 19 Jun 2021 16:39:55 +0200 Subject: [PATCH 06/65] doc [skip ci] --- examples/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/README.md b/examples/README.md index e03d01d0..001031ab 100644 --- a/examples/README.md +++ b/examples/README.md @@ -468,7 +468,8 @@ STDERR is TTY?: false ## [normalize-keywords.clj](normalize-keywords.clj) Provide a Clojure file to the script and it will print the Clojure file with -auto-resolved keywords normalized to fully qualified ones: `::set/foo` becomes `:clojure.set/foo`. +auto-resolved keywords normalized to fully qualified ones without double colons: +`::set/foo` becomes `:clojure.set/foo`. ``` clojure $ cat /tmp/test.clj From 55f9458f65ffa2f6cd14ba3b30e0897be3d990c1 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Sat, 19 Jun 2021 23:02:24 +0200 Subject: [PATCH 07/65] sci: minor map eval stuff --- sci | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sci b/sci index 9b1e2b03..4c0e8bb2 160000 --- a/sci +++ b/sci @@ -1 +1 @@ -Subproject commit 9b1e2b03ee087241f66dc4cd74ecc317c75530b1 +Subproject commit 4c0e8bb2afd940342445052eea9b64ba515c19dd From 35e2cd9d057cef8a634d409c51ce78763d5ed56e Mon Sep 17 00:00:00 2001 From: Bob Date: Sun, 20 Jun 2021 03:23:58 -0400 Subject: [PATCH 08/65] make tests run on windows as the default (#235) (#898) * make tests run on windows as the default - change from selecting tests to run to selecting tests to skip (remove all :windows tags, add :skip-windows tag to tests that don't currently work on windows) - handfuls of calls to `normalize` and `escape-file-paths` to handle platform differences - split `task-test` to make most of the tests run on windows, and exclude just a couple of Unix-y tests * make a binding name clearer * skip nrepl-server-test on Windows - test fails on CI, so disabling it for now * unset bb environment vars after running tests * unset bb environment var after running release-artifact BABASHKA_EDN being set can interfere with some tests, so unset it before running the native tests * skip uberjar test on Windows uberjar-test's 'throw on empty classpath' test failing on Windows native (but passes on JVM) - skip it for now --- appveyor.yml | 2 + project.clj | 2 +- script/test.bat | 29 ++- test/babashka/async_test.clj | 2 +- test/babashka/bb_edn_test.clj | 174 +++++++++--------- test/babashka/classpath_test.clj | 15 +- test/babashka/deps_test.clj | 4 +- test/babashka/error_test.clj | 12 +- .../babashka/impl/clojure/java/shell_test.clj | 2 +- test/babashka/impl/nrepl_server_test.clj | 2 +- test/babashka/main_test.clj | 150 +++++++-------- test/babashka/test_utils.clj | 15 +- test/babashka/transit_test.clj | 2 +- test/babashka/uberjar_test.clj | 14 +- test/babashka/udp_test.clj | 2 +- 15 files changed, 232 insertions(+), 195 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index b5e535ed..2650deff 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -65,6 +65,8 @@ build_script: bb release-artifact %zip% + set BABASHKA_EDN= + set BABASHKA_TEST_ENV=native call script/test.bat diff --git a/project.clj b/project.clj index 86cf3710..7e23b51a 100644 --- a/project.clj +++ b/project.clj @@ -14,7 +14,7 @@ ;; :java-source-paths ["sci/reflector/src-java"] :java-source-paths ["src-java"] :resource-paths ["resources" "sci/resources"] - :test-selectors {:windows :windows} + :test-selectors {:windows (complement :skip-windows)} :dependencies [[org.clojure/clojure "1.11.0-alpha1"] [borkdude/edamame "0.0.11"] [borkdude/graal.locking "0.0.2"] diff --git a/script/test.bat b/script/test.bat index a29c6ffa..2144ce6b 100755 --- a/script/test.bat +++ b/script/test.bat @@ -11,16 +11,39 @@ set PATH=%GRAALVM_HOME%\bin;%PATH% set BABASHKA_PRELOADS= set BABASHKA_CLASSPATH= set BABASHKA_PRELOADS_TEST= +set BABASHKA_CLASSPATH_TEST= +set BABASHKA_POD_TEST= +set BABASHKA_SOCKET_REPL_TEST= echo "running tests part 1" -call lein do clean, test :windows +call lein do clean, test :windows || exit /B 1 set BABASHKA_PRELOADS=(defn __bb__foo [] "foo") (defn __bb__bar [] "bar") set BABASHKA_PRELOADS_TEST=true echo "running tests part 2" -call lein test :only babashka.main-test/preloads-test +call lein test :only babashka.main-test/preloads-test || exit /B 1 set BABASHKA_PRELOADS=(defn ithrow [] (/ 1 0)) set BABASHKA_PRELOADS_TEST=true echo "running tests part 3" -call lein test :only babashka.main-test/preloads-file-location-test +call lein test :only babashka.main-test/preloads-file-location-test || exit /B 1 + +set BABASHKA_PRELOADS=(require '[env-ns]) +set BABASHKA_CLASSPATH_TEST=true +set BABASHKA_CLASSPATH=test-resources/babashka/src_for_classpath_test/env +echo "running tests part 4" +call lein test :only babashka.classpath-test/classpath-env-test || exit /B 1 + +echo "not running pod tests on windows (yet)" +REM set BABASHKA_POD_TEST=true +REM call lein test :only babashka.pod-test || exit /B 1 + +set BABASHKA_SOCKET_REPL_TEST=true +call lein test :only babashka.impl.socket-repl-test || exit /B 1 + +set BABASHKA_PRELOADS= +set BABASHKA_CLASSPATH= +set BABASHKA_PRELOADS_TEST= +set BABASHKA_CLASSPATH_TEST= +set BABASHKA_POD_TEST= +set BABASHKA_SOCKET_REPL_TEST= diff --git a/test/babashka/async_test.clj b/test/babashka/async_test.clj index 783e7788..f2be1a35 100644 --- a/test/babashka/async_test.clj +++ b/test/babashka/async_test.clj @@ -4,7 +4,7 @@ [clojure.edn :as edn] [clojure.test :as t :refer [deftest is]])) -(deftest alts!!-test +(deftest ^:skip-windows alts!!-test (is (= "process 2\n" (test-utils/bb nil " (defn async-command [& args] (async/thread (apply shell/sh \"bash\" \"-c\" args))) diff --git a/test/babashka/bb_edn_test.clj b/test/babashka/bb_edn_test.clj index 6c43a6ea..6c54d679 100644 --- a/test/babashka/bb_edn_test.clj +++ b/test/babashka/bb_edn_test.clj @@ -37,54 +37,66 @@ (deftest task-test (test-utils/with-config '{:tasks {foo (+ 1 2 3)}} (is (= 6 (bb "run" "--prn" "foo")))) - (let [tmp-dir (fs/create-temp-dir) - out (str (fs/file tmp-dir "out.txt"))] + (testing "init test" + (test-utils/with-config '{:tasks {:init (def x 1) + foo x}} + (is (= 1 (bb "run" "--prn" "foo"))))) + (testing "requires test" + (test-utils/with-config '{:tasks {:requires ([babashka.fs :as fs]) + foo (fs/exists? ".")}} + (is (= true (bb "run" "--prn" "foo")))) + (test-utils/with-config '{:tasks {foo {:requires ([babashka.fs :as fs]) + :task (fs/exists? ".")}}} + (is (= true (bb "run" "--prn" "foo")))) + (test-utils/with-config '{:tasks {bar {:requires ([babashka.fs :as fs])} + foo {:depends [bar] + :task (fs/exists? ".")}}} + (is (= true (bb "run" "--prn" "foo"))))) + (testing "map returned from task" + (test-utils/with-config '{:tasks {foo {:task {:a 1 :b 2}}}} + (is (= {:a 1 :b 2} (bb "run" "--prn" "foo"))))) + (let [tmp-dir (fs/create-temp-dir) + out (str (fs/file tmp-dir "out.txt")) + echo-cmd (if main/windows? "cmd /c echo" "echo") + ls-cmd (if main/windows? "cmd /c dir" "ls") + fix-lines test-utils/normalize] (testing "shell test" (test-utils/with-config {:tasks {'foo (list 'shell {:out out} - "echo hello")}} + echo-cmd "hello")}} (bb "foo") - (is (= "hello\n" (slurp out))))) - (fs/delete out) - (testing "shell test with :continue" - (test-utils/with-config {:tasks {'foo (list 'shell {:out out - :err out - :continue true} - "ls foobar")}} - (bb "foo") - (is (str/includes? (slurp out) - "foobar")))) + (is (= "hello\n" (fix-lines (slurp out)))))) (fs/delete out) (testing "shell test with :continue fn" (test-utils/with-config {:tasks {'foo (list '-> (list 'shell {:out out :err out :continue '(fn [proc] (contains? proc :exit))} - "ls foobar") - :exit)}} + ls-cmd "foobar") + :exit)}} (is (pos? (bb "run" "--prn" "foo"))))) (testing "shell test with :error" (test-utils/with-config {:tasks {'foo (list '-> (list 'shell {:out out :err out - :error-fn '(constantly 1337) } - "ls foobar"))}} + :error-fn '(constantly 1337)} + ls-cmd "foobar"))}} (is (= 1337 (bb "run" "--prn" "foo")))) (test-utils/with-config - {:tasks {'foo (list '-> (list 'shell {:out out - :err out + {:tasks {'foo (list '-> (list 'shell {:out out + :err out :error-fn - '(fn [opts] - (and (:task opts) - (:proc opts) - (not (zero? (:exit (:proc opts))))))} - "ls foobar"))}} + '(fn [opts] + (and (:task opts) + (:proc opts) + (not (zero? (:exit (:proc opts))))))} + ls-cmd "foobar"))}} (is (true? (bb "run" "--prn" "foo"))))) (fs/delete out) (testing "clojure test" (test-utils/with-config {:tasks {'foo (list 'clojure {:out out} - "-M -e" "(println :yolo)")}} + "-M -e" "(println :yolo)")}} (bb "foo") - (is (= ":yolo\n" (slurp out))))) + (is (= ":yolo\n" (fix-lines (slurp out)))))) (fs/delete out) (testing "depends" (test-utils/with-config {:tasks {'quux (list 'spit out "quux\n") @@ -107,24 +119,6 @@ :task (list 'spit out "foo\n" :append true)}}} (bb "foo") (is (= "quux\nbaz\nbar\nfoo\n" (slurp out)))))) - (testing "init test" - (test-utils/with-config '{:tasks {:init (def x 1) - foo x}} - (is (= 1 (bb "run" "--prn" "foo"))))) - (testing "requires test" - (test-utils/with-config '{:tasks {:requires ([babashka.fs :as fs]) - foo (fs/exists? ".")}} - (is (= true (bb "run" "--prn" "foo")))) - (test-utils/with-config '{:tasks {foo {:requires ([babashka.fs :as fs]) - :task (fs/exists? ".")}}} - (is (= true (bb "run" "--prn" "foo")))) - (test-utils/with-config '{:tasks {bar {:requires ([babashka.fs :as fs])} - foo {:depends [bar] - :task (fs/exists? ".")}}} - (is (= true (bb "run" "--prn" "foo"))))) - (testing "map returned from task" - (test-utils/with-config '{:tasks {foo {:task {:a 1 :b 2}}}} - (is (= {:a 1 :b 2} (bb "run" "--prn" "foo"))))) (testing "fully qualified symbol execution" (test-utils/with-config {:paths ["test-resources/task_scripts"] :tasks '{foo tasks/foo}} @@ -167,27 +161,27 @@ (testing "no such task" (test-utils/with-config '{:tasks {a (+ 1 2 3)}} (is (thrown-with-msg? - Exception #"No such task: b" - (bb "run" "b"))))) + Exception #"No such task: b" + (bb "run" "b"))))) (testing "unresolved dependency" (test-utils/with-config '{:tasks {a (+ 1 2 3) b {:depends [x] :task (+ a 4 5 6)}}} (is (thrown-with-msg? - Exception #"No such task: x" - (bb "run" "b"))))) + Exception #"No such task: x" + (bb "run" "b"))))) (testing "cyclic task" (test-utils/with-config '{:tasks {b {:depends [b] :task (+ a 4 5 6)}}} (is (thrown-with-msg? - Exception #"Cyclic task: b" - (bb "run" "b")))) + Exception #"Cyclic task: b" + (bb "run" "b")))) (test-utils/with-config '{:tasks {c {:depends [b]} b {:depends [c] :task (+ a 4 5 6)}}} (is (thrown-with-msg? - Exception #"Cyclic task: b" - (bb "run" "b"))))) + Exception #"Cyclic task: b" + (bb "run" "b"))))) (testing "doc" (test-utils/with-config '{:tasks {b {:doc "Beautiful docstring"}}} (let [s (test-utils/bb nil "doc" "b")] @@ -196,25 +190,18 @@ (test-utils/with-config '{:tasks {b (System/getProperty "babashka.task")}} (let [s (bb "run" "--prn" "b")] (is (= "b" s))))) - (testing "shell pipe test" - (test-utils/with-config '{:tasks {a (-> (shell {:out :string} - "echo hello") - (shell {:out :string} "cat") - :out)}} - (let [s (bb "run" "--prn" "a")] - (is (= "hello\n" s))))) (testing "parallel test" (test-utils/with-config (edn/read-string (slurp "test-resources/coffee-tasks.edn")) - (let [tree [:made-coffee [[:ground-beans [:measured-beans]] [:heated-water [:poured-water]] :filter :mug]] - t0 (System/currentTimeMillis) - s (bb "run" "--prn" "coffeep") - t1 (System/currentTimeMillis) + (let [tree [:made-coffee [[:ground-beans [:measured-beans]] [:heated-water [:poured-water]] :filter :mug]] + t0 (System/currentTimeMillis) + s (bb "run" "--prn" "coffeep") + t1 (System/currentTimeMillis) delta-sequential (- t1 t0)] (is (= tree s)) (test-utils/with-config (edn/read-string (slurp "test-resources/coffee-tasks.edn")) - (let [t0 (System/currentTimeMillis) - s (bb "run" "--parallel" "--prn" "coffeep") - t1 (System/currentTimeMillis) + (let [t0 (System/currentTimeMillis) + s (bb "run" "--parallel" "--prn" "coffeep") + t1 (System/currentTimeMillis) delta-parallel (- t1 t0)] (is (= tree s)) (is (< delta-parallel delta-sequential)))))) @@ -224,40 +211,61 @@ (throw (ex-info "0 noes" {}))) c {:depends [a b]}}} (is (thrown-with-msg? Exception #"0 noes" - (bb "run" "--parallel" "c"))))) + (bb "run" "--parallel" "c"))))) (testing "edge case" (test-utils/with-config '{:tasks {a (run '-a {:parallel true}) -a {:depends [a:a a:b c] - :task (prn [a:a a:b c])} + :task (prn [a:a a:b c])} a:a {:depends [c] - :task (+ 1 2 3)} + :task (+ 1 2 3)} a:b {:depends [c] - :task (do (Thread/sleep 10) - (+ 1 2 3))} - c (do (Thread/sleep 10) :c)}} + :task (do (Thread/sleep 10) + (+ 1 2 3))} + c (do (Thread/sleep 10) :c)}} (is (= [6 6 :c] (bb "run" "--prn" "a")))))) (testing "dynamic vars" (test-utils/with-config '{:tasks {:init (def ^:dynamic *foo* true) - a (do - (def ^:dynamic *bar* false) - (binding [*foo* false - *bar* true] - [*foo* *bar*]))}} + a (do + (def ^:dynamic *bar* false) + (binding [*foo* false + *bar* true] + [*foo* *bar*]))}} (is (= [false true] (bb "run" "--prn" "a"))))) (testing "stable namespace name" (test-utils/with-config '{:tasks - {:init (do (def ^:dynamic *jdk*) - (def ^:dynamic *server*)) - server [*jdk* *server*] - run-all (for [jdk [8 11 15] + {:init (do (def ^:dynamic *jdk*) + (def ^:dynamic *server*)) + server [*jdk* *server*] + run-all (for [jdk [8 11 15] server [:foo :bar]] - (binding [*jdk* jdk + (binding [*jdk* jdk *server* server] (babashka.tasks/run 'server)))}} (is (= '([8 :foo] [8 :bar] [11 :foo] [11 :bar] [15 :foo] [15 :bar]) - (bb "run" "--prn" "run-all")))))) + (bb "run" "--prn" "run-all")))))) + + +(deftest ^:skip-windows unix-task-test + (let [tmp-dir (fs/create-temp-dir) + out (str (fs/file tmp-dir "out.txt"))] + (testing "shell test with :continue" + (test-utils/with-config {:tasks {'foo (list 'shell {:out out + :err out + :continue true} + "ls foobar")}} + (bb "foo") + (is (str/includes? (slurp out) + "foobar")))) + (fs/delete out)) + (testing "shell pipe test" + (test-utils/with-config '{:tasks {a (-> (shell {:out :string} + "echo hello") + (shell {:out :string} "cat") + :out)}} + (let [s (bb "run" "--prn" "a")] + (is (= "hello\n" s)))))) (deftest list-tasks-test (test-utils/with-config {} diff --git a/test/babashka/classpath_test.clj b/test/babashka/classpath_test.clj index de8cfab3..ae04e945 100644 --- a/test/babashka/classpath_test.clj +++ b/test/babashka/classpath_test.clj @@ -9,6 +9,8 @@ (defn bb [input & args] (edn/read-string (apply tu/bb (when (some? input) (str input)) (map str args)))) +(def path-sep (System/getProperty "path.separator")) + (deftest classpath-test (is (= :my-script/bb (bb nil "--classpath" "test-resources/babashka/src_for_classpath_test" @@ -24,12 +26,12 @@ (is (= "test-resources" (bb nil "--classpath" "test-resources" "(require '[babashka.classpath :as cp]) (cp/get-classpath)"))) - (is (= "test-resources:foobar" - (bb nil "--classpath" "test-resources" - "(require '[babashka.classpath :as cp]) (cp/add-classpath \"foobar\") (cp/get-classpath)"))) + (is (= (str/join path-sep ["test-resources" "foobar"]) + (bb nil "--classpath" "test-resources" + "(require '[babashka.classpath :as cp]) (cp/add-classpath \"foobar\") (cp/get-classpath)"))) (is (= ["foo" "bar"] - (bb nil "--classpath" "foo:bar" - "(require '[babashka.classpath :as cp]) (cp/split-classpath (cp/get-classpath))")))) + (bb nil "--classpath" (str/join path-sep ["foo" "bar"]) + "(require '[babashka.classpath :as cp]) (cp/split-classpath (cp/get-classpath))")))) (deftest classpath-env-test ;; for this test you have to set `BABASHKA_CLASSPATH` to test-resources/babashka/src_for_classpath_test/env @@ -57,7 +59,8 @@ (deftest resource-test (let [tmp-file (java.io.File/createTempFile "icon" ".png")] (.deleteOnExit tmp-file) - (bb nil "--classpath" "logo" "-e" (format "(io/copy (io/input-stream (io/resource \"icon.png\")) (io/file \"%s\"))" (.getPath tmp-file))) + (bb nil "--classpath" "logo" "-e" (format "(io/copy (io/input-stream (io/resource \"icon.png\")) (io/file \"%s\"))" + (tu/escape-file-paths (.getPath tmp-file)))) (is (= (.length (io/file "logo" "icon.png")) (.length tmp-file)))) (testing "No exception on absolute path" diff --git a/test/babashka/deps_test.clj b/test/babashka/deps_test.clj index c7c5d448..d8f083c9 100644 --- a/test/babashka/deps_test.clj +++ b/test/babashka/deps_test.clj @@ -42,14 +42,14 @@ (babashka.deps/clojure [\"-P\"]) true ")))) - (is (= "6\n" (bb " + (is (= "6\n" (test-utils/normalize (bb " (require '[babashka.deps :as deps]) (require '[babashka.process :as p]) (-> (babashka.deps/clojure [\"-M\" \"-e\" \"(+ 1 2 3)\"] {:out :string}) (p/check) :out) -"))) +")))) (when-not test-utils/native? (is (thrown-with-msg? Exception #"Option changed" (bb " (require '[babashka.deps :as deps]) diff --git a/test/babashka/error_test.clj b/test/babashka/error_test.clj index 25914e35..064290ff 100644 --- a/test/babashka/error_test.clj +++ b/test/babashka/error_test.clj @@ -40,7 +40,7 @@ (defn foo [] (/ 1 0)) (foo)") (catch Exception e (ex-message e)))] - (is (str/includes? output "----- Stack trace -------------------------------------------------------------- + (is (str/includes? (tu/normalize output) "----- Stack trace -------------------------------------------------------------- clojure.core// - user/foo - :2:14 user/foo - :2:1 @@ -51,7 +51,7 @@ user - :3:1")))) (defn foo [] (/ 1 0)) (foo)") (catch Exception e (ex-message e)))] - (is (str/includes? output "----- Context ------------------------------------------------------------------ + (is (str/includes? (tu/normalize output) "----- Context ------------------------------------------------------------------ 1: 2: (defn foo [] (/ 1 0)) ^--- Divide by zero @@ -60,14 +60,14 @@ user - :3:1")))) (deftest parse-error-context-test (let [output (try (tu/bb nil "{:a}") (catch Exception e (ex-message e)))] - (is (str/includes? output "----- Context ------------------------------------------------------------------ + (is (str/includes? (tu/normalize output) "----- Context ------------------------------------------------------------------ 1: {:a} ^--- The map literal starting with :a contains 1 form(s).")))) (deftest jar-error-test (let [output (try (tu/bb nil "-cp" (.getPath (io/file "test-resources" "divide_by_zero.jar")) "-e" "(require 'foo)") (catch Exception e (ex-message e)))] - (is (str/includes? output "----- Error -------------------------------------------------------------------- + (is (str/includes? (tu/normalize output) "----- Error -------------------------------------------------------------------- Type: java.lang.ArithmeticException Message: Divide by zero Location: foo.clj:1:10 @@ -83,7 +83,7 @@ foo - foo.clj:1:10")))) (deftest static-call-test (let [output (try (tu/bb nil "-e" "File/x") (catch Exception e (ex-message e)))] - (is (str/includes? output + (is (str/includes? (tu/normalize output) "----- Error -------------------------------------------------------------------- Type: java.lang.IllegalArgumentException Message: No matching field found: x for class java.io.File @@ -97,7 +97,7 @@ Location: :1:1 user - :1:1")) (let [output (try (tu/bb nil "-e" "(File/x)") (catch Exception e (ex-message e)))] - (is (str/includes? output + (is (str/includes? (tu/normalize output) "----- Error -------------------------------------------------------------------- Type: java.lang.IllegalArgumentException Message: No matching method x found taking 0 args diff --git a/test/babashka/impl/clojure/java/shell_test.clj b/test/babashka/impl/clojure/java/shell_test.clj index 0f1cd8db..1f8e75fb 100644 --- a/test/babashka/impl/clojure/java/shell_test.clj +++ b/test/babashka/impl/clojure/java/shell_test.clj @@ -3,7 +3,7 @@ [babashka.test-utils :as test-utils] [clojure.string :as str])) -(deftest with-sh-env-test +(deftest ^:skip-windows with-sh-env-test (is (= "\"BAR\"" (str/trim (test-utils/bb nil " (-> (shell/with-sh-env {:FOO \"BAR\"} diff --git a/test/babashka/impl/nrepl_server_test.clj b/test/babashka/impl/nrepl_server_test.clj index 822fb802..3367e89e 100644 --- a/test/babashka/impl/nrepl_server_test.clj +++ b/test/babashka/impl/nrepl_server_test.clj @@ -182,7 +182,7 @@ (let [reply (read-reply in session @id)] (is (= "Hello\n" (tu/normalize (:out reply)))))))))) -(deftest nrepl-server-test +(deftest ^:skip-windows nrepl-server-test (let [proc-state (atom nil) server-state (atom nil)] (try diff --git a/test/babashka/main_test.clj b/test/babashka/main_test.clj index 8b456e57..d2e83fe4 100644 --- a/test/babashka/main_test.clj +++ b/test/babashka/main_test.clj @@ -17,7 +17,7 @@ :eof nil} (apply test-utils/bb (when (some? input) (str input)) (map str args)))) -(deftest ^:windows parse-opts-test +(deftest parse-opts-test (is (= "1667" (:nrepl (main/parse-opts ["--nrepl-server"])))) (is (= "1666" @@ -55,18 +55,18 @@ (is (:feature/xml v)))) -(deftest ^:windows version-test +(deftest version-test (is (= [1 0 0] (main/parse-version "1.0.0-SNAPSHOT"))) (is (main/satisfies-min-version? "0.1.0")) (is (main/satisfies-min-version? "0.1.0-SNAPSHOT")) (is (not (main/satisfies-min-version? "300.0.0"))) (is (not (main/satisfies-min-version? "300.0.0-SNAPSHOT")))) -(deftest ^:windows print-error-test +(deftest print-error-test (is (thrown-with-msg? Exception #"java.lang.NullPointerException" (bb nil "(subs nil 0 0)")))) -(deftest ^:windows input-test +(deftest input-test (testing "-io behaves as identity" (is (= "foo\nbar\n" (test-utils/bb "foo\nbar\n" "-io" "*input*")))) (testing "if and when" @@ -122,24 +122,24 @@ (testing "bb doesn't wait for input if *input* isn't used" (is (= "2\n" (test-utils/normalize (with-out-str (main/main "(inc 1)"))))))) -(deftest ^:windows println-test +(deftest println-test (is (= "hello\n" (test-utils/bb nil "(println \"hello\")")))) -(deftest ^:windows System-test +(deftest System-test (let [res (bb nil "-f" "test/babashka/scripts/System.bb")] (is (= "bar" (second res))) (doseq [s res] (is (not-empty s))))) -(deftest ^:windows malformed-command-line-args-test +(deftest malformed-command-line-args-test (is (thrown-with-msg? Exception #"File does not exist: non-existing" (bb nil "-f" "non-existing")))) -(deftest ^:windows ssl-test +(deftest ssl-test (let [resp (bb nil "(slurp \"https://www.google.com\")")] (is (re-find #"doctype html" resp)))) -(deftest ^:windows stream-test +(deftest stream-test (is (= "2\n3\n4\n" (test-utils/bb "1 2 3" "--stream" "(inc *input*)"))) (is (= "2\n3\n4\n" (test-utils/bb "{:x 2} {:x 3} {:x 4}" "--stream" "(:x *input*)"))) (let [x "foo\n\bar\n"] @@ -147,7 +147,7 @@ (let [x "f\n\b\n"] (is (= x (test-utils/bb x "--stream" "-io" "(subs *input* 0 1)"))))) -(deftest ^:windows load-file-test +(deftest load-file-test (let [tmp (java.io.File/createTempFile "script" ".clj")] (.deleteOnExit tmp) (spit tmp "(ns foo) (defn foo [x y] (+ x y)) (defn bar [x y] (* x y))") @@ -158,7 +158,7 @@ (bb nil (format "(ns start-ns) (load-file \"%s\") (ns-name *ns*)" (test-utils/escape-file-paths (.getPath tmp))))))))) -(deftest ^:windows repl-source-test +(deftest repl-source-test (let [tmp (java.io.File/createTempFile "lib" ".clj") name (str/replace (.getName tmp) ".clj" "") dir (.getParent tmp)] @@ -185,22 +185,22 @@ "-e" (format "(require '[clojure.repl :refer [source]] '[%s])" name) "-e" (format "(with-out-str (source %s/foo))" name)))))))) -(deftest ^:windows eval-test +(deftest eval-test (is (= "120\n" (test-utils/bb nil "(eval '(do (defn foo [x y] (+ x y)) (defn bar [x y] (* x y)) (bar (foo 10 30) 3)))")))) -(deftest ^:windows preloads-test +(deftest preloads-test ;; THIS TEST REQUIRES: ;; export BABASHKA_PRELOADS='(defn __bb__foo [] "foo") (defn __bb__bar [] "bar")' (when (System/getenv "BABASHKA_PRELOADS_TEST") (is (= "foobar" (bb nil "(str (__bb__foo) (__bb__bar))"))))) -(deftest ^:windows io-test +(deftest io-test (is (true? (bb nil "(.exists (io/file \"README.md\"))"))) (is (true? (bb nil "(.canWrite (io/file \"README.md\"))")))) -(deftest pipe-test +(deftest ^:skip-windows pipe-test (when (and test-utils/native? (not main/windows?)) (let [out (:out (sh "bash" "-c" "./bb -o '(range)' | @@ -217,22 +217,22 @@ out (edn/read-string out)] (is (= '("duderino" "duderino" "duderino") out))))) -(deftest lazy-text-in-test +(deftest ^:skip-windows lazy-text-in-test (when test-utils/native? (let [out (:out (sh "bash" "-c" "yes | ./bb -i '(take 2 *input*)'")) out (edn/read-string out)] (is (= '("y" "y") out))))) -(deftest ^:windows future-test +(deftest future-test (is (= 6 (bb nil "@(future (+ 1 2 3))")))) -(deftest ^:windows promise-test +(deftest promise-test (is (= :timeout (bb nil "(deref (promise) 1 :timeout)"))) (is (= :ok (bb nil "(let [x (promise)] (deliver x :ok) @x)")))) -(deftest ^:windows process-builder-test +(deftest process-builder-test (let [cmd-line (if main/windows? "[\"cmd\" \"/c\" \"dir\" ]" "[\"ls\"]")] @@ -255,7 +255,7 @@ (is (every? number? parsed)) (is (= process-count (count parsed))))))) -(deftest create-temp-file-test +(deftest ^:skip-windows create-temp-file-test (let [temp-dir-path (System/getProperty "java.io.tmpdir")] (is (= true (bb nil (format "(let [tdir (io/file \"%s\") @@ -265,7 +265,7 @@ (.exists tfile))" temp-dir-path)))))) -(deftest ^:windows wait-for-port-test +(deftest wait-for-port-test (let [server (test-utils/start-server! 1777)] (is (= 1777 (:port (bb nil "(wait/wait-for-port \"127.0.0.1\" 1777)")))) (test-utils/stop-server! server) @@ -275,7 +275,7 @@ (is (= 1777 (:port edn))) (is (number? (:took edn))))) -(deftest wait-for-path-test +(deftest ^:skip-windows wait-for-path-test (let [temp-dir-path (System/getProperty "java.io.tmpdir")] (is (not= :timed-out (bb nil (format "(let [tdir (io/file \"%s\") @@ -298,10 +298,10 @@ {:default :timed-out :timeout 100}))" temp-dir-path)))))) -(deftest ^:windows tools-cli-test +(deftest tools-cli-test (is (= {:result 8080} (bb nil "test/babashka/scripts/tools.cli.bb")))) -(deftest ^:windows try-catch-test +(deftest try-catch-test (is (zero? (bb nil "(try (/ 1 0) (catch ArithmeticException _ 0))"))) (is (= :got-it (bb nil " (defn foo [] @@ -315,27 +315,27 @@ (bar) ")))) -(deftest ^:windows reader-conditionals-test +(deftest reader-conditionals-test (is (= :hello (bb nil "#?(:bb :hello :default :bye)"))) (is (= :hello (bb nil "#? (:bb :hello :default :bye)"))) (is (= :hello (bb nil "#?(:clj :hello :bb :bye)"))) (is (= [1 2] (bb nil "[1 2 #?@(:bb [] :clj [1])]")))) -(deftest ^:windows csv-test +(deftest csv-test (is (= '(["Adult" "87727"] ["Elderly" "43914"] ["Child" "33411"] ["Adolescent" "29849"] ["Infant" "15238"] ["Newborn" "10050"] ["In Utero" "1198"]) (bb nil (.getPath (io/file "test" "babashka" "scripts" "csv.bb")))))) -(deftest ^:windows assert-test ;; assert was first implemented in bb but moved to sci later +(deftest assert-test ;; assert was first implemented in bb but moved to sci later (is (thrown-with-msg? Exception #"should-be-true" (bb nil "(def should-be-true false) (assert should-be-true)")))) -(deftest ^:windows Pattern-test +(deftest Pattern-test (is (= ["1" "2" "3"] (bb nil "(vec (.split (java.util.regex.Pattern/compile \"f\") \"1f2f3\"))"))) (is (true? (bb nil "(some? java.util.regex.Pattern/CANON_EQ)")))) -(deftest ^:windows writer-test +(deftest writer-test (let [tmp-file (java.io.File/createTempFile "bbb" "bbb") path (test-utils/escape-file-paths (.getPath tmp-file))] (bb nil (format "(with-open [w (io/writer \"%s\")] @@ -345,21 +345,21 @@ path)) (is (= "foobar\nbarfoo\n" (slurp path))))) -(deftest ^:windows binding-test +(deftest binding-test (is (= (if main/windows? 7 6) (bb nil "(def w (java.io.StringWriter.)) (binding [clojure.core/*out* w] (println \"hello\")) (count (str w))")))) -(deftest ^:windows with-out-str-test +(deftest with-out-str-test (is (= (if main/windows? 7 6) (bb nil "(count (with-out-str (println \"hello\")))")))) -(deftest ^:windows with-in-str-test +(deftest with-in-str-test (is (= 5 (bb nil "(count (with-in-str \"hello\" (read-line)))")))) -(deftest ^:windows java-nio-test +(deftest java-nio-test (let [f (java.io.File/createTempFile "foo" "bar") temp-path (test-utils/escape-file-paths (.getPath f)) p (.toPath (io/file f)) @@ -381,31 +381,31 @@ (is (vector? v)) (is (.exists (io/file (first v))))))) -(deftest ^:windows future-print-test +(deftest future-print-test (testing "the root binding of sci/*out*" (is (= "hello" (bb nil "@(future (prn \"hello\"))"))))) -(deftest ^:windows Math-test +(deftest Math-test (is (== 8.0 (bb nil "(Math/pow 2 3)")))) -(deftest ^:windows Base64-test +(deftest Base64-test (is (= "babashka" (bb nil "(String. (.decode (java.util.Base64/getDecoder) (.encode (java.util.Base64/getEncoder) (.getBytes \"babashka\"))))")))) -(deftest ^:windows Thread-test +(deftest Thread-test (is (= "hello" (bb nil "(doto (java.lang.Thread. (fn [] (prn \"hello\"))) (.start) (.join)) nil")))) -(deftest ^:windows dynvar-test +(deftest dynvar-test (is (= 1 (bb nil "(binding [*command-line-args* 1] *command-line-args*)")))) -(deftest ^:windows file-in-error-msg-test +(deftest file-in-error-msg-test (is (thrown-with-msg? Exception #"error.bb" (bb nil (.getPath (io/file "test" "babashka" "scripts" "error.bb")))))) -(deftest ^:windows compatibility-test +(deftest compatibility-test (is (true? (bb nil "(set! *warn-on-reflection* true)")))) -(deftest ^:windows clojure-main-repl-test +(deftest clojure-main-repl-test (let [expected-outcome (if main/windows? "\"> foo!\\r\\nnil\\r\\n> \"\n" "\"> foo!\\nnil\\n> \"\n")] @@ -415,28 +415,28 @@ (with-in-str \"(foo)\" (clojure.main/repl :init (fn []) :prompt (fn [] (print \"> \")))))"))))) -(deftest ^:windows command-line-args-test +(deftest command-line-args-test (is (true? (bb nil "(nil? *command-line-args*)"))) (is (= ["1" "2" "3"] (bb nil "*command-line-args*" "1" "2" "3")))) -(deftest ^:windows constructors-test +(deftest constructors-test (testing "the clojure.lang.Delay constructor works" (is (= 1 (bb nil "@(delay 1)")))) (testing "the clojure.lang.MapEntry constructor works" (is (true? (bb nil "(= (first {1 2}) (clojure.lang.MapEntry. 1 2))"))))) -(deftest ^:windows clojure-data-xml-test +(deftest clojure-data-xml-test (is (= "12" (bb nil "(let [xml (xml/parse-str \"12\")] (xml/emit-str xml))"))) (is (= "0.0.87-SNAPSHOT" (bb nil "examples/pom_version_get.clj" (.getPath (io/file "test-resources" "pom.xml")))))) -(deftest ^:windows uberscript-test +(deftest uberscript-test (let [tmp-file (java.io.File/createTempFile "uberscript" ".clj")] (.deleteOnExit tmp-file) (is (empty? (bb nil "--uberscript" (test-utils/escape-file-paths (.getPath tmp-file)) "-e" "(System/exit 1)"))) (is (= "(System/exit 1)" (slurp tmp-file))))) -(deftest ^:windows unrestricted-access +(deftest unrestricted-access (testing "babashka is allowed to mess with built-in vars" (is (= {} (bb nil " (def assoc2 assoc) (alter-var-root #'clojure.core/assoc (constantly dissoc)) @@ -444,7 +444,7 @@ (alter-var-root #'clojure.core/assoc (constantly assoc2)) res)"))))) -(deftest ^:windows pprint-test +(deftest pprint-test (testing "writer" (is (string? (bb nil "(let [sw (java.io.StringWriter.)] (clojure.pprint/pprint (range 10) sw) (str sw))")))) (testing "*print-right-margin*" @@ -461,21 +461,21 @@ (testing "print-table writes to sci/out" (is (str/includes? (test-utils/bb "(with-out-str (clojure.pprint/print-table [{:a 1} {:a 2}]))") "----")))) -(deftest ^:windows read-string-test +(deftest read-string-test (testing "namespaced keyword via alias" (is (= :clojure.string/foo (bb nil "(ns foo (:require [clojure.string :as str])) (read-string \"::str/foo\")"))))) -(deftest ^:windows available-stream-test +(deftest available-stream-test (is (= 0 (bb nil "(.available System/in)")))) -(deftest file-reader-test +(deftest ^:skip-windows file-reader-test (when (str/includes? (str/lower-case (System/getProperty "os.name")) "linux") (let [v (bb nil "(slurp (io/reader (java.io.FileReader. \"/proc/loadavg\")))")] (prn "output:" v) (is v)))) -(deftest download-and-extract-test +(deftest ^:skip-windows download-and-extract-test ;; Disabled because Github throttles bandwidth and this makes for a very slow test. ;; TODO: refactor into individual unit tests ;; One for downloading a small file and one for unzipping. @@ -483,41 +483,41 @@ (catch Exception e (is (str/includes? (str e) "timed out")))))) -(deftest ^:windows get-message-on-exception-info-test +(deftest get-message-on-exception-info-test (is "foo" (bb nil "(try (throw (ex-info \"foo\" {})) (catch Exception e (.getMessage e)))"))) -(deftest ^:windows pushback-reader-test +(deftest pushback-reader-test (is (= "foo" (bb nil " (require '[clojure.java.io :as io]) (let [pb (java.io.PushbackInputStream. (java.io.ByteArrayInputStream. (.getBytes \"foo\")))] (.unread pb (.read pb)) (slurp pb))")))) -(deftest ^:windows delete-on-exit-test +(deftest delete-on-exit-test (when test-utils/native? (let [f (java.io.File/createTempFile "foo" "bar") p (test-utils/escape-file-paths (.getPath f))] (bb nil (format "(.deleteOnExit (io/file \"%s\"))" p)) (is (false? (.exists f)))))) -(deftest ^:windows yaml-test +(deftest yaml-test (is (str/starts-with? (bb nil "(yaml/generate-string [{:name \"John Smith\", :age 33} {:name \"Mary Smith\", :age 27}])") "-"))) -(deftest ^:windows arrays-copy-of-test +(deftest arrays-copy-of-test (is (= "foo" (bb nil "(String. (java.util.Arrays/copyOf (.getBytes \"foo\") 3))")))) -(deftest ^:windows data-readers-test +(deftest data-readers-test (is (= 2 (bb nil "(set! *data-readers* {'t/tag inc}) #t/tag 1")))) -(deftest ^:windows ordered-test +(deftest ordered-test (is (= (ordered-map :a 1 :b 2) (bb nil "(flatland.ordered.map/ordered-map :a 1 :b 2)")))) -(deftest ^:windows data-diff-test +(deftest data-diff-test (is (= [[nil 1] [nil 2] [1 nil 2]] (bb nil "(require '[clojure.data :as d]) (d/diff [1 1 2] [1 2 2])")))) -(deftest ^:windows version-property-test +(deftest version-property-test (is (= "true\ntrue\nfalse\n" (test-utils/bb nil (.getPath (io/file "test-resources" "babashka" "version.clj")))))) @@ -527,13 +527,13 @@ (clojure.test/do-report {:type :pass, :message ~msg, :expected :success, :actual :success})))) -(deftest ^:windows empty-expressions-test +(deftest empty-expressions-test (testing "bb executes the empty file and doesn't start a REPL" (is (working? (test-utils/bb nil (.getPath (io/file "test-resources" "babashka" "empty.clj")))))) (testing "bb executes the empty expression and doesn't start a REPL" (is (working? (test-utils/bb nil "-e" ""))))) -(deftest ^:windows file-property-test +(deftest file-property-test (is (= "true\nfalse\n" (test-utils/bb nil (.getPath (io/file "test-resources" "babashka" "file_property1.clj"))))) (is (= "true\n" @@ -545,18 +545,18 @@ (is (apply = res)) (is (str/includes? (first res) "..")))) -(deftest ^:windows file-location-test +(deftest file-location-test (is (thrown-with-msg? Exception #"file_location2.clj" (test-utils/bb nil (.getPath (io/file "test-resources" "babashka" "file_location1.clj")))))) -(deftest ^:windows preloads-file-location-test +(deftest preloads-file-location-test (when (System/getenv "BABASHKA_PRELOADS_TEST") (is (thrown-with-msg? Exception #"preloads" (test-utils/bb nil (.getPath (io/file "test-resources" "babashka" "file_location_preloads.clj"))))))) -(deftest ^:windows repl-test +(deftest repl-test (is (str/includes? (test-utils/bb "(ns foo) ::foo" "--repl") ":foo/foo")) (is (str/includes? (test-utils/bb "[*warn-on-reflection* (set! *warn-on-reflection* true) *warn-on-reflection*]") "[false true true]")) @@ -566,14 +566,14 @@ (test-utils/bb {:in "x" :err sw} "--repl")) (is (str/includes? (str sw) "Could not resolve symbol: x [at :1:1]"))))) -(deftest ^:windows java-stream-test +(deftest java-stream-test (is (every? number? (bb nil "(take 2 (iterator-seq (.iterator (.doubles (java.util.Random.)))))")))) -(deftest ^:windows read+string-test +(deftest read+string-test (is (= '[:user/foo "::foo"] (bb nil "(read+string (clojure.lang.LineNumberingPushbackReader. (java.io.StringReader. \"::foo\")))")))) -(deftest ^:windows iterable-test +(deftest iterable-test (is (true? (bb nil " (defn iter [coll] (if (instance? java.lang.Iterable coll) @@ -583,16 +583,16 @@ (= [1 2 3] (iterator-seq (iter [1 2 3])))")))) -(deftest ^:windows var-print-method-test +(deftest var-print-method-test (when test-utils/native? (is (bb nil "(defmethod print-method sci.lang.IVar [o w] (.write w (str :foo (symbol o)))) (def x 1) (= \":foouser/x\" (pr-str #'x))")) (is (= :foouser/x (bb nil "(defmethod print-method sci.lang.IVar [o w] (.write w (str :foo (symbol o)))) (def x 1)"))))) -(deftest ^:windows stdout-interop-test +(deftest stdout-interop-test (when test-utils/native? (is (= 'Something (bb nil "(.print (System/out) \"Something\")"))))) -(deftest ^:windows byte-buffer-test +(deftest byte-buffer-test (testing "interop with HeapByteBuffer" (is (= 42 (bb nil "(count (.array (java.nio.ByteBuffer/allocate 42)))")))) (testing "interop with HeapByteByfferR" @@ -618,7 +618,7 @@ true")) (.force view) true"))) -(deftest ^:windows secure-random-test +(deftest secure-random-test (let [prog '(do (import 'java.security.SecureRandom 'java.util.Base64) (let [random (SecureRandom.) @@ -630,7 +630,7 @@ true"))) (generate-token))] (is (string? (bb nil (str prog)))))) -(deftest ^:windows with-precision-test +(deftest with-precision-test (is (= 0.33333333333333333333M (bb nil "(with-precision 20 (/ 1M 3))"))) (is (= 0.33333333333333333334M (bb nil "(with-precision 20 :rounding CEILING (/ 1M 3))")))) @@ -651,7 +651,7 @@ true"))) (is (str/blank? (with-out-str (main/main "doc" "non-existing")))) (is (= 1 (main/main "doc" "non-existing"))))) -(deftest process-handler-info-test +(deftest ^:skip-windows process-handler-info-test (when test-utils/native? (is (= ["-e" "(vec (.get (.arguments (.info (java.lang.ProcessHandle/current)))))"] (bb nil "-e" "(vec (.get (.arguments (.info (java.lang.ProcessHandle/current)))))"))) @@ -659,7 +659,7 @@ true"))) (bb nil "-e" "(.get (.command (.info (java.lang.ProcessHandle/current))))") "bb")))) -(deftest ^:windows interop-concurrency-test +(deftest interop-concurrency-test (is (= ["true" 3] (last (bb nil "-e" " (def f (fn [_] diff --git a/test/babashka/test_utils.clj b/test/babashka/test_utils.clj index ca2ca749..dcc77e7b 100644 --- a/test/babashka/test_utils.clj +++ b/test/babashka/test_utils.clj @@ -13,16 +13,15 @@ (set! *warn-on-reflection* true) +(defn string-replace-if-windows [match replacement] + (fn [s] + (if main/windows? + (str/replace s match replacement) + s))) -(defn normalize [s] - (if main/windows? - (str/replace s "\r\n" "\n") - s)) +(def normalize (string-replace-if-windows "\r\n" "\n")) -(defn escape-file-paths [s] - (if main/windows? - (str/replace s "\\" "\\\\") - s)) +(def escape-file-paths (string-replace-if-windows "\\" "\\\\")) (def ^:dynamic *bb-edn-path* nil) diff --git a/test/babashka/transit_test.clj b/test/babashka/transit_test.clj index 86523771..f8a7eb7a 100644 --- a/test/babashka/transit_test.clj +++ b/test/babashka/transit_test.clj @@ -10,4 +10,4 @@ (deftest transit-test (is (= "\"foo\"\n{:a [1 2]}\n" (bb (format "(load-file \"%s\")" - (.getPath (io/file "test-resources" "babashka" "transit.clj"))))))) + (test-utils/escape-file-paths (.getPath (io/file "test-resources" "babashka" "transit.clj")))))))) diff --git a/test/babashka/uberjar_test.clj b/test/babashka/uberjar_test.clj index ee2e85a3..49865c33 100644 --- a/test/babashka/uberjar_test.clj +++ b/test/babashka/uberjar_test.clj @@ -1,8 +1,9 @@ (ns babashka.uberjar-test (:require - [babashka.test-utils :as tu] - [clojure.string :as str] - [clojure.test :as t :refer [deftest is testing]])) + [babashka.test-utils :as tu] + [clojure.string :as str] + [clojure.test :as t :refer [deftest is testing]] + [babashka.main :as main])) (defn count-entries [jar] (with-open [jar-file (java.util.jar.JarFile. jar)] @@ -11,7 +12,7 @@ (enumeration-seq (.entries jar-file)))))) -(deftest uberjar-test +(deftest ^:skip-windows uberjar-test (testing "uberjar with --main" (let [tmp-file (java.io.File/createTempFile "uber" ".jar") path (.getPath tmp-file)] @@ -53,8 +54,9 @@ (tu/bb nil "uberjar" path "-m" "my.main-main"))))) (testing "ignore empty entries on classpath" (let [tmp-file (java.io.File/createTempFile "uber" ".jar") - path (.getPath tmp-file)] + path (.getPath tmp-file) + empty-classpath (if main/windows? ";;;" ":::")] (.deleteOnExit tmp-file) - (tu/bb nil "--classpath" ":::" "uberjar" path "-m" "my.main-main") + (tu/bb nil "--classpath" empty-classpath "uberjar" path "-m" "my.main-main") ;; Only a manifest entry is added (is (< (count-entries path) 3))))) diff --git a/test/babashka/udp_test.clj b/test/babashka/udp_test.clj index 5c0f3730..dbe65ffe 100644 --- a/test/babashka/udp_test.clj +++ b/test/babashka/udp_test.clj @@ -22,4 +22,4 @@ "-e" "(load-file (io/file \"test-resources\" \"babashka\" \"statsd.clj\"))" "-e" "(require '[statsd-client :as c])" "-e" "(c/increment :foo)")) - (is (= ":foo:1|c\n" (str sw))))) + (is (= ":foo:1|c\n" (tu/normalize (str sw)))))) From 13773d01041d00ee245ceef6a53cb0a2fec01117 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Sun, 20 Jun 2021 12:42:11 +0200 Subject: [PATCH 09/65] sci: minor map eval --- sci | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sci b/sci index 4c0e8bb2..aa26c292 160000 --- a/sci +++ b/sci @@ -1 +1 @@ -Subproject commit 4c0e8bb2afd940342445052eea9b64ba515c19dd +Subproject commit aa26c292e39a3bb3169f56d1497e94c7c902ba80 From af754d013fd252d502ea1521ea2278190298304a Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Sun, 20 Jun 2021 13:32:33 +0200 Subject: [PATCH 10/65] [#899] (read-line) is buggy in REPL --- src/babashka/impl/clojure/main.clj | 2 ++ src/babashka/impl/repl.clj | 10 +++++++++- test/babashka/impl/repl_test.clj | 2 ++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/babashka/impl/clojure/main.clj b/src/babashka/impl/clojure/main.clj index 1e8ac7a4..aea9726e 100644 --- a/src/babashka/impl/clojure/main.clj +++ b/src/babashka/impl/clojure/main.clj @@ -17,6 +17,8 @@ babashka.impl.clojure.main (:refer-clojure :exclude [with-bindings])) +(set! *warn-on-reflection* true) + (defn demunge "Given a string representation of a fn class, as in a stack trace element, returns a readable version." diff --git a/src/babashka/impl/repl.clj b/src/babashka/impl/repl.clj index 73b2267f..1ae3cebb 100644 --- a/src/babashka/impl/repl.clj +++ b/src/babashka/impl/repl.clj @@ -38,11 +38,18 @@ (str ":" line ":" column))"]")))) (sio/flush)))) +(defn skip-if-eol + "Inspired by skip-if-eol from clojure.main." + [s] + (let [c (r/read-char s)] + (when-not (= c \newline) + (r/unread s c)))) + (defn repl "REPL with predefined hooks for attachable socket server." ([sci-ctx] (repl sci-ctx nil)) ([sci-ctx {:keys [:init :read :eval :need-prompt :prompt :flush :print :caught]}] - (let [in (r/indexing-push-back-reader (r/push-back-reader @sci/in))] + (let [in @sci/in #_(r/indexing-push-back-reader (r/push-back-reader @sci/in))] (m/repl :init (or init (fn [] @@ -57,6 +64,7 @@ :read (or read (fn [_request-prompt request-exit] (let [v (parser/parse-next sci-ctx in)] + (skip-if-eol in) (if (or (identical? :repl/quit v) (identical? :repl/exit v) (identical? parser/eof v)) diff --git a/test/babashka/impl/repl_test.clj b/test/babashka/impl/repl_test.clj index a1bd730b..c82b12ca 100644 --- a/test/babashka/impl/repl_test.clj +++ b/test/babashka/impl/repl_test.clj @@ -47,6 +47,8 @@ (assert-repl "1\n(dec *1)(+ *2 *2)" "2") (assert-repl "1\n(dec *1)(+ *2 *2)" "2") (assert-repl "*command-line-args*" "[\"a\" \"b\" \"c\"]") + (assert-repl "(read-line)hello" "hello") + (assert-repl "(read-line)\nhello" "hello") (assert-repl-error "(+ 1 nil)" "NullPointerException") (assert-repl-error "(/ 1 0) (pst 1)" "Divide by zero\n\tclojure.lang.Numbers")) From f27098f8776430098a62c44f0a1c4573cc57aedc Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Sun, 20 Jun 2021 13:33:04 +0200 Subject: [PATCH 11/65] CHANGELOG [skip ci] --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08a85c1f..f693b4f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ For a list of breaking changes, check [here](#breaking-changes). ## Unreleased - Passing form on Windows with question mark breaks evaluation [#889](https://github.com/babashka/babashka/issues/889) +- `(read-line)` is buggy in REPL [#899](https://github.com/babashka/babashka/issues/899) ## 0.4.6 From e143eb1cb13a99a27ddd1f065731d63ecb93f112 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Sun, 20 Jun 2021 14:26:40 +0200 Subject: [PATCH 12/65] [#899] Fix JVM test --- src/babashka/impl/repl.clj | 2 +- test/babashka/test_utils.clj | 4 +++- test/babashka/uberjar_test.clj | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/babashka/impl/repl.clj b/src/babashka/impl/repl.clj index 1ae3cebb..9cbf4d95 100644 --- a/src/babashka/impl/repl.clj +++ b/src/babashka/impl/repl.clj @@ -49,7 +49,7 @@ "REPL with predefined hooks for attachable socket server." ([sci-ctx] (repl sci-ctx nil)) ([sci-ctx {:keys [:init :read :eval :need-prompt :prompt :flush :print :caught]}] - (let [in @sci/in #_(r/indexing-push-back-reader (r/push-back-reader @sci/in))] + (let [in @sci/in] (m/repl :init (or init (fn [] diff --git a/test/babashka/test_utils.clj b/test/babashka/test_utils.clj index dcc77e7b..9fac05a3 100644 --- a/test/babashka/test_utils.clj +++ b/test/babashka/test_utils.clj @@ -8,6 +8,7 @@ [clojure.edn :as edn] [clojure.string :as str] [clojure.test :as test :refer [*report-counters*]] + [clojure.tools.reader.reader-types :as r] [sci.core :as sci] [sci.impl.vars :as vars])) @@ -51,7 +52,8 @@ in (if (string? input-or-opts) input-or-opts (:in input-or-opts)) is (when in - (java.io.StringReader. in)) + (r/indexing-push-back-reader + (r/push-back-reader (java.io.StringReader. in)))) bindings-map (cond-> {sci/out os sci/err es} is (assoc sci/in is))] diff --git a/test/babashka/uberjar_test.clj b/test/babashka/uberjar_test.clj index 49865c33..9709df1a 100644 --- a/test/babashka/uberjar_test.clj +++ b/test/babashka/uberjar_test.clj @@ -1,9 +1,9 @@ (ns babashka.uberjar-test (:require + [babashka.main :as main] [babashka.test-utils :as tu] [clojure.string :as str] - [clojure.test :as t :refer [deftest is testing]] - [babashka.main :as main])) + [clojure.test :as t :refer [deftest is testing]])) (defn count-entries [jar] (with-open [jar-file (java.util.jar.JarFile. jar)] From d90f4e7bacb0af902764f66be4ba0255528d795c Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Mon, 21 Jun 2021 12:00:53 +0200 Subject: [PATCH 13/65] sci: pull apart bindings in eval (#900) --- sci | 2 +- src/babashka/main.clj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sci b/sci index aa26c292..8f08012b 160000 --- a/sci +++ b/sci @@ -1 +1 @@ -Subproject commit aa26c292e39a3bb3169f56d1497e94c7c902ba80 +Subproject commit 8f08012b8ec945ff859062e6b96877b21223f0df diff --git a/src/babashka/main.clj b/src/babashka/main.clj index 7a8c1725..1b1098c7 100644 --- a/src/babashka/main.clj +++ b/src/babashka/main.clj @@ -314,7 +314,7 @@ Use bb run --help to show this help output. (def namespaces (cond-> {'user {'*input* (ctx-fn - (fn [_ctx] + (fn [_ctx _bindings] (force @input-var)) nil)} 'clojure.tools.cli tools-cli-namespace From e47e77c3d6305381e3ca5513ab9a978e317ee615 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Mon, 21 Jun 2021 19:42:04 +0200 Subject: [PATCH 14/65] Add java.io.FileInputStream --- src/babashka/impl/classes.clj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/babashka/impl/classes.clj b/src/babashka/impl/classes.clj index fae96345..d81a62ab 100644 --- a/src/babashka/impl/classes.clj +++ b/src/babashka/impl/classes.clj @@ -100,6 +100,7 @@ java.io.InputStream java.io.IOException java.io.OutputStream + java.io.FileInputStream java.io.FileReader java.io.InputStreamReader java.io.OutputStreamWriter From ef64e9323852162e760dbe0d25e0adf0a4252182 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Mon, 21 Jun 2021 21:58:41 +0200 Subject: [PATCH 15/65] replikativ/hasch tests in CI --- deps.edn | 3 +- doc/projects.md | 14 ++ .../lib_tests/babashka/run_all_libtests.clj | 3 + test-resources/lib_tests/hasch/test.cljc | 147 ++++++++++++++++++ 4 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 test-resources/lib_tests/hasch/test.cljc diff --git a/deps.edn b/deps.edn index ec064874..a766dcc0 100644 --- a/deps.edn +++ b/deps.edn @@ -79,7 +79,8 @@ failjure/failjure {:mvn/version "2.1.1"} io.helins/binf {:mvn/version "1.1.0-beta0"} rm-hull/jasentaa {:mvn/version "0.2.5"} - slingshot/slingshot {:mvn/version "0.12.2"}} + slingshot/slingshot {:mvn/version "0.12.2"} + io.replikativ/hasch {:mvn/version "0.3.7"}} :classpath-overrides {org.clojure/clojure nil org.clojure/spec.alpha nil org.clojure/core.specs.alpha nil}} diff --git a/doc/projects.md b/doc/projects.md index 41737362..3f70ff57 100644 --- a/doc/projects.md +++ b/doc/projects.md @@ -584,6 +584,20 @@ NOTE: slingshot's tests pass with babashka except one: catching a record types by name. This is due to a difference in how records are implemented in babashka. This may be fixed later if this turns out to be really useful. +### [hasch](https://github.com/replikativ/hasch) + +Cross-platform (JVM and JS atm.) edn data structure hashing for Clojure. + +``` clojure +$ export BABASHKA_CLASSPATH=$(clojure -Spath -Sdeps '{:deps {io.replikativ/hasch {:mvn/version "0.3.7"}}}') +$ bb -e "(use 'hasch.core) (edn-hash (range 100))" +(168 252 48 247 180 148 51 182 108 76 20 251 155 187 66 8 124 123 103 28 250 151 26 139 10 216 119 168 101 123 130 225 66 168 48 63 53 99 25 117 173 29 198 229 101 196 162 30 23 145 7 166 232 193 57 239 226 238 240 41 254 78 135 122) +``` + +NOTE: hasch's tests pass with babashka except the test around hashing +records. This is due to a difference in how records are implemented in +babashka. This may be fixed later if this turns out to be really useful. + ## Pods [Babashka pods](https://github.com/babashka/babashka.pods) are programs that can diff --git a/test-resources/lib_tests/babashka/run_all_libtests.clj b/test-resources/lib_tests/babashka/run_all_libtests.clj index e7dd18d3..96ff628e 100644 --- a/test-resources/lib_tests/babashka/run_all_libtests.clj +++ b/test-resources/lib_tests/babashka/run_all_libtests.clj @@ -218,6 +218,9 @@ ;; 'slingshot.test-test ) +(test-namespaces 'hasch.test + ) + ;;;; final exit code (let [{:keys [:test :fail :error] :as m} @status] diff --git a/test-resources/lib_tests/hasch/test.cljc b/test-resources/lib_tests/hasch/test.cljc new file mode 100644 index 00000000..48c3ba63 --- /dev/null +++ b/test-resources/lib_tests/hasch/test.cljc @@ -0,0 +1,147 @@ +(ns hasch.test + (:require [hasch.core :refer [edn-hash uuid squuid b64-hash]] + [hasch.benc :refer [xor-hashes]] + [hasch.md5 :as md5] + [hasch.hex :as hex] + [hasch.platform :refer [uuid5 sha512-message-digest hash->str #?(:cljs utf8)]] + [incognito.base :as ic] + #?(:clj [clojure.test :as t :refer (is deftest run-tests testing)] + :cljs [cljs.test :as t :refer-macros (is deftest run-tests testing)]))) + +#?(:cljs (def byte-array into-array)) + +(defrecord Bar [name]) + +(deftest hash-test + (testing "Basic hash coercions of EDN primitives." + (is (= (edn-hash nil) + '(184 36 77 2 137 129 214 147 175 123 69 106 248 239 164 202 214 61 40 46 25 255 20 148 44 36 110 80 217 53 29 34 112 74 128 42 113 195 88 11 99 112 222 76 235 41 60 50 74 132 35 52 37 87 212 229 195 132 56 240 227 105 16 238))) + + (is (= (edn-hash true) + '(221 223 252 44 103 48 51 199 71 184 156 187 201 140 35 99 235 153 185 70 157 229 122 4 111 90 12 150 43 67 185 166 210 79 54 62 117 173 76 252 187 67 163 85 202 124 63 252 109 44 47 70 74 129 52 241 35 15 116 253 241 141 50 131))) + + (is (= (edn-hash false) + '(54 0 110 63 158 137 176 89 220 235 107 213 84 159 27 25 148 206 193 96 192 73 41 255 220 181 215 106 208 220 173 69 213 190 181 70 141 193 1 225 188 142 127 176 102 61 13 54 151 161 195 158 152 190 212 168 91 43 153 108 122 123 90 32))) + + (is (= (edn-hash \f) + '(211 133 203 224 194 174 136 44 216 77 98 85 54 188 116 101 139 174 40 108 48 180 235 231 214 189 34 246 32 30 56 45 179 218 36 206 61 191 79 160 212 162 212 226 235 17 27 228 218 74 17 229 9 147 187 232 35 244 179 233 66 165 152 253))) + + (is (= (edn-hash \ä) + '(51 232 113 238 243 104 216 10 143 88 143 111 122 220 35 138 251 22 8 130 238 73 253 62 143 207 208 45 116 21 120 18 253 34 160 30 144 46 182 7 160 254 197 120 199 220 140 209 3 66 25 214 131 145 17 222 28 157 22 103 226 254 178 186))) + + (is (= (edn-hash "hello") + '(178 114 9 243 3 150 0 132 236 216 60 87 108 34 2 35 85 37 203 202 97 176 9 55 25 191 143 251 251 47 49 139 99 191 77 63 167 158 61 183 233 59 43 57 16 252 121 198 65 201 112 167 96 61 134 122 177 149 45 87 233 23 173 192))) + + (is (= (edn-hash "小鳩ちゃんかわいいなぁ") + '(2 191 84 39 34 44 227 102 135 109 17 136 159 80 253 7 40 0 170 134 198 204 137 10 194 21 113 203 2 87 125 80 172 165 111 110 222 7 123 138 148 124 207 180 240 207 91 6 248 28 53 168 143 30 106 103 101 82 133 215 69 35 93 47))) + + (is (= (edn-hash "😡😡😡") + '(18 17 129 25 13 183 170 164 178 18 97 0 123 151 164 145 95 197 214 178 107 96 255 105 255 104 69 21 205 160 13 222 9 55 63 37 174 33 35 86 204 73 17 110 82 107 151 64 63 79 191 246 177 76 71 24 107 44 43 156 178 169 195 214))) + + (is (= (edn-hash (int 1234567890)) + (edn-hash (long 1234567890)) + #?(:clj (edn-hash (biginteger "1234567890"))) + #?(:clj (edn-hash (bigint "1234567890"))) + '(65 199 158 164 193 95 213 144 233 29 41 86 123 106 110 215 117 225 149 249 204 124 220 217 226 120 131 178 61 133 39 228 182 233 235 249 10 249 141 122 101 25 46 134 18 222 175 224 134 61 167 114 15 109 2 146 38 65 1 55 128 137 144 55))) + + (is (= (edn-hash (double 123.1)) + (edn-hash (float 123.1)) + '(155 181 33 252 126 113 188 20 210 155 50 24 125 212 205 160 135 108 90 43 154 65 61 229 226 83 11 110 64 61 124 45 43 186 152 127 64 171 171 154 28 149 180 136 229 69 195 145 126 99 56 14 48 194 180 126 212 83 123 206 36 189 189 167) + #?(:clj (edn-hash (BigDecimal. "123.1"))))) + + (is (= (edn-hash :core/test) + '(62 51 214 78 41 84 37 205 69 197 105 26 235 55 30 87 46 117 187 194 101 184 139 244 111 232 98 175 16 174 182 211 11 171 154 64 90 18 229 93 188 246 33 234 102 145 68 30 92 0 81 208 210 10 124 137 203 18 249 138 226 253 60 62))) + + (is (= (edn-hash #uuid "242525f1-8ed7-5979-9232-6992dd1e11e4") + '(42 243 183 237 233 94 246 1 110 56 231 49 64 217 181 17 108 11 120 199 223 53 149 47 49 8 109 94 127 93 250 51 167 211 25 31 3 171 149 67 23 245 38 248 40 31 199 211 162 242 120 99 187 6 29 237 53 174 22 192 27 159 227 164))) + + (is (= (edn-hash (#?(:clj java.util.Date. :cljs js/Date.) 1000000000000)) + '(177 226 212 235 221 67 176 34 184 69 101 45 117 193 95 187 54 50 210 149 10 193 10 67 220 174 25 99 176 115 250 216 29 49 148 167 52 86 203 90 30 170 62 149 115 102 109 120 128 62 2 213 188 41 203 91 202 106 142 100 119 160 26 3))) + + (is (= (edn-hash 'core/+) + '(164 63 64 77 190 144 72 80 34 36 254 237 101 99 57 114 54 44 195 22 255 11 242 114 99 87 99 135 103 73 164 183 20 192 184 54 183 244 192 151 88 96 55 204 73 156 73 92 154 8 248 205 119 157 34 112 202 51 52 169 162 61 91 235))) + + (is (= (edn-hash '(1 2 3)) + '(244 105 186 110 183 117 195 78 70 57 251 132 133 114 134 175 228 94 242 41 194 191 186 237 163 178 255 193 141 120 5 137 223 130 170 47 231 133 78 131 128 194 115 140 186 169 124 71 205 210 228 236 82 97 166 158 190 98 106 80 237 149 96 102))) + + (is (= (edn-hash [1 2 3 4]) + '(172 52 37 123 179 106 243 207 88 177 218 22 170 25 13 155 205 89 156 251 253 50 3 3 191 74 229 97 252 37 162 240 197 252 240 199 177 8 96 227 121 100 106 132 68 227 175 189 247 184 108 25 117 154 186 63 108 4 210 20 75 25 239 199))) + + (is (= (edn-hash {:a "hello" + :balloon "world"}) + '(135 204 255 206 109 55 248 198 218 226 173 91 27 244 68 34 108 207 62 12 114 49 69 90 22 44 155 178 212 188 139 50 217 200 63 207 14 112 179 94 202 96 196 139 202 154 214 211 182 97 31 139 49 153 203 233 240 223 154 161 78 131 159 102))) + + (is (= (edn-hash #{1 2 3 4}) + '(42 216 217 238 97 125 210 112 2 83 128 62 82 47 119 14 59 95 246 107 191 138 251 102 201 52 9 132 96 243 199 223 218 81 88 130 165 214 125 48 222 30 64 233 101 122 196 84 11 93 186 26 92 225 203 161 196 98 186 138 174 118 244 248))) + + (is (= #_(edn-hash (Bar. "hello")) + #_(edn-hash (ic/incognito-reader {'hasch.test.Bar map->Bar} + (ic/incognito-writer {} (Bar. "hello")))) + #_(edn-hash (ic/map->IncognitoTaggedLiteral (ic/incognito-writer {} (Bar. "hello")))) + (edn-hash (ic/map->IncognitoTaggedLiteral {:tag 'hasch.test.Bar + :value {:name "hello"}})) + '(194 16 151 144 95 224 245 28 219 137 32 192 218 166 162 177 32 154 132 5 111 169 220 211 204 164 67 231 51 96 248 217 77 78 28 136 150 212 202 152 45 167 120 241 14 152 250 246 187 113 212 216 204 46 163 107 91 24 91 0 72 38 4 31))) + + (is (= (edn-hash #?(:cljs (js/Uint8Array. #js [1 2 3 42 149]) + :clj (byte-array [1 2 3 42 149]))) + '(135 209 248 171 162 90 41 221 173 216 64 218 222 93 242 60 243 5 190 153 101 194 74 130 55 184 84 148 167 94 210 250 140 211 6 234 221 25 113 83 153 75 180 4 194 163 178 197 243 126 27 172 248 169 161 90 102 172 160 98 249 32 42 157))))) + +(deftest padded-coercion + (testing "Padded xor coercion for commutative collections." + (is (= (map byte + (xor-hashes (map byte-array + [[0xa0 0x01 0xf3] [0x0c 0xf0 0x5f] [0x0a 0x30 0x07]]))) + (map byte (xor-hashes (map byte-array + [[0x0a 0x30 0x07] [0x0c 0xf0 0x5f] [0xa0 0x01 0xf3]]))))))) + + +(deftest code-hashing + (testing "Code hashing." + (is (= (-> '(fn fib [n] + (if (or (= n 0) (= n 1)) 1 + (+ (fib (- n 1)) (fib (- n 2))))) + edn-hash + uuid5) + #uuid "386eabb0-8adc-52a2-a715-5a74c9197646")))) + +(deftest hash-stringification + (testing "Stringification." + (is (= (hash->str (range 256)) + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff")))) + +(deftest squuid-test + (testing "Sequential UUID functionality." + (is (= (subs (str (squuid (uuid [1 2 3]))) 8) + "-5c15-555e-a1c8-6166a78fc808")))) + +(deftest b64-hash-test + (testing "Testing the base64 encoding of a hash." + (is (= (b64-hash [1 2 3 {:key 5 :value 10}]) + "TREJlRrK211AASiqQMFG9RLFW0CPC/arrCxeaUj27Qho2USJU40T01uCdjUg/OMiPGttyL1ELPCrVXXhMIroRQ==")))) + + +(deftest test-md5 + (is (= (hex/encode (md5/str->md5 "geheimnis")) + "525e92c6aa11544a2ab794f8921ecb0f"))) + +#_(run-tests) + +#?(:cljs + (deftest utf8-test + (is (= (js->clj (utf8 "小鳩ちゃんかわいいなぁ")) + [229 176 143 233 179 169 227 129 161 227 130 131 227 130 147 227 + 129 139 227 130 143 227 129 132 227 129 132 227 129 170 227 129 129])))) + +#?(:cljs + (defn ^:export run + [] + (enable-console-print!) + (run-tests))) + +;; fire up repl +#_(do + (ns dev) + (def repl-env (reset! cemerick.austin.repls/browser-repl-env + (cemerick.austin/repl-env))) + (cemerick.austin.repls/cljs-repl repl-env)) + From 9df9566836afaedbaabea208e90433d87c7c1925 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Mon, 21 Jun 2021 22:41:24 +0200 Subject: [PATCH 16/65] CHANGELOG [skip ci] --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f693b4f0..94dd4326 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,13 @@ For a list of breaking changes, check [here](#breaking-changes). ## Unreleased +Babashka proper: + - Passing form on Windows with question mark breaks evaluation [#889](https://github.com/babashka/babashka/issues/889) - `(read-line)` is buggy in REPL [#899](https://github.com/babashka/babashka/issues/899) +- Add `java.io.FileInputStream`. This fixes compatibility with [replikativ/hasch](https://github.com/replikativ/hasch). + +Sci: minor perf improvements. ## 0.4.6 From b1992e028d933de871f06ac52cfa188e1e78fe66 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Tue, 22 Jun 2021 22:29:10 +0200 Subject: [PATCH 17/65] sci: tests [skip ci] --- sci | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sci b/sci index 8f08012b..8c37419e 160000 --- a/sci +++ b/sci @@ -1 +1 @@ -Subproject commit 8f08012b8ec945ff859062e6b96877b21223f0df +Subproject commit 8c37419ed378034ad4edb96b545a0a872b3c5f5b From c7942badfb17bd2643bea00233f3f07572b2ff34 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Thu, 24 Jun 2021 10:35:06 +0200 Subject: [PATCH 18/65] sci: issue 575 --- sci | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sci b/sci index 8c37419e..bc8df65f 160000 --- a/sci +++ b/sci @@ -1 +1 @@ -Subproject commit 8c37419ed378034ad4edb96b545a0a872b3c5f5b +Subproject commit bc8df65fffdf03a92678dceb98e43723df0a6b06 From e42603dac010cdec9c757a82350b10578fde15d4 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Thu, 24 Jun 2021 13:22:34 +0200 Subject: [PATCH 19/65] example [skip ci] --- examples/README.md | 9 +++++---- examples/{file-server.clj => http-server.clj} | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) rename examples/{file-server.clj => http-server.clj} (99%) diff --git a/examples/README.md b/examples/README.md index 001031ab..330d8757 100644 --- a/examples/README.md +++ b/examples/README.md @@ -25,7 +25,7 @@ - [Invoke vim inside a script](#invoke-vim-inside-a-script) - [Portal](#portal) - [Image viewer](#image-viewer) - - [File server](#file-server) + - [HTTP server](#http-server) - [Torrent viewer](#torrent-viewer) - [cprop.clj](#cpropclj) - [fzf](#fzf) @@ -372,14 +372,15 @@ $ examples/image-viewer.clj See [image-viewer.clj](image-viewer.clj). -## File server +## HTTP Server -Opens browser window and lets user navigate through filesystem. +Opens browser window and lets user navigate through filesystem, similar to +`python3 -m http.server`. Example usage: ``` shell -$ examples/file-server.clj +$ examples/http-server.clj ``` See [file-server.clj](file-server.clj). diff --git a/examples/file-server.clj b/examples/http-server.clj similarity index 99% rename from examples/file-server.clj rename to examples/http-server.clj index d8fa3f72..9a47f63d 100755 --- a/examples/file-server.clj +++ b/examples/http-server.clj @@ -3,7 +3,7 @@ ;; Source: https://gist.github.com/holyjak/36c6284c047ffb7573e8a34399de27d8 ;; Based on https://github.com/babashka/babashka/blob/master/examples/image_viewer.clj -(ns file-server +(ns http-server (:require [babashka.fs :as fs] [clojure.java.browse :as browse] [clojure.string :as str] From 6843eb6d2ebd8defefd9063b275206086c9674f6 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Thu, 24 Jun 2021 15:09:50 +0200 Subject: [PATCH 20/65] sci: minor cleanup [skip ci] --- sci | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sci b/sci index bc8df65f..113ea735 160000 --- a/sci +++ b/sci @@ -1 +1 @@ -Subproject commit bc8df65fffdf03a92678dceb98e43723df0a6b06 +Subproject commit 113ea735934b62925308339dc64e4e89114fb446 From 16911a54f06e5e07fa27bf0320c9229e2117feda Mon Sep 17 00:00:00 2001 From: Bob Date: Thu, 24 Jun 2021 16:34:57 -0400 Subject: [PATCH 21/65] add more windows testing (#902) - add default test selector to skip "windows only" tests - in cases where the differences between *nix shell and windows shell make the test very messy, add a separate "windows only" test - make more tests work on Windows --- project.clj | 3 +- script/test.bat | 5 ++- test-resources/pod.clj | 10 +++--- test/babashka/bb_edn_test.clj | 31 +++++++++++----- .../babashka/impl/clojure/java/shell_test.clj | 20 +++++++++-- test/babashka/main_test.clj | 36 +++++++++++++------ test/babashka/pod_test.clj | 14 +++++--- test/babashka/uberjar_test.clj | 19 +++++----- 8 files changed, 97 insertions(+), 41 deletions(-) diff --git a/project.clj b/project.clj index 7e23b51a..72f22857 100644 --- a/project.clj +++ b/project.clj @@ -14,7 +14,8 @@ ;; :java-source-paths ["sci/reflector/src-java"] :java-source-paths ["src-java"] :resource-paths ["resources" "sci/resources"] - :test-selectors {:windows (complement :skip-windows)} + :test-selectors {:default (complement :windows-only) + :windows (complement :skip-windows)} :dependencies [[org.clojure/clojure "1.11.0-alpha1"] [borkdude/edamame "0.0.11"] [borkdude/graal.locking "0.0.2"] diff --git a/script/test.bat b/script/test.bat index 2144ce6b..d0fe976e 100755 --- a/script/test.bat +++ b/script/test.bat @@ -34,9 +34,8 @@ set BABASHKA_CLASSPATH=test-resources/babashka/src_for_classpath_test/env echo "running tests part 4" call lein test :only babashka.classpath-test/classpath-env-test || exit /B 1 -echo "not running pod tests on windows (yet)" -REM set BABASHKA_POD_TEST=true -REM call lein test :only babashka.pod-test || exit /B 1 +set BABASHKA_POD_TEST=true +call lein test :only babashka.pod-test || exit /B 1 set BABASHKA_SOCKET_REPL_TEST=true call lein test :only babashka.impl.socket-repl-test || exit /B 1 diff --git a/test-resources/pod.clj b/test-resources/pod.clj index a92baecf..cd57ea17 100644 --- a/test-resources/pod.clj +++ b/test-resources/pod.clj @@ -128,10 +128,12 @@ (if (contains? cli-args "--run-as-pod") (do (debug "running pod with cli args" cli-args) (run-pod cli-args)) - (let [native? (contains? cli-args "--native")] - (pods/load-pod (if native? - (into ["./bb" "test-resources/pod.clj" "--run-as-pod"] cli-args) - (into ["lein" "bb" "test-resources/pod.clj" "--run-as-pod"] cli-args))) + (let [native? (contains? cli-args "--native") + windows? (contains? cli-args "--windows")] + (pods/load-pod (cond + native? (into ["./bb" "test-resources/pod.clj" "--run-as-pod"] cli-args) + windows? (into ["cmd" "/c" "lein" "bb" "test-resources/pod.clj" "--run-as-pod"] cli-args) + :else (into ["lein" "bb" "test-resources/pod.clj" "--run-as-pod"] cli-args))) (require '[pod.test-pod]) (if (contains? cli-args "--json") (do diff --git a/test/babashka/bb_edn_test.clj b/test/babashka/bb_edn_test.clj index 6c54d679..e54f7862 100644 --- a/test/babashka/bb_edn_test.clj +++ b/test/babashka/bb_edn_test.clj @@ -244,21 +244,23 @@ *server* server] (babashka.tasks/run 'server)))}} (is (= '([8 :foo] [8 :bar] [11 :foo] [11 :bar] [15 :foo] [15 :bar]) - (bb "run" "--prn" "run-all")))))) - - -(deftest ^:skip-windows unix-task-test + (bb "run" "--prn" "run-all"))))) (let [tmp-dir (fs/create-temp-dir) - out (str (fs/file tmp-dir "out.txt"))] + out (str (fs/file tmp-dir "out.txt")) + ls-cmd (if main/windows? "cmd /c dir" "ls") + expected-output (if main/windows? "File Not Found" "foobar")] (testing "shell test with :continue" (test-utils/with-config {:tasks {'foo (list 'shell {:out out :err out :continue true} - "ls foobar")}} + (str ls-cmd " foobar"))}} (bb "foo") (is (str/includes? (slurp out) - "foobar")))) - (fs/delete out)) + expected-output)))) + (fs/delete out))) + + +(deftest ^:skip-windows unix-task-test (testing "shell pipe test" (test-utils/with-config '{:tasks {a (-> (shell {:out :string} "echo hello") @@ -267,6 +269,19 @@ (let [s (bb "run" "--prn" "a")] (is (= "hello\n" s)))))) +(deftest ^:windows-only win-task-test + (when main/windows? + (testing "shell pipe test" + ; this task prints the contents of deps.edn + (test-utils/with-config '{:tasks {a (->> (shell {:out :string} + "cmd /c echo deps.edn") + :out + clojure.string/trim-newline + (shell {:out :string} "cmd /c type") + :out)}} + (let [s (bb "run" "--prn" "a")] + (is (str/includes? s "paths"))))))) + (deftest list-tasks-test (test-utils/with-config {} (let [res (test-utils/bb nil "tasks")] diff --git a/test/babashka/impl/clojure/java/shell_test.clj b/test/babashka/impl/clojure/java/shell_test.clj index 1f8e75fb..3a9cc45a 100644 --- a/test/babashka/impl/clojure/java/shell_test.clj +++ b/test/babashka/impl/clojure/java/shell_test.clj @@ -1,7 +1,9 @@ (ns babashka.impl.clojure.java.shell-test - (:require [clojure.test :as t :refer [deftest is testing]] + (:require [babashka.main :as main] [babashka.test-utils :as test-utils] - [clojure.string :as str])) + [clojure.string :as str] + [clojure.test :as t :refer [deftest is testing]])) + (deftest ^:skip-windows with-sh-env-test (is (= "\"BAR\"" @@ -15,3 +17,17 @@ (shell/sh \"ls\")) :out)")) "icon.svg"))) + +(deftest ^:windows-only win-with-sh-env-test + (when main/windows? + (is (= "\"BAR\"" + (str/trim (test-utils/bb nil " +(-> (shell/with-sh-env {:FOO \"BAR\"} + (shell/sh \"cmd\" \"/c\" \"echo %FOO%\")) + :out + str/trim)")))) + (is (str/includes? (str/trim (test-utils/bb nil " +(-> (shell/with-sh-dir \"logo\" + (shell/sh \"cmd\" \"/c\" \"dir\")) + :out)")) + "icon.svg")))) diff --git a/test/babashka/main_test.clj b/test/babashka/main_test.clj index d2e83fe4..63e4da43 100644 --- a/test/babashka/main_test.clj +++ b/test/babashka/main_test.clj @@ -200,6 +200,7 @@ (is (true? (bb nil "(.exists (io/file \"README.md\"))"))) (is (true? (bb nil "(.canWrite (io/file \"README.md\"))")))) +; skipped because the windows shell doesn't seem to deal well with infinite things (deftest ^:skip-windows pipe-test (when (and test-utils/native? (not main/windows?)) @@ -208,15 +209,21 @@ head -n10")) out (str/split-lines out) out (map edn/read-string out)] - (is (= (take 10 (map #(* % %) (range))) out)))) - (when (and test-utils/native? - (not main/windows?)) + (is (= (take 10 (map #(* % %) (range))) out))) (let [out (:out (sh "bash" "-c" "./bb -O '(repeat \"dude\")' | ./bb --stream '(str *input* \"rino\")' | ./bb -I '(take 3 *input*)'")) out (edn/read-string out)] (is (= '("duderino" "duderino" "duderino") out))))) +(deftest ^:windows-only win-pipe-test + (when (and test-utils/native? main/windows?) + (let [out (:out (sh "cmd" "/c" ".\\bb -O \"(repeat 50 \\\"dude\\\")\" |" + ".\\bb --stream \"(str *input* \\\"rino\\\")\" |" + ".\\bb -I \"(take 3 *input*)\"")) + out (edn/read-string out)] + (is (= '("duderino" "duderino" "duderino") out))))) + (deftest ^:skip-windows lazy-text-in-test (when test-utils/native? (let [out (:out (sh "bash" "-c" "yes | ./bb -i '(take 2 *input*)'")) @@ -255,15 +262,11 @@ (is (every? number? parsed)) (is (= process-count (count parsed))))))) -(deftest ^:skip-windows create-temp-file-test - (let [temp-dir-path (System/getProperty "java.io.tmpdir")] - (is (= true - (bb nil (format "(let [tdir (io/file \"%s\") - tfile - (File/createTempFile \"ctf\" \"tmp\" tdir)] +(deftest create-temp-file-test + (is (= true + (bb nil "(let [tfile (File/createTempFile \"ctf\" \"tmp\")] (.deleteOnExit tfile) ; for cleanup - (.exists tfile))" - temp-dir-path)))))) + (.exists tfile))")))) (deftest wait-for-port-test (let [server (test-utils/start-server! 1777)] @@ -475,6 +478,11 @@ (prn "output:" v) (is v)))) +(deftest win-file-reader-test + (let [v (bb nil "(slurp (io/reader (java.io.FileReader. \"test-resources/babashka/empty.clj\")))")] + (prn "output:" v) + (is (empty? v)))) + (deftest ^:skip-windows download-and-extract-test ;; Disabled because Github throttles bandwidth and this makes for a very slow test. ;; TODO: refactor into individual unit tests @@ -659,6 +667,12 @@ true"))) (bb nil "-e" "(.get (.command (.info (java.lang.ProcessHandle/current))))") "bb")))) +(deftest ^:windows-only win-process-handler-info-test + (when (and test-utils/native? main/windows?) + (is (str/ends-with? + (bb nil "-e" "(.get (.command (.info (java.lang.ProcessHandle/current))))") + "bb.exe")))) + (deftest interop-concurrency-test (is (= ["true" 3] (last (bb nil "-e" " diff --git a/test/babashka/pod_test.clj b/test/babashka/pod_test.clj index 0b20ff58..f6c8e136 100644 --- a/test/babashka/pod_test.clj +++ b/test/babashka/pod_test.clj @@ -1,23 +1,29 @@ (ns babashka.pod-test - (:require [babashka.test-utils :as tu] + (:require [babashka.main :as main] + [babashka.test-utils :as tu] [clojure.edn :as edn] [clojure.test :as t :refer [deftest is]])) (deftest pod-test (if (= "true" (System/getenv "BABASHKA_POD_TEST")) (let [native? tu/native? + windows? main/windows? sw (java.io.StringWriter.) res (apply tu/bb {:err sw} (cond-> ["-f" "test-resources/pod.clj"] native? - (conj "--native"))) + (conj "--native") + windows? + (conj "--windows"))) err (str sw)] (is (= "6\n1\n2\n3\n4\n5\n6\n7\n8\n9\n\"Illegal arguments / {:args (1 2 3)}\"\n(\"hello\" \"print\" \"this\" \"debugging\" \"message\")\ntrue\n" res)) (when-not tu/native? - (is (= "(\"hello\" \"print\" \"this\" \"error\")\n" err))) + (is (= "(\"hello\" \"print\" \"this\" \"error\")\n" (tu/normalize err)))) (is (= {:a 1 :b 2} (edn/read-string (apply tu/bb nil (cond-> ["-f" "test-resources/pod.clj" "--json"] native? - (conj "--native"))))))) + (conj "--native") + windows? + (conj "--windows"))))))) (println "Skipping pod test because BABASHKA_POD_TEST isn't set to true."))) diff --git a/test/babashka/uberjar_test.clj b/test/babashka/uberjar_test.clj index 9709df1a..581a863d 100644 --- a/test/babashka/uberjar_test.clj +++ b/test/babashka/uberjar_test.clj @@ -12,7 +12,7 @@ (enumeration-seq (.entries jar-file)))))) -(deftest ^:skip-windows uberjar-test +(deftest uberjar-test (testing "uberjar with --main" (let [tmp-file (java.io.File/createTempFile "uber" ".jar") path (.getPath tmp-file)] @@ -45,13 +45,16 @@ (is (= "(\"42\")\n" (tu/bb nil "--jar" path "-m" "my.main-main" "42"))) (is (= "(\"42\")\n" (tu/bb nil "--classpath" path "-m" "my.main-main" "42"))) (is (= "(\"42\")\n" (tu/bb nil path "42")))))) - (testing "throw on empty classpath" - (let [tmp-file (java.io.File/createTempFile "uber" ".jar") - path (.getPath tmp-file)] - (.deleteOnExit tmp-file) - (is (thrown-with-msg? - Exception #"classpath" - (tu/bb nil "uberjar" path "-m" "my.main-main"))))) + + ; this test fails the windows native test in CI + (when-not main/windows? + (testing "throw on empty classpath" + (let [tmp-file (java.io.File/createTempFile "uber" ".jar") + path (.getPath tmp-file)] + (.deleteOnExit tmp-file) + (is (thrown-with-msg? + Exception #"classpath" + (tu/bb nil "uberjar" path "-m" "my.main-main")))))) (testing "ignore empty entries on classpath" (let [tmp-file (java.io.File/createTempFile "uber" ".jar") path (.getPath tmp-file) From 4133c9f5625803199fbb179c76ac5699274b5075 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Fri, 25 Jun 2021 12:52:32 +0200 Subject: [PATCH 22/65] sci [skip ci] --- sci | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sci b/sci index 113ea735..c38f72df 160000 --- a/sci +++ b/sci @@ -1 +1 @@ -Subproject commit 113ea735934b62925308339dc64e4e89114fb446 +Subproject commit c38f72df79943fce9c95716ec71ee94ee189d6a7 From 98ab1338ab27a1d0a697ce593c1bbcfdf0d4898a Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Sun, 27 Jun 2021 16:31:14 +0200 Subject: [PATCH 23/65] sci: refactor error reporting structure --- sci | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sci b/sci index c38f72df..46061d52 160000 --- a/sci +++ b/sci @@ -1 +1 @@ -Subproject commit c38f72df79943fce9c95716ec71ee94ee189d6a7 +Subproject commit 46061d52348cdc32f2d33059cbdaa95848855299 From 07c9f58cf80a77897d4407237289e20d99f4305e Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Sun, 27 Jun 2021 23:14:56 +0200 Subject: [PATCH 24/65] sci: minor cleanups --- sci | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sci b/sci index 46061d52..5bb4544c 160000 --- a/sci +++ b/sci @@ -1 +1 @@ -Subproject commit 46061d52348cdc32f2d33059cbdaa95848855299 +Subproject commit 5bb4544ce6ca84843c61e332ad997a7ec8cdab28 From 9acf8145d001866504c11f828f0dffb3c37df241 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Sun, 27 Jun 2021 23:24:45 +0200 Subject: [PATCH 25/65] sci: minor cleanup --- sci | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sci b/sci index 5bb4544c..05d20ae0 160000 --- a/sci +++ b/sci @@ -1 +1 @@ -Subproject commit 5bb4544ce6ca84843c61e332ad997a7ec8cdab28 +Subproject commit 05d20ae07ad9c99a3e4aab6afa194dd9570c48e4 From c447bc3f2c2712f8c90472e746f0dcc440785af5 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Sun, 27 Jun 2021 23:46:04 +0200 Subject: [PATCH 26/65] Revert last cleanup --- sci | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sci b/sci index 05d20ae0..6a712e21 160000 --- a/sci +++ b/sci @@ -1 +1 @@ -Subproject commit 05d20ae07ad9c99a3e4aab6afa194dd9570c48e4 +Subproject commit 6a712e211a4978b3bef59202ee28dad8f5452fbf From 000e88f0c658171b7f789ea483d3408cf5de3187 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Mon, 28 Jun 2021 18:19:59 +0200 Subject: [PATCH 27/65] sci: minor cleanup --- sci | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sci b/sci index 6a712e21..3c9f34f5 160000 --- a/sci +++ b/sci @@ -1 +1 @@ -Subproject commit 6a712e211a4978b3bef59202ee28dad8f5452fbf +Subproject commit 3c9f34f5878e2c8fa6b8aca112c40078480a255b From 9fa5b600d9d86ed9e6f5ba398347235ec4af7038 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Tue, 29 Jun 2021 23:37:29 +0200 Subject: [PATCH 28/65] doc [skip ci] --- README.md | 3 +++ doc/news.md | 23 ++++++++++++++++++++++- sci | 2 +- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 36363f3e..06000b07 100644 --- a/README.md +++ b/README.md @@ -298,6 +298,9 @@ handling of SIGINT and SIGPIPE. This can be done by setting ## Articles, podcasts and videos +- [Integrating Babashka into Bazel](https://timjaeger.io/20210627-integrating-babashka-with-bazel.html) by Tim Jäger +- [Talk](https://youtu.be/Yjeh57eE9rg): Babashka: a native Clojure interpreter for scripting — The 2021 Graal Workshop at CGO +- [Blog](https://savo.rocks/posts/playing-new-music-on-old-car-stereo-with-clojure-and-babashka/): Playing New Music On Old Car Stereo With Clojure And Babashka - [Homoiconicity and feature flags](https://martinklepsch.org/posts/homoiconicity-and-feature-flags.html) by Martin Klepsch - [Clojure like its PHP](https://eccentric-j.com/blog/clojure-like-its-php.html) by Jay Zawrotny (eccentric-j) - [Deploy babashka script to AWS Lambda](https://www.jocas.lt/blog/post/babashka-aws-lambda/) by Dainius Jocas. diff --git a/doc/news.md b/doc/news.md index b6b7192b..d94dd095 100644 --- a/doc/news.md +++ b/doc/news.md @@ -5,15 +5,36 @@ you have anything to add. Also see [#babashka](https://twitter.com/hashtag/babashka?src=hashtag_click&f=live) on Twitter. +## 2021-06 + +- New babashka release 0.4.4-0.4.5 +- Share your babashka creations on the [Show and tell](https://github.com/babashka/babashka/discussions/categories/show-and-tell) forum on Github. +- [Integrating Babashka into Bazel](https://timjaeger.io/20210627-integrating-babashka-with-bazel.html) by Tim Jäger +- [Babashka + scittle guestbook example](https://github.com/kloimhardt/babashka-scittle-guestbook) +- [Slingshot works with babashka](https://twitter.com/borkdude/status/1402547783295504387) +- [Spire gets a babashka pod](https://twitter.com/epic_castle/status/1402212817533431808) +- [Text to speech AWS example](https://twitter.com/FieryCodDev/status/1401843357555511301) with scittle and babashka. +- [Game of Life](https://gist.github.com/mmzsource/655b9dcfe56eed8a045022837186ed84) +- [ob-babashka](https://gist.github.com/adam-james-v/f4d2b75a70b095d14a351a1eff96b4b0): Emacs org-babel functions for babashka. +- [Normalize auto-resolved keywords](https://github.com/babashka/babashka/tree/master/examples#normalize-keywordsclj) +- [Create PostgreSQL backups](https://twitter.com/stelstuff/status/1400559261025980418) using babashka. +- [Change flutter SDK](https://gist.github.com/ampersanda/aac70cc0644df12199ea32988f3c4d73) using babashka. + ## 2021-05 -- Babashka 0.3.6-0.4.0 release. Highlights: +- Babashka 0.3.6-0.4.3 release. Highlights: - New [task runner feature](https://book.babashka.org/#tasks). - Add [Selmer](https://github.com/yogthos/Selmer) to built-in libraries. - Add compatibility with [jasentaa](https://github.com/rm-hull/jasentaa). - New [website](https://babashka.org). +- [Talk](https://youtu.be/Yjeh57eE9rg): Babashka: a native Clojure interpreter for scripting — The 2021 Graal Workshop at CGO +- Babashka is now compatible with [jasentaa](https://twitter.com/borkdude/status/1391346873986805763), a parser combinator library. +- Babashka now comes with the [Selmer](https://twitter.com/borkdude/status/1390280042618540037) templating library. +- [Blog](https://savo.rocks/posts/playing-new-music-on-old-car-stereo-with-clojure-and-babashka/): Playing New Music On Old Car Stereo With Clojure And Babashka - [Homoiconicity and feature flags](https://martinklepsch.org/posts/homoiconicity-and-feature-flags.html) by Martin Klepsch. +- [Manage your macOS setup](https://github.com/cldwalker/osx-setup) using babashka. - [Localizing a Ghost theme](https://martinklepsch.org/posts/localizing-a-ghost-theme.html) by Martin Klepsch. +- [Babashka SQL pods 0.0.8](https://twitter.com/borkdude/status/1396136828479188997) including a MySQL pod ## 2021-04 diff --git a/sci b/sci index 3c9f34f5..98042fc6 160000 --- a/sci +++ b/sci @@ -1 +1 @@ -Subproject commit 3c9f34f5878e2c8fa6b8aca112c40078480a255b +Subproject commit 98042fc613e01adf637cb927ccfe78b183084eaf From ac957dada428a3965fa8e4f8c92accf479fd81f7 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Tue, 29 Jun 2021 23:38:21 +0200 Subject: [PATCH 29/65] doc [skip ci] --- doc/news.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/news.md b/doc/news.md index d94dd095..3047c1d7 100644 --- a/doc/news.md +++ b/doc/news.md @@ -28,8 +28,6 @@ Twitter. - Add compatibility with [jasentaa](https://github.com/rm-hull/jasentaa). - New [website](https://babashka.org). - [Talk](https://youtu.be/Yjeh57eE9rg): Babashka: a native Clojure interpreter for scripting — The 2021 Graal Workshop at CGO -- Babashka is now compatible with [jasentaa](https://twitter.com/borkdude/status/1391346873986805763), a parser combinator library. -- Babashka now comes with the [Selmer](https://twitter.com/borkdude/status/1390280042618540037) templating library. - [Blog](https://savo.rocks/posts/playing-new-music-on-old-car-stereo-with-clojure-and-babashka/): Playing New Music On Old Car Stereo With Clojure And Babashka - [Homoiconicity and feature flags](https://martinklepsch.org/posts/homoiconicity-and-feature-flags.html) by Martin Klepsch. - [Manage your macOS setup](https://github.com/cldwalker/osx-setup) using babashka. From 42dffdad84aaa60554d53da0f75c4d8605253857 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Tue, 29 Jun 2021 23:39:07 +0200 Subject: [PATCH 30/65] doc [skip ci] --- doc/news.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/news.md b/doc/news.md index 3047c1d7..f89e656c 100644 --- a/doc/news.md +++ b/doc/news.md @@ -7,7 +7,7 @@ Twitter. ## 2021-06 -- New babashka release 0.4.4-0.4.5 +- New babashka 0.4.4 - 0.4.5 released. - Share your babashka creations on the [Show and tell](https://github.com/babashka/babashka/discussions/categories/show-and-tell) forum on Github. - [Integrating Babashka into Bazel](https://timjaeger.io/20210627-integrating-babashka-with-bazel.html) by Tim Jäger - [Babashka + scittle guestbook example](https://github.com/kloimhardt/babashka-scittle-guestbook) @@ -22,7 +22,7 @@ Twitter. ## 2021-05 -- Babashka 0.3.6-0.4.3 release. Highlights: +- Babashka 0.3.7 - 0.4.3 released. Highlights: - New [task runner feature](https://book.babashka.org/#tasks). - Add [Selmer](https://github.com/yogthos/Selmer) to built-in libraries. - Add compatibility with [jasentaa](https://github.com/rm-hull/jasentaa). From 47bcb4be5e0b7267cbd6d47b769fe857b2d008cb Mon Sep 17 00:00:00 2001 From: Bob Date: Wed, 30 Jun 2021 12:21:35 -0400 Subject: [PATCH 31/65] add heap size and 'expert' flags to help text (#908) --- src/babashka/main.clj | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/babashka/main.clj b/src/babashka/main.clj index 1b1098c7..1e9799c1 100644 --- a/src/babashka/main.clj +++ b/src/babashka/main.clj @@ -117,8 +117,9 @@ or: bb [global-opts] subcommand [subcommand opts] [cmdline args] Global opts: - -cp, --classpath Classpath to use. Overrides bb.edn classpath. - --debug Print debug information and internal stacktrace in case of exception. + -cp, --classpath Classpath to use. Overrides bb.edn classpath. + --debug Print debug information and internal stacktrace in case of exception. + -Xmx[g|G|m|M|k|K] Set a maximum heap size (e.g. -Xmx256M to limit the heap to 256MB). Help: @@ -126,6 +127,7 @@ Help: version Print the current version of babashka. describe Print an EDN map with information about this version of babashka. doc Print docstring of var or namespace. Requires namespace if necessary. + -XX:PrintFlags= Print help text for \"expert\" runtime options (GC/safepoint options). Evaluation: From a542227442f71ec127c9c49ecc704d40f75b5fe9 Mon Sep 17 00:00:00 2001 From: Bob Date: Sat, 3 Jul 2021 17:53:58 -0400 Subject: [PATCH 32/65] add examples for #324 and #369 [skip ci] (#911) * add examples for: - checking stdin for available input - using data.xml lib * fix some string contents left over from an XML change --- examples/README.md | 29 +++++++++++++++ examples/xml-example.clj | 78 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 examples/xml-example.clj diff --git a/examples/README.md b/examples/README.md index 330d8757..7c958753 100644 --- a/examples/README.md +++ b/examples/README.md @@ -32,6 +32,9 @@ - [digitalocean-ping.clj](#digitalocean-pingclj) - [download-aliases.clj](#download-aliasesclj) - [Is TTY?](#is-tty) + - [normalize-keywords.clj](#normalize-keywordsclj) + - [Check stdin for data](#check-stdin-for-data) + - [Using org.clojure/data.xml](#using-orgclojuredataxml) Here's a gallery of useful examples. Do you have a useful example? PR welcome! @@ -483,3 +486,29 @@ $ bb examples/normalize-keywords.clj /tmp/test.clj [:clojure.set/foo :test/bar] ``` + +## Check stdin for data + +```shell +# when piping something in, we get a positive number +$ echo 'abc' | bb '(pos? (.available System/in))' +true +# even if we echo an empty string, we still get the newline +$ echo '' | bb '(pos? (.available System/in))' +true +# with nothing passed in, we finally return false +$ bb '(pos? (.available System/in))' +false +``` + +## Using org.clojure/data.xml + +[xml-example.clj](xml-example.clj) explores some of the capabilities provided +by the `org.clojure/data.xml` library (required as `xml` by default in Babashka). +While running the script will show some output, reading the file shows the library +in use. + +```shell +$ bb examples/xml-example.clj +... some vaguely interesting XML manipulation output +``` diff --git a/examples/xml-example.clj b/examples/xml-example.clj new file mode 100644 index 00000000..8aa28dbd --- /dev/null +++ b/examples/xml-example.clj @@ -0,0 +1,78 @@ +; let's build up a little data structure to play with + +(def pet-store-sexp + [:pet-store + [:family + [:owners + [:name "Terry Smith"] + [:name "Sam Smith"] + [:phone "555-1212"]] + [:animals + [:animal {:type "dog"} "Sparky"]]] + [:family + [:owners + [:name "Pat Jones"] + [:phone "555-2121"]] + [:animals + [:animal {:type "hamster"} "Oliver"] + [:animal {:type "cat"} "Kat"]]]]) + +; we can build XML from this + +(def xml-str (xml/indent-str (xml/sexp-as-element pet-store-sexp))) + +(println "Our XML as a string is:") +(println xml-str) + +(comment xml-str is + " + + + + Terry Smith...") + +; and then we can parse that XML back into a data structure + +(def xml-tree (xml/parse-str xml-str)) + +#_"xml-tree is a nested associative structure: + {:tag :pet-store, + :attrs {}, + :content + ({:tag :family, + :attrs {}, + :content ...})}" + + +; with a couple of quick helper functions... + +(defn get-by-tag + "takes a seq of XML elements (or a 'root-ish' element) and a tag, filters by tag name, and gets the content of each" + [elems tag-name] + ; if we get (presumably) a root element, wrap it in a vector so we can still + ; filter by its tag + (if (xml/element? elems) + (recur [elems] tag-name) + (->> (filter #(= (:tag %) tag-name) elems) + (mapcat :content)))) + +(defn get-in-by-tag + "takes a seq of XML elements and a vector of tags, and drills into each + element by the tags, sort of like a mash-up of core/get-in and an XPath + lookup" + [elems tag-vec] + (reduce get-by-tag elems tag-vec)) + +; we can do things like... + +(println "all the owner names:" (get-in-by-tag + xml-tree + [:pet-store :family :owners :name])) + +(println "all the animal names:" (get-in-by-tag + xml-tree + [:pet-store :family :animals :animal])) + +(println "all the phone numbers:" (get-in-by-tag + xml-tree + [:pet-store :family :owners :phone])) From b809dd55e8a70f13186a9c5ed82d8f2332eadd20 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Sun, 4 Jul 2021 11:45:43 +0200 Subject: [PATCH 33/65] [#914] clojure with :dir option doesn't resolve deps in :dir --- deps.clj | 2 +- sci | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/deps.clj b/deps.clj index 520b6b05..6a4d0f89 160000 --- a/deps.clj +++ b/deps.clj @@ -1 +1 @@ -Subproject commit 520b6b053b7bdfe46990ab82220a2d13f79f9772 +Subproject commit 6a4d0f895791687d6289de0644ef11f04acebeb8 diff --git a/sci b/sci index 98042fc6..e80a2093 160000 --- a/sci +++ b/sci @@ -1 +1 @@ -Subproject commit 98042fc613e01adf637cb927ccfe78b183084eaf +Subproject commit e80a2093722c510ef7988ed4e3b0d9f19f821b52 From 9eb3c8189cab20c82574ff1b7ebbe5db247408fe Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Sun, 4 Jul 2021 11:47:28 +0200 Subject: [PATCH 34/65] CHANGELOG [skip ci] --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 94dd4326..5ef1913a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ Babashka proper: - Passing form on Windows with question mark breaks evaluation [#889](https://github.com/babashka/babashka/issues/889) - `(read-line)` is buggy in REPL [#899](https://github.com/babashka/babashka/issues/899) - Add `java.io.FileInputStream`. This fixes compatibility with [replikativ/hasch](https://github.com/replikativ/hasch). +- `babashka.tasks/clojure` with `:dir` option doesn't resolve deps in `:dir` [#914](https://github.com/babashka/babashka/issues/914) Sci: minor perf improvements. From 3cf3a83c49aa303ddade2a1beff64eb838e51d15 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Sun, 4 Jul 2021 12:16:16 +0200 Subject: [PATCH 35/65] [#914] clojure with :dir option doesn't resolve deps in :dir (2) --- deps.clj | 2 +- src/babashka/impl/deps.clj | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/deps.clj b/deps.clj index 6a4d0f89..ebf1a670 160000 --- a/deps.clj +++ b/deps.clj @@ -1 +1 @@ -Subproject commit 6a4d0f895791687d6289de0644ef11f04acebeb8 +Subproject commit ebf1a6701f9db58da8345ae608dadb0602e79228 diff --git a/src/babashka/impl/deps.clj b/src/babashka/impl/deps.clj index b5aee8d7..4200e90a 100644 --- a/src/babashka/impl/deps.clj +++ b/src/babashka/impl/deps.clj @@ -109,6 +109,7 @@ (binding [*in* @sci/in *out* @sci/out *err* @sci/err + deps/*dir* (:dir opts) deps/*process-fn* (fn ([cmd] (p/process cmd opts)) ([cmd _] (p/process cmd opts))) From 1efed2c3c7135d0f24721e70962345484af93d8b Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Sun, 4 Jul 2021 20:41:09 +0200 Subject: [PATCH 36/65] minor help edit [skip ci] --- src/babashka/main.clj | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/babashka/main.clj b/src/babashka/main.clj index 1e9799c1..b6fcdb11 100644 --- a/src/babashka/main.clj +++ b/src/babashka/main.clj @@ -111,15 +111,19 @@ (defn print-help [_ctx _command-line-args] (println (str "Babashka v" version)) (println " -Usage: bb [global-opts] [eval opts] [cmdline args] -or: bb [global-opts] file [cmdline args] -or: bb [global-opts] subcommand [subcommand opts] [cmdline args] +Usage: bb [svm-opts] [global-opts] [eval opts] [cmdline args] +or: bb [svm-opts] [global-opts] file [cmdline args] +or: bb [svm-opts] [global-opts] subcommand [subcommand opts] [cmdline args] + +Substrate VM opts: + + -Xmx[g|G|m|M|k|K] Set a maximum heap size (e.g. -Xmx256M to limit the heap to 256MB). + -XX:PrintFlags= Print all Substrate VM options. Global opts: -cp, --classpath Classpath to use. Overrides bb.edn classpath. --debug Print debug information and internal stacktrace in case of exception. - -Xmx[g|G|m|M|k|K] Set a maximum heap size (e.g. -Xmx256M to limit the heap to 256MB). Help: @@ -127,7 +131,6 @@ Help: version Print the current version of babashka. describe Print an EDN map with information about this version of babashka. doc Print docstring of var or namespace. Requires namespace if necessary. - -XX:PrintFlags= Print help text for \"expert\" runtime options (GC/safepoint options). Evaluation: From 432680b2f3a386cd73b4b833c6787d81690d56ee Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Sun, 4 Jul 2021 22:18:07 +0200 Subject: [PATCH 37/65] [#914] Fix cache dir --- deps.clj | 2 +- test-resources/clojure-dir-test/deps.edn | 1 + test/babashka/deps_test.clj | 6 +++++- 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 test-resources/clojure-dir-test/deps.edn diff --git a/deps.clj b/deps.clj index ebf1a670..435a7cc2 160000 --- a/deps.clj +++ b/deps.clj @@ -1 +1 @@ -Subproject commit ebf1a6701f9db58da8345ae608dadb0602e79228 +Subproject commit 435a7cc2088524edab734d2a89c2b5521e5e9fd9 diff --git a/test-resources/clojure-dir-test/deps.edn b/test-resources/clojure-dir-test/deps.edn new file mode 100644 index 00000000..b489dfa7 --- /dev/null +++ b/test-resources/clojure-dir-test/deps.edn @@ -0,0 +1 @@ +{:deps {medley/medley {:mvn/version "1.3.0"}}} diff --git a/test/babashka/deps_test.clj b/test/babashka/deps_test.clj index d8f083c9..e7c9719e 100644 --- a/test/babashka/deps_test.clj +++ b/test/babashka/deps_test.clj @@ -56,4 +56,8 @@ true (babashka.deps/clojure [\"-Sresolve-tags\"]) ")))) (is (true? (bb " -(= 5 (:exit @(babashka.deps/clojure [] {:in \"(System/exit 5)\" :out :string})))")))) +(= 5 (:exit @(babashka.deps/clojure [] {:in \"(System/exit 5)\" :out :string})))"))) + (testing "start from other directory" + (is (= {1 {:id 1}, 2 {:id 2}} + (edn/read-string (bb " +(:out @(babashka.deps/clojure [\"-M\" \"-e\" \"(require 'medley.core) (medley.core/index-by :id [{:id 1} {:id 2}])\"] {:out :string :dir \"test-resources/clojure-dir-test\"}))")))))) From a7d669b47b94976b3039996f7daca2587a643794 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Sun, 4 Jul 2021 22:27:14 +0200 Subject: [PATCH 38/65] Fix tests --- deps.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps.clj b/deps.clj index 435a7cc2..e25d6f64 160000 --- a/deps.clj +++ b/deps.clj @@ -1 +1 @@ -Subproject commit 435a7cc2088524edab734d2a89c2b5521e5e9fd9 +Subproject commit e25d6f6498cfed9474ec44d568f7131d2aa0cc63 From 2dd18e7cc6ed2e3f942c8b6360dc313438510b4f Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Mon, 5 Jul 2021 00:05:48 +0200 Subject: [PATCH 39/65] Failing test, fix later --- test/babashka/deps_test.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/babashka/deps_test.clj b/test/babashka/deps_test.clj index e7c9719e..a461fb7b 100644 --- a/test/babashka/deps_test.clj +++ b/test/babashka/deps_test.clj @@ -57,7 +57,7 @@ true ")))) (is (true? (bb " (= 5 (:exit @(babashka.deps/clojure [] {:in \"(System/exit 5)\" :out :string})))"))) - (testing "start from other directory" + #_(testing "start from other directory" (is (= {1 {:id 1}, 2 {:id 2}} (edn/read-string (bb " (:out @(babashka.deps/clojure [\"-M\" \"-e\" \"(require 'medley.core) (medley.core/index-by :id [{:id 1} {:id 2}])\"] {:out :string :dir \"test-resources/clojure-dir-test\"}))")))))) From 277029caaeb1b681a3256cc1b0cf05945bbfe448 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Mon, 5 Jul 2021 18:26:29 +0200 Subject: [PATCH 40/65] [#914] Fix failing test --- deps.clj | 2 +- test/babashka/deps_test.clj | 2 +- test/babashka/test_utils.clj | 11 ++++++----- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/deps.clj b/deps.clj index e25d6f64..d85b9aac 160000 --- a/deps.clj +++ b/deps.clj @@ -1 +1 @@ -Subproject commit e25d6f6498cfed9474ec44d568f7131d2aa0cc63 +Subproject commit d85b9aac2fe750ec75fd611842ddf055b64bb933 diff --git a/test/babashka/deps_test.clj b/test/babashka/deps_test.clj index a461fb7b..e7c9719e 100644 --- a/test/babashka/deps_test.clj +++ b/test/babashka/deps_test.clj @@ -57,7 +57,7 @@ true ")))) (is (true? (bb " (= 5 (:exit @(babashka.deps/clojure [] {:in \"(System/exit 5)\" :out :string})))"))) - #_(testing "start from other directory" + (testing "start from other directory" (is (= {1 {:id 1}, 2 {:id 2}} (edn/read-string (bb " (:out @(babashka.deps/clojure [\"-M\" \"-e\" \"(require 'medley.core) (medley.core/index-by :id [{:id 1} {:id 2}])\"] {:out :string :dir \"test-resources/clojure-dir-test\"}))")))))) diff --git a/test/babashka/test_utils.clj b/test/babashka/test_utils.clj index 9fac05a3..8f9a75b2 100644 --- a/test/babashka/test_utils.clj +++ b/test/babashka/test_utils.clj @@ -31,11 +31,12 @@ (println)) (defmethod clojure.test/report :end-test-var [_m] - (let [{:keys [:fail :error]} @*report-counters*] - (when (and (= "true" (System/getenv "BABASHKA_FAIL_FAST")) - (or (pos? fail) (pos? error))) - (println "=== Failing fast") - (System/exit 1)))) + (when-let [rc *report-counters*] + (let [{:keys [:fail :error]} @rc] + (when (and (= "true" (System/getenv "BABASHKA_FAIL_FAST")) + (or (pos? fail) (pos? error))) + (println "=== Failing fast") + (System/exit 1))))) (defn bb-jvm [input-or-opts & args] (reset! cp/cp-state nil) From f47f8b9ad142d6f5d9887c22ba823ab6298b0868 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Mon, 5 Jul 2021 18:45:16 +0200 Subject: [PATCH 41/65] Catch up with clojure CLI --- deps.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps.clj b/deps.clj index d85b9aac..178cd8d1 160000 --- a/deps.clj +++ b/deps.clj @@ -1 +1 @@ -Subproject commit d85b9aac2fe750ec75fd611842ddf055b64bb933 +Subproject commit 178cd8d10fbcef5d885b0d17bd974345829ea3e6 From 097e45d180fce8a7082fe29ee3b55b97d838e871 Mon Sep 17 00:00:00 2001 From: Bob Date: Mon, 5 Jul 2021 15:12:11 -0400 Subject: [PATCH 42/65] [#877] add omniconf lib tests --- deps.edn | 3 +- .../lib_tests/babashka/run_all_libtests.clj | 2 ++ .../lib_tests/omniconf/core_test.clj | 36 +++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 test-resources/lib_tests/omniconf/core_test.clj diff --git a/deps.edn b/deps.edn index a766dcc0..fedfe577 100644 --- a/deps.edn +++ b/deps.edn @@ -80,7 +80,8 @@ io.helins/binf {:mvn/version "1.1.0-beta0"} rm-hull/jasentaa {:mvn/version "0.2.5"} slingshot/slingshot {:mvn/version "0.12.2"} - io.replikativ/hasch {:mvn/version "0.3.7"}} + io.replikativ/hasch {:mvn/version "0.3.7"} + com.grammarly/omniconf {:mvn/version "0.4.3"}} :classpath-overrides {org.clojure/clojure nil org.clojure/spec.alpha nil org.clojure/core.specs.alpha nil}} diff --git a/test-resources/lib_tests/babashka/run_all_libtests.clj b/test-resources/lib_tests/babashka/run_all_libtests.clj index 96ff628e..723ad4ee 100644 --- a/test-resources/lib_tests/babashka/run_all_libtests.clj +++ b/test-resources/lib_tests/babashka/run_all_libtests.clj @@ -221,6 +221,8 @@ (test-namespaces 'hasch.test ) +(test-namespaces 'omniconf.core-test) + ;;;; final exit code (let [{:keys [:test :fail :error] :as m} @status] diff --git a/test-resources/lib_tests/omniconf/core_test.clj b/test-resources/lib_tests/omniconf/core_test.clj new file mode 100644 index 00000000..2f832f56 --- /dev/null +++ b/test-resources/lib_tests/omniconf/core_test.clj @@ -0,0 +1,36 @@ +(ns omniconf.core-test + (:require [clojure.string :as str] + [clojure.test :refer [deftest is testing]] + [omniconf.core :as cfg]) + (:import (java.io File))) + +(cfg/define + {:conf {:type :file} + :foo {:type :string + :required true} + :the-boolean {:type :boolean} + :missing {:type :string + :required true}}) + +(deftest load-cfg-test + (testing "multiple config sources" + (let [temp-cfg-file (File/createTempFile "cfg" "edn") + _ (.deleteOnExit temp-cfg-file) + fake-args ["--conf" (.getAbsolutePath temp-cfg-file) + "--foo" "this will be overridden"]] + (do + ; put some props in the temp file + (spit temp-cfg-file "{:foo \"final value\" :the-boolean false }") + ; and set a system property + (System/setProperty "the-boolean" "18") + (cfg/populate-from-cmd fake-args) + (cfg/populate-from-file (cfg/get :conf)) + (cfg/populate-from-properties) + ; cleanup + (System/clearProperty "the-boolean"))) + (is (= "final value" (cfg/get :foo))) + (is (= true (cfg/get :the-boolean))) + (is (thrown-with-msg? Exception #":missing" (cfg/verify))) + (cfg/populate-from-map {:missing "abc"}) + (let [verify-output (with-out-str (cfg/verify))] + (is (every? #(str/includes? verify-output %) [":missing" "abc"]))))) From 789b8f701ed2f67b3eb00eeef92e5fb07edefb1b Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Mon, 5 Jul 2021 21:24:24 +0200 Subject: [PATCH 43/65] deps.clj update --- deps.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps.clj b/deps.clj index 178cd8d1..2d1f34b2 160000 --- a/deps.clj +++ b/deps.clj @@ -1 +1 @@ -Subproject commit 178cd8d10fbcef5d885b0d17bd974345829ea3e6 +Subproject commit 2d1f34b253d2f8a3e91c633e835cad987467aa38 From 4c0578c56cd4ca6b54da3236caff694d2b7fe97e Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Mon, 5 Jul 2021 21:27:45 +0200 Subject: [PATCH 44/65] CHANGELOGS [skip ci] --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ef1913a..bbef42c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ Babashka proper: - Add `java.io.FileInputStream`. This fixes compatibility with [replikativ/hasch](https://github.com/replikativ/hasch). - `babashka.tasks/clojure` with `:dir` option doesn't resolve deps in `:dir` [#914](https://github.com/babashka/babashka/issues/914) +Deps.clj: + +Update to v0.0.16 which corresponds to clojure CLI `1.10.3.855`. + Sci: minor perf improvements. ## 0.4.6 From b53be25b9478c6958d9121fa117f1d76b7b8f95b Mon Sep 17 00:00:00 2001 From: Bob Date: Wed, 7 Jul 2021 04:01:36 -0400 Subject: [PATCH 45/65] [#817] add crispin to lib tests and projects.md (#918) * add crispin to lib tests and projects.md * add a missing line in crispin example --- deps.edn | 3 +- doc/projects.md | 30 +++++++++++++++++++ .../lib_tests/babashka/run_all_libtests.clj | 2 ++ .../lib_tests/crispin/core_test.clj | 22 ++++++++++++++ .../lib_tests/crispin/crispin-test-cfg.edn | 2 ++ .../crispin/crispin-test-custom-cfg.edn | 1 + 6 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 test-resources/lib_tests/crispin/core_test.clj create mode 100644 test-resources/lib_tests/crispin/crispin-test-cfg.edn create mode 100644 test-resources/lib_tests/crispin/crispin-test-custom-cfg.edn diff --git a/deps.edn b/deps.edn index fedfe577..61664cd3 100644 --- a/deps.edn +++ b/deps.edn @@ -81,7 +81,8 @@ rm-hull/jasentaa {:mvn/version "0.2.5"} slingshot/slingshot {:mvn/version "0.12.2"} io.replikativ/hasch {:mvn/version "0.3.7"} - com.grammarly/omniconf {:mvn/version "0.4.3"}} + com.grammarly/omniconf {:mvn/version "0.4.3"} + crispin/crispin {:mvn/version "0.3.8"}} :classpath-overrides {org.clojure/clojure nil org.clojure/spec.alpha nil org.clojure/core.specs.alpha nil}} diff --git a/doc/projects.md b/doc/projects.md index 3f70ff57..2a337adb 100644 --- a/doc/projects.md +++ b/doc/projects.md @@ -40,6 +40,9 @@ The following libraries and projects are known to work with babashka. - [rewrite-edn](#rewrite-edn) - [expound](#expound) - [omniconf](#omniconf) + - [slingshot](#slingshot) + - [hasch](#hasch) + - [crispin](#crispin) - [Pods](#pods) - [Projects](#projects-1) - [babashka-test-action](#babashka-test-action) @@ -598,6 +601,33 @@ NOTE: hasch's tests pass with babashka except the test around hashing records. This is due to a difference in how records are implemented in babashka. This may be fixed later if this turns out to be really useful. +### [crispin](https://github.com/dunaj-project/crispin) + +Populate a configuration map from multiple sources (environment variables, +system variables, config files, etc.) + +Example: + +script.clj +``` clojure +#!/usr/bin/env bb + +(ns script + (:require [babashka.deps :as deps])) + +(deps/add-deps + '{:deps {crispin/crispin {:mvn/version "0.3.8"}}}) + +(require '[crispin.core :as crispin]) +(def app-cfg (crispin/cfg)) +(app-cfg :foo) +``` + +``` text +FOO=1 script.clj +"1" +``` + ## Pods [Babashka pods](https://github.com/babashka/babashka.pods) are programs that can diff --git a/test-resources/lib_tests/babashka/run_all_libtests.clj b/test-resources/lib_tests/babashka/run_all_libtests.clj index 723ad4ee..44a6ebe3 100644 --- a/test-resources/lib_tests/babashka/run_all_libtests.clj +++ b/test-resources/lib_tests/babashka/run_all_libtests.clj @@ -223,6 +223,8 @@ (test-namespaces 'omniconf.core-test) +(test-namespaces 'crispin.core-test) + ;;;; final exit code (let [{:keys [:test :fail :error] :as m} @status] diff --git a/test-resources/lib_tests/crispin/core_test.clj b/test-resources/lib_tests/crispin/core_test.clj new file mode 100644 index 00000000..fbb6e7f6 --- /dev/null +++ b/test-resources/lib_tests/crispin/core_test.clj @@ -0,0 +1,22 @@ +(ns crispin.core-test + (:require [clojure.test :refer [deftest is testing]] + [crispin.core :as cfg])) + +(deftest crispin.core-test + (testing "config from multiple sources" + (do + (cfg/load-custom-cfg! "test-resources/lib_tests/crispin" "crispin-test-custom-cfg.edn") + (System/setProperty "crispintest.value" "yes") + (System/setProperty "crispin" "test-resources/lib_tests/crispin/crispin-test-cfg.edn") + (let [c (cfg/cfg)] + ; something from the environment + (is (not-empty (cfg/sget c :path))) + ; things from the resource named by the :crispin property + (is (= "pina colada" (cfg/sget-in c [:likes 0]))) + (is (= 3.14 (cfg/nget-in c [:crispintest :pi]))) + ; something from system properties + (is (true? (cfg/bget-in c [:crispintest :value]))) + ; something from load-custom-cfg! file + (is (= :bar (:foo c)))) + (System/clearProperty "crispintest.value") + (System/clearProperty "crispin")))) diff --git a/test-resources/lib_tests/crispin/crispin-test-cfg.edn b/test-resources/lib_tests/crispin/crispin-test-cfg.edn new file mode 100644 index 00000000..303c2ac9 --- /dev/null +++ b/test-resources/lib_tests/crispin/crispin-test-cfg.edn @@ -0,0 +1,2 @@ +{:crispintest {:pi 3.14} + :likes ["pina colada" "getting caught in the rain"]} diff --git a/test-resources/lib_tests/crispin/crispin-test-custom-cfg.edn b/test-resources/lib_tests/crispin/crispin-test-custom-cfg.edn new file mode 100644 index 00000000..cf1c0f08 --- /dev/null +++ b/test-resources/lib_tests/crispin/crispin-test-custom-cfg.edn @@ -0,0 +1 @@ +{:foo :bar} From b95a40c4f29d6cf8ea2543c8bb4e92595ced559e Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Wed, 7 Jul 2021 16:16:15 +0200 Subject: [PATCH 46/65] sci docs [skip ci] --- sci | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sci b/sci index e80a2093..34bc45b0 160000 --- a/sci +++ b/sci @@ -1 +1 @@ -Subproject commit e80a2093722c510ef7988ed4e3b0d9f19f821b52 +Subproject commit 34bc45b0531b52ca2a7a8d8b21b0d86f30f697cf From 46892580c27c1a09edda2125a140a2e8058c6ad0 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Wed, 7 Jul 2021 21:17:57 +0200 Subject: [PATCH 47/65] [#921, #922] clojure.data.json support, first steps --- sci | 2 +- src/babashka/impl/classes.clj | 6 ++++++ src/babashka/impl/pprint.clj | 22 ++++++++++++++++------ src/babashka/main.clj | 4 +++- 4 files changed, 26 insertions(+), 8 deletions(-) diff --git a/sci b/sci index 34bc45b0..e4cfa161 160000 --- a/sci +++ b/sci @@ -1 +1 @@ -Subproject commit 34bc45b0531b52ca2a7a8d8b21b0d86f30f697cf +Subproject commit e4cfa161b06fa3cfe2c18342aaf8d7ffe2d5ae9d diff --git a/src/babashka/impl/classes.clj b/src/babashka/impl/classes.clj index d81a62ab..dd1cb527 100644 --- a/src/babashka/impl/classes.clj +++ b/src/babashka/impl/classes.clj @@ -111,11 +111,13 @@ java.io.StringReader java.io.StringWriter java.io.Writer + java.lang.Appendable java.lang.ArithmeticException java.lang.AssertionError java.lang.Boolean java.lang.Byte java.lang.Character + java.lang.CharSequence java.lang.Class java.lang.ClassNotFoundException java.lang.Comparable @@ -199,6 +201,7 @@ java.security.MessageDigest java.security.DigestInputStream java.security.SecureRandom + java.sql.Date java.text.ParseException ~@(when features/java-time? `[java.time.format.DateTimeFormatter @@ -329,6 +332,9 @@ clojure.lang.Sequential clojure.lang.Seqable clojure.lang.Volatile + java.util.concurrent.atomic.AtomicInteger + java.util.concurrent.atomic.AtomicLong + java.util.Collection java.util.List java.util.Iterator java.util.Map$Entry] diff --git a/src/babashka/impl/pprint.clj b/src/babashka/impl/pprint.clj index 073c2f7c..e598c0ae 100644 --- a/src/babashka/impl/pprint.clj +++ b/src/babashka/impl/pprint.clj @@ -1,8 +1,7 @@ (ns babashka.impl.pprint {:no-doc true} (:require [clojure.pprint :as pprint] - [sci.core :as sci] - [sci.impl.vars :as vars])) + [sci.core :as sci])) (defonce patch-option-table (alter-var-root #'pprint/write-option-table @@ -48,10 +47,8 @@ (alter-var-root #'pprint/write (constantly new-write)) -(def pprint-ns (vars/->SciNamespace 'clojure.pprint nil)) +(def pprint-ns (sci/create-ns 'clojure.pprint nil)) -(def print-right-margin - (sci/new-dynamic-var 'print-right-margin pprint/*print-right-margin* {:ns pprint-ns})) (defn print-table "Prints a collection of maps in a textual table. Prints table headings @@ -62,13 +59,20 @@ (binding [*out* @sci/out] (pprint/print-table ks rows)))) +(def print-right-margin + (sci/new-dynamic-var '*print-right-margin* pprint/*print-right-margin* {:ns pprint-ns})) + +(def print-pprint-dispatch + (sci/new-dynamic-var '*print-pprint-dispatch* pprint/*print-pprint-dispatch* {:ns pprint-ns})) + (defn pprint "Pretty print object to the optional output writer. If the writer is not provided, print the object to the currently bound value of *out*." ([s] (pprint s @sci/out)) ([s writer] - (binding [pprint/*print-right-margin* @print-right-margin] + (binding [pprint/*print-right-margin* @print-right-margin + #_#_pprint/*print-pprint-dispatch* @print-pprint-dispatch] (pprint/pprint s writer)))) (def pprint-namespace @@ -80,4 +84,10 @@ ;; we alter-var-root-ed write above, so this should copy the right function 'write (sci/copy-var pprint/write pprint-ns) 'simple-dispatch (sci/copy-var pprint/simple-dispatch pprint-ns) + ;; 'formatter-out (sci/copy-var pprint/formatter-out pprint-ns) + ;; 'cached-compile (sci/copy-var pprint/cached-compile pprint-ns) #_(sci/new-var 'cache-compile @#'pprint/cached-compile (meta @#'pprint/cached-compile)) + ;; 'init-navigator (sci/copy-var pprint/init-navigator pprint-ns) + ;; 'execute-format (sci/copy-var pprint/execute-format pprint-ns) + ;; 'with-pprint-dispatch (sci/copy-var pprint/with-pprint-dispatch pprint-ns) + ;; '*print-pprint-dispatch* print-pprint-dispatch }) diff --git a/src/babashka/main.clj b/src/babashka/main.clj index b6fcdb11..b96ae97c 100644 --- a/src/babashka/main.clj +++ b/src/babashka/main.clj @@ -409,13 +409,15 @@ Use bb run --help to show this help output. @(resolve 'babashka.impl.selmer/selmer-validator-namespace)))) (def imports - '{ArithmeticException java.lang.ArithmeticException + '{Appendable java.lang.Appendable + ArithmeticException java.lang.ArithmeticException AssertionError java.lang.AssertionError BigDecimal java.math.BigDecimal BigInteger java.math.BigInteger Boolean java.lang.Boolean Byte java.lang.Byte Character java.lang.Character + CharSequence java.lang.CharSequence Class java.lang.Class ClassNotFoundException java.lang.ClassNotFoundException Comparable java.lang.Comparable From 39e17f149bdd2237b9383d110297b68401033224 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Wed, 7 Jul 2021 21:20:21 +0200 Subject: [PATCH 48/65] CHANGELOG [skip ci] --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bbef42c7..4251f4a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,10 @@ Deps.clj: Update to v0.0.16 which corresponds to clojure CLI `1.10.3.855`. -Sci: minor perf improvements. +Sci: + +- Perf improvements +- `case` expression generated from macro doesn't work correctly ## 0.4.6 From 5430fee1fdcfa630447b88cddb2423eb049f9c6c Mon Sep 17 00:00:00 2001 From: Bob Date: Thu, 8 Jul 2021 14:18:01 -0400 Subject: [PATCH 49/65] ffclj link and logger example (#839 and #806) (#924) * add ffclj to libraries list * add simple logger macro to examples * add a missing link on projects page --- doc/projects.md | 5 +++++ examples/README.md | 10 ++++++++++ examples/logger.clj | 11 +++++++++++ 3 files changed, 26 insertions(+) create mode 100644 examples/logger.clj diff --git a/doc/projects.md b/doc/projects.md index 2a337adb..512d3e48 100644 --- a/doc/projects.md +++ b/doc/projects.md @@ -43,6 +43,7 @@ The following libraries and projects are known to work with babashka. - [slingshot](#slingshot) - [hasch](#hasch) - [crispin](#crispin) + - [ffclj](#ffclj) - [Pods](#pods) - [Projects](#projects-1) - [babashka-test-action](#babashka-test-action) @@ -628,6 +629,10 @@ FOO=1 script.clj "1" ``` +### [ffclj](https://github.com/luissantos/ffclj) + +A wrapper around executing `ffmpeg` and `ffprobe`. Supports progress reporting via core.async channels. + ## Pods [Babashka pods](https://github.com/babashka/babashka.pods) are programs that can diff --git a/examples/README.md b/examples/README.md index 7c958753..e02d648a 100644 --- a/examples/README.md +++ b/examples/README.md @@ -35,6 +35,7 @@ - [normalize-keywords.clj](#normalize-keywordsclj) - [Check stdin for data](#check-stdin-for-data) - [Using org.clojure/data.xml](#using-orgclojuredataxml) + - [Simple logger](#simple-logger) Here's a gallery of useful examples. Do you have a useful example? PR welcome! @@ -512,3 +513,12 @@ in use. $ bb examples/xml-example.clj ... some vaguely interesting XML manipulation output ``` + +## Simple logger + +[logger.clj](logger.clj) is a simple logger that works in bb. + +``` clojure +$ bb "(require 'logger) (logger/log \"the logger says hi\")" +:1:19 the logger says hi +``` diff --git a/examples/logger.clj b/examples/logger.clj new file mode 100644 index 00000000..bc2c48ad --- /dev/null +++ b/examples/logger.clj @@ -0,0 +1,11 @@ +(ns logger) + +(defmacro log [& msgs] + (let [m (meta &form) + _ns (ns-name *ns*) ;; can also be used for logging + file *file*] + `(binding [*out* *err*] ;; or bind to (io/writer log-file) + (println (str ~file ":" + ~(:line m) ":" + ~(:column m)) + ~@msgs)))) From d47290e996a4dcd02fab03caf854b0acd39672ef Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Sat, 10 Jul 2021 11:32:21 +0200 Subject: [PATCH 50/65] [#922,#927] pprint/formatter-out + cl-format with-out-str support (#930) --- sci | 2 +- src/babashka/impl/pprint.clj | 100 +++++++++++++++++++++++++++-------- test/babashka/main_test.clj | 46 +++++++++------- 3 files changed, 106 insertions(+), 42 deletions(-) diff --git a/sci b/sci index e4cfa161..96a54feb 160000 --- a/sci +++ b/sci @@ -1 +1 @@ -Subproject commit e4cfa161b06fa3cfe2c18342aaf8d7ffe2d5ae9d +Subproject commit 96a54feb9acb397a785d29a0307c8a6de2404c37 diff --git a/src/babashka/impl/pprint.clj b/src/babashka/impl/pprint.clj index e598c0ae..d1420cc4 100644 --- a/src/babashka/impl/pprint.clj +++ b/src/babashka/impl/pprint.clj @@ -3,7 +3,9 @@ (:require [clojure.pprint :as pprint] [sci.core :as sci])) -(defonce patch-option-table +(defonce patched? (volatile! false)) + +(when-not @patched? (alter-var-root #'pprint/write-option-table (fn [m] (zipmap (keys m) @@ -16,12 +18,21 @@ #(when-let [v (get t (key %))] [v (val %)]) m)))) -(alter-var-root #'pprint/table-ize (constantly new-table-ize)) +(when-not @patched? + (alter-var-root #'pprint/table-ize (constantly new-table-ize)) + (alter-meta! #'pprint/write-option-table dissoc :private) + (alter-meta! #'pprint/with-pretty-writer dissoc :private) + (alter-meta! #'pprint/pretty-writer? dissoc :private) + (alter-meta! #'pprint/make-pretty-writer dissoc :private) + (alter-meta! #'pprint/execute-format dissoc :private)) -(alter-meta! #'pprint/write-option-table dissoc :private) -(alter-meta! #'pprint/with-pretty-writer dissoc :private) -(alter-meta! #'pprint/pretty-writer? dissoc :private) -(alter-meta! #'pprint/make-pretty-writer dissoc :private) +(def pprint-ns (sci/create-ns 'clojure.pprint nil)) + +(def print-right-margin + (sci/new-dynamic-var '*print-right-margin* pprint/*print-right-margin* {:ns pprint-ns})) + +(def print-pprint-dispatch + (sci/new-dynamic-var '*print-pprint-dispatch* pprint/*print-pprint-dispatch* {:ns pprint-ns})) (def new-write (fn [object & kw-args] @@ -45,10 +56,8 @@ (if (nil? optval) (.toString ^java.io.StringWriter base-writer)))))))) -(alter-var-root #'pprint/write (constantly new-write)) - -(def pprint-ns (sci/create-ns 'clojure.pprint nil)) - +(when-not @patched? + (alter-var-root #'pprint/write (constantly new-write))) (defn print-table "Prints a collection of maps in a textual table. Prints table headings @@ -59,11 +68,19 @@ (binding [*out* @sci/out] (pprint/print-table ks rows)))) -(def print-right-margin - (sci/new-dynamic-var '*print-right-margin* pprint/*print-right-margin* {:ns pprint-ns})) - -(def print-pprint-dispatch - (sci/new-dynamic-var '*print-pprint-dispatch* pprint/*print-pprint-dispatch* {:ns pprint-ns})) +(defmacro formatter-out + "Makes a function which can directly run format-in. The function is + fn [& args] ... and returns nil. This version of the formatter macro is + designed to be used with *out* set to an appropriate Writer. In particular, + this is meant to be used as part of a pretty printer dispatch method. + format-in can be either a control string or a previously compiled format." + {:added "1.2"} + [format-in] + `(let [format-in# ~format-in + cf# (if (string? format-in#) (#'clojure.pprint/cached-compile format-in#) format-in#)] + (fn [& args#] + (let [navigator# (#'clojure.pprint/init-navigator args#)] + (#'clojure.pprint/execute-format cf# navigator#))))) (defn pprint "Pretty print object to the optional output writer. If the writer is not provided, @@ -72,22 +89,59 @@ (pprint s @sci/out)) ([s writer] (binding [pprint/*print-right-margin* @print-right-margin - #_#_pprint/*print-pprint-dispatch* @print-pprint-dispatch] + pprint/*print-pprint-dispatch* @print-pprint-dispatch] (pprint/pprint s writer)))) +(defn cl-format + "An implementation of a Common Lisp compatible format function. cl-format formats its +arguments to an output stream or string based on the format control string given. It +supports sophisticated formatting of structured data. +Writer is an instance of java.io.Writer, true to output to *out* or nil to output +to a string, format-in is the format control string and the remaining arguments +are the data to be formatted. +The format control string is a string to be output with embedded 'format directives' +describing how to format the various arguments passed in. +If writer is nil, cl-format returns the formatted result string. Otherwise, cl-format +returns nil. +For example: + (let [results [46 38 22]] + (cl-format true \"There ~[are~;is~:;are~]~:* ~d result~:p: ~{~d~^, ~}~%\" + (count results) results)) +Prints to *out*: + There are 3 results: 46, 38, 22 +Detailed documentation on format control strings is available in the \"Common Lisp the +Language, 2nd edition\", Chapter 22 (available online at: +http://www.cs.cmu.edu/afs/cs.cmu.edu/project/ai-repository/ai/html/cltl/clm/node200.html#SECTION002633000000000000000) +and in the Common Lisp HyperSpec at +http://www.lispworks.com/documentation/HyperSpec/Body/22_c.htm +" + [& args] + ;; bind *out* to sci/out, so with-out-str works + (binding [*out* @sci/out] + (apply pprint/cl-format args))) + +(defn execute-format + "We need to bind sci/out to *out* so all calls to clojure.core/print are directed + to the writer bound to *out* by the cl-format logic." + [& args] + (sci/binding [sci/out *out*] + (apply #'pprint/execute-format args))) + (def pprint-namespace {'pp (sci/copy-var pprint/pp pprint-ns) 'pprint (sci/copy-var pprint pprint-ns) 'print-table (sci/copy-var print-table pprint-ns) '*print-right-margin* print-right-margin - 'cl-format (sci/copy-var pprint/cl-format pprint-ns) + 'cl-format (sci/copy-var cl-format pprint-ns) ;; we alter-var-root-ed write above, so this should copy the right function 'write (sci/copy-var pprint/write pprint-ns) 'simple-dispatch (sci/copy-var pprint/simple-dispatch pprint-ns) - ;; 'formatter-out (sci/copy-var pprint/formatter-out pprint-ns) - ;; 'cached-compile (sci/copy-var pprint/cached-compile pprint-ns) #_(sci/new-var 'cache-compile @#'pprint/cached-compile (meta @#'pprint/cached-compile)) - ;; 'init-navigator (sci/copy-var pprint/init-navigator pprint-ns) - ;; 'execute-format (sci/copy-var pprint/execute-format pprint-ns) - ;; 'with-pprint-dispatch (sci/copy-var pprint/with-pprint-dispatch pprint-ns) - ;; '*print-pprint-dispatch* print-pprint-dispatch + 'formatter-out (sci/copy-var formatter-out pprint-ns) + 'cached-compile (sci/copy-var pprint/cached-compile pprint-ns) #_(sci/new-var 'cache-compile @#'pprint/cached-compile (meta @#'pprint/cached-compile)) + 'init-navigator (sci/copy-var pprint/init-navigator pprint-ns) + 'execute-format (sci/copy-var execute-format pprint-ns) + 'with-pprint-dispatch (sci/copy-var pprint/with-pprint-dispatch pprint-ns) + '*print-pprint-dispatch* print-pprint-dispatch }) + +(vreset! patched? true) diff --git a/test/babashka/main_test.clj b/test/babashka/main_test.clj index 63e4da43..ead8de87 100644 --- a/test/babashka/main_test.clj +++ b/test/babashka/main_test.clj @@ -12,10 +12,11 @@ [sci.core :as sci])) (defn bb [input & args] - (edn/read-string - {:readers *data-readers* - :eof nil} - (apply test-utils/bb (when (some? input) (str input)) (map str args)))) + (test-utils/normalize + (edn/read-string + {:readers *data-readers* + :eof nil} + (apply test-utils/bb (when (some? input) (str input)) (map str args))))) (deftest parse-opts-test (is (= "1667" @@ -170,20 +171,18 @@ (defn foo [x y] (+ x y))" name)) (is (= "(defn foo [x y]\n (+ x y))\n" - (test-utils/normalize - (bb nil (format " + (bb nil (format " (load-file \"%s\") (require '[clojure.repl :refer [source]]) (with-out-str (source %s/foo))" - (test-utils/escape-file-paths (.getPath tmp)) - name)))))) + (test-utils/escape-file-paths (.getPath tmp)) + name))))) (testing "print source from file on classpath" (is (= "(defn foo [x y]\n (+ x y))\n" - (test-utils/normalize - (bb nil - "-cp" dir - "-e" (format "(require '[clojure.repl :refer [source]] '[%s])" name) - "-e" (format "(with-out-str (source %s/foo))" name)))))))) + (bb nil + "-cp" dir + "-e" (format "(require '[clojure.repl :refer [source]] '[%s])" name) + "-e" (format "(with-out-str (source %s/foo))" name))))))) (deftest eval-test (is (= "120\n" (test-utils/bb nil "(eval '(do (defn foo [x y] (+ x y)) @@ -452,17 +451,28 @@ (is (string? (bb nil "(let [sw (java.io.StringWriter.)] (clojure.pprint/pprint (range 10) sw) (str sw))")))) (testing "*print-right-margin*" (is (= "(0\n 1\n 2\n 3\n 4\n 5\n 6\n 7\n 8\n 9)\n" - (test-utils/normalize (bb nil " + (bb nil " (let [sw (java.io.StringWriter.)] (binding [clojure.pprint/*print-right-margin* 5] - (clojure.pprint/pprint (range 10) sw)) (str sw))")))) + (clojure.pprint/pprint (range 10) sw)) (str sw))"))) (is (= "(0 1 2 3 4 5 6 7 8 9)\n" - (test-utils/normalize (bb nil " + (bb nil " (let [sw (java.io.StringWriter.)] (binding [clojure.pprint/*print-right-margin* 50] - (clojure.pprint/pprint (range 10) sw)) (str sw))"))))) + (clojure.pprint/pprint (range 10) sw)) (str sw))")))) (testing "print-table writes to sci/out" - (is (str/includes? (test-utils/bb "(with-out-str (clojure.pprint/print-table [{:a 1} {:a 2}]))") "----")))) + (is (str/includes? (test-utils/bb "(with-out-str (clojure.pprint/print-table [{:a 1} {:a 2}]))") "----"))) + (testing "cl-format writes to sci/out" + (is (= "[1, 2, 3]" (bb nil "(with-out-str (clojure.pprint/cl-format true \"~<[~;~@{~w~^, ~:_~}~;]~:>\" [1,2,3]))")))) + (testing "formatter-out" + (is (= "[1, 2, 3]\n" + (bb nil (pr-str '(do (require '[clojure.pprint :as pprint]) + (def print-array (pprint/formatter-out "~<[~;~@{~w~^, ~:_~}~;]~:>")) + (pprint/with-pprint-dispatch + #(if (seqable? %) + (print-array %) + (print %)) + (with-out-str (pprint/pprint [1 2 3])))))))))) (deftest read-string-test (testing "namespaced keyword via alias" From 9b6929e745ab11f8fbfb16e65685f64c6432f526 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Sat, 10 Jul 2021 11:33:45 +0200 Subject: [PATCH 51/65] CHANGELOG [skip ci] --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4251f4a9..c85832a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ Babashka proper: - `(read-line)` is buggy in REPL [#899](https://github.com/babashka/babashka/issues/899) - Add `java.io.FileInputStream`. This fixes compatibility with [replikativ/hasch](https://github.com/replikativ/hasch). - `babashka.tasks/clojure` with `:dir` option doesn't resolve deps in `:dir` [#914](https://github.com/babashka/babashka/issues/914) +- Support `pprint/formatter-out` [#922](https://github.com/babashka/babashka/issues/922) +- Support `pprint/cl-format` with `with-out-str` [#930](https://github.com/babashka/babashka/issues/930) Deps.clj: From 0832b0a480f78899f3b412a65c602416feddf933 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Sat, 10 Jul 2021 11:40:19 +0200 Subject: [PATCH 52/65] Fully support PushbackReader --- src/babashka/impl/classes.clj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/babashka/impl/classes.clj b/src/babashka/impl/classes.clj index dd1cb527..38fa9cfe 100644 --- a/src/babashka/impl/classes.clj +++ b/src/babashka/impl/classes.clj @@ -106,6 +106,7 @@ java.io.OutputStreamWriter java.io.PrintStream java.io.PushbackInputStream + java.io.PushbackReader java.io.Reader java.io.SequenceInputStream java.io.StringReader @@ -277,8 +278,7 @@ clojure.lang.MapEntry clojure.lang.LineNumberingPushbackReader java.io.EOFException - java.io.PrintWriter - java.io.PushbackReader] + java.io.PrintWriter] :methods [borkdude.graal.LockFix] ;; support for locking :fields [clojure.lang.PersistentQueue] From 02237c47ce3250e3b7d3350bf074993a177b3e69 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Sat, 10 Jul 2021 14:00:14 +0200 Subject: [PATCH 53/65] Fix windows tests --- test/babashka/test_utils.clj | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/test/babashka/test_utils.clj b/test/babashka/test_utils.clj index 8f9a75b2..0c6da084 100644 --- a/test/babashka/test_utils.clj +++ b/test/babashka/test_utils.clj @@ -14,15 +14,19 @@ (set! *warn-on-reflection* true) -(defn string-replace-if-windows [match replacement] - (fn [s] - (if main/windows? - (str/replace s match replacement) - s))) +(def normalize + (if main/windows? + (fn [s] (if (string? s) + (str/replace s "\r\n" "\n") + s)) + identity)) -(def normalize (string-replace-if-windows "\r\n" "\n")) - -(def escape-file-paths (string-replace-if-windows "\\" "\\\\")) +(def escape-file-paths + (if main/windows? + (fn [s] (if (string? s) + (str/replace s "\\" "\\\\") + s)) + identity)) (def ^:dynamic *bb-edn-path* nil) From 3deb154fca0d269f13db59e671139c32b890c743 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Sat, 10 Jul 2021 16:51:34 +0200 Subject: [PATCH 54/65] sci: function reference equality --- sci | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sci b/sci index 96a54feb..db70b23c 160000 --- a/sci +++ b/sci @@ -1 +1 @@ -Subproject commit 96a54feb9acb397a785d29a0307c8a6de2404c37 +Subproject commit db70b23cea63d7aa1ff5879909e577d846664f47 From 8c3759400661fca10e11170918b0a1f351644af1 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Sat, 10 Jul 2021 17:16:04 +0200 Subject: [PATCH 55/65] Add clojure.data.json tests --- deps.edn | 4 +- .../lib_tests/babashka/run_all_libtests.clj | 3 + .../lib_tests/clojure/data/json_test.clj | 425 ++++++++++++++++++ .../clojure/data/json_test_suite_test.clj | 393 ++++++++++++++++ 4 files changed, 824 insertions(+), 1 deletion(-) create mode 100644 test-resources/lib_tests/clojure/data/json_test.clj create mode 100644 test-resources/lib_tests/clojure/data/json_test_suite_test.clj diff --git a/deps.edn b/deps.edn index 61664cd3..88612fca 100644 --- a/deps.edn +++ b/deps.edn @@ -82,7 +82,9 @@ slingshot/slingshot {:mvn/version "0.12.2"} io.replikativ/hasch {:mvn/version "0.3.7"} com.grammarly/omniconf {:mvn/version "0.4.3"} - crispin/crispin {:mvn/version "0.3.8"}} + crispin/crispin {:mvn/version "0.3.8"} + org.clojure/data.json {:git/url "https://github.com/babashka/data.json.git" + :sha "7d4ae6a2923965bf2e83962f5268f69eaa4a9a57"}} :classpath-overrides {org.clojure/clojure nil org.clojure/spec.alpha nil org.clojure/core.specs.alpha nil}} diff --git a/test-resources/lib_tests/babashka/run_all_libtests.clj b/test-resources/lib_tests/babashka/run_all_libtests.clj index 44a6ebe3..0a46f1bd 100644 --- a/test-resources/lib_tests/babashka/run_all_libtests.clj +++ b/test-resources/lib_tests/babashka/run_all_libtests.clj @@ -225,6 +225,9 @@ (test-namespaces 'crispin.core-test) +(test-namespaces 'clojure.data.json-test + 'clojure.data.json-test-suite-test) + ;;;; final exit code (let [{:keys [:test :fail :error] :as m} @status] diff --git a/test-resources/lib_tests/clojure/data/json_test.clj b/test-resources/lib_tests/clojure/data/json_test.clj new file mode 100644 index 00000000..53984e46 --- /dev/null +++ b/test-resources/lib_tests/clojure/data/json_test.clj @@ -0,0 +1,425 @@ +(ns clojure.data.json-test + (:require [clojure.data.json :as json] + [clojure.test :refer :all] + [clojure.string :as str])) + +(deftest read-from-pushback-reader + (let [s (java.io.PushbackReader. (java.io.StringReader. "42"))] + (is (= 42 (json/read s))))) + +(deftest read-from-reader + (let [s (java.io.StringReader. "42")] + (is (= 42 (json/read s))))) + +(deftest read-numbers + (is (= 42 (json/read-str "42"))) + (is (= -3 (json/read-str "-3"))) + (is (= 3.14159 (json/read-str "3.14159"))) + (is (= 6.022e23 (json/read-str "6.022e23")))) + +(deftest read-bigint + (is (= 123456789012345678901234567890N + (json/read-str "123456789012345678901234567890")))) + +(deftest write-bigint + (is (= "123456789012345678901234567890" + (json/write-str 123456789012345678901234567890N)))) + +(deftest read-bigdec + (is (= 3.14159M (json/read-str "3.14159" :bigdec true)))) + +(deftest write-bigdec + (is (= "3.14159" (json/write-str 3.14159M)))) + +(deftest read-null + (is (= nil (json/read-str "null")))) + +(deftest read-strings + (is (= "Hello, World!" (json/read-str "\"Hello, World!\"")))) + +(deftest escaped-slashes-in-strings + (is (= "/foo/bar" (json/read-str "\"\\/foo\\/bar\"")))) + +(deftest unicode-escapes + (is (= " \u0beb " (json/read-str "\" \\u0bEb \"")))) + +(deftest unicode-outside-bmp + (is (= "\"smiling face: \uD83D\uDE03\"" + (json/write-str "smiling face: \uD83D\uDE03" :escape-unicode false))) + (is (= "\"smiling face: \\ud83d\\ude03\"" + (json/write-str "smiling face: \uD83D\uDE03" :escape-unicode true)))) + +(deftest escaped-whitespace + (is (= "foo\nbar" (json/read-str "\"foo\\nbar\""))) + (is (= "foo\rbar" (json/read-str "\"foo\\rbar\""))) + (is (= "foo\tbar" (json/read-str "\"foo\\tbar\"")))) + +(deftest read-booleans + (is (= true (json/read-str "true"))) + (is (= false (json/read-str "false")))) + +(deftest ignore-whitespace + (is (= nil (json/read-str "\r\n null")))) + +(deftest read-arrays + (is (= (vec (range 35)) + (json/read-str "[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34]"))) + (is (= ["Ole" "Lena"] (json/read-str "[\"Ole\", \r\n \"Lena\"]")))) + +(deftest read-objects + (is (= {:k1 1, :k2 2, :k3 3, :k4 4, :k5 5, :k6 6, :k7 7, :k8 8 + :k9 9, :k10 10, :k11 11, :k12 12, :k13 13, :k14 14, :k15 15, :k16 16} + (json/read-str "{\"k1\": 1, \"k2\": 2, \"k3\": 3, \"k4\": 4, + \"k5\": 5, \"k6\": 6, \"k7\": 7, \"k8\": 8, + \"k9\": 9, \"k10\": 10, \"k11\": 11, \"k12\": 12, + \"k13\": 13, \"k14\": 14, \"k15\": 15, \"k16\": 16}" + :key-fn keyword)))) + +(deftest read-nested-structures + (is (= {:a [1 2 {:b [3 "four"]} 5.5]} + (json/read-str "{\"a\":[1,2,{\"b\":[3,\"four\"]},5.5]}" + :key-fn keyword)))) + +(deftest read-nested-structures-stream + (is (= {:a [1 2 {:b [3 "four"]} 5.5]} + (json/read (java.io.StringReader. "{\"a\":[1,2,{\"b\":[3,\"four\"]},5.5]}") + :key-fn keyword)))) + +(deftest reads-long-string-correctly + (let [long-string (str/join "" (take 100 (cycle "abcde")))] + (is (= long-string (json/read-str (str "\"" long-string "\"")))))) + +(deftest disallows-non-string-keys + (is (thrown? Exception (json/read-str "{26:\"z\"")))) + +(deftest disallows-barewords + (is (thrown? Exception (json/read-str " foo ")))) + +(deftest disallows-unclosed-arrays + (is (thrown? Exception (json/read-str "[1, 2, ")))) + +(deftest disallows-unclosed-objects + (is (thrown? Exception (json/read-str "{\"a\":1, ")))) + +(deftest disallows-empty-entry-in-object + (is (thrown? Exception (json/read-str "{\"a\":1,}"))) + (is (thrown? Exception (json/read-str "{\"a\":1, }"))) + (is (thrown? Exception (json/read-str "{\"a\":1,,,,}"))) + (is (thrown? Exception (json/read-str "{\"a\":1,,\"b\":2}")))) + +(deftest get-string-keys + (is (= {"a" [1 2 {"b" [3 "four"]} 5.5]} + (json/read-str "{\"a\":[1,2,{\"b\":[3,\"four\"]},5.5]}")))) + +(deftest keywordize-keys + (is (= {:a [1 2 {:b [3 "four"]} 5.5]} + (json/read-str "{\"a\":[1,2,{\"b\":[3,\"four\"]},5.5]}" + :key-fn keyword)))) + +(deftest convert-values + (is (= {:number 42 :date (java.sql.Date. 55 6 12)} + (json/read-str "{\"number\": 42, \"date\": \"1955-07-12\"}" + :key-fn keyword + :value-fn (fn [k v] + (if (= :date k) + (java.sql.Date/valueOf v) + v)))))) + +(deftest omit-values + (is (= {:number 42} + (json/read-str "{\"number\": 42, \"date\": \"1955-07-12\"}" + :key-fn keyword + :value-fn (fn thisfn [k v] + (if (= :date k) + thisfn + v))))) + (is (= "{\"c\":1,\"e\":2}" + (json/write-str (sorted-map :a nil, :b nil, :c 1, :d nil, :e 2, :f nil) + :value-fn (fn remove-nils [k v] + (if (nil? v) + remove-nils + v)))))) + +(declare pass1-string) + +(deftest pass1-test + (let [input (json/read-str pass1-string)] + (is (= "JSON Test Pattern pass1" (first input))) + (is (= "array with 1 element" (get-in input [1 "object with 1 member" 0]))) + (is (= 1234567890 (get-in input [8 "integer"]))) + (is (= "rosebud" (last input))))) + +; from http://www.json.org/JSON_checker/test/pass1.json +(def pass1-string + "[ + \"JSON Test Pattern pass1\", + {\"object with 1 member\":[\"array with 1 element\"]}, + {}, + [], + -42, + true, + false, + null, + { + \"integer\": 1234567890, + \"real\": -9876.543210, + \"e\": 0.123456789e-12, + \"E\": 1.234567890E+34, + \"\": 23456789012E66, + \"zero\": 0, + \"one\": 1, + \"space\": \" \", + \"quote\": \"\\\"\", + \"backslash\": \"\\\\\", + \"controls\": \"\\b\\f\\n\\r\\t\", + \"slash\": \"/ & \\/\", + \"alpha\": \"abcdefghijklmnopqrstuvwyz\", + \"ALPHA\": \"ABCDEFGHIJKLMNOPQRSTUVWYZ\", + \"digit\": \"0123456789\", + \"0123456789\": \"digit\", + \"special\": \"`1~!@#$%^&*()_+-={':[,]}|;.?\", + \"hex\": \"\\u0123\\u4567\\u89AB\\uCDEF\\uabcd\\uef4A\", + \"true\": true, + \"false\": false, + \"null\": null, + \"array\":[ ], + \"object\":{ }, + \"address\": \"50 St. James Street\", + \"url\": \"http://www.JSON.org/\", + \"comment\": \"// /* */\": \" \", + \" s p a c e d \" :[1,2 , 3 + +, + +4 , 5 , 6 ,7 ],\"compact\":[1,2,3,4,5,6,7], + \"jsontext\": \"{\\\"object with 1 member\\\":[\\\"array with 1 element\\\"]}\", + \"quotes\": \"" \\u0022 %22 0x22 034 "\", + \"\\/\\\\\\\"\\uCAFE\\uBABE\\uAB98\\uFCDE\\ubcda\\uef4A\\b\\f\\n\\r\\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?\" +: \"A key can be any string\" + }, + 0.5 ,98.6 +, +99.44 +, + +1066, +1e1, +0.1e1, +1e-1, +1e00,2e+00,2e-00 +,\"rosebud\"]") + + +(deftest print-json-strings + (is (= "\"Hello, World!\"" (json/write-str "Hello, World!"))) + (is (= "\"\\\"Embedded\\\" Quotes\"" (json/write-str "\"Embedded\" Quotes")))) + +(deftest print-unicode + (is (= "\"\\u1234\\u4567\"" (json/write-str "\u1234\u4567")))) + +(deftest print-nonescaped-unicode + (is (= "\"\\u0000\\t\\u001f \"" (json/write-str "\u0000\u0009\u001f\u0020" :escape-unicode true))) + (is (= "\"\\u0000\\t\\u001f \"" (json/write-str "\u0000\u0009\u001f\u0020" :escape-unicode false))) + (is (= "\"\u1234\u4567\"" (json/write-str "\u1234\u4567" :escape-unicode false)))) + +(deftest escape-special-separators + (is (= "\"\\u2028\\u2029\"" (json/write-str "\u2028\u2029" :escape-unicode false))) + (is (= "\"\u2028\u2029\"" (json/write-str "\u2028\u2029" :escape-js-separators false)))) + +(deftest print-json-null + (is (= "null" (json/write-str nil)))) + +(deftest print-ratios-as-doubles + (is (= "0.75" (json/write-str 3/4)))) + +(deftest print-bigints + (is (= "12345678901234567890" (json/write-str 12345678901234567890)))) + +(deftest print-uuids + (let [uid (java.util.UUID/randomUUID) + roundtripped (java.util.UUID/fromString (json/read-str (json/write-str uid)))] + (is (= uid roundtripped)))) + +#_(def ^java.text.SimpleDateFormat date-format + (doto (java.text.SimpleDateFormat. "dd-MM-yyyy hh:mm:ss") + (.setTimeZone (java.util.TimeZone/getDefault)))) + +#_(deftest print-util-date + (let [date (.parse date-format "24-03-2006 15:49:00") + epoch-millis (.getTime date)] + (is (= epoch-millis (-> date + json/write-str + json/read-str + java.time.Instant/parse + .toEpochMilli))))) + +#_(deftest print-sql-date + (let [date (.parse date-format "24-03-2006 15:49:00") + sql-date (java.sql.Date. (.getTime date)) + epoch-millis-start-of-day (.getTime (.getTime (doto (java.util.Calendar/getInstance) + (.setTime date) + (.set java.util.Calendar/HOUR_OF_DAY 0) + (.set java.util.Calendar/MINUTE 0) + (.set java.util.Calendar/SECOND 0) + (.set java.util.Calendar/MILLISECOND 0))))] + (is (= epoch-millis-start-of-day (-> sql-date + json/write-str + json/read-str + java.time.Instant/parse + .toEpochMilli))))) + +(deftest print-time + (let [time (java.time.Instant/parse "2006-03-24T15:49:00.000Z")] + (is (= time (java.time.Instant/parse (json/read-str (json/write-str time))))))) + + +#_(deftest print-time-supports-format + (let [formatter (.withZone java.time.format.DateTimeFormatter/ISO_ZONED_DATE_TIME + (java.time.ZoneId/systemDefault)) + date (.parse date-format "24-03-2006 15:49:00") + time (.toInstant (.atZone (java.time.LocalDateTime/parse + "2006-03-24T15:49:00.000Z" + formatter) + (java.time.ZoneId/systemDefault)))] + (is (= time (->> (json/write-str date :date-formatter formatter) + json/read-str + (.parse formatter) + (java.time.Instant/from)))))) + +(deftest error-on-NaN + (is (thrown? Exception (json/write-str Float/NaN))) + (is (thrown? Exception (json/write-str Double/NaN)))) + +(deftest error-on-infinity + (is (thrown? Exception (json/write-str Float/POSITIVE_INFINITY))) + (is (thrown? Exception (json/write-str Float/NEGATIVE_INFINITY))) + (is (thrown? Exception (json/write-str Double/POSITIVE_INFINITY))) + (is (thrown? Exception (json/write-str Double/NEGATIVE_INFINITY)))) + +(defn- double-value [_ v] + (if (and (instance? Double v) + (or (.isNaN ^Double v) + (.isInfinite ^Double v))) + (str v) + v)) + +(deftest special-handler-for-double-NaN + (is (= "{\"double\":\"NaN\"}" + (json/write-str {:double Double/NaN} + :value-fn double-value)))) + +(deftest special-handler-for-double-infinity + (is (= "{\"double\":\"Infinity\"}" + (json/write-str {:double Double/POSITIVE_INFINITY} + :value-fn double-value))) + (is (= "{\"double\":\"-Infinity\"}" + (json/write-str {:double Double/NEGATIVE_INFINITY} + :value-fn double-value)))) + +(deftest print-json-arrays + (is (= "[1,2,3]" (json/write-str [1 2 3]))) + (is (= "[1,2,3]" (json/write-str (list 1 2 3)))) + (is (= "[1,2,3]" (json/write-str (sorted-set 1 2 3)))) + (is (= "[1,2,3]" (json/write-str (seq [1 2 3]))))) + +(deftest print-java-arrays + (is (= "[1,2,3]" (json/write-str (into-array [1 2 3]))))) + +(deftest print-empty-arrays + (is (= "[]" (json/write-str []))) + (is (= "[]" (json/write-str (list)))) + (is (= "[]" (json/write-str #{})))) + +(deftest print-json-objects + (is (= "{\"a\":1,\"b\":2}" (json/write-str (sorted-map :a 1 :b 2))))) + +(deftest object-keys-must-be-strings + (is (= "{\"1\":1,\"2\":2}" (json/write-str (sorted-map 1 1 2 2))))) + +(deftest print-empty-objects + (is (= "{}" (json/write-str {})))) + +(deftest accept-sequence-of-nils + (is (= "[null,null,null]" (json/write-str [nil nil nil])))) + +(deftest error-on-nil-keys + (is (thrown? Exception (json/write-str {nil 1})))) + +(deftest characters-in-symbols-are-escaped + (is (= "\"foo\\u1b1b\"" (json/write-str (symbol "foo\u1b1b"))))) + +(deftest default-throws-on-eof + (is (thrown? java.io.EOFException (json/read-str "")))) + +(deftest throws-eof-in-unterminated-array + (is (thrown? java.io.EOFException + (json/read-str "[1, ")))) + +(deftest throws-eof-in-unterminated-string + (is (thrown? java.io.EOFException + (json/read-str "\"missing end quote")))) + +(deftest throws-eof-in-escaped-chars + (is (thrown? java.io.EOFException + (json/read-str "\"\\")))) + +(deftest accept-eof + (is (= ::eof (json/read-str "" :eof-error? false :eof-value ::eof)))) + +(deftest characters-in-map-keys-are-escaped + (is (= "{\"\\\"\":42}" (json/write-str {"\"" 42})))) + +;;; Indent + +(deftest print-json-arrays-indent + (is (= "[\n 1,\n 2,\n 3\n]" (json/write-str [1 2 3] :indent true))) + (is (= "[\n 1,\n 2,\n 3\n]" (json/write-str (list 1 2 3) :indent true))) + (is (= "[\n 1,\n 2,\n 3\n]" (json/write-str (sorted-set 1 2 3) :indent true))) + (is (= "[\n 1,\n 2,\n 3\n]" (json/write-str (seq [1 2 3]) :indent true)))) + +(deftest print-java-arrays-indent + (is (= "[\n 1,\n 2,\n 3\n]" (json/write-str (into-array [1 2 3]) :indent true)))) + +(deftest print-empty-arrays-indent + (is (= "[]" (json/write-str [] :indent true))) + (is (= "[]" (json/write-str (list) :indent true))) + (is (= "[]" (json/write-str #{} :indent true)))) + +(deftest print-json-objects-indent + (is (= "{\n \"a\": 1,\n \"b\": 2\n}" (json/write-str (sorted-map :a 1 :b 2) :indent true)))) + +(deftest print-empty-objects-indent + (is (= "{}" (json/write-str {} :indent true)))) + +(deftest print-json-nested-indent + (is (= +"{ + \"a\": { + \"b\": [ + 1, + 2 + ], + \"c\": [], + \"d\": {} + } +}" (json/write-str {:a (sorted-map :b [1 2] :c [] :d {})} :indent true)))) + + +;;; Pretty-printer + +(deftest pretty-printing + (let [x (json/read-str pass1-string)] + (is (= x (json/read-str (with-out-str (json/pprint x))))))) + +(deftest pretty-print-nonescaped-unicode + (is (= "\"\u1234\u4567\"\n" + (with-out-str + (json/pprint "\u1234\u4567" :escape-unicode false))))) + +(defn benchmark [] + (dotimes [_ 8] + (time + (dotimes [_ 1000] + (assert (= (json/read-str pass1-string) + (json/read-str (json/write-str (json/read-str pass1-string))))))))) diff --git a/test-resources/lib_tests/clojure/data/json_test_suite_test.clj b/test-resources/lib_tests/clojure/data/json_test_suite_test.clj new file mode 100644 index 00000000..c0b714c3 --- /dev/null +++ b/test-resources/lib_tests/clojure/data/json_test_suite_test.clj @@ -0,0 +1,393 @@ +(ns clojure.data.json-test-suite-test + (:require [clojure.data.json :as json] + [clojure.test :refer :all] + [clojure.string :as str])) + +(deftest i-number-double-huge-neg-exp-test + (is (= [0.0] (json/read-str "[123.456e-789]")))) + +(deftest i-number-huge-exp-test + (is (= [##Inf] + (json/read-str "[0.4e00669999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999969999999006]")))) + +(deftest i-number-neg-int-huge-exp-test + (is (= [##-Inf] (json/read-str "[-1e+9999]")))) + +(deftest i-number-pos-double-huge-exp-test + (is (= [##Inf] (json/read-str "[1.5e+9999]")))) + +(deftest i-number-real-neg-overflow-test + (is (= [##-Inf] (json/read-str "[-123123e100000]")))) + +(deftest i-number-real-pos-overflow-test + (is (= [##Inf] (json/read-str "[123123e100000]")))) + +(deftest i-number-real-underflow-test + (is (= [0.0] (json/read-str "[123e-10000000]")))) + +(deftest i-number-too-big-neg-int-test + (is (= [-123123123123123123123123123123N] + (json/read-str "[-123123123123123123123123123123]")))) + +(deftest i-number-too-big-pos-int-test + (is (= [100000000000000000000N] (json/read-str "[100000000000000000000]")))) + +(deftest i-number-very-big-negative-int-test + (is (= [-237462374673276894279832749832423479823246327846N] + (json/read-str "[-237462374673276894279832749832423479823246327846]")))) + +(deftest n-array-1-true-without-comma-test + (is (thrown? Exception (json/read-str "[1 true]")))) + +(deftest n-array-colon-instead-of-comma-test + (is (thrown? Exception (json/read-str "[\"\": 1]")))) + +(deftest n-array-comma-and-number-test + (is (thrown? Exception (json/read-str "[,1]")))) + +(deftest n-array-double-comma-test + (is (thrown? Exception (json/read-str "[1,,2]")))) + +(deftest n-array-double-extra-comma-test + (is (thrown? Exception (json/read-str "[\"x\",,]")))) + +(deftest n-array-extra-comma-test + (is (thrown? Exception (json/read-str "[\"\",]")))) + +(deftest n-array-incomplete-invalid-value-test + (is (thrown? Exception (json/read-str "[x")))) + +(deftest n-array-incomplete-test + (is (thrown? Exception (json/read-str "[\"x\"")))) + +(deftest n-array-inner-array-no-comma-test + (is (thrown? Exception (json/read-str "[3[4]]")))) + +(deftest n-array-items-separated-by-semicolon-test + (is (thrown? Exception (json/read-str "[1:2]")))) + +(deftest n-array-just-comma-test + (is (thrown? Exception (json/read-str "[,]")))) + +(deftest n-array-just-minus-test + (is (thrown? Exception (json/read-str "[-]")))) + +(deftest n-array-missing-value-test + (is (thrown? Exception (json/read-str "[ , \"\"]")))) + +(deftest n-array-newlines-unclosed-test + (is (thrown? Exception (json/read-str "[\"a\",\n4\n,1,")))) + +(deftest n-array-number-and-comma-test + (is (thrown? Exception (json/read-str "[1,]")))) + +(deftest n-array-number-and-several-commas-test + (is (thrown? Exception (json/read-str "[1,,]")))) + +(deftest n-array-spaces-vertical-tab-formfeed-test + (is (thrown? Exception (json/read-str "[\" a\"\\f]")))) + +(deftest n-array-star-inside-test + (is (thrown? Exception (json/read-str "[*]")))) + +(deftest n-array-unclosed-test + (is (thrown? Exception (json/read-str "[\"\"")))) + +(deftest n-array-unclosed-trailing-comma-test + (is (thrown? Exception (json/read-str "[1,")))) + +(deftest n-array-unclosed-with-new-lines-test + (is (thrown? Exception (json/read-str "[1,\n1\n,1")))) + +(deftest n-array-unclosed-with-object-inside-test + (is (thrown? Exception (json/read-str "[{}")))) + +(deftest n-number-++-test + (is (thrown? Exception (json/read-str "[++1234]")))) + +(deftest n-number-+1-test + (is (thrown? Exception (json/read-str "[+1]")))) + +(deftest n-number-+Inf-test + (is (thrown? Exception (json/read-str "[+Inf]")))) + +(deftest n-number--01-test + (is (thrown? Exception (json/read-str "[-01]")))) + +(deftest n-number--1.0.-test + (is (thrown? Exception (json/read-str "[-1.0.]")))) + +(deftest n-number--2.-test + (is (thrown? Exception (json/read-str "[-2.]")))) + +(deftest n-number--NaN-test + (is (thrown? Exception (json/read-str "[-NaN]")))) + +(deftest n-number-.-1-test + (is (thrown? Exception (json/read-str "[.-1]")))) + +(deftest n-number-.2e-3-test + (is (thrown? Exception (json/read-str "[.2e-3]")))) + +(deftest n-number-0-capital-E+-test + (is (thrown? Exception (json/read-str "[0E+]")))) + +(deftest n-number-0-capital-E-test + (is (thrown? Exception (json/read-str "[0E]")))) + +(deftest n-number-0.1.2-test + (is (thrown? Exception (json/read-str "[0.1.2]")))) + +(deftest n-number-0.3e+-test + (is (thrown? Exception (json/read-str "[0.3e+]")))) + +(deftest n-number-0.3e-test + (is (thrown? Exception (json/read-str "[0.3e]")))) + +(deftest n-number-0.e1-test + (is (thrown? Exception (json/read-str "[0.e1]")))) + +(deftest n-number-0e+-test + (is (thrown? Exception (json/read-str "[0e+]")))) + +(deftest n-number-0e-test + (is (thrown? Exception (json/read-str "[0e]")))) + +(deftest n-number-1-000-test + (is (thrown? Exception (json/read-str "[1 000.0]")))) + +(deftest n-number-1.0e+-test + (is (thrown? Exception (json/read-str "[1.0e+]")))) + +(deftest n-number-1.0e--test + (is (thrown? Exception (json/read-str "[1.0e-]")))) + +(deftest n-number-1.0e-test + (is (thrown? Exception (json/read-str "[1.0e]")))) + +(deftest n-number-1eE2-test + (is (thrown? Exception (json/read-str "[1eE2]")))) + +(deftest n-number-2.e+3-test + (is (thrown? Exception (json/read-str "[2.e+3]")))) + +(deftest n-number-2.e-3-test + (is (thrown? Exception (json/read-str "[2.e-3]")))) + +(deftest n-number-2.e3-test + (is (thrown? Exception (json/read-str "[2.e3]")))) + +(deftest n-number-9.e+-test + (is (thrown? Exception (json/read-str "[9.e+]")))) + +(deftest n-number-Inf-test + (is (thrown? Exception (json/read-str "[Inf]")))) + +(deftest n-number-NaN-test + (is (thrown? Exception (json/read-str "[NaN]")))) + +(deftest n-number-expression-test + (is (thrown? Exception (json/read-str "[1+2]")))) + +(deftest n-number-hex-1-digit-test + (is (thrown? Exception (json/read-str "[0x1]")))) + +(deftest n-number-hex-2-digits-test + (is (thrown? Exception (json/read-str "[0x42]")))) + +(deftest n-number-infinity-test + (is (thrown? Exception (json/read-str "[Infinity]")))) + +(deftest n-number-invalid+--test + (is (thrown? Exception (json/read-str "[0e+-1]")))) + +(deftest n-number-invalid-negative-real-test + (is (thrown? Exception (json/read-str "[-123.123foo]")))) + +(deftest n-number-minus-infinity-test + (is (thrown? Exception (json/read-str "[-Infinity]")))) + +(deftest n-number-minus-sign-with-trailing-garbage-test + (is (thrown? Exception (json/read-str "[-foo]")))) + +(deftest n-number-minus-space-1-test + (is (thrown? Exception (json/read-str "[- 1]")))) + +(deftest n-number-neg-int-starting-with-zero-test + (is (thrown? Exception (json/read-str "[-012]")))) + +(deftest n-number-neg-real-without-int-part-test + (is (thrown? Exception (json/read-str "[-.123]")))) + +(deftest n-number-neg-with-garbage-at-end-test + (is (thrown? Exception (json/read-str "[-1x]")))) + +(deftest n-number-real-garbage-after-e-test + (is (thrown? Exception (json/read-str "[1ea]")))) + +(deftest n-number-real-without-fractional-part-test + (is (thrown? Exception (json/read-str "[1.]")))) + +(deftest n-number-starting-with-dot-test + (is (thrown? Exception (json/read-str "[.123]")))) + +(deftest n-number-with-alpha-char-test + (is (thrown? Exception (json/read-str "[1.8011670033376514H-308]")))) + +(deftest n-number-with-alpha-test + (is (thrown? Exception (json/read-str "[1.2a-3]")))) + +(deftest n-number-with-leading-zero-test + (is (thrown? Exception (json/read-str "[012]")))) + +(deftest n-object-non-string-key-but-huge-number-instead-test + (is (thrown? Exception (json/read-str "{9999E9999:1}")))) + +(deftest n-structure-array-with-unclosed-string-test + (is (thrown? Exception (json/read-str "[\"asd]")))) + +(deftest n-structure-end-array-test + (is (thrown? Exception (json/read-str "]")))) + +(deftest n-structure-number-with-trailing-garbage-test + (is (thrown? Exception (json/read-str "2@")))) + +(deftest n-structure-open-array-apostrophe-test + (is (thrown? Exception (json/read-str "['")))) + +(deftest n-structure-open-array-comma-test + (is (thrown? Exception (json/read-str "[,")))) + +(deftest n-structure-open-array-open-object-test + (is (thrown? Exception (json/read-str "[{")))) + +(deftest n-structure-open-array-open-string-test + (is (thrown? Exception (json/read-str "[\"a")))) + +(deftest n-structure-open-array-string-test + (is (thrown? Exception (json/read-str "[\"a\"")))) + +(deftest n-structure-open-object-close-array-test + (is (thrown? Exception (json/read-str "{]")))) + +(deftest n-structure-open-object-open-array-test + (is (thrown? Exception (json/read-str "{[")))) + +(deftest n-structure-unclosed-array-partial-null-test + (is (thrown? Exception (json/read-str "[ false, nul")))) + +(deftest n-structure-unclosed-array-test + (is (thrown? Exception (json/read-str "[1")))) + +(deftest n-structure-unclosed-array-unfinished-false-test + (is (thrown? Exception (json/read-str "[ true, fals")))) + +(deftest n-structure-unclosed-array-unfinished-true-test + (is (thrown? Exception (json/read-str "[ false, tru")))) + +(deftest y-array-arraysWithSpaces-test + (is (= [[]] (json/read-str "[[] ]")))) + +(deftest y-array-empty-string-test + (is (= [""] (json/read-str "[\"\"]")))) + +(deftest y-array-empty-test + (is (= [] (json/read-str "[]")))) + +(deftest y-array-ending-with-newline-test + (is (= ["a"] (json/read-str "[\"a\"]")))) + +(deftest y-array-false-test + (is (= [false] (json/read-str "[false]")))) + +(deftest y-array-heterogeneous-test + (is (= [nil 1 "1" {}] (json/read-str "[null, 1, \"1\", {}]")))) + +(deftest y-array-null-test + (is (= [nil] (json/read-str "[null]")))) + +(deftest y-array-with-1-and-newline-test + (is (= [1] (json/read-str "[1\n]")))) + +(deftest y-array-with-leading-space-test + (is (= [1] (json/read-str " [1]")))) + +(deftest y-array-with-several-null-test + (is (= [1 nil nil nil 2] (json/read-str "[1,null,null,null,2]")))) + +(deftest y-array-with-trailing-space-test + (is (= [2] (json/read-str "[2] ")))) + +(deftest y-number-0e+1-test + (is (= [0.0] (json/read-str "[0e+1]")))) + +(deftest y-number-0e1-test + (is (= [0.0] (json/read-str "[0e1]")))) + +(deftest y-number-after-space-test + (is (= [4] (json/read-str "[ 4]")))) + +(deftest y-number-double-close-to-zero-test + (is (= [-1.0E-78] + (json/read-str "[-0.000000000000000000000000000000000000000000000000000000000000000000000000000001]")))) + +(deftest y-number-int-with-exp-test + (is (= [200.0] (json/read-str "[20e1]")))) + +(deftest y-number-minus-zero-test + (is (= [0] (json/read-str "[-0]")))) + +(deftest y-number-negative-int-test + (is (= [-123] (json/read-str "[-123]")))) + +(deftest y-number-negative-one-test + (is (= [-1] (json/read-str "[-1]")))) + +(deftest y-number-negative-zero-test + (is (= [0] (json/read-str "[-0]")))) + +(deftest y-number-real-capital-e-neg-exp-test + (is (= [0.01] (json/read-str "[1E-2]")))) + +(deftest y-number-real-capital-e-pos-exp-test + (is (= [100.0] (json/read-str "[1E+2]")))) + +(deftest y-number-real-capital-e-test + (is (= [1.0E22] (json/read-str "[1E22]")))) + +(deftest y-number-real-exponent-test + (is (= [1.23E47] (json/read-str "[123e45]")))) + +(deftest y-number-real-fraction-exponent-test + (is (= [1.23456E80] (json/read-str "[123.456e78]")))) + +(deftest y-number-real-neg-exp-test + (is (= [0.01] (json/read-str "[1e-2]")))) + +(deftest y-number-real-pos-exponent-test + (is (= [100.0] (json/read-str "[1e+2]")))) + +(deftest y-number-simple-int-test + (is (= [123] (json/read-str "[123]")))) + +(deftest y-number-simple-real-test + (is (= [123.456789] (json/read-str "[123.456789]")))) + +(deftest y-number-test + (is (= [1.23E67] (json/read-str "[123e65]")))) + +(deftest y-object-extreme-numbers-test + (is (= {"min" -1.0E28, "max" 1.0E28} + (json/read-str "{\"min\": -1.0e+28, \"max\": 1.0e+28}")))) + +(deftest y-string-in-array-test + (is (= ["asd"] (json/read-str "[\"asd\"]")))) + +(deftest y-string-in-array-with-leading-space-test + (is (= ["asd"] (json/read-str "[ \"asd\"]")))) + +(deftest y-structure-true-in-array-test + (is (= [true] (json/read-str "[true]")))) + +(deftest y-structure-whitespace-array-test + (is (= [] (json/read-str " [] ")))) From 6a76a73e188ffddb03daeafd3dbfc99babf01920 Mon Sep 17 00:00:00 2001 From: Michiel Borkent Date: Sat, 10 Jul 2021 20:34:38 +0200 Subject: [PATCH 56/65] Use direct linking in profiler [skip ci] --- deps.edn | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/deps.edn b/deps.edn index 88612fca..ae413ed8 100644 --- a/deps.edn +++ b/deps.edn @@ -44,7 +44,8 @@ {:extra-deps {com.clojure-goes-fast/clj-async-profiler {:mvn/version "0.4.1"}} :extra-paths ["test"] - :jvm-opts ["-Djdk.attach.allowAttachSelf"] + :jvm-opts ["-Djdk.attach.allowAttachSelf" + "-Dclojure.compiler.direct-linking=true"] :main-opts ["-m" "babashka.profile"]} :lib-tests {:extra-paths ["process/src" "process/test"] From b6e65c08a8fef8d04d9ad46685a99b4902e52e89 Mon Sep 17 00:00:00 2001 From: Bob Date: Sat, 10 Jul 2021 15:39:23 -0400 Subject: [PATCH 57/65] add cl-format tests for nil and Writer args (#931) --- test/babashka/main_test.clj | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/test/babashka/main_test.clj b/test/babashka/main_test.clj index ead8de87..22f57620 100644 --- a/test/babashka/main_test.clj +++ b/test/babashka/main_test.clj @@ -462,8 +462,16 @@ (clojure.pprint/pprint (range 10) sw)) (str sw))")))) (testing "print-table writes to sci/out" (is (str/includes? (test-utils/bb "(with-out-str (clojure.pprint/print-table [{:a 1} {:a 2}]))") "----"))) - (testing "cl-format writes to sci/out" - (is (= "[1, 2, 3]" (bb nil "(with-out-str (clojure.pprint/cl-format true \"~<[~;~@{~w~^, ~:_~}~;]~:>\" [1,2,3]))")))) + (testing "cl-format outputs" + (testing "cl-format true writes to sci/out" + (is (= "[1, 2, 3]" (bb nil "(with-out-str (clojure.pprint/cl-format true \"~<[~;~@{~w~^, ~:_~}~;]~:>\" [1,2,3]))")))) + (testing "cl-format nil returns a string" + (is (= "forty-two" (bb nil "(clojure.pprint/cl-format nil \"~R\" 42)")))) + (testing "cl-format with a writer uses the writer" + (is (= "1,234,567 " (bb nil " +(let [sw (java.io.StringWriter.)] + (clojure.pprint/cl-format sw \"~15@<~:d~>\" 1234567) + (str sw))"))))) (testing "formatter-out" (is (= "[1, 2, 3]\n" (bb nil (pr-str '(do (require '[clojure.pprint :as pprint]) From af6f94ef81712769b5cc053d04d45c9b96d78e30 Mon Sep 17 00:00:00 2001 From: Bob Date: Sun, 11 Jul 2021 18:00:14 -0400 Subject: [PATCH 58/65] run lib tests in Windows CI (#933) * run lib tests in Windows CI - add batch scripts for invoking tests - skip some tests on windows - tweak a couple tests to run on linux and windows * configure git to checkout with Windows line endings on Appveyor --- appveyor.yml | 3 +++ script/lib_tests/run_all_libtests.bat | 5 ++++ script/run_lib_tests.bat | 1 + .../lib_tests/babashka/run_all_libtests.clj | 24 ++++++++++++------- .../lib_tests/clojure/data/json_test.clj | 2 +- test-resources/lib_tests/selmer/core_test.clj | 3 +-- 6 files changed, 26 insertions(+), 12 deletions(-) create mode 100644 script/lib_tests/run_all_libtests.bat create mode 100644 script/run_lib_tests.bat diff --git a/appveyor.yml b/appveyor.yml index 2650deff..cff66027 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -17,6 +17,7 @@ cache: - 'graalvm -> appveyor.yml' clone_script: +- cmd: git config --global core.autocrlf true - ps: >- if(-not $env:APPVEYOR_PULL_REQUEST_NUMBER) { git clone -q --branch=$env:APPVEYOR_REPO_BRANCH https://github.com/$env:APPVEYOR_REPO_NAME.git $env:APPVEYOR_BUILD_FOLDER @@ -71,6 +72,8 @@ build_script: call script/test.bat + call script/run_lib_tests.bat + artifacts: - path: babashka-*-windows-amd64.zip name: babashka diff --git a/script/lib_tests/run_all_libtests.bat b/script/lib_tests/run_all_libtests.bat new file mode 100644 index 00000000..015073a1 --- /dev/null +++ b/script/lib_tests/run_all_libtests.bat @@ -0,0 +1,5 @@ +if "%BABASHKA_TEST_ENV%" EQU "native" (set BB_CMD=.\bb) else (set BB_CMD=lein bb) + +for /f %%i in ('.\bb clojure -A:lib-tests -Spath') do set BABASHKA_CLASSPATH=%%i + +%BB_CMD% -cp "%BABASHKA_CLASSPATH%;test-resources/lib_tests" -f test-resources/lib_tests/babashka/run_all_libtests.clj %* diff --git a/script/run_lib_tests.bat b/script/run_lib_tests.bat new file mode 100644 index 00000000..003786b9 --- /dev/null +++ b/script/run_lib_tests.bat @@ -0,0 +1 @@ +call script/lib_tests/run_all_libtests.bat %* || exit /B 1 diff --git a/test-resources/lib_tests/babashka/run_all_libtests.clj b/test-resources/lib_tests/babashka/run_all_libtests.clj index 0a46f1bd..a9b11e6d 100644 --- a/test-resources/lib_tests/babashka/run_all_libtests.clj +++ b/test-resources/lib_tests/babashka/run_all_libtests.clj @@ -1,5 +1,6 @@ (ns babashka.run-all-libtests (:require [clojure.java.io :as io] + [clojure.string :as str] [clojure.test :as t])) (def ns-args (set (map symbol *command-line-args*))) @@ -19,6 +20,10 @@ (swap! status (fn [status] (merge-with + status (dissoc m :type)))))))) +(def windows? (-> (System/getProperty "os.name") + (str/lower-case) + (str/includes? "win"))) + ;;;; clj-http-lite (test-namespaces 'clj-http.lite.client-test) @@ -38,8 +43,8 @@ (prn (random-uuid)) ;;;; babashka.curl - -(test-namespaces 'babashka.curl-test) +; skip tests on Windows because of the :compressed thing +(when-not windows? (test-namespaces 'babashka.curl-test)) ;;;; cprop @@ -114,7 +119,8 @@ (require '[babashka.curl :as curl]) (spit "deps_test.clj" - (:body (curl/get "https://raw.githubusercontent.com/borkdude/deps.clj/master/deps.clj"))) + (:body (curl/get "https://raw.githubusercontent.com/borkdude/deps.clj/master/deps.clj" + (if windows? {:compressed false} {})))) (binding [*command-line-args* ["-Sdescribe"]] (load-file "deps_test.clj")) @@ -170,13 +176,13 @@ (test-namespaces 'httpkit.client-test) ;;;; babashka.process +(when-not windows? + ;; test built-in babashka.process + (test-namespaces 'babashka.process-test) -;; test built-in babashka.process -(test-namespaces 'babashka.process-test) - -;; test babashka.process from source -(require '[babashka.process] :reload) -(test-namespaces 'babashka.process-test) + ;; test babashka.process from source + (require '[babashka.process] :reload) + (test-namespaces 'babashka.process-test)) (test-namespaces 'core-match.core-tests) diff --git a/test-resources/lib_tests/clojure/data/json_test.clj b/test-resources/lib_tests/clojure/data/json_test.clj index 53984e46..9e905279 100644 --- a/test-resources/lib_tests/clojure/data/json_test.clj +++ b/test-resources/lib_tests/clojure/data/json_test.clj @@ -413,7 +413,7 @@ (is (= x (json/read-str (with-out-str (json/pprint x))))))) (deftest pretty-print-nonescaped-unicode - (is (= "\"\u1234\u4567\"\n" + (is (= (str "\"\u1234\u4567\"" (System/lineSeparator)) (with-out-str (json/pprint "\u1234\u4567" :escape-unicode false))))) diff --git a/test-resources/lib_tests/selmer/core_test.clj b/test-resources/lib_tests/selmer/core_test.clj index ddf65652..a2f35782 100644 --- a/test-resources/lib_tests/selmer/core_test.clj +++ b/test-resources/lib_tests/selmer/core_test.clj @@ -1048,7 +1048,7 @@ ;; (is (nil? *custom-resource-path*))) (deftest custom-resource-path-setting-url - (p/set-resource-path! (clojure.java.io/resource "templates/inheritance")) + (p/set-resource-path! "templates/inheritance") #_(is (string? *custom-resource-path*)) (is (= (fix-line-sep "Hello, World!\n") (render-file "foo.html" {:name "World"}))) (p/set-resource-path! nil)) @@ -1257,4 +1257,3 @@ "debug-value")) (testing "basic rendering escapes HTML" (is (str/includes? (basic-edn->html {:a "
"}) """))))
-

From 220037c681b601902c8fcd3a5be6b08250bc4ce7 Mon Sep 17 00:00:00 2001
From: Michiel Borkent 
Date: Mon, 12 Jul 2021 12:10:54 +0200
Subject: [PATCH 59/65] borkdude/sci#589: fix stacktrace with invalid import

---
 CHANGELOG.md | 1 +
 sci          | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c85832a4..7f41c207 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -21,6 +21,7 @@ Sci:
 
 - Perf improvements
 - `case` expression generated from macro doesn't work correctly
+- Fix stacktrace with invalid import [borkdude/sci#589](https://github.com/borkdude/sci/issues/589)
 
 ## 0.4.6
 
diff --git a/sci b/sci
index db70b23c..edff738f 160000
--- a/sci
+++ b/sci
@@ -1 +1 @@
-Subproject commit db70b23cea63d7aa1ff5879909e577d846664f47
+Subproject commit edff738f0c2eeb8959292882c3be64d0155e2f84

From bb50b6a9421a84f76ef89a27504d49584248f405 Mon Sep 17 00:00:00 2001
From: Michiel Borkent 
Date: Mon, 12 Jul 2021 15:32:31 +0200
Subject: [PATCH 60/65] Update links in dev doc [skip ci]

---
 doc/dev.md | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/doc/dev.md b/doc/dev.md
index d9e4e15c..2450c386 100644
--- a/doc/dev.md
+++ b/doc/dev.md
@@ -7,7 +7,7 @@ You need [lein](https://leiningen.org/) for running JVM tests and/or producing u
 To work on Babashka itself make sure Git submodules are checked out.
 
 ``` shellsession
-$ git clone https://github.com/borkdude/babashka --recursive
+$ git clone https://github.com/babashka/babashka --recursive
 ```
 
 To update later on:
@@ -66,7 +66,7 @@ Findings from various experiments with JDBC drivers in babashka:
   20MB to the binary. Since sqlite has a nice CLI we could also just shell out
   to it (there's an example in the examples dir). We could also build a
   `babashka.sqlite` namespace around the CLI maybe similar to
-  `babashka.curl`. See [#385](https://github.com/borkdude/babashka/issues/385)
+  `babashka.curl`. See [#385](https://github.com/babashka/babashka/issues/385)
   for details.
 - HSQLDB: easy to get going with Graalvm. Adds 10 MB to the binary. It's under a
   feature flag right now on master. See [build.md](build.md) for details. Derby
@@ -75,7 +75,7 @@ Findings from various experiments with JDBC drivers in babashka:
   got it to crash. 4800m did work, but it took 17 minutes (compared to 10
   minutes without this feature).
 - MySQL / MariaDB: can't get those to work yet. Work in progress in issue
-  [#387](https://github.com/borkdude/babashka/issues/387).
+  [#387](https://github.com/babashka/babashka/issues/387).
 
 To progress work on sqlite and mySQL, I need a working Clojure example. If you
 want to contribute, consider making a an example Clojure GraalVM CLI that puts

From 28f986e201e2cce22f8afc086ac9c00cd330b1ab Mon Sep 17 00:00:00 2001
From: Michiel Borkent 
Date: Mon, 12 Jul 2021 16:59:10 +0200
Subject: [PATCH 61/65] [#934] pick up env vars from :extra-env in deps step

---
 deps.clj                   | 2 +-
 src/babashka/impl/deps.clj | 6 ++++--
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/deps.clj b/deps.clj
index 2d1f34b2..985e5ca7 160000
--- a/deps.clj
+++ b/deps.clj
@@ -1 +1 @@
-Subproject commit 2d1f34b253d2f8a3e91c633e835cad987467aa38
+Subproject commit 985e5ca7f9cb123f86a0747aded1ee98e1f3deee
diff --git a/src/babashka/impl/deps.clj b/src/babashka/impl/deps.clj
index 4200e90a..40aef913 100644
--- a/src/babashka/impl/deps.clj
+++ b/src/babashka/impl/deps.clj
@@ -56,7 +56,7 @@
   keywords) which will used to calculate classpath. The classpath is
   then used to resolve dependencies in babashka."
   ([deps-map] (add-deps deps-map nil))
-  ([deps-map {:keys [:aliases]}]
+  ([deps-map {:keys [:aliases :extra-env]}]
    (when-let [paths (:paths deps-map)]
      (cp/add-classpath (str/join cp/path-sep paths)))
    (when-let [deps-map (not-empty (dissoc deps-map :paths :tasks :raw :min-bb-version))]
@@ -70,7 +70,8 @@
                  "-Sdeps-file" "" ;; we reset deps file so the local deps.edn isn't used
                  ,]
            args (conj args (str "-A:" (str/join ":" (cons ":org.babashka/defaults" aliases))))
-           cp (with-out-str (apply deps/-main args))
+           cp (with-out-str (binding [deps/*extra-env* extra-env]
+                              (apply deps/-main args)))
            cp (str/trim cp)
            cp (str/replace cp (re-pattern (str cp/path-sep "+$")) "")]
        (cp/add-classpath cp)))))
@@ -110,6 +111,7 @@
                *out* @sci/out
                *err* @sci/err
                deps/*dir* (:dir opts)
+               deps/*extra-env* (:extra-env opts)
                deps/*process-fn* (fn
                                    ([cmd] (p/process cmd opts))
                                    ([cmd _] (p/process cmd opts)))

From 0a9d7cbc6fe1fbbe6163da5e92610b3605928a62 Mon Sep 17 00:00:00 2001
From: Michiel Borkent 
Date: Mon, 12 Jul 2021 17:07:29 +0200
Subject: [PATCH 62/65] Add Dig Gashinsky to sponsors [skip ci]

---
 README.md | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 06000b07..6bdb3c5e 100644
--- a/README.md
+++ b/README.md
@@ -383,13 +383,18 @@ This project exists thanks to all the people who contribute. [[Contribute](doc/d
 
 ### Financial Contributors
 
+#### Github Sponsors
+
+- [Dig Gashinsky](https://github.com/digash)
+
+#### OpenCollective
 Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/babashka/contribute)]
 
-#### Individuals
+##### Individuals
 
 
 
-#### Organizations
+##### Organizations
 
 Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/babashka/contribute)]
 

From a359bd174615326cfb4eb1090725a74efd7a5959 Mon Sep 17 00:00:00 2001
From: Michiel Borkent 
Date: Mon, 12 Jul 2021 22:50:07 +0200
Subject: [PATCH 63/65] Use data.json 2.4.0

---
 deps.edn | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/deps.edn b/deps.edn
index ae413ed8..e68e04de 100644
--- a/deps.edn
+++ b/deps.edn
@@ -84,8 +84,7 @@
                          io.replikativ/hasch {:mvn/version "0.3.7"}
                          com.grammarly/omniconf {:mvn/version "0.4.3"}
                          crispin/crispin {:mvn/version "0.3.8"}
-                         org.clojure/data.json {:git/url "https://github.com/babashka/data.json.git"
-                                                :sha     "7d4ae6a2923965bf2e83962f5268f69eaa4a9a57"}}
+                         org.clojure/data.json {:mvn/version "2.4.0"}}
             :classpath-overrides {org.clojure/clojure nil
                                   org.clojure/spec.alpha nil
                                   org.clojure/core.specs.alpha nil}}

From e996351dc930a14b4cbd7ad2706b005c625d01c2 Mon Sep 17 00:00:00 2001
From: Michiel Borkent 
Date: Sat, 10 Jul 2021 22:14:06 +0200
Subject: [PATCH 64/65] Add clojure.tools.logging + timbre

---
 CHANGELOG.md                 |   4 +
 deps.edn                     |   4 +-
 project.clj                  |   4 +-
 src/babashka/impl/timbre.clj | 137 +++++++++++++++++++++++++++++++++++
 src/babashka/main.clj        |   7 +-
 5 files changed, 153 insertions(+), 3 deletions(-)
 create mode 100644 src/babashka/impl/timbre.clj

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7f41c207..345fafa4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,12 +6,16 @@ For a list of breaking changes, check [here](#breaking-changes).
 
 Babashka proper:
 
+- Add `clojure.tools.logging` with `taoensso.timbre` as the default implementation
 - Passing form on Windows with question mark breaks evaluation [#889](https://github.com/babashka/babashka/issues/889)
 - `(read-line)` is buggy in REPL [#899](https://github.com/babashka/babashka/issues/899)
 - Add `java.io.FileInputStream`. This fixes compatibility with [replikativ/hasch](https://github.com/replikativ/hasch).
 - `babashka.tasks/clojure` with `:dir` option doesn't resolve deps in `:dir` [#914](https://github.com/babashka/babashka/issues/914)
 - Support `pprint/formatter-out` [#922](https://github.com/babashka/babashka/issues/922)
 - Support `pprint/cl-format` with `with-out-str` [#930](https://github.com/babashka/babashka/issues/930)
+- Compatibility with `org.clojure/data.json {:mvn/version "2.4.0}"`
+- Support passing `GITLIBS` via `:extra-env` in `clojure` to set git lib dir:
+  `(clojure {:extra-env {"GITLIBS" ".gitlib"}} ,,,) [#934](https://github.com/babashka/babashka/issues/934)`
 
 Deps.clj:
 
diff --git a/deps.edn b/deps.edn
index e68e04de..275b302e 100644
--- a/deps.edn
+++ b/deps.edn
@@ -37,7 +37,9 @@
         org.clojure/core.match {:mvn/version "1.0.0"}
         hiccup/hiccup {:mvn/version "2.0.0-alpha2"}
         rewrite-clj/rewrite-clj {:mvn/version "1.0.605-alpha"}
-        selmer/selmer {:mvn/version "1.12.40"}}
+        selmer/selmer {:mvn/version "1.12.40"}
+        com.taoensso/timbre {:mvn/version "5.1.2"}
+        org.clojure/tools.logging {:mvn/version "1.1.0"}}
  :aliases {:babashka/dev
            {:main-opts ["-m" "babashka.main"]}
            :profile
diff --git a/project.clj b/project.clj
index 72f22857..2b2c2787 100644
--- a/project.clj
+++ b/project.clj
@@ -23,7 +23,9 @@
                  [cheshire "5.10.0"]
                  [nrepl/bencode "1.1.0"]
                  [borkdude/sci.impl.reflector "0.0.1"]
-                 [org.clojure/test.check "1.1.0"]]
+                 [org.clojure/test.check "1.1.0"]
+                 [com.taoensso/timbre "5.1.2"]
+                 [org.clojure/tools.logging "1.1.0"]]
   :profiles {:feature/xml  {:source-paths ["feature-xml"]
                             :dependencies [[org.clojure/data.xml "0.2.0-alpha6"]]}
              :feature/yaml {:source-paths ["feature-yaml"]
diff --git a/src/babashka/impl/timbre.clj b/src/babashka/impl/timbre.clj
new file mode 100644
index 00000000..803cf80b
--- /dev/null
+++ b/src/babashka/impl/timbre.clj
@@ -0,0 +1,137 @@
+(ns babashka.impl.timbre
+  (:require [clojure.tools.logging]
+            [clojure.tools.logging.impl :as impl]
+            [sci.core :as sci]
+            [taoensso.encore :as enc :refer [have]]
+            [taoensso.timbre :as timbre]))
+
+;;;; timbre
+
+(def tns (sci/create-ns 'taoensso.timbre nil))
+
+(defn- fline [and-form] (:line (meta and-form)))
+
+(defmacro log! ; Public wrapper around `-log!`
+  "Core low-level log macro. Useful for tooling, etc.
+    * `level`    - must eval to a valid logging level
+    * `msg-type` - must eval to e/o #{:p :f nil}
+    * `opts`     - ks e/o #{:config :?err :?ns-str :?file :?line :?base-data :spying?}
+  Supports compile-time elision when compile-time const vals
+  provided for `level` and/or `?ns-str`."
+  [level msg-type args & [opts]]
+  (have [:or nil? sequential?] args) ; To allow -> (delay [~@args])
+  (let [{:keys [?ns-str] :or {?ns-str (str @sci/ns)}} opts]
+    ;; level, ns may/not be compile-time consts:
+    (when-not (timbre/-elide? level ?ns-str)
+      (let [{:keys [config ?err ?file ?line ?base-data spying?]
+             :or   {config 'taoensso.timbre/*config*
+                    ?err   :auto ; => Extract as err-type v0
+                    ?file  @sci/file
+                    ;; NB waiting on CLJ-865:
+                    ?line (fline &form)}} opts
+
+            ?file (when (not= ?file "NO_SOURCE_PATH") ?file)
+
+            ;; Identifies this particular macro expansion; note that this'll
+            ;; be fixed for any fns wrapping `log!` (notably `tools.logging`,
+            ;; `slf4j-timbre`, etc.):
+            callsite-id
+            (hash [level msg-type args ; Unevaluated args (arg forms)
+                   ?ns-str ?file ?line (rand)])]
+
+        `(taoensso.timbre/-log! ~config ~level ~?ns-str ~?file ~?line ~msg-type ~?err
+                                (delay [~@args]) ~?base-data ~callsite-id ~spying?)))))
+
+(defn make-ns [ns sci-ns ks]
+  (reduce (fn [ns-map [var-name var]]
+            (let [m (meta var)
+                  no-doc (:no-doc m)
+                  doc (:doc m)
+                  arglists (:arglists m)]
+              (if no-doc ns-map
+                  (assoc ns-map var-name
+                         (sci/new-var (symbol var-name) @var
+                                      (cond-> {:ns sci-ns
+                                               :name (:name m)}
+                                        (:macro m) (assoc :macro true)
+                                        doc (assoc :doc doc)
+                                        arglists (assoc :arglists arglists)))))))
+          {}
+          (select-keys (ns-publics ns) ks)))
+
+(def config (sci/new-dynamic-var '*config* timbre/*config* {:ns tns}))
+
+(defn swap-config! [f & args]
+  (apply sci/alter-var-root config f args))
+
+(defn set-level! [level] (swap-config! (fn [m] (assoc m :min-level level))))
+
+(def timbre-namespace
+  (assoc (make-ns 'taoensso.timbre tns ['trace 'tracef 'debug 'debugf
+                                        'info 'infof 'warn 'warnf
+                                        'error 'errorf
+                                        '-log! 'with-level
+                                        'println-appender 'spit-appender])
+         'log! (sci/copy-var log! tns)
+         '*config* config
+         'swap-config! (sci/copy-var swap-config! tns)
+         'set-level! (sci/copy-var set-level! tns)))
+
+;;;; clojure.tools.logging
+
+(defn- force-var "To support dynamic vars, etc."
+  [x] (if (instance? clojure.lang.IDeref x) (deref x) x))
+
+(deftype Logger [logger-ns-str timbre-config]
+  clojure.tools.logging.impl/Logger
+
+  (enabled? [_ level]
+    ;; No support for per-call config
+    (timbre/may-log? level logger-ns-str
+                     (force-var timbre-config)))
+
+  (write! [_ level throwable message]
+    (log! level :p
+          [message] ; No support for pre-msg raw args
+          {:config  (force-var timbre-config) ; No support for per-call config
+           :?ns-str logger-ns-str
+           :?file   nil ; No support
+           :?line   nil ; ''
+           :?err    throwable})))
+
+(deftype LoggerFactory [get-logger-fn]
+  clojure.tools.logging.impl/LoggerFactory
+  (name [_] "Timbre")
+  (get-logger [_ logger-ns] (get-logger-fn logger-ns)))
+
+(alter-var-root
+ #'clojure.tools.logging/*logger-factory*
+ (fn [_]
+   (LoggerFactory.
+    (enc/memoize (fn [logger-ns] (Logger. (str logger-ns) config))))))
+
+(def lns (sci/create-ns 'clojure.tools.logging nil))
+
+(defmacro log
+  "Evaluates and logs a message only if the specified level is enabled. See log*
+  for more details."
+  ([level message]
+   `(clojure.tools.logging/log ~level nil ~message))
+  ([level throwable message]
+   `(clojure.tools.logging/log ~(deref sci/ns) ~level ~throwable ~message))
+  ([logger-ns level throwable message]
+   `(clojure.tools.logging/log clojure.tools.logging/*logger-factory* ~logger-ns ~level ~throwable ~message))
+  ([logger-factory logger-ns level throwable message]
+   `(let [logger# (impl/get-logger ~logger-factory ~logger-ns)]
+      (if (impl/enabled? logger# ~level)
+        (clojure.tools.logging/log* logger# ~level ~throwable ~message)))))
+
+(def tools-logging-namespace
+  (assoc (make-ns 'clojure.tools.logging lns ['debug 'debugf 'info 'infof 'warn 'warnf 'error 'errorf
+                                              'logp 'logf '*logger-factory* 'log*])
+         'log (sci/copy-var log lns)))
+
+(def lins (sci/create-ns 'clojure.tools.logging.impl nil))
+
+(def tools-logging-impl-namespace
+  (make-ns 'clojure.tools.logging.impl lins ['get-logger 'enabled?]))
diff --git a/src/babashka/main.clj b/src/babashka/main.clj
index b96ae97c..30cd7a77 100644
--- a/src/babashka/main.clj
+++ b/src/babashka/main.clj
@@ -33,6 +33,8 @@
    [babashka.impl.socket-repl :as socket-repl]
    [babashka.impl.tasks :as tasks :refer [tasks-namespace]]
    [babashka.impl.test :as t]
+   [babashka.impl.timbre :refer [timbre-namespace tools-logging-namespace
+                                 tools-logging-impl-namespace]]
    [babashka.impl.tools.cli :refer [tools-cli-namespace]]
    [babashka.nrepl.server :as nrepl-server]
    [babashka.wait :as wait]
@@ -350,7 +352,10 @@ Use bb run --help to show this help output.
        'babashka.process process-namespace
        'clojure.core.server clojure-core-server
        'babashka.deps deps-namespace
-       'babashka.tasks tasks-namespace}
+       'babashka.tasks tasks-namespace
+       'taoensso.timbre timbre-namespace
+       'clojure.tools.logging tools-logging-namespace
+       'clojure.tools.logging.impl tools-logging-impl-namespace}
     features/xml?  (assoc 'clojure.data.xml @(resolve 'babashka.impl.xml/xml-namespace))
     features/yaml? (assoc 'clj-yaml.core @(resolve 'babashka.impl.yaml/yaml-namespace)
                           'flatland.ordered.map @(resolve 'babashka.impl.ordered/ordered-map-ns))

From 588cda9eac7968d30ab5ac95106ef5b77403d77c Mon Sep 17 00:00:00 2001
From: Michiel Borkent 
Date: Tue, 13 Jul 2021 11:31:36 +0200
Subject: [PATCH 65/65] [#934] Environment variables not picked up by
 tools.deps

---
 CHANGELOG.md                |  1 +
 src/babashka/impl/deps.clj  | 16 +++++++++-------
 src/babashka/main.clj       | 13 +++++++++----
 test/babashka/deps_test.clj | 28 +++++++++++++++++++++++++---
 test/babashka/main_test.clj |  4 ++--
 5 files changed, 46 insertions(+), 16 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 345fafa4..3b98c672 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,6 +16,7 @@ Babashka proper:
 - Compatibility with `org.clojure/data.json {:mvn/version "2.4.0}"`
 - Support passing `GITLIBS` via `:extra-env` in `clojure` to set git lib dir:
   `(clojure {:extra-env {"GITLIBS" ".gitlib"}} ,,,) [#934](https://github.com/babashka/babashka/issues/934)`
+- Add `--force` option to force recomputation of bababashka deps classpath.
 
 Deps.clj:
 
diff --git a/src/babashka/impl/deps.clj b/src/babashka/impl/deps.clj
index 40aef913..8e04c2a2 100644
--- a/src/babashka/impl/deps.clj
+++ b/src/babashka/impl/deps.clj
@@ -56,7 +56,7 @@
   keywords) which will used to calculate classpath. The classpath is
   then used to resolve dependencies in babashka."
   ([deps-map] (add-deps deps-map nil))
-  ([deps-map {:keys [:aliases :extra-env]}]
+  ([deps-map {:keys [:aliases :env :extra-env :force]}]
    (when-let [paths (:paths deps-map)]
      (cp/add-classpath (str/join cp/path-sep paths)))
    (when-let [deps-map (not-empty (dissoc deps-map :paths :tasks :raw :min-bb-version))]
@@ -65,12 +65,13 @@
                                 :classpath-overrides {org.clojure/clojure ""
                                                       org.clojure/spec.alpha ""
                                                       org.clojure/core.specs.alpha ""}})
-           args ["-Srepro" ;; do not include deps.edn from user config
-                 "-Spath" "-Sdeps" (str deps-map)
-                 "-Sdeps-file" "" ;; we reset deps file so the local deps.edn isn't used
-                 ,]
-           args (conj args (str "-A:" (str/join ":" (cons ":org.babashka/defaults" aliases))))
-           cp (with-out-str (binding [deps/*extra-env* extra-env]
+           args (list "-Srepro" ;; do not include deps.edn from user config
+                      "-Spath" "-Sdeps" (str deps-map)
+                      "-Sdeps-file" "") ;; we reset deps file so the local deps.edn isn't used
+           args (if force (cons "-Sforce" args) args)
+           args (concat args [(str "-A:" (str/join ":" (cons ":org.babashka/defaults" aliases)))])
+           cp (with-out-str (binding [deps/*env* env
+                                      deps/*extra-env* extra-env]
                               (apply deps/-main args)))
            cp (str/trim cp)
            cp (str/replace cp (re-pattern (str cp/path-sep "+$")) "")]
@@ -111,6 +112,7 @@
                *out* @sci/out
                *err* @sci/err
                deps/*dir* (:dir opts)
+               deps/*env* (:env opts)
                deps/*extra-env* (:extra-env opts)
                deps/*process-fn* (fn
                                    ([cmd] (p/process cmd opts))
diff --git a/src/babashka/main.clj b/src/babashka/main.clj
index 30cd7a77..b7811121 100644
--- a/src/babashka/main.clj
+++ b/src/babashka/main.clj
@@ -124,8 +124,9 @@ Substrate VM opts:
 
 Global opts:
 
-  -cp, --classpath         Classpath to use. Overrides bb.edn classpath.
-  --debug                  Print debug information and internal stacktrace in case of exception.
+  -cp, --classpath  Classpath to use. Overrides bb.edn classpath.
+  --debug           Print debug information and internal stacktrace in case of exception.
+  --force           Passes -Sforce to deps.clj, forcing recalculation of the classpath.
 
 Help:
 
@@ -505,9 +506,13 @@ Use bb run --help to show this help output.
           ("--doc")
           {:doc true
            :command-line-args (rest options)}
+          ;; renamed to --debug
           ("--verbose") (recur (next options)
                                (assoc opts-map
                                       :verbose? true))
+          ("--force") (recur (next options)
+                               (assoc opts-map
+                                      :force? true))
           ("--describe") (recur (next options)
                                 (assoc opts-map
                                        :describe? true))
@@ -675,7 +680,7 @@ Use bb run --help to show this help output.
                     :help :file :command-line-args
                     :expressions :stream?
                     :repl :socket-repl :nrepl
-                    :debug :classpath
+                    :debug :classpath :force?
                     :main :uberscript :describe?
                     :jar :uberjar :clojure
                     :doc :run :list-tasks]}
@@ -703,7 +708,7 @@ Use bb run --help to show this help output.
             _ (if classpath
                 (cp/add-classpath classpath)
                 ;; when classpath isn't set, we calculate it from bb.edn, if present
-                (when-let [bb-edn @common/bb-edn] (deps/add-deps bb-edn)))
+                (when-let [bb-edn @common/bb-edn] (deps/add-deps bb-edn {:force force?})))
             abs-path (when file
                        (let [abs-path (.getAbsolutePath (io/file file))]
                          (vars/bindRoot sci/file abs-path)
diff --git a/test/babashka/deps_test.clj b/test/babashka/deps_test.clj
index e7c9719e..01ff96e5 100644
--- a/test/babashka/deps_test.clj
+++ b/test/babashka/deps_test.clj
@@ -1,5 +1,6 @@
 (ns babashka.deps-test
   (:require
+   [babashka.fs :as fs]
    [babashka.test-utils :as test-utils]
    [clojure.edn :as edn]
    [clojure.test :as test :refer [deftest is testing]]))
@@ -10,7 +11,8 @@
     :eof nil}
    (apply test-utils/bb nil (map str args))))
 
-(deftest dependency-test (is (= #{:a :c :b} (bb "
+(deftest dependency-test
+  (is (= #{:a :c :b} (bb "
 (require '[babashka.deps :as deps])
 
 (deps/add-deps '{:deps {com.stuartsierra/dependency {:mvn/version \"1.0.0\"}}})
@@ -24,7 +26,19 @@
             (dep/depend :d :c)))
 
 (dep/transitive-dependencies g1 :d)
-"))))
+")))
+  (testing "GITLIBS can set location of .gitlibs dir"
+    (let [tmp-dir (fs/create-temp-dir)
+          libs-dir (fs/file tmp-dir ".gitlibs")
+          libs-dir2 (fs/file tmp-dir ".gitlibs2")]
+      (bb (pr-str `(do (babashka.deps/add-deps '{:deps {babashka/process {:git/url "https://github.com/babashka/process" :sha "4c6699d06b49773d3e5c5b4c11d3334fb78cc996"}}}
+                                               {:force true
+                                                :env {"GITLIBS" ~(str libs-dir)}}) nil)))
+      (bb (pr-str `(do (babashka.deps/add-deps '{:deps {babashka/process {:git/url "https://github.com/babashka/process" :sha "4c6699d06b49773d3e5c5b4c11d3334fb78cc996"}}}
+                                               {:force true
+                                                :extra-env {"GITLIBS" ~(str libs-dir2)}}) nil)))
+      (is (fs/exists? libs-dir))
+      (is (fs/exists? libs-dir2)))))
 
 (deftest clojure-test
   (testing "-Stree prints to *out*"
@@ -60,4 +74,12 @@ true
   (testing "start from other directory"
     (is (= {1 {:id 1}, 2 {:id 2}}
            (edn/read-string (bb "
-(:out @(babashka.deps/clojure [\"-M\" \"-e\" \"(require 'medley.core) (medley.core/index-by :id [{:id 1} {:id 2}])\"] {:out :string :dir \"test-resources/clojure-dir-test\"}))"))))))
+(:out @(babashka.deps/clojure [\"-M\" \"-e\" \"(require 'medley.core) (medley.core/index-by :id [{:id 1} {:id 2}])\"] {:out :string :dir \"test-resources/clojure-dir-test\"}))")))))
+  (testing "GITLIBS can set location of .gitlibs dir"
+    (let [tmp-dir (fs/create-temp-dir)
+          libs-dir (fs/file tmp-dir ".gitlibs")
+          libs-dir2 (fs/file tmp-dir ".gitlibs2")]
+      (bb (pr-str `(do (babashka.deps/clojure ["-Sforce" "-Spath" "-Sdeps" "{:deps {babashka/process {:git/url \"https://github.com/babashka/process\" :sha \"4c6699d06b49773d3e5c5b4c11d3334fb78cc996\"}}}"] {:out :string :env {"GITLIBS" ~(str libs-dir)}}) nil)))
+      (bb (pr-str `(do (babashka.deps/clojure ["-Sforce" "-Spath" "-Sdeps" "{:deps {babashka/process {:git/url \"https://github.com/babashka/process\" :sha \"4c6699d06b49773d3e5c5b4c11d3334fb78cc996\"}}}"] {:out :string :extra-env {"GITLIBS" ~(str libs-dir2)}}) nil)))
+      (is (fs/exists? libs-dir))
+      (is (fs/exists? libs-dir2)))))
diff --git a/test/babashka/main_test.clj b/test/babashka/main_test.clj
index 22f57620..8854383d 100644
--- a/test/babashka/main_test.clj
+++ b/test/babashka/main_test.clj
@@ -53,8 +53,8 @@
   (is (= '("-e" "1") (bb nil "-e" "*command-line-args*" "--" "-e" "1")))
   (let [v (bb nil "--describe")]
     (is (:babashka/version v))
-    (is (:feature/xml v))))
-
+    (is (:feature/xml v)))
+  (is (= {:force? true} (main/parse-opts ["--force"]))))
 
 (deftest version-test
   (is (= [1 0 0] (main/parse-version "1.0.0-SNAPSHOT")))