Configure clojure.spec, add a few specs (#23)
Creates specs for init, create, and init-network
This commit is contained in:
parent
36f3820f4f
commit
c0c08b2e26
9 changed files with 216 additions and 100 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -11,3 +11,4 @@ pom.xml.asc
|
|||
.hgignore
|
||||
.hg/
|
||||
.DS_Store
|
||||
.lsp
|
||||
|
|
|
|||
14
dev-src/user.clj
Normal file
14
dev-src/user.clj
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
(ns user
|
||||
(:require
|
||||
[clojure.spec.alpha :as s]
|
||||
[expound.alpha :as ea]
|
||||
[kaocha.repl]))
|
||||
|
||||
(try
|
||||
;; Attempt to set *explain-out*, assuming that we're inside of
|
||||
;; a binding context...
|
||||
(set! s/*explain-out* ea/printer)
|
||||
|
||||
(catch IllegalStateException _
|
||||
;; ...if not, just alter the root binding.
|
||||
(alter-var-root #'s/*explain-out* (constantly ea/printer))))
|
||||
14
project.clj
14
project.clj
|
|
@ -14,14 +14,18 @@
|
|||
|
||||
:plugins [[jainsahab/lein-githooks "1.0.0"]]
|
||||
|
||||
:profiles {:dev {:dependencies [[org.testcontainers/postgresql "1.14.3"]
|
||||
[lambdaisland/kaocha-cloverage "1.0-45"]
|
||||
:profiles {:dev {:dependencies [[expound "0.8.5"]
|
||||
[lambdaisland/kaocha "1.0.641"]
|
||||
[lambdaisland/kaocha-cloverage "1.0-45"]
|
||||
[lambdaisland/kaocha-junit-xml "0.0.76"]
|
||||
[mvxcvi/cljstyle "0.13.0" :exclusions [org.clojure/clojure]]]
|
||||
[lambdaisland/kaocha-junit-xml "0.0.76"]
|
||||
[mvxcvi/cljstyle "0.13.0" :exclusions [org.clojure/clojure]]
|
||||
[org.clojure/test.check "1.1.0"]
|
||||
[org.clojure/tools.namespace "1.0.0"]
|
||||
[org.testcontainers/postgresql "1.14.3"]]
|
||||
:githooks {:auto-install true
|
||||
:ci-env-variable "CI"
|
||||
:pre-commit ["script/pre-commit"]}}}
|
||||
:pre-commit ["script/pre-commit"]}
|
||||
:source-paths ["dev-src"]}}
|
||||
|
||||
:target-path "target/%s")
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
(ns clj-test-containers.core
|
||||
(:require
|
||||
[clj-test-containers.spec.container :as csc]
|
||||
[clj-test-containers.spec.core :as cs]
|
||||
[clojure.spec.alpha :as s])
|
||||
(:import
|
||||
(java.nio.file
|
||||
|
|
@ -19,6 +21,10 @@
|
|||
BindMode/READ_WRITE
|
||||
BindMode/READ_ONLY))
|
||||
|
||||
(s/fdef init
|
||||
:args (s/cat :init-options ::cs/init-options)
|
||||
:ret ::cs/container)
|
||||
|
||||
(defn init
|
||||
"Sets the properties for a testcontainer instance"
|
||||
[{:keys [container exposed-ports env-vars command network network-aliases]}]
|
||||
|
|
@ -42,6 +48,10 @@
|
|||
:host (.getHost container)
|
||||
:network network})
|
||||
|
||||
(s/fdef create
|
||||
:args (s/cat :create-options ::cs/create-options)
|
||||
:ret ::cs/container)
|
||||
|
||||
(defn create
|
||||
"Creates a generic testcontainer and sets its properties"
|
||||
[{:keys [image-name] :as options}]
|
||||
|
|
@ -122,26 +132,27 @@
|
|||
(dissoc :id)
|
||||
(dissoc :mapped-ports)))
|
||||
|
||||
(defn- build-network
|
||||
[{:keys [ipv6 driver]}]
|
||||
(let [builder (Network/builder)]
|
||||
(s/fdef init-network
|
||||
:args (s/alt :nullary (s/cat)
|
||||
:unary (s/cat :init-network-options
|
||||
::cs/init-network-options))
|
||||
:ret ::cs/network)
|
||||
|
||||
(when ipv6
|
||||
(.enableIpv6 builder true))
|
||||
|
||||
(when driver
|
||||
(.driver builder driver))
|
||||
|
||||
(let [network (.build builder)]
|
||||
{:network network
|
||||
:id (.getId network)
|
||||
:name (.getName network)
|
||||
:ipv6 (.getEnableIpv6 network)
|
||||
:driver (.getDriver network)})))
|
||||
|
||||
(defn init-network
|
||||
(defn ^:no-gen init-network
|
||||
"Creates a network. The optional map accepts config values for enabling ipv6 and setting the driver"
|
||||
([]
|
||||
(build-network {}))
|
||||
([options]
|
||||
(build-network options)))
|
||||
(init-network {}))
|
||||
([{:keys [ipv6 driver]}]
|
||||
(let [builder (Network/builder)]
|
||||
(when ipv6
|
||||
(.enableIpv6 builder true))
|
||||
|
||||
(when driver
|
||||
(.driver builder driver))
|
||||
|
||||
(let [network (.build builder)]
|
||||
{:network network
|
||||
:id (.getId network)
|
||||
:name (.getName network)
|
||||
:ipv6 (.getEnableIpv6 network)
|
||||
:driver (.getDriver network)}))))
|
||||
|
|
|
|||
27
src/clj_test_containers/spec/container.clj
Normal file
27
src/clj_test_containers/spec/container.clj
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
(ns clj-test-containers.spec.container
|
||||
(:require
|
||||
[clojure.spec.alpha :as s]
|
||||
[clojure.spec.gen.alpha :as gen])
|
||||
(:import
|
||||
(org.testcontainers.containers
|
||||
GenericContainer)))
|
||||
|
||||
(s/def ::container
|
||||
(s/with-gen #(instance? GenericContainer %)
|
||||
#(gen/fmap (fn [image-name] (GenericContainer. image-name))
|
||||
(gen/string-alphanumeric))))
|
||||
|
||||
(s/def ::exposed-ports
|
||||
(s/coll-of (s/int-in 1 65535)))
|
||||
|
||||
(s/def ::env-vars
|
||||
(s/map-of string? string?))
|
||||
|
||||
(s/def ::command
|
||||
(s/coll-of string?))
|
||||
|
||||
(s/def ::network-aliases
|
||||
(s/coll-of string?))
|
||||
|
||||
(s/def ::image-name
|
||||
string?)
|
||||
39
src/clj_test_containers/spec/core.clj
Normal file
39
src/clj_test_containers/spec/core.clj
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
(ns clj-test-containers.spec.core
|
||||
(:require
|
||||
[clj-test-containers.spec.container :as csc]
|
||||
[clj-test-containers.spec.network :as csn]
|
||||
[clojure.spec.alpha :as s]))
|
||||
|
||||
(s/def ::network
|
||||
(s/nilable (s/keys :req-un [::csn/network
|
||||
::csn/id
|
||||
::csn/name
|
||||
::csn/ipv6
|
||||
::csn/driver])))
|
||||
|
||||
(s/def ::container
|
||||
(s/keys :req-un [::csc/container
|
||||
::csc/exposed-ports
|
||||
::csc/env-vars
|
||||
::csc/host]
|
||||
:opt-un [::network]))
|
||||
|
||||
(s/def ::init-options
|
||||
(s/keys :req-un [::csc/container]
|
||||
:opt-un [::csc/exposed-ports
|
||||
::csc/env-vars
|
||||
::csc/command
|
||||
::network
|
||||
::csc/network-aliases]))
|
||||
|
||||
(s/def ::create-options
|
||||
(s/keys :req-un [::csc/image-name]
|
||||
:opt-un [::csc/exposed-ports
|
||||
::csc/env-vars
|
||||
::csc/command
|
||||
::network
|
||||
::csc/network-aliases]))
|
||||
|
||||
(s/def ::init-network-options
|
||||
(s/keys :opt-un [::csn/ipv6
|
||||
::csn/driver]))
|
||||
22
src/clj_test_containers/spec/network.clj
Normal file
22
src/clj_test_containers/spec/network.clj
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
(ns clj-test-containers.spec.network
|
||||
(:require
|
||||
[clojure.spec.alpha :as s])
|
||||
(:import
|
||||
(org.testcontainers.containers
|
||||
Network)))
|
||||
|
||||
(s/def ::id
|
||||
string?)
|
||||
|
||||
(s/def ::ipv6
|
||||
(s/nilable boolean?))
|
||||
|
||||
(s/def ::driver
|
||||
(s/nilable string?))
|
||||
|
||||
(s/def ::name
|
||||
string?)
|
||||
|
||||
(s/def ::network
|
||||
(s/with-gen #(instance? Network %)
|
||||
#(s/gen #{(Network/newNetwork)})))
|
||||
|
|
@ -1,19 +1,18 @@
|
|||
(ns clj-test-containers.core-test
|
||||
(:require
|
||||
[clj-test-containers.core :refer :all]
|
||||
[clojure.test :refer :all])
|
||||
[clj-test-containers.core :as sut]
|
||||
[clojure.test :refer [deftest is testing]])
|
||||
(:import
|
||||
(org.testcontainers.containers
|
||||
PostgreSQLContainer)))
|
||||
|
||||
(deftest create-test
|
||||
(testing "Testing basic testcontainer generic image initialisation"
|
||||
|
||||
(let [container (create {:image-name "postgres:12.2"
|
||||
:exposed-ports [5432]
|
||||
:env-vars {"POSTGRES_PASSWORD" "pw"}})
|
||||
initialized-container (start! container)
|
||||
stopped-container (stop! container)]
|
||||
(let [container (sut/create {:image-name "postgres:12.2"
|
||||
:exposed-ports [5432]
|
||||
:env-vars {"POSTGRES_PASSWORD" "pw"}})
|
||||
initialized-container (sut/start! container)
|
||||
stopped-container (sut/stop! container)]
|
||||
(is (some? (:id initialized-container)))
|
||||
(is (some? (:mapped-ports initialized-container)))
|
||||
(is (some? (get (:mapped-ports initialized-container) 5432)))
|
||||
|
|
@ -21,10 +20,10 @@
|
|||
(is (nil? (:mapped-ports stopped-container)))))
|
||||
|
||||
(testing "Testing basic testcontainer image creation from docker file"
|
||||
(let [container (create-from-docker-file {:exposed-ports [80]
|
||||
:docker-file "test/resources/Dockerfile"})
|
||||
initialized-container (start! container)
|
||||
stopped-container (stop! container)]
|
||||
(let [container (sut/create-from-docker-file {:exposed-ports [80]
|
||||
:docker-file "test/resources/Dockerfile"})
|
||||
initialized-container (sut/start! container)
|
||||
stopped-container (sut/stop! container)]
|
||||
(is (some? (:id initialized-container)))
|
||||
(is (some? (:mapped-ports initialized-container)))
|
||||
(is (some? (get (:mapped-ports initialized-container) 80)))
|
||||
|
|
@ -33,37 +32,37 @@
|
|||
|
||||
|
||||
(testing "Executing a command in the running Docker container with a custom container"
|
||||
(let [container (init {:container (PostgreSQLContainer. "postgres:12.2")})
|
||||
initialized-container (start! container)
|
||||
result (execute-command! initialized-container ["whoami"])
|
||||
stopped-container (stop! container)]
|
||||
(let [container (sut/init {:container (PostgreSQLContainer. "postgres:12.2")})
|
||||
initialized-container (sut/start! container)
|
||||
result (sut/execute-command! initialized-container ["whoami"])
|
||||
_stopped-container (sut/stop! container)]
|
||||
(is (= 0 (:exit-code result)))
|
||||
(is (= "root\n" (:stdout result))))))
|
||||
|
||||
(deftest execute-command-in-container
|
||||
|
||||
(testing "Executing a command in the running Docker container"
|
||||
(let [container (create {:image-name "postgres:12.2"
|
||||
:exposed-ports [5432]
|
||||
:env-vars {"POSTGRES_PASSWORD" "pw"}})
|
||||
initialized-container (start! container)
|
||||
result (execute-command! initialized-container ["whoami"])
|
||||
stopped-container (stop! container)]
|
||||
(let [container (sut/create {:image-name "postgres:12.2"
|
||||
:exposed-ports [5432]
|
||||
:env-vars {"POSTGRES_PASSWORD" "pw"}})
|
||||
initialized-container (sut/start! container)
|
||||
result (sut/execute-command! initialized-container ["whoami"])
|
||||
_stopped-container (sut/stop! container)]
|
||||
(is (= 0 (:exit-code result)))
|
||||
(is (= "root\n" (:stdout result))))))
|
||||
|
||||
(deftest init-volume-test
|
||||
|
||||
(testing "Testing mapping of a classpath resource"
|
||||
(let [container (-> (create {:image-name "postgres:12.2"
|
||||
:exposed-ports [5432]
|
||||
:env-vars {"POSTGRES_PASSWORD" "pw"}})
|
||||
(map-classpath-resource! {:resource-path "test.sql"
|
||||
:container-path "/opt/test.sql"
|
||||
:mode :read-only}))
|
||||
initialized-container (start! container)
|
||||
file-check (execute-command! initialized-container ["tail" "/opt/test.sql"])
|
||||
stopped-container (stop! container)]
|
||||
(let [container (-> (sut/create {:image-name "postgres:12.2"
|
||||
:exposed-ports [5432]
|
||||
:env-vars {"POSTGRES_PASSWORD" "pw"}})
|
||||
(sut/map-classpath-resource! {:resource-path "test.sql"
|
||||
:container-path "/opt/test.sql"
|
||||
:mode :read-only}))
|
||||
initialized-container (sut/start! container)
|
||||
file-check (sut/execute-command! initialized-container ["tail" "/opt/test.sql"])
|
||||
stopped-container (sut/stop! container)]
|
||||
(is (some? (:id initialized-container)))
|
||||
(is (some? (:mapped-ports initialized-container)))
|
||||
(is (some? (get (:mapped-ports initialized-container) 5432)))
|
||||
|
|
@ -72,15 +71,15 @@
|
|||
(is (nil? (:mapped-ports stopped-container)))))
|
||||
|
||||
(testing "Testing mapping of a filesystem-binding"
|
||||
(let [container (-> (create {:image-name "postgres:12.2"
|
||||
:exposed-ports [5432]
|
||||
:env-vars {"POSTGRES_PASSWORD" "pw"}})
|
||||
(bind-filesystem! {:host-path "."
|
||||
:container-path "/opt"
|
||||
:mode :read-only}))
|
||||
initialized-container (start! container)
|
||||
file-check (execute-command! initialized-container ["tail" "/opt/README.md"])
|
||||
stopped-container (stop! container)]
|
||||
(let [container (-> (sut/create {:image-name "postgres:12.2"
|
||||
:exposed-ports [5432]
|
||||
:env-vars {"POSTGRES_PASSWORD" "pw"}})
|
||||
(sut/bind-filesystem! {:host-path "."
|
||||
:container-path "/opt"
|
||||
:mode :read-only}))
|
||||
initialized-container (sut/start! container)
|
||||
file-check (sut/execute-command! initialized-container ["tail" "/opt/README.md"])
|
||||
stopped-container (sut/stop! container)]
|
||||
(is (some? (:id initialized-container)))
|
||||
(is (some? (:mapped-ports initialized-container)))
|
||||
(is (some? (get (:mapped-ports initialized-container) 5432)))
|
||||
|
|
@ -89,15 +88,15 @@
|
|||
(is (nil? (:mapped-ports stopped-container)))))
|
||||
|
||||
(testing "Copying a file from the host into the container"
|
||||
(let [container (-> (create {:image-name "postgres:12.2"
|
||||
:exposed-ports [5432]
|
||||
:env-vars {"POSTGRES_PASSWORD" "pw"}})
|
||||
(copy-file-to-container! {:path "test.sql"
|
||||
:container-path "/opt/test.sql"
|
||||
:type :host-path}))
|
||||
initialized-container (start! container)
|
||||
file-check (execute-command! initialized-container ["tail" "/opt/test.sql"])
|
||||
stopped-container (stop! container)]
|
||||
(let [container (-> (sut/create {:image-name "postgres:12.2"
|
||||
:exposed-ports [5432]
|
||||
:env-vars {"POSTGRES_PASSWORD" "pw"}})
|
||||
(sut/copy-file-to-container! {:path "test.sql"
|
||||
:container-path "/opt/test.sql"
|
||||
:type :host-path}))
|
||||
initialized-container (sut/start! container)
|
||||
file-check (sut/execute-command! initialized-container ["tail" "/opt/test.sql"])
|
||||
stopped-container (sut/stop! container)]
|
||||
(is (some? (:id initialized-container)))
|
||||
(is (some? (:mapped-ports initialized-container)))
|
||||
(is (some? (get (:mapped-ports initialized-container) 5432)))
|
||||
|
|
@ -106,15 +105,15 @@
|
|||
(is (nil? (:mapped-ports stopped-container)))))
|
||||
|
||||
(testing "Copying a file from the classpath into the container"
|
||||
(let [container (-> (create {:image-name "postgres:12.2"
|
||||
:exposed-ports [5432]
|
||||
:env-vars {"POSTGRES_PASSWORD" "pw"}})
|
||||
(copy-file-to-container! {:path "test.sql"
|
||||
:container-path "/opt/test.sql"
|
||||
:type :classpath-resource}))
|
||||
initialized-container (start! container)
|
||||
file-check (execute-command! initialized-container ["tail" "/opt/test.sql"])
|
||||
stopped-container (stop! container)]
|
||||
(let [container (-> (sut/create {:image-name "postgres:12.2"
|
||||
:exposed-ports [5432]
|
||||
:env-vars {"POSTGRES_PASSWORD" "pw"}})
|
||||
(sut/copy-file-to-container! {:path "test.sql"
|
||||
:container-path "/opt/test.sql"
|
||||
:type :classpath-resource}))
|
||||
initialized-container (sut/start! container)
|
||||
file-check (sut/execute-command! initialized-container ["tail" "/opt/test.sql"])
|
||||
stopped-container (sut/stop! container)]
|
||||
(is (some? (:id initialized-container)))
|
||||
(is (some? (:mapped-ports initialized-container)))
|
||||
(is (some? (get (:mapped-ports initialized-container) 5432)))
|
||||
|
|
@ -123,23 +122,21 @@
|
|||
(is (nil? (:mapped-ports stopped-container))))))
|
||||
|
||||
(deftest networking-test
|
||||
|
||||
(testing "Putting two containers into the same network and check their communication"
|
||||
(let [network (init-network)
|
||||
server-container (create {:image-name "alpine:3.5"
|
||||
:network network
|
||||
:network-aliases ["foo"]
|
||||
:command ["/bin/sh"
|
||||
"-c"
|
||||
"while true ; do printf 'HTTP/1.1 200 OK\\n\\nyay' | nc -l -p 8080; done"]})
|
||||
client-container (create {:image-name "alpine:3.5"
|
||||
:network network
|
||||
:command ["top"]})
|
||||
started-server (start! server-container)
|
||||
started-client (start! client-container)
|
||||
response (execute-command! started-client ["wget", "-O", "-", "http://foo:8080"])
|
||||
stopped-server (stop! started-server)
|
||||
stopped-client (stop! started-client)]
|
||||
|
||||
(let [network (sut/init-network)
|
||||
server-container (sut/create {:image-name "alpine:3.5"
|
||||
:network network
|
||||
:network-aliases ["foo"]
|
||||
:command ["/bin/sh"
|
||||
"-c"
|
||||
"while true ; do printf 'HTTP/1.1 200 OK\\n\\nyay' | nc -l -p 8080; done"]})
|
||||
client-container (sut/create {:image-name "alpine:3.5"
|
||||
:network network
|
||||
:command ["top"]})
|
||||
started-server (sut/start! server-container)
|
||||
started-client (sut/start! client-container)
|
||||
response (sut/execute-command! started-client ["wget", "-O", "-", "http://foo:8080"])
|
||||
_stopped-server (sut/stop! started-server)
|
||||
_stopped-client (sut/stop! started-client)]
|
||||
(is (= 0 (:exit-code response)))
|
||||
(is (= "yay" (:stdout response))))))
|
||||
|
|
|
|||
|
|
@ -2,4 +2,5 @@
|
|||
{:plugins [:kaocha.plugin/junit-xml
|
||||
:kaocha.plugin/cloverage
|
||||
:kaocha.plugin.alpha/spec-test-check]
|
||||
:reporter [kaocha.report/documentation]
|
||||
:kaocha.plugin.junit-xml/target-file "target/junit.xml"}
|
||||
|
|
|
|||
Loading…
Reference in a new issue