Add some additional libraries (#1138)

* Add some additional libraries to test

Also improved docs around add-libtest
Close #1137
Close #1128

* Add method needed for supporting pyramid

Pyramid tests passed locally but that was on jvm

* Remove pyramid tests and do in subsequent PR

* Revert "Add method needed for supporting pyramid"

This reverts commit 4d84a2a2ac.

* Skip exoscale tests for windows since most aren't windows compatible
This commit is contained in:
Gabriel Horner 2022-01-14 08:56:09 -05:00 committed by GitHub
parent b765ed3ec7
commit 093709386a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 1231 additions and 5 deletions

View file

@ -114,7 +114,12 @@
clojure-term-colors/clojure-term-colors {:mvn/version "0.1.0"}
io.aviso/pretty {:mvn/version "1.1.1"}
progrock/progrock {:mvn/version "0.1.2"}
djblue/portal {:mvn/version "0.19.0"}}
djblue/portal {:mvn/version "0.19.0"}
com.wsscode/cljc-misc {:mvn/version "2021.10.16"}
edn-query-language/eql {:mvn/version "2021.07.18"}
meta-merge/meta-merge {:mvn/version "1.0.0"}
com.exoscale/lingo {:mvn/version "1.0.0-alpha14"}
io.github.swirrl/dogstatsd {:mvn/version "0.1.39"}}
:classpath-overrides {org.clojure/clojure nil
org.clojure/spec.alpha nil}}
:clj-nvd

View file

@ -81,9 +81,19 @@ Test the native version:
## Tests for Libraries
Babashka runs tests of libraries that are compatible with it through
`script/run_lib_tests`. To add tests for a new library that has a git repository
and run them, use the script `add-libtest.clj` e.g. `script/add-libtest.clj
'{listora/again {:mvn/version "1.0.0"}}' https://github.com/liwp/again --test`.
`script/run_lib_tests`. The script `add-libtest.clj` makes adding new libraries
fairly easy. Some examples:
```sh
# To add tests for a new library on clojars
script/add-libtest.clj com.exoscale/lingo -t
# To add tests for a new library that is git based only
script/add-libtest.clj '{borkdude/carve {:git/url "https://github.com/borkdude/carve" :sha "df552797a198b6701fb2d92390fce7c59205ea77"}}' -t
# There are a number of options for specifying how to copy tests
script/add-libtest.clj -h
```
If the library you want to add doesn't work automatically, you can manually do the following:

View file

@ -12,10 +12,12 @@ clj-commons/clj-yaml,https://github.com/clj-commons/clj-yaml
clj-commons/multigrep,https://github.com/clj-commons/multigrep
clojure-csv/clojure-csv,https://github.com/davidsantiago/clojure-csv
clojure-term-colors/clojure-term-colors,https://github.com/trhura/clojure-term-colors
com.exoscale/lingo,https://github.com/exoscale/lingo
com.github.seancorfield/honeysql,https://github.com/seancorfield/honeysql
com.grammarly/omniconf,https://github.com/grammarly/omniconf
com.stuartsierra/component,https://github.com/stuartsierra/component
com.stuartsierra/dependency,https://github.com/stuartsierra/dependency
com.wsscode/cljc-misc,https://github.com/wilkerlucio/cljc-misc
comb/comb,https://github.com/weavejester/comb
cprop/cprop,https://github.com/tolitius/cprop
crispin/crispin,https://github.com/dunaj-project/crispin
@ -23,6 +25,7 @@ dev.nubank/docopt,https://github.com/nubank/docopt.clj
djblue/portal,https://github.com/djblue/portal
doric/doric,https://github.com/joegallo/doric
douglass/clj-psql,https://github.com/DarinDouglass/clj-psql
edn-query-language/eql,https://github.com/edn-query-language/eql
environ/environ,https://github.com/weavejester/environ
exoscale/coax,https://github.com/exoscale/coax
expound/expound,https://github.com/bhb/expound
@ -34,8 +37,10 @@ henryw374/cljc.java-time,https://github.com/henryw374/cljc.java-time
hiccup/hiccup,http://github.com/weavejester/hiccup
honeysql/honeysql,https://github.com/seancorfield/honeysql
http-kit/http-kit,https://github.com/http-kit/http-kit
integrant/integrant,https://github.com/weavejester/integrant
io.aviso/pretty,https://github.com/AvisoNovate/pretty
io.github.cognitect-labs/test-runner,https://github.com/cognitect-labs/test-runner
io.github.swirrl/dogstatsd,https://github.com/swirrl/dogstatsd
io.github.technomancy/limit-break,https://github.com/technomancy/limit-break
io.helins/binf,https://github.com/helins/binf.cljc
io.replikativ/hasch,https://github.com/replikativ/hasch
@ -44,6 +49,7 @@ lambdaisland/regal,https://github.com/lambdaisland/regal
listora/again,https://github.com/liwp/again
markdown-clj/markdown-clj,https://github.com/yogthos/markdown-clj
medley/medley,https://github.com/weavejester/medley
meta-merge/meta-merge,https://github.com/weavejester/meta-merge
minimallist/minimallist,https://github.com/green-coder/minimallist
mvxcvi/arrangement,https://github.com/greglook/clj-arrangement
orchestra/orchestra,https://github.com/jeaye/orchestra

1 maven-name git-url
12 clj-commons/multigrep https://github.com/clj-commons/multigrep
13 clojure-csv/clojure-csv https://github.com/davidsantiago/clojure-csv
14 clojure-term-colors/clojure-term-colors https://github.com/trhura/clojure-term-colors
15 com.exoscale/lingo https://github.com/exoscale/lingo
16 com.github.seancorfield/honeysql https://github.com/seancorfield/honeysql
17 com.grammarly/omniconf https://github.com/grammarly/omniconf
18 com.stuartsierra/component https://github.com/stuartsierra/component
19 com.stuartsierra/dependency https://github.com/stuartsierra/dependency
20 com.wsscode/cljc-misc https://github.com/wilkerlucio/cljc-misc
21 comb/comb https://github.com/weavejester/comb
22 cprop/cprop https://github.com/tolitius/cprop
23 crispin/crispin https://github.com/dunaj-project/crispin
25 djblue/portal https://github.com/djblue/portal
26 doric/doric https://github.com/joegallo/doric
27 douglass/clj-psql https://github.com/DarinDouglass/clj-psql
28 edn-query-language/eql https://github.com/edn-query-language/eql
29 environ/environ https://github.com/weavejester/environ
30 exoscale/coax https://github.com/exoscale/coax
31 expound/expound https://github.com/bhb/expound
37 hiccup/hiccup http://github.com/weavejester/hiccup
38 honeysql/honeysql https://github.com/seancorfield/honeysql
39 http-kit/http-kit https://github.com/http-kit/http-kit
40 integrant/integrant https://github.com/weavejester/integrant
41 io.aviso/pretty https://github.com/AvisoNovate/pretty
42 io.github.cognitect-labs/test-runner https://github.com/cognitect-labs/test-runner
43 io.github.swirrl/dogstatsd https://github.com/swirrl/dogstatsd
44 io.github.technomancy/limit-break https://github.com/technomancy/limit-break
45 io.helins/binf https://github.com/helins/binf.cljc
46 io.replikativ/hasch https://github.com/replikativ/hasch
49 listora/again https://github.com/liwp/again
50 markdown-clj/markdown-clj https://github.com/yogthos/markdown-clj
51 medley/medley https://github.com/weavejester/medley
52 meta-merge/meta-merge https://github.com/weavejester/meta-merge
53 minimallist/minimallist https://github.com/green-coder/minimallist
54 mvxcvi/arrangement https://github.com/greglook/clj-arrangement
55 orchestra/orchestra https://github.com/jeaye/orchestra

