Skip to content

Commit 15932d8

Browse files
andrewhrstuarthalloway
authored andcommitted
CLJ-1453: Test Iterator contract from various sources
Test via test.check, asserting about the correct behavior of differt Iterator implementations, comming from different data sources - both data structures or helper functions. Used a bunch of custom made generators to simplify the spec declarations. The structure adopted by specs that test multiple sources uses a tuple containing the symbol related to source (eg `vector`, `hash-map`), mostly for debugging porpouses on failure cases. This symbol is ignored on the actual test assertion. Signed-off-by: Stuart Halloway <stu@cognitect.com>
1 parent c716a5a commit 15932d8

File tree

1 file changed

+131
-0
lines changed

1 file changed

+131
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
; Copyright (c) Rich Hickey. 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-clojure.data-structures-interop
10+
(:require [clojure.test :refer :all]
11+
[clojure.test.check.generators :as gen]
12+
[clojure.test.check.properties :as prop]
13+
[clojure.test.check.clojure-test :refer (defspec)]))
14+
15+
(defn gen-range [min max]
16+
(gen/bind (gen/choose min max) (fn [n] (gen/tuple (gen/return n)
17+
(gen/choose n max)))))
18+
19+
(defn gen-subvec [generator]
20+
(gen/bind (gen/not-empty generator)
21+
(fn [v] (gen/bind (gen-range 0 (dec (count v)))
22+
(fn [[n m]] (gen/return (subvec v n m)))))))
23+
24+
(defn gen-gvec
25+
([]
26+
(gen/bind (gen/elements {:int gen/int
27+
:short (gen/fmap short gen/byte)
28+
:long (gen/fmap long gen/int)
29+
:float (gen/fmap float gen/int)
30+
:double (gen/fmap double gen/int)
31+
:byte gen/byte
32+
:char gen/char
33+
:boolean gen/boolean})
34+
#(apply gen-gvec %)))
35+
([type generator]
36+
(gen/bind (gen/list generator) #(gen/return (apply vector-of type %)))))
37+
38+
(defn gen-hash-set [generator]
39+
(gen/fmap (partial apply hash-set) (gen/list generator)))
40+
41+
(defn gen-sorted-set [generator]
42+
(gen/fmap (partial apply sorted-set) (gen/list generator)))
43+
44+
(defn gen-array-map [key-gen val-gen]
45+
(gen/fmap (partial into (array-map)) (gen/map key-gen val-gen)))
46+
47+
(defn gen-sorted-map [key-gen val-gen]
48+
(gen/fmap (partial into (sorted-map)) (gen/map key-gen val-gen)))
49+
50+
(defn gen-array
51+
([]
52+
(gen/bind (gen/elements {int-array gen/int
53+
short-array gen/int
54+
long-array (gen/fmap long gen/int)
55+
float-array (gen/fmap float gen/int)
56+
double-array (gen/fmap double gen/int)
57+
byte-array gen/byte
58+
char-array gen/char
59+
boolean-array gen/boolean
60+
object-array gen/string})
61+
#(apply gen-array %)))
62+
([array-fn generator]
63+
(gen/fmap array-fn (gen/list generator))))
64+
65+
(defn exaust-iterator-forward [^java.util.Iterator iter]
66+
(loop [_ iter] (when (.hasNext iter) (recur (.next iter))))
67+
(try (.next iter) nil (catch Throwable t t)))
68+
69+
(defn exaust-iterator-backward [^java.util.ListIterator iter]
70+
(loop [_ iter] (when (.hasPrevious iter) (recur (.previous iter))))
71+
(try (.previous iter) nil (catch Throwable t t)))
72+
73+
(defspec iterator-throws-exception-on-exaustion 100
74+
(prop/for-all [[_ x] (gen/bind (gen/elements [['list (gen/list gen/int)]
75+
['vector (gen/vector gen/int)]
76+
['vector-of (gen-gvec)]
77+
['subvec (gen-subvec (gen/vector gen/int))]
78+
['hash-set (gen-hash-set gen/int)]
79+
['sorted-set (gen-sorted-set gen/int)]
80+
['hash-map (gen/hash-map gen/symbol gen/int)]
81+
['array-map (gen-array-map gen/symbol gen/int)]
82+
['sorted-map (gen-sorted-map gen/symbol gen/int)]])
83+
(fn [[s g]] (gen/tuple (gen/return s) g)))]
84+
(instance? java.util.NoSuchElementException (exaust-iterator-forward (.iterator x)))))
85+
86+
(defspec array-iterator-throws-exception-on-exaustion 100
87+
(prop/for-all [arr (gen-array)]
88+
(let [iter (clojure.lang.ArrayIter/createFromObject arr)]
89+
(instance? java.util.NoSuchElementException (exaust-iterator-forward iter)))))
90+
91+
(defspec list-iterator-throws-exception-on-forward-exaustion 50
92+
(prop/for-all [[_ x] (gen/bind (gen/elements [['vector (gen/vector gen/int)]
93+
['subvec (gen-subvec (gen/vector gen/int))]
94+
['vector-of (gen-gvec)]])
95+
(fn [[s g]] (gen/tuple (gen/return s) g)))]
96+
(instance? java.util.NoSuchElementException (exaust-iterator-forward (.listIterator x)))))
97+
98+
(defspec list-iterator-throws-exception-on-backward-exaustion 50
99+
(prop/for-all [[_ x] (gen/bind (gen/elements [['vector (gen/vector gen/int)]
100+
['subvec (gen-subvec (gen/vector gen/int))]
101+
['vector-of (gen-gvec)]])
102+
(fn [[s g]] (gen/tuple (gen/return s) g)))]
103+
(instance? java.util.NoSuchElementException (exaust-iterator-backward (.listIterator x)))))
104+
105+
(defspec map-keyset-iterator-throws-exception-on-exaustion 50
106+
(prop/for-all [[_ m] (gen/bind (gen/elements [['hash-map (gen/hash-map gen/symbol gen/int)
107+
'array-map (gen-array-map gen/symbol gen/int)
108+
'sorted-map (gen-sorted-map gen/symbol gen/int)]])
109+
(fn [[s g]] (gen/tuple (gen/return s) g)))]
110+
(let [iter (.iterator (.keySet m))]
111+
(instance? java.util.NoSuchElementException (exaust-iterator-forward iter)))))
112+
113+
(defspec map-values-iterator-throws-exception-on-exaustion 50
114+
(prop/for-all [[_ m] (gen/bind (gen/elements [['hash-map (gen/hash-map gen/symbol gen/int)
115+
'array-map (gen-array-map gen/symbol gen/int)
116+
'sorted-map (gen-sorted-map gen/symbol gen/int)]])
117+
(fn [[s g]] (gen/tuple (gen/return s) g)))]
118+
(let [iter (.iterator (.values m))]
119+
(instance? java.util.NoSuchElementException (exaust-iterator-forward iter)))))
120+
121+
(defspec map-keys-iterator-throws-exception-on-exaustion 50
122+
(prop/for-all [m (gen-sorted-map gen/symbol gen/int)]
123+
(instance? java.util.NoSuchElementException (exaust-iterator-forward (.keys m)))))
124+
125+
(defspec map-vals-iterator-throws-exception-on-exaustion 50
126+
(prop/for-all [m (gen-sorted-map gen/symbol gen/int)]
127+
(instance? java.util.NoSuchElementException (exaust-iterator-forward (.vals m)))))
128+
129+
(defspec map-reverse-iterator-throws-exception-on-exaustion 50
130+
(prop/for-all [m (gen-sorted-map gen/symbol gen/int)]
131+
(instance? java.util.NoSuchElementException (exaust-iterator-forward (.reverseIterator m)))))

0 commit comments

Comments
 (0)