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:
Gabriel Horner 2021-12-28 01:56:36 -05:00
parent 23699de359
commit 78a05139cb
41 changed files with 6870 additions and 45 deletions

View file

@ -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

View file

@ -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

View file

@ -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

1 maven-name git-url
4 babashka/babashka.curl https://github.com/babashka/babashka.curl
5 better-cond/better-cond https://github.com/Engelberg/better-cond
6 borkdude/deps https://github.com/borkdude/deps.clj
7 borkdude/missing.test.assertions https://github.com/borkdude/missing.test.assertions
8 borkdude/rewrite-edn https://github.com/borkdude/rewrite-edn
9 camel-snake-kebab/camel-snake-kebab https://github.com/clj-commons/camel-snake-kebab
10 circleci/bond https://github.com/circleci/bond
11 clj-commons/clj-yaml https://github.com/clj-commons/clj-yaml
12 clj-commons/multigrep https://github.com/clj-commons/multigrep
13 clojure-csv/clojure-csv https://github.com/davidsantiago/clojure-csv
14 clojure-term-colors/clojure-term-colors https://github.com/trhura/clojure-term-colors
15 com.github.seancorfield/honeysql https://github.com/seancorfield/honeysql
16 com.grammarly/omniconf https://github.com/grammarly/omniconf
17 com.stuartsierra/component https://github.com/stuartsierra/component
19 comb/comb https://github.com/weavejester/comb
20 cprop/cprop https://github.com/tolitius/cprop
21 crispin/crispin https://github.com/dunaj-project/crispin
22 dev.nubank/docopt https://github.com/nubank/docopt.clj
23 djblue/portal https://github.com/djblue/portal
24 doric/doric https://github.com/joegallo/doric
25 douglass/clj-psql https://github.com/DarinDouglass/clj-psql
26 environ/environ https://github.com/weavejester/environ
27 exoscale/coax https://github.com/exoscale/coax
28 expound/expound https://github.com/bhb/expound
29 failjure/failjure https://github.com/adambard/failjure
30 ffclj/ffclj https://github.com/luissantos/ffclj
31 gaka/gaka https://github.com/cdaddr/gaka
32 hato/hato https://github.com/gnarroway/hato
33 henryw374/cljc.java-time https://github.com/henryw374/cljc.java-time
34 hiccup/hiccup http://github.com/weavejester/hiccup
35 honeysql/honeysql https://github.com/seancorfield/honeysql
36 http-kit/http-kit https://github.com/http-kit/http-kit
37 io.aviso/pretty https://github.com/AvisoNovate/pretty
38 io.github.cognitect-labs/test-runner https://github.com/cognitect-labs/test-runner
39 io.github.technomancy/limit-break https://github.com/technomancy/limit-break
40 io.helins/binf https://github.com/helins/binf.cljc
41 io.replikativ/hasch https://github.com/replikativ/hasch
42 java-http-clj/java-http-clj http://www.github.com/schmee/java-http-clj
51 org.clj-commons/clj-http-lite https://github.com/clj-commons/clj-http-lite
52 org.clj-commons/digest https://github.com/clj-commons/clj-digest
53 org.clojars.askonomm/ruuter https://github.com/askonomm/ruuter
54 org.clojars.lispyclouds/contajners https://github.com/lispyclouds/contajners
55 org.clojure/core.match https://github.com/clojure/core.match
56 org.clojure/data.csv https://github.com/clojure/data.csv
57 org.clojure/data.generators https://github.com/clojure/data.generators
61 org.clojure/test.check https://github.com/clojure/test.check
62 org.clojure/tools.gitlibs https://github.com/clojure/tools.gitlibs
63 org.clojure/tools.namespace https://github.com/babashka/tools.namespace
64 progrock/progrock https://github.com/weavejester/progrock
65 reifyhealth/specmonstah https://github.com/reifyhealth/specmonstah
66 rewrite-clj/rewrite-clj https://github.com/clj-commons/rewrite-clj
67 rm-hull/jasentaa https://github.com/rm-hull/jasentaa
68 selmer/selmer https://github.com/yogthos/Selmer
69 slingshot/slingshot https://github.com/scgilardi/slingshot
70 table/table https://github.com/cldwalker/table
71 testdoc/testdoc https://github.com/liquidz/testdoc
72 version-clj/version-clj https://github.com/xsc/version-clj

View file

@ -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)*"

View file

@ -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"

View file

@ -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"}}

View 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))))))

View 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."))))

View file

@ -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)))))

View file

@ -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)))

View 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]))

View 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}}))))

View 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")))))

View 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")))

View 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}

File diff suppressed because it is too large Load diff

View 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))))))

View 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))))))

View 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}))))))))

View 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])))))

View 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?)))))

View 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)))))

View 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"))))

View 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))

View 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))

View 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)))
))

View 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}))))))

View 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)))

View 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})

View 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))))))

View 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)))

View 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))

View 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)))))

View 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)))))

View 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))

View 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))))

View 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)

View 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"))))

View 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")))))

View 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)))))

View 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)))))