View file

@ -96,4 +96,10 @@
io.aviso/pretty {:git-url "https://github.com/AvisoNovate/pretty", :test-namespaces (io.aviso.binary-test), :git-sha "155926f991f94addaf6f5c8621748924ab144988" :skip-windows true}
progrock/progrock {:git-url "https://github.com/weavejester/progrock", :test-namespaces (progrock.core-test), :git-sha "9c277a3244c52bfde19c21add327d6e20b94fdf5"}
;; Don't run portal.jvm-test as it depends on headless chrome
djblue/portal {:git-url "https://github.com/djblue/portal", :test-namespaces (portal.test-runner portal.runtime.cson-test portal.runtime.fs-test portal.e2e portal.bench), :git-sha "64e4624bcf3bee2dd47e3d8e47982c709738eb11"}}
djblue/portal {:git-url "https://github.com/djblue/portal", :test-namespaces (portal.test-runner portal.runtime.cson-test portal.runtime.fs-test portal.e2e portal.bench), :git-sha "64e4624bcf3bee2dd47e3d8e47982c709738eb11"}
integrant/integrant {:git-url "https://github.com/weavejester/integrant", :test-namespaces (integrant.test.foo integrant.test.quz integrant.test.bar integrant.test.baz integrant.core-test), :git-sha "32a46f5dca8a6b563a6dddf88bec887be3201b08"}
com.wsscode/cljc-misc {:git-url "https://github.com/wilkerlucio/cljc-misc", :test-namespaces (com.wsscode.misc.uuid-test com.wsscode.misc.macros-test com.wsscode.misc.math-test com.wsscode.misc.coll-test com.wsscode.misc.refs-test), :git-sha "dc8e31a200f9cacf86af10b63e40fcb448c259f4"}
edn-query-language/eql {:git-url "https://github.com/edn-query-language/eql", :test-namespaces (edn-query-language.core-test), :git-sha "0d4f9745d98c3d20b81bb4bdce3e8e15db7fd094"}
meta-merge/meta-merge {:git-url "https://github.com/weavejester/meta-merge", :test-namespaces (meta-merge.core-test), :git-sha "c968c38baccd4219fe0ba592d89af37ea8e426bf"}
com.exoscale/lingo {:git-url "https://github.com/exoscale/lingo", :test-namespaces (exoscale.lingo.test.core-test), :git-sha "30b5084fab28d24c99ec683e21535366910d9f2f" :skip-windows true}
io.github.swirrl/dogstatsd {:git-url "https://github.com/swirrl/dogstatsd", :test-namespaces (swirrl.dogstatsd-test), :git-sha "e110caae452cd1185e65e389a359b69502076d61"}}

View file

