Codebase list test-check-clojure / 41d421b
Move cljs tests to src/test/clojure This way the tests will still run under cljs when they get to be converted to .cljc Nicolas Berger authored 8 years ago Gary Fredericks committed 8 years ago
9 changed file(s) with 733 addition(s) and 733 deletion(s). Raw diff Collapse all Expand all
2020 :cljsbuild
2121 {:builds
2222 [{:id "node-dev"
23 :source-paths ["src/main/clojure" "src/test/cljs"
23 :source-paths ["src/main/clojure" "src/test/clojure"
2424 "src/target/cljs/node"]
2525 :notify-command ["node" "resources/run.js"]
2626 :compiler {:optimizations :none
3030 :output-dir "target/cljs/node_dev/out"
3131 :source-map true}}
3232 {:id "browser-dev"
33 :source-paths ["src/main/clojure" "src/test/cljs"
33 :source-paths ["src/main/clojure" "src/test/clojure"
3434 "src/target/cljs/browser"]
3535 :compiler {:optimizations :none
3636 :static-fns true
3838 :output-dir "target/cljs/browser_dev/out"
3939 :source-map true}}
4040 {:id "node-adv"
41 :source-paths ["src/main/clojure" "src/test/cljs"
41 :source-paths ["src/main/clojure" "src/test/clojure"
4242 "src/target/cljs/node"]
4343 :notify-command ["node" "target/cljs/node_adv/tests.js"]
4444 :compiler {:optimizations :advanced
4747 :output-to "target/cljs/node_adv/tests.js"
4848 :output-dir "target/cljs/node_adv/out"}}
4949 {:id "browser-adv"
50 :source-paths ["src/main/clojure" "src/test/cljs"
50 :source-paths ["src/main/clojure" "src/test/clojure"
5151 "src/target/cljs/browser"]
5252 :compiler {:optimizations :advanced
5353 :pretty-print false
+0
-81
src/test/cljs/clojure/test/check/clojure_test_test.cljs less more
0 ; Copyright (c) Rich Hickey, Reid Draper, and contributors.
1 ; All rights reserved.
2 ; The use and distribution terms for this software are covered by the
3 ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
4 ; which can be found in the file epl-v10.html at the root of this distribution.
5 ; By using this software in any fashion, you are agreeing to be bound by
6 ; the terms of this license.
7 ; You must not remove this notice, or any other, from this software.
8
9 (ns clojure.test.check.clojure-test-test
10 (:require [cljs.test :as test :refer [test-var] :refer-macros [is]]
11 [clojure.test.check.generators :as gen]
12 [clojure.test.check.properties :as prop :include-macros true]
13 [clojure.test.check.clojure-test :as ct :refer-macros [defspec]]
14 [cljs.reader :refer [read-string]]))
15
16 (defspec default-trial-counts
17 (prop/for-all* [gen/int] (constantly true)))
18
19 (defspec trial-counts 5000
20 (prop/for-all* [gen/int] (constantly true)))
21
22 ;; NOTE: No Thread/sleep in JS - David
23 ;; (defspec long-running-spec 1000
24 ;; (prop/for-all* [] #(do (Thread/sleep 1) true)))
25
26 (defn- vector-elements-are-unique*
27 [v]
28 (== (count v) (count (distinct v))))
29
30 (def ^:private vector-elements-are-unique
31 (prop/for-all*
32 [(gen/vector gen/int)]
33 vector-elements-are-unique*))
34
35 (defspec this-is-supposed-to-fail 100 vector-elements-are-unique)
36
37 (defn- capture-test-var
38 [v]
39 (doto (with-out-str (test-var v))
40 print))
41
42 (defn test-ns-hook
43 []
44 (let [out-str (capture-test-var #'default-trial-counts)
45 num-tests (-> out-str
46 read-string
47 :num-tests)]
48 (is (= num-tests ct/*default-test-count*)))
49
50 (is (-> (capture-test-var #'trial-counts)
51 read-string
52 (select-keys [:test-var :result :num-tests])
53 (= {:test-var "trial-counts", :result true, :num-tests 5000})))
54
55 (binding [ct/*report-trials* true]
56 (let [output (capture-test-var #'trial-counts)]
57 (is (re-matches #"\.{5}[\s\S]+" output))))
58
59 ;; NOTE: No Thread/sleep in JS - David
60 ;; (binding [ct/*report-trials* ct/trial-report-periodic
61 ;; ct/*trial-report-period* 500]
62 ;; (is (re-seq
63 ;; #"(Passing trial \d{3} / 1000 for .+\n)+"
64 ;; (capture-test-var #'long-running-spec))))
65
66 (let [[report-counters report-str]
67 (binding [ct/*report-shrinking* true]
68 ;; need to keep the failure of this-is-supposed-to-fail from
69 ;; affecting the clojure.test.check test run
70 (let [restore-env (test/get-current-env)
71 _ (test/set-env! (test/empty-env))
72 report-str (capture-test-var #'this-is-supposed-to-fail)
73 env (test/get-current-env)]
74 (test/set-env! restore-env)
75 [(:report-counters env) report-str]))]
76 (is (== 1 (:fail report-counters)))
77 (is (re-seq
78 #"Shrinking vector-elements-are-unique starting with parameters \[\[[\s\S]+"
79 report-str))))
80
+0
-58
src/test/cljs/clojure/test/check/random_test.cljs less more
0 (ns clojure.test.check.random-test
1 "Testing that the cljs impl matches the clojure impl."
2 (:require [cljs.test :refer-macros [deftest is]]
3 [clojure.test.check.random :as random]))
4
5 (deftest longs-test
6
7 ;; comparing with this code run on clj-jvm:
8 (comment
9 (-> 42
10 (random/make-java-util-splittable-random)
11 (random/split-n 17)
12 (->> (mapcat random/split)
13 (map random/rand-long)
14 (reduce bit-xor))
15 (str))
16 =>
17 "5298131359241775269")
18
19 (is (= "5298131359241775269"
20 (-> 42
21 (random/make-java-util-splittable-random)
22 (random/split-n 17)
23 (->> (mapcat random/split)
24 (map random/rand-long)
25 (reduce #(.xor %1 %2)))
26 (str)))))
27
28 (deftest doubles-test
29
30 ;; comparing with this code run on clj-jvm:
31 (comment
32
33 (-> -42
34 (random/make-java-util-splittable-random)
35 (random/split-n 17)
36 (->> (mapcat random/split)
37 (map random/rand-double)
38 (reduce +))
39 (str))
40 =>
41 "17.39141655134964")
42
43 (is (= "17.39141655134964"
44 (-> -42
45 (random/make-java-util-splittable-random)
46 (random/split-n 17)
47 (->> (mapcat random/split)
48 (map random/rand-double)
49 (reduce +))
50 (str)))))
51
52 (deftest auto-seeding-test
53 (is (distinct? (random/rand-double (random/make-random))
54 (random/rand-double (random/make-random))
55 (random/rand-double (random/make-random))
56 (random/rand-double (random/make-random)))
57 "Each call to make-random should return a different RNG."))
+0
-35
src/test/cljs/clojure/test/check/rose_tree_test.cljs less more
0 ; Copyright (c) Rich Hickey, Reid Draper, and contributors.
1 ; All rights reserved.
2 ; The use and distribution terms for this software are covered by the
3 ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
4 ; which can be found in the file epl-v10.html at the root of this distribution.
5 ; By using this software in any fashion, you are agreeing to be bound by
6 ; the terms of this license.
7 ; You must not remove this notice, or any other, from this software.
8
9 (ns clojure.test.check.rose-tree-test
10 (:require [cljs.test :as test :include-macros true]
11 [clojure.test.check :as tc]
12 [clojure.test.check.generators :as gen]
13 [clojure.test.check.properties :as prop :include-macros true]
14 [clojure.test.check.rose-tree :as rose]
15 [clojure.test.check.clojure-test :as ct :refer-macros [defspec]]))
16
17 (defn depth-one-children
18 [rose]
19 (into [] (map rose/root (rose/children rose))))
20
21 (defn depth-one-and-two-children
22 [rose]
23 (let [the-children (rose/children rose)]
24 (into []
25 (concat
26 (map rose/root the-children)
27 (map rose/root (mapcat rose/children the-children))))))
28
29 (defspec test-collapse-rose
30 100
31 (prop/for-all [i gen/int]
32 (let [tree (gen/int-rose-tree i)]
33 (= (depth-one-and-two-children tree)
34 (depth-one-children (rose/collapse tree))))))
+0
-555
src/test/cljs/clojure/test/check/test.cljs less more
0 (ns clojure.test.check.test
1 (:require [cljs.test :as test :refer-macros [deftest testing is]]
2 [clojure.test.check :as tc]
3 [clojure.test.check.generators :as gen]
4 [clojure.test.check.properties :as prop :include-macros true]
5 [clojure.test.check.random :as random]
6 [clojure.test.check.rose-tree :as rose]
7 [clojure.test.check.clojure-test :as ct :refer-macros [defspec]]
8 [cljs.reader :as edn]))
9
10 (deftest generators-are-generators
11 (testing "generator? returns true when called with a generator"
12 (is (gen/generator? gen/int))
13 (is (gen/generator? (gen/vector gen/int)))
14 (is (gen/generator? (gen/return 5)))))
15
16
17 (deftest values-are-not-generators
18 (testing "generator? returns false when called with a value"
19 (is (not (gen/generator? 5)))
20 (is (not (gen/generator? int)))
21 (is (not (gen/generator? [1 2 3])))))
22
23 ;; plus and 0 form a monoid
24 ;; ---------------------------------------------------------------------------
25
26 (defn passes-monoid-properties
27 [a b c]
28 (and
29 (= (+ 0 a) a)
30 (= (+ a 0) a)
31 (= (+ a (+ b c)) (+ (+ a b) c))))
32
33 (deftest plus-and-0-are-a-monoid
34 (testing "+ and 0 form a monoid"
35 (is
36 (let [p (prop/for-all* [gen/int gen/int gen/int]
37 passes-monoid-properties)]
38 (:result (tc/quick-check 1000 p)))))
39 ;; NOTE: no ratios in ClojureScript - David
40 ;; (testing "with ratios as well"
41 ;; (is
42 ;; (let [p (prop/for-all* [gen/ratio gen/ratio gen/ratio]
43 ;; passes-monoid-properties)]
44 ;; (:result (tc/quick-check 1000 p)))))
45 )
46
47 ;; reverse
48 ;; ---------------------------------------------------------------------------
49
50 (defn reverse-equal?-helper
51 [l]
52 (let [r (vec (reverse l))]
53 (and (= (count l) (count r))
54 (= (seq l) (rseq r)))))
55
56 (deftest reverse-equal?
57 (testing "For all vectors L, reverse(reverse(L)) == L"
58 (is (let [p (prop/for-all* [(gen/vector gen/int)] reverse-equal?-helper)]
59 (:result (tc/quick-check 1000 p))))))
60
61 ;; failing reverse
62 ;; ---------------------------------------------------------------------------
63
64 (deftest bad-reverse-test
65 (testing "For all vectors L, L == reverse(L). Not true"
66 (is (false?
67 (let [p (prop/for-all* [(gen/vector gen/int)] #(= (reverse %) %))]
68 (:result (tc/quick-check 1000 p)))))))
69
70 ;; failing element remove
71 ;; ---------------------------------------------------------------------------
72
73 (defn first-is-gone
74 [l]
75 (not (some #{(first l)} (vec (rest l)))))
76
77 (deftest bad-remove
78 (testing "For all vectors L, if we remove the first element E, E should not
79 longer be in the list. (This is a false assumption)"
80 (is (false?
81 (let [p (prop/for-all* [(gen/vector gen/int)] first-is-gone)]
82 (:result (tc/quick-check 1000 p)))))))
83
84 ;; exceptions shrink and return as result
85 ;; ---------------------------------------------------------------------------
86
87 (def exception (js/Error. "I get caught"))
88
89 (defn exception-thrower
90 [& args]
91 (throw exception))
92
93 (deftest exceptions-are-caught
94 (testing "Exceptions during testing are caught. They're also shrunk as long
95 as they continue to throw."
96 (is (= [exception [0]]
97 (let [result
98 (tc/quick-check
99 1000 (prop/for-all* [gen/int] exception-thrower))]
100 [(:result result) (get-in result [:shrunk :smallest])])))))
101
102 ;; Count and concat work as expected
103 ;; ---------------------------------------------------------------------------
104
105 (defn concat-counts-correct
106 [a b]
107 (= (count (concat a b))
108 (+ (count a) (count b))))
109
110 (deftest count-and-concat
111 (testing "For all vectors A and B:
112 length(A + B) == length(A) + length(B)"
113 (is (:result
114 (let [p (prop/for-all* [(gen/vector gen/int)
115 (gen/vector gen/int)] concat-counts-correct)]
116 (tc/quick-check 1000 p))))))
117
118 ;; Interpose (Count)
119 ;; ---------------------------------------------------------------------------
120
121 (defn interpose-twice-the-length ;; (or one less)
122 [v]
123 (let [interpose-count (count (interpose :i v))
124 original-count (count v)]
125 (or
126 (= (* 2 original-count) interpose-count)
127 (= (dec (* 2 original-count)) interpose-count))))
128
129
130 (deftest interpose-creates-sequence-twice-the-length
131 (testing
132 "Interposing a collection with a value makes its count
133 twice the original collection, or ones less."
134 (is (:result
135 (tc/quick-check 1000 (prop/for-all [v (gen/vector gen/int)] (interpose-twice-the-length v)))))))
136
137 ;; Lists and vectors are equivalent with seq abstraction
138 ;; ---------------------------------------------------------------------------
139
140 (defn list-vector-round-trip-equiv
141 [a]
142 ;; NOTE: can't use `(into '() ...)` here because that
143 ;; puts the list in reverse order. clojure.test.check found that bug
144 ;; pretty quickly...
145 (= a (apply list (vec a))))
146
147 (deftest list-and-vector-round-trip
148 (testing
149 ""
150 (is (:result
151 (tc/quick-check
152 1000 (prop/for-all*
153 [(gen/list gen/int)] list-vector-round-trip-equiv))))))
154
155 ;; keyword->string->keyword roundtrip
156 ;; ---------------------------------------------------------------------------
157
158 (defn keyword-string-roundtrip-equiv
159 [k]
160 (= k (keyword (name k))))
161
162 ;; NOTE: this is one of the slowest due to how keywords are constructed
163 ;; drop N to 200 - David
164 (deftest keyword-string-roundtrip
165 (testing
166 "For all keywords, turning them into a string and back is equivalent
167 to the original string (save for the `:` bit)"
168 (is (:result
169 (tc/quick-check 100 (prop/for-all*
170 [gen/keyword] keyword-string-roundtrip-equiv)
171 :max-size 25)))))
172
173 ;; Boolean and/or
174 ;; ---------------------------------------------------------------------------
175
176 (deftest boolean-or
177 (testing
178 "`or` with true and anything else should be true"
179 (is (:result (tc/quick-check
180 1000 (prop/for-all*
181 [gen/boolean] #(or % true)))))))
182
183 (deftest boolean-and
184 (testing
185 "`and` with false and anything else should be false"
186 (is (:result (tc/quick-check
187 1000 (prop/for-all*
188 [gen/boolean] #(not (and % false))))))))
189
190 ;; Sorting
191 ;; ---------------------------------------------------------------------------
192
193 (defn elements-are-in-order-after-sorting
194 [v]
195 (every? identity (map <= (partition 2 1 (sort v)))))
196
197 (deftest sorting
198 (testing
199 "For all vectors V, sorted(V) should have the elements in order"
200 (is (:result
201 (tc/quick-check
202 1000
203 (prop/for-all*
204 [(gen/vector gen/int)] elements-are-in-order-after-sorting))))))
205
206 ;; Constant generators
207 ;; ---------------------------------------------------------------------------
208
209 ;; A constant generator always returns its created value
210 (defspec constant-generators 100
211 (prop/for-all [a (gen/return 42)]
212 (print "")
213 (= a 42)))
214
215 (deftest constant-generators-dont-shrink
216 (testing "Generators created with `gen/return` should not shrink"
217 (is (= [42]
218 (let [result (tc/quick-check 100
219 (prop/for-all
220 [a (gen/return 42)]
221 false))]
222 (-> result :shrunk :smallest))))))
223
224 ;; Tests are deterministic
225 ;; ---------------------------------------------------------------------------
226
227 (defn vector-elements-are-unique
228 [v]
229 (== (count v) (count (distinct v))))
230
231 (defn unique-test
232 [seed]
233 (tc/quick-check 1000
234 (prop/for-all*
235 [(gen/vector gen/int)] vector-elements-are-unique)
236 :seed seed))
237
238 (defn equiv-runs
239 [seed]
240 (= (unique-test seed) (unique-test seed)))
241
242 (deftest tests-are-deterministic
243 (testing "If two runs are started with the same seed, they should
244 return the same results."
245 (is (:result
246 (tc/quick-check 1000 (prop/for-all* [gen/int] equiv-runs))))))
247
248 ;; Generating basic generators
249 ;; --------------------------------------------------------------------------
250
251 (deftest generators-test
252 (let [t (fn [generator pred]
253 (is (:result (tc/quick-check 100
254 (prop/for-all [x generator]
255 (pred x))))))]
256
257 (testing "keyword" (t gen/keyword keyword?))
258 ;; (testing "ratio" (t gen/ratio clojure.lang.Ratio))
259 ;; (testing "byte" (t gen/byte Byte))
260 ;; (testing "bytes" (t gen/bytes (Class/forName "[B")))
261
262 (testing "char" (t gen/char string?))
263 (testing "char-ascii" (t gen/char-ascii string?))
264 (testing "char-alphanumeric" (t gen/char-alphanumeric string?))
265 (testing "string" (t gen/string string?))
266 (testing "string-ascii" (t gen/string-ascii string?))
267 (testing "string-alphanumeric" (t gen/string-alphanumeric string?))
268
269 (testing "vector" (t (gen/vector gen/int) vector?))
270 (testing "list" (t (gen/list gen/int) list?))
271 (testing "map" (t (gen/map gen/int gen/int) map?))
272 ))
273
274 ;; Generating proper matrices
275 ;; ---------------------------------------------------------------------------
276
277 (defn proper-matrix?
278 "Check if provided nested vectors form a proper matrix — that is, all nested
279 vectors have the same length"
280 [mtx]
281 (let [first-size (count (first mtx))]
282 (every? (partial = first-size) (map count (rest mtx)))))
283
284 (deftest proper-matrix-test
285 (testing
286 "can generate proper matrices"
287 (is (:result (tc/quick-check
288 100 (prop/for-all
289 [mtx (gen/vector (gen/vector gen/int 3) 3)]
290 (proper-matrix? mtx)))))))
291
292 (def bounds-and-vector
293 (gen/bind (gen/tuple gen/s-pos-int gen/s-pos-int)
294 (fn [[a b]]
295 (let [minimum (min a b)
296 maximum (max a b)]
297 (gen/tuple (gen/return [minimum maximum])
298 (gen/vector gen/int minimum maximum))))))
299
300 (deftest proper-vector-test
301 (testing
302 "can generate vectors with sizes in a provided range"
303 (is (:result (tc/quick-check
304 100 (prop/for-all
305 [b-and-v bounds-and-vector]
306 (let [[[minimum maximum] v] b-and-v
307 c (count v)]
308 (and (<= c maximum)
309 (>= c minimum)))))))))
310
311 ;; Tuples and Pairs retain their count during shrinking
312 ;; ---------------------------------------------------------------------------
313
314 (defn n-int-generators
315 [n]
316 (vec (repeat n gen/int)))
317
318 (def tuples
319 [(apply gen/tuple (n-int-generators 1))
320 (apply gen/tuple (n-int-generators 2))
321 (apply gen/tuple (n-int-generators 3))
322 (apply gen/tuple (n-int-generators 4))
323 (apply gen/tuple (n-int-generators 5))
324 (apply gen/tuple (n-int-generators 6))])
325
326 (defn get-tuple-gen
327 [index]
328 (nth tuples (dec index)))
329
330 (defn inner-tuple-property
331 [size]
332 (prop/for-all [t (get-tuple-gen size)]
333 false))
334
335 (defspec tuples-retain-size-during-shrinking 1000
336 (prop/for-all [index (gen/choose 1 6)]
337 (let [result (tc/quick-check
338 100 (inner-tuple-property index))]
339 (= index (count (-> result
340 :shrunk :smallest first))))))
341
342 ;; Bind works
343 ;; ---------------------------------------------------------------------------
344
345 (def nat-vec
346 (gen/such-that not-empty
347 (gen/vector gen/nat)))
348
349 (def vec-and-elem
350 (gen/bind nat-vec
351 (fn [v]
352 (gen/tuple (gen/elements v) (gen/return v)))))
353
354 (defspec element-is-in-vec 100
355 (prop/for-all [[element coll] vec-and-elem]
356 (some #{element} coll)))
357
358 ;; fmap is respected during shrinking
359 ;; ---------------------------------------------------------------------------
360
361 (def plus-fifty
362 (gen/fmap (partial + 50) gen/nat))
363
364 (deftest f-map-respected-during-shrinking
365 (testing
366 "Generators created fmap should have that function applied
367 during shrinking"
368 (is (= [50]
369 (let [result (tc/quick-check 100
370 (prop/for-all
371 [a plus-fifty]
372 false))]
373 (-> result :shrunk :smallest))))))
374
375 ;; edn rountrips
376 ;; ---------------------------------------------------------------------------
377
378 ;; TODO: EDN round trips sometimes fail - David
379
380 (defn edn-roundtrip?
381 [value]
382 (= value (-> value prn-str edn/read-string)))
383
384 (defspec edn-roundtrips 50
385 (prop/for-all [a gen/any]
386 (edn-roundtrip? a)))
387
388 ;; not-empty works
389 ;; ---------------------------------------------------------------------------
390
391 (defspec not-empty-works 100
392 (prop/for-all [v (gen/not-empty (gen/vector gen/boolean))]
393 (not-empty v)))
394
395 ;; no-shrink works
396 ;; ---------------------------------------------------------------------------
397
398 (defn run-no-shrink
399 [i]
400 (tc/quick-check 100
401 (prop/for-all [coll (gen/vector gen/nat)]
402 (some #{i} coll))))
403
404 (defspec no-shrink-works 100
405 (prop/for-all [i gen/nat]
406 (let [result (run-no-shrink i)]
407 (if (:result result)
408 true
409 (= (:fail result)
410 (-> result :shrunk :smallest))))))
411
412 ;; elements works with a variety of input
413 ;; ---------------------------------------------------------------------------
414
415 (deftest elements-with-empty
416 (is (thrown? js/Error (gen/elements ()))))
417
418 (defspec elements-with-a-set 100
419 (prop/for-all [num (gen/elements #{9 10 11 12})]
420 (<= 9 num 12)))
421
422
423 ;; choose respects bounds during shrinking
424 ;; ---------------------------------------------------------------------------
425
426 (def range-gen
427 (gen/fmap (fn [[a b]]
428 [(min a b) (max a b)])
429 (gen/tuple gen/int gen/int)))
430
431 (defspec choose-respects-bounds-during-shrinking 100
432 (prop/for-all [[mini maxi] range-gen
433 random-seed gen/nat
434 size gen/nat]
435 (let [tree (gen/call-gen
436 (gen/choose mini maxi)
437 (random/make-random random-seed)
438 size)]
439 (every?
440 #(and (<= mini %) (>= maxi %))
441 (rose/seq tree)))))
442
443 ;; rand-range copes with full range of longs as bounds
444 ;; ---------------------------------------------------------------------------
445
446 ;; NOTE: need to adjust for JS numerics - David
447
448 ;; (deftest rand-range-copes-with-full-range-of-longs
449 ;; (let [[low high] (reduce
450 ;; (fn [[low high :as margins] x]
451 ;; (cond
452 ;; (< x low) [x high]
453 ;; (> x high) [low x]
454 ;; :else margins))
455 ;; [Long/MAX_VALUE Long/MIN_VALUE]
456 ;; ; choose uses rand-range directly, reasonable proxy for its
457 ;; ; guarantees
458 ;; (take 1e6 (gen/sample-seq (gen/choose Long/MIN_VALUE Long/MAX_VALUE))))]
459 ;; (is (< low high))
460 ;; (is (< low Integer/MIN_VALUE))
461 ;; (is (> high Integer/MAX_VALUE))))
462
463 ;; rand-range yields values inclusive of both lower & upper bounds provided to it
464 ;; further, that generators that use rand-range use its full range of values
465 ;; ---------------------------------------------------------------------------
466
467 (deftest rand-range-uses-inclusive-bounds
468 (let [bounds [5 7]
469 rand-range (fn [r] (apply gen/rand-range r bounds))]
470 (loop [trials 0
471 bounds (set bounds)
472 r (random/make-random)]
473 (cond
474 (== trials 10000)
475 (is nil (str "rand-range didn't return both of its bounds after 10000 trials; "
476 "it is possible for this to fail without there being a problem, "
477 "but we should be able to rely upon probability to not bother us "
478 "too frequently."))
479 (empty? bounds) (is true)
480 :else (let [[r1 r2] (random/split r)]
481 (recur (inc trials) (disj bounds (rand-range r1)) r2))))))
482
483 (deftest elements-generates-all-provided-values
484 (let [options [:a 42 'c/d "foo"]]
485 (is (->> (reductions
486 disj
487 (set options)
488 (gen/sample-seq (gen/elements options)))
489 (take 10000)
490 (some empty?))
491 (str "elements didn't return all of its candidate values after 10000 trials; "
492 "it is possible for this to fail without there being a problem, "
493 "but we should be able to rely upon probability to not bother us "
494 "too frequently."))))
495
496 ;; shuffling a vector generates a permutation of that vector
497 ;; ---------------------------------------------------------------------------
498
499 (def original-vector-and-permutation
500 (gen/bind (gen/vector gen/int)
501 #(gen/tuple (gen/return %) (gen/shuffle %))))
502
503 (defspec shuffled-vector-is-a-permutation-of-original 100
504 (prop/for-all [[coll permutation] original-vector-and-permutation]
505 (= (sort coll) (sort permutation))))
506
507 ;; vector can generate large vectors; regression for TCHECK-49
508 ;; ---------------------------------------------------------------------------
509
510 (deftest large-vector-test
511 (is (= 100000
512 (count (first (gen/sample
513 (gen/vector gen/nat 100000)
514 1))))))
515
516 ;; scale controls growth rate of generators
517 ;; ---------------------------------------------------------------------------
518
519 (deftest scale-test
520 (let [g (gen/scale (partial min 10) gen/pos-int) ;; should limit size to 10
521 samples (gen/sample g 1000)]
522 (is (every? (partial >= 11) samples))
523 (is (some (partial = 10) samples))))
524
525 ;; generator dev helpers
526 ;; ---------------------------------------------------------------------------
527
528 (deftest generate-test
529 (is (string? (gen/generate gen/string)))
530 (is (string? (gen/generate gen/string 42))))
531
532 ;; defspec macro
533 ;; ---------------------------------------------------------------------------
534
535 (defspec run-only-once 1 (prop/for-all* [gen/int] (constantly true)))
536
537 (defspec run-default-times (prop/for-all* [gen/int] (constantly true)))
538
539 (defspec run-with-map1 {:num-tests 1} (prop/for-all* [gen/int] (constantly true)))
540
541 (defspec run-with-map {:num-tests 1
542 :seed 1}
543 (prop/for-all [a gen/int]
544 (= a 0)))
545
546 (def my-defspec-options {:num-tests 1 :seed 1})
547
548 (defspec run-with-symbolic-options my-defspec-options
549 (prop/for-all [a gen/int]
550 (= a 0)))
551
552 (defspec run-with-no-options
553 (prop/for-all [a gen/int]
554 (integer? a)))
0 ; Copyright (c) Rich Hickey, Reid Draper, and contributors.
1 ; All rights reserved.
2 ; The use and distribution terms for this software are covered by the
3 ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
4 ; which can be found in the file epl-v10.html at the root of this distribution.
5 ; By using this software in any fashion, you are agreeing to be bound by
6 ; the terms of this license.
7 ; You must not remove this notice, or any other, from this software.
8
9 (ns clojure.test.check.clojure-test-test
10 (:require [cljs.test :as test :refer [test-var] :refer-macros [is]]
11 [clojure.test.check.generators :as gen]
12 [clojure.test.check.properties :as prop :include-macros true]
13 [clojure.test.check.clojure-test :as ct :refer-macros [defspec]]
14 [cljs.reader :refer [read-string]]))
15
16 (defspec default-trial-counts
17 (prop/for-all* [gen/int] (constantly true)))
18
19 (defspec trial-counts 5000
20 (prop/for-all* [gen/int] (constantly true)))
21
22 ;; NOTE: No Thread/sleep in JS - David
23 ;; (defspec long-running-spec 1000
24 ;; (prop/for-all* [] #(do (Thread/sleep 1) true)))
25
26 (defn- vector-elements-are-unique*
27 [v]
28 (== (count v) (count (distinct v))))
29
30 (def ^:private vector-elements-are-unique
31 (prop/for-all*
32 [(gen/vector gen/int)]
33 vector-elements-are-unique*))
34
35 (defspec this-is-supposed-to-fail 100 vector-elements-are-unique)
36
37 (defn- capture-test-var
38 [v]
39 (doto (with-out-str (test-var v))
40 print))
41
42 (defn test-ns-hook
43 []
44 (let [out-str (capture-test-var #'default-trial-counts)
45 num-tests (-> out-str
46 read-string
47 :num-tests)]
48 (is (= num-tests ct/*default-test-count*)))
49
50 (is (-> (capture-test-var #'trial-counts)
51 read-string
52 (select-keys [:test-var :result :num-tests])
53 (= {:test-var "trial-counts", :result true, :num-tests 5000})))
54
55 (binding [ct/*report-trials* true]
56 (let [output (capture-test-var #'trial-counts)]
57 (is (re-matches #"\.{5}[\s\S]+" output))))
58
59 ;; NOTE: No Thread/sleep in JS - David
60 ;; (binding [ct/*report-trials* ct/trial-report-periodic
61 ;; ct/*trial-report-period* 500]
62 ;; (is (re-seq
63 ;; #"(Passing trial \d{3} / 1000 for .+\n)+"
64 ;; (capture-test-var #'long-running-spec))))
65
66 (let [[report-counters report-str]
67 (binding [ct/*report-shrinking* true]
68 ;; need to keep the failure of this-is-supposed-to-fail from
69 ;; affecting the clojure.test.check test run
70 (let [restore-env (test/get-current-env)
71 _ (test/set-env! (test/empty-env))
72 report-str (capture-test-var #'this-is-supposed-to-fail)
73 env (test/get-current-env)]
74 (test/set-env! restore-env)
75 [(:report-counters env) report-str]))]
76 (is (== 1 (:fail report-counters)))
77 (is (re-seq
78 #"Shrinking vector-elements-are-unique starting with parameters \[\[[\s\S]+"
79 report-str))))
80
0 (ns clojure.test.check.random-test
1 "Testing that the cljs impl matches the clojure impl."
2 (:require [cljs.test :refer-macros [deftest is]]
3 [clojure.test.check.random :as random]))
4
5 (deftest longs-test
6
7 ;; comparing with this code run on clj-jvm:
8 (comment
9 (-> 42
10 (random/make-java-util-splittable-random)
11 (random/split-n 17)
12 (->> (mapcat random/split)
13 (map random/rand-long)
14 (reduce bit-xor))
15 (str))
16 =>
17 "5298131359241775269")
18
19 (is (= "5298131359241775269"
20 (-> 42
21 (random/make-java-util-splittable-random)
22 (random/split-n 17)
23 (->> (mapcat random/split)
24 (map random/rand-long)
25 (reduce #(.xor %1 %2)))
26 (str)))))
27
28 (deftest doubles-test
29
30 ;; comparing with this code run on clj-jvm:
31 (comment
32
33 (-> -42
34 (random/make-java-util-splittable-random)
35 (random/split-n 17)
36 (->> (mapcat random/split)
37 (map random/rand-double)
38 (reduce +))
39 (str))
40 =>
41 "17.39141655134964")
42
43 (is (= "17.39141655134964"
44 (-> -42
45 (random/make-java-util-splittable-random)
46 (random/split-n 17)
47 (->> (mapcat random/split)
48 (map random/rand-double)
49 (reduce +))
50 (str)))))
51
52 (deftest auto-seeding-test
53 (is (distinct? (random/rand-double (random/make-random))
54 (random/rand-double (random/make-random))
55 (random/rand-double (random/make-random))
56 (random/rand-double (random/make-random)))
57 "Each call to make-random should return a different RNG."))
0 ; Copyright (c) Rich Hickey, Reid Draper, and contributors.
1 ; All rights reserved.
2 ; The use and distribution terms for this software are covered by the
3 ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
4 ; which can be found in the file epl-v10.html at the root of this distribution.
5 ; By using this software in any fashion, you are agreeing to be bound by
6 ; the terms of this license.
7 ; You must not remove this notice, or any other, from this software.
8
9 (ns clojure.test.check.rose-tree-test
10 (:require [cljs.test :as test :include-macros true]
11 [clojure.test.check :as tc]
12 [clojure.test.check.generators :as gen]
13 [clojure.test.check.properties :as prop :include-macros true]
14 [clojure.test.check.rose-tree :as rose]
15 [clojure.test.check.clojure-test :as ct :refer-macros [defspec]]))
16
17 (defn depth-one-children
18 [rose]
19 (into [] (map rose/root (rose/children rose))))
20
21 (defn depth-one-and-two-children
22 [rose]
23 (let [the-children (rose/children rose)]
24 (into []
25 (concat
26 (map rose/root the-children)
27 (map rose/root (mapcat rose/children the-children))))))
28
29 (defspec test-collapse-rose
30 100
31 (prop/for-all [i gen/int]
32 (let [tree (gen/int-rose-tree i)]
33 (= (depth-one-and-two-children tree)
34 (depth-one-children (rose/collapse tree))))))
0 (ns clojure.test.check.test
1 (:require [cljs.test :as test :refer-macros [deftest testing is]]
2 [clojure.test.check :as tc]
3 [clojure.test.check.generators :as gen]
4 [clojure.test.check.properties :as prop :include-macros true]
5 [clojure.test.check.random :as random]
6 [clojure.test.check.rose-tree :as rose]
7 [clojure.test.check.clojure-test :as ct :refer-macros [defspec]]
8 [cljs.reader :as edn]))
9
10 (deftest generators-are-generators
11 (testing "generator? returns true when called with a generator"
12 (is (gen/generator? gen/int))
13 (is (gen/generator? (gen/vector gen/int)))
14 (is (gen/generator? (gen/return 5)))))
15
16
17 (deftest values-are-not-generators
18 (testing "generator? returns false when called with a value"
19 (is (not (gen/generator? 5)))
20 (is (not (gen/generator? int)))
21 (is (not (gen/generator? [1 2 3])))))
22
23 ;; plus and 0 form a monoid
24 ;; ---------------------------------------------------------------------------
25
26 (defn passes-monoid-properties
27 [a b c]
28 (and
29 (= (+ 0 a) a)
30 (= (+ a 0) a)
31 (= (+ a (+ b c)) (+ (+ a b) c))))
32
33 (deftest plus-and-0-are-a-monoid
34 (testing "+ and 0 form a monoid"
35 (is
36 (let [p (prop/for-all* [gen/int gen/int gen/int]
37 passes-monoid-properties)]
38 (:result (tc/quick-check 1000 p)))))
39 ;; NOTE: no ratios in ClojureScript - David
40 ;; (testing "with ratios as well"
41 ;; (is
42 ;; (let [p (prop/for-all* [gen/ratio gen/ratio gen/ratio]
43 ;; passes-monoid-properties)]
44 ;; (:result (tc/quick-check 1000 p)))))
45 )
46
47 ;; reverse
48 ;; ---------------------------------------------------------------------------
49
50 (defn reverse-equal?-helper
51 [l]
52 (let [r (vec (reverse l))]
53 (and (= (count l) (count r))
54 (= (seq l) (rseq r)))))
55
56 (deftest reverse-equal?
57 (testing "For all vectors L, reverse(reverse(L)) == L"
58 (is (let [p (prop/for-all* [(gen/vector gen/int)] reverse-equal?-helper)]
59 (:result (tc/quick-check 1000 p))))))
60
61 ;; failing reverse
62 ;; ---------------------------------------------------------------------------
63
64 (deftest bad-reverse-test
65 (testing "For all vectors L, L == reverse(L). Not true"
66 (is (false?
67 (let [p (prop/for-all* [(gen/vector gen/int)] #(= (reverse %) %))]
68 (:result (tc/quick-check 1000 p)))))))
69
70 ;; failing element remove
71 ;; ---------------------------------------------------------------------------
72
73 (defn first-is-gone
74 [l]
75 (not (some #{(first l)} (vec (rest l)))))
76
77 (deftest bad-remove
78 (testing "For all vectors L, if we remove the first element E, E should not
79 longer be in the list. (This is a false assumption)"
80 (is (false?
81 (let [p (prop/for-all* [(gen/vector gen/int)] first-is-gone)]
82 (:result (tc/quick-check 1000 p)))))))
83
84 ;; exceptions shrink and return as result
85 ;; ---------------------------------------------------------------------------
86
87 (def exception (js/Error. "I get caught"))
88
89 (defn exception-thrower
90 [& args]
91 (throw exception))
92
93 (deftest exceptions-are-caught
94 (testing "Exceptions during testing are caught. They're also shrunk as long
95 as they continue to throw."
96 (is (= [exception [0]]
97 (let [result
98 (tc/quick-check
99 1000 (prop/for-all* [gen/int] exception-thrower))]
100 [(:result result) (get-in result [:shrunk :smallest])])))))
101
102 ;; Count and concat work as expected
103 ;; ---------------------------------------------------------------------------
104
105 (defn concat-counts-correct
106 [a b]
107 (= (count (concat a b))
108 (+ (count a) (count b))))
109
110 (deftest count-and-concat
111 (testing "For all vectors A and B:
112 length(A + B) == length(A) + length(B)"
113 (is (:result
114 (let [p (prop/for-all* [(gen/vector gen/int)
115 (gen/vector gen/int)] concat-counts-correct)]
116 (tc/quick-check 1000 p))))))
117
118 ;; Interpose (Count)
119 ;; ---------------------------------------------------------------------------
120
121 (defn interpose-twice-the-length ;; (or one less)
122 [v]
123 (let [interpose-count (count (interpose :i v))
124 original-count (count v)]
125 (or
126 (= (* 2 original-count) interpose-count)
127 (= (dec (* 2 original-count)) interpose-count))))
128
129
130 (deftest interpose-creates-sequence-twice-the-length
131 (testing
132 "Interposing a collection with a value makes its count
133 twice the original collection, or ones less."
134 (is (:result
135 (tc/quick-check 1000 (prop/for-all [v (gen/vector gen/int)] (interpose-twice-the-length v)))))))
136
137 ;; Lists and vectors are equivalent with seq abstraction
138 ;; ---------------------------------------------------------------------------
139
140 (defn list-vector-round-trip-equiv
141 [a]
142 ;; NOTE: can't use `(into '() ...)` here because that
143 ;; puts the list in reverse order. clojure.test.check found that bug
144 ;; pretty quickly...
145 (= a (apply list (vec a))))
146
147 (deftest list-and-vector-round-trip
148 (testing
149 ""
150 (is (:result
151 (tc/quick-check
152 1000 (prop/for-all*
153 [(gen/list gen/int)] list-vector-round-trip-equiv))))))
154
155 ;; keyword->string->keyword roundtrip
156 ;; ---------------------------------------------------------------------------
157
158 (defn keyword-string-roundtrip-equiv
159 [k]
160 (= k (keyword (name k))))
161
162 ;; NOTE: this is one of the slowest due to how keywords are constructed
163 ;; drop N to 200 - David
164 (deftest keyword-string-roundtrip
165 (testing
166 "For all keywords, turning them into a string and back is equivalent
167 to the original string (save for the `:` bit)"
168 (is (:result
169 (tc/quick-check 100 (prop/for-all*
170 [gen/keyword] keyword-string-roundtrip-equiv)
171 :max-size 25)))))
172
173 ;; Boolean and/or
174 ;; ---------------------------------------------------------------------------
175
176 (deftest boolean-or
177 (testing
178 "`or` with true and anything else should be true"
179 (is (:result (tc/quick-check
180 1000 (prop/for-all*
181 [gen/boolean] #(or % true)))))))
182
183 (deftest boolean-and
184 (testing
185 "`and` with false and anything else should be false"
186 (is (:result (tc/quick-check
187 1000 (prop/for-all*
188 [gen/boolean] #(not (and % false))))))))
189
190 ;; Sorting
191 ;; ---------------------------------------------------------------------------
192
193 (defn elements-are-in-order-after-sorting
194 [v]
195 (every? identity (map <= (partition 2 1 (sort v)))))
196
197 (deftest sorting
198 (testing
199 "For all vectors V, sorted(V) should have the elements in order"
200 (is (:result
201 (tc/quick-check
202 1000
203 (prop/for-all*
204 [(gen/vector gen/int)] elements-are-in-order-after-sorting))))))
205
206 ;; Constant generators
207 ;; ---------------------------------------------------------------------------
208
209 ;; A constant generator always returns its created value
210 (defspec constant-generators 100
211 (prop/for-all [a (gen/return 42)]
212 (print "")
213 (= a 42)))
214
215 (deftest constant-generators-dont-shrink
216 (testing "Generators created with `gen/return` should not shrink"
217 (is (= [42]
218 (let [result (tc/quick-check 100
219 (prop/for-all
220 [a (gen/return 42)]
221 false))]
222 (-> result :shrunk :smallest))))))
223
224 ;; Tests are deterministic
225 ;; ---------------------------------------------------------------------------
226
227 (defn vector-elements-are-unique
228 [v]
229 (== (count v) (count (distinct v))))
230
231 (defn unique-test
232 [seed]
233 (tc/quick-check 1000
234 (prop/for-all*
235 [(gen/vector gen/int)] vector-elements-are-unique)
236 :seed seed))
237
238 (defn equiv-runs
239 [seed]
240 (= (unique-test seed) (unique-test seed)))
241
242 (deftest tests-are-deterministic
243 (testing "If two runs are started with the same seed, they should
244 return the same results."
245 (is (:result
246 (tc/quick-check 1000 (prop/for-all* [gen/int] equiv-runs))))))
247
248 ;; Generating basic generators
249 ;; --------------------------------------------------------------------------
250
251 (deftest generators-test
252 (let [t (fn [generator pred]
253 (is (:result (tc/quick-check 100
254 (prop/for-all [x generator]
255 (pred x))))))]
256
257 (testing "keyword" (t gen/keyword keyword?))
258 ;; (testing "ratio" (t gen/ratio clojure.lang.Ratio))
259 ;; (testing "byte" (t gen/byte Byte))
260 ;; (testing "bytes" (t gen/bytes (Class/forName "[B")))
261
262 (testing "char" (t gen/char string?))
263 (testing "char-ascii" (t gen/char-ascii string?))
264 (testing "char-alphanumeric" (t gen/char-alphanumeric string?))
265 (testing "string" (t gen/string string?))
266 (testing "string-ascii" (t gen/string-ascii string?))
267 (testing "string-alphanumeric" (t gen/string-alphanumeric string?))
268
269 (testing "vector" (t (gen/vector gen/int) vector?))
270 (testing "list" (t (gen/list gen/int) list?))
271 (testing "map" (t (gen/map gen/int gen/int) map?))
272 ))
273
274 ;; Generating proper matrices
275 ;; ---------------------------------------------------------------------------
276
277 (defn proper-matrix?
278 "Check if provided nested vectors form a proper matrix — that is, all nested
279 vectors have the same length"
280 [mtx]
281 (let [first-size (count (first mtx))]
282 (every? (partial = first-size) (map count (rest mtx)))))
283
284 (deftest proper-matrix-test
285 (testing
286 "can generate proper matrices"
287 (is (:result (tc/quick-check
288 100 (prop/for-all
289 [mtx (gen/vector (gen/vector gen/int 3) 3)]
290 (proper-matrix? mtx)))))))
291
292 (def bounds-and-vector
293 (gen/bind (gen/tuple gen/s-pos-int gen/s-pos-int)
294 (fn [[a b]]
295 (let [minimum (min a b)
296 maximum (max a b)]
297 (gen/tuple (gen/return [minimum maximum])
298 (gen/vector gen/int minimum maximum))))))
299
300 (deftest proper-vector-test
301 (testing
302 "can generate vectors with sizes in a provided range"
303 (is (:result (tc/quick-check
304 100 (prop/for-all
305 [b-and-v bounds-and-vector]
306 (let [[[minimum maximum] v] b-and-v
307 c (count v)]
308 (and (<= c maximum)
309 (>= c minimum)))))))))
310
311 ;; Tuples and Pairs retain their count during shrinking
312 ;; ---------------------------------------------------------------------------
313
314 (defn n-int-generators
315 [n]
316 (vec (repeat n gen/int)))
317
318 (def tuples
319 [(apply gen/tuple (n-int-generators 1))
320 (apply gen/tuple (n-int-generators 2))
321 (apply gen/tuple (n-int-generators 3))
322 (apply gen/tuple (n-int-generators 4))
323 (apply gen/tuple (n-int-generators 5))
324 (apply gen/tuple (n-int-generators 6))])
325
326 (defn get-tuple-gen
327 [index]
328 (nth tuples (dec index)))
329
330 (defn inner-tuple-property
331 [size]
332 (prop/for-all [t (get-tuple-gen size)]
333 false))
334
335 (defspec tuples-retain-size-during-shrinking 1000
336 (prop/for-all [index (gen/choose 1 6)]
337 (let [result (tc/quick-check
338 100 (inner-tuple-property index))]
339 (= index (count (-> result
340 :shrunk :smallest first))))))
341
342 ;; Bind works
343 ;; ---------------------------------------------------------------------------
344
345 (def nat-vec
346 (gen/such-that not-empty
347 (gen/vector gen/nat)))
348
349 (def vec-and-elem
350 (gen/bind nat-vec
351 (fn [v]
352 (gen/tuple (gen/elements v) (gen/return v)))))
353
354 (defspec element-is-in-vec 100
355 (prop/for-all [[element coll] vec-and-elem]
356 (some #{element} coll)))
357
358 ;; fmap is respected during shrinking
359 ;; ---------------------------------------------------------------------------
360
361 (def plus-fifty
362 (gen/fmap (partial + 50) gen/nat))
363
364 (deftest f-map-respected-during-shrinking
365 (testing
366 "Generators created fmap should have that function applied
367 during shrinking"
368 (is (= [50]
369 (let [result (tc/quick-check 100
370 (prop/for-all
371 [a plus-fifty]
372 false))]
373 (-> result :shrunk :smallest))))))
374
375 ;; edn rountrips
376 ;; ---------------------------------------------------------------------------
377
378 ;; TODO: EDN round trips sometimes fail - David
379
380 (defn edn-roundtrip?
381 [value]
382 (= value (-> value prn-str edn/read-string)))
383
384 (defspec edn-roundtrips 50
385 (prop/for-all [a gen/any]
386 (edn-roundtrip? a)))
387
388 ;; not-empty works
389 ;; ---------------------------------------------------------------------------
390
391 (defspec not-empty-works 100
392 (prop/for-all [v (gen/not-empty (gen/vector gen/boolean))]
393 (not-empty v)))
394
395 ;; no-shrink works
396 ;; ---------------------------------------------------------------------------
397
398 (defn run-no-shrink
399 [i]
400 (tc/quick-check 100
401 (prop/for-all [coll (gen/vector gen/nat)]
402 (some #{i} coll))))
403
404 (defspec no-shrink-works 100
405 (prop/for-all [i gen/nat]
406 (let [result (run-no-shrink i)]
407 (if (:result result)
408 true
409 (= (:fail result)
410 (-> result :shrunk :smallest))))))
411
412 ;; elements works with a variety of input
413 ;; ---------------------------------------------------------------------------
414
415 (deftest elements-with-empty
416 (is (thrown? js/Error (gen/elements ()))))
417
418 (defspec elements-with-a-set 100
419 (prop/for-all [num (gen/elements #{9 10 11 12})]
420 (<= 9 num 12)))
421
422
423 ;; choose respects bounds during shrinking
424 ;; ---------------------------------------------------------------------------
425
426 (def range-gen
427 (gen/fmap (fn [[a b]]
428 [(min a b) (max a b)])
429 (gen/tuple gen/int gen/int)))
430
431 (defspec choose-respects-bounds-during-shrinking 100
432 (prop/for-all [[mini maxi] range-gen
433 random-seed gen/nat
434 size gen/nat]
435 (let [tree (gen/call-gen
436 (gen/choose mini maxi)
437 (random/make-random random-seed)
438 size)]
439 (every?
440 #(and (<= mini %) (>= maxi %))
441 (rose/seq tree)))))
442
443 ;; rand-range copes with full range of longs as bounds
444 ;; ---------------------------------------------------------------------------
445
446 ;; NOTE: need to adjust for JS numerics - David
447
448 ;; (deftest rand-range-copes-with-full-range-of-longs
449 ;; (let [[low high] (reduce
450 ;; (fn [[low high :as margins] x]
451 ;; (cond
452 ;; (< x low) [x high]
453 ;; (> x high) [low x]
454 ;; :else margins))
455 ;; [Long/MAX_VALUE Long/MIN_VALUE]
456 ;; ; choose uses rand-range directly, reasonable proxy for its
457 ;; ; guarantees
458 ;; (take 1e6 (gen/sample-seq (gen/choose Long/MIN_VALUE Long/MAX_VALUE))))]
459 ;; (is (< low high))
460 ;; (is (< low Integer/MIN_VALUE))
461 ;; (is (> high Integer/MAX_VALUE))))
462
463 ;; rand-range yields values inclusive of both lower & upper bounds provided to it
464 ;; further, that generators that use rand-range use its full range of values
465 ;; ---------------------------------------------------------------------------
466
467 (deftest rand-range-uses-inclusive-bounds
468 (let [bounds [5 7]
469 rand-range (fn [r] (apply gen/rand-range r bounds))]
470 (loop [trials 0
471 bounds (set bounds)
472 r (random/make-random)]
473 (cond
474 (== trials 10000)
475 (is nil (str "rand-range didn't return both of its bounds after 10000 trials; "
476 "it is possible for this to fail without there being a problem, "
477 "but we should be able to rely upon probability to not bother us "
478 "too frequently."))
479 (empty? bounds) (is true)
480 :else (let [[r1 r2] (random/split r)]
481 (recur (inc trials) (disj bounds (rand-range r1)) r2))))))
482
483 (deftest elements-generates-all-provided-values
484 (let [options [:a 42 'c/d "foo"]]
485 (is (->> (reductions
486 disj
487 (set options)
488 (gen/sample-seq (gen/elements options)))
489 (take 10000)
490 (some empty?))
491 (str "elements didn't return all of its candidate values after 10000 trials; "
492 "it is possible for this to fail without there being a problem, "
493 "but we should be able to rely upon probability to not bother us "
494 "too frequently."))))
495
496 ;; shuffling a vector generates a permutation of that vector
497 ;; ---------------------------------------------------------------------------
498
499 (def original-vector-and-permutation
500 (gen/bind (gen/vector gen/int)
501 #(gen/tuple (gen/return %) (gen/shuffle %))))
502
503 (defspec shuffled-vector-is-a-permutation-of-original 100
504 (prop/for-all [[coll permutation] original-vector-and-permutation]
505 (= (sort coll) (sort permutation))))
506
507 ;; vector can generate large vectors; regression for TCHECK-49
508 ;; ---------------------------------------------------------------------------
509
510 (deftest large-vector-test
511 (is (= 100000
512 (count (first (gen/sample
513 (gen/vector gen/nat 100000)
514 1))))))
515
516 ;; scale controls growth rate of generators
517 ;; ---------------------------------------------------------------------------
518
519 (deftest scale-test
520 (let [g (gen/scale (partial min 10) gen/pos-int) ;; should limit size to 10
521 samples (gen/sample g 1000)]
522 (is (every? (partial >= 11) samples))
523 (is (some (partial = 10) samples))))
524
525 ;; generator dev helpers
526 ;; ---------------------------------------------------------------------------
527
528 (deftest generate-test
529 (is (string? (gen/generate gen/string)))
530 (is (string? (gen/generate gen/string 42))))
531
532 ;; defspec macro
533 ;; ---------------------------------------------------------------------------
534
535 (defspec run-only-once 1 (prop/for-all* [gen/int] (constantly true)))
536
537 (defspec run-default-times (prop/for-all* [gen/int] (constantly true)))
538
539 (defspec run-with-map1 {:num-tests 1} (prop/for-all* [gen/int] (constantly true)))
540
541 (defspec run-with-map {:num-tests 1
542 :seed 1}
543 (prop/for-all [a gen/int]
544 (= a 0)))
545
546 (def my-defspec-options {:num-tests 1 :seed 1})
547
548 (defspec run-with-symbolic-options my-defspec-options
549 (prop/for-all [a gen/int]
550 (= a 0)))
551
552 (defspec run-with-no-options
553 (prop/for-all [a gen/int]
554 (integer? a)))