Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tighten up the test-machine specs #231

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/jackdaw/test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
kafka cluster shared with other users."
(:require
[clojure.tools.logging :as log]
[clojure.spec.alpha :as s]
[jackdaw.streams :as k]
[jackdaw.test.commands :refer [with-handler command-handler]]
[jackdaw.test.commands.base]
Expand Down Expand Up @@ -64,6 +65,7 @@
;; resources when the test machine is closed.

(def +default-executor+ (-> (fn [machine cmd]
(s/assert :jackdaw.test.commands/test-event cmd)
((:command-handler machine) machine cmd))
with-status
with-timing
Expand Down
75 changes: 66 additions & 9 deletions src/jackdaw/test/commands.clj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[jackdaw.test.commands.base :as base]
[jackdaw.test.commands.write :as write]
[jackdaw.test.commands.watch :as watch])
(:refer-clojure :exclude [do]))
(:refer-clojure :exclude [do println pprint inspect]))

(def base-commands base/command-map)
(def write-command write/command-map)
Expand Down Expand Up @@ -42,11 +42,55 @@

;; Test Command API

(defmulti test-event first)

(s/def ::topic-id (s/or :keyword keyword?
:string string?))
(s/def ::timeout int?)
(s/def ::key any?)
(s/def ::key-fn ifn?)
(s/def ::partition int?)
(s/def ::partition-fn ifn?)
(s/def ::info string?)
(s/def ::test-message any?)
(s/def ::write-options map?)
(s/def ::watch-options map?)
(s/def ::write-options (s/keys :opt-un [::key ::key-fn ::partition ::partition-fn]))
(s/def ::watch-options (s/keys :opt-un [::timeout ::info]))
(s/def ::test-event (s/multi-spec test-event first))

(defmethod test-event :do [_] (s/cat :op #{:do}
:do-fn ifn?))

(defmethod test-event :do! [_] (s/cat :op #{:do!}
:do-fn ifn?))

(defmethod test-event :inspect [_] (s/cat :op #{:do!}
:inspect-fn ifn?))

(defmethod test-event :write! [_] (s/cat :op #{:write!}
:topic-id ::topic-id
:message ::test-message
:options (s/? ::write-options)))

(defmethod test-event :watch [_] (s/cat :op #{:watch}
:watch-fn ifn?
:option (s/? ::watch-options)))

;; Deprecated test events
;;
;; Keeping these around to ensure existing test-sequences continue to be valid
;; but `:stop` is a relic of when the implementation required an explicit stop
;; command and the others are all expressible as a simple `:do`.

(defmethod test-event :stop [_] (s/cat :op #{:stop}))

(defmethod test-event :println [_] (s/cat :op #{:println}
:print-args (s/? any?)))

(defmethod test-event :pprint [_] (s/cat :op #{:pprint}
:print-args (s/? any?)))

(defmethod test-event :sleep [_] (s/cat :op #{:sleep}
:sleep-args int?))

(defn do
"Invoke the provided function, passing a snapshot of the test journal
Expand All @@ -56,8 +100,8 @@
`[:do ~do-fn])

(s/fdef do
:args ifn?
:ret vector?)
:args (s/cat :do-fn ifn?)
:ret ::test-event)

(defn do!
"Invoke the provided function, passing the journal `ref`
Expand All @@ -69,8 +113,20 @@
`[:do! ~do-fn])

(s/fdef do!
:args ifn?
:ret vector?)
:args (s/cat :do-fn ifn?)
:ret ::test-event)

(defn inspect
"Invoke the provided function, passing the entire test-machine

Can be useful while learning about how the test-machine works to inspect the state
of the test-machine."
[inspect-fn]
`[:do! ~inspect-fn])

(s/fdef inspect
:args (s/cat :inspect-fn ifn?)
:ret ::test-event)

(defn write!
"Write a message to the topic identified in the topic-metadata by `topic-id`
Expand All @@ -94,7 +150,7 @@
:args (s/cat :topic-id ::topic-id
:message ::test-message
:options (s/? ::write-options))
:ret vector?)
:ret ::test-event)

(defn watch
"Watch the test-journal until the `watch-fn` predicate returns true
Expand All @@ -115,4 +171,5 @@
(s/fdef watch
:args (s/cat :watch-fn ifn?
:options (s/? ::watch-options))
:ret vector?)
:ret ::test-event)

42 changes: 42 additions & 0 deletions test/jackdaw/test/commands_test.clj
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
(ns jackdaw.test.commands-test
(:require
[clojure.spec.alpha :as s]
[clojure.test :refer :all]
[jackdaw.test.commands :as cmd]))

Expand All @@ -16,3 +17,44 @@
(is (thrown-with-msg? clojure.lang.ExceptionInfo
#"Unknown command: :not-found"
(cmd/command-handler {} [:not-found])))))

(defn valid-command?
[cmd]
(s/valid? ::cmd/test-event cmd))

(deftest test-command-specs
(testing "base commands"
(is (not (valid-command? [:yolo])))
(is (valid-command? (cmd/do #(println "yolo" %))))
(is (valid-command? (cmd/do! #(println "yolo" %))))
(is (valid-command? [:stop]))
(is (valid-command? [:println "yolo"]))
(is (valid-command? [:pprint {:foo "yolo"}]))
(is (valid-command? [:sleep 420])))

(testing "write commands"
(is (valid-command? (cmd/write! :foo {:id 1 :payload "yolo"})))

(is (valid-command? (cmd/write! :foo {:id 1 :payload "yolo"}
{:key 1
:partition 1})))

(is (valid-command? (cmd/write! :foo {:id 1 :payload "yolo"}
{:key-fn :id
:partition-fn (constantly 1)})))

(is (not (valid-command? [:write! :foo {:id 1 :payload "yolo"}
{:key-fn "not a fn"
:partition-fn "not a fn"}]))))

(testing "watch commands"
(is (valid-command? (cmd/watch #(= % :expected))))
(is (valid-command? (cmd/watch #(= % :expected)
{:info "error hint"})))
(is (valid-command? (cmd/watch #(= % :expected)
{:timeout 420})))

(is (not (valid-command? [:watch #(= % :expected)
{:timeout "not an int"}])))
(is (not (valid-command? [:watch #(= % :expected)
{:info :not-a-string}])))))