@ -0,0 +1,257 @@
(ns com.wsscode.misc.coll-test
(:require
[clojure.test :refer [deftest is are run-tests testing]]
[com.wsscode.misc.coll :as coll]))
(deftest distinct-by-test
(is (= (coll/distinct-by :id
[{:id 1
:name "foo"}
{:id 2
:name "bar"}
{:id 1
:name "other"}])
[{:id 1
:name "foo"}
{:id 2
:name "bar"}])))
(deftest dedupe-by-test
(is (= (coll/dedupe-by :id
[{:id 1
:name "foo"}
{:id 1
:name "dedup-me"}
{:id 2
:name "bar"}
{:id 1
:name "other"}])
[{:id 1
:name "foo"}
{:id 2
:name "bar"}
{:id 1
:name "other"}])))
(deftest index-by-test
(is (= (coll/index-by :id
[{:id 1
:name "foo"}
{:id 1
:name "dedup-me"}
{:id 2
:name "bar"}
{:id 1
:name "other"}])
{1 {:id 1, :name "other"}, 2 {:id 2, :name "bar"}})))
(deftest find-first-test
(is (= (coll/find-first even? [1 2 3 4])
2)))
(deftest sconj-test
(is (= (coll/sconj nil 42) #{42}))
(is (set? (coll/sconj nil 42))))
(deftest vconj-test
(is (= (coll/vconj nil 42) [42]))
(is (vector? (coll/vconj nil 42))))
(deftest queue-test
(let [queue (-> (coll/queue)
(conj 1 2))]
(is (= queue [1 2]))
(is (= (peek queue) 1))
(is (= (pop queue) [2])))
(let [queue (coll/queue [1 2])]
(is (= queue [1 2]))
(is (= (peek queue) 1))
(is (= (pop queue) [2]))))
(deftest map-keys-test
(is (= (coll/map-keys inc {1 :a 2 :b})
{2 :a 3 :b})))
(deftest filter-keys-test
(is (= (coll/filter-keys simple-keyword? {1 :a 2 :b "foo" 3 :bar 4})
{:bar 4})))
(deftest filter-vals-test
(is (= (coll/filter-vals simple-keyword? {1 :a 2 :b "foo" 3 :bar 4})
{1 :a 2 :b})))
(deftest remove-keys-test
(is (= (coll/remove-keys number? {1 :a 2 :b "foo" 3 :bar 4})
{"foo" 3 :bar 4})))
(deftest remove-vals-test
(is (= (coll/remove-vals number? {1 :a 2 :b "foo" 3 :bar 4})
{1 :a 2 :b})))
(deftest map-vals-test
(is (= (coll/map-vals inc {:a 1 :b 2})
{:a 2 :b 3})))
(deftest keys-set-test
(is (= (coll/keys-set {:a 1 :b 2}) #{:a :b}))
(is (= (coll/keys-set 5) nil)))
(deftest merge-grow-test
(is (= (coll/merge-grow) {}))
(is (= (coll/merge-grow {:foo "bar"}) {:foo "bar"}))
(testing "merge sets by union"
(is (= (coll/merge-grow {:foo #{:a}} {:foo #{:b}})
{:foo #{:a :b}})))
(testing "merge maps"
(is (= (coll/merge-grow {:foo {:a 1}} {:foo {:b 2}})
{:foo {:a 1 :b 2}})))
(testing "keep left value if right one is nil"
(is (= (coll/merge-grow {:foo {:a 1}} {:foo {:a nil}})
{:foo {:a 1}}))))
(deftest merge-defaults-test
(is (= (coll/merge-defaults {:a 1} {:b 2})
{:a 1 :b 2}))
(is (= (coll/merge-defaults {:a 1} {:a 2})
{:a 1})))
(deftest assoc-if-test
(is (= (coll/assoc-if {} :foo "bar")
{:foo "bar"}))
(is (= (coll/assoc-if {} :foo nil)
{}))
(is (= (coll/assoc-if {} :foo false)
{}))
(is (= (coll/assoc-if {} :foo false :bar 30)
{:bar 30}))
(is (= (coll/assoc-if {} :foo false :bar 30 :baz false)
{:bar 30})))
(deftest update-contained-test
(is (= (coll/update-contained {:foo 3} :foo inc)
{:foo 4}))
(is (= (coll/update-contained {:foo nil} :foo #(str % " bla"))
{:foo " bla"}))
(is (= (coll/update-contained {} :foo inc)
{})))
(deftest update-if-test
(is (= (coll/update-if {:foo 3} :foo inc)
{:foo 4}))
(is (= (coll/update-if {:foo nil} :foo inc)
{:foo nil}))
(is (= (coll/update-if {} :foo inc)
{})))
(defrecord CustomRecord [])
(deftest native-map?-test
(is (= true (coll/native-map? {})))
(is (= true (coll/native-map? {:foo "bar"})))
(is (= true (coll/native-map? (zipmap (range 50) (range 50)))))
(is (= false (coll/native-map? (->CustomRecord)))))
(deftest restore-order-test
(is (= (coll/restore-order
[{:my.entity/id 1} {:my.entity/id 2}]
:my.entity/id
[{:my.entity/id 2
:my.entity/color :my.entity.color/green}
{:my.entity/id 1
:my.entity/color :my.entity.color/purple}])
[{:my.entity/id 1
:my.entity/color :my.entity.color/purple}
{:my.entity/id 2
:my.entity/color :my.entity.color/green}]))
(is (= (coll/restore-order
[{:my.entity/id 1}
{:my.entity/id 2}
{:my.entity/id 3}]
:my.entity/id
[{:my.entity/id 3
:my.entity/color :my.entity.color/green}
{:my.entity/id 1
:my.entity/color :my.entity.color/purple}])
[{:my.entity/id 1
:my.entity/color :my.entity.color/purple}
{:my.entity/id 2}
{:my.entity/id 3
:my.entity/color :my.entity.color/green}]))
(is (= (coll/restore-order [{:my.entity/id 1}
{:my.entity/id 2}
{:my.entity/id 3}]
:my.entity/id
[{:my.entity/id 3
:my.entity/color :my.entity.color/green}
{:my.entity/id 1
:my.entity/color :my.entity.color/purple}]
(fn [x] (assoc x :my.entity/color nil)))
[{:my.entity/id 1
:my.entity/color :my.entity.color/purple}
{:my.entity/id 2
:my.entity/color nil}
{:my.entity/id 3
:my.entity/color :my.entity.color/green}])))
(deftest conj-at-index-test
(is (= (coll/conj-at-index [:a :b] 0 :c)
[:c :a :b]))
(is (= (coll/conj-at-index [:a :b] 1 :c)
[:a :c :b]))
(is (= (coll/conj-at-index [:a :b] 2 :c)
[:a :b :c])))
(deftest index-of-test
(is (= (coll/index-of [:a {:id :b} :c] :not-here)
nil))
(is (= (coll/index-of [:a {:id :b} :c] :a)
0))
(is (= (coll/index-of [:a {:id :b} :c] {:id :b})
1)))
(deftest coll-append-ahead?-test
(is (true? (coll/coll-append-at-head? (list "foo"))))
(is (true? (coll/coll-append-at-head? (map identity ["foo"]))))
(is (false? (coll/coll-append-at-head? ["foo"])))
(is (false? (coll/coll-append-at-head? #{"foo"}))))
(deftest collection?-test
(is (true? (coll/collection? [])))
(is (true? (coll/collection? '())))
(is (true? (coll/collection? #{})))
(is (true? (coll/collection? (map identity []))))
(is (false? (coll/collection? {}))))
(deftest vector-compare-test
(is (= (coll/vector-compare [0] [1])
-1))
(is (= (coll/vector-compare [1] [0])
1))
(is (= (coll/vector-compare [1] [1])
0))
(is (= (coll/vector-compare [2 0] [2 1])
-1))
(is (= (coll/vector-compare [2 0 0] [2 1])
-1)))
(deftest iterate-while-test
(is (= (coll/iterate-while :n {:x 1 :n {:x 2 :n {:x 3}}})
[{:x 1, :n {:x 2, :n {:x 3}}} {:x 2, :n {:x 3}} {:x 3}])))
(deftest deep-merge-test
(is (= (coll/deep-merge {:a 1} {:b 2})
{:a 1 :b 2}))
(is (= (coll/deep-merge {:a {:x 1 :foo "bar"}} {:a {:baz "f" :foo "2"}})
{:a {:baz "f" :foo "2" :x 1}}))
(is (= (coll/deep-merge {:a [{:a 1}]} {:a [{:b 2}]})
{:a [{:b 2}]})))

View file

@ -0,0 +1,14 @@
(ns com.wsscode.misc.macros-test
(:require
[clojure.test :refer [deftest is are run-tests testing]]
[com.wsscode.misc.macros :as macros]))
(deftest full-symbol-test
(is (= (macros/full-symbol
'known/foo
"bar")
'known/foo))
(is (= (macros/full-symbol
'foo
"bar")
'bar/foo)))

View file

@ -0,0 +1,28 @@
(ns com.wsscode.misc.math-test
(:require
[clojure.test :refer [deftest is are run-tests testing]]
[com.wsscode.misc.math :as math]))
(deftest floor-test
(is (= (math/floor 30.2) 30))
(is (= (math/floor 30.9) 30)))
(deftest round-test
(is (= (math/round 30.2) 30))
(is (= (math/round 30.6) 31)))
(deftest ceil-test
(is (= (math/ceil 30.2) 31))
(is (= (math/ceil 30.9) 31)))
(deftest divmod-test
(is (= (math/divmod 10 3)
[3 1])))
(deftest parse-long-test
(is (= (math/parse-long "21")
21)))
(deftest parse-double-test
(is (= (math/parse-double "21.3")
21.3)))

View file

@ -0,0 +1,36 @@
(ns com.wsscode.misc.refs-test
(:require
[clojure.test :refer [deftest is are run-tests testing]]
[com.wsscode.misc.refs :refer [atom?] :as refs]))
(deftest kw-identical?-test
(is (not (refs/kw-identical? :foo :bar)))
(is (not (refs/kw-identical? :foo "foo")))
(is (refs/kw-identical? :foo :foo))
(is (refs/kw-identical? :foo (keyword "foo"))))
(deftest atom?-test
(is (true? (atom? (atom "x"))))
(is (false? (atom? "x"))))
(deftest greset!-test
(let [x (atom nil)]
(refs/greset! x "val")
(is (= @x "val")))
(let [x (volatile! nil)]
(refs/greset! x "val")
(is (= @x "val"))))
(deftest gswap!-test
(let [x (atom 10)]
(refs/gswap! x inc)
(is (= @x 11)))
(let [x (volatile! 10)]
(refs/gswap! x inc)
(is (= @x 11)))
(let [x (volatile! 10)]
(refs/gswap! x + 1 2 3 4 5)
(is (= @x 25))))

View file

@ -0,0 +1,7 @@
(ns com.wsscode.misc.uuid-test
(:require
[clojure.test :refer [deftest is are run-tests testing]]
[com.wsscode.misc.uuid :as uuid]))
(deftest cljc-random-uuid-test
(is (uuid? (uuid/cljc-random-uuid))))

View file

@ -0,0 +1,386 @@
(ns edn-query-language.core-test
(:require [clojure.spec.alpha :as s]
[clojure.spec.test.alpha :as s.test]
[clojure.test :refer [deftest is testing]]
[clojure.test.check :as tc]
[clojure.test.check.clojure-test :as test]
[clojure.test.check.generators :as gen]
[clojure.test.check.properties :as props]
[edn-query-language.core :as eql]
[edn-query-language.gen :as eql-gen]))
(s.test/instrument)
;; spec tests
(defn valid-queries-props []
(props/for-all [query (eql-gen/make-gen {} ::eql-gen/gen-query)]
(s/valid? ::eql/query query)))
(test/defspec generator-makes-valid-queries {:max-size 12 :num-tests 50} (valid-queries-props))
(comment
(tc/quick-check 50 (valid-queries-props) :max-size 12))
;; lib tests
(defn remove-meta [x]
(eql/transduce-children (map #(dissoc % :meta)) x))
(defn tquery->ast [query]
(remove-meta (eql/query->ast query)))
(deftest test-query->ast
(testing "empty query"
(is (= (tquery->ast [])
{:type :root, :children []})))
(testing "single property"
(is (= (tquery->ast [:a])
{:type :root, :children [{:type :prop, :dispatch-key :a, :key :a}]})))
(testing "multiple properties"
(is (= (tquery->ast [:a :b])
{:type :root,
:children [{:type :prop, :dispatch-key :a, :key :a}
{:type :prop, :dispatch-key :b, :key :b}]})))
(testing "blank join"
(is (= (tquery->ast [{:a []}])
{:type :root,
:children [{:type :join, :dispatch-key :a, :key :a, :query [], :children []}]})))
(testing "simple join"
(is (= (tquery->ast [{:a [:b]}])
{:type :root,
:children [{:type :join,
:dispatch-key :a,
:key :a,
:query [:b],
:children [{:type :prop, :dispatch-key :b, :key :b}]}]})))
(testing "param expression"
(is (= (tquery->ast ['(:a {:foo "bar"})])
{:type :root,
:children [{:type :prop,
:dispatch-key :a,
:key :a,
:params {:foo "bar"},}]})))
(testing "param join"
(is (= (tquery->ast ['({:a [:sub]} {:foo "bar"})])
{:type :root,
:children [{:type :join,
:dispatch-key :a,
:key :a,
:query [:sub],
:children [{:type :prop, :dispatch-key :sub, :key :sub}],
:params {:foo "bar"},}]})))
(testing "param join 2"
(is (= (tquery->ast [{'(:a {:foo "bar"}) [:sub]}])
{:type :root
:children [{:children [{:dispatch-key :sub
:key :sub
:type :prop}]
:dispatch-key :a
:key :a
:params {:foo "bar"}
:query [:sub]
:type :join}]})))
(testing "union query"
(is (= (tquery->ast [{:foo {:a [:b]
:c [:d]}}])
{:type :root,
:children [{:type :join,
:dispatch-key :foo,
:key :foo,
:query {:a [:b], :c [:d]},
:children [{:type :union,
:query {:a [:b], :c [:d]},
:children [{:type :union-entry,
:union-key :a,
:query [:b],
:children [{:type :prop, :dispatch-key :b, :key :b}]}
{:type :union-entry,
:union-key :c,
:query [:d],
:children [{:type :prop, :dispatch-key :d, :key :d}]}]}]}]})))
(testing "unbounded recursion"
(is (= (tquery->ast '[{:item [:a :b {:parent ...}]}])
'{:type :root,
:children [{:type :join,
:dispatch-key :item,
:key :item,
:query [:a :b {:parent ...}],
:children [{:type :prop, :dispatch-key :a, :key :a}
{:type :prop, :dispatch-key :b, :key :b}
{:type :join, :dispatch-key :parent, :key :parent, :query ...}]}]})))
(testing "bounded recursion"
(is (= (tquery->ast '[{:item [:a :b {:parent 5}]}])
'{:type :root,
:children [{:type :join,
:dispatch-key :item,
:key :item,
:query [:a :b {:parent 5}],
:children [{:type :prop, :dispatch-key :a, :key :a}
{:type :prop, :dispatch-key :b, :key :b}
{:type :join, :dispatch-key :parent, :key :parent, :query 5}]}]})))
(testing "mutation expression"
(is (= (tquery->ast ['(a {})])
'{:type :root,
:children [{:dispatch-key a,
:key a,
:params {},
:type :call}]})))
(testing "mutation join expression"
(is (= (tquery->ast [{'(a {}) [:sub-query]}])
'{:type :root,
:children [{:dispatch-key a,
:key a,
:params {},
:type :call,
:query [:sub-query],
:children [{:type :prop, :dispatch-key :sub-query, :key :sub-query}]}]}))))
(defn query<->ast-props []
(props/for-all [query (eql-gen/make-gen {::eql-gen/gen-params
(fn [_]
(gen/map gen/keyword gen/string-alphanumeric))}
::eql-gen/gen-query)]
(let [ast (-> query
eql/query->ast
eql/ast->query
eql/query->ast)]
(= ast (-> ast
eql/ast->query
eql/query->ast)))))
(test/defspec query-ast-roundtrip {:max-size 12 :num-tests 100} (query<->ast-props))
(comment
(tc/quick-check 100 (query<->ast-props) :max-size 12))
(deftest test-ast->query
(is (= (eql/ast->query {:type :prop
:key :foo
:dispatch-key :foo})
[:foo]))
(is (= (eql/ast->query {:type :root
:children [{:type :prop
:dispatch-key :foo
:key :foo}]})
[:foo])))
(deftest test-focus-subquery
(is (= (eql/focus-subquery [] [])
[]))
(is (= (eql/focus-subquery [:a :b :c] [])
[]))
(is (= (eql/focus-subquery [:a :b :c] [:d])
[]))
(is (= (eql/focus-subquery [:a :b :c] [:a])
[:a]))
(is (= (eql/focus-subquery [:a :b :c] [:a :b])
[:a :b]))
(is (= (eql/focus-subquery [:a {:b [:d]}] [:a :b])
[:a {:b [:d]}]))
(is (= (eql/focus-subquery [:a {:b [:c :d]}] [:a {:b [:c]}])
[:a {:b [:c]}]))
(is (= (eql/focus-subquery [:a '({:b [:c :d]} {:param "value"})] [:a {:b [:c]}])
[:a '({:b [:c]} {:param "value"})]))
; in union case, keys absent from focus will be pulled anyway, given ones will focus
(is (= (eql/focus-subquery [:a {:b {:c [:d :e]
:f [:g :h]}}]
[:a {:b {:f [:g]}}])
[:a {:b {:c [:d :e] :f [:g]}}])))
(defn transduce-query [xform query]
(->> query eql/query->ast
(eql/transduce-children xform)
eql/ast->query))
(deftest test-tranduce-children
(is (= (transduce-query
(comp (filter (comp #{:a :c} :key))
(map #(assoc % :params {:n 42})))
[:a :b :c :d])
'[(:a {:n 42}) (:c {:n 42})])))
(deftest test-merge-queries
(is (= (eql/merge-queries nil nil)
[]))
(is (= (eql/merge-queries [:a] nil)
[:a]))
(is (= (eql/merge-queries [] [])
[]))
(is (= (eql/merge-queries [:a] [])
[:a]))
(is (= (eql/merge-queries [:a] [:a])
[:a]))
(is (= (eql/merge-queries [:a] [:b])
[:a :b]))
(is (= (eql/merge-queries [:a] [:b :c :d])
[:a :b :c :d]))
(is (= (eql/merge-queries [[:u/id 1]] [[:u/id 2]])
[[:u/id 1] [:u/id 2]]))
(is (= (eql/merge-queries [{:user [:name]}] [{:user [:email]}])
[{:user [:name :email]}]))
(is (= (eql/merge-queries [:a] [{:a [:x]}])
[{:a [:x]}]))
(is (= (eql/merge-queries [{:a [:x]}] [:a])
[{:a [:x]}]))
(testing "don't merge queries with different params"
(is (= (eql/merge-queries ['({:user [:name]} {:login "u1"})]
['({:user [:email]} {:login "u2"})])
nil)))
(testing "don't merge queries with different params"
(is (= (eql/merge-queries ['(:user {:login "u1"})]
['(:user {:login "u2"})])
nil)))
(testing "merge when params are same"
(is (= (eql/merge-queries ['({:user [:name]} {:login "u1"})]
['({:user [:email]} {:login "u1"})])
['({:user [:name :email]} {:login "u1"})])))
(testing "calls can't be merged when same name occurs"
(is (= (eql/merge-queries ['(hello {:login "u1"})]
['(hello {:bla "2"})])
nil)))
(testing "even when parameters are the same"
(is (= (eql/merge-queries ['(hello {:login "u1"})]
['(hello {:login "u1"})])
nil))))
(deftest test-update-child
(is (= (eql/update-child {:children [{:dispatch-key :id :key :id :type :prop}
{:dispatch-key :parent :key :parent :query 3 :type :join}]
:type :root}
:parent update :query dec)
{:children [{:dispatch-key :id :key :id :type :prop}
{:dispatch-key :parent :key :parent :query 2 :type :join}]
:type :root})))
(deftest update-recursive-depth-test
(is (= (eql/update-recursive-depth
{:children [{:dispatch-key :id :key :id :type :prop}
{:dispatch-key :parent :key :parent :query 3 :type :join}]
:type :root}
:parent dec)
{:children [{:dispatch-key :id :key :id :type :prop}
{:dispatch-key :parent :key :parent :query 2 :type :join}]
:type :root})))
(deftest test-mask-query
(is (= (eql/mask-query [] [])
[]))
(is (= (eql/mask-query [:foo :bar] [])
[]))
(is (= (eql/mask-query [:foo :bar] [:foo])
[:foo]))
(is (= (eql/mask-query [:bar :foo] [:foo])
[:foo]))
(is (= (eql/mask-query [:foo {:bar [:inside]}] [:foo])
[:foo]))
(is (= (eql/mask-query ['(:foo {:bla "meh"}) :bar] [:foo])
['(:foo {:bla "meh"})]))
(is (= (eql/mask-query [:foo {:bar [:inside :more]}] [:foo :bar])
[:foo {:bar [:inside :more]}]))
(is (= (eql/mask-query [:foo {:bar [:inside :more]}] [:foo {:bar [:inside]}])
[:foo {:bar [:inside]}])))
(deftest test-normalize-query-variables
(testing "blank query"
(is (= (eql/normalize-query-variables [])
[])))
(testing "simple query"
(is (= (eql/normalize-query-variables [:a :b :c])
[:a :b :c])))
(testing "normalize ident values"
(is (= (eql/normalize-query-variables [[:foo "bar"]])
[[:foo ::eql/var]])))
(testing "normalize params"
(is (= (eql/normalize-query-variables ['(:foo {:x 1 :y 2})])
['(:foo {:x ::eql/var :y ::eql/var})])))
(testing "all together"
(is (= (eql/normalize-query-variables '[:a :b {[:join "val"] [{(:c {:page 10}) [:d]}]}])
'[:a :b
{[:join ::eql/var]
[({:c [:d]}
{:page ::eql/var})]}]))))
(deftest test-query-id
(is (= (eql/query-id '[:a :b {[:join "val"] [{(:c {:page 10}) [:d]}]}])
-61421281)))
(deftest shallow-conversion
(testing "requesting shallow conversion will only convert the first layer of a query"
(let [ast (eql/query->shallow-ast [:x
{:y [{:z [:a]}]}
{[:table 1] [:z {:other [:m :n]}]}
{:ujoin {:u1 [:x] :u2 [:y]}}])]
(is (= {:type :root,
:children [{:type :prop, :dispatch-key :x, :key :x}
;; BB-TEST-PATCH: bb returns {} for some meta calls that clojure doesn't
{:type :join, :dispatch-key :y, :key :y, :query [{:z [:a]}] :meta {}}
{:type :join, :dispatch-key :table, :key [:table 1], :query [:z {:other [:m :n]}] :meta {}}
{:type :join, :dispatch-key :ujoin, :key :ujoin, :query {:u1 [:x], :u2 [:y]} :meta {}}]}
ast)))))
(deftest merge-asts-as-reduce-function
(testing
"init - when called with arity zero, it returns an empty ast"
(is (= {:type :root
:children []}
(transduce (map identity)
eql/merge-asts
[]))))
(testing
"completion - when called with arity one, it should return its argument"
(is (= {:children [{:dispatch-key :a
:key :a
:type :prop}]
:type :root}
(transduce (map identity)
eql/merge-asts
[(eql/query->ast [:a])]))))
(testing
"step - the old arity 2. Should compose both nodes into a new node"
(is (= {:children [{:dispatch-key :a
:key :a
:type :prop}
{:dispatch-key :b
:key :b
:type :prop}]
:type :root}
(transduce (map identity)
eql/merge-asts
[(eql/query->ast [:a])
(eql/query->ast [:b])])))))

View file

@ -0,0 +1,385 @@
(ns exoscale.lingo.test.core-test
(:require [clojure.test :refer [are deftest is]]
[exoscale.lingo :as l]
[exoscale.lingo.impl :as impl]
[exoscale.lingo.highlight :as u]
[clojure.spec.alpha :as s]))
(defn f2? [_] false)
(defn f3? [_] false)
(l/set-spec-error! `exoscale.lingo.test.core-test/f2? "yolo")
(l/set-spec-error! `f3? "should match Something")
(-> (s/def ::thing #(string? %))
(l/set-spec-error! "should be a string with bla bla bla"))
(s/def ::things (s/coll-of ::thing))
(s/def :foo/name string?)
(s/def :foo/names (s/coll-of :foo/name))
(s/def :foo/person (s/keys :req-un [:foo/names]))
(s/def :foo/age int?)
(s/def :foo/agent (s/keys :req-un [:foo/person :foo/age]))
(s/def :foo/agent2 (s/keys :req-un [:foo/person :foo/age]))
(def ^:dynamic *opts* {:highlight? false
:group-missing-keys? false
:group-or-problems? false
:header? false})
(deftest test-outputs
(are [spec val output] (= (l/explain-str spec val *opts*)
output)
::thing
1
"1 is an invalid :exoscale.lingo.test.core-test/thing - should be a string with bla bla bla\n"
(s/coll-of ::thing)
[1]
"1 in `[0]` is an invalid :exoscale.lingo.test.core-test/thing - should be a string with bla bla bla\n"
::things
[1]
"1 in `[0]` is an invalid :exoscale.lingo.test.core-test/thing - should be a string with bla bla bla\n"
;; test traversing
(s/def ::things2 ::things)
[1]
"1 in `[0]` is an invalid :exoscale.lingo.test.core-test/thing - should be a string with bla bla bla\n"
::things
1
"1 is an invalid :exoscale.lingo.test.core-test/things - should be a Collection\n"
(s/and string? #(> (count %) 3))
""
"\"\" is invalid - should contain more than 3 elements\n"
(s/def ::cnt #(> (count %) 3))
""
"\"\" is an invalid :exoscale.lingo.test.core-test/cnt - should contain more than 3 elements\n"
;; test the original unchanged msg
(s/and string? #(pos? (count %)))
""
"\"\" is invalid - (pos? (count %))\n"
;; with a custom pred matcher
(do
(l/set-pred-error! #{'(pos? (count %))} (constantly "should be non blank"))
(s/and string? #(pos? (count %))))
""
"\"\" is invalid - should be non blank\n"
#{:a :b :c}
"b"
"\"b\" is invalid - should be one of :a, :b, :c\n"
;; (s/and string? #(xss/string-of* % {:blank? false :min-length 3 :max-length 10}))
;; ""
;; "\"\" is invalid - should be a String non blank, at least 3 characters in length, at most 10 characters in length\n"
(s/def :exoscale.lingo/c1 (s/map-of int? int? :count 3))
{"a" "b"}
"{\"a\" \"b\"} is an invalid :exoscale.lingo/c1 - should contain exactly 3 elements\n"
(s/and any? #(= 1 (count %)))
[]
"[] is invalid - should contain exactly 1 element\n"
(s/and any? #(= (count %) 1))
[]
"[] is invalid - should contain exactly 1 element\n"
(s/and any? #(= 42 (count %)))
[]
"[] is invalid - should contain exactly 42 elements\n"
(s/and any? #(= (count %) 42))
[]
"[] is invalid - should contain exactly 42 elements\n"
(s/and any? #(>= (count %) 42))
[]
"[] is invalid - should contain at least 42 elements\n"
(s/and any? #(<= (count %) 1))
[1 1]
"[1 1] is invalid - should contain at most 1 element\n"
(s/and any? #(<= % 1))
10
"10 is invalid - should be at most 1\n"
(s/and any? #(< % 1))
10
"10 is invalid - should be less than 1\n"
(s/and any? #(>= % 1))
0
"0 is invalid - should be at least 1\n"
(s/and any? #(> % 1))
0
"0 is invalid - should be greater than 1\n"
(s/and any? #(= % "yolo"))
0
"0 is invalid - should be equal to yolo\n"
(s/and any? #(= "yolo" %))
0
"0 is invalid - should be equal to yolo\n"
(s/int-in 0 10)
-1
"-1 is invalid - should be an Integer between 0 10\n"
(s/and number? #(<= 0 % 10))
-1
"-1 is invalid - should be an Integer between 0 10\n"
(s/double-in :min 0 :max 10)
(double 11)
"11.0 is invalid - should be at most 10\n"
(s/coll-of any? :min-count 3)
[1]
"[1] is invalid - should contain at least 3 elements\n"
(s/coll-of any? :max-count 3)
[1 1 1 1]
"[1 1 1 1] is invalid - should contain between 0 3 elements\n"
(s/coll-of any? :max-count 3 :min-count 1)
[1 1 1 1]
"[1 1 1 1] is invalid - should contain between 1 3 elements\n"
(s/coll-of any? :count 3)
[1 1 1 1]
"[1 1 1 1] is invalid - should contain exactly 3 elements\n"
(s/coll-of any? :count 1)
[1 1 1 1]
"[1 1 1 1] is invalid - should contain exactly 1 element\n"
(s/coll-of any? :kind set?)
[1]
"[1] is invalid - should be a Set\n"
(s/map-of any? any? :count 1)
{:a 1 :b 2}
"{:a 1, :b 2} is invalid - should contain exactly 1 element\n"
neg-int?
[1]
"[1] is invalid - should be a Negative Integer\n"
(s/def :foo/agent (s/keys :req-un [:foo/person :foo/age]))
{:age 10}
"{:age 10} is an invalid :foo/agent - missing key :person\n"
(s/def :foo/agent (s/keys :req [:foo/person :foo/age]))
{:foo/age 10}
"#:foo{:age 10} is an invalid :foo/agent - missing key :foo/person\n"
(do
(alter-var-root #'*opts* assoc :hide-keyword-namespaces? true)
(s/def :foo/agent (s/keys :req [:foo/person :foo/age])))
{:foo/age 10}
"#:foo{:age 10} is an invalid :foo/agent - missing key :person\n"
(do
(alter-var-root #'*opts* dissoc :hide-keyword-namespaces?)
(s/def :foo/agent (s/keys :req-un [:foo/person :foo/age])))
{:age 10 :person {:names [1]}}
"1 in `person.names[0]` is an invalid :foo/name - should be a String\n"
(-> (s/def :foo/agent2 (s/keys :req-un [:foo/person :foo/age]))
;; (xs/with-meta! {:exoscale.lingo/name "Agent"})
)
{:age ""}
"\"\" in `age` is an invalid :foo/age - should be an Integer\n{:age \"\"} is an invalid :foo/agent2 - missing key :person\n"
(s/def :foo/animal #{:a :b :c})
1
"1 is an invalid :foo/animal - should be one of :a, :b, :c\n"
:foo/person
{:names [1 :yolo]}
"1 in `names[0]` is an invalid :foo/name - should be a String\n:yolo in `names[1]` is an invalid :foo/name - should be a String\n"
nil?
1
"1 is invalid - should be nil\n"
(s/nilable string?)
1
"1 is invalid - should be a String\n1 is invalid - should be nil\n"
;; BB-TEST-PATCH: bb returns sci details instead of string
#_f2?
#_1
#_"1 is invalid - yolo\n"
;; BB-TEST-PATCH: bb returns sci details instead of string
#_f3?
#_1
#_"1 is invalid - should match Something\n"))
(deftest focus-test
(let [_ '_]
(is (= [_ _ _] (u/focus [3 2 1] nil)))
(is (= _ (u/focus 1 nil)))
(is (= 1 (u/focus 1 [])))
(is (= [_ _ 1] (u/focus [3 2 1] [2])))
(is (= [3 _ _] (u/focus [3 2 1] [0])))
(is (= {:a 1} (u/focus {:a 1} [:a])))
(is (= {:a _} (u/focus {:a 1} [:b])))
(is (= {:a _ :c 1} (u/focus {:a {:b 1} :c 1} [:c])))
(is (= {:a {:b [_ {:c {:d #{:b :a}, :e _}}]}}
(u/focus {:a {:b [1 {:c {:d #{:a :b} :e :foo}}]}}
[:a :b 1 :c :d]
{:descend-mismatching-nodes? true})))
(is (= {:a {:b [1 {:c {:d #{_}, :e _}}]}}
(u/focus {:a {:b [1 {:c {:d #{:a :b} :e :foo}}]}}
[:a :b 0]
{:descend-mismatching-nodes? true})))
(is (= {:a {:b [_ {:c {:d #{_}, :e _}}]}}
(u/focus {:a {:b [1 {:c {:d #{:a :b} :e :foo}}]}}
nil
{:descend-mismatching-nodes? true})))
(is (= {:a {:b [1 _]}}
(u/focus {:a {:b [1 {:c {:d #{:a :b} :e :foo}}]}}
[:a :b 0])))
(is (= {:a {:b [_ {:c {:d #{:b :a} :e _}}]}}
(u/focus {:a {:b [1 {:c {:d #{:b :a} :e {:f 1}}}]}}
[:a :b 1 :c :d])))))
(deftest highlight-test
(are [input path output]
(= (u/highlight input path {:focus? true})
output)
[3 2 1] {:in [2] :val 1} "[_ _ 1]\n ^"
[3 2 1] {:in [0] :val 3} "[3 _ _]\n ^"
{:a 1} {:in [:a] :val 1} "{:a 1}\n ^"
{:a {:b 1} :c 1} {:in [:c] :val 1} "{:a _, :c 1}\n ^"
{:a {:b [1 {:c {:d #{:a :b} :e :foo}}]}}
{:in [:a :b 1 :c :d] :val #{:a :b}}
"{:a {:b [_ {:c {:d #{:b :a}, :e _}}]}}\n ^^^^^^^^"
{:a {:b [1 {:c {:d #{:a :b} :e :foo}}]}}
{:in [:a :b 0] :val 1}
"{:a {:b [1 _]}}\n ^"
{:a {:b [1 {:c {:d #{:a :b} :e :foo}}]}}
{:in [:a :b 0] :val 1}
"{:a {:b [1 _]}}\n ^"
{:a {:b [1 {:c {:d #{:b :a} :e {:f 1}}}]}}
{:in [:a :b 1 :c :d] :val #{:b :a}}
"{:a {:b [_ {:c {:d #{:b :a}, :e _}}]}}\n ^^^^^^^^"
;; single line hl
{:a {:bar 255555 :c 3 :d 4 :e 5}}
{:in [:a :bar] :val 255555}
"{:a {:bar 255555, :c _, :d _, :e _}}\n ^^^^^^"
;; ;; multiline hl output
{:aaaaaaaaaaaaa
{:bbbbbbbbbbbbbbbbbdddddddddddddddddddddddddddddddddddddd 2 :c 33333 :d 4 :e 5}}
{:in [:aaaaaaaaaaaaa :c] :val 33333}
"{:aaaaaaaaaaaaa\n {:bbbbbbbbbbbbbbbbbdddddddddddddddddddddddddddddddddddddd _,\n :c 33333,\n ^^^^^\n :d _,\n :e _}}")
(is (= ["[1]\n ^ should be a string with bla bla bla"]
(->> (l/explain-data ::things [1])
:clojure.spec.alpha/problems
(map :exoscale.lingo.explain/highlight)))))
(deftest test-group-map-keys
(is (= "missing keys :age, :person"
(-> (l/explain-data :foo/agent2 {} {:group-missing-keys? true})
:clojure.spec.alpha/problems
first
:exoscale.lingo.explain/message)))
(is (= #{"missing keys :age, :person"
"missing keys :names"}
(->> (l/explain-data (s/tuple :foo/agent2 :foo/person)
[{} {}]
{:group-missing-keys? true})
:clojure.spec.alpha/problems
(map :exoscale.lingo.explain/message)
set))))
(deftest test-group-or-keys
(s/def ::test-group-or-keys (s/nilable string?))
(s/def ::test-group-or-keys2 (s/or :str string? :int int?))
(is (= #{"should be a String OR should be nil"}
(->> (l/explain-data ::test-group-or-keys
1
{:group-or-problems? true
:group-missing-keys? true})
:clojure.spec.alpha/problems
(map :exoscale.lingo.explain/message)
set)))
(is (= #{"should be a String OR should be an Integer"}
(->> (l/explain-data ::test-group-or-keys2
:kw
{:group-or-problems? true
:group-missing-keys? true})
:clojure.spec.alpha/problems
(map :exoscale.lingo.explain/message)
set)))
(is (= #{"should be a String OR should be nil"}
(->> (l/explain-data (s/coll-of (s/or :_ ::test-group-or-keys
:_ string?))
["" 1]
{:group-or-problems? true
:group-missing-keys? true})
:clojure.spec.alpha/problems
(map :exoscale.lingo.explain/message)
set))
"ensure there is no duplication of messages in the final pb string")
(s/def ::test-group-or-keys3 int?)
(is (= #{"should be a String OR should be nil"
"should be a String OR should be an Integer"
"should be an Integer"}
(->> (l/explain-data (s/keys :req-un [::test-group-or-keys])
{:test-group-or-keys 1
::test-group-or-keys2 :boom
::test-group-or-keys3 ""}
{:group-or-problems? true
:group-missing-keys? true})
:clojure.spec.alpha/problems
(map :exoscale.lingo.explain/message)
set))
"grouping does not alter the other problems"))
(deftest fix-map-path-test
(is (= [] (impl/fix-map-path [] [])))
(is (= [] (impl/fix-map-path {} [])))
(is (= [:a] (impl/fix-map-path {:a 1} [:a 1])))
(is (= [:a :b :c] (impl/fix-map-path {:a {:b {:c 1}}} [:a 1 :b 1 :c 1])))
(is (= [:a :b :c 0] (impl/fix-map-path {:a {:b {:c [1]}}}
[:a 1 :b 1 :c 1 0])))
(is (= [:a :b :c 1 :d]
(impl/fix-map-path {:a {:b {:c [{} {:d 1}]}}} [:a 1 :b 1 :c 1 1 :d 1]))))

View file

@ -98,6 +98,7 @@
"{:foo/a #test/var clojure.core/+}")
{:foo/a #'+}))))
;; BB-TEST-PATCH: No *loaded-libs* in bb
#?(:bb :TODO :clj
(defn- remove-lib [lib]
(remove-ns lib)
@ -105,6 +106,7 @@
(derive :integrant.test-child/foo :integrant.test/foo)
;; BB-TEST-PATCH: No *loaded-libs* in bb
#?(:bb :TODO
:clj
(deftest load-namespaces-test

View file

@ -0,0 +1,57 @@
(ns meta-merge.core-test
(:require #?(:clj [clojure.test :refer :all]
:cljs [cljs.test :refer-macros [deftest is testing]])
[meta-merge.core :refer [meta-merge]]))
(deftest test-meta-merge
(testing "simple merge"
(is (= (meta-merge {:a 1 :b 2} {:b 3 :c 4})
{:a 1 :b 3 :c 4})))
(testing "inner map merge"
(is (= (meta-merge {:a {:b 1 :c 2}} {:a {:c 3}})
{:a {:b 1 :c 3}})))
(testing "inner set merge"
(is (= (meta-merge {:a #{:b :c}} {:a #{:c :d}})
{:a #{:b :c :d}})))
(testing "inner vector merge"
(is (= (meta-merge {:a [:b :c]} {:a [:d]})
{:a [:b :c :d]})))
(testing "meta replace"
(is (= (meta-merge {:a [:b :c]} {:a ^:replace [:d]})
{:a [:d]})))
(testing "meta displace"
(is (= (meta-merge {:a [:b :c]} {:a ^:displace [:d]})
{:a [:b :c]})))
(testing "meta prepend"
(is (= (meta-merge {:a [:b :c]} {:a ^:prepend [:d]})
{:a [:d :b :c]})))
(testing "deep inner merge"
(is (= (meta-merge {:a {:b {:c [:d]}}} {:a {:b {:c [:e] :f :g}}})
{:a {:b {:c [:d :e] :f :g}}})))
(testing "collection type remains the same"
(is (map? (meta-merge {:a :b} {:c :d})))
(is (vector? (meta-merge [:a :b] [:c])))
(is (set? (meta-merge #{:a :b} #{:c})))
(is (list? (meta-merge '(:a :b) '(:c)))))
(testing "nil displace"
(is (= (meta-merge {:b :c} {:a ^:displace [:d]})
{:a [:d] :b :c})))
(testing "varargs"
(is (= (meta-merge)
{}))
(is (= (meta-merge {:a :b})
{:a :b}))
(is (= (meta-merge {:a :b :x 1} {:a :c :y 2} {:a :d})
{:a :d :x 1 :y 2}))
(is (= (meta-merge {:a :b :x 1} {:a :c :y 2} {:a :d} {:y 4 :z 3})
{:a :d :x 1 :y 4 :z 3}))))

View file

@ -0,0 +1,5 @@
(ns meta-merge.test-runner
(:require [doo.runner :refer-macros [doo-tests]]
[meta-merge.core-test]))
(doo-tests 'meta-merge.core-test)

View file

@ -0,0 +1,22 @@
(ns swirrl.dogstatsd-test
(:require [swirrl.dogstatsd :as sut]
[swirrl.dogstatsd.specs]
[clojure.test :refer [deftest is testing]]
[clojure.spec.test.alpha :as st]))
(st/instrument)
(deftest basic-invocation-tests
(testing "Basic metric procedure calls run without error"
(let [client (sut/configure {:endpoint "localhost:8111"})]
(sut/increment! client ::increment)
(sut/increment! client ::increment 10)
(sut/decrement! client ::decrement)
(sut/histogram! client ::histogram 10)
(sut/distribution! client ::distribution 10)
(sut/set! client ::set "a-value")
(sut/event! client "event title" "some text here" {})
(is true))))