Add a number of library tests from projects.md
Also add more docs around adding test libs and tweak add script
This commit is contained in:
parent
23699de359
commit
78a05139cb
41 changed files with 6870 additions and 45 deletions
12
deps.edn
12
deps.edn
|
|
@ -104,7 +104,17 @@
|
|||
table/table {:git/url "https://github.com/cldwalker/table", :sha "f6293c5f3dac1dd6f525a80fc80930f8ccdf16b7"}
|
||||
markdown-clj/markdown-clj {:mvn/version "1.10.8"}
|
||||
org.clojure/tools.namespace {:git/url "https://github.com/babashka/tools.namespace", :sha "a13b037215e21a2e71aa34b27e1dd52c801a2a7b"}
|
||||
medley/medley {:mvn/version "1.3.0"}}
|
||||
medley/medley {:mvn/version "1.3.0"}
|
||||
io.github.cognitect-labs/test-runner {:git/tag "v0.5.0", :git/sha "b3fd0d2"}
|
||||
borkdude/missing.test.assertions {:git/url "https://github.com/borkdude/missing.test.assertions", :sha "603cb01bee72fb17addacc53c34c85612684ad70"}
|
||||
dev.nubank/docopt {:mvn/version "0.6.1-fix7"}
|
||||
testdoc/testdoc {:mvn/version "1.4.1"}
|
||||
org.clojars.lispyclouds/contajners {:mvn/version "0.0.4"}
|
||||
borkdude/rewrite-edn {:mvn/version "0.1.0"}
|
||||
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"}}
|
||||
:classpath-overrides {org.clojure/clojure nil
|
||||
org.clojure/spec.alpha nil}}
|
||||
:clj-nvd
|
||||
|
|
|
|||
|
|
@ -85,15 +85,15 @@ Babashka runs tests of libraries that are compatible with it through
|
|||
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`.
|
||||
|
||||
If the library you want to add doesn't work with the script, you can manually do the following:
|
||||
If the library you want to add doesn't work automatically, you can manually do the following:
|
||||
|
||||
* Add an entry for the library in `deps.edn` under the `:lib-tests` alias.
|
||||
* Create a directory for the library in `test-resources/lib_tests/` and copy its tests to there.
|
||||
* Add an entry in `run_all_libtests.clj` to run the added test namespaces.
|
||||
* Add a manual lib entry using `add-libtest.clj` e.g. `script/add-libtest.clj http-kit/http-kit -m '{:test-namespaces [httpkit.client-test]}'`.
|
||||
* Run the tests `script/lib_tests/run_all_libtests NS1 NS2`
|
||||
|
||||
Note: If you have to modify a test to have it work with bb, add an inline
|
||||
comment with prefix "BB-TEST-PATCH:" explaining what you did.
|
||||
Note: If you have to modify any test file or configuration to have it work with
|
||||
bb, add an inline comment with prefix `BB-TEST-PATCH:` explaining what you did.
|
||||
|
||||
## Build
|
||||
|
||||
|
|
|
|||
|
|
@ -4,11 +4,14 @@ amperity/vault-clj,https://github.com/amperity/vault-clj
|
|||
babashka/babashka.curl,https://github.com/babashka/babashka.curl
|
||||
better-cond/better-cond,https://github.com/Engelberg/better-cond
|
||||
borkdude/deps,https://github.com/borkdude/deps.clj
|
||||
borkdude/missing.test.assertions,https://github.com/borkdude/missing.test.assertions
|
||||
borkdude/rewrite-edn,https://github.com/borkdude/rewrite-edn
|
||||
camel-snake-kebab/camel-snake-kebab,https://github.com/clj-commons/camel-snake-kebab
|
||||
circleci/bond,https://github.com/circleci/bond
|
||||
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.github.seancorfield/honeysql,https://github.com/seancorfield/honeysql
|
||||
com.grammarly/omniconf,https://github.com/grammarly/omniconf
|
||||
com.stuartsierra/component,https://github.com/stuartsierra/component
|
||||
|
|
@ -16,16 +19,24 @@ com.stuartsierra/dependency,https://github.com/stuartsierra/dependency
|
|||
comb/comb,https://github.com/weavejester/comb
|
||||
cprop/cprop,https://github.com/tolitius/cprop
|
||||
crispin/crispin,https://github.com/dunaj-project/crispin
|
||||
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
|
||||
environ/environ,https://github.com/weavejester/environ
|
||||
exoscale/coax,https://github.com/exoscale/coax
|
||||
expound/expound,https://github.com/bhb/expound
|
||||
failjure/failjure,https://github.com/adambard/failjure
|
||||
ffclj/ffclj,https://github.com/luissantos/ffclj
|
||||
gaka/gaka,https://github.com/cdaddr/gaka
|
||||
hato/hato,https://github.com/gnarroway/hato
|
||||
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
|
||||
io.aviso/pretty,https://github.com/AvisoNovate/pretty
|
||||
io.github.cognitect-labs/test-runner,https://github.com/cognitect-labs/test-runner
|
||||
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
|
||||
java-http-clj/java-http-clj,http://www.github.com/schmee/java-http-clj
|
||||
|
|
@ -40,6 +51,7 @@ org.babashka/spec.alpha,https://github.com/babashka/spec.alpha
|
|||
org.clj-commons/clj-http-lite,https://github.com/clj-commons/clj-http-lite
|
||||
org.clj-commons/digest,https://github.com/clj-commons/clj-digest
|
||||
org.clojars.askonomm/ruuter,https://github.com/askonomm/ruuter
|
||||
org.clojars.lispyclouds/contajners,https://github.com/lispyclouds/contajners
|
||||
org.clojure/core.match,https://github.com/clojure/core.match
|
||||
org.clojure/data.csv,https://github.com/clojure/data.csv
|
||||
org.clojure/data.generators,https://github.com/clojure/data.generators
|
||||
|
|
@ -49,10 +61,12 @@ org.clojure/math.combinatorics,https://github.com/clojure/math.combinatorics
|
|||
org.clojure/test.check,https://github.com/clojure/test.check
|
||||
org.clojure/tools.gitlibs,https://github.com/clojure/tools.gitlibs
|
||||
org.clojure/tools.namespace,https://github.com/babashka/tools.namespace
|
||||
progrock/progrock,https://github.com/weavejester/progrock
|
||||
reifyhealth/specmonstah,https://github.com/reifyhealth/specmonstah
|
||||
rewrite-clj/rewrite-clj,https://github.com/clj-commons/rewrite-clj
|
||||
rm-hull/jasentaa,https://github.com/rm-hull/jasentaa
|
||||
selmer/selmer,https://github.com/yogthos/Selmer
|
||||
slingshot/slingshot,https://github.com/scgilardi/slingshot
|
||||
table/table,https://github.com/cldwalker/table
|
||||
testdoc/testdoc,https://github.com/liquidz/testdoc
|
||||
version-clj/version-clj,https://github.com/xsc/version-clj
|
||||
|
|
|
|||
|
|
|
@ -83,13 +83,14 @@ The following libraries and projects are known to work with babashka.
|
|||
- [Babashka + scittle guestbook](#babashka--scittle-guestbook)
|
||||
- [bb htmx todo app](#bb-htmx-todo-app)
|
||||
|
||||
For more supported libraries, see [this test
|
||||
file](../test-resources/lib_tests/babashka/run_all_libtests.clj ). Also keep an eye
|
||||
on the [news](news.md) page for new projects, gists and other developments
|
||||
around babashka.
|
||||
Also keep an eye on the [news](news.md) page for new projects, gists and other
|
||||
developments around babashka.
|
||||
|
||||
## Libraries
|
||||
|
||||
For a full list of libraries, see [libraries.csv](./libraries.csv). To add a
|
||||
library, see [these instructions](./dev.md#tests-for-libraries).
|
||||
|
||||
### [tools.namespace](https://github.com/babashka/tools.namespace)
|
||||
|
||||
A fork of `tools.namespace`. This is used by other libraries and enables them to
|
||||
|
|
@ -111,12 +112,12 @@ instrumentation! Its readme also contains instructions on how to use
|
|||
|
||||
A fork of `tools.build`.
|
||||
|
||||
### [clj-http-lite](https://github.com/babashka/clj-http-lite)
|
||||
### [clj-http-lite](https://github.com/clj-commons/clj-http-lite)
|
||||
|
||||
A fork of a fork of `clj-http-lite`. Example:
|
||||
Example:
|
||||
|
||||
``` shell
|
||||
$ export BABASHKA_CLASSPATH="$(clojure -Sdeps '{:deps {clj-http-lite {:git/url "https://github.com/babashka/clj-http-lite" :sha "f44ebe45446f0f44f2b73761d102af3da6d0a13e"}}}' -Spath)"
|
||||
$ export BABASHKA_CLASSPATH="$(clojure -Sdeps '{:deps {org.clj-commons/clj-http-lite {:mvn/version "0.4.392"}}}' -Spath)"
|
||||
|
||||
$ bb "(require '[clj-http.lite.client :as client]) (:status (client/get \"https://www.clojure.org\"))"
|
||||
200
|
||||
|
|
@ -146,16 +147,10 @@ Ran 1 tests containing 0 assertions.
|
|||
|
||||
### [medley](https://github.com/weavejester/medley/)
|
||||
|
||||
Requires `bb` >= v0.0.71. Latest coordinates checked with with bb:
|
||||
|
||||
``` clojure
|
||||
{:git/url "https://github.com/weavejester/medley" :sha "a4e5fb5383f5c0d83cb2d005181a35b76d8a136d"}
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
``` shell
|
||||
$ export BABASHKA_CLASSPATH=$(clojure -Spath -Sdeps '{:deps {medley {:git/url "https://github.com/weavejester/medley" :sha "a4e5fb5383f5c0d83cb2d005181a35b76d8a136d"}}}')
|
||||
$ export BABASHKA_CLASSPATH=$(clojure -Spath -Sdeps '{:deps {medley/medley {:mvn/version "1.3.0"}}}')
|
||||
|
||||
$ bb -e "(require '[medley.core :as m]) (m/index-by :id [{:id 1} {:id 2}])"
|
||||
{1 {:id 1}, 2 {:id 2}}
|
||||
|
|
@ -202,16 +197,10 @@ export BABASHKA_CLASSPATH="$(clojure -Sdeps '{:deps {clojure-csv {:mvn/version "
|
|||
|
||||
### [regal](https://github.com/lambdaisland/regal)
|
||||
|
||||
Requires `bb` >= v0.0.71. Latest coordinates checked with with bb:
|
||||
|
||||
``` clojure
|
||||
{:git/url "https://github.com/lambdaisland/regal" :sha "d4e25e186f7b9705ebb3df6b21c90714d278efb7"}
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
``` shell
|
||||
$ export BABASHKA_CLASSPATH=$(clojure -Spath -Sdeps '{:deps {regal {:git/url "https://github.com/lambdaisland/regal" :sha "d4e25e186f7b9705ebb3df6b21c90714d278efb7"}}}')
|
||||
$ export BABASHKA_CLASSPATH=$(clojure -Spath -Sdeps '{:deps {lambdaisland/regal {:mvn/version "0.0.143"}}}')
|
||||
|
||||
$ bb -e "(require '[lambdaisland.regal :as regal]) (regal/regex [:* \"ab\"])"
|
||||
#"(?:\Qab\E)*"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
#!/usr/bin/env bb
|
||||
;; Adds a library to bb-tested-libs.edn to be tested given a library version and
|
||||
;; git repository. Optionally takes a --test to then test the added library.
|
||||
;; Adds a library to bb-tested-libs.edn and libraries.csv and optionally run its
|
||||
;; tests. There are two modes to this script - automatic (default) and manual.
|
||||
;; The script defaults to automatically copying tests as this normally works.
|
||||
;; There are several options to specify where the library is including
|
||||
;; --git-url, --dir and --test-directories. See --help for more. In manual mode,
|
||||
;; tests are manually added outside of the script and the script is run to add
|
||||
;; the library to library lists.
|
||||
|
||||
(ns add-libtest
|
||||
(:require [babashka.deps :as deps]
|
||||
|
|
@ -74,6 +79,7 @@
|
|||
(gl/procure git-url lib-name branch)
|
||||
(or (gl/procure git-url lib-name "master")
|
||||
(gl/procure git-url lib-name "main")))
|
||||
_ (println "Git clone is at" lib-dir)
|
||||
lib-root-dir (if directory (fs/file lib-dir directory) lib-dir)
|
||||
test-dirs (if test-directories
|
||||
(map #(when (fs/exists? (fs/file lib-root-dir %))
|
||||
|
|
@ -123,6 +129,9 @@
|
|||
namespaces))
|
||||
|
||||
(defn- fetch-artifact
|
||||
"Using the clojars api to get a library's git url doesn't always work. A
|
||||
possibly more reliable data source could be the scm urls in this POM feed -
|
||||
https://github.com/clojars/clojars-web/wiki/Data#useful-extracts-from-the-poms"
|
||||
[artifact]
|
||||
(let [url (str "https://clojars.org/api/artifacts/" artifact)
|
||||
_ (println "GET" url "...")
|
||||
|
|
@ -131,15 +140,6 @@
|
|||
(-> resp :body slurp edn/read-string)
|
||||
(error (str "Response failed and returned " (pr-str resp))))))
|
||||
|
||||
(defn- deps-to-lib-name-and-coordinate
|
||||
[deps-string]
|
||||
(let [deps-map (edn/read-string deps-string)
|
||||
_ (when (not= 1 (count deps-map))
|
||||
(error "Deps map must have one key"))
|
||||
lib-name (ffirst deps-map)
|
||||
lib-coordinate (deps-map lib-name)]
|
||||
[lib-name lib-coordinate]))
|
||||
|
||||
(defn- get-lib-map
|
||||
[deps-string options]
|
||||
;; if deps-string is artifact name
|
||||
|
|
@ -148,12 +148,13 @@
|
|||
{:lib-name (symbol deps-string)
|
||||
:lib-coordinate {:mvn/version (:latest_version artifact-edn)}
|
||||
:git-url (or (:git-url options) (:homepage artifact-edn))})
|
||||
(let [deps-map (edn/read-string deps-string)]
|
||||
(when (not= 1 (count deps-map))
|
||||
(error "Deps map must have one key"))
|
||||
(let [deps-map (edn/read-string deps-string)
|
||||
_ (when (or (not (map? deps-map)) (not= 1 (count deps-map)))
|
||||
(error "Deps map must have one key"))
|
||||
lib-coordinate (-> deps-map vals first)]
|
||||
{:lib-name (ffirst deps-map)
|
||||
:lib-coordinate (-> deps-map vals first)
|
||||
:git-url (:git-url options)})))
|
||||
:lib-coordinate lib-coordinate
|
||||
:git-url (or (:git/url lib-coordinate) (:git-url options))})))
|
||||
|
||||
(defn- write-lib-to-csv
|
||||
"Updates libraries.csv with latest bb-tested-libs.edn"
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
aero/aero {:git-sha "743e9bc495425b4a4a7c780f5e4b09f6680b4e7a", :git-url "http://github.com/juxt/aero", :test-namespaces (aero.core-test)}
|
||||
org.clojure/data.generators {:git-sha "bf65f99aa9dcabed7de7c09b74d71db208cf61ee", :git-url "https://github.com/clojure/data.generators", :test-namespaces (clojure.data.generators-test)}
|
||||
camel-snake-kebab/camel-snake-kebab {:git-sha "d072c7fd242ab0becd4bb265622ded415f2a4b68", :git-url "https://github.com/clj-commons/camel-snake-kebab", :test-namespaces (camel-snake-kebab.internals.string-separator-test camel-snake-kebab.extras-test camel-snake-kebab.core-test)}
|
||||
;; BB-TEST-PATCH: Removed cljs-test-opts.edn
|
||||
;; BB-TEST-PATCH: Deleted cljs-test-opts.edn
|
||||
henryw374/cljc.java-time {:git-sha "b9da12ea25e80a0e284a5bffd88ebcbf18fc3bf7", :git-url "https://github.com/henryw374/cljc.java-time", :test-namespaces (cljc.java-time-test)}
|
||||
org.babashka/spec.alpha {:git-sha "6c4aed643daaf55c6f898d4915275704db683aa2", :git-url "https://github.com/babashka/spec.alpha", :test-namespaces (clojure.test-clojure.instr clojure.test-clojure.spec)}
|
||||
;; BB-TEST-PATCH: Don't have 4 tests namespaces because they depend on
|
||||
|
|
@ -66,8 +66,31 @@
|
|||
;; TODO: failing tests in the following namespaces: vault.client.mock-test, vault.secrets.kvv1-test vault.secrets.kvv2-test
|
||||
amperity/vault-clj {:git-url "https://github.com/amperity/vault-clj", :test-namespaces [vault.lease-test vault.client.http-test], :manually-added true}
|
||||
orchestra/orchestra {:git-url "https://github.com/jeaye/orchestra", :test-namespaces (orchestra.make-fns orchestra.many-fns orchestra.expound-test orchestra.core-test orchestra.reload-test), :test-directories ("test/cljc" "test/clj"), :git-sha "81e5181f7b42e5e2763a2b37db17954f3be0314e"}
|
||||
;; BB-TEST-PATCH: Manually removed tasks.clj
|
||||
;; BB-TEST-PATCH: Deleted tasks.clj
|
||||
org.clj-commons/clj-http-lite {:git-url "https://github.com/clj-commons/clj-http-lite", :test-namespaces (clj-http.lite.test-runner clj-http.lite.client-test), :test-directories ("bb"), :git-sha "6b53000df55ac05c4ff8e5047a5323fc08a52e8b"}
|
||||
cprop/cprop {:git-url "https://github.com/tolitius/cprop", :test-namespaces [cprop.smoke-test], :manually-added true}
|
||||
org.clojure/data.zip {:git-url "https://github.com/clojure/data.zip", :test-namespaces [clojure.data.zip-test], :manually-added true}
|
||||
borkdude/deps {:git-url "https://github.com/borkdude/deps.clj", :test-namespaces [borkdude.deps.smoke-test], :manually-added true}}
|
||||
borkdude/deps {:git-url "https://github.com/borkdude/deps.clj", :test-namespaces [borkdude.deps.smoke-test], :manually-added true}
|
||||
io.github.cognitect-labs/test-runner {:git-url "https://github.com/cognitect-labs/test-runner", :test-namespaces (cognitect.test-runner.samples-test cognitect.test-runner.sample-property-test cognitect.test-runner-test), :git-sha "cc75980b43011773162b485f46f939dc5fba91e4"}
|
||||
borkdude/missing.test.assertions {:git-url "https://github.com/borkdude/missing.test.assertions", :test-namespaces (missing.test.assertions-test missing.test.old-methods), :git-sha "603cb01bee72fb17addacc53c34c85612684ad70"}
|
||||
;; No tests to run
|
||||
io.github.technomancy/limit-break {:git-url "https://github.com/technomancy/limit-break", :test-namespaces [], :manually-added true}
|
||||
dev.nubank/docopt {:git-url "https://github.com/nubank/docopt.clj", :test-namespaces (docopt.core-test), :git-sha "2794195a7288002e8d8a44f7bc37180c9cca8971"}
|
||||
;; BB-TEST-PATCH: Deleted unused resources/
|
||||
testdoc/testdoc {:git-url "https://github.com/liquidz/testdoc", :test-namespaces (testdoc.style.repl-test testdoc.style.code-first-test testdoc.core-test), :git-sha "6b995ef25f3cc6450a1ce30f72baed371476f6eb"}
|
||||
org.clojars.lispyclouds/contajners {:git-url "https://github.com/lispyclouds/contajners", :test-namespaces (contajners.core-test contajners.impl-test), :git-sha "d163637ff36d79995516d6705da1e9afc7b44764"}
|
||||
;; Don't run tests b/c they depend on `psql`
|
||||
douglass/clj-psql {:git-url "https://github.com/DarinDouglass/clj-psql", :test-namespaces [], :manually-added true}
|
||||
;; Don't run tests b/c they depend on `ffmpeg`
|
||||
ffclj/ffclj {:git-url "https://github.com/luissantos/ffclj", :test-namespaces [], :manually-added true}
|
||||
;; BB-TEST-PATCH: Can't load deps for tests - expound.alpha-test, expound.spell-spec-test, expound.paths-test. Skip expound.printer-test as most tests fail
|
||||
;; BB-TEST-PATCH: Deleted cljs_test.cljs and *.txt
|
||||
expound/expound {:git-url "https://github.com/bhb/expound", :test-namespaces (expound.specs-test expound.print-length-test expound.test-utils expound.spec-gen expound.problems-test), :git-sha "589a7f69323dc0423197b346c75808e48e771427"}
|
||||
;; BB-TEST-PATCH: Removed borkdude.rewrite-edn-test because it fails
|
||||
borkdude/rewrite-edn {:git-url "https://github.com/borkdude/rewrite-edn", :test-namespaces [], :branch "63f09048a3ebbd48f86fa9626076e7e540cfb7ee", :git-sha "63f09048a3ebbd48f86fa9626076e7e540cfb7ee"}
|
||||
clojure-term-colors/clojure-term-colors {:git-url "https://github.com/trhura/clojure-term-colors", :test-namespaces (clojure.term.colors-test), :git-sha "71620a5e121d51afe28c50c0aa14ceb4cbff7981"}
|
||||
;; BB-TEST-PATCH: Removed io.aviso.exception-test because it can't load ns with clojure.lang.Compiler.
|
||||
;; BB-TEST-PATCH: Deleted demo*.clj
|
||||
io.aviso/pretty {:git-url "https://github.com/AvisoNovate/pretty", :test-namespaces (io.aviso.binary-test), :git-sha "155926f991f94addaf6f5c8621748924ab144988"}
|
||||
progrock/progrock {:git-url "https://github.com/weavejester/progrock", :test-namespaces (progrock.core-test), :git-sha "9c277a3244c52bfde19c21add327d6e20b94fdf5"}
|
||||
djblue/portal {:git-url "https://github.com/djblue/portal", :test-namespaces (portal.jvm-test portal.test-runner portal.runtime.cson-test portal.runtime.fs-test portal.e2e portal.bench), :git-sha "64e4624bcf3bee2dd47e3d8e47982c709738eb11"}}
|
||||
|
|
|
|||
133
test-resources/lib_tests/borkdude/rewrite_edn_test.cljc
Normal file
133
test-resources/lib_tests/borkdude/rewrite_edn_test.cljc
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
(ns borkdude.rewrite-edn-test
|
||||
(:require [borkdude.rewrite-edn :as r]
|
||||
[clojure.test :as t :refer [deftest testing is]]))
|
||||
|
||||
(deftest assoc-test
|
||||
(testing "Base case"
|
||||
(is (= "{:a 1}"
|
||||
(str (r/assoc
|
||||
(r/parse-string "{}")
|
||||
:a 1)))))
|
||||
(testing "When there's only one existing, keys are added on a new line"
|
||||
(is (= "
|
||||
{:a 1
|
||||
:b 1}"
|
||||
(str (r/assoc
|
||||
(r/parse-string "
|
||||
{:a 1}")
|
||||
:b 1)))))
|
||||
(testing "Unless there are already keys on the same line"
|
||||
(is (= "{:a 1 :b 2 :c 3}"
|
||||
(str (r/assoc
|
||||
(r/parse-string "{:a 1 :b 2}")
|
||||
:c 3)))))
|
||||
(testing "when map is already multi-line, new keys are added on new line"
|
||||
(is (= "
|
||||
{:a 1
|
||||
:b 2}
|
||||
;; this is a cool map"
|
||||
(str (r/assoc
|
||||
(r/parse-string "
|
||||
{:a 1}
|
||||
;; this is a cool map")
|
||||
:b 2)))))
|
||||
(testing "Updating existing val"
|
||||
(is (= "{:a 2}"
|
||||
(str (r/assoc
|
||||
(r/parse-string "{:a 1}")
|
||||
:a 2)))))
|
||||
(testing "Something between key and val"
|
||||
(is (= "{:a #_:something 2}"
|
||||
(str (r/assoc
|
||||
(r/parse-string "{:a #_:something 1}")
|
||||
:a 2)))))
|
||||
(testing "Comment at the end"
|
||||
(is (= "{:a 2} ;; this is a cool map"
|
||||
(str (r/assoc
|
||||
(r/parse-string "{:a 1} ;; this is a cool map")
|
||||
:a 2)))))
|
||||
(testing "Vector index assoc"
|
||||
(is (= "[9 8 99 7] ;; this is a cool vector"
|
||||
(str (r/assoc
|
||||
(r/parse-string "[9 8 3 7] ;; this is a cool vector")
|
||||
2 99)))))
|
||||
(testing "Vector last index assoc"
|
||||
(is (= "[9 8 3 99] ;; this is a cool vector"
|
||||
(str (r/assoc
|
||||
(r/parse-string "[9 8 3 7] ;; this is a cool vector")
|
||||
3 99)))))
|
||||
(testing "Vector assoc out of bounds"
|
||||
(is (try
|
||||
(r/assoc (r/parse-string "[9 8 3 7] ;; this is a cool vector") 9 99)
|
||||
false
|
||||
(catch java.lang.IndexOutOfBoundsException _ true))))
|
||||
(testing "Vector assoc out of bounds with ignored"
|
||||
(is (try
|
||||
(r/assoc (r/parse-string "[9 8 3 #_99 #_213 7] ;; this is a cool vector") 4 99)
|
||||
false
|
||||
(catch java.lang.IndexOutOfBoundsException _ true)))))
|
||||
|
||||
(deftest update-test
|
||||
(is (= "{:a #_:foo 2}"
|
||||
(str (r/update
|
||||
(r/parse-string "{:a #_:foo 1}")
|
||||
:a (fn [node]
|
||||
(inc (r/sexpr node))))))))
|
||||
|
||||
(defn qualify-sym-node [sym-node]
|
||||
(let [sym (r/sexpr sym-node)]
|
||||
(if (or (not (symbol? sym))
|
||||
(qualified-symbol? sym))
|
||||
sym-node
|
||||
(symbol (str sym) (str sym)))))
|
||||
|
||||
(deftest map-keys-test
|
||||
(is (= "
|
||||
{foo/foo 1
|
||||
bar/bar 2}"
|
||||
(str (r/map-keys qualify-sym-node
|
||||
(r/parse-string "
|
||||
{foo 1
|
||||
bar 2}"))))))
|
||||
|
||||
(deftest update-deps-test
|
||||
(is (= "{:deps {foo/foo {:mvn/version \"0.1.0\"}}}"
|
||||
(str (r/update (r/parse-string "{:deps {foo {:mvn/version \"0.1.0\"}}}")
|
||||
:deps
|
||||
(fn [deps-map-node]
|
||||
(r/map-keys qualify-sym-node deps-map-node)))))))
|
||||
|
||||
(deftest assoc-in-test
|
||||
(is (= "{:a {:b {:c 2}}}"
|
||||
(str (r/assoc-in (r/parse-string "{}")
|
||||
[:a :b :c] 2))))
|
||||
(is (= "{:a {:b {:c 2}}}"
|
||||
(str (r/assoc-in (r/parse-string "nil")
|
||||
[:a :b :c] 2))))
|
||||
(is (= "{:deps {foo/foo {:mvn/version \"0.2.0\"}}}"
|
||||
(str (r/assoc-in (r/parse-string "{:deps {foo/foo {:mvn/version \"0.1.0\"}}}")
|
||||
[:deps 'foo/foo :mvn/version]
|
||||
"0.2.0"))))
|
||||
(is (= "{:a 1 :b {:c 1}}"
|
||||
(str (r/assoc-in (r/parse-string "{:a 1}") [:b :c] 1)))))
|
||||
|
||||
(deftest update-in-test
|
||||
(is (= "{:deps {foo/foo {:mvn/version \"0.2.0\"}}}"
|
||||
(str (r/update-in (r/parse-string "{:deps {foo/foo {:mvn/version \"0.1.0\"}}}")
|
||||
[:deps 'foo/foo]
|
||||
#(r/assoc % :mvn/version "0.2.0")))))
|
||||
(is (= "{:a {:b {:c 1}}}"
|
||||
(str (r/update-in (r/parse-string "{}")
|
||||
[:a :b :c]
|
||||
(comp (fnil inc 0) r/sexpr)))))
|
||||
(is (= "{:a {:b {:c 1}}}"
|
||||
(str (r/update-in (r/parse-string "nil")
|
||||
[:a :b :c]
|
||||
(comp (fnil inc 0) r/sexpr))))))
|
||||
|
||||
(deftest dissoc-test
|
||||
(is (= "{}" (str (r/dissoc (r/parse-string "{:a 1}") :a))))
|
||||
(is (= "{:a 1}" (str (r/dissoc (r/parse-string "{:a 1 \n\n:b 2}") :b))))
|
||||
(is (= "{:a 1\n:c 3}" (str (r/dissoc (r/parse-string "{:a 1\n:b 2\n:c 3}") :b))))
|
||||
(is (= "{:deps {foo/bar {}}}" (str (r/update (r/parse-string "{:deps {foo/bar {} foo/baz {}}}")
|
||||
:deps #(r/dissoc % 'foo/baz))))))
|
||||
29
test-resources/lib_tests/clojure/term/colors_test.clj
Normal file
29
test-resources/lib_tests/clojure/term/colors_test.clj
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
(ns clojure.term.colors-test
|
||||
(:require [clojure.test :refer :all]
|
||||
[clojure.term.colors :refer :all]))
|
||||
|
||||
(defn get-fn
|
||||
"get function from symbol in clojure.term.colors package"
|
||||
[fname]
|
||||
(ns-resolve (the-ns 'clojure.term.colors)
|
||||
(-> fname name symbol)))
|
||||
|
||||
(defn test-colors-from-map
|
||||
"test print colors from a color map"
|
||||
[colormap & more]
|
||||
(eval
|
||||
`(do ~@(map (fn [[color _]]
|
||||
`(println ((get-fn ~color)
|
||||
(name ~color) (str ~@more))))
|
||||
colormap))))
|
||||
|
||||
(deftest color-test
|
||||
(testing "Testing colors."
|
||||
(test-colors-from-map *colors* " foreground.")
|
||||
(test-colors-from-map *highlights* " background.")
|
||||
(test-colors-from-map *attributes* " attributes."))
|
||||
|
||||
(testing "Testing disable colors."
|
||||
(binding [*disable-colors* true]
|
||||
(println \newline "When disabled-colors is set ...")
|
||||
(test-colors-from-map *colors* " foreground."))))
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
(ns cognitect.test-runner.sample-property-test
|
||||
(:require [clojure.test.check :as tc]
|
||||
[clojure.test.check.generators :as gen]
|
||||
[clojure.test.check.properties :as prop]
|
||||
[clojure.test.check.clojure-test :refer [defspec]]))
|
||||
|
||||
(defspec first-element-is-min-after-sorting 100
|
||||
(prop/for-all [v (gen/not-empty (gen/vector gen/int))]
|
||||
(= (apply min v)
|
||||
(first (sort v)))))
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
(ns cognitect.test-runner.samples-test
|
||||
(:require [clojure.test :as t :refer [deftest is testing]]))
|
||||
|
||||
(deftest math-works
|
||||
(testing "basic addition and subtraction"
|
||||
(is (= 42 (+ 40 2)))
|
||||
(is (= 42 (- 44 2)))))
|
||||
|
||||
(deftest ^:integration test-i
|
||||
(is (= 1 1)))
|
||||
|
||||
|
||||
|
||||
|
||||
23
test-resources/lib_tests/cognitect/test_runner_test.clj
Normal file
23
test-resources/lib_tests/cognitect/test_runner_test.clj
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
(ns cognitect.test-runner-test
|
||||
(:require
|
||||
[clojure.test :refer :all]
|
||||
[cognitect.test-runner :as tr]))
|
||||
|
||||
(deftest ns-filters
|
||||
(are [ns-names ns-regexes available selected]
|
||||
(= selected (filter (#'tr/ns-filter {:namespace ns-names :namespace-regex ns-regexes}) available))
|
||||
|
||||
;; default settings (no -n / -r, use default for -r)
|
||||
nil nil nil []
|
||||
nil nil '[ns1-test ns2-test] '[ns1-test ns2-test]
|
||||
nil nil '[ns1-test ns2-test ns3 ns4 ns5] '[ns1-test ns2-test]
|
||||
|
||||
;; specific namespaces
|
||||
'#{ns3} nil '[ns1-test ns2-test] '[]
|
||||
'#{ns3 ns4} nil '[ns1-test ns2-test ns3 ns4 ns5] '[ns3 ns4]
|
||||
|
||||
;; regexes
|
||||
nil #{#"ns1.*" #"ns3"} '[ns1-test ns2-test ns3 ns4] '[ns1-test ns3]
|
||||
|
||||
;; both
|
||||
'#{ns3} '#{#"ns1.*"} '[ns1-test ns2-test ns3 ns4] '[ns1-test ns3]))
|
||||
22
test-resources/lib_tests/contajners/core_test.clj
Normal file
22
test-resources/lib_tests/contajners/core_test.clj
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
(ns contajners.core-test
|
||||
(:require [clojure.test :as t]
|
||||
[contajners.core :as c]))
|
||||
|
||||
(t/deftest docker-tests
|
||||
(let [image "busybox:musl"
|
||||
client (c/client {:engine :docker
|
||||
:version "v1.41"
|
||||
:category :images
|
||||
:conn {:uri "unix:///var/run/docker.sock"}})]
|
||||
(t/testing "pull an image"
|
||||
(c/invoke client
|
||||
{:op :ImageCreate
|
||||
:params {:fromImage image}})
|
||||
(let [images (c/invoke client {:op :ImageList})]
|
||||
(t/is (contains? (->> images
|
||||
(mapcat :RepoTags)
|
||||
(into #{}))
|
||||
image)))
|
||||
(c/invoke client
|
||||
{:op :ImageDelete
|
||||
:params {:name image}}))))
|
||||
45
test-resources/lib_tests/contajners/impl_test.clj
Normal file
45
test-resources/lib_tests/contajners/impl_test.clj
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
(ns contajners.impl-test
|
||||
(:require
|
||||
[clojure.test :as t]
|
||||
[contajners.impl :as impl]))
|
||||
|
||||
(t/deftest meta-cleanup
|
||||
(t/testing "remove internal namespace"
|
||||
(t/is (= [:foo]
|
||||
(impl/remove-internal-meta [:contajners/foo :foo])))))
|
||||
|
||||
(t/deftest param-gathering
|
||||
(t/testing "gathering params as header query and path"
|
||||
(t/is (= {:header {:a 1 :b 2}
|
||||
:query {:c 3 :d 4}
|
||||
:path {:e 5 :f 6}}
|
||||
(reduce (partial impl/gather-params {:a 1 :b 2 :c 3 :d 4 :e 5 :f 6})
|
||||
{}
|
||||
[{:name "a" :in :header}
|
||||
{:name "b" :in :header}
|
||||
{:name "c" :in :query}
|
||||
{:name "d" :in :query}
|
||||
{:name "e" :in :path}
|
||||
{:name "f" :in :path}])))))
|
||||
|
||||
(t/deftest body-serialization
|
||||
(t/testing "body serialization when a map"
|
||||
(t/is (= {:headers {"content-type" "application/json"}
|
||||
:body "{\"a\":42}"}
|
||||
(impl/maybe-serialize-body {:body {:a 42}}))))
|
||||
(t/testing "body serialization when not a map"
|
||||
(t/is (= {:body "yes"}
|
||||
(impl/maybe-serialize-body {:body "yes"})))))
|
||||
|
||||
(t/deftest path-interpolation
|
||||
(t/testing "path interpolation"
|
||||
(t/is (= "/a/{w}/b/41/42"
|
||||
(impl/interpolate-path "/a/{w}/b/{x}/{y}" {:x 41 :y 42 :z 43})))))
|
||||
|
||||
(t/deftest json-parsing
|
||||
(t/testing "successful json parsing"
|
||||
(t/is (= {:a 42}
|
||||
(impl/try-json-parse "{\"a\":42}"))))
|
||||
(t/testing "failed json parsing"
|
||||
(t/is (= "yes"
|
||||
(impl/try-json-parse "yes")))))
|
||||
88
test-resources/lib_tests/docopt/core_test.clj
Normal file
88
test-resources/lib_tests/docopt/core_test.clj
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
(ns docopt.core-test
|
||||
(:require [cheshire.core :as json]
|
||||
[clojure.string :as s]
|
||||
[clojure.test :refer :all]
|
||||
[docopt.core :as d]
|
||||
[docopt.match :as m]))
|
||||
|
||||
(def doc-block-regex
|
||||
(let [doc-begin "r\\\"{3}"
|
||||
doc-body "((?:\\\"{0,2}[^\\\"]+)*)"
|
||||
separator "\\\"{3}\n+"
|
||||
tests "((?:[^r]|r(?!\\\"{3}))*)"]
|
||||
(re-pattern (str doc-begin doc-body separator tests))))
|
||||
|
||||
(def test-block-regex
|
||||
(let [input-begin "(?:\\A|\\n+)\\s*\\$\\s*prog"
|
||||
input-body "(.*)"
|
||||
separator "\\n"
|
||||
tests "((?:.+\\n)*)"]
|
||||
(re-pattern (str input-begin input-body separator tests))))
|
||||
|
||||
(defn load-test-cases
|
||||
"Loads language-agnostic docopt tests from file (such as testcases.docopt)."
|
||||
[path]
|
||||
(into [] (mapcat (fn [[_ doc tests]]
|
||||
(map (fn [[_ args result]]
|
||||
[doc (into [] (filter seq (s/split (or args "") #"\s+"))) (json/parse-string result)])
|
||||
(re-seq test-block-regex tests)))
|
||||
(re-seq doc-block-regex (s/replace (slurp path) #"#.*" "")))))
|
||||
|
||||
(defn test-case-error-report
|
||||
"Returns a report of all failed test cases"
|
||||
[doc in out]
|
||||
(let [docinfo (try (d/parse doc)
|
||||
(catch Exception e (.getMessage e)))]
|
||||
(if (string? docinfo)
|
||||
(str "\n" (s/trim-newline doc) "\n" docinfo)
|
||||
(let [result (or (m/match-argv docinfo in) "user-error")]
|
||||
(when (not= result out)
|
||||
(str "\n" (s/trim-newline doc)
|
||||
"\n$ prog " (s/join " " in)
|
||||
"\nexpected: " (json/generate-string out)
|
||||
"\nobtained: " (json/generate-string result) "\n\n"))))))
|
||||
|
||||
(defn valid?
|
||||
"Validates all test cases found in the file named 'test-cases-file-name'."
|
||||
[test-cases-file-name]
|
||||
(let [test-cases (load-test-cases test-cases-file-name)]
|
||||
(when-let [eseq (seq (remove nil? (map (partial apply test-case-error-report) test-cases)))]
|
||||
(println "Failed" (count eseq) "/" (count test-cases) "tests loaded from '" test-cases-file-name "'.\n")
|
||||
(throw (Exception. (apply str eseq))))
|
||||
(println "Successfully passed" (count test-cases) "tests loaded from '" test-cases-file-name "'.\n")
|
||||
true))
|
||||
|
||||
(deftest docopt-test
|
||||
(testing "2-arity version"
|
||||
(is (= {"<foo>" "a"}
|
||||
(d/docopt "usage: prog <foo>" ["a"]))))
|
||||
|
||||
(testing "3-arity version"
|
||||
(is (= "a"
|
||||
(d/docopt "usage: prog <foo>" ["a"] #(get % "<foo>")))))
|
||||
|
||||
(testing "4-arity version"
|
||||
(is (= "usage: prog <foo>"
|
||||
(d/docopt "usage: prog <foo>" [] identity identity))))
|
||||
|
||||
;; Adding this test here since it seems testcases file doesn't support quoted args
|
||||
(testing "should parse quoted args correctly"
|
||||
(is (= {"-f" "a b"}
|
||||
(d/docopt "usage: prog [options]\noptions: -f <foo>" ["-f" "a b"])))
|
||||
(is (= {"--foo" "a\nb"}
|
||||
(d/docopt "usage: prog [options]\noptions: --foo <foo>" ["--foo" "a\nb"])))
|
||||
(is (= {"<foo>" "a b c "}
|
||||
(d/docopt "usage: prog <foo>" ["a b c "])))
|
||||
(is (= {"<foo>" "a\tb\nc"}
|
||||
(d/docopt "usage: prog <foo>" ["a\tb\nc"])))
|
||||
(binding [docopt.match/*sep-table* {\ "FOO"
|
||||
\newline "BAR"
|
||||
\tab "QUX"
|
||||
\backspace "QUZ"}]
|
||||
(is (= {"<foo>" "a b\nc\td\b"}
|
||||
(d/docopt "usage: prog <foo>" ["aFOObBARcQUXdQUZ"]))))))
|
||||
|
||||
(deftest language-agnostic-test
|
||||
(is (valid? "https://raw.github.com/docopt/docopt/511d1c57b59cd2ed663a9f9e181b5160ce97e728/testcases.docopt"))
|
||||
;; BB-TEST-PATCH: Modified test path
|
||||
(is (valid? "test-resources/lib_tests/docopt/extra_testcases.docopt")))
|
||||
57
test-resources/lib_tests/docopt/extra_testcases.docopt
Normal file
57
test-resources/lib_tests/docopt/extra_testcases.docopt
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
# Should output the same things as docopt/docopt for language agnostic tests
|
||||
|
||||
# Testing `--`
|
||||
|
||||
r"""Usage: prog foo -- <extra-opts>...
|
||||
|
||||
"""
|
||||
|
||||
$ prog foo
|
||||
"user-error"
|
||||
|
||||
$ prog foo -- --bar
|
||||
{"--":true, "<extra-opts>": ["--bar"], "foo":true}
|
||||
|
||||
r"""Usage: prog foo [--] <extra-opts>...
|
||||
|
||||
"""
|
||||
|
||||
$ prog foo
|
||||
"user-error"
|
||||
# Wrong, should be
|
||||
# {"foo": true, "--": false, "<extra-opts>": []}
|
||||
|
||||
$ prog foo -- --bar
|
||||
{"foo": true, "--": true, "<extra-opts>": ["--bar"]}
|
||||
|
||||
r"""Complex command
|
||||
|
||||
Usage:
|
||||
prog [options] <param-x> <param-y> -- <extra>...
|
||||
prog [options] <param-a> <param-b> <param-c> <param-d> -- <extra>...
|
||||
prog [options] <param-x> <param-y>
|
||||
prog [options] <param-a> <param-b> <param-c> <param-d>
|
||||
|
||||
Options:
|
||||
-f --foo Foo
|
||||
--bar <bar> Bar
|
||||
|
||||
"""
|
||||
|
||||
$ prog x y --foo
|
||||
{"--":false,"--bar":null,"--foo":true,"<extra>":[],"<param-a>":null,"<param-b>":null,"<param-c>":null,"<param-d>":null,"<param-x>":"x","<param-y>":"y"}
|
||||
|
||||
$ prog a b c d
|
||||
{"--":false,"--bar":null,"--foo":false,"<extra>":[],"<param-a>":"a","<param-b>":"b","<param-c>":"c","<param-d>":"d","<param-x>":null,"<param-y>":null}
|
||||
|
||||
$ prog a b c d --foo --bar bar
|
||||
{"--":false,"--bar":"bar","--foo":true,"<extra>":[],"<param-a>":"a","<param-b>":"b","<param-c>":"c","<param-d>":"d","<param-x>":null,"<param-y>":null}
|
||||
|
||||
$ prog x y --bar bar -- extra
|
||||
{"--bar": "bar", "--foo": false, "<param-x>": "x", "<param-y>": "y", "--": true, "<extra>": ["extra"], "<param-a>": null, "<param-b>": null, "<param-c>": null, "<param-d>": null}
|
||||
|
||||
$ prog a b c d --foo --bar bar -- extra
|
||||
{"--foo": true, "--bar": "bar", "<param-x>": null, "<param-y>": null, "--": true, "<extra>": ["extra"], "<param-a>": "a", "<param-b>": "b", "<param-c>": "c", "<param-d>": "d"}
|
||||
|
||||
$ prog x y -- e1 e2 e3 e4
|
||||
{"--bar": null, "--foo": false, "<param-x>": "x", "<param-y>": "y", "--": true, "<extra>": ["e1", "e2", "e3", "e4"], "<param-a>": null, "<param-b>": null, "<param-c>": null, "<param-d>": null}
|
||||
4350
test-resources/lib_tests/expound/alpha_test.cljc
Normal file
4350
test-resources/lib_tests/expound/alpha_test.cljc
Normal file
File diff suppressed because it is too large
Load diff
39
test-resources/lib_tests/expound/paths_test.cljc
Normal file
39
test-resources/lib_tests/expound/paths_test.cljc
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
(ns expound.paths-test
|
||||
(:require [clojure.test :as ct :refer [is deftest use-fixtures]]
|
||||
[clojure.test.check.generators :as gen]
|
||||
[com.gfredericks.test.chuck.clojure-test :refer [checking]]
|
||||
[expound.paths :as paths]
|
||||
[expound.test-utils :as test-utils]
|
||||
[com.gfredericks.test.chuck :as chuck]))
|
||||
|
||||
(def num-tests 100)
|
||||
|
||||
(use-fixtures :once
|
||||
test-utils/check-spec-assertions
|
||||
test-utils/instrument-all)
|
||||
|
||||
(deftest compare-paths-test
|
||||
(checking
|
||||
"path to a key comes before a path to a value"
|
||||
10
|
||||
[k gen/simple-type-printable]
|
||||
(is (= -1 (paths/compare-paths [(paths/->KeyPathSegment k)] [k])))
|
||||
(is (= 1 (paths/compare-paths [k] [(paths/->KeyPathSegment k)])))))
|
||||
|
||||
(defn nth-value [form i]
|
||||
(let [seq (remove map-entry? (tree-seq coll? seq form))]
|
||||
(nth seq (mod i (count seq)))))
|
||||
|
||||
(deftest paths-to-value-test
|
||||
(checking
|
||||
"value-in is inverse of paths-to-value"
|
||||
(chuck/times num-tests)
|
||||
[form test-utils/any-printable-wo-nan
|
||||
i gen/nat
|
||||
:let [x (nth-value form i)
|
||||
paths (paths/paths-to-value form x [] [])]]
|
||||
(is (seq paths))
|
||||
(doseq [path paths]
|
||||
(is (= x
|
||||
(paths/value-in form
|
||||
path))))))
|
||||
23
test-resources/lib_tests/expound/print_length_test.cljc
Normal file
23
test-resources/lib_tests/expound/print_length_test.cljc
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
(ns expound.print-length-test
|
||||
(:require [clojure.test :as ct :refer [is deftest testing]]
|
||||
[clojure.spec.alpha :as s]
|
||||
[expound.alpha]
|
||||
[clojure.string :as string]))
|
||||
|
||||
(def the-value (range 10))
|
||||
;; Fails on the last element of the range
|
||||
(def the-spec (s/coll-of #(< % 9)))
|
||||
(def the-explanation (s/explain-data the-spec the-value))
|
||||
|
||||
(deftest print-length-test
|
||||
(testing "Expound works even in face of a low `*print-length*` and `*print-level*`, without throwing exceptions.
|
||||
See https://github.com/bhb/expound/issues/217"
|
||||
(doseq [length [1 5 100 *print-length*]
|
||||
level [1 5 100 *print-level*]
|
||||
;; Note that the `is` resides outside of the `binding`. Else test output itself can be affected.
|
||||
:let [v (binding [*print-length* length
|
||||
*print-level* level]
|
||||
(with-out-str
|
||||
(expound.alpha/printer the-explanation)))]]
|
||||
;; Don't make a particularly specific test assertion, since a limited print-length isn't necessarily realistic/usual:
|
||||
(is (not (string/blank? v))))))
|
||||
428
test-resources/lib_tests/expound/printer_test.cljc
Normal file
428
test-resources/lib_tests/expound/printer_test.cljc
Normal file
|
|
@ -0,0 +1,428 @@
|
|||
(ns expound.printer-test
|
||||
(:require [clojure.spec.alpha :as s]
|
||||
[clojure.test :as ct :refer [is deftest use-fixtures testing]]
|
||||
[expound.printer :as printer]
|
||||
[clojure.string :as string]
|
||||
[com.gfredericks.test.chuck.clojure-test :refer [checking]]
|
||||
[expound.test-utils :as test-utils :refer [contains-nan?]]
|
||||
[expound.spec-gen :as sg]
|
||||
[expound.problems :as problems]))
|
||||
|
||||
(def num-tests 5)
|
||||
|
||||
(use-fixtures :once
|
||||
test-utils/check-spec-assertions
|
||||
test-utils/instrument-all)
|
||||
|
||||
(defn example-fn [])
|
||||
(defn get-args [& args] args)
|
||||
|
||||
(deftest pprint-fn
|
||||
(is (= "string?"
|
||||
(printer/pprint-fn (::s/spec (s/explain-data string? 1)))))
|
||||
(is (= "expound.printer-test/example-fn"
|
||||
(printer/pprint-fn example-fn)))
|
||||
(is (= "<anonymous function>"
|
||||
(printer/pprint-fn #(inc (inc %)))))
|
||||
(is (= "<anonymous function>"
|
||||
(printer/pprint-fn (constantly true))))
|
||||
(is (= "<anonymous function>"
|
||||
(printer/pprint-fn (comp vec str))))
|
||||
(is (= "expound.test-utils/instrument-all"
|
||||
(printer/pprint-fn test-utils/instrument-all)))
|
||||
(is (= "expound.test-utils/contains-nan?"
|
||||
(printer/pprint-fn contains-nan?))))
|
||||
|
||||
(s/def :print-spec-keys/field1 string?)
|
||||
(s/def :print-spec-keys/field2 (s/coll-of :print-spec-keys/field1))
|
||||
(s/def :print-spec-keys/field3 int?)
|
||||
(s/def :print-spec-keys/field4 string?)
|
||||
(s/def :print-spec-keys/field5 string?)
|
||||
(s/def :print-spec-keys/key-spec (s/keys
|
||||
:req [:print-spec-keys/field1]
|
||||
:req-un [:print-spec-keys/field2]))
|
||||
(s/def :print-spec-keys/key-spec2 (s/keys
|
||||
:req-un [(and
|
||||
:print-spec-keys/field1
|
||||
(or
|
||||
:print-spec-keys/field2
|
||||
:print-spec-keys/field3))]))
|
||||
(s/def :print-spec-keys/key-spec3 (s/keys
|
||||
:req-un [:print-spec-keys/field1
|
||||
:print-spec-keys/field4
|
||||
:print-spec-keys/field5]))
|
||||
(s/def :print-spec-keys/set-spec (s/coll-of :print-spec-keys/field1
|
||||
:kind set?))
|
||||
(s/def :print-spec-keys/vector-spec (s/coll-of :print-spec-keys/field1
|
||||
:kind vector?))
|
||||
(s/def :print-spec-keys/key-spec4 (s/keys
|
||||
:req-un [:print-spec-keys/set-spec
|
||||
:print-spec-keys/vector-spec
|
||||
:print-spec-keys/key-spec3]))
|
||||
|
||||
(defn copy-key [m k1 k2]
|
||||
(assoc m k2 (get m k1)))
|
||||
|
||||
(deftest print-spec-keys*
|
||||
(is (=
|
||||
[{"key" :field2, "spec" "(coll-of :print-spec-keys/field1)"}
|
||||
{"key" :print-spec-keys/field1, "spec" "string?"}]
|
||||
(printer/print-spec-keys*
|
||||
(map #(copy-key % :via :expound/via)
|
||||
(::s/problems
|
||||
(s/explain-data
|
||||
:print-spec-keys/key-spec
|
||||
{}))))))
|
||||
(is (nil?
|
||||
(printer/print-spec-keys*
|
||||
(map #(copy-key % :via :expound/via)
|
||||
(::s/problems
|
||||
(s/explain-data
|
||||
(s/keys
|
||||
:req [:print-spec-keys/field1]
|
||||
:req-un [:print-spec-keys/field2])
|
||||
{}))))))
|
||||
|
||||
(is (=
|
||||
[{"key" :print-spec-keys/field1, "spec" "string?"}]
|
||||
(printer/print-spec-keys*
|
||||
(map #(copy-key % :via :expound/via)
|
||||
(::s/problems
|
||||
(s/explain-data
|
||||
(s/keys
|
||||
:req [:print-spec-keys/field1]
|
||||
:req-un [:print-spec-keys/field2])
|
||||
{:field2 [""]}))))))
|
||||
|
||||
(is (=
|
||||
[{"key" :print-spec-keys/field1, "spec" "string?"}
|
||||
{"key" :print-spec-keys/field2,
|
||||
"spec" "(coll-of :print-spec-keys/field1)"}]
|
||||
(printer/print-spec-keys*
|
||||
(map #(copy-key % :via :expound/via)
|
||||
(::s/problems
|
||||
(s/explain-data
|
||||
(s/keys
|
||||
:req [:print-spec-keys/field1
|
||||
:print-spec-keys/field2])
|
||||
{}))))))
|
||||
(is (=
|
||||
[{"key" :field1, "spec" "string?"}
|
||||
{"key" :field2, "spec" "(coll-of :print-spec-keys/field1)"}
|
||||
{"key" :field3, "spec" "int?"}]
|
||||
(printer/print-spec-keys*
|
||||
(map #(copy-key % :via :expound/via)
|
||||
(::s/problems
|
||||
(s/explain-data
|
||||
:print-spec-keys/key-spec2
|
||||
{}))))))
|
||||
(is (=
|
||||
[{"key" :key-spec3,
|
||||
"spec" #?(:clj
|
||||
"(keys\n :req-un\n [:print-spec-keys/field1\n :print-spec-keys/field4\n :print-spec-keys/field5])"
|
||||
:cljs
|
||||
"(keys\n :req-un\n [:print-spec-keys/field1\n :print-spec-keys/field4 \n :print-spec-keys/field5])")}
|
||||
{"key" :set-spec, "spec" #?(:clj
|
||||
"(coll-of\n :print-spec-keys/field1\n :kind\n set?)"
|
||||
:cljs
|
||||
"(coll-of :print-spec-keys/field1 :kind set?)")}
|
||||
{"key" :vector-spec, "spec" #?(:clj "(coll-of\n :print-spec-keys/field1\n :kind\n vector?)"
|
||||
:cljs "(coll-of\n :print-spec-keys/field1 \n :kind \n vector?)")}]
|
||||
(printer/print-spec-keys*
|
||||
(map #(copy-key % :via :expound/via)
|
||||
(::s/problems
|
||||
(s/explain-data
|
||||
:print-spec-keys/key-spec4
|
||||
{})))))))
|
||||
|
||||
(deftest print-table
|
||||
(is (=
|
||||
"
|
||||
| :key | :spec |
|
||||
|======+=======|
|
||||
| abc | a |
|
||||
| | b |
|
||||
|------+-------|
|
||||
| def | d |
|
||||
| | e |
|
||||
"
|
||||
(printer/print-table [{:key "abc" :spec "a\nb"}
|
||||
{:key "def" :spec "d\ne"}])))
|
||||
;; can select ordering of keys
|
||||
(is (=
|
||||
"
|
||||
| :b | :c |
|
||||
|====+====|
|
||||
| 2 | 3 |
|
||||
|----+----|
|
||||
| {} | () |
|
||||
"
|
||||
(printer/print-table
|
||||
[:b :c]
|
||||
[{:a 1 :b 2 :c 3}
|
||||
{:a [] :b {} :c '()}])))
|
||||
|
||||
;; ordering is deterministic, not based on hashmap
|
||||
;; semantics
|
||||
(is (=
|
||||
"
|
||||
| :k | :a | :b | :c | :d | :e | :f | :g | :h | :i | :j |
|
||||
|====+====+====+====+====+====+====+====+====+====+====|
|
||||
| k | a | b | c | d | e | f | g | h | i | j |
|
||||
|----+----+----+----+----+----+----+----+----+----+----|
|
||||
| k | a | b | c | d | e | f | g | h | i | j |
|
||||
"
|
||||
(printer/print-table
|
||||
[:k :a :b :c :d :e :f :g :h :i :j]
|
||||
[{:a "a" :b "b" :c "c" :d "d" :e "e" :f "f" :g "g" :h "h" :i "i" :j "j" :k "k" :l "l"}
|
||||
{:l "l" :k "k" :j "j" :i "i" :h "h" :g "g" :f "f" :e "e" :d "d" :c "c" :b "b" :a "a"}]))))
|
||||
|
||||
(deftest print-table-gen
|
||||
(checking
|
||||
"any table with have constant width"
|
||||
num-tests
|
||||
[col-count (s/gen pos-int?)
|
||||
keys (s/gen (s/coll-of keyword? :min-count 1))
|
||||
row-count (s/gen pos-int?)
|
||||
vals (s/gen (s/coll-of
|
||||
(s/coll-of string? :count col-count)
|
||||
:count row-count))
|
||||
:let [rows (mapv
|
||||
#(zipmap keys (get vals %))
|
||||
(range 0 row-count))
|
||||
table (printer/print-table rows)
|
||||
srows (rest (string/split table #"\n"))]]
|
||||
|
||||
(is (apply = (map count srows))))
|
||||
|
||||
(checking
|
||||
"any table will contain a sub-table of all rows but the last"
|
||||
num-tests
|
||||
[col-count (s/gen pos-int?)
|
||||
keys (s/gen (s/coll-of keyword? :min-count 1))
|
||||
row-count (s/gen (s/int-in 2 10))
|
||||
vals (s/gen (s/coll-of
|
||||
(s/coll-of string? :count col-count)
|
||||
:count row-count))
|
||||
:let [rows (mapv
|
||||
#(zipmap keys (get vals %))
|
||||
(range 0 row-count))
|
||||
sub-rows (butlast rows)
|
||||
table (printer/print-table rows)
|
||||
sub-table (printer/print-table sub-rows)
|
||||
sub-table-last-row (last (string/split sub-table #"\n"))
|
||||
table-last-row (last (string/split table #"\n"))]]
|
||||
;; If the line we delete shrinks the width of the table
|
||||
;; (because it was the widest value)
|
||||
;; then the property will not apply
|
||||
(when (= (count sub-table-last-row) (count table-last-row))
|
||||
(is (string/includes? table sub-table))))
|
||||
|
||||
#?(:clj
|
||||
(checking
|
||||
"for any known registered spec, table has max width"
|
||||
num-tests
|
||||
[spec sg/spec-gen
|
||||
:let [rows [{:key spec
|
||||
:spec (printer/expand-spec spec)}]
|
||||
table (printer/print-table rows)
|
||||
srows (rest (string/split table #"\n"))]]
|
||||
(is (< (count (last srows)) 200)))
|
||||
:cljs
|
||||
;; Noop, just to make clj-kondo happy
|
||||
(sg/topo-sort [])))
|
||||
|
||||
(deftest highlighted-value
|
||||
(testing "atomic value"
|
||||
(is (= "\"Fred\"\n^^^^^^"
|
||||
(printer/highlighted-value
|
||||
{}
|
||||
{:expound/form "Fred"
|
||||
:expound/in []}))))
|
||||
(testing "value in vector"
|
||||
(is (= "[... :b ...]\n ^^"
|
||||
(printer/highlighted-value
|
||||
{}
|
||||
{:expound/form [:a :b :c]
|
||||
:expound/in [1]}))))
|
||||
(testing "long, composite values are pretty-printed"
|
||||
(is (= (str "{:letters {:a \"aaaaaaaa\",
|
||||
:b \"bbbbbbbb\",
|
||||
:c \"cccccccd\",
|
||||
:d \"dddddddd\",
|
||||
:e \"eeeeeeee\"}}"
|
||||
#?(:clj "\n ^^^^^^^^^^^^^^^"
|
||||
:cljs "\n ^^^^^^^^^^^^^^^^"))
|
||||
;; ^- the above works in clojure - maybe not CLJS?
|
||||
(printer/highlighted-value
|
||||
{}
|
||||
{:expound/form
|
||||
{:letters
|
||||
{:a "aaaaaaaa"
|
||||
:b "bbbbbbbb"
|
||||
:c "cccccccd"
|
||||
:d "dddddddd"
|
||||
:e "eeeeeeee"}}
|
||||
:expound/in [:letters]}))))
|
||||
(testing "args to function"
|
||||
(is (= "(1 ... ...)\n ^"
|
||||
(printer/highlighted-value
|
||||
{}
|
||||
{:expound/form (get-args 1 2 3)
|
||||
:expound/in [0]}))))
|
||||
(testing "show all values"
|
||||
(is (= "(1 2 3)\n ^"
|
||||
(printer/highlighted-value
|
||||
{:show-valid-values? true}
|
||||
{:expound/form (get-args 1 2 3)
|
||||
:expound/in [0]}))))
|
||||
|
||||
(testing "special replacement chars are not used"
|
||||
(is (= "\"$ $$ $1 $& $` $'\"\n^^^^^^^^^^^^^^^^^^"
|
||||
(printer/highlighted-value
|
||||
{}
|
||||
(first
|
||||
(:expound/problems
|
||||
(problems/annotate
|
||||
(s/explain-data keyword? "$ $$ $1 $& $` $'"))))))))
|
||||
|
||||
(testing "nested map-of specs"
|
||||
(is (= "{:a {:b 1}}\n ^"
|
||||
(printer/highlighted-value
|
||||
{}
|
||||
(first
|
||||
(:expound/problems
|
||||
(problems/annotate
|
||||
(s/explain-data :highlighted-value/nested-map-of {:a {:b 1}})))))))
|
||||
(is (= "{:a {\"a\" ...}}\n ^^^"
|
||||
(printer/highlighted-value
|
||||
{}
|
||||
(first
|
||||
(:expound/problems
|
||||
(problems/annotate
|
||||
(s/explain-data :highlighted-value/nested-map-of {:a {"a" :b}})))))))
|
||||
(is (= "{1 ...}\n ^"
|
||||
(printer/highlighted-value
|
||||
{}
|
||||
(first
|
||||
(:expound/problems
|
||||
(problems/annotate
|
||||
(s/explain-data :highlighted-value/nested-map-of {1 {:a :b}}))))))))
|
||||
|
||||
(testing "nested keys specs"
|
||||
(is (= "{:address {:city 1}}\n ^"
|
||||
(printer/highlighted-value
|
||||
{}
|
||||
(first
|
||||
(:expound/problems
|
||||
(problems/annotate
|
||||
(s/explain-data :highlighted-value/house {:address {:city 1}})))))))
|
||||
(is (= "{:address {\"city\" \"Denver\"}}\n ^^^^^^^^^^^^^^^^^"
|
||||
(printer/highlighted-value
|
||||
{}
|
||||
(first
|
||||
(:expound/problems
|
||||
(problems/annotate
|
||||
(s/explain-data :highlighted-value/house {:address {"city" "Denver"}})))))))
|
||||
(is (= "{\"address\" {:city \"Denver\"}}\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^"
|
||||
(printer/highlighted-value
|
||||
{}
|
||||
(first
|
||||
(:expound/problems
|
||||
(problems/annotate
|
||||
(s/explain-data :highlighted-value/house {"address" {:city "Denver"}})))))))))
|
||||
|
||||
(deftest highlighted-value-on-alt
|
||||
(is (= "[... 0]\n ^"
|
||||
(printer/highlighted-value
|
||||
{}
|
||||
(first
|
||||
(:expound/problems
|
||||
(problems/annotate
|
||||
(s/explain-data
|
||||
(clojure.spec.alpha/alt :a int?
|
||||
:b (clojure.spec.alpha/spec (clojure.spec.alpha/cat :c int?)))
|
||||
[1 0]))))))))
|
||||
|
||||
(deftest highlighted-value-on-coll-of
|
||||
;; sets
|
||||
(is (= "#{1 3 2 :a}\n ^^"
|
||||
(printer/highlighted-value
|
||||
{}
|
||||
(first
|
||||
(:expound/problems
|
||||
(problems/annotate
|
||||
(s/explain-data
|
||||
(s/coll-of integer?)
|
||||
#{1 :a 2 3})))))))
|
||||
(is (= "#{:a}\n ^^"
|
||||
(printer/highlighted-value
|
||||
{}
|
||||
(first
|
||||
(:expound/problems
|
||||
(problems/annotate
|
||||
(s/explain-data
|
||||
(s/coll-of integer?)
|
||||
#{:a})))))))
|
||||
|
||||
;; lists
|
||||
(is (= "(... :a ... ...)\n ^^"
|
||||
(printer/highlighted-value
|
||||
{}
|
||||
(first
|
||||
(:expound/problems
|
||||
(problems/annotate
|
||||
(s/explain-data
|
||||
(s/coll-of integer?)
|
||||
'(1 :a 2 3))))))))
|
||||
(is (= "(:a)\n ^^"
|
||||
(printer/highlighted-value
|
||||
{}
|
||||
(first
|
||||
(:expound/problems
|
||||
(problems/annotate
|
||||
(s/explain-data
|
||||
(s/coll-of integer?)
|
||||
'(:a))))))))
|
||||
|
||||
;; vectors
|
||||
(is (= "[... :a ... ...]\n ^^"
|
||||
(printer/highlighted-value
|
||||
{}
|
||||
(first
|
||||
(:expound/problems
|
||||
(problems/annotate
|
||||
(s/explain-data
|
||||
(s/coll-of integer?)
|
||||
[1 :a 2 3])))))))
|
||||
|
||||
(is (= "[:a]\n ^^"
|
||||
(printer/highlighted-value
|
||||
{}
|
||||
(first
|
||||
(:expound/problems
|
||||
(problems/annotate
|
||||
(s/explain-data
|
||||
(s/coll-of integer?)
|
||||
[:a])))))))
|
||||
|
||||
;; maps
|
||||
(is (= "[1 :a]\n^^^^^^"
|
||||
(printer/highlighted-value
|
||||
{}
|
||||
(first
|
||||
(:expound/problems
|
||||
(problems/annotate
|
||||
(s/explain-data
|
||||
(s/coll-of integer?)
|
||||
{1 :a 2 3})))))))
|
||||
|
||||
(is (= "[:a 1]\n^^^^^^"
|
||||
(printer/highlighted-value
|
||||
{}
|
||||
(first
|
||||
(:expound/problems
|
||||
(problems/annotate
|
||||
(s/explain-data
|
||||
(s/coll-of integer?)
|
||||
{:a 1}))))))))
|
||||
30
test-resources/lib_tests/expound/problems_test.cljc
Normal file
30
test-resources/lib_tests/expound/problems_test.cljc
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
(ns expound.problems-test
|
||||
(:require [clojure.test :as ct :refer [is deftest use-fixtures]]
|
||||
[clojure.spec.alpha :as s]
|
||||
[expound.problems :as problems]
|
||||
[expound.test-utils :as test-utils]))
|
||||
|
||||
(use-fixtures :once
|
||||
test-utils/check-spec-assertions
|
||||
test-utils/instrument-all)
|
||||
|
||||
(s/def :highlighted-value/nested-map-of (s/map-of keyword? (s/map-of keyword? keyword?)))
|
||||
|
||||
(s/def :highlighted-value/city string?)
|
||||
(s/def :highlighted-value/address (s/keys :req-un [:highlighted-value/city]))
|
||||
(s/def :highlighted-value/house (s/keys :req-un [:highlighted-value/address]))
|
||||
|
||||
(s/def :annotate-test/div-fn (s/fspec
|
||||
:args (s/cat :x int? :y pos-int?)))
|
||||
(defn my-div [x y]
|
||||
(assert (pos? (/ x y))))
|
||||
|
||||
(deftest annotate-test
|
||||
(is (= {:expound/in [0]
|
||||
:val '(0 1)
|
||||
:reason "Assert failed: (pos? (/ x y))"}
|
||||
(-> (s/explain-data (s/coll-of :annotate-test/div-fn) [my-div])
|
||||
problems/annotate
|
||||
:expound/problems
|
||||
first
|
||||
(select-keys [:expound/in :val :reason])))))
|
||||
97
test-resources/lib_tests/expound/spec_gen.cljc
Normal file
97
test-resources/lib_tests/expound/spec_gen.cljc
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
(ns expound.spec-gen
|
||||
(:require [clojure.spec.alpha :as s]
|
||||
[com.stuartsierra.dependency :as deps]
|
||||
[clojure.test.check.generators :as gen]
|
||||
[expound.alpha :as expound]))
|
||||
|
||||
;; I want to do something like
|
||||
;; (s/def :specs.coll-of/into #{[] '() #{}})
|
||||
;; but Clojure (not Clojurescript) won't allow
|
||||
;; this. As a workaround, I'll just use vectors instead
|
||||
;; of vectors and lists.
|
||||
;; FIXME - force a specific type of into/kind one for each test
|
||||
;; (one for vectors, one for lists, etc)
|
||||
|
||||
(s/def :specs.coll-of/into #{[] #{}})
|
||||
(s/def :specs.coll-of/kind #{vector? list? set?})
|
||||
(s/def :specs.coll-of/count pos-int?)
|
||||
(s/def :specs.coll-of/max-count pos-int?)
|
||||
(s/def :specs.coll-of/min-count pos-int?)
|
||||
(s/def :specs.coll-of/distinct boolean?)
|
||||
|
||||
(s/def :specs/every-args
|
||||
(s/keys :req-un
|
||||
[:specs.coll-of/into
|
||||
:specs.coll-of/kind
|
||||
:specs.coll-of/count
|
||||
:specs.coll-of/max-count
|
||||
:specs.coll-of/min-count
|
||||
:specs.coll-of/distinct]))
|
||||
|
||||
(defn apply-coll-of [spec {:keys [into max-count min-count distinct]}]
|
||||
(s/coll-of spec :into into :min-count min-count :max-count max-count :distinct distinct))
|
||||
|
||||
(defn apply-map-of [spec1 spec2 {:keys [into max-count min-count distinct _gen-max]}]
|
||||
(s/map-of spec1 spec2 :into into :min-count min-count :max-count max-count :distinct distinct))
|
||||
|
||||
;; Since CLJS prints out entire source of a function when
|
||||
;; it pretty-prints a failure, the output becomes much nicer if
|
||||
;; we wrap each function in a simple spec
|
||||
(expound/def :specs/string string? "should be a string")
|
||||
(expound/def :specs/vector vector? "should be a vector")
|
||||
(s/def :specs/int int?)
|
||||
(s/def :specs/boolean boolean?)
|
||||
(expound/def :specs/keyword keyword? "should be a keyword")
|
||||
(s/def :specs/map map?)
|
||||
(s/def :specs/symbol symbol?)
|
||||
(s/def :specs/pos-int pos-int?)
|
||||
(s/def :specs/neg-int neg-int?)
|
||||
(s/def :specs/zero #(and (number? %) (zero? %)))
|
||||
(s/def :specs/keys (s/keys
|
||||
:req-un [:specs/string]
|
||||
:req [:specs/map]
|
||||
:opt-un [:specs/vector]
|
||||
:opt [:specs/int]))
|
||||
|
||||
(def simple-spec-gen (gen/one-of
|
||||
[(gen/elements [:specs/string
|
||||
:specs/vector
|
||||
:specs/int
|
||||
:specs/boolean
|
||||
:specs/keyword
|
||||
:specs/map
|
||||
:specs/symbol
|
||||
:specs/pos-int
|
||||
:specs/neg-int
|
||||
:specs/zero
|
||||
:specs/keys])
|
||||
(gen/set gen/simple-type-printable)]))
|
||||
|
||||
(defn spec-dependencies [spec]
|
||||
(->> spec
|
||||
s/form
|
||||
(tree-seq coll? seq)
|
||||
(filter #(and (s/get-spec %) (not= spec %)))
|
||||
distinct))
|
||||
|
||||
(defn topo-sort [specs]
|
||||
(deps/topo-sort
|
||||
(reduce
|
||||
(fn [gr spec]
|
||||
(reduce
|
||||
(fn [g d]
|
||||
;; If this creates a circular reference, then
|
||||
;; just skip it.
|
||||
(if (deps/depends? g d spec)
|
||||
g
|
||||
(deps/depend g spec d)))
|
||||
gr
|
||||
(spec-dependencies spec)))
|
||||
(deps/graph)
|
||||
specs)))
|
||||
|
||||
#?(:clj
|
||||
(def spec-gen (gen/elements (->> (s/registry)
|
||||
(map key)
|
||||
topo-sort
|
||||
(filter keyword?)))))
|
||||
26
test-resources/lib_tests/expound/specs_test.cljc
Normal file
26
test-resources/lib_tests/expound/specs_test.cljc
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
(ns expound.specs-test
|
||||
(:require [expound.specs]
|
||||
[clojure.spec.alpha :as s]
|
||||
[clojure.test :as ct :refer [is deftest use-fixtures]]
|
||||
[expound.test-utils :as test-utils]
|
||||
[expound.alpha :as expound]))
|
||||
|
||||
(use-fixtures :once
|
||||
test-utils/check-spec-assertions
|
||||
test-utils/instrument-all)
|
||||
|
||||
(deftest provided-specs
|
||||
(binding [s/*explain-out* (expound/custom-printer {:print-specs? false})]
|
||||
(is (= "-- Spec failed --------------------
|
||||
|
||||
1
|
||||
|
||||
should be a keyword with no namespace
|
||||
|
||||
-------------------------
|
||||
Detected 1 error
|
||||
"
|
||||
(s/explain-str :expound.specs/simple-kw 1)))
|
||||
(doseq [kw expound.specs/public-specs]
|
||||
(is (some? (s/get-spec kw)) (str "Failed to find spec for keyword " kw))
|
||||
(is (some? (expound/error-message kw)) (str "Failed to find error message for keyword " kw)))))
|
||||
115
test-resources/lib_tests/expound/spell_spec_test.cljc
Normal file
115
test-resources/lib_tests/expound/spell_spec_test.cljc
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
;; copied from
|
||||
;; https://github.com/bhauman/spell-spec/blob/master/test/spell_spec/expound_test.cljc
|
||||
;; so I don't break the extension API
|
||||
(ns expound.spell-spec-test
|
||||
(:require [#?(:clj clojure.test :cljs cljs.test)
|
||||
:refer [deftest is testing]]
|
||||
[#?(:clj clojure.spec.alpha
|
||||
:cljs cljs.spec.alpha)
|
||||
:as s]
|
||||
[clojure.string :as string]
|
||||
[spell-spec.alpha :as spell :refer [warn-keys strict-keys warn-strict-keys]]
|
||||
[expound.alpha :as exp]
|
||||
[spell-spec.expound :as sp.ex]))
|
||||
|
||||
;; copied from
|
||||
;; https://github.com/bhauman/spell-spec/blob/48ea2ca544f02b04a73dc42a91aa4876dcc5fc95/src/spell_spec/expound.cljc#L23-L34
|
||||
;; because test-refresh doesn't refesh libraries if I set explicit paths and
|
||||
;; if I don't restrict the paths, it tries to reload deps in the CLJS build
|
||||
|
||||
(defmethod exp/problem-group-str :spell-spec.alpha/misspelled-key [_type spec-name val path problems opts]
|
||||
(sp.ex/exp-formated "Misspelled map key" _type spec-name val path problems opts))
|
||||
|
||||
(defmethod exp/expected-str :spell-spec.alpha/misspelled-key [_type _spec-name _val _path problems _opts]
|
||||
(let [{:keys [:spell-spec.alpha/likely-misspelling-of]} (first problems)]
|
||||
(str "should probably be" (sp.ex/format-correction-list likely-misspelling-of))))
|
||||
|
||||
(defmethod exp/problem-group-str :spell-spec.alpha/unknown-key [_type spec-name val path problems opts]
|
||||
(sp.ex/exp-formated "Unknown map key" _type spec-name val path problems opts))
|
||||
|
||||
(defmethod exp/expected-str :spell-spec.alpha/unknown-key [_type _spec-name _val _path problems _opts]
|
||||
(str "should be" (sp.ex/format-correction-list (-> problems first :pred))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn fetch-warning-output [thunk]
|
||||
#?(:clj (binding [*err* (java.io.StringWriter.)]
|
||||
(thunk)
|
||||
(str *err*))
|
||||
:cljs (with-out-str (thunk))))
|
||||
|
||||
(deftest check-misspell-test
|
||||
(let [spec (spell/keys :opt-un [::hello ::there])
|
||||
data {:there 1 :helloo 1 :barabara 1}
|
||||
result
|
||||
(exp/expound-str spec data)]
|
||||
(is (string/includes? result "Misspelled map key"))
|
||||
(is (string/includes? result "should probably be"))
|
||||
(is (string/includes? result " :hello\n"))))
|
||||
|
||||
(deftest check-misspell-with-namespace-test
|
||||
(let [spec (spell/keys :opt [::hello ::there])
|
||||
data {::there 1 ::helloo 1 :barabara 1}
|
||||
result (exp/expound-str spec data)]
|
||||
(is (string/includes? result "Misspelled map key"))
|
||||
(is (string/includes? result "should probably be"))
|
||||
(is (string/includes? result ":expound.spell-spec-test/hello\n"))))
|
||||
|
||||
(s/def ::hello integer?)
|
||||
(s/def ::there integer?)
|
||||
|
||||
(deftest other-errors-test
|
||||
(let [spec (spell/keys :opt-un [::hello ::there])
|
||||
data {:there "1" :helloo 1 :barabara 1}
|
||||
result (exp/expound-str spec data)]
|
||||
(is (string/includes? result "Misspelled map key"))
|
||||
(is (string/includes? result "should probably be"))
|
||||
(is (string/includes? result " :hello\n"))
|
||||
|
||||
(is (not (string/includes? result "Spec failed")))
|
||||
(is (not (string/includes? result "should satisfy")))
|
||||
(is (not (string/includes? result "integer?")))))
|
||||
|
||||
(deftest warning-is-valid-test
|
||||
(let [spec (warn-keys :opt-un [::hello ::there])
|
||||
data {:there 1 :helloo 1 :barabara 1}]
|
||||
(testing "expound prints warning to *err*"
|
||||
(is (= (fetch-warning-output #(exp/expound-str spec data))
|
||||
"SPEC WARNING: possible misspelled map key :helloo should probably be :hello in {:there 1, :helloo 1, :barabara 1}\n")))))
|
||||
|
||||
(deftest strict-keys-test
|
||||
(let [spec (strict-keys :opt-un [::hello ::there])
|
||||
data {:there 1 :barabara 1}
|
||||
result (exp/expound-str spec data)]
|
||||
(is (string/includes? result "Unknown map key"))
|
||||
(is (string/includes? result "should be one of"))
|
||||
(is (string/includes? result " :hello, :there\n"))))
|
||||
|
||||
(deftest warn-on-unknown-keys-test
|
||||
(let [spec (warn-strict-keys :opt-un [::hello ::there])
|
||||
data {:there 1 :barabara 1}]
|
||||
(testing "expound prints warning to *err*"
|
||||
(is (= (fetch-warning-output #(exp/expound-str spec data))
|
||||
"SPEC WARNING: unknown map key :barabara in {:there 1, :barabara 1}\n")))))
|
||||
|
||||
(deftest multiple-spelling-matches
|
||||
(let [spec (spell/keys :opt-un [::hello1 ::hello2 ::hello3 ::hello4 ::there])
|
||||
data {:there 1 :helloo 1 :barabara 1}
|
||||
result (exp/expound-str spec data)]
|
||||
(is (string/includes? result "Misspelled map key"))
|
||||
(is (string/includes? result "should probably be one of"))
|
||||
(doseq [k [:hello1 :hello2 :hello3 :hello4]]
|
||||
(is (string/includes? result (pr-str k)))))
|
||||
(let [spec (spell/keys :opt-un [::hello1 ::hello2 ::hello3 ::there])
|
||||
data {:there 1 :helloo 1 :barabara 1}
|
||||
result (exp/expound-str spec data)]
|
||||
(is (string/includes? result "Misspelled map key"))
|
||||
(is (string/includes? result "should probably be one of"))
|
||||
(is (not (string/includes? result (pr-str :hello4))))
|
||||
(doseq [k [:hello1 :hello2 :hello3]]
|
||||
(is (string/includes? result (pr-str k)))))
|
||||
(let [spec (spell/keys :opt-un [::hello ::there])
|
||||
data {:there 1 :helloo 1 :barabara 1}
|
||||
result (exp/expound-str spec data)]
|
||||
(is (string/includes? result "Misspelled map key"))
|
||||
(is (string/includes? result "should probably be: :hello\n"))))
|
||||
28
test-resources/lib_tests/expound/test_runner.cljs
Normal file
28
test-resources/lib_tests/expound/test_runner.cljs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
(ns expound.test-runner
|
||||
(:require [jx.reporter.karma :refer-macros [#_run-tests #_run-all-tests]]
|
||||
[expound.alpha-test]
|
||||
[expound.paths-test]
|
||||
[expound.printer-test]
|
||||
[expound.print-length-test]
|
||||
[expound.problems-test]
|
||||
[expound.test-utils]
|
||||
[expound.specs-test]
|
||||
[expound.spell-spec-test]))
|
||||
|
||||
(enable-console-print!)
|
||||
|
||||
;; runs all tests in all namespaces
|
||||
;; This is what runs by default
|
||||
(defn ^:export run-all [karma]
|
||||
(jx.reporter.karma/run-all-tests karma))
|
||||
|
||||
;; runs all tests in all namespaces - only namespaces with names matching
|
||||
;; the regular expression will be tested
|
||||
;; You can use this by changing client.args in karma.conf.js
|
||||
#_(defn ^:export run-all-regex [karma]
|
||||
(run-all-tests karma #".*-test$"))
|
||||
|
||||
;; runs all tests in the given namespaces
|
||||
;; You can use this by changing client.args in karma.conf.js
|
||||
#_(defn ^:export run [karma]
|
||||
(run-tests karma 'expound.alpha-test))
|
||||
41
test-resources/lib_tests/expound/test_utils.cljc
Normal file
41
test-resources/lib_tests/expound/test_utils.cljc
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
(ns expound.test-utils
|
||||
(:require [clojure.spec.alpha :as s]
|
||||
#?(:cljs
|
||||
[clojure.spec.test.alpha :as st]
|
||||
;; FIXME
|
||||
;; orchestra is supposed to work with cljs but
|
||||
;; it isn't working for me right now
|
||||
#_[orchestra-cljs.spec.test :as st]
|
||||
:clj [orchestra.spec.test :as st])
|
||||
[expound.alpha :as expound]
|
||||
[clojure.test :as ct]
|
||||
;; BB-TEST-PATCH: Don't have this dep and can't load it
|
||||
#_[com.gfredericks.test.chuck.clojure-test :as chuck]
|
||||
[expound.util :as util]
|
||||
[clojure.test.check.generators :as gen]))
|
||||
|
||||
;; test.chuck defines a reporter for the shrunk results, but only for the
|
||||
;; default reporter (:cljs.test/default). Since karma uses its own reporter,
|
||||
;; we need to provide an implementation of the report multimethod for
|
||||
;; the karma reporter and shrunk results
|
||||
|
||||
; (defmethod ct/report [:jx.reporter.karma/karma ::chuck/shrunk] [m]
|
||||
; (let [f (get (methods ct/report) [::ct/default ::chuck/shrunk])]
|
||||
; (f m)))
|
||||
|
||||
(defn check-spec-assertions [test-fn]
|
||||
(s/check-asserts true)
|
||||
(test-fn)
|
||||
(s/check-asserts false))
|
||||
|
||||
(defn instrument-all [test-fn]
|
||||
(binding [s/*explain-out* (expound/custom-printer {:theme :figwheel-theme})]
|
||||
(st/instrument)
|
||||
(test-fn)
|
||||
(st/unstrument)))
|
||||
|
||||
(defn contains-nan? [x]
|
||||
(boolean (some util/nan? (tree-seq coll? identity x))))
|
||||
|
||||
(def any-printable-wo-nan (gen/such-that (complement contains-nan?)
|
||||
gen/any-printable))
|
||||
52
test-resources/lib_tests/io/aviso/binary_test.clj
Normal file
52
test-resources/lib_tests/io/aviso/binary_test.clj
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
(ns io.aviso.binary-test
|
||||
"Tests for the io.aviso.binary namespace."
|
||||
(:use io.aviso.binary
|
||||
clojure.test)
|
||||
(:import (java.nio ByteBuffer)))
|
||||
|
||||
(defn ^:private format-string-as-byte-array [str]
|
||||
(format-binary (.getBytes str)))
|
||||
|
||||
(deftest format-byte-array-test
|
||||
|
||||
(are [input expected]
|
||||
(= expected (format-string-as-byte-array input))
|
||||
|
||||
"Hello" "0000: 48 65 6C 6C 6F\n"
|
||||
|
||||
"This is a longer text that spans to a second line."
|
||||
"0000: 54 68 69 73 20 69 73 20 61 20 6C 6F 6E 67 65 72 20 74 65 78 74 20 74 68 61 74 20 73 70 61 6E 73\n0020: 20 74 6F 20 61 20 73 65 63 6F 6E 64 20 6C 69 6E 65 2E\n"))
|
||||
|
||||
(deftest format-string-as-byte-data
|
||||
(are [input expected]
|
||||
(= expected (format-binary input))
|
||||
"" ""
|
||||
|
||||
"Hello" "0000: 48 65 6C 6C 6F\n"
|
||||
|
||||
"This is a longer text that spans to a second line."
|
||||
|
||||
"0000: 54 68 69 73 20 69 73 20 61 20 6C 6F 6E 67 65 72 20 74 65 78 74 20 74 68 61 74 20 73 70 61 6E 73\n0020: 20 74 6F 20 61 20 73 65 63 6F 6E 64 20 6C 69 6E 65 2E\n"))
|
||||
|
||||
(deftest nil-is-an-empty-data
|
||||
(is (= (format-binary nil) "")))
|
||||
|
||||
(deftest byte-buffer
|
||||
(let [bb (ByteBuffer/wrap (.getBytes "Duty Now For The Future" "UTF-8"))]
|
||||
(is (= "0000: 44 75 74 79 20 4E 6F 77 20 46 6F 72 20 54 68 65 20 46 75 74 75 72 65\n"
|
||||
(format-binary bb)))
|
||||
|
||||
(is (= "0000: 44 75 74 79\n"
|
||||
(-> bb
|
||||
(.position 5)
|
||||
(.limit 9)
|
||||
format-binary)))
|
||||
|
||||
(is (= "0000: 46 6F 72\n"
|
||||
(-> bb
|
||||
(.position 9)
|
||||
(.limit 12)
|
||||
.slice
|
||||
format-binary)))
|
||||
|
||||
))
|
||||
583
test-resources/lib_tests/io/aviso/exception_test.clj
Normal file
583
test-resources/lib_tests/io/aviso/exception_test.clj
Normal file
|
|
@ -0,0 +1,583 @@
|
|||
(ns io.aviso.exception-test
|
||||
(:use clojure.test)
|
||||
(:require [clojure.string :as str]
|
||||
[io.aviso.exception :as e :refer [*fonts* parse-exception format-exception]]
|
||||
[clojure.pprint :refer [pprint]]
|
||||
[com.stuartsierra.component :as component]
|
||||
[com.walmartlabs.test-reporting :refer [reporting]]
|
||||
io.aviso.component))
|
||||
|
||||
(deftest write-exceptions
|
||||
(testing "exception properties printing"
|
||||
(testing "Does not fail with ex-info's map keys not implementing clojure.lang.Named"
|
||||
(is (re-find #"string-key.*string-val"
|
||||
(format-exception (ex-info "Error" {"string-key" "string-val"})))))))
|
||||
|
||||
(defn parse [& text-lines]
|
||||
(let [text (str/join \newline text-lines)]
|
||||
(binding [*fonts* nil]
|
||||
(parse-exception text nil))))
|
||||
|
||||
(deftest parse-exceptions
|
||||
(is (= [{:class-name "java.lang.IllegalArgumentException"
|
||||
:message "No value supplied for key: {:host \"example.com\"}"
|
||||
:stack-trace
|
||||
[{:simple-class "PersistentHashMap"
|
||||
:package "clojure.lang"
|
||||
:omitted true
|
||||
:is-clojure? false
|
||||
:method "create"
|
||||
:name ""
|
||||
:formatted-name "..."
|
||||
:file ""
|
||||
:line nil
|
||||
:class "clojure.lang.PersistentHashMap"
|
||||
:names []}
|
||||
{:simple-class "client$tcp_client"
|
||||
:package "riemann"
|
||||
:is-clojure? true
|
||||
:method "doInvoke"
|
||||
:name "riemann.client/tcp-client"
|
||||
:formatted-name "riemann.client/tcp-client"
|
||||
:file "client.clj"
|
||||
:line 90
|
||||
:class "riemann.client$tcp_client"
|
||||
:names '("riemann.client" "tcp-client")}
|
||||
{:simple-class "RestFn"
|
||||
:package "clojure.lang"
|
||||
:omitted true
|
||||
:is-clojure? false
|
||||
:method "invoke"
|
||||
:name ""
|
||||
:formatted-name "..."
|
||||
:file ""
|
||||
:line nil
|
||||
:class "clojure.lang.RestFn"
|
||||
:names []}
|
||||
{:simple-class "error_monitor$make_connection"
|
||||
:package "com.example"
|
||||
:is-clojure? true
|
||||
:method "invoke"
|
||||
:name "com.example.error-monitor/make-connection"
|
||||
:formatted-name "com.example.error-monitor/make-connection"
|
||||
:file "error_monitor.clj"
|
||||
:line 22
|
||||
:class "com.example.error_monitor$make_connection"
|
||||
:names '("com.example.error-monitor" "make-connection")}
|
||||
{:simple-class "error_monitor$make_client"
|
||||
:package "com.example"
|
||||
:is-clojure? true
|
||||
:method "invoke"
|
||||
:name "com.example.error-monitor/make-client"
|
||||
:formatted-name "com.example.error-monitor/make-client"
|
||||
:file "error_monitor.clj"
|
||||
:line 26
|
||||
:class "com.example.error_monitor$make_client"
|
||||
:names '("com.example.error-monitor" "make-client")}
|
||||
{:simple-class "core$map$fn__4553"
|
||||
:package "clojure"
|
||||
:is-clojure? true
|
||||
:method "invoke"
|
||||
:name "clojure.core/map/fn"
|
||||
:formatted-name "clojure.core/map/fn"
|
||||
:file "core.clj"
|
||||
:line 2624
|
||||
:class "clojure.core$map$fn__4553"
|
||||
:names '("clojure.core" "map" "fn")}
|
||||
{:simple-class "LazySeq"
|
||||
:package "clojure.lang"
|
||||
:omitted true
|
||||
:is-clojure? false
|
||||
:method "sval"
|
||||
:name ""
|
||||
:formatted-name "..."
|
||||
:file ""
|
||||
:line nil
|
||||
:class "clojure.lang.LazySeq"
|
||||
:names []}
|
||||
{:simple-class "core$seq__4128"
|
||||
:package "clojure"
|
||||
:is-clojure? true
|
||||
:method "invoke"
|
||||
:name "clojure.core/seq"
|
||||
:formatted-name "clojure.core/seq"
|
||||
:file "core.clj"
|
||||
:line 137
|
||||
:class "clojure.core$seq__4128"
|
||||
:names '("clojure.core" "seq")}
|
||||
{:simple-class "core$sort"
|
||||
:package "clojure"
|
||||
:is-clojure? true
|
||||
:method "invoke"
|
||||
:name "clojure.core/sort"
|
||||
:formatted-name "clojure.core/sort"
|
||||
:file "core.clj"
|
||||
:line 2981
|
||||
:class "clojure.core$sort"
|
||||
:names '("clojure.core" "sort")}
|
||||
{:simple-class "core$sort_by"
|
||||
:package "clojure"
|
||||
:is-clojure? true
|
||||
:method "invoke"
|
||||
:name "clojure.core/sort-by"
|
||||
:formatted-name "clojure.core/sort-by"
|
||||
:file "core.clj"
|
||||
:line 2998
|
||||
:class "clojure.core$sort_by"
|
||||
:names '("clojure.core" "sort-by")}
|
||||
{:simple-class "core$sort_by"
|
||||
:package "clojure"
|
||||
:is-clojure? true
|
||||
:method "invoke"
|
||||
:name "clojure.core/sort-by"
|
||||
:formatted-name "clojure.core/sort-by"
|
||||
:file "core.clj"
|
||||
:line 2996
|
||||
:class "clojure.core$sort_by"
|
||||
:names '("clojure.core" "sort-by")}
|
||||
{:simple-class "error_monitor$make_clients"
|
||||
:package "com.example"
|
||||
:is-clojure? true
|
||||
:method "invoke"
|
||||
:name "com.example.error-monitor/make-clients"
|
||||
:formatted-name "com.example.error-monitor/make-clients"
|
||||
:file "error_monitor.clj"
|
||||
:line 31
|
||||
:class "com.example.error_monitor$make_clients"
|
||||
:names '("com.example.error-monitor" "make-clients")}
|
||||
{:simple-class "error_monitor$report_and_reset"
|
||||
:package "com.example"
|
||||
:is-clojure? true
|
||||
:method "invoke"
|
||||
:name "com.example.error-monitor/report-and-reset"
|
||||
:formatted-name "com.example.error-monitor/report-and-reset"
|
||||
:file "error_monitor.clj"
|
||||
:line 185
|
||||
:class "com.example.error_monitor$report_and_reset"
|
||||
:names '("com.example.error-monitor" "report-and-reset")}
|
||||
{:simple-class "main$_main$fn__705"
|
||||
:package "com.example.error_monitor"
|
||||
:is-clojure? true
|
||||
:method "invoke"
|
||||
:name "com.example.error-monitor.main/-main/fn"
|
||||
:formatted-name "com.example.error-monitor.main/-main/fn"
|
||||
:file "main.clj"
|
||||
:line 19
|
||||
:class "com.example.error_monitor.main$_main$fn__705"
|
||||
:names '("com.example.error-monitor.main" "-main" "fn")}
|
||||
{:simple-class "main$_main"
|
||||
:package "com.example.error_monitor"
|
||||
:is-clojure? true
|
||||
:method "doInvoke"
|
||||
:name "com.example.error-monitor.main/-main"
|
||||
:formatted-name "com.example.error-monitor.main/-main"
|
||||
:file "main.clj"
|
||||
:line 16
|
||||
:class "com.example.error_monitor.main$_main"
|
||||
:names '("com.example.error-monitor.main" "-main")}
|
||||
{:simple-class "RestFn"
|
||||
:package "clojure.lang"
|
||||
:omitted true
|
||||
:is-clojure? false
|
||||
:method "applyTo"
|
||||
:name ""
|
||||
:formatted-name "..."
|
||||
:file ""
|
||||
:line nil
|
||||
:class "clojure.lang.RestFn"
|
||||
:names []}
|
||||
{:class "com.example.error_monitor.main"
|
||||
:file ""
|
||||
:formatted-name "com.example.error_monitor.main.main"
|
||||
:is-clojure? false
|
||||
:line nil
|
||||
:method "main"
|
||||
:name ""
|
||||
:names []
|
||||
:package "com.example.error_monitor"
|
||||
:simple-class "main"}]}]
|
||||
(parse "java.lang.IllegalArgumentException: No value supplied for key: {:host \"example.com\"}"
|
||||
"\tat clojure.lang.PersistentHashMap.create(PersistentHashMap.java:77)"
|
||||
"\tat riemann.client$tcp_client.doInvoke(client.clj:90)"
|
||||
"\tat clojure.lang.RestFn.invoke(RestFn.java:408)"
|
||||
"\tat com.example.error_monitor$make_connection.invoke(error_monitor.clj:22)"
|
||||
"\tat com.example.error_monitor$make_client.invoke(error_monitor.clj:26)"
|
||||
"\tat clojure.core$map$fn__4553.invoke(core.clj:2624)"
|
||||
"\tat clojure.lang.LazySeq.sval(LazySeq.java:40)"
|
||||
"\tat clojure.lang.LazySeq.seq(LazySeq.java:49)"
|
||||
"\tat clojure.lang.RT.seq(RT.java:507)"
|
||||
"\tat clojure.core$seq__4128.invoke(core.clj:137)"
|
||||
"\tat clojure.core$sort.invoke(core.clj:2981)"
|
||||
"\tat clojure.core$sort_by.invoke(core.clj:2998)"
|
||||
"\tat clojure.core$sort_by.invoke(core.clj:2996)"
|
||||
"\tat com.example.error_monitor$make_clients.invoke(error_monitor.clj:31)"
|
||||
"\tat com.example.error_monitor$report_and_reset.invoke(error_monitor.clj:185)"
|
||||
"\tat com.example.error_monitor.main$_main$fn__705.invoke(main.clj:19)"
|
||||
"\tat com.example.error_monitor.main$_main.doInvoke(main.clj:16)"
|
||||
"\tat clojure.lang.RestFn.applyTo(RestFn.java:137)"
|
||||
"\tat com.example.error_monitor.main.main(Unknown Source)"))
|
||||
|
||||
(is (= [{:class-name "java.lang.RuntimeException", :message "Request handling exception"}
|
||||
{:class-name "java.lang.RuntimeException", :message "Failure updating row"}
|
||||
{:class-name "java.sql.SQLException"
|
||||
:message "Database failure\nSELECT FOO, BAR, BAZ\nFROM GNIP\nfailed with ABC123"
|
||||
:stack-trace [{:simple-class "user$jdbc_update"
|
||||
:package nil
|
||||
:is-clojure? true
|
||||
:method "invoke"
|
||||
:name "user/jdbc-update"
|
||||
:formatted-name "user/jdbc-update"
|
||||
:file "user.clj"
|
||||
:line 7
|
||||
:class "user$jdbc_update"
|
||||
:names '("user" "jdbc-update")}
|
||||
{:simple-class "user$make_jdbc_update_worker$reify__497"
|
||||
:package nil
|
||||
:is-clojure? true
|
||||
:method "do_work"
|
||||
:name "user/make-jdbc-update-worker/reify/do-work"
|
||||
:formatted-name "user/make-jdbc-update-worker/reify/do-work"
|
||||
:file "user.clj"
|
||||
:line 18
|
||||
:class "user$make_jdbc_update_worker$reify__497"
|
||||
:names '("user" "make-jdbc-update-worker" "reify" "do-work")}
|
||||
{:simple-class "user$update_row"
|
||||
:package nil
|
||||
:is-clojure? true
|
||||
:method "invoke"
|
||||
:name "user/update-row"
|
||||
:formatted-name "user/update-row"
|
||||
:file "user.clj"
|
||||
:line 23
|
||||
:class "user$update_row"
|
||||
:names '("user" "update-row")}
|
||||
{:simple-class "user$make_exception"
|
||||
:package nil
|
||||
:is-clojure? true
|
||||
:method "invoke"
|
||||
:name "user/make-exception"
|
||||
:formatted-name "user/make-exception"
|
||||
:file "user.clj"
|
||||
:line 31
|
||||
:class "user$make_exception"
|
||||
:names '("user" "make-exception")}
|
||||
{:simple-class "user$eval2018"
|
||||
:package nil
|
||||
:is-clojure? true
|
||||
:method "invoke"
|
||||
:name "user/eval2018"
|
||||
:formatted-name "user/eval2018"
|
||||
:file "REPL Input"
|
||||
:line nil
|
||||
:class "user$eval2018"
|
||||
:names '("user" "eval2018")}
|
||||
{:simple-class "Compiler"
|
||||
:package "clojure.lang"
|
||||
:omitted true
|
||||
:is-clojure? false
|
||||
:method "eval"
|
||||
:name ""
|
||||
:formatted-name "..."
|
||||
:file ""
|
||||
:line nil
|
||||
:class "clojure.lang.Compiler"
|
||||
:names []}
|
||||
{:simple-class "core$eval"
|
||||
:package "clojure"
|
||||
:is-clojure? true
|
||||
:method "invoke"
|
||||
:name "clojure.core/eval"
|
||||
:formatted-name "clojure.core/eval"
|
||||
:file "core.clj"
|
||||
:line 2852
|
||||
:class "clojure.core$eval"
|
||||
:names '("clojure.core" "eval")}]}]
|
||||
(parse "java.lang.RuntimeException: Request handling exception"
|
||||
"\tat user$make_exception.invoke(user.clj:31)"
|
||||
"\tat user$eval2018.invoke(form-init1482095333541107022.clj:1)"
|
||||
"\tat clojure.lang.Compiler.eval(Compiler.java:6619)"
|
||||
"\tat clojure.lang.Compiler.eval(Compiler.java:6582)"
|
||||
"\tat clojure.core$eval.invoke(core.clj:2852)"
|
||||
"\tat clojure.main$repl$read_eval_print__6602$fn__6605.invoke(main.clj:259)"
|
||||
"\tat clojure.main$repl$read_eval_print__6602.invoke(main.clj:259)"
|
||||
"\tat clojure.main$repl$fn__6611$fn__6612.invoke(main.clj:277)"
|
||||
"\tat clojure.main$repl$fn__6611.invoke(main.clj:277)"
|
||||
"\tat clojure.main$repl.doInvoke(main.clj:275)"
|
||||
"\tat clojure.lang.RestFn.invoke(RestFn.java:1523)"
|
||||
"\tat clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn__1419.invoke(interruptible_eval.clj:72)"
|
||||
"\tat clojure.lang.AFn.applyToHelper(AFn.java:159)"
|
||||
"\tat clojure.lang.AFn.applyTo(AFn.java:151)"
|
||||
"\tat clojure.core$apply.invoke(core.clj:617)"
|
||||
"\tat clojure.core$with_bindings_STAR_.doInvoke(core.clj:1788)"
|
||||
"\tat clojure.lang.RestFn.invoke(RestFn.java:425)"
|
||||
"\tat clojure.tools.nrepl.middleware.interruptible_eval$evaluate.invoke(interruptible_eval.clj:56)"
|
||||
"\tat clojure.tools.nrepl.middleware.interruptible_eval$interruptible_eval$fn__1461$fn__1464.invoke(interruptible_eval.clj:191)"
|
||||
"\tat clojure.tools.nrepl.middleware.interruptible_eval$run_next$fn__1456.invoke(interruptible_eval.clj:159)"
|
||||
"\tat clojure.lang.AFn.run(AFn.java:24)"
|
||||
"\tat java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)"
|
||||
"\tat java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)"
|
||||
"\tat java.lang.Thread.run(Thread.java:745)"
|
||||
"Caused by: java.lang.RuntimeException: Failure updating row"
|
||||
"\tat user$update_row.invoke(user.clj:23)"
|
||||
"\t... 24 more"
|
||||
"Caused by: java.sql.SQLException: Database failure"
|
||||
"SELECT FOO, BAR, BAZ"
|
||||
"FROM GNIP"
|
||||
"failed with ABC123"
|
||||
"\tat user$jdbc_update.invoke(user.clj:7)"
|
||||
"\tat user$make_jdbc_update_worker$reify__497.do_work(user.clj:18)"
|
||||
"\t... 25 more"))
|
||||
|
||||
(is (= [{:class-name "com.datastax.driver.core.TransportException", :message "/17.76.3.14:9042 Cannot connect"}
|
||||
{:class-name "java.net.ConnectException",
|
||||
:message "Connection refused: /17.76.3.14:9042",
|
||||
:stack-trace [{:simple-class "SocketChannelImpl"
|
||||
:package "sun.nio.ch"
|
||||
:is-clojure? false
|
||||
:method "checkConnect"
|
||||
:name ""
|
||||
:formatted-name "sun.nio.ch.SocketChannelImpl.checkConnect"
|
||||
:file ""
|
||||
:line nil
|
||||
:class "sun.nio.ch.SocketChannelImpl"
|
||||
:names []}
|
||||
{:simple-class "SocketChannelImpl"
|
||||
:package "sun.nio.ch"
|
||||
:is-clojure? false
|
||||
:method "finishConnect"
|
||||
:name ""
|
||||
:formatted-name "sun.nio.ch.SocketChannelImpl.finishConnect"
|
||||
:file "SocketChannelImpl.java"
|
||||
:line 717
|
||||
:class "sun.nio.ch.SocketChannelImpl"
|
||||
:names []}
|
||||
{:simple-class "NioClientBoss"
|
||||
:package "com.datastax.shaded.netty.channel.socket.nio"
|
||||
:is-clojure? false
|
||||
:method "connect"
|
||||
:name ""
|
||||
:formatted-name "com.datastax.shaded.netty.channel.socket.nio.NioClientBoss.connect"
|
||||
:file "NioClientBoss.java"
|
||||
:line 150
|
||||
:class "com.datastax.shaded.netty.channel.socket.nio.NioClientBoss"
|
||||
:names []}
|
||||
{:simple-class "NioClientBoss"
|
||||
:package "com.datastax.shaded.netty.channel.socket.nio"
|
||||
:is-clojure? false
|
||||
:method "processSelectedKeys"
|
||||
:name ""
|
||||
:formatted-name "com.datastax.shaded.netty.channel.socket.nio.NioClientBoss.processSelectedKeys"
|
||||
:file "NioClientBoss.java"
|
||||
:line 105
|
||||
:class "com.datastax.shaded.netty.channel.socket.nio.NioClientBoss"
|
||||
:names []}
|
||||
{:simple-class "NioClientBoss"
|
||||
:package "com.datastax.shaded.netty.channel.socket.nio"
|
||||
:is-clojure? false
|
||||
:method "process"
|
||||
:name ""
|
||||
:formatted-name "com.datastax.shaded.netty.channel.socket.nio.NioClientBoss.process"
|
||||
:file "NioClientBoss.java"
|
||||
:line 79
|
||||
:class "com.datastax.shaded.netty.channel.socket.nio.NioClientBoss"
|
||||
:names []}
|
||||
{:simple-class "AbstractNioSelector"
|
||||
:package "com.datastax.shaded.netty.channel.socket.nio"
|
||||
:is-clojure? false
|
||||
:method "run"
|
||||
:name ""
|
||||
:formatted-name "com.datastax.shaded.netty.channel.socket.nio.AbstractNioSelector.run"
|
||||
:file "AbstractNioSelector.java"
|
||||
:line 318
|
||||
:class "com.datastax.shaded.netty.channel.socket.nio.AbstractNioSelector"
|
||||
:names []}
|
||||
{:simple-class "NioClientBoss"
|
||||
:package "com.datastax.shaded.netty.channel.socket.nio"
|
||||
:is-clojure? false
|
||||
:method "run"
|
||||
:name ""
|
||||
:formatted-name "com.datastax.shaded.netty.channel.socket.nio.NioClientBoss.run"
|
||||
:file "NioClientBoss.java"
|
||||
:line 42
|
||||
:class "com.datastax.shaded.netty.channel.socket.nio.NioClientBoss"
|
||||
:names []}
|
||||
{:simple-class "ThreadRenamingRunnable"
|
||||
:package "com.datastax.shaded.netty.util"
|
||||
:is-clojure? false
|
||||
:method "run"
|
||||
:name ""
|
||||
:formatted-name "com.datastax.shaded.netty.util.ThreadRenamingRunnable.run"
|
||||
:file "ThreadRenamingRunnable.java"
|
||||
:line 108
|
||||
:class "com.datastax.shaded.netty.util.ThreadRenamingRunnable"
|
||||
:names []}
|
||||
{:simple-class "DeadLockProofWorker$1"
|
||||
:package "com.datastax.shaded.netty.util.internal"
|
||||
:is-clojure? false
|
||||
:method "run"
|
||||
:name ""
|
||||
:formatted-name "com.datastax.shaded.netty.util.internal.DeadLockProofWorker$1.run"
|
||||
:file "DeadLockProofWorker.java"
|
||||
:line 42
|
||||
:class "com.datastax.shaded.netty.util.internal.DeadLockProofWorker$1"
|
||||
:names []}
|
||||
{:simple-class "Connection"
|
||||
:package "com.datastax.driver.core"
|
||||
:is-clojure? false
|
||||
:method "<init>"
|
||||
:name ""
|
||||
:formatted-name "com.datastax.driver.core.Connection.<init>"
|
||||
:file "Connection.java"
|
||||
:line 104
|
||||
:class "com.datastax.driver.core.Connection"
|
||||
:names []}
|
||||
{:simple-class "PooledConnection"
|
||||
:package "com.datastax.driver.core"
|
||||
:is-clojure? false
|
||||
:method "<init>"
|
||||
:name ""
|
||||
:formatted-name "com.datastax.driver.core.PooledConnection.<init>"
|
||||
:file "PooledConnection.java"
|
||||
:line 32
|
||||
:class "com.datastax.driver.core.PooledConnection"
|
||||
:names []}
|
||||
{:simple-class "Connection$Factory"
|
||||
:package "com.datastax.driver.core"
|
||||
:is-clojure? false
|
||||
:method "open"
|
||||
:name ""
|
||||
:formatted-name "com.datastax.driver.core.Connection$Factory.open"
|
||||
:file "Connection.java"
|
||||
:line 557
|
||||
:class "com.datastax.driver.core.Connection$Factory"
|
||||
:names []}
|
||||
{:simple-class "DynamicConnectionPool"
|
||||
:package "com.datastax.driver.core"
|
||||
:is-clojure? false
|
||||
:method "<init>"
|
||||
:name ""
|
||||
:formatted-name "com.datastax.driver.core.DynamicConnectionPool.<init>"
|
||||
:file "DynamicConnectionPool.java"
|
||||
:line 74
|
||||
:class "com.datastax.driver.core.DynamicConnectionPool"
|
||||
:names []}
|
||||
{:simple-class "HostConnectionPool"
|
||||
:package "com.datastax.driver.core"
|
||||
:is-clojure? false
|
||||
:method "newInstance"
|
||||
:name ""
|
||||
:formatted-name "com.datastax.driver.core.HostConnectionPool.newInstance"
|
||||
:file "HostConnectionPool.java"
|
||||
:line 33
|
||||
:class "com.datastax.driver.core.HostConnectionPool"
|
||||
:names []}
|
||||
{:simple-class "SessionManager$2"
|
||||
:package "com.datastax.driver.core"
|
||||
:is-clojure? false
|
||||
:method "call"
|
||||
:name ""
|
||||
:formatted-name "com.datastax.driver.core.SessionManager$2.call"
|
||||
:file "SessionManager.java"
|
||||
:line 231
|
||||
:class "com.datastax.driver.core.SessionManager$2"
|
||||
:names []}
|
||||
{:simple-class "SessionManager$2"
|
||||
:package "com.datastax.driver.core"
|
||||
:is-clojure? false
|
||||
:method "call"
|
||||
:name ""
|
||||
:formatted-name "com.datastax.driver.core.SessionManager$2.call"
|
||||
:file "SessionManager.java"
|
||||
:line 224
|
||||
:class "com.datastax.driver.core.SessionManager$2"
|
||||
:names []}
|
||||
{:simple-class "FutureTask"
|
||||
:package "java.util.concurrent"
|
||||
:is-clojure? false
|
||||
:method "run"
|
||||
:name ""
|
||||
:formatted-name "java.util.concurrent.FutureTask.run"
|
||||
:file "FutureTask.java"
|
||||
:line 266
|
||||
:class "java.util.concurrent.FutureTask"
|
||||
:names []}
|
||||
{:simple-class "ThreadPoolExecutor"
|
||||
:package "java.util.concurrent"
|
||||
:is-clojure? false
|
||||
:method "runWorker"
|
||||
:name ""
|
||||
:formatted-name "java.util.concurrent.ThreadPoolExecutor.runWorker"
|
||||
:file "ThreadPoolExecutor.java"
|
||||
:line 1142
|
||||
:class "java.util.concurrent.ThreadPoolExecutor"
|
||||
:names []}
|
||||
{:simple-class "ThreadPoolExecutor$Worker"
|
||||
:package "java.util.concurrent"
|
||||
:is-clojure? false
|
||||
:method "run"
|
||||
:name ""
|
||||
:formatted-name "java.util.concurrent.ThreadPoolExecutor$Worker.run"
|
||||
:file "ThreadPoolExecutor.java"
|
||||
:line 617
|
||||
:class "java.util.concurrent.ThreadPoolExecutor$Worker"
|
||||
:names []}
|
||||
{:simple-class "Thread"
|
||||
:package "java.lang"
|
||||
:is-clojure? false
|
||||
:method "run"
|
||||
:name ""
|
||||
:formatted-name "java.lang.Thread.run"
|
||||
:file "Thread.java"
|
||||
:line 745
|
||||
:class "java.lang.Thread"
|
||||
:names []}]}]
|
||||
|
||||
(parse "com.datastax.driver.core.TransportException: /17.76.3.14:9042 Cannot connect"
|
||||
"\tat com.datastax.driver.core.Connection.<init>(Connection.java:104) ~store-service.jar:na"
|
||||
"\tat com.datastax.driver.core.PooledConnection.<init>(PooledConnection.java:32) ~store-service.jar:na"
|
||||
"\tat com.datastax.driver.core.Connection$Factory.open(Connection.java:557) ~store-service.jar:na"
|
||||
"\tat com.datastax.driver.core.DynamicConnectionPool.<init>(DynamicConnectionPool.java:74) ~store-service.jar:na"
|
||||
"\tat com.datastax.driver.core.HostConnectionPool.newInstance(HostConnectionPool.java:33) ~store-service.jar:na"
|
||||
"\tat com.datastax.driver.core.SessionManager$2.call(SessionManager.java:231) store-service.jar:na"
|
||||
"\tat com.datastax.driver.core.SessionManager$2.call(SessionManager.java:224) store-service.jar:na"
|
||||
"\tat java.util.concurrent.FutureTask.run(FutureTask.java:266) na:1.8.0_66"
|
||||
"\tat java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) na:1.8.0_66"
|
||||
"\tat java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) na:1.8.0_66"
|
||||
"\tat java.lang.Thread.run(Thread.java:745) na:1.8.0_66"
|
||||
"Caused by: java.net.ConnectException: Connection refused: /17.76.3.14:9042"
|
||||
"\tat sun.nio.ch.SocketChannelImpl.checkConnect(Native Method) ~na:1.8.0_66"
|
||||
"\tat sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:717) ~na:1.8.0_66"
|
||||
"\tat com.datastax.shaded.netty.channel.socket.nio.NioClientBoss.connect(NioClientBoss.java:150) ~store-service.jar:na"
|
||||
"\tat com.datastax.shaded.netty.channel.socket.nio.NioClientBoss.processSelectedKeys(NioClientBoss.java:105) ~store-service.jar:na"
|
||||
"\tat com.datastax.shaded.netty.channel.socket.nio.NioClientBoss.process(NioClientBoss.java:79) ~store-service.jar:na"
|
||||
"\tat com.datastax.shaded.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:318) ~store-service.jar:na"
|
||||
"\tat com.datastax.shaded.netty.channel.socket.nio.NioClientBoss.run(NioClientBoss.java:42) ~store-service.jar:na"
|
||||
"\tat com.datastax.shaded.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108) ~store-service.jar:na"
|
||||
"\tat com.datastax.shaded.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42) ~store-service.jar:na"
|
||||
"\t... 3 common frames omitted"))))))
|
||||
|
||||
(defrecord MyComponent []
|
||||
|
||||
component/Lifecycle
|
||||
(start [this] this)
|
||||
(stop [this] this))
|
||||
|
||||
|
||||
(deftest component-print-behavior
|
||||
(binding [e/*fonts* nil]
|
||||
(let [my-component (map->MyComponent {})
|
||||
system (component/system-map
|
||||
:my-component my-component)
|
||||
sys-exception (format-exception (ex-info "System Exception" {:system system}))
|
||||
comp-exception (format-exception (ex-info "Component Exception" {:component my-component}))]
|
||||
|
||||
(reporting {sys-exception (str/split-lines sys-exception)}
|
||||
(is (re-find #"system: #<SystemMap>" sys-exception)))
|
||||
|
||||
(reporting {comp-exception (str/split-lines comp-exception)}
|
||||
(is (re-find #"component: #<Component io.aviso.exception_test.MyComponent>" comp-exception))))))
|
||||
|
||||
(deftest write-exceptions-with-nil-data
|
||||
(testing "Does not fail with a nil ex-info map key"
|
||||
(is (re-find #"nil.*nil"
|
||||
(format-exception (ex-info "Error" {nil nil}))))))
|
||||
12
test-resources/lib_tests/missing/test/assertions_test.cljc
Normal file
12
test-resources/lib_tests/missing/test/assertions_test.cljc
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
(ns missing.test.assertions-test
|
||||
(:require
|
||||
[clojure.test :refer [deftest testing is] :as t]
|
||||
[missing.test.old-methods]
|
||||
[missing.test.assertions]))
|
||||
|
||||
(deftest a-test
|
||||
(testing "FIXME, I fail."
|
||||
1))
|
||||
|
||||
(deftest another-test
|
||||
(testing (is 1)))
|
||||
13
test-resources/lib_tests/missing/test/old_methods.cljc
Normal file
13
test-resources/lib_tests/missing/test/old_methods.cljc
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
(ns missing.test.old-methods
|
||||
(:require [clojure.test :as t]
|
||||
[missing.test.assertions :refer [register!]]))
|
||||
|
||||
(defmethod t/report #?(:clj :begin-test-var
|
||||
:cljs [::t/default :begin-test-var]) [_]
|
||||
(println "Begin test var."))
|
||||
|
||||
(defmethod t/report #?(:clj :end-test-var
|
||||
:cljs [::t/default :end-test-var]) [_]
|
||||
(println "End test var."))
|
||||
|
||||
(register! {:throw? false})
|
||||
18
test-resources/lib_tests/portal/bench.cljc
Normal file
18
test-resources/lib_tests/portal/bench.cljc
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
(ns portal.bench
|
||||
#?(:cljs (:refer-clojure :exclude [simple-benchmark]))
|
||||
#?(:cljs (:require-macros portal.bench)))
|
||||
|
||||
(defn now []
|
||||
#?(:clj (System/currentTimeMillis)
|
||||
:cljs (.now js/Date)))
|
||||
|
||||
(defmacro simple-benchmark
|
||||
[bindings expr iterations & {:keys [print-fn] :or {print-fn 'println}}]
|
||||
(let [expr-str (pr-str expr)]
|
||||
`(let ~bindings
|
||||
(dotimes [_# ~iterations] ~expr)
|
||||
(let [start# (now)
|
||||
ret# (dotimes [_# ~iterations] ~expr)
|
||||
end# (now)
|
||||
elapsed# (- end# start#)]
|
||||
(~print-fn (str ~iterations " runs, " elapsed# " msecs, " ~expr-str))))))
|
||||
32
test-resources/lib_tests/portal/e2e.clj
Normal file
32
test-resources/lib_tests/portal/e2e.clj
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
(ns portal.e2e
|
||||
(:require [portal.colors :as c]))
|
||||
|
||||
(defn step [code]
|
||||
(binding [*out* *err*]
|
||||
(println "\n==> Enter to execute:" code "\n"))
|
||||
(read-line)
|
||||
(prn code))
|
||||
|
||||
(def pane-titles '("Alice" "Mad Hatter" "The Cake is a Lie"))
|
||||
|
||||
(defn options []
|
||||
{:portal.colors/theme
|
||||
(rand-nth (keys (dissoc c/themes ::c/vs-code-embedded)))
|
||||
:portal.launcher/window-title
|
||||
(rand-nth pane-titles)})
|
||||
|
||||
(defn -main [& args]
|
||||
(if (= (first args) "web")
|
||||
(step '(require '[portal.web :as p]))
|
||||
(step '(require '[portal.api :as p])))
|
||||
(step `(do (add-tap #'p/submit)
|
||||
(p/open ~(options))))
|
||||
(step '(tap> :hello-world))
|
||||
(step '(p/clear))
|
||||
(step '(require '[examples.data :refer [data]]))
|
||||
(step '(tap> data))
|
||||
(step '(p/clear))
|
||||
(step '(remove-tap #'p/submit))
|
||||
(step '(tap> :hello-world))
|
||||
(step '(p/eval-str "(js/alert 1)"))
|
||||
(step '(p/close)))
|
||||
23
test-resources/lib_tests/portal/jvm_test.clj
Normal file
23
test-resources/lib_tests/portal/jvm_test.clj
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
(ns portal.jvm-test
|
||||
(:require [clojure.test :refer [deftest is]]
|
||||
[portal.api :as p]
|
||||
[portal.runtime.browser :as browser]
|
||||
[portal.runtime.index :as index]
|
||||
[portal.runtime.jvm.client :as client]))
|
||||
|
||||
(defn- headless-chrome-flags [url]
|
||||
["--headless" "--disable-gpu" url])
|
||||
|
||||
(defn- open [f]
|
||||
(with-redefs [browser/flags f] (p/open)))
|
||||
|
||||
(deftest e2e-jvm
|
||||
(reset! index/testing? true)
|
||||
(when-let [portal (open headless-chrome-flags)]
|
||||
(with-redefs [client/timeout 60000]
|
||||
(reset! portal 0)
|
||||
(is (= @portal 0))
|
||||
(swap! portal inc)
|
||||
(is (= @portal 1))))
|
||||
(p/close))
|
||||
|
||||
172
test-resources/lib_tests/portal/runtime/cson_test.cljc
Normal file
172
test-resources/lib_tests/portal/runtime/cson_test.cljc
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
(ns portal.runtime.cson-test
|
||||
(:require [clojure.test :refer [deftest are is]]
|
||||
#?(:clj [clojure.edn :as edn]
|
||||
:cljs [cljs.reader :as edn])
|
||||
[cognitect.transit :as transit]
|
||||
[portal.bench :as b]
|
||||
[portal.runtime.cson :as cson])
|
||||
#?(:clj (:import [java.io ByteArrayOutputStream ByteArrayInputStream]
|
||||
[java.util Date]
|
||||
[java.util UUID])))
|
||||
|
||||
(defn- transit-read [^String string]
|
||||
#?(:clj (-> string
|
||||
.getBytes
|
||||
ByteArrayInputStream.
|
||||
(transit/reader :json)
|
||||
transit/read)
|
||||
:cljs (transit/read (transit/reader :json) string)))
|
||||
|
||||
(defn- transit-write [value]
|
||||
#?(:clj (let [out (ByteArrayOutputStream. 1024)]
|
||||
(transit/write
|
||||
(transit/writer out :json {:transform transit/write-meta})
|
||||
value)
|
||||
(.toString out))
|
||||
:cljs (transit/write
|
||||
(transit/writer :json {:transform transit/write-meta})
|
||||
value)))
|
||||
|
||||
(defn pass [v]
|
||||
(cson/read (cson/write v)))
|
||||
|
||||
(deftest simple-values
|
||||
(are [value]
|
||||
(= value (pass value))
|
||||
nil
|
||||
0
|
||||
1.0
|
||||
#?(:clj 42N
|
||||
:cljs (when (exists? js/BigInt)
|
||||
(js/BigInt "42")))
|
||||
\newline
|
||||
true
|
||||
false
|
||||
'hello
|
||||
'hello/world
|
||||
:hello
|
||||
:hello/world
|
||||
""
|
||||
"hello"
|
||||
"hello/world"))
|
||||
|
||||
(deftest escape-strings
|
||||
(are [value]
|
||||
(= value (pass value))
|
||||
"\n"
|
||||
"\""
|
||||
" \"hello\" "))
|
||||
|
||||
(deftest basic-collections
|
||||
(are [value]
|
||||
(= value (pass value))
|
||||
[]
|
||||
[1 2 3]
|
||||
{}
|
||||
{:a :b}
|
||||
#{}
|
||||
#{1 2 3}
|
||||
'()
|
||||
(list 1 2 3)))
|
||||
|
||||
(def composite-value
|
||||
['hello
|
||||
'hello/world
|
||||
'(1 2 3)
|
||||
""
|
||||
3.14
|
||||
true
|
||||
false
|
||||
#inst "2021-04-07T22:43:59.393-00:00"
|
||||
#uuid "1d80bdbb-ab16-47b2-a8bd-068f94950248"
|
||||
nil
|
||||
1
|
||||
\h
|
||||
"data"
|
||||
{:hello/world :grep}
|
||||
#{1 2 3}])
|
||||
|
||||
(deftest composite-collections
|
||||
(are [value]
|
||||
(= value (pass value))
|
||||
[[[]]]
|
||||
#{#{#{}}}
|
||||
{{} {}}
|
||||
{[] []}
|
||||
{#{} #{}}
|
||||
{(list) (list)}
|
||||
(list [] #{} {})
|
||||
composite-value))
|
||||
|
||||
(deftest special-collections
|
||||
(are [value]
|
||||
(= value (pass value))
|
||||
(range 10)))
|
||||
|
||||
(deftest seq-collections
|
||||
(are [value]
|
||||
(= (seq value) (pass (seq value)))
|
||||
'(0)
|
||||
[0]
|
||||
#{0}
|
||||
{0 0}))
|
||||
|
||||
(def tagged
|
||||
[#?(:clj (Date.)
|
||||
:cljs (js/Date.))
|
||||
#?(:clj (UUID/randomUUID)
|
||||
:cljs (random-uuid))
|
||||
(tagged-literal 'tag :value)])
|
||||
|
||||
(deftest tagged-objects
|
||||
(doseq [value tagged]
|
||||
(is (= value (pass value)))))
|
||||
|
||||
(deftest metadata
|
||||
(doseq [value ['hello {} [] #{}]]
|
||||
(let [m {:my :meta}
|
||||
value (with-meta value m)]
|
||||
(is (= m (meta (pass value)))))))
|
||||
|
||||
(deftest symbol-key-with-meta
|
||||
(let [m {:a :b}
|
||||
value {(with-meta 'k m) 'v}]
|
||||
(is (= value (pass value)))
|
||||
(is (= m (meta (first (keys (pass value))))))))
|
||||
|
||||
(deftest cson-over-edn
|
||||
(is
|
||||
(-> composite-value
|
||||
(cson/write {:stringify pr-str})
|
||||
(cson/read {:parse edn/read-string})
|
||||
(= composite-value))))
|
||||
|
||||
(def n 10000)
|
||||
(def v composite-value)
|
||||
|
||||
(def edn
|
||||
{:parse edn/read-string
|
||||
:stringify pr-str})
|
||||
|
||||
(comment
|
||||
(deftest rich-benchmark
|
||||
(b/simple-benchmark [] (transit-write v) n)
|
||||
(b/simple-benchmark [] (cson/write v edn) n)
|
||||
(b/simple-benchmark [] (cson/write v) n)
|
||||
|
||||
(prn)
|
||||
|
||||
(b/simple-benchmark
|
||||
[v (transit-write v)] (transit-read v) n)
|
||||
(b/simple-benchmark
|
||||
[v (cson/write v edn)] (cson/read v edn) n)
|
||||
(b/simple-benchmark
|
||||
[v (cson/write v)] (cson/read v) n)))
|
||||
|
||||
#?(:clj
|
||||
(deftest java-longs
|
||||
(is (= 1 (byte 1) (pass (byte 1))))
|
||||
(is (= 1 (short 1) (pass (short 1))))
|
||||
(is (= 1 (int 1) (pass (int 1))))
|
||||
(is (= 1 (long 1) (pass (long 1))))
|
||||
(is (= 4611681620380904123 (pass 4611681620380904123)))))
|
||||
21
test-resources/lib_tests/portal/runtime/fs_test.cljc
Normal file
21
test-resources/lib_tests/portal/runtime/fs_test.cljc
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
(ns portal.runtime.fs-test
|
||||
(:require [clojure.test :refer [deftest is]]
|
||||
[portal.runtime.fs :as fs]))
|
||||
|
||||
(deftest fs
|
||||
(is (some? (fs/slurp "deps.edn")))
|
||||
(let [deps (fs/join (fs/cwd) "deps.edn")]
|
||||
(is (= (fs/exists deps) deps)))
|
||||
(is (some? (fs/home)))
|
||||
(is (some? (seq (fs/paths))))
|
||||
(is (contains?
|
||||
(into #{} (fs/list (fs/cwd)))
|
||||
(fs/join (fs/cwd) "deps.edn")))
|
||||
(let [dir (str "target/" (gensym))
|
||||
file (str dir "/" (gensym))]
|
||||
(fs/mkdir dir)
|
||||
(fs/spit file "hello")
|
||||
(is (= (fs/slurp file) "hello"))
|
||||
(fs/rm dir)
|
||||
(is (nil? (fs/exists file)))
|
||||
(is (nil? (fs/exists dir)))))
|
||||
11
test-resources/lib_tests/portal/test_planck.cljs
Normal file
11
test-resources/lib_tests/portal/test_planck.cljs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
(ns portal.test-planck
|
||||
(:require [cljs.test :refer [run-tests]]
|
||||
[planck.core :refer [exit]]
|
||||
[portal.runtime.cson-test]))
|
||||
|
||||
(defmethod cljs.test/report [:cljs.test/default :end-run-tests] [m]
|
||||
(when-not (cljs.test/successful? m)
|
||||
(exit 1)))
|
||||
|
||||
(defn -main []
|
||||
(run-tests 'portal.runtime.cson-test))
|
||||
14
test-resources/lib_tests/portal/test_runner.clj
Normal file
14
test-resources/lib_tests/portal/test_runner.clj
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
(ns portal.test-runner
|
||||
(:require [clojure.test :refer [run-tests]]
|
||||
[portal.jvm-test]
|
||||
[portal.runtime.cson-test]
|
||||
[portal.runtime.fs-test]))
|
||||
|
||||
(defn -main []
|
||||
(let [{:keys [fail error]}
|
||||
(run-tests 'portal.jvm-test
|
||||
'portal.runtime.cson-test
|
||||
'portal.runtime.fs-test)]
|
||||
(shutdown-agents)
|
||||
(System/exit (+ fail error))))
|
||||
|
||||
14
test-resources/lib_tests/portal/test_runner.cljs
Normal file
14
test-resources/lib_tests/portal/test_runner.cljs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
(ns portal.test-runner
|
||||
(:require [cljs.test :refer [run-tests]]
|
||||
[portal.runtime.cson-test]
|
||||
[portal.runtime.fs-test]))
|
||||
|
||||
(defmethod cljs.test/report [:cljs.test/default :end-run-tests] [m]
|
||||
(when-not (cljs.test/successful? m)
|
||||
(.exit js/process 1)))
|
||||
|
||||
(defn -main []
|
||||
(run-tests 'portal.runtime.cson-test
|
||||
'portal.runtime.fs-test))
|
||||
|
||||
(-main)
|
||||
41
test-resources/lib_tests/progrock/core_test.clj
Normal file
41
test-resources/lib_tests/progrock/core_test.clj
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
(ns progrock.core-test
|
||||
(:require [clojure.test :refer :all]
|
||||
[progrock.core :as pr]))
|
||||
|
||||
(deftest test-progress-bar
|
||||
(let [bar (pr/progress-bar 50)]
|
||||
(is (= (:total bar) 50))
|
||||
(is (= (:progress bar) 0))
|
||||
(is (not (:done? bar)))))
|
||||
|
||||
(deftest test-tick
|
||||
(let [bar (pr/progress-bar 50)]
|
||||
(is (= (-> bar pr/tick :progress) 1))
|
||||
(is (= (-> bar (pr/tick 16) :progress) 16))
|
||||
(is (= (-> bar (pr/tick 5) pr/tick :progress) 6))))
|
||||
|
||||
(deftest test-done
|
||||
(let [bar (pr/progress-bar 50)]
|
||||
(is (-> bar pr/done :done?))))
|
||||
|
||||
(deftest test-render
|
||||
(let [bar (pr/progress-bar 50)]
|
||||
(is (= (pr/render bar)
|
||||
" 0/50 0% [ ] ETA: --:--"))
|
||||
(is (= (pr/render (pr/tick bar 25))
|
||||
"25/50 50% [========================= ] ETA: 00:00"))
|
||||
(is (= (pr/render (pr/tick bar 25) {:format "(:bar)", :length 10})
|
||||
"(===== )"))
|
||||
(is (= (pr/render (pr/tick bar 25) {:format "[:bar]", :complete \#, :incomplete \-})
|
||||
"[#########################-------------------------]"))
|
||||
(is (= (pr/render (pr/progress-bar 0))
|
||||
"0/0 0% [ ] ETA: --:--"))))
|
||||
|
||||
(deftest test-print
|
||||
(let [bar (pr/progress-bar 50)]
|
||||
(is (= (with-out-str (pr/print bar))
|
||||
"\r 0/50 0% [ ] ETA: --:--"))
|
||||
(is (= (with-out-str (pr/print bar {:length 10}))
|
||||
"\r 0/50 0% [ ] ETA: --:--"))
|
||||
(is (= (with-out-str (pr/print (pr/done bar) {:length 10}))
|
||||
"\r 0/50 0% [ ] ETA: --:--\n"))))
|
||||
133
test-resources/lib_tests/testdoc/core_test.clj
Normal file
133
test-resources/lib_tests/testdoc/core_test.clj
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
(ns testdoc.core-test
|
||||
(:require
|
||||
[clojure.java.io :as io]
|
||||
[clojure.test :as t]
|
||||
[testdoc.core :as sut]))
|
||||
|
||||
(defn- repl-styled-success-test-func
|
||||
"foo bar
|
||||
|
||||
=> (+ 1 2 3)
|
||||
6
|
||||
=> (+ 1 2
|
||||
=> 3 4)
|
||||
10
|
||||
=> *1
|
||||
10
|
||||
=> (inc *1)
|
||||
11"
|
||||
[])
|
||||
|
||||
(defn- code-first-styled-success-test-func
|
||||
"foo bar
|
||||
|
||||
(+ 1 2 3)
|
||||
;; => 6
|
||||
|
||||
(+ 1 2
|
||||
3 4)
|
||||
;; => 10
|
||||
*1
|
||||
;; => 10
|
||||
(inc *1)
|
||||
;; => 11"
|
||||
[])
|
||||
|
||||
(defn- repl-styled-partial-success-test-func
|
||||
"foo bar
|
||||
|
||||
=> (+ 1 2 3)
|
||||
6
|
||||
=> (+ 1 2 3 4)
|
||||
999"
|
||||
[])
|
||||
|
||||
(defn- code-first-styled-partial-success-test-func
|
||||
"foo bar
|
||||
|
||||
(+ 1 2 3)
|
||||
;; => 6
|
||||
(+ 1 2 3 4)
|
||||
;; => 999"
|
||||
[])
|
||||
|
||||
(t/deftest testdoc-test
|
||||
(t/testing "repl style"
|
||||
(t/is (= [{:type :pass :expected 6 :actual 6}
|
||||
{:type :pass :expected 10 :actual 10}
|
||||
{:type :pass :expected 10 :actual 10}
|
||||
{:type :pass :expected 11 :actual 11}]
|
||||
(->> (sut/testdoc nil #'repl-styled-success-test-func)
|
||||
(map #(select-keys % [:type :expected :actual]))
|
||||
(sort-by :expected))))
|
||||
|
||||
(t/is (= [{:type :pass :expected 6 :actual 6}
|
||||
{:type :fail :expected 999 :actual 10}]
|
||||
(->> (sut/testdoc nil #'repl-styled-partial-success-test-func)
|
||||
(map #(select-keys % [:type :expected :actual]))
|
||||
(sort-by :expected)))))
|
||||
|
||||
(t/testing "code-first style"
|
||||
(t/is (= [{:type :pass :expected 6 :actual 6}
|
||||
{:type :pass :expected 10 :actual 10}
|
||||
{:type :pass :expected 10 :actual 10}
|
||||
{:type :pass :expected 11 :actual 11}]
|
||||
(->> (sut/testdoc nil #'code-first-styled-success-test-func)
|
||||
(map #(select-keys % [:type :expected :actual]))
|
||||
(sort-by :expected))))
|
||||
|
||||
(t/is (= [{:type :pass :expected 6 :actual 6}
|
||||
{:type :fail :expected 999 :actual 10}]
|
||||
(->> (sut/testdoc nil #'code-first-styled-partial-success-test-func)
|
||||
(map #(select-keys % [:type :expected :actual]))
|
||||
(sort-by :expected))))))
|
||||
|
||||
(t/deftest testdoc-unsupported-test
|
||||
(let [[result :as results] (sut/testdoc nil 123)]
|
||||
(t/is (= 1 (count results)))
|
||||
(t/is (= :fail (:type result)))
|
||||
(t/is (re-seq #"^Unsupported document:" (:message result)))))
|
||||
|
||||
(defn plus
|
||||
"Add a and b
|
||||
|
||||
=> (plus 1 2)
|
||||
3
|
||||
=> (plus 2
|
||||
=> 3)
|
||||
5"
|
||||
[a b]
|
||||
(+ a b))
|
||||
|
||||
(t/deftest plus-test
|
||||
(t/is (testdoc #'plus)))
|
||||
|
||||
(t/deftest plus-string-test
|
||||
(t/is (testdoc "=> (require '[testdoc.core-test :as ct])
|
||||
nil
|
||||
=> (ct/plus 1 2)
|
||||
3
|
||||
=> (ct/plus 2
|
||||
=> 3)
|
||||
5")))
|
||||
|
||||
(t/deftest nil-value-test
|
||||
(t/is (= [{:type :fail :message "(= 1 nil)" :expected nil :actual 1}]
|
||||
(sut/testdoc nil "=> 1
|
||||
nil"))))
|
||||
|
||||
(t/deftest unresolved-symbol-test
|
||||
(let [[err :as res] (sut/testdoc nil "
|
||||
=> (unresolved-fn 10)
|
||||
11")]
|
||||
(t/is (= 1 (count res)))
|
||||
(t/is (= :fail (:type err)))
|
||||
(t/is (every? #(some? (get err %)) [:type :message :expected :actual]))
|
||||
(t/is (= "(= (unresolved-fn 10) 11), [line: 2]" (:message err)))))
|
||||
|
||||
(t/deftest debug-test
|
||||
(with-out-str
|
||||
(t/is (testdoc #'sut/debug))))
|
||||
|
||||
(t/deftest README-test
|
||||
(t/is (testdoc (slurp (io/file "README.md")))))
|
||||
26
test-resources/lib_tests/testdoc/style/code_first_test.clj
Normal file
26
test-resources/lib_tests/testdoc/style/code_first_test.clj
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
(ns testdoc.style.code-first-test
|
||||
(:require
|
||||
[clojure.string :as str]
|
||||
[clojure.test :as t]
|
||||
[testdoc.style.code-first :as sut]))
|
||||
|
||||
(defn- lines
|
||||
[ls]
|
||||
(str/join "\n" ls))
|
||||
|
||||
(t/deftest parse-doc-test
|
||||
(t/are [expected in] (= expected (sut/parse-doc (lines in)))
|
||||
'[[a b]], ["a" ";; => b"]
|
||||
'[[(a b) c]], ["(a" "b)" ";; => c"]
|
||||
'[[(a b) c]], ["head" "(a" "b)" ";; => c"]
|
||||
'[[a b] [c d]], ["a" ";; => b" "c" ";; => d"]
|
||||
'[], ["a"]
|
||||
'[[a b]], ["a" ";; => b" "c"]
|
||||
'[[a b]], ["a" ";; => b" ";; => c"]
|
||||
'[[a (b c)]], ["a" ";; => [b" ";; => c]"]))
|
||||
|
||||
(t/deftest parse-doc-with-meta-test
|
||||
(let [ret (sut/parse-doc (lines ["" "a" ";; => 6" "c" ";; => :d"]))]
|
||||
(t/is (= '[[a 6] [c :d]] ret))
|
||||
(t/is (= 2 (-> ret first meta :testdoc.string/line)))
|
||||
(t/is (= 4 (-> ret second meta :testdoc.string/line)))))
|
||||
25
test-resources/lib_tests/testdoc/style/repl_test.clj
Normal file
25
test-resources/lib_tests/testdoc/style/repl_test.clj
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
(ns testdoc.style.repl-test
|
||||
(:require
|
||||
[clojure.string :as str]
|
||||
[clojure.test :as t]
|
||||
[testdoc.style.repl :as sut]))
|
||||
|
||||
(defn- lines
|
||||
[ls]
|
||||
(str/join "\n" ls))
|
||||
|
||||
(t/deftest parse-doc-test
|
||||
(t/are [expected in] (= expected (sut/parse-doc (lines in)))
|
||||
'[[a b]], ["=> a" "b"]
|
||||
'[[(a b) c]], ["=> (a" "=> b)" "c"]
|
||||
'[[a b] [c d]], ["=> a" "b" "=> c" "d"]
|
||||
'[], ["=> a"]
|
||||
'[[a b]], ["=> a" "b" "=> c"]
|
||||
'[[a b]], ["=> a" "b" "c"]
|
||||
'[[a (b c)]], ["=> a" "[b" "c]"]))
|
||||
|
||||
(t/deftest parse-doc-with-meta-test
|
||||
(let [ret (sut/parse-doc (lines ["" "=> a" "6" "=> c" ":d"]))]
|
||||
(t/is (= '[[a 6] [c :d]] ret))
|
||||
(t/is (= 2 (-> ret first meta :testdoc.string/line)))
|
||||
(t/is (= 4 (-> ret second meta :testdoc.string/line)))))
|
||||
Loading…
Reference in a new issue