Add spec tests to CI
This commit is contained in:
parent
54cd1fa85f
commit
9dd4941230
4 changed files with 490 additions and 7 deletions
4
deps.edn
4
deps.edn
|
|
@ -53,8 +53,8 @@
|
|||
:lib-tests
|
||||
{:extra-paths ["process/src" "process/test" "test-resources/lib_tests"]
|
||||
:extra-deps {org.clj-commons/clj-http-lite {:mvn/version "0.4.392"}
|
||||
borkdude/spartan.spec {:git/url "https://github.com/borkdude/spartan.spec"
|
||||
:sha "7689f85d4c79de6c7b5ee3ab62e3e72eeccd3318"}
|
||||
org.babashka/spec.alpha {:git/url "https://github.com/babashka/spec.alpha"
|
||||
:sha "9597a68339ab6be83323345fc0cea4ce848266b9"}
|
||||
lambdaisland/regal {:git/url "https://github.com/lambdaisland/regal"
|
||||
:sha "f902d2c43121f9e1c48603d6eb99f5900eb6a9f6"}
|
||||
weavejester/medley {:git/url "https://github.com/weavejester/medley"
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
(ns babashka.run-all-libtests
|
||||
(:require [clojure.java.io :as io]
|
||||
[clojure.string :as str]
|
||||
[clojure.test :as t]
|
||||
[spartan.spec]))
|
||||
[clojure.test :as t]))
|
||||
|
||||
(require 'clojure.spec.alpha)
|
||||
#_(require 'clojure.spec.alpha)
|
||||
|
||||
(def ns-args (set (map symbol *command-line-args*)))
|
||||
|
||||
|
|
@ -34,9 +33,10 @@
|
|||
|
||||
(test-namespaces 'clj-http.lite.client-test)
|
||||
|
||||
;;;; spartan.spec
|
||||
;; ;;;; clojure.spec
|
||||
|
||||
(test-namespaces 'spartan.spec-test)
|
||||
(test-namespaces 'clojure.test-clojure.spec
|
||||
'clojure.test-clojure.instr)
|
||||
|
||||
;;;; regal
|
||||
|
||||
|
|
|
|||
178
test-resources/lib_tests/clojure/test_clojure/instr.clj
Normal file
178
test-resources/lib_tests/clojure/test_clojure/instr.clj
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
(ns clojure.test-clojure.instr
|
||||
(:require [clojure.spec.alpha :as s]
|
||||
[clojure.spec.gen.alpha :as gen]
|
||||
[clojure.spec.test.alpha :as stest]
|
||||
[clojure.test :refer :all]))
|
||||
|
||||
(set! *warn-on-reflection* true)
|
||||
|
||||
;; utils
|
||||
|
||||
(defmacro with-feature [feature & body]
|
||||
`(try ~feature
|
||||
~@body
|
||||
(catch Exception ex#)))
|
||||
|
||||
;; instrument tests
|
||||
|
||||
(defn kwargs-fn
|
||||
([opts] opts)
|
||||
([a b] [a b])
|
||||
([a b & {:as m}] [a b m]))
|
||||
|
||||
(defn no-kwargs-fn
|
||||
([opts] opts)
|
||||
([a b] [a b])
|
||||
([args inner & opts] [args inner opts]))
|
||||
|
||||
(defn no-kwargs-destruct-fn
|
||||
([opts] opts)
|
||||
([{:as a} b] [a b])
|
||||
([{:as args} inner & opts] [args inner opts]))
|
||||
|
||||
(defn just-varargs [& args]
|
||||
(apply + args))
|
||||
|
||||
(defn add10 [n]
|
||||
(+ 10 n))
|
||||
|
||||
(alter-meta! #'add10 dissoc :arglists)
|
||||
|
||||
;;; Specs
|
||||
|
||||
(s/def ::a any?)
|
||||
(s/def ::b number?)
|
||||
(s/def ::c any?)
|
||||
(s/def ::m map?)
|
||||
|
||||
(s/fdef kwargs-fn
|
||||
:args (s/alt :unary (s/cat :a ::a)
|
||||
:binary (s/cat :a ::a :b ::b)
|
||||
:variadic (s/cat :a ::a
|
||||
:b ::b
|
||||
:kwargs (s/keys* :opt-un [::a ::b ::c]))))
|
||||
|
||||
(s/fdef no-kwargs-fn
|
||||
:args (s/alt :unary (s/cat :a ::a)
|
||||
:binary (s/cat :a ::a :b ::b)
|
||||
:variadic (s/cat :a ::a
|
||||
:b ::b
|
||||
:varargs (s/cat :numbers (s/* number?)))))
|
||||
|
||||
(s/fdef no-kwargs-destruct-fn
|
||||
:args (s/alt :unary (s/cat :a ::a)
|
||||
:binary (s/cat :a ::a :m ::m)
|
||||
:variadic (s/cat :a ::a
|
||||
:b ::b
|
||||
:varargs (s/cat :numbers (s/* number?)))))
|
||||
|
||||
(s/fdef just-varargs
|
||||
:args (s/cat :numbers (s/* number?))
|
||||
:ret number?)
|
||||
|
||||
(s/fdef add10
|
||||
:args (s/cat :arg ::b)
|
||||
:ret number?)
|
||||
|
||||
(defn- fail-no-kwargs [& args] (apply no-kwargs-fn args))
|
||||
(defn- fail-kwargs [& args] (apply kwargs-fn args))
|
||||
|
||||
(with-feature (kwargs-fn 1 2 {:a 1 :b 2})
|
||||
(deftest test-instrument
|
||||
(testing "that a function taking fixed args and varargs is spec'd and checked at runtime"
|
||||
(letfn [(test-varargs-raw []
|
||||
(are [x y] (= x y)
|
||||
1 (no-kwargs-fn 1)
|
||||
[1 2] (no-kwargs-fn 1 2)
|
||||
[1 2 [3 4 5]] (no-kwargs-fn 1 2 3 4 5)))]
|
||||
(testing "that the raw kwargs function operates as expected"
|
||||
(test-varargs-raw))
|
||||
|
||||
(testing "that the instrumented kwargs function operates as expected"
|
||||
(stest/instrument `no-kwargs-fn {})
|
||||
|
||||
(test-varargs-raw)
|
||||
(is (thrown-with-msg? clojure.lang.ExceptionInfo #"did not conform to spec" (no-kwargs-fn 1 :not-num)))
|
||||
(is (thrown-with-msg? clojure.lang.ExceptionInfo #"did not conform to spec" (no-kwargs-fn 1 2 :not-num 3)))
|
||||
|
||||
#_(testing "that the ex-info data looks correct"
|
||||
(try (fail-no-kwargs 1 :not-num)
|
||||
(catch Exception ei
|
||||
(is (= 'clojure.test-clojure.instr/fail-no-kwargs (-> ei ex-data :clojure.spec.test.alpha/caller :var-scope)))))
|
||||
|
||||
(try (fail-no-kwargs 1 2 :not-num 3)
|
||||
(catch Exception ei
|
||||
(is (= 'clojure.test-clojure.instr/fail-no-kwargs (-> ei ex-data :clojure.spec.test.alpha/caller :var-scope)))))))
|
||||
|
||||
(testing "that the uninstrumented kwargs function operates as the raw function"
|
||||
(stest/unstrument `no-kwargs-fn)
|
||||
(test-varargs-raw))))
|
||||
|
||||
(testing "that a function taking only varargs is spec'd and checked at runtime"
|
||||
(letfn [(test-varargs-raw []
|
||||
(are [x y] (= x y)
|
||||
1 (just-varargs 1)
|
||||
3 (just-varargs 1 2)
|
||||
15 (just-varargs 1 2 3 4 5)))]
|
||||
(testing "that the raw varargs function operates as expected"
|
||||
(test-varargs-raw))
|
||||
|
||||
(testing "that the instrumented varargs function operates as expected"
|
||||
(stest/instrument `just-varargs {})
|
||||
|
||||
(test-varargs-raw)
|
||||
(is (thrown-with-msg? clojure.lang.ExceptionInfo #"did not conform to spec" (just-varargs 1 :not-num)))
|
||||
(is (thrown-with-msg? clojure.lang.ExceptionInfo #"did not conform to spec" (just-varargs 1 2 :not-num 3))))
|
||||
|
||||
(testing "that the uninstrumented kwargs function operates as the raw function"
|
||||
(stest/unstrument `just-varargs)
|
||||
(test-varargs-raw))))
|
||||
|
||||
(testing "that a function taking keyword args is spec'd and checked at runtime"
|
||||
(letfn [(test-kwargs-baseline []
|
||||
(are [x y] (= x y)
|
||||
1 (kwargs-fn 1)
|
||||
[1 2] (kwargs-fn 1 2)
|
||||
[1 2 {:a 1}] (kwargs-fn 1 2 :a 1)
|
||||
[1 2 {:a 1}] (kwargs-fn 1 2 {:a 1})
|
||||
[1 2 {:a 1 :b 2}] (kwargs-fn 1 2 :a 1 {:b 2})))
|
||||
(test-kwargs-extended []
|
||||
(are [x y] (= x y)
|
||||
[1 :not-num] (kwargs-fn 1 :not-num)
|
||||
[1 2 {:a 1 :b :not-num}] (kwargs-fn 1 2 :a 1 {:b :not-num})))]
|
||||
(testing "that the raw kwargs function operates as expected"
|
||||
(test-kwargs-baseline)
|
||||
(test-kwargs-extended))
|
||||
|
||||
(testing "that the instrumented kwargs function operates as expected"
|
||||
(stest/instrument `kwargs-fn {})
|
||||
|
||||
(test-kwargs-baseline)
|
||||
(is (thrown-with-msg? clojure.lang.ExceptionInfo #"did not conform to spec" (kwargs-fn 1 :not-num)))
|
||||
(is (thrown-with-msg? clojure.lang.ExceptionInfo #"did not conform to spec" (kwargs-fn 1 2 :a 1 {:b :not-num})))
|
||||
|
||||
#_(testing "that the ex-info data looks correct"
|
||||
(try (fail-kwargs 1 :not-num)
|
||||
(catch Exception ei
|
||||
(is (= 'clojure.test-clojure.instr/fail-kwargs (-> ei ex-data :clojure.spec.test.alpha/caller :var-scope)))))
|
||||
|
||||
(try (fail-kwargs 1 2 :a 1 {:b :not-num})
|
||||
(catch Exception ei
|
||||
(is (= 'clojure.test-clojure.instr/fail-kwargs (-> ei ex-data :clojure.spec.test.alpha/caller :var-scope)))))))
|
||||
|
||||
(testing "that the uninstrumented kwargs function operates as the raw function"
|
||||
(stest/unstrument `kwargs-fn)
|
||||
(test-kwargs-baseline)
|
||||
(test-kwargs-extended))))
|
||||
|
||||
(testing "that a var with no arglists meta is spec'd and checked at runtime"
|
||||
(stest/instrument `add10 {})
|
||||
(is (= 11 (add10 1)))
|
||||
(is (thrown-with-msg? clojure.lang.ExceptionInfo #"did not conform to spec" (add10 :not-num)))
|
||||
(is (= 11 (add10 1))))
|
||||
|
||||
(testing "that a function with positional destructuring in its parameter list is spec'd and checked at runtime"
|
||||
(stest/instrument `no-kwargs-destruct-fn {})
|
||||
|
||||
(is (= [{:a 1} {}] (no-kwargs-destruct-fn {:a 1} {})))
|
||||
(is (= [{:a 1} 2 [3 4 5]] (no-kwargs-destruct-fn {:a 1} 2 3 4 5))))))
|
||||
305
test-resources/lib_tests/clojure/test_clojure/spec.clj
Normal file
305
test-resources/lib_tests/clojure/test_clojure/spec.clj
Normal file
|
|
@ -0,0 +1,305 @@
|
|||
(ns clojure.test-clojure.spec
|
||||
(:require [clojure.spec.alpha :as s]
|
||||
[clojure.spec.gen.alpha :as gen]
|
||||
[clojure.spec.test.alpha :as stest]
|
||||
[clojure.test :refer :all]))
|
||||
|
||||
(set! *warn-on-reflection* true)
|
||||
|
||||
(defmacro result-or-ex [x]
|
||||
`(try
|
||||
~x
|
||||
(catch Throwable t#
|
||||
(.getName (class t#)))))
|
||||
|
||||
(def even-count? #(even? (count %)))
|
||||
|
||||
(defn submap?
|
||||
"Is m1 a subset of m2?"
|
||||
[m1 m2]
|
||||
(if (and (map? m1) (map? m2))
|
||||
(every? (fn [[k v]] (and (contains? m2 k)
|
||||
(submap? v (get m2 k))))
|
||||
m1)
|
||||
(= m1 m2)))
|
||||
|
||||
(deftest conform-explain
|
||||
(let [a (s/and #(> % 5) #(< % 10))
|
||||
o (s/or :s string? :k keyword?)
|
||||
c (s/cat :a string? :b keyword?)
|
||||
either (s/alt :a string? :b keyword?)
|
||||
star (s/* keyword?)
|
||||
plus (s/+ keyword?)
|
||||
opt (s/? keyword?)
|
||||
andre (s/& (s/* keyword?) even-count?)
|
||||
andre2 (s/& (s/* keyword?) #{[:a]})
|
||||
m (s/map-of keyword? string?)
|
||||
mkeys (s/map-of (s/and keyword? (s/conformer name)) any?)
|
||||
mkeys2 (s/map-of (s/and keyword? (s/conformer name)) any? :conform-keys true)
|
||||
s (s/coll-of (s/spec (s/cat :tag keyword? :val any?)) :kind list?)
|
||||
v (s/coll-of keyword? :kind vector?)
|
||||
coll (s/coll-of keyword?)
|
||||
lrange (s/int-in 7 42)
|
||||
drange (s/double-in :infinite? false :NaN? false :min 3.1 :max 3.2)
|
||||
irange (s/inst-in #inst "1939" #inst "1946")
|
||||
]
|
||||
(are [spec x conformed ed]
|
||||
(let [co (result-or-ex (s/conform spec x))
|
||||
e (result-or-ex (::s/problems (s/explain-data spec x)))]
|
||||
(when (not= conformed co) (println "conform fail\n\texpect=" conformed "\n\tactual=" co))
|
||||
(when (not (every? true? (map submap? ed e)))
|
||||
(println "explain failures\n\texpect=" ed "\n\tactual failures=" e "\n\tsubmap?=" (map submap? ed e)))
|
||||
(and (= conformed co) (every? true? (map submap? ed e))))
|
||||
|
||||
lrange 7 7 nil
|
||||
lrange 8 8 nil
|
||||
lrange 42 ::s/invalid [{:pred '(clojure.core/fn [%] (clojure.spec.alpha/int-in-range? 7 42 %)), :val 42}]
|
||||
|
||||
irange #inst "1938" ::s/invalid [{:pred '(clojure.core/fn [%] (clojure.spec.alpha/inst-in-range? #inst "1939-01-01T00:00:00.000-00:00" #inst "1946-01-01T00:00:00.000-00:00" %)), :val #inst "1938"}]
|
||||
irange #inst "1942" #inst "1942" nil
|
||||
irange #inst "1946" ::s/invalid [{:pred '(clojure.core/fn [%] (clojure.spec.alpha/inst-in-range? #inst "1939-01-01T00:00:00.000-00:00" #inst "1946-01-01T00:00:00.000-00:00" %)), :val #inst "1946"}]
|
||||
|
||||
drange 3.0 ::s/invalid [{:pred '(clojure.core/fn [%] (clojure.core/<= 3.1 %)), :val 3.0}]
|
||||
drange 3.1 3.1 nil
|
||||
drange 3.2 3.2 nil
|
||||
;; TODO: drange Double/POSITIVE_INFINITY ::s/invalid [{:pred '(clojure.core/fn [%] (clojure.core/not (Double/isInfinite %))), :val Double/POSITIVE_INFINITY}]
|
||||
;; See https://github.com/babashka/sci/issues/647
|
||||
;; can't use equality-based test for Double/NaN
|
||||
;; drange Double/NaN ::s/invalid {[] {:pred '(clojure.core/fn [%] (clojure.core/not (Double/isNaN %))), :val Double/NaN}}
|
||||
|
||||
keyword? :k :k nil
|
||||
keyword? nil ::s/invalid [{:pred `keyword? :val nil}]
|
||||
keyword? "abc" ::s/invalid [{:pred `keyword? :val "abc"}]
|
||||
|
||||
a 6 6 nil
|
||||
a 3 ::s/invalid '[{:pred (clojure.core/fn [%] (clojure.core/> % 5)), :val 3}]
|
||||
a 20 ::s/invalid '[{:pred (clojure.core/fn [%] (clojure.core/< % 10)), :val 20}]
|
||||
a nil "java.lang.NullPointerException" "java.lang.NullPointerException"
|
||||
a :k "java.lang.ClassCastException" "java.lang.ClassCastException"
|
||||
|
||||
o "a" [:s "a"] nil
|
||||
o :a [:k :a] nil
|
||||
o 'a ::s/invalid '[{:pred clojure.core/string?, :val a, :path [:s]} {:pred clojure.core/keyword?, :val a :path [:k]}]
|
||||
|
||||
c nil ::s/invalid '[{:reason "Insufficient input", :pred clojure.core/string?, :val (), :path [:a]}]
|
||||
c [] ::s/invalid '[{:reason "Insufficient input", :pred clojure.core/string?, :val (), :path [:a]}]
|
||||
c [:a] ::s/invalid '[{:pred clojure.core/string?, :val :a, :path [:a], :in [0]}]
|
||||
c ["a"] ::s/invalid '[{:reason "Insufficient input", :pred clojure.core/keyword?, :val (), :path [:b]}]
|
||||
c ["s" :k] '{:a "s" :b :k} nil
|
||||
c ["s" :k 5] ::s/invalid '[{:reason "Extra input", :pred (clojure.spec.alpha/cat :a clojure.core/string? :b clojure.core/keyword?), :val (5)}]
|
||||
(s/cat) nil {} nil
|
||||
(s/cat) [5] ::s/invalid '[{:reason "Extra input", :pred (clojure.spec.alpha/cat), :val (5), :in [0]}]
|
||||
|
||||
either nil ::s/invalid '[{:reason "Insufficient input", :pred (clojure.spec.alpha/alt :a clojure.core/string? :b clojure.core/keyword?), :val () :via []}]
|
||||
either [] ::s/invalid '[{:reason "Insufficient input", :pred (clojure.spec.alpha/alt :a clojure.core/string? :b clojure.core/keyword?), :val () :via []}]
|
||||
either [:k] [:b :k] nil
|
||||
either ["s"] [:a "s"] nil
|
||||
either [:b "s"] ::s/invalid '[{:reason "Extra input", :pred (clojure.spec.alpha/alt :a clojure.core/string? :b clojure.core/keyword?), :val ("s") :via []}]
|
||||
|
||||
star nil [] nil
|
||||
star [] [] nil
|
||||
star [:k] [:k] nil
|
||||
star [:k1 :k2] [:k1 :k2] nil
|
||||
star [:k1 :k2 "x"] ::s/invalid '[{:pred clojure.core/keyword?, :val "x" :via []}]
|
||||
star ["a"] ::s/invalid '[{:pred clojure.core/keyword?, :val "a" :via []}]
|
||||
|
||||
plus nil ::s/invalid '[{:reason "Insufficient input", :pred clojure.core/keyword?, :val () :via []}]
|
||||
plus [] ::s/invalid '[{:reason "Insufficient input", :pred clojure.core/keyword?, :val () :via []}]
|
||||
plus [:k] [:k] nil
|
||||
plus [:k1 :k2] [:k1 :k2] nil
|
||||
plus [:k1 :k2 "x"] ::s/invalid '[{:pred clojure.core/keyword?, :val "x", :in [2]}]
|
||||
plus ["a"] ::s/invalid '[{:pred clojure.core/keyword?, :val "a" :via []}]
|
||||
|
||||
opt nil nil nil
|
||||
opt [] nil nil
|
||||
opt :k ::s/invalid '[{:pred (clojure.core/fn [%] (clojure.core/or (clojure.core/nil? %) (clojure.core/sequential? %))), :val :k}]
|
||||
opt [:k] :k nil
|
||||
opt [:k1 :k2] ::s/invalid '[{:reason "Extra input", :pred (clojure.spec.alpha/? clojure.core/keyword?), :val (:k2)}]
|
||||
opt [:k1 :k2 "x"] ::s/invalid '[{:reason "Extra input", :pred (clojure.spec.alpha/? clojure.core/keyword?), :val (:k2 "x")}]
|
||||
opt ["a"] ::s/invalid '[{:pred clojure.core/keyword?, :val "a"}]
|
||||
|
||||
andre nil nil nil
|
||||
andre [] nil nil
|
||||
andre :k :clojure.spec.alpha/invalid '[{:pred (clojure.core/fn [%] (clojure.core/or (clojure.core/nil? %) (clojure.core/sequential? %))), :val :k}]
|
||||
andre [:k] ::s/invalid '[{:pred clojure.test-clojure.spec/even-count?, :val [:k]}]
|
||||
andre [:j :k] [:j :k] nil
|
||||
|
||||
andre2 nil :clojure.spec.alpha/invalid [{:pred #{[:a]}, :val []}]
|
||||
andre2 [] :clojure.spec.alpha/invalid [{:pred #{[:a]}, :val []}]
|
||||
andre2 [:a] [:a] nil
|
||||
|
||||
m nil ::s/invalid '[{:pred clojure.core/map?, :val nil}]
|
||||
m {} {} nil
|
||||
m {:a "b"} {:a "b"} nil
|
||||
|
||||
mkeys nil ::s/invalid '[{:pred clojure.core/map?, :val nil}]
|
||||
mkeys {} {} nil
|
||||
mkeys {:a 1 :b 2} {:a 1 :b 2} nil
|
||||
|
||||
mkeys2 nil ::s/invalid '[{:pred clojure.core/map?, :val nil}]
|
||||
mkeys2 {} {} nil
|
||||
mkeys2 {:a 1 :b 2} {"a" 1 "b" 2} nil
|
||||
|
||||
s '([:a 1] [:b "2"]) '({:tag :a :val 1} {:tag :b :val "2"}) nil
|
||||
|
||||
v [:a :b] [:a :b] nil
|
||||
v '(:a :b) ::s/invalid '[{:pred clojure.core/vector? :val (:a :b)}]
|
||||
|
||||
coll nil ::s/invalid '[{:path [], :pred clojure.core/coll?, :val nil, :via [], :in []}]
|
||||
coll [] [] nil
|
||||
coll [:a] [:a] nil
|
||||
coll [:a :b] [:a :b] nil
|
||||
coll (map identity [:a :b]) '(:a :b) nil
|
||||
;;coll [:a "b"] ::s/invalid '[{:pred (coll-checker keyword?), :val [:a b]}]
|
||||
)))
|
||||
|
||||
(deftest describing-evaled-specs
|
||||
(let [sp #{1 2}]
|
||||
(is (= (s/describe sp) (s/form sp) sp)))
|
||||
|
||||
(is (= (s/describe odd?) 'odd?))
|
||||
(is (= (s/form odd?) 'clojure.core/odd?))
|
||||
|
||||
#_(is (= (s/describe #(odd? %)) ::s/unknown))
|
||||
#_(is (= (s/form #(odd? %)) ::s/unknown)))
|
||||
|
||||
(defn check-conform-unform [spec vals expected-conforms]
|
||||
(let [actual-conforms (map #(s/conform spec %) vals)
|
||||
unforms (map #(s/unform spec %) actual-conforms)]
|
||||
(is (= actual-conforms expected-conforms))
|
||||
(is (= vals unforms))))
|
||||
|
||||
(deftest nilable-conform-unform
|
||||
(check-conform-unform
|
||||
(s/nilable int?)
|
||||
[5 nil]
|
||||
[5 nil])
|
||||
(check-conform-unform
|
||||
(s/nilable (s/or :i int? :s string?))
|
||||
[5 "x" nil]
|
||||
[[:i 5] [:s "x"] nil]))
|
||||
|
||||
(deftest nonconforming-conform-unform
|
||||
(check-conform-unform
|
||||
(s/nonconforming (s/or :i int? :s string?))
|
||||
[5 "x"]
|
||||
[5 "x"]))
|
||||
|
||||
(deftest coll-form
|
||||
(are [spec form]
|
||||
(= (s/form spec) form)
|
||||
(s/map-of int? any?)
|
||||
'(clojure.spec.alpha/map-of clojure.core/int? clojure.core/any?)
|
||||
|
||||
(s/coll-of int?)
|
||||
'(clojure.spec.alpha/coll-of clojure.core/int?)
|
||||
|
||||
(s/every-kv int? int?)
|
||||
'(clojure.spec.alpha/every-kv clojure.core/int? clojure.core/int?)
|
||||
|
||||
(s/every int?)
|
||||
'(clojure.spec.alpha/every clojure.core/int?)
|
||||
|
||||
(s/coll-of (s/tuple (s/tuple int?)))
|
||||
'(clojure.spec.alpha/coll-of (clojure.spec.alpha/tuple (clojure.spec.alpha/tuple clojure.core/int?)))
|
||||
|
||||
(s/coll-of int? :kind vector?)
|
||||
'(clojure.spec.alpha/coll-of clojure.core/int? :kind clojure.core/vector?)
|
||||
|
||||
(s/coll-of int? :gen #(gen/return [1 2]))
|
||||
'(clojure.spec.alpha/coll-of clojure.core/int? :gen (fn* [] (gen/return [1 2])))))
|
||||
|
||||
(deftest coll-conform-unform
|
||||
(check-conform-unform
|
||||
(s/coll-of (s/or :i int? :s string?))
|
||||
[[1 "x"]]
|
||||
[[[:i 1] [:s "x"]]])
|
||||
(check-conform-unform
|
||||
(s/every (s/or :i int? :s string?))
|
||||
[[1 "x"]]
|
||||
[[1 "x"]])
|
||||
(check-conform-unform
|
||||
(s/map-of int? (s/or :i int? :s string?))
|
||||
[{10 10 20 "x"}]
|
||||
[{10 [:i 10] 20 [:s "x"]}])
|
||||
(check-conform-unform
|
||||
(s/map-of (s/or :i int? :s string?) int? :conform-keys true)
|
||||
[{10 10 "x" 20}]
|
||||
[{[:i 10] 10 [:s "x"] 20}])
|
||||
(check-conform-unform
|
||||
(s/every-kv int? (s/or :i int? :s string?))
|
||||
[{10 10 20 "x"}]
|
||||
[{10 10 20 "x"}]))
|
||||
|
||||
(deftest &-explain-pred
|
||||
(are [val expected]
|
||||
(= expected (-> (s/explain-data (s/& int? even?) val) ::s/problems first :pred))
|
||||
[] 'clojure.core/int?
|
||||
[0 2] '(clojure.spec.alpha/& clojure.core/int? clojure.core/even?)))
|
||||
|
||||
(deftest keys-explain-pred
|
||||
(is (= 'clojure.core/map? (-> (s/explain-data (s/keys :req [::x]) :a) ::s/problems first :pred))))
|
||||
|
||||
(deftest remove-def
|
||||
(is (= ::ABC (s/def ::ABC string?)))
|
||||
(is (= ::ABC (s/def ::ABC nil)))
|
||||
(is (nil? (s/get-spec ::ABC))))
|
||||
|
||||
;; TODO replace this with a generative test once we have specs for s/keys
|
||||
(deftest map-spec-generators
|
||||
(s/def ::a nat-int?)
|
||||
(s/def ::b boolean?)
|
||||
(s/def ::c keyword?)
|
||||
(s/def ::d double?)
|
||||
(s/def ::e inst?)
|
||||
|
||||
(is (= #{[::a]
|
||||
[::a ::b]
|
||||
[::a ::b ::c]
|
||||
[::a ::c]}
|
||||
(->> (s/exercise (s/keys :req [::a] :opt [::b ::c]) 100)
|
||||
(map (comp sort keys first))
|
||||
(into #{}))))
|
||||
|
||||
(is (= #{[:a]
|
||||
[:a :b]
|
||||
[:a :b :c]
|
||||
[:a :c]}
|
||||
(->> (s/exercise (s/keys :req-un [::a] :opt-un [::b ::c]) 100)
|
||||
(map (comp sort keys first))
|
||||
(into #{}))))
|
||||
|
||||
(is (= #{[::a ::b]
|
||||
[::a ::b ::c ::d]
|
||||
[::a ::b ::c ::d ::e]
|
||||
[::a ::b ::c ::e]
|
||||
[::a ::c ::d]
|
||||
[::a ::c ::d ::e]
|
||||
[::a ::c ::e]}
|
||||
(->> (s/exercise (s/keys :req [::a (or ::b (and ::c (or ::d ::e)))]) 200)
|
||||
(map (comp vec sort keys first))
|
||||
(into #{}))))
|
||||
|
||||
(is (= #{[:a :b]
|
||||
[:a :b :c :d]
|
||||
[:a :b :c :d :e]
|
||||
[:a :b :c :e]
|
||||
[:a :c :d]
|
||||
[:a :c :d :e]
|
||||
[:a :c :e]}
|
||||
(->> (s/exercise (s/keys :req-un [::a (or ::b (and ::c (or ::d ::e)))]) 200)
|
||||
(map (comp vec sort keys first))
|
||||
(into #{})))))
|
||||
|
||||
(deftest tuple-explain-pred
|
||||
(are [val expected]
|
||||
(= expected (-> (s/explain-data (s/tuple int?) val) ::s/problems first :pred))
|
||||
:a 'clojure.core/vector?
|
||||
[] '(clojure.core/= (clojure.core/count %) 1)))
|
||||
|
||||
(comment
|
||||
(require '[clojure.test :refer (run-tests)])
|
||||
(in-ns 'clojure.test-clojure.spec)
|
||||
(run-tests)
|
||||
|
||||
)
|
||||
Loading…
Reference in a new issue