[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.
+ -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:
@@ -314,7 +322,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
@@ -345,7 +353,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))
@@ -404,13 +415,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
@@ -493,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))
@@ -663,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]}
@@ -691,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-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-resources/lib_tests/babashka/run_all_libtests.clj b/test-resources/lib_tests/babashka/run_all_libtests.clj
index e7dd18d3..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)
@@ -218,6 +224,16 @@
;; 'slingshot.test-test
)
+(test-namespaces 'hasch.test
+ )
+
+(test-namespaces 'omniconf.core-test)
+
+(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..9e905279
--- /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 (= (str "\"\u1234\u4567\"" (System/lineSeparator))
+ (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 " [] "))))
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}
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))
+
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"])))))
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 ""}) """))))
-
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/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..e54f7862 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,76 @@
(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")))))
+ (let [tmp-dir (fs/create-temp-dir)
+ 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}
+ (str ls-cmd " foobar"))}}
+ (bb "foo")
+ (is (str/includes? (slurp 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")
+ (shell {:out :string} "cat")
+ :out)}}
+ (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 {}
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..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*"
@@ -42,18 +56,30 @@
(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])
(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\"}))")))))
+ (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/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..3a9cc45a 100644
--- a/test/babashka/impl/clojure/java/shell_test.clj
+++ b/test/babashka/impl/clojure/java/shell_test.clj
@@ -1,9 +1,11 @@
(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 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\"}
@@ -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/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/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"))
diff --git a/test/babashka/main_test.clj b/test/babashka/main_test.clj
index a56bfc87..8854383d 100644
--- a/test/babashka/main_test.clj
+++ b/test/babashka/main_test.clj
@@ -12,12 +12,13 @@
[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 ^:windows parse-opts-test
+(deftest parse-opts-test
(is (= "1667"
(:nrepl (main/parse-opts ["--nrepl-server"]))))
(is (= "1666"
@@ -52,17 +53,17 @@
(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 ^: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)"))))
@@ -120,7 +121,7 @@
(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
(is (= "hello\n" (test-utils/bb nil "(println \"hello\")"))))
@@ -131,7 +132,7 @@
(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"))))
@@ -152,11 +153,11 @@
(.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
(let [tmp (java.io.File/createTempFile "lib" ".clj")
@@ -174,15 +175,14 @@
(load-file \"%s\")
(require '[clojure.repl :refer [source]])
(with-out-str (source %s/foo))"
- (.getPath tmp)
+ (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))
@@ -199,7 +199,8 @@
(is (true? (bb nil "(.exists (io/file \"README.md\"))")))
(is (true? (bb nil "(.canWrite (io/file \"README.md\"))"))))
-(deftest pipe-test
+; 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?))
(let [out (:out (sh "bash" "-c" "./bb -o '(range)' |
@@ -207,16 +208,22 @@
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 lazy-text-in-test
+(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*)'"))
out (edn/read-string out)]
@@ -232,8 +239,11 @@
@x)"))))
(deftest process-builder-test
- (is (str/includes? (bb nil "
-(def pb (ProcessBuilder. [\"ls\"]))
+ (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,24 +251,21 @@
(.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")]
- (is (= true
- (bb nil (format "(let [tdir (io/file \"%s\")
- tfile
- (File/createTempFile \"ctf\" \"tmp\" tdir)]
+ (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)]
@@ -270,7 +277,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\")
@@ -332,7 +339,7 @@
(deftest 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\")
@@ -341,20 +348,22 @@
(is (= "foobar\nbarfoo\n" (slurp path)))))
(deftest binding-test
- (is (= 6 (bb nil "(def w (java.io.StringWriter.))
+ (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\")))"))))
+ (is (= (if main/windows? 7 6)
+ (bb nil "(count (with-out-str (println \"hello\")))"))))
(deftest with-in-str-test
(is (= 5 (bb nil "(count (with-in-str \"hello\" (read-line)))"))))
(deftest 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')]
@@ -399,11 +408,14 @@
(is (true? (bb nil "(set! *warn-on-reflection* true)"))))
(deftest clojure-main-repl-test
- (is (= "\"> foo!\\nnil\\n> \"\n" (test-utils/bb nil "
+ (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
(is (true? (bb nil "(nil? *command-line-args*)")))
@@ -423,7 +435,7 @@
(deftest 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
@@ -438,16 +450,37 @@
(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"
+ (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 "
+ (is (= "(0 1 2 3 4 5 6 7 8 9)\n"
+ (bb nil "
(let [sw (java.io.StringWriter.)]
(binding [clojure.pprint/*print-right-margin* 50]
(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 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])
+ (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"
@@ -457,13 +490,18 @@
(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 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
;; One for downloading a small file and one for unzipping.
@@ -484,7 +522,7 @@
(deftest 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))))))
@@ -639,7 +677,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)))))")))
@@ -647,6 +685,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/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..0c6da084 100644
--- a/test/babashka/test_utils.clj
+++ b/test/babashka/test_utils.clj
@@ -8,16 +8,25 @@
[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]))
(set! *warn-on-reflection* true)
-
-(defn normalize [s]
+(def normalize
(if main/windows?
- (str/replace s "\r\n" "\n")
- s))
+ (fn [s] (if (string? s)
+ (str/replace s "\r\n" "\n")
+ s))
+ identity))
+
+(def escape-file-paths
+ (if main/windows?
+ (fn [s] (if (string? s)
+ (str/replace s "\\" "\\\\")
+ s))
+ identity))
(def ^:dynamic *bb-edn-path* nil)
@@ -26,11 +35,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)
@@ -47,7 +57,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))]
@@ -86,7 +97,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")
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..581a863d 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.main :as main]
+ [babashka.test-utils :as tu]
+ [clojure.string :as str]
+ [clojure.test :as t :refer [deftest is testing]]))
(defn count-entries [jar]
(with-open [jar-file (java.util.jar.JarFile. jar)]
@@ -44,17 +45,21 @@
(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)]
+ 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))))))