Add some additional libraries to test
Also improved docs around add-libtest Close #1137 Close #1128
This commit is contained in:
parent
2f6d363ee8
commit
744c5d0732
18 changed files with 1943 additions and 5 deletions
8
deps.edn
8
deps.edn
|
|
@ -114,7 +114,13 @@
|
||||||
clojure-term-colors/clojure-term-colors {:mvn/version "0.1.0"}
|
clojure-term-colors/clojure-term-colors {:mvn/version "0.1.0"}
|
||||||
io.aviso/pretty {:mvn/version "1.1.1"}
|
io.aviso/pretty {:mvn/version "1.1.1"}
|
||||||
progrock/progrock {:mvn/version "0.1.2"}
|
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"}
|
||||||
|
town.lilac/pyramid {:mvn/version "3.2.0"}
|
||||||
|
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
|
:classpath-overrides {org.clojure/clojure nil
|
||||||
org.clojure/spec.alpha nil}}
|
org.clojure/spec.alpha nil}}
|
||||||
:clj-nvd
|
:clj-nvd
|
||||||
|
|
|
||||||
16
doc/dev.md
16
doc/dev.md
|
|
@ -81,9 +81,19 @@ Test the native version:
|
||||||
## Tests for Libraries
|
## Tests for Libraries
|
||||||
|
|
||||||
Babashka runs tests of libraries that are compatible with it through
|
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
|
`script/run_lib_tests`. The script `add-libtest.clj` makes adding new libraries
|
||||||
and run them, use the script `add-libtest.clj` e.g. `script/add-libtest.clj
|
fairly easy. Some examples:
|
||||||
'{listora/again {:mvn/version "1.0.0"}}' https://github.com/liwp/again --test`.
|
|
||||||
|
```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:
|
If the library you want to add doesn't work automatically, you can manually do the following:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,12 @@ clj-commons/clj-yaml,https://github.com/clj-commons/clj-yaml
|
||||||
clj-commons/multigrep,https://github.com/clj-commons/multigrep
|
clj-commons/multigrep,https://github.com/clj-commons/multigrep
|
||||||
clojure-csv/clojure-csv,https://github.com/davidsantiago/clojure-csv
|
clojure-csv/clojure-csv,https://github.com/davidsantiago/clojure-csv
|
||||||
clojure-term-colors/clojure-term-colors,https://github.com/trhura/clojure-term-colors
|
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.github.seancorfield/honeysql,https://github.com/seancorfield/honeysql
|
||||||
com.grammarly/omniconf,https://github.com/grammarly/omniconf
|
com.grammarly/omniconf,https://github.com/grammarly/omniconf
|
||||||
com.stuartsierra/component,https://github.com/stuartsierra/component
|
com.stuartsierra/component,https://github.com/stuartsierra/component
|
||||||
com.stuartsierra/dependency,https://github.com/stuartsierra/dependency
|
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
|
comb/comb,https://github.com/weavejester/comb
|
||||||
cprop/cprop,https://github.com/tolitius/cprop
|
cprop/cprop,https://github.com/tolitius/cprop
|
||||||
crispin/crispin,https://github.com/dunaj-project/crispin
|
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
|
djblue/portal,https://github.com/djblue/portal
|
||||||
doric/doric,https://github.com/joegallo/doric
|
doric/doric,https://github.com/joegallo/doric
|
||||||
douglass/clj-psql,https://github.com/DarinDouglass/clj-psql
|
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
|
environ/environ,https://github.com/weavejester/environ
|
||||||
exoscale/coax,https://github.com/exoscale/coax
|
exoscale/coax,https://github.com/exoscale/coax
|
||||||
expound/expound,https://github.com/bhb/expound
|
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
|
hiccup/hiccup,http://github.com/weavejester/hiccup
|
||||||
honeysql/honeysql,https://github.com/seancorfield/honeysql
|
honeysql/honeysql,https://github.com/seancorfield/honeysql
|
||||||
http-kit/http-kit,https://github.com/http-kit/http-kit
|
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.aviso/pretty,https://github.com/AvisoNovate/pretty
|
||||||
io.github.cognitect-labs/test-runner,https://github.com/cognitect-labs/test-runner
|
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.github.technomancy/limit-break,https://github.com/technomancy/limit-break
|
||||||
io.helins/binf,https://github.com/helins/binf.cljc
|
io.helins/binf,https://github.com/helins/binf.cljc
|
||||||
io.replikativ/hasch,https://github.com/replikativ/hasch
|
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
|
listora/again,https://github.com/liwp/again
|
||||||
markdown-clj/markdown-clj,https://github.com/yogthos/markdown-clj
|
markdown-clj/markdown-clj,https://github.com/yogthos/markdown-clj
|
||||||
medley/medley,https://github.com/weavejester/medley
|
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
|
minimallist/minimallist,https://github.com/green-coder/minimallist
|
||||||
mvxcvi/arrangement,https://github.com/greglook/clj-arrangement
|
mvxcvi/arrangement,https://github.com/greglook/clj-arrangement
|
||||||
orchestra/orchestra,https://github.com/jeaye/orchestra
|
orchestra/orchestra,https://github.com/jeaye/orchestra
|
||||||
|
|
@ -69,4 +75,5 @@ selmer/selmer,https://github.com/yogthos/Selmer
|
||||||
slingshot/slingshot,https://github.com/scgilardi/slingshot
|
slingshot/slingshot,https://github.com/scgilardi/slingshot
|
||||||
table/table,https://github.com/cldwalker/table
|
table/table,https://github.com/cldwalker/table
|
||||||
testdoc/testdoc,https://github.com/liquidz/testdoc
|
testdoc/testdoc,https://github.com/liquidz/testdoc
|
||||||
|
town.lilac/pyramid,https://github.com/lilactown/pyramid
|
||||||
version-clj/version-clj,https://github.com/xsc/version-clj
|
version-clj/version-clj,https://github.com/xsc/version-clj
|
||||||
|
|
|
||||||
|
|
|
@ -96,4 +96,11 @@
|
||||||
io.aviso/pretty {:git-url "https://github.com/AvisoNovate/pretty", :test-namespaces (io.aviso.binary-test), :git-sha "155926f991f94addaf6f5c8621748924ab144988" :skip-windows true}
|
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"}
|
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
|
;; 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"}
|
||||||
|
town.lilac/pyramid {:git-url "https://github.com/lilactown/pyramid", :test-namespaces (pyramid.pull-test pyramid.query-test pyramid.core-test), :git-sha "3862d64bc78e789739515191b70a1f6591fd1b68"}
|
||||||
|
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"}
|
||||||
|
io.github.swirrl/dogstatsd {:git-url "https://github.com/swirrl/dogstatsd", :test-namespaces (swirrl.dogstatsd-test), :git-sha "e110caae452cd1185e65e389a359b69502076d61"}}
|
||||||
|
|
|
||||||
257
test-resources/lib_tests/com/wsscode/misc/coll_test.cljc
Normal file
257
test-resources/lib_tests/com/wsscode/misc/coll_test.cljc
Normal 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}]})))
|
||||||
14
test-resources/lib_tests/com/wsscode/misc/macros_test.clj
Normal file
14
test-resources/lib_tests/com/wsscode/misc/macros_test.clj
Normal 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)))
|
||||||
28
test-resources/lib_tests/com/wsscode/misc/math_test.cljc
Normal file
28
test-resources/lib_tests/com/wsscode/misc/math_test.cljc
Normal 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)))
|
||||||
36
test-resources/lib_tests/com/wsscode/misc/refs_test.cljc
Normal file
36
test-resources/lib_tests/com/wsscode/misc/refs_test.cljc
Normal 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))))
|
||||||
7
test-resources/lib_tests/com/wsscode/misc/uuid_test.cljc
Normal file
7
test-resources/lib_tests/com/wsscode/misc/uuid_test.cljc
Normal 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))))
|
||||||
386
test-resources/lib_tests/edn_query_language/core_test.cljc
Normal file
386
test-resources/lib_tests/edn_query_language/core_test.cljc
Normal 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])])))))
|
||||||
385
test-resources/lib_tests/exoscale/lingo/test/core_test.cljc
Normal file
385
test-resources/lib_tests/exoscale/lingo/test/core_test.cljc
Normal 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]))))
|
||||||
|
|
@ -98,6 +98,7 @@
|
||||||
"{:foo/a #test/var clojure.core/+}")
|
"{:foo/a #test/var clojure.core/+}")
|
||||||
{:foo/a #'+}))))
|
{:foo/a #'+}))))
|
||||||
|
|
||||||
|
;; BB-TEST-PATCH: No *loaded-libs* in bb
|
||||||
#?(:bb :TODO :clj
|
#?(:bb :TODO :clj
|
||||||
(defn- remove-lib [lib]
|
(defn- remove-lib [lib]
|
||||||
(remove-ns lib)
|
(remove-ns lib)
|
||||||
|
|
@ -105,6 +106,7 @@
|
||||||
|
|
||||||
(derive :integrant.test-child/foo :integrant.test/foo)
|
(derive :integrant.test-child/foo :integrant.test/foo)
|
||||||
|
|
||||||
|
;; BB-TEST-PATCH: No *loaded-libs* in bb
|
||||||
#?(:bb :TODO
|
#?(:bb :TODO
|
||||||
:clj
|
:clj
|
||||||
(deftest load-namespaces-test
|
(deftest load-namespaces-test
|
||||||
|
|
|
||||||
57
test-resources/lib_tests/meta_merge/core_test.cljc
Normal file
57
test-resources/lib_tests/meta_merge/core_test.cljc
Normal 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}))))
|
||||||
5
test-resources/lib_tests/meta_merge/test_runner.cljs
Normal file
5
test-resources/lib_tests/meta_merge/test_runner.cljs
Normal 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)
|
||||||
574
test-resources/lib_tests/pyramid/core_test.cljc
Normal file
574
test-resources/lib_tests/pyramid/core_test.cljc
Normal file
|
|
@ -0,0 +1,574 @@
|
||||||
|
(ns pyramid.core-test
|
||||||
|
(:require
|
||||||
|
[pyramid.core :as p]
|
||||||
|
[pyramid.ident :as ident]
|
||||||
|
[clojure.test :as t]))
|
||||||
|
|
||||||
|
|
||||||
|
(t/deftest normalization
|
||||||
|
(t/is (= {:person/id {0 {:person/id 0}}}
|
||||||
|
(p/db [{:person/id 0}]))
|
||||||
|
"a single entity")
|
||||||
|
(t/is (= {:person/id {0 {:person/id 0
|
||||||
|
:person/name "asdf"}
|
||||||
|
1 {:person/id 1
|
||||||
|
:person/name "jkl"}}}
|
||||||
|
(p/db [{:person/id 0
|
||||||
|
:person/name "asdf"}
|
||||||
|
{:person/id 1
|
||||||
|
:person/name "jkl"}]))
|
||||||
|
"multiple entities with attributes")
|
||||||
|
(t/is (= {:person/id {0 {:person/id 0
|
||||||
|
:person/name "asdf"}
|
||||||
|
1 {:person/id 1
|
||||||
|
:person/name "jkl"}}
|
||||||
|
:people [[:person/id 0]
|
||||||
|
[:person/id 1]]}
|
||||||
|
(p/db [{:people [{:person/id 0
|
||||||
|
:person/name "asdf"}
|
||||||
|
{:person/id 1
|
||||||
|
:person/name "jkl"}]}]))
|
||||||
|
"nested under a key")
|
||||||
|
(t/is (= {:person/id {0 {:person/id 0
|
||||||
|
:some-data {1 "hello"
|
||||||
|
3 "world"}}}}
|
||||||
|
(p/db [{:person/id 0
|
||||||
|
:some-data {1 "hello"
|
||||||
|
3 "world"}}]))
|
||||||
|
"Map with numbers as keys")
|
||||||
|
(t/is (= {:a/id {1 {:a/id 1
|
||||||
|
:b [{:c [:d/id 1]}]}}
|
||||||
|
:d/id {1 {:d/id 1
|
||||||
|
:d/txt "a"}}}
|
||||||
|
(p/db [{:a/id 1
|
||||||
|
:b [{:c {:d/id 1
|
||||||
|
:d/txt "a"}}]}]))
|
||||||
|
"Collections of non-entities still get normalized")
|
||||||
|
(t/is (= {:person/id
|
||||||
|
{123
|
||||||
|
{:person/id 123,
|
||||||
|
:person/name "Will",
|
||||||
|
:contact {:phone "000-000-0001"},
|
||||||
|
:best-friend [:person/id 456],
|
||||||
|
:friends
|
||||||
|
[[:person/id 9001]
|
||||||
|
[:person/id 456]
|
||||||
|
[:person/id 789]
|
||||||
|
[:person/id 1000]]},
|
||||||
|
456
|
||||||
|
{:person/id 456,
|
||||||
|
:person/name "Jose",
|
||||||
|
:account/email "asdf@jkl",
|
||||||
|
:best-friend [:person/id 123]},
|
||||||
|
9001 #:person{:id 9001, :name "Georgia"},
|
||||||
|
789 #:person{:id 789, :name "Frank"},
|
||||||
|
1000 #:person{:id 1000, :name "Robert"}}}
|
||||||
|
(p/db [{:person/id 123
|
||||||
|
:person/name "Will"
|
||||||
|
:contact {:phone "000-000-0001"}
|
||||||
|
:best-friend
|
||||||
|
{:person/id 456
|
||||||
|
:person/name "Jose"
|
||||||
|
:account/email "asdf@jkl"}
|
||||||
|
:friends
|
||||||
|
[{:person/id 9001
|
||||||
|
:person/name "Georgia"}
|
||||||
|
{:person/id 456
|
||||||
|
:person/name "Jose"}
|
||||||
|
{:person/id 789
|
||||||
|
:person/name "Frank"}
|
||||||
|
{:person/id 1000
|
||||||
|
:person/name "Robert"}]}
|
||||||
|
{:person/id 456
|
||||||
|
:best-friend {:person/id 123}}]))
|
||||||
|
"refs"))
|
||||||
|
|
||||||
|
|
||||||
|
(t/deftest non-entities
|
||||||
|
(t/is (= {:foo ["bar"]} (p/db [{:foo ["bar"]}])))
|
||||||
|
(t/is (= {:person/id {0 {:person/id 0
|
||||||
|
:foo ["bar"]}}}
|
||||||
|
(p/db [{:person/id 0
|
||||||
|
:foo ["bar"]}]))))
|
||||||
|
|
||||||
|
|
||||||
|
(t/deftest custom-schema
|
||||||
|
(t/is (= {:color {"red" {:color "red" :hex "#ff0000"}}}
|
||||||
|
(p/db [{:color "red" :hex "#ff0000"}]
|
||||||
|
(ident/by-keys :color)))
|
||||||
|
"ident/by-keys")
|
||||||
|
(t/is (= {:color {"red" {:color "red" :hex "#ff0000"}}}
|
||||||
|
(p/db [^{:db/ident :color}
|
||||||
|
{:color "red" :hex "#ff0000"}]))
|
||||||
|
"local schema")
|
||||||
|
(t/testing "complex schema"
|
||||||
|
(let [db (p/db [{:type "person"
|
||||||
|
:id "1234"
|
||||||
|
:purchases [{:type "item"
|
||||||
|
:id "1234"}]}
|
||||||
|
{:type "item"
|
||||||
|
:id "5678"}
|
||||||
|
{:type "foo"}
|
||||||
|
{:id "bar"}]
|
||||||
|
(fn [entity]
|
||||||
|
(let [{:keys [type id]} entity]
|
||||||
|
(when (and (some? type) (some? id))
|
||||||
|
[(keyword type "id") id]))))]
|
||||||
|
(t/is (= {:person/id
|
||||||
|
{"1234" {:type "person", :id "1234", :purchases [[:item/id "1234"]]}},
|
||||||
|
:item/id
|
||||||
|
{"1234" {:type "item", :id "1234"}, "5678" {:type "item", :id "5678"}},
|
||||||
|
:type "foo",
|
||||||
|
:id "bar"}
|
||||||
|
db)
|
||||||
|
"correctly identifies entities")
|
||||||
|
(t/is (= {[:person/id "1234"]
|
||||||
|
{:type "person", :id "1234", :purchases [{:type "item", :id "1234"}]}}
|
||||||
|
(p/pull db [{[:person/id "1234"] [:type :id {:purchases [:type :id]}]}]))
|
||||||
|
"pull"))))
|
||||||
|
|
||||||
|
|
||||||
|
(t/deftest add
|
||||||
|
(t/is (= {:person/id {0 {:person/id 0}}}
|
||||||
|
(p/add {} {:person/id 0})))
|
||||||
|
(t/is (= {:person/id {0 {:person/id 0 :person/name "Gill"}
|
||||||
|
1 {:person/id 1}}}
|
||||||
|
(p/add
|
||||||
|
{}
|
||||||
|
{:person/id 0}
|
||||||
|
{:person/id 1}
|
||||||
|
{:person/id 0 :person/name "Gill"}))))
|
||||||
|
|
||||||
|
|
||||||
|
(t/deftest add-report
|
||||||
|
(t/is (= {:db {:person/id {0 {:person/id 0}}}
|
||||||
|
:entities #{[:person/id 0]}}
|
||||||
|
(p/add-report {} {:person/id 0})))
|
||||||
|
(t/is (= {:db {:person/id {0 {:person/id 0
|
||||||
|
:person/name "Gill"
|
||||||
|
:best-friend [:person/id 1]}
|
||||||
|
1 {:person/id 1
|
||||||
|
:person/name "Uma"}}
|
||||||
|
:me [:person/id 0]}
|
||||||
|
:entities #{[:person/id 0]
|
||||||
|
[:person/id 1]}}
|
||||||
|
(p/add-report {} {:me {:person/id 0
|
||||||
|
:person/name "Gill"
|
||||||
|
:best-friend {:person/id 1
|
||||||
|
:person/name "Uma"}}})))
|
||||||
|
#_(t/is (= {:db {:person/id {0 {:person/id 0 :person/name "Gill"}
|
||||||
|
1 {:person/id 1}}}
|
||||||
|
:entities #{{:person/id 0 :person/name "Gill"}
|
||||||
|
{:person/id 1}}}
|
||||||
|
(p/add-report
|
||||||
|
{}
|
||||||
|
{:person/id 0}
|
||||||
|
{:person/id 1}
|
||||||
|
{:person/id 0 :person/name "Gill"}))))
|
||||||
|
|
||||||
|
|
||||||
|
(def data
|
||||||
|
{:people/all [{:person/id 0
|
||||||
|
:person/name "Alice"
|
||||||
|
:person/age 25
|
||||||
|
:best-friend {:person/id 1}
|
||||||
|
:person/favorites
|
||||||
|
{:favorite/ice-cream "vanilla"}}
|
||||||
|
{:person/id 1
|
||||||
|
:person/name "Bob"
|
||||||
|
:person/age 23}]})
|
||||||
|
|
||||||
|
|
||||||
|
(def db
|
||||||
|
(p/db [data]))
|
||||||
|
|
||||||
|
|
||||||
|
(t/deftest pull
|
||||||
|
(t/is (= #:people{:all [{:person/id 0} {:person/id 1}]}
|
||||||
|
(p/pull db [:people/all]))
|
||||||
|
"simple key")
|
||||||
|
(t/is (= {:people/all [{:person/name "Alice"
|
||||||
|
:person/id 0}
|
||||||
|
{:person/name "Bob"
|
||||||
|
:person/id 1}]}
|
||||||
|
(p/pull db [{:people/all [:person/name :person/id]}]))
|
||||||
|
"basic join + prop")
|
||||||
|
(t/is (= #:people{:all [{:person/name "Alice"
|
||||||
|
:person/id 0
|
||||||
|
:best-friend #:person{:name "Bob", :id 1 :age 23}}
|
||||||
|
#:person{:name "Bob", :id 1}]}
|
||||||
|
(p/pull db [#:people{:all [:person/name :person/id :best-friend]}]))
|
||||||
|
"join + prop + join ref lookup")
|
||||||
|
(t/is (= #:people{:all [{:person/name "Alice"
|
||||||
|
:person/id 0
|
||||||
|
:best-friend #:person{:name "Bob"}}
|
||||||
|
#:person{:name "Bob", :id 1}]}
|
||||||
|
(p/pull db [#:people{:all [:person/name
|
||||||
|
:person/id
|
||||||
|
{:best-friend [:person/name]}]}]))
|
||||||
|
"join + prop, ref as prop resolver")
|
||||||
|
(t/is (= {[:person/id 1] #:person{:id 1, :name "Bob", :age 23}}
|
||||||
|
(p/pull db [[:person/id 1]]))
|
||||||
|
"ident acts as ref lookup")
|
||||||
|
(t/is (= {[:person/id 0] {:person/id 0
|
||||||
|
:person/name "Alice"
|
||||||
|
:person/age 25
|
||||||
|
:best-friend {:person/id 1}
|
||||||
|
:person/favorites #:favorite{:ice-cream "vanilla"}}}
|
||||||
|
(p/pull db [[:person/id 0]]))
|
||||||
|
"ident does not resolve nested refs")
|
||||||
|
(t/is (= {[:person/id 0] #:person{:id 0
|
||||||
|
:name "Alice"
|
||||||
|
:favorites #:favorite{:ice-cream "vanilla"}}}
|
||||||
|
(p/pull db [{[:person/id 0] [:person/id
|
||||||
|
:person/name
|
||||||
|
:person/favorites]}]))
|
||||||
|
"join on ident")
|
||||||
|
(t/is (= {:people/all [{:person/name "Alice"
|
||||||
|
:person/id 0
|
||||||
|
:best-friend #:person{:name "Bob", :id 1 :age 23}}
|
||||||
|
#:person{:name "Bob", :id 1}]
|
||||||
|
[:person/id 1] #:person{:age 23}}
|
||||||
|
(p/pull db [{:people/all [:person/name :person/id :best-friend]}
|
||||||
|
{[:person/id 1] [:person/age]}]))
|
||||||
|
"multiple joins")
|
||||||
|
|
||||||
|
(t/testing "includes params"
|
||||||
|
(t/is (= #:people{:all [#:person{:name "Bob", :id 1}]}
|
||||||
|
(p/pull (-> db
|
||||||
|
(p/add {'(:people/all {:with "params"}) [[:person/id 1]]}))
|
||||||
|
'[{(:people/all {:with "params"})
|
||||||
|
[:person/name :person/id]}])))
|
||||||
|
(t/is (= '{:person/foo {:person/id 1
|
||||||
|
:person/name "Bob"}}
|
||||||
|
(p/pull (-> db
|
||||||
|
(p/add {'(:person/foo {:person/id 2})
|
||||||
|
{:person/id 1}}))
|
||||||
|
'[{(:person/foo {:person/id 2})
|
||||||
|
[:person/name :person/id]}]))
|
||||||
|
"params that include an entity-looking thing should not be normalized")
|
||||||
|
(t/is (= {}
|
||||||
|
(p/pull db '[([:person/id 1] {:with "params"})])))
|
||||||
|
(t/is (= {}
|
||||||
|
(p/pull db '[{(:people/all {:with "params"})
|
||||||
|
[:person/name :person/id]}]))))
|
||||||
|
|
||||||
|
(t/testing "union"
|
||||||
|
(let [data {:chat/entries
|
||||||
|
[{:message/id 0
|
||||||
|
:message/text "foo"
|
||||||
|
:chat.entry/timestamp "1234"}
|
||||||
|
{:message/id 1
|
||||||
|
:message/text "bar"
|
||||||
|
:chat.entry/timestamp "1235"}
|
||||||
|
{:audio/id 0
|
||||||
|
:audio/url "audio://asdf.jkl"
|
||||||
|
:audio/duration 1234
|
||||||
|
:chat.entry/timestamp "4567"}
|
||||||
|
{:photo/id 0
|
||||||
|
:photo/url "photo://asdf_10x10.jkl"
|
||||||
|
:photo/height 10
|
||||||
|
:photo/width 10
|
||||||
|
:chat.entry/timestamp "7890"}]}
|
||||||
|
db1 (p/db [data])
|
||||||
|
query [{:chat/entries
|
||||||
|
{:message/id
|
||||||
|
[:message/id :message/text :chat.entry/timestamp]
|
||||||
|
|
||||||
|
:audio/id
|
||||||
|
[:audio/id :audio/url :audio/duration :chat.entry/timestamp]
|
||||||
|
|
||||||
|
:photo/id
|
||||||
|
[:photo/id :photo/url :photo/width :photo/height :chat.entry/timestamp]
|
||||||
|
|
||||||
|
:asdf/jkl [:asdf/jkl]}}]]
|
||||||
|
(t/is (= #:chat{:entries [{:message/id 0
|
||||||
|
:message/text "foo"
|
||||||
|
:chat.entry/timestamp "1234"}
|
||||||
|
{:message/id 1
|
||||||
|
:message/text "bar"
|
||||||
|
:chat.entry/timestamp "1235"}
|
||||||
|
{:audio/id 0
|
||||||
|
:audio/url "audio://asdf.jkl"
|
||||||
|
:audio/duration 1234
|
||||||
|
:chat.entry/timestamp "4567"}
|
||||||
|
{:photo/id 0
|
||||||
|
:photo/url "photo://asdf_10x10.jkl"
|
||||||
|
:photo/width 10
|
||||||
|
:photo/height 10
|
||||||
|
:chat.entry/timestamp "7890"}]}
|
||||||
|
(p/pull db1 query)))))
|
||||||
|
|
||||||
|
(t/testing "not found"
|
||||||
|
(t/is (= {} (p/pull {} [:foo])))
|
||||||
|
(t/is (= {} (p/pull {} [:foo :bar :baz])))
|
||||||
|
(t/is (= {} (p/pull {} [:foo {:bar [:asdf]} :baz])))
|
||||||
|
|
||||||
|
(t/is (= {:foo "bar"}
|
||||||
|
(p/pull {:foo "bar"} [:foo {:bar [:asdf]} :baz])))
|
||||||
|
(t/is (= {:bar {:asdf 123}}
|
||||||
|
(p/pull
|
||||||
|
{:bar {:asdf 123}}
|
||||||
|
[:foo {:bar [:asdf :jkl]} :baz])))
|
||||||
|
(t/is (= {:bar {}}
|
||||||
|
(p/pull
|
||||||
|
(p/db [{:bar {:bar/id 0}}
|
||||||
|
{:bar/id 0
|
||||||
|
:qwerty 1234}])
|
||||||
|
[:foo {:bar [:asdf :jkl]} :baz])))
|
||||||
|
(t/is (= {:bar {:asdf "jkl"}}
|
||||||
|
(p/pull
|
||||||
|
(p/db [{:bar {:bar/id 0}}
|
||||||
|
{:bar/id 0
|
||||||
|
:asdf "jkl"}])
|
||||||
|
[:foo {:bar [:asdf :jkl]} :baz])))
|
||||||
|
(t/is (= {:bar {}}
|
||||||
|
(p/pull
|
||||||
|
(p/db [{:bar {:bar/id 0}}
|
||||||
|
{:bar/id 1
|
||||||
|
:asdf "jkl"}])
|
||||||
|
[:foo {:bar [:asdf :jkl]} :baz])))
|
||||||
|
|
||||||
|
(t/is (= {:foo [{:bar/id 1
|
||||||
|
:bar/name "asdf"}
|
||||||
|
{:baz/id 1
|
||||||
|
:baz/name "jkl"}]}
|
||||||
|
(p/pull
|
||||||
|
(p/db [{:foo [{:bar/id 1
|
||||||
|
:bar/name "asdf"}
|
||||||
|
{:baz/id 1
|
||||||
|
:baz/name "jkl"}]}])
|
||||||
|
[{:foo {:bar/id [:bar/id :bar/name]
|
||||||
|
:baz/id [:baz/id :baz/name]}}])))
|
||||||
|
|
||||||
|
(t/is (= {:foo [{:bar/id 1
|
||||||
|
:bar/name "asdf"}
|
||||||
|
{:bar/id 2}
|
||||||
|
{:baz/id 1
|
||||||
|
:baz/name "jkl"}]}
|
||||||
|
(p/pull
|
||||||
|
(p/db [{:foo [{:bar/id 1
|
||||||
|
:bar/name "asdf"}
|
||||||
|
{:bar/id 2}
|
||||||
|
{:baz/id 1
|
||||||
|
:baz/name "jkl"}]}])
|
||||||
|
[{:foo {:bar/id [:bar/id :bar/name]
|
||||||
|
:baz/id [:baz/id :baz/name]}}]))))
|
||||||
|
|
||||||
|
(t/testing "bounded recursion"
|
||||||
|
(let [data {:entries
|
||||||
|
{:entry/id "foo"
|
||||||
|
:entry/folders
|
||||||
|
[{:entry/id "bar"}
|
||||||
|
{:entry/id "baz"
|
||||||
|
:entry/folders
|
||||||
|
[{:entry/id "asdf"
|
||||||
|
:entry/folders
|
||||||
|
[{:entry/id "qwerty"}]}
|
||||||
|
{:entry/id "jkl"
|
||||||
|
:entry/folders
|
||||||
|
[{:entry/id "uiop"}]}]}]}}
|
||||||
|
db (p/db [data])]
|
||||||
|
(t/is (= {:entries
|
||||||
|
{:entry/id "foo"
|
||||||
|
:entry/folders
|
||||||
|
[]}}
|
||||||
|
(p/pull db '[{:entries [:entry/id
|
||||||
|
{:entry/folders 0}]}])))
|
||||||
|
(t/is (= {:entries
|
||||||
|
{:entry/id "foo"
|
||||||
|
:entry/folders
|
||||||
|
[{:entry/id "bar"}
|
||||||
|
{:entry/id "baz"
|
||||||
|
:entry/folders []}]}}
|
||||||
|
(p/pull db '[{:entries [:entry/id
|
||||||
|
{:entry/folders 1}]}])))
|
||||||
|
(t/is (= {:entries
|
||||||
|
{:entry/id "foo"
|
||||||
|
:entry/folders
|
||||||
|
[{:entry/id "bar"}
|
||||||
|
{:entry/id "baz"
|
||||||
|
:entry/folders
|
||||||
|
[{:entry/id "asdf"
|
||||||
|
:entry/folders []}
|
||||||
|
{:entry/id "jkl"
|
||||||
|
:entry/folders []}]}]}}
|
||||||
|
(p/pull db '[{:entries [:entry/id
|
||||||
|
{:entry/folders 2}]}])))
|
||||||
|
(t/is (= {:entries
|
||||||
|
{:entry/id "foo"
|
||||||
|
:entry/folders
|
||||||
|
[{:entry/id "bar"}
|
||||||
|
{:entry/id "baz"
|
||||||
|
:entry/folders
|
||||||
|
[{:entry/id "asdf"
|
||||||
|
:entry/folders
|
||||||
|
[{:entry/id "qwerty"}]}
|
||||||
|
{:entry/id "jkl"
|
||||||
|
:entry/folders
|
||||||
|
[{:entry/id "uiop"}]}]}]}}
|
||||||
|
(p/pull db '[{:entries [:entry/id
|
||||||
|
{:entry/folders 3}]}])))
|
||||||
|
(t/is (= {:entries
|
||||||
|
{:entry/id "foo"
|
||||||
|
:entry/folders
|
||||||
|
[{:entry/id "bar"}
|
||||||
|
{:entry/id "baz"
|
||||||
|
:entry/folders
|
||||||
|
[{:entry/id "asdf"
|
||||||
|
:entry/folders
|
||||||
|
[{:entry/id "qwerty"}]}
|
||||||
|
{:entry/id "jkl"
|
||||||
|
:entry/folders
|
||||||
|
[{:entry/id "uiop"}]}]}]}}
|
||||||
|
(p/pull db '[{:entries [:entry/id
|
||||||
|
{:entry/folders 10}]}])))))
|
||||||
|
|
||||||
|
(t/testing "infinite recursion"
|
||||||
|
(let [data {:entries
|
||||||
|
{:entry/id "foo"
|
||||||
|
:entry/folders
|
||||||
|
[{:entry/id "bar"}
|
||||||
|
{:entry/id "baz"
|
||||||
|
:entry/folders
|
||||||
|
[{:entry/id "asdf"
|
||||||
|
:entry/folders
|
||||||
|
[{:entry/id "qwerty"}]}
|
||||||
|
{:entry/id "jkl"
|
||||||
|
:entry/folders
|
||||||
|
[{:entry/id "uiop"}]}]}]}}
|
||||||
|
db (p/db [data])]
|
||||||
|
(t/is (= data
|
||||||
|
(p/pull db '[{:entries [:entry/id
|
||||||
|
{:entry/folders ...}]}])))))
|
||||||
|
|
||||||
|
(t/testing "query metadata"
|
||||||
|
(t/is (-> db
|
||||||
|
(p/pull ^:foo [])
|
||||||
|
(meta)
|
||||||
|
(:foo))
|
||||||
|
"root")
|
||||||
|
(t/is (-> db
|
||||||
|
(p/pull [^:foo {[:person/id 0] [:person/name]}])
|
||||||
|
(get [:person/id 0])
|
||||||
|
(meta)
|
||||||
|
(:foo))
|
||||||
|
"join")
|
||||||
|
(let [data {:chat/entries
|
||||||
|
[{:message/id 0
|
||||||
|
:message/text "foo"
|
||||||
|
:chat.entry/timestamp "1234"}
|
||||||
|
{:message/id 1
|
||||||
|
:message/text "bar"
|
||||||
|
:chat.entry/timestamp "1235"}
|
||||||
|
{:audio/id 0
|
||||||
|
:audio/url "audio://asdf.jkl"
|
||||||
|
:audio/duration 1234
|
||||||
|
:chat.entry/timestamp "4567"}
|
||||||
|
{:photo/id 0
|
||||||
|
:photo/url "photo://asdf_10x10.jkl"
|
||||||
|
:photo/height 10
|
||||||
|
:photo/width 10
|
||||||
|
:chat.entry/timestamp "7890"}]}
|
||||||
|
db1 (p/db [data])
|
||||||
|
query ^:foo [^:bar
|
||||||
|
{:chat/entries
|
||||||
|
{:message/id
|
||||||
|
[:message/id :message/text :chat.entry/timestamp]
|
||||||
|
|
||||||
|
:audio/id
|
||||||
|
[:audio/id :audio/url :audio/duration :chat.entry/timestamp]
|
||||||
|
|
||||||
|
:photo/id
|
||||||
|
[:photo/id :photo/url :photo/width :photo/height :chat.entry/timestamp]
|
||||||
|
|
||||||
|
:asdf/jkl [:asdf/jkl]}}]
|
||||||
|
result (p/pull db1 query)]
|
||||||
|
(t/is (= #:chat{:entries [{:message/id 0
|
||||||
|
:message/text "foo"
|
||||||
|
:chat.entry/timestamp "1234"}
|
||||||
|
{:message/id 1
|
||||||
|
:message/text "bar"
|
||||||
|
:chat.entry/timestamp "1235"}
|
||||||
|
{:audio/id 0
|
||||||
|
:audio/url "audio://asdf.jkl"
|
||||||
|
:audio/duration 1234
|
||||||
|
:chat.entry/timestamp "4567"}
|
||||||
|
{:photo/id 0
|
||||||
|
:photo/url "photo://asdf_10x10.jkl"
|
||||||
|
:photo/width 10
|
||||||
|
:photo/height 10
|
||||||
|
:chat.entry/timestamp "7890"}]}
|
||||||
|
result))
|
||||||
|
(t/is (-> result meta :foo))
|
||||||
|
(t/is (every? #(:bar (meta %)) (get result :chat/entries)))))
|
||||||
|
(t/testing "dangling entities"
|
||||||
|
(t/is (= {[:id 0] {:friends [{:id 1} {:id 2}]}}
|
||||||
|
(p/pull
|
||||||
|
{:id {0 {:id 0 :name "asdf" :friends [[:id 1] [:id 2]]}
|
||||||
|
1 {:id 1 :name "jkl"}}}
|
||||||
|
[{[:id 0] [:friends]}]))
|
||||||
|
"dangling entity shows up in queries that do not select any props")
|
||||||
|
;; BB-TEST-PATCH: NullPointerException: Cannot invoke "clojure.lang.IObj.withMeta(clojure.lang.IPersistentMap)"
|
||||||
|
#_(t/is (= {[:id 0] {:friends [{:id 1, :name "jkl"} {:id 2}]}}
|
||||||
|
(p/pull
|
||||||
|
{:id {0 {:id 0 :name "asdf" :friends [[:id 1] [:id 2]]}
|
||||||
|
1 {:id 1 :name "jkl"}}}
|
||||||
|
[{[:id 0] [{:friends [:id :name]}]}]))
|
||||||
|
"dangling entity shows up in queries that include ID")
|
||||||
|
;; BB-TEST-PATCH: NullPointerException: Cannot invoke "clojure.lang.IObj.withMeta(clojure.lang.IPersistentMap)"
|
||||||
|
#_(t/is (= {[:id 0] {:friends [{:name "jkl"}]}}
|
||||||
|
(p/pull
|
||||||
|
{:id {0 {:id 0 :name "asdf" :friends [[:id 1] [:id 2]]}
|
||||||
|
1 {:id 1 :name "jkl"}}}
|
||||||
|
[{[:id 0] [{:friends [:name]}]}]))
|
||||||
|
"dangling entity does not show up in queries that do not include ID")))
|
||||||
|
|
||||||
|
|
||||||
|
(t/deftest pull-report
|
||||||
|
(t/is (= {:data {:people/all [{:person/name "Alice"}
|
||||||
|
{:person/name "Bob"}]}
|
||||||
|
:entities #{[:person/id 0] [:person/id 1]}}
|
||||||
|
(p/pull-report db [{:people/all [:person/name]}]))
|
||||||
|
"basic join + prop")
|
||||||
|
(t/is (= {:data #:people{:all [{:person/name "Alice"
|
||||||
|
:best-friend #:person{:name "Bob", :id 1 :age 23}}
|
||||||
|
#:person{:name "Bob"}]}
|
||||||
|
:entities #{[:person/id 0] [:person/id 1]}}
|
||||||
|
(p/pull-report db [#:people{:all [:person/name :best-friend]}]))
|
||||||
|
"join + prop + join ref lookup")
|
||||||
|
(t/is (= {:data {[:person/id 1] #:person{:id 1, :name "Bob", :age 23}}
|
||||||
|
:entities #{[:person/id 1]}}
|
||||||
|
(p/pull-report db [[:person/id 1]]))
|
||||||
|
"ident acts as ref lookup")
|
||||||
|
(t/is (= {:data {[:person/id 0] {:person/id 0
|
||||||
|
:person/name "Alice"
|
||||||
|
:person/age 25
|
||||||
|
:best-friend {:person/id 1}
|
||||||
|
:person/favorites #:favorite{:ice-cream "vanilla"}}}
|
||||||
|
:entities #{[:person/id 0]}}
|
||||||
|
(p/pull-report db [[:person/id 0]]))
|
||||||
|
"ident does not resolve nested refs"))
|
||||||
|
|
||||||
|
|
||||||
|
(t/deftest delete
|
||||||
|
(t/is (= {:people/all [[:person/id 0]]
|
||||||
|
:person/id {0 {:person/id 0
|
||||||
|
:person/name "Alice"
|
||||||
|
:person/age 25
|
||||||
|
:person/favorites #:favorite{:ice-cream "vanilla"}}}}
|
||||||
|
(p/delete db [:person/id 1]))))
|
||||||
|
|
||||||
|
|
||||||
|
(t/deftest data->query
|
||||||
|
(t/is (= [:a]
|
||||||
|
(p/data->query {:a 42})))
|
||||||
|
(t/is (= [{:a [:b]}]
|
||||||
|
(p/data->query {:a {:b 42}})))
|
||||||
|
(t/is (= [{:a [:b :c]}]
|
||||||
|
(p/data->query {:a [{:b 42} {:c :d}]})))
|
||||||
|
(t/is (= [{[:a 42] [:b]}]
|
||||||
|
(p/data->query {[:a 42] {:b 33}}))))
|
||||||
|
|
||||||
|
(comment
|
||||||
|
(t/run-tests))
|
||||||
23
test-resources/lib_tests/pyramid/pull_test.cljc
Normal file
23
test-resources/lib_tests/pyramid/pull_test.cljc
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
(ns pyramid.pull-test
|
||||||
|
(:require
|
||||||
|
[clojure.test :as t]
|
||||||
|
[pyramid.pull :as p]))
|
||||||
|
|
||||||
|
|
||||||
|
(def entities
|
||||||
|
(for [i (range 1000)]
|
||||||
|
[:id i]))
|
||||||
|
|
||||||
|
|
||||||
|
(t/deftest many-entities
|
||||||
|
(t/is (= (set entities)
|
||||||
|
(:entities
|
||||||
|
(p/pull-report
|
||||||
|
{:id (into
|
||||||
|
{}
|
||||||
|
(map #(vector
|
||||||
|
(second %)
|
||||||
|
(hash-map (first %) (second %))))
|
||||||
|
entities)
|
||||||
|
:all (vec entities)}
|
||||||
|
[{:all [:id]}])))))
|
||||||
112
test-resources/lib_tests/pyramid/query_test.cljc
Normal file
112
test-resources/lib_tests/pyramid/query_test.cljc
Normal file
|
|
@ -0,0 +1,112 @@
|
||||||
|
(ns pyramid.query-test
|
||||||
|
(:require
|
||||||
|
[pyramid.query :as p.q :refer [q]]
|
||||||
|
[clojure.test :as t]))
|
||||||
|
|
||||||
|
|
||||||
|
(def db {:person/id {"123" {:person/id "123"
|
||||||
|
:person/name "foo"
|
||||||
|
:person/best-friend [:person/id "789"]
|
||||||
|
:person/friends [[:person/id "456"]
|
||||||
|
[:person/id "789"]]}
|
||||||
|
"456" {:person/id "456"
|
||||||
|
:person/name "bar"
|
||||||
|
:person/friends [[:person/id "123"]
|
||||||
|
[:person/id "789"]]}
|
||||||
|
"789" {:person/id "789"
|
||||||
|
:person/name "baz"
|
||||||
|
:person/friends [[:person/id "123"]
|
||||||
|
[:person/id "456"]]}
|
||||||
|
"1011" {:person/id "1011"}}
|
||||||
|
:person {:bar "baz"}
|
||||||
|
:asdf "jkl"})
|
||||||
|
|
||||||
|
|
||||||
|
(t/deftest joins
|
||||||
|
(t/is (= '(["123"] ["456"] ["789"] ["1011"])
|
||||||
|
(q '[:find ?id
|
||||||
|
:where
|
||||||
|
[?e :person/id ?id]]
|
||||||
|
db)))
|
||||||
|
|
||||||
|
(t/is (= '(["123" "foo"] ["456" "bar"] ["789" "baz"])
|
||||||
|
(q '[:find ?id ?name
|
||||||
|
:where
|
||||||
|
[?e :person/id ?id]
|
||||||
|
[?e :person/name ?name]]
|
||||||
|
db)))
|
||||||
|
|
||||||
|
(t/is (= '(["123" "foo" [:person/id "789"]])
|
||||||
|
(q '[:find ?id ?name ?friend
|
||||||
|
:where
|
||||||
|
[?e :person/id ?id]
|
||||||
|
[?e :person/name ?name]
|
||||||
|
[?e :person/best-friend ?friend]]
|
||||||
|
db)))
|
||||||
|
|
||||||
|
(t/is (= '(["foo" "baz"])
|
||||||
|
(q '[:find ?name ?friend-name
|
||||||
|
:where
|
||||||
|
[?e :person/name ?name]
|
||||||
|
[?e :person/best-friend ?friend]
|
||||||
|
[?friend :person/name ?friend-name]]
|
||||||
|
db)))
|
||||||
|
|
||||||
|
(t/is (= '()
|
||||||
|
(q '[:find ?id
|
||||||
|
:where
|
||||||
|
[?e :person/name "asdf"]
|
||||||
|
[?e :person/id ?id]]
|
||||||
|
db))
|
||||||
|
"not found")
|
||||||
|
|
||||||
|
(t/is (= '(["123" "foo"])
|
||||||
|
(q '[:find ?id ?name
|
||||||
|
:in $ ?name
|
||||||
|
:where
|
||||||
|
[?e :person/name ?name]
|
||||||
|
[?e :person/id ?id]]
|
||||||
|
db
|
||||||
|
"foo"))
|
||||||
|
"join on :in")
|
||||||
|
|
||||||
|
(t/is (= '(["foo" "bar"]
|
||||||
|
["foo" "baz"]
|
||||||
|
["bar" "foo"]
|
||||||
|
["bar" "baz"]
|
||||||
|
["baz" "foo"]
|
||||||
|
["baz" "bar"])
|
||||||
|
(q '[:find ?name ?friend-name
|
||||||
|
:where
|
||||||
|
[?e :person/name ?name]
|
||||||
|
[?e :person/friends ^:many ?friend]
|
||||||
|
[?friend :person/name ?friend-name]]
|
||||||
|
db))
|
||||||
|
"multiple cardinality value")
|
||||||
|
|
||||||
|
(t/is (= '(["123" "foo"]
|
||||||
|
["456" "bar"])
|
||||||
|
(q '[:find ?id ?name
|
||||||
|
:in $ ^:many ?name
|
||||||
|
:where
|
||||||
|
[?e :person/name ?name]
|
||||||
|
[?e :person/id ?id]]
|
||||||
|
db
|
||||||
|
["foo" "bar"]))
|
||||||
|
"multi cardinality join on :in")
|
||||||
|
|
||||||
|
(t/is (= '(["foo" "foo"]
|
||||||
|
["foo" "bar"]
|
||||||
|
["foo" "baz"]
|
||||||
|
["bar" "foo"]
|
||||||
|
["bar" "bar"]
|
||||||
|
["bar" "baz"]
|
||||||
|
["baz" "foo"]
|
||||||
|
["baz" "bar"]
|
||||||
|
["baz" "baz"])
|
||||||
|
(q '[:find ?name1 ?name2
|
||||||
|
:where
|
||||||
|
[?e1 :person/name ?name1]
|
||||||
|
[?e2 :person/name ?name2]]
|
||||||
|
db))
|
||||||
|
"cross product"))
|
||||||
22
test-resources/lib_tests/swirrl/dogstatsd_test.clj
Normal file
22
test-resources/lib_tests/swirrl/dogstatsd_test.clj
Normal 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))))
|
||||||
Loading…
Reference in a new issue