/
fsm_tests3.clj
97 lines (79 loc) · 2.65 KB
/
fsm_tests3.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
(ns stateful-testing.fsm-tests3
(:require
[clojure.pprint :refer [pprint]]
[clojure.test :refer :all]
[clojure.test.check :as tc]
[clojure.test.check.generators :as gen]
[clojure.test.check.properties :as prop]
[stateful-testing.fsm-test-utils :as fsm]))
(defn apply-command
"translate a command map into an operation and invoke it, with any required args"
[state cmd]
(update-in state [:ids]
(fn [ids]
(case (:type cmd)
:add-cmd (conj ids (:id cmd))
:delete-cmd (disj ids (:id cmd))
:clear-cmd #{}))))
(def add-cmd
(reify
fsm/Command
(precondition [_ state]
true)
(postcondition [_ state cmd]
true)
(exec [_ state cmd]
(apply-command state cmd))
(generate [_ state]
(gen/fmap (partial zipmap [:type :id])
(gen/tuple (gen/return :add-cmd)
(gen/such-that #(not (contains? (:ids state) %))
gen/int))))))
(def delete-cmd
(reify
fsm/Command
(precondition [_ state]
; must be values present for a delete to be possible
(seq (:ids state)))
(postcondition [_ state cmd]
;;delete only valid if present in the set
(->> (:ids state)
(filter #(= % (:id cmd)))
seq))
(exec [_ state cmd]
(apply-command state cmd))
(generate [_ state]
(gen/fmap (partial zipmap [:type :id])
(gen/tuple (gen/return :delete-cmd)
(gen/elements (:ids state)))))))
(def clear-cmd
(reify
fsm/Command
(precondition [_ state]
true)
(postcondition [_ state cmd]
true)
(exec [_ state cmd]
(apply-command state cmd))
(generate [_ state]
(gen/fmap (partial zipmap [:type])
(gen/tuple (gen/return :clear-cmd))))))
;;-----------------------------------------------------
;;property definition
(defn apply-commands
[commands]
(reduce apply-command
{:ids #{}}
commands))
(comment
(gen/sample (fsm/cmd-seq {:ids #{}} {:add-cmd add-cmd
:delete-cmd delete-cmd
:clear-cmd clear-cmd})
3))
(def commands-consistent-apply
(prop/for-all [commands (fsm/cmd-seq {:ids #{}} {:add-cmd add-cmd
:delete-cmd delete-cmd
:clear-cmd clear-cmd})]
(set? (:ids (apply-commands commands)))))
(deftest set-operations-pass
(is (true? (:result (tc/quick-check 100 commands-consistent-apply)))))