rlm@10
|
1 ; Copyright (c) Rich Hickey. All rights reserved.
|
rlm@10
|
2 ; The use and distribution terms for this software are covered by the
|
rlm@10
|
3 ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
rlm@10
|
4 ; which can be found in the file epl-v10.html at the root of this distribution.
|
rlm@10
|
5 ; By using this software in any fashion, you are agreeing to be bound by
|
rlm@10
|
6 ; the terms of this license.
|
rlm@10
|
7 ; You must not remove this notice, or any other, from this software.
|
rlm@10
|
8
|
rlm@10
|
9 ; Author: Frantisek Sodomka
|
rlm@10
|
10
|
rlm@10
|
11
|
rlm@10
|
12 (ns clojure.test-clojure.data-structures
|
rlm@10
|
13 (:use clojure.test))
|
rlm@10
|
14
|
rlm@10
|
15
|
rlm@10
|
16 ;; *** Helper functions ***
|
rlm@10
|
17
|
rlm@10
|
18 (defn diff [s1 s2]
|
rlm@10
|
19 (seq (reduce disj (set s1) (set s2))))
|
rlm@10
|
20
|
rlm@10
|
21
|
rlm@10
|
22 ;; *** General ***
|
rlm@10
|
23
|
rlm@10
|
24 (defstruct equality-struct :a :b)
|
rlm@10
|
25
|
rlm@10
|
26 (deftest test-equality
|
rlm@10
|
27 ; nil is not equal to any other value
|
rlm@10
|
28 (are [x] (not (= nil x))
|
rlm@10
|
29 true false
|
rlm@10
|
30 0 0.0
|
rlm@10
|
31 \space
|
rlm@10
|
32 "" #""
|
rlm@10
|
33 () [] #{} {}
|
rlm@10
|
34 (lazy-seq nil) ; SVN 1292: fixed (= (lazy-seq nil) nil)
|
rlm@10
|
35 (lazy-seq ())
|
rlm@10
|
36 (lazy-seq [])
|
rlm@10
|
37 (lazy-seq {})
|
rlm@10
|
38 (lazy-seq #{})
|
rlm@10
|
39 (lazy-seq "")
|
rlm@10
|
40 (lazy-seq (into-array []))
|
rlm@10
|
41 (new Object) )
|
rlm@10
|
42
|
rlm@10
|
43 ; numbers equality across types (see tests below - NOT IMPLEMENTED YET)
|
rlm@10
|
44
|
rlm@10
|
45 ; ratios
|
rlm@10
|
46 (is (= 1/2 0.5))
|
rlm@10
|
47 (is (= 1/1000 0.001))
|
rlm@10
|
48 (is (not= 2/3 0.6666666666666666))
|
rlm@10
|
49
|
rlm@10
|
50 ; vectors equal other seqs by items equality
|
rlm@10
|
51 (are [x y] (= x y)
|
rlm@10
|
52 '() [] ; regression fixed in r1208; was not equal
|
rlm@10
|
53 '(1) [1]
|
rlm@10
|
54 '(1 2) [1 2]
|
rlm@10
|
55
|
rlm@10
|
56 [] '() ; same again, but vectors first
|
rlm@10
|
57 [1] '(1)
|
rlm@10
|
58 [1 2] '(1 2) )
|
rlm@10
|
59 (is (not= [1 2] '(2 1))) ; order of items matters
|
rlm@10
|
60
|
rlm@10
|
61 ; list and vector vs. set and map
|
rlm@10
|
62 (are [x y] (not= x y)
|
rlm@10
|
63 ; only () equals []
|
rlm@10
|
64 () #{}
|
rlm@10
|
65 () {}
|
rlm@10
|
66 [] #{}
|
rlm@10
|
67 [] {}
|
rlm@10
|
68 #{} {}
|
rlm@10
|
69 ; only '(1) equals [1]
|
rlm@10
|
70 '(1) #{1}
|
rlm@10
|
71 [1] #{1} )
|
rlm@10
|
72
|
rlm@10
|
73 ; sorted-map, hash-map and array-map - classes differ, but content is equal
|
rlm@10
|
74
|
rlm@10
|
75 ;; TODO: reimplement all-are with new do-template?
|
rlm@10
|
76 ;; (all-are (not= (class _1) (class _2))
|
rlm@10
|
77 ;; (sorted-map :a 1)
|
rlm@10
|
78 ;; (hash-map :a 1)
|
rlm@10
|
79 ;; (array-map :a 1))
|
rlm@10
|
80 ;; (all-are (= _1 _2)
|
rlm@10
|
81 ;; (sorted-map)
|
rlm@10
|
82 ;; (hash-map)
|
rlm@10
|
83 ;; (array-map))
|
rlm@10
|
84 ;; (all-are (= _1 _2)
|
rlm@10
|
85 ;; (sorted-map :a 1)
|
rlm@10
|
86 ;; (hash-map :a 1)
|
rlm@10
|
87 ;; (array-map :a 1))
|
rlm@10
|
88 ;; (all-are (= _1 _2)
|
rlm@10
|
89 ;; (sorted-map :a 1 :z 3 :c 2)
|
rlm@10
|
90 ;; (hash-map :a 1 :z 3 :c 2)
|
rlm@10
|
91 ;; (array-map :a 1 :z 3 :c 2))
|
rlm@10
|
92
|
rlm@10
|
93 ; struct-map vs. sorted-map, hash-map and array-map
|
rlm@10
|
94 (are [x] (and (not= (class (struct equality-struct 1 2)) (class x))
|
rlm@10
|
95 (= (struct equality-struct 1 2) x))
|
rlm@10
|
96 (sorted-map-by compare :a 1 :b 2)
|
rlm@10
|
97 (sorted-map :a 1 :b 2)
|
rlm@10
|
98 (hash-map :a 1 :b 2)
|
rlm@10
|
99 (array-map :a 1 :b 2))
|
rlm@10
|
100
|
rlm@10
|
101 ; sorted-set vs. hash-set
|
rlm@10
|
102 (is (not= (class (sorted-set 1)) (class (hash-set 1))))
|
rlm@10
|
103 (are [x y] (= x y)
|
rlm@10
|
104 (sorted-set-by <) (hash-set)
|
rlm@10
|
105 (sorted-set-by < 1) (hash-set 1)
|
rlm@10
|
106 (sorted-set-by < 3 2 1) (hash-set 3 2 1)
|
rlm@10
|
107 (sorted-set) (hash-set)
|
rlm@10
|
108 (sorted-set 1) (hash-set 1)
|
rlm@10
|
109 (sorted-set 3 2 1) (hash-set 3 2 1) ))
|
rlm@10
|
110
|
rlm@10
|
111
|
rlm@10
|
112 ;; *** Collections ***
|
rlm@10
|
113
|
rlm@10
|
114 (deftest test-count
|
rlm@10
|
115 (are [x y] (= x y)
|
rlm@10
|
116 (count nil) 0
|
rlm@10
|
117
|
rlm@10
|
118 (count ()) 0
|
rlm@10
|
119 (count '(1)) 1
|
rlm@10
|
120 (count '(1 2 3)) 3
|
rlm@10
|
121
|
rlm@10
|
122 (count []) 0
|
rlm@10
|
123 (count [1]) 1
|
rlm@10
|
124 (count [1 2 3]) 3
|
rlm@10
|
125
|
rlm@10
|
126 (count #{}) 0
|
rlm@10
|
127 (count #{1}) 1
|
rlm@10
|
128 (count #{1 2 3}) 3
|
rlm@10
|
129
|
rlm@10
|
130 (count {}) 0
|
rlm@10
|
131 (count {:a 1}) 1
|
rlm@10
|
132 (count {:a 1 :b 2 :c 3}) 3
|
rlm@10
|
133
|
rlm@10
|
134 (count "") 0
|
rlm@10
|
135 (count "a") 1
|
rlm@10
|
136 (count "abc") 3
|
rlm@10
|
137
|
rlm@10
|
138 (count (into-array [])) 0
|
rlm@10
|
139 (count (into-array [1])) 1
|
rlm@10
|
140 (count (into-array [1 2 3])) 3
|
rlm@10
|
141
|
rlm@10
|
142 (count (java.util.ArrayList. [])) 0
|
rlm@10
|
143 (count (java.util.ArrayList. [1])) 1
|
rlm@10
|
144 (count (java.util.ArrayList. [1 2 3])) 3
|
rlm@10
|
145
|
rlm@10
|
146 (count (java.util.HashMap. {})) 0
|
rlm@10
|
147 (count (java.util.HashMap. {:a 1})) 1
|
rlm@10
|
148 (count (java.util.HashMap. {:a 1 :b 2 :c 3})) 3 )
|
rlm@10
|
149
|
rlm@10
|
150 ; different types
|
rlm@10
|
151 (are [x] (= (count [x]) 1)
|
rlm@10
|
152 nil true false
|
rlm@10
|
153 0 0.0 "" \space
|
rlm@10
|
154 () [] #{} {} ))
|
rlm@10
|
155
|
rlm@10
|
156
|
rlm@10
|
157 (deftest test-conj
|
rlm@10
|
158 ; doesn't work on strings or arrays
|
rlm@10
|
159 (is (thrown? ClassCastException (conj "" \a)))
|
rlm@10
|
160 (is (thrown? ClassCastException (conj (into-array []) 1)))
|
rlm@10
|
161
|
rlm@10
|
162 (are [x y] (= x y)
|
rlm@10
|
163 (conj nil 1) '(1)
|
rlm@10
|
164 (conj nil 3 2 1) '(1 2 3)
|
rlm@10
|
165
|
rlm@10
|
166 (conj nil nil) '(nil)
|
rlm@10
|
167 (conj nil nil nil) '(nil nil)
|
rlm@10
|
168 (conj nil nil nil 1) '(1 nil nil)
|
rlm@10
|
169
|
rlm@10
|
170 ; list -> conj puts the item at the front of the list
|
rlm@10
|
171 (conj () 1) '(1)
|
rlm@10
|
172 (conj () 1 2) '(2 1)
|
rlm@10
|
173
|
rlm@10
|
174 (conj '(2 3) 1) '(1 2 3)
|
rlm@10
|
175 (conj '(2 3) 1 4 3) '(3 4 1 2 3)
|
rlm@10
|
176
|
rlm@10
|
177 (conj () nil) '(nil)
|
rlm@10
|
178 (conj () ()) '(())
|
rlm@10
|
179
|
rlm@10
|
180 ; vector -> conj puts the item at the end of the vector
|
rlm@10
|
181 (conj [] 1) [1]
|
rlm@10
|
182 (conj [] 1 2) [1 2]
|
rlm@10
|
183
|
rlm@10
|
184 (conj [2 3] 1) [2 3 1]
|
rlm@10
|
185 (conj [2 3] 1 4 3) [2 3 1 4 3]
|
rlm@10
|
186
|
rlm@10
|
187 (conj [] nil) [nil]
|
rlm@10
|
188 (conj [] []) [[]]
|
rlm@10
|
189
|
rlm@10
|
190 ; map -> conj expects another (possibly single entry) map as the item,
|
rlm@10
|
191 ; and returns a new map which is the old map plus the entries
|
rlm@10
|
192 ; from the new, which may overwrite entries of the old.
|
rlm@10
|
193 ; conj also accepts a MapEntry or a vector of two items (key and value).
|
rlm@10
|
194 (conj {} {}) {}
|
rlm@10
|
195 (conj {} {:a 1}) {:a 1}
|
rlm@10
|
196 (conj {} {:a 1 :b 2}) {:a 1 :b 2}
|
rlm@10
|
197 (conj {} {:a 1 :b 2} {:c 3}) {:a 1 :b 2 :c 3}
|
rlm@10
|
198 (conj {} {:a 1 :b 2} {:a 3 :c 4}) {:a 3 :b 2 :c 4}
|
rlm@10
|
199
|
rlm@10
|
200 (conj {:a 1} {:a 7}) {:a 7}
|
rlm@10
|
201 (conj {:a 1} {:b 2}) {:a 1 :b 2}
|
rlm@10
|
202 (conj {:a 1} {:a 7 :b 2}) {:a 7 :b 2}
|
rlm@10
|
203 (conj {:a 1} {:a 7 :b 2} {:c 3}) {:a 7 :b 2 :c 3}
|
rlm@10
|
204 (conj {:a 1} {:a 7 :b 2} {:b 4 :c 5}) {:a 7 :b 4 :c 5}
|
rlm@10
|
205
|
rlm@10
|
206 (conj {} (first {:a 1})) {:a 1} ; MapEntry
|
rlm@10
|
207 (conj {:a 1} (first {:b 2})) {:a 1 :b 2}
|
rlm@10
|
208 (conj {:a 1} (first {:a 7})) {:a 7}
|
rlm@10
|
209 (conj {:a 1} (first {:b 2}) (first {:a 5})) {:a 5 :b 2}
|
rlm@10
|
210
|
rlm@10
|
211 (conj {} [:a 1]) {:a 1} ; vector
|
rlm@10
|
212 (conj {:a 1} [:b 2]) {:a 1 :b 2}
|
rlm@10
|
213 (conj {:a 1} [:a 7]) {:a 7}
|
rlm@10
|
214 (conj {:a 1} [:b 2] [:a 5]) {:a 5 :b 2}
|
rlm@10
|
215
|
rlm@10
|
216 (conj {} {nil {}}) {nil {}}
|
rlm@10
|
217 (conj {} {{} nil}) {{} nil}
|
rlm@10
|
218 (conj {} {{} {}}) {{} {}}
|
rlm@10
|
219
|
rlm@10
|
220 ; set
|
rlm@10
|
221 (conj #{} 1) #{1}
|
rlm@10
|
222 (conj #{} 1 2 3) #{1 2 3}
|
rlm@10
|
223
|
rlm@10
|
224 (conj #{2 3} 1) #{3 1 2}
|
rlm@10
|
225 (conj #{3 2} 1) #{1 2 3}
|
rlm@10
|
226
|
rlm@10
|
227 (conj #{2 3} 2) #{2 3}
|
rlm@10
|
228 (conj #{2 3} 2 3) #{2 3}
|
rlm@10
|
229 (conj #{2 3} 4 1 2 3) #{1 2 3 4}
|
rlm@10
|
230
|
rlm@10
|
231 (conj #{} nil) #{nil}
|
rlm@10
|
232 (conj #{} #{}) #{#{}} ))
|
rlm@10
|
233
|
rlm@10
|
234
|
rlm@10
|
235 ;; *** Lists and Vectors ***
|
rlm@10
|
236
|
rlm@10
|
237 (deftest test-peek
|
rlm@10
|
238 ; doesn't work for sets and maps
|
rlm@10
|
239 (is (thrown? ClassCastException (peek #{1})))
|
rlm@10
|
240 (is (thrown? ClassCastException (peek {:a 1})))
|
rlm@10
|
241
|
rlm@10
|
242 (are [x y] (= x y)
|
rlm@10
|
243 (peek nil) nil
|
rlm@10
|
244
|
rlm@10
|
245 ; list = first
|
rlm@10
|
246 (peek ()) nil
|
rlm@10
|
247 (peek '(1)) 1
|
rlm@10
|
248 (peek '(1 2 3)) 1
|
rlm@10
|
249
|
rlm@10
|
250 (peek '(nil)) nil ; special cases
|
rlm@10
|
251 (peek '(1 nil)) 1
|
rlm@10
|
252 (peek '(nil 2)) nil
|
rlm@10
|
253 (peek '(())) ()
|
rlm@10
|
254 (peek '(() nil)) ()
|
rlm@10
|
255 (peek '(() 2 nil)) ()
|
rlm@10
|
256
|
rlm@10
|
257 ; vector = last
|
rlm@10
|
258 (peek []) nil
|
rlm@10
|
259 (peek [1]) 1
|
rlm@10
|
260 (peek [1 2 3]) 3
|
rlm@10
|
261
|
rlm@10
|
262 (peek [nil]) nil ; special cases
|
rlm@10
|
263 (peek [1 nil]) nil
|
rlm@10
|
264 (peek [nil 2]) 2
|
rlm@10
|
265 (peek [[]]) []
|
rlm@10
|
266 (peek [[] nil]) nil
|
rlm@10
|
267 (peek [[] 2 nil]) nil ))
|
rlm@10
|
268
|
rlm@10
|
269
|
rlm@10
|
270 (deftest test-pop
|
rlm@10
|
271 ; doesn't work for sets and maps
|
rlm@10
|
272 (is (thrown? ClassCastException (pop #{1})))
|
rlm@10
|
273 (is (thrown? ClassCastException (pop #{:a 1})))
|
rlm@10
|
274
|
rlm@10
|
275 ; collection cannot be empty
|
rlm@10
|
276 (is (thrown? IllegalStateException (pop ())))
|
rlm@10
|
277 (is (thrown? IllegalStateException (pop [])))
|
rlm@10
|
278
|
rlm@10
|
279 (are [x y] (= x y)
|
rlm@10
|
280 (pop nil) nil
|
rlm@10
|
281
|
rlm@10
|
282 ; list - pop first
|
rlm@10
|
283 (pop '(1)) ()
|
rlm@10
|
284 (pop '(1 2 3)) '(2 3)
|
rlm@10
|
285
|
rlm@10
|
286 (pop '(nil)) ()
|
rlm@10
|
287 (pop '(1 nil)) '(nil)
|
rlm@10
|
288 (pop '(nil 2)) '(2)
|
rlm@10
|
289 (pop '(())) ()
|
rlm@10
|
290 (pop '(() nil)) '(nil)
|
rlm@10
|
291 (pop '(() 2 nil)) '(2 nil)
|
rlm@10
|
292
|
rlm@10
|
293 ; vector - pop last
|
rlm@10
|
294 (pop [1]) []
|
rlm@10
|
295 (pop [1 2 3]) [1 2]
|
rlm@10
|
296
|
rlm@10
|
297 (pop [nil]) []
|
rlm@10
|
298 (pop [1 nil]) [1]
|
rlm@10
|
299 (pop [nil 2]) [nil]
|
rlm@10
|
300 (pop [[]]) []
|
rlm@10
|
301 (pop [[] nil]) [[]]
|
rlm@10
|
302 (pop [[] 2 nil]) [[] 2] ))
|
rlm@10
|
303
|
rlm@10
|
304
|
rlm@10
|
305 ;; *** Lists (IPersistentList) ***
|
rlm@10
|
306
|
rlm@10
|
307 (deftest test-list
|
rlm@10
|
308 (are [x] (list? x)
|
rlm@10
|
309 ()
|
rlm@10
|
310 '()
|
rlm@10
|
311 (list)
|
rlm@10
|
312 (list 1 2 3) )
|
rlm@10
|
313
|
rlm@10
|
314 ; order is important
|
rlm@10
|
315 (are [x y] (not (= x y))
|
rlm@10
|
316 (list 1 2) (list 2 1)
|
rlm@10
|
317 (list 3 1 2) (list 1 2 3) )
|
rlm@10
|
318
|
rlm@10
|
319 (are [x y] (= x y)
|
rlm@10
|
320 '() ()
|
rlm@10
|
321 (list) '()
|
rlm@10
|
322 (list 1) '(1)
|
rlm@10
|
323 (list 1 2) '(1 2)
|
rlm@10
|
324
|
rlm@10
|
325 ; nesting
|
rlm@10
|
326 (list 1 (list 2 3) (list 3 (list 4 5 (list 6 (list 7)))))
|
rlm@10
|
327 '(1 (2 3) (3 (4 5 (6 (7)))))
|
rlm@10
|
328
|
rlm@10
|
329 ; different data structures
|
rlm@10
|
330 (list true false nil)
|
rlm@10
|
331 '(true false nil)
|
rlm@10
|
332 (list 1 2.5 2/3 "ab" \x 'cd :kw)
|
rlm@10
|
333 '(1 2.5 2/3 "ab" \x cd :kw)
|
rlm@10
|
334 (list (list 1 2) [3 4] {:a 1 :b 2} #{:c :d})
|
rlm@10
|
335 '((1 2) [3 4] {:a 1 :b 2} #{:c :d})
|
rlm@10
|
336
|
rlm@10
|
337 ; evaluation
|
rlm@10
|
338 (list (+ 1 2) [(+ 2 3) 'a] (list (* 2 3) 8))
|
rlm@10
|
339 '(3 [5 a] (6 8))
|
rlm@10
|
340
|
rlm@10
|
341 ; special cases
|
rlm@10
|
342 (list nil) '(nil)
|
rlm@10
|
343 (list 1 nil) '(1 nil)
|
rlm@10
|
344 (list nil 2) '(nil 2)
|
rlm@10
|
345 (list ()) '(())
|
rlm@10
|
346 (list 1 ()) '(1 ())
|
rlm@10
|
347 (list () 2) '(() 2) ))
|
rlm@10
|
348
|
rlm@10
|
349
|
rlm@10
|
350 ;; *** Maps (IPersistentMap) ***
|
rlm@10
|
351
|
rlm@10
|
352 (deftest test-find
|
rlm@10
|
353 (are [x y] (= x y)
|
rlm@10
|
354 (find {} :a) nil
|
rlm@10
|
355
|
rlm@10
|
356 (find {:a 1} :a) [:a 1]
|
rlm@10
|
357 (find {:a 1} :b) nil
|
rlm@10
|
358
|
rlm@10
|
359 (find {:a 1 :b 2} :a) [:a 1]
|
rlm@10
|
360 (find {:a 1 :b 2} :b) [:b 2]
|
rlm@10
|
361 (find {:a 1 :b 2} :c) nil
|
rlm@10
|
362
|
rlm@10
|
363 (find {} nil) nil
|
rlm@10
|
364 (find {:a 1} nil) nil
|
rlm@10
|
365 (find {:a 1 :b 2} nil) nil ))
|
rlm@10
|
366
|
rlm@10
|
367
|
rlm@10
|
368 (deftest test-contains?
|
rlm@10
|
369 ; contains? is designed to work preferably on maps and sets
|
rlm@10
|
370 (are [x y] (= x y)
|
rlm@10
|
371 (contains? {} :a) false
|
rlm@10
|
372 (contains? {} nil) false
|
rlm@10
|
373
|
rlm@10
|
374 (contains? {:a 1} :a) true
|
rlm@10
|
375 (contains? {:a 1} :b) false
|
rlm@10
|
376 (contains? {:a 1} nil) false
|
rlm@10
|
377
|
rlm@10
|
378 (contains? {:a 1 :b 2} :a) true
|
rlm@10
|
379 (contains? {:a 1 :b 2} :b) true
|
rlm@10
|
380 (contains? {:a 1 :b 2} :c) false
|
rlm@10
|
381 (contains? {:a 1 :b 2} nil) false
|
rlm@10
|
382
|
rlm@10
|
383 ; sets
|
rlm@10
|
384 (contains? #{} 1) false
|
rlm@10
|
385 (contains? #{} nil) false
|
rlm@10
|
386
|
rlm@10
|
387 (contains? #{1} 1) true
|
rlm@10
|
388 (contains? #{1} 2) false
|
rlm@10
|
389 (contains? #{1} nil) false
|
rlm@10
|
390
|
rlm@10
|
391 (contains? #{1 2 3} 1) true
|
rlm@10
|
392 (contains? #{1 2 3} 3) true
|
rlm@10
|
393 (contains? #{1 2 3} 10) false
|
rlm@10
|
394 (contains? #{1 2 3} nil) false)
|
rlm@10
|
395
|
rlm@10
|
396 ; numerically indexed collections (e.g. vectors and Java arrays)
|
rlm@10
|
397 ; => test if the numeric key is WITHIN THE RANGE OF INDEXES
|
rlm@10
|
398 (are [x y] (= x y)
|
rlm@10
|
399 (contains? [] 0) false
|
rlm@10
|
400 (contains? [] -1) false
|
rlm@10
|
401 (contains? [] 1) false
|
rlm@10
|
402
|
rlm@10
|
403 (contains? [1] 0) true
|
rlm@10
|
404 (contains? [1] -1) false
|
rlm@10
|
405 (contains? [1] 1) false
|
rlm@10
|
406
|
rlm@10
|
407 (contains? [1 2 3] 0) true
|
rlm@10
|
408 (contains? [1 2 3] 2) true
|
rlm@10
|
409 (contains? [1 2 3] 3) false
|
rlm@10
|
410 (contains? [1 2 3] -1) false
|
rlm@10
|
411
|
rlm@10
|
412 ; arrays
|
rlm@10
|
413 (contains? (into-array []) 0) false
|
rlm@10
|
414 (contains? (into-array []) -1) false
|
rlm@10
|
415 (contains? (into-array []) 1) false
|
rlm@10
|
416
|
rlm@10
|
417 (contains? (into-array [1]) 0) true
|
rlm@10
|
418 (contains? (into-array [1]) -1) false
|
rlm@10
|
419 (contains? (into-array [1]) 1) false
|
rlm@10
|
420
|
rlm@10
|
421 (contains? (into-array [1 2 3]) 0) true
|
rlm@10
|
422 (contains? (into-array [1 2 3]) 2) true
|
rlm@10
|
423 (contains? (into-array [1 2 3]) 3) false
|
rlm@10
|
424 (contains? (into-array [1 2 3]) -1) false)
|
rlm@10
|
425
|
rlm@10
|
426 ; 'contains?' operates constant or logarithmic time,
|
rlm@10
|
427 ; it WILL NOT perform a linear search for a value.
|
rlm@10
|
428 (are [x] (= x false)
|
rlm@10
|
429 (contains? '(1 2 3) 0)
|
rlm@10
|
430 (contains? '(1 2 3) 1)
|
rlm@10
|
431 (contains? '(1 2 3) 3)
|
rlm@10
|
432 (contains? '(1 2 3) 10)
|
rlm@10
|
433 (contains? '(1 2 3) nil)
|
rlm@10
|
434 (contains? '(1 2 3) ()) ))
|
rlm@10
|
435
|
rlm@10
|
436
|
rlm@10
|
437 (deftest test-keys
|
rlm@10
|
438 (are [x y] (= x y) ; other than map data structures
|
rlm@10
|
439 (keys ()) nil
|
rlm@10
|
440 (keys []) nil
|
rlm@10
|
441 (keys #{}) nil
|
rlm@10
|
442 (keys "") nil )
|
rlm@10
|
443
|
rlm@10
|
444 (are [x y] (= x y)
|
rlm@10
|
445 ; (class {:a 1}) => clojure.lang.PersistentArrayMap
|
rlm@10
|
446 (keys {}) nil
|
rlm@10
|
447 (keys {:a 1}) '(:a)
|
rlm@10
|
448 (diff (keys {:a 1 :b 2}) '(:a :b)) nil ; (keys {:a 1 :b 2}) '(:a :b)
|
rlm@10
|
449
|
rlm@10
|
450 ; (class (sorted-map :a 1)) => clojure.lang.PersistentTreeMap
|
rlm@10
|
451 (keys (sorted-map)) nil
|
rlm@10
|
452 (keys (sorted-map :a 1)) '(:a)
|
rlm@10
|
453 (diff (keys (sorted-map :a 1 :b 2)) '(:a :b)) nil ; (keys (sorted-map :a 1 :b 2)) '(:a :b)
|
rlm@10
|
454
|
rlm@10
|
455 ; (class (hash-map :a 1)) => clojure.lang.PersistentHashMap
|
rlm@10
|
456 (keys (hash-map)) nil
|
rlm@10
|
457 (keys (hash-map :a 1)) '(:a)
|
rlm@10
|
458 (diff (keys (hash-map :a 1 :b 2)) '(:a :b)) nil )) ; (keys (hash-map :a 1 :b 2)) '(:a :b)
|
rlm@10
|
459
|
rlm@10
|
460
|
rlm@10
|
461 (deftest test-vals
|
rlm@10
|
462 (are [x y] (= x y) ; other than map data structures
|
rlm@10
|
463 (vals ()) nil
|
rlm@10
|
464 (vals []) nil
|
rlm@10
|
465 (vals #{}) nil
|
rlm@10
|
466 (vals "") nil )
|
rlm@10
|
467
|
rlm@10
|
468 (are [x y] (= x y)
|
rlm@10
|
469 ; (class {:a 1}) => clojure.lang.PersistentArrayMap
|
rlm@10
|
470 (vals {}) nil
|
rlm@10
|
471 (vals {:a 1}) '(1)
|
rlm@10
|
472 (diff (vals {:a 1 :b 2}) '(1 2)) nil ; (vals {:a 1 :b 2}) '(1 2)
|
rlm@10
|
473
|
rlm@10
|
474 ; (class (sorted-map :a 1)) => clojure.lang.PersistentTreeMap
|
rlm@10
|
475 (vals (sorted-map)) nil
|
rlm@10
|
476 (vals (sorted-map :a 1)) '(1)
|
rlm@10
|
477 (diff (vals (sorted-map :a 1 :b 2)) '(1 2)) nil ; (vals (sorted-map :a 1 :b 2)) '(1 2)
|
rlm@10
|
478
|
rlm@10
|
479 ; (class (hash-map :a 1)) => clojure.lang.PersistentHashMap
|
rlm@10
|
480 (vals (hash-map)) nil
|
rlm@10
|
481 (vals (hash-map :a 1)) '(1)
|
rlm@10
|
482 (diff (vals (hash-map :a 1 :b 2)) '(1 2)) nil )) ; (vals (hash-map :a 1 :b 2)) '(1 2)
|
rlm@10
|
483
|
rlm@10
|
484
|
rlm@10
|
485 (deftest test-key
|
rlm@10
|
486 (are [x] (= (key (first (hash-map x :value))) x)
|
rlm@10
|
487 nil
|
rlm@10
|
488 false true
|
rlm@10
|
489 0 42
|
rlm@10
|
490 0.0 3.14
|
rlm@10
|
491 2/3
|
rlm@10
|
492 0M 1M
|
rlm@10
|
493 \c
|
rlm@10
|
494 "" "abc"
|
rlm@10
|
495 'sym
|
rlm@10
|
496 :kw
|
rlm@10
|
497 () '(1 2)
|
rlm@10
|
498 [] [1 2]
|
rlm@10
|
499 {} {:a 1 :b 2}
|
rlm@10
|
500 #{} #{1 2} ))
|
rlm@10
|
501
|
rlm@10
|
502
|
rlm@10
|
503 (deftest test-val
|
rlm@10
|
504 (are [x] (= (val (first (hash-map :key x))) x)
|
rlm@10
|
505 nil
|
rlm@10
|
506 false true
|
rlm@10
|
507 0 42
|
rlm@10
|
508 0.0 3.14
|
rlm@10
|
509 2/3
|
rlm@10
|
510 0M 1M
|
rlm@10
|
511 \c
|
rlm@10
|
512 "" "abc"
|
rlm@10
|
513 'sym
|
rlm@10
|
514 :kw
|
rlm@10
|
515 () '(1 2)
|
rlm@10
|
516 [] [1 2]
|
rlm@10
|
517 {} {:a 1 :b 2}
|
rlm@10
|
518 #{} #{1 2} ))
|
rlm@10
|
519
|
rlm@10
|
520 (deftest test-get
|
rlm@10
|
521 (let [m {:a 1, :b 2, :c {:d 3, :e 4}, :f nil, :g false, nil {:h 5}}]
|
rlm@10
|
522 (is (thrown? IllegalArgumentException (get-in {:a 1} 5)))
|
rlm@10
|
523 (are [x y] (= x y)
|
rlm@10
|
524 (get m :a) 1
|
rlm@10
|
525 (get m :e) nil
|
rlm@10
|
526 (get m :e 0) 0
|
rlm@10
|
527 (get m :b 0) 2
|
rlm@10
|
528 (get m :f 0) nil
|
rlm@10
|
529
|
rlm@10
|
530 (get-in m [:c :e]) 4
|
rlm@10
|
531 (get-in m '(:c :e)) 4
|
rlm@10
|
532 (get-in m [:c :x]) nil
|
rlm@10
|
533 (get-in m [:f]) nil
|
rlm@10
|
534 (get-in m [:g]) false
|
rlm@10
|
535 (get-in m [:h]) nil
|
rlm@10
|
536 (get-in m []) m
|
rlm@10
|
537 (get-in m nil) m
|
rlm@10
|
538
|
rlm@10
|
539 (get-in m [:c :e] 0) 4
|
rlm@10
|
540 (get-in m '(:c :e) 0) 4
|
rlm@10
|
541 (get-in m [:c :x] 0) 0
|
rlm@10
|
542 (get-in m [:b] 0) 2
|
rlm@10
|
543 (get-in m [:f] 0) nil
|
rlm@10
|
544 (get-in m [:g] 0) false
|
rlm@10
|
545 (get-in m [:h] 0) 0
|
rlm@10
|
546 (get-in m [:x :y] {:y 1}) {:y 1}
|
rlm@10
|
547 (get-in m [] 0) m
|
rlm@10
|
548 (get-in m nil 0) m)))
|
rlm@10
|
549
|
rlm@10
|
550 ;; *** Sets ***
|
rlm@10
|
551
|
rlm@10
|
552 (deftest test-hash-set
|
rlm@10
|
553 (are [x] (set? x)
|
rlm@10
|
554 #{}
|
rlm@10
|
555 #{1 2}
|
rlm@10
|
556 (hash-set)
|
rlm@10
|
557 (hash-set 1 2) )
|
rlm@10
|
558
|
rlm@10
|
559 ; order isn't important
|
rlm@10
|
560 (are [x y] (= x y)
|
rlm@10
|
561 #{1 2} #{2 1}
|
rlm@10
|
562 #{3 1 2} #{1 2 3}
|
rlm@10
|
563 (hash-set 1 2) (hash-set 2 1)
|
rlm@10
|
564 (hash-set 3 1 2) (hash-set 1 2 3) )
|
rlm@10
|
565
|
rlm@10
|
566
|
rlm@10
|
567 (are [x y] (= x y)
|
rlm@10
|
568 ; equal classes
|
rlm@10
|
569 (class #{}) (class (hash-set))
|
rlm@10
|
570 (class #{1 2}) (class (hash-set 1 2))
|
rlm@10
|
571
|
rlm@10
|
572 ; creating
|
rlm@10
|
573 (hash-set) #{}
|
rlm@10
|
574 (hash-set 1) #{1}
|
rlm@10
|
575 (hash-set 1 2) #{1 2}
|
rlm@10
|
576
|
rlm@10
|
577 ; nesting
|
rlm@10
|
578 (hash-set 1 (hash-set 2 3) (hash-set 3 (hash-set 4 5 (hash-set 6 (hash-set 7)))))
|
rlm@10
|
579 #{1 #{2 3} #{3 #{4 5 #{6 #{7}}}}}
|
rlm@10
|
580
|
rlm@10
|
581 ; different data structures
|
rlm@10
|
582 (hash-set true false nil)
|
rlm@10
|
583 #{true false nil}
|
rlm@10
|
584 (hash-set 1 2.5 2/3 "ab" \x 'cd :kw)
|
rlm@10
|
585 #{1 2.5 2/3 "ab" \x 'cd :kw}
|
rlm@10
|
586 (hash-set (list 1 2) [3 4] {:a 1 :b 2} #{:c :d})
|
rlm@10
|
587 #{'(1 2) [3 4] {:a 1 :b 2} #{:c :d}}
|
rlm@10
|
588
|
rlm@10
|
589 ; evaluation
|
rlm@10
|
590 (hash-set (+ 1 2) [(+ 2 3) :a] (hash-set (* 2 3) 8))
|
rlm@10
|
591 #{3 [5 :a] #{6 8}}
|
rlm@10
|
592
|
rlm@10
|
593 ; special cases
|
rlm@10
|
594 (hash-set nil) #{nil}
|
rlm@10
|
595 (hash-set 1 nil) #{1 nil}
|
rlm@10
|
596 (hash-set nil 2) #{nil 2}
|
rlm@10
|
597 (hash-set #{}) #{#{}}
|
rlm@10
|
598 (hash-set 1 #{}) #{1 #{}}
|
rlm@10
|
599 (hash-set #{} 2) #{#{} 2} ))
|
rlm@10
|
600
|
rlm@10
|
601
|
rlm@10
|
602 (deftest test-sorted-set
|
rlm@10
|
603 ; only compatible types can be used
|
rlm@10
|
604 (is (thrown? ClassCastException (sorted-set 1 "a")))
|
rlm@10
|
605 (is (thrown? ClassCastException (sorted-set '(1 2) [3 4])))
|
rlm@10
|
606
|
rlm@10
|
607 ; creates set?
|
rlm@10
|
608 (are [x] (set? x)
|
rlm@10
|
609 (sorted-set)
|
rlm@10
|
610 (sorted-set 1 2) )
|
rlm@10
|
611
|
rlm@10
|
612 ; equal and unique
|
rlm@10
|
613 (are [x] (and (= (sorted-set x) #{x})
|
rlm@10
|
614 (= (sorted-set x x) (sorted-set x)))
|
rlm@10
|
615 nil
|
rlm@10
|
616 false true
|
rlm@10
|
617 0 42
|
rlm@10
|
618 0.0 3.14
|
rlm@10
|
619 2/3
|
rlm@10
|
620 0M 1M
|
rlm@10
|
621 \c
|
rlm@10
|
622 "" "abc"
|
rlm@10
|
623 'sym
|
rlm@10
|
624 :kw
|
rlm@10
|
625 () ; '(1 2)
|
rlm@10
|
626 [] [1 2]
|
rlm@10
|
627 {} ; {:a 1 :b 2}
|
rlm@10
|
628 #{} ; #{1 2}
|
rlm@10
|
629 )
|
rlm@10
|
630 ; cannot be cast to java.lang.Comparable
|
rlm@10
|
631 (is (thrown? ClassCastException (sorted-set '(1 2) '(1 2))))
|
rlm@10
|
632 (is (thrown? ClassCastException (sorted-set {:a 1 :b 2} {:a 1 :b 2})))
|
rlm@10
|
633 (is (thrown? ClassCastException (sorted-set #{1 2} #{1 2})))
|
rlm@10
|
634
|
rlm@10
|
635 (are [x y] (= x y)
|
rlm@10
|
636 ; generating
|
rlm@10
|
637 (sorted-set) #{}
|
rlm@10
|
638 (sorted-set 1) #{1}
|
rlm@10
|
639 (sorted-set 1 2) #{1 2}
|
rlm@10
|
640
|
rlm@10
|
641 ; sorting
|
rlm@10
|
642 (seq (sorted-set 5 4 3 2 1)) '(1 2 3 4 5)
|
rlm@10
|
643
|
rlm@10
|
644 ; special cases
|
rlm@10
|
645 (sorted-set nil) #{nil}
|
rlm@10
|
646 (sorted-set 1 nil) #{nil 1}
|
rlm@10
|
647 (sorted-set nil 2) #{nil 2}
|
rlm@10
|
648 (sorted-set #{}) #{#{}} ))
|
rlm@10
|
649
|
rlm@10
|
650
|
rlm@10
|
651 (deftest test-sorted-set-by
|
rlm@10
|
652 ; only compatible types can be used
|
rlm@10
|
653 ; NB: not a ClassCastException, but a RuntimeException is thrown,
|
rlm@10
|
654 ; requires discussion on whether this should be symmetric with test-sorted-set
|
rlm@10
|
655 (is (thrown? Exception (sorted-set-by < 1 "a")))
|
rlm@10
|
656 (is (thrown? Exception (sorted-set-by < '(1 2) [3 4])))
|
rlm@10
|
657
|
rlm@10
|
658 ; creates set?
|
rlm@10
|
659 (are [x] (set? x)
|
rlm@10
|
660 (sorted-set-by <)
|
rlm@10
|
661 (sorted-set-by < 1 2) )
|
rlm@10
|
662
|
rlm@10
|
663 ; equal and unique
|
rlm@10
|
664 (are [x] (and (= (sorted-set-by compare x) #{x})
|
rlm@10
|
665 (= (sorted-set-by compare x x) (sorted-set-by compare x)))
|
rlm@10
|
666 nil
|
rlm@10
|
667 false true
|
rlm@10
|
668 0 42
|
rlm@10
|
669 0.0 3.14
|
rlm@10
|
670 2/3
|
rlm@10
|
671 0M 1M
|
rlm@10
|
672 \c
|
rlm@10
|
673 "" "abc"
|
rlm@10
|
674 'sym
|
rlm@10
|
675 :kw
|
rlm@10
|
676 () ; '(1 2)
|
rlm@10
|
677 [] [1 2]
|
rlm@10
|
678 {} ; {:a 1 :b 2}
|
rlm@10
|
679 #{} ; #{1 2}
|
rlm@10
|
680 )
|
rlm@10
|
681 ; cannot be cast to java.lang.Comparable
|
rlm@10
|
682 ; NB: not a ClassCastException, but a RuntimeException is thrown,
|
rlm@10
|
683 ; requires discussion on whether this should be symmetric with test-sorted-set
|
rlm@10
|
684 (is (thrown? Exception (sorted-set-by compare '(1 2) '(1 2))))
|
rlm@10
|
685 (is (thrown? Exception (sorted-set-by compare {:a 1 :b 2} {:a 1 :b 2})))
|
rlm@10
|
686 (is (thrown? Exception (sorted-set-by compare #{1 2} #{1 2})))
|
rlm@10
|
687
|
rlm@10
|
688 (are [x y] (= x y)
|
rlm@10
|
689 ; generating
|
rlm@10
|
690 (sorted-set-by >) #{}
|
rlm@10
|
691 (sorted-set-by > 1) #{1}
|
rlm@10
|
692 (sorted-set-by > 1 2) #{1 2}
|
rlm@10
|
693
|
rlm@10
|
694 ; sorting
|
rlm@10
|
695 (seq (sorted-set-by < 5 4 3 2 1)) '(1 2 3 4 5)
|
rlm@10
|
696
|
rlm@10
|
697 ; special cases
|
rlm@10
|
698 (sorted-set-by compare nil) #{nil}
|
rlm@10
|
699 (sorted-set-by compare 1 nil) #{nil 1}
|
rlm@10
|
700 (sorted-set-by compare nil 2) #{nil 2}
|
rlm@10
|
701 (sorted-set-by compare #{}) #{#{}} ))
|
rlm@10
|
702
|
rlm@10
|
703
|
rlm@10
|
704 (deftest test-set
|
rlm@10
|
705 ; set?
|
rlm@10
|
706 (are [x] (set? (set x))
|
rlm@10
|
707 () '(1 2)
|
rlm@10
|
708 [] [1 2]
|
rlm@10
|
709 #{} #{1 2}
|
rlm@10
|
710 {} {:a 1 :b 2}
|
rlm@10
|
711 (into-array []) (into-array [1 2])
|
rlm@10
|
712 "" "abc" )
|
rlm@10
|
713
|
rlm@10
|
714 ; unique
|
rlm@10
|
715 (are [x] (= (set [x x]) #{x})
|
rlm@10
|
716 nil
|
rlm@10
|
717 false true
|
rlm@10
|
718 0 42
|
rlm@10
|
719 0.0 3.14
|
rlm@10
|
720 2/3
|
rlm@10
|
721 0M 1M
|
rlm@10
|
722 \c
|
rlm@10
|
723 "" "abc"
|
rlm@10
|
724 'sym
|
rlm@10
|
725 :kw
|
rlm@10
|
726 () '(1 2)
|
rlm@10
|
727 [] [1 2]
|
rlm@10
|
728 {} {:a 1 :b 2}
|
rlm@10
|
729 #{} #{1 2} )
|
rlm@10
|
730
|
rlm@10
|
731 ; conversion
|
rlm@10
|
732 (are [x y] (= (set x) y)
|
rlm@10
|
733 () #{}
|
rlm@10
|
734 '(1 2) #{1 2}
|
rlm@10
|
735
|
rlm@10
|
736 [] #{}
|
rlm@10
|
737 [1 2] #{1 2}
|
rlm@10
|
738
|
rlm@10
|
739 #{} #{} ; identity
|
rlm@10
|
740 #{1 2} #{1 2} ; identity
|
rlm@10
|
741
|
rlm@10
|
742 {} #{}
|
rlm@10
|
743 {:a 1 :b 2} #{[:a 1] [:b 2]}
|
rlm@10
|
744
|
rlm@10
|
745 (into-array []) #{}
|
rlm@10
|
746 (into-array [1 2]) #{1 2}
|
rlm@10
|
747
|
rlm@10
|
748 "" #{}
|
rlm@10
|
749 "abc" #{\a \b \c} ))
|
rlm@10
|
750
|
rlm@10
|
751
|
rlm@10
|
752 (deftest test-disj
|
rlm@10
|
753 ; doesn't work on lists, vectors or maps
|
rlm@10
|
754 (is (thrown? ClassCastException (disj '(1 2) 1)))
|
rlm@10
|
755 (is (thrown? ClassCastException (disj [1 2] 1)))
|
rlm@10
|
756 (is (thrown? ClassCastException (disj {:a 1} :a)))
|
rlm@10
|
757
|
rlm@10
|
758 ; identity
|
rlm@10
|
759 (are [x] (= (disj x) x)
|
rlm@10
|
760 nil
|
rlm@10
|
761 #{}
|
rlm@10
|
762 #{1 2 3}
|
rlm@10
|
763 ; different data types
|
rlm@10
|
764 #{nil
|
rlm@10
|
765 false true
|
rlm@10
|
766 0 42
|
rlm@10
|
767 0.0 3.14
|
rlm@10
|
768 2/3
|
rlm@10
|
769 0M 1M
|
rlm@10
|
770 \c
|
rlm@10
|
771 "" "abc"
|
rlm@10
|
772 'sym
|
rlm@10
|
773 :kw
|
rlm@10
|
774 [] [1 2]
|
rlm@10
|
775 {} {:a 1 :b 2}
|
rlm@10
|
776 #{} #{1 2}} )
|
rlm@10
|
777
|
rlm@10
|
778 ; type identity
|
rlm@10
|
779 (are [x] (= (class (disj x)) (class x))
|
rlm@10
|
780 (hash-set)
|
rlm@10
|
781 (hash-set 1 2)
|
rlm@10
|
782 (sorted-set)
|
rlm@10
|
783 (sorted-set 1 2) )
|
rlm@10
|
784
|
rlm@10
|
785 (are [x y] (= x y)
|
rlm@10
|
786 (disj nil :a) nil
|
rlm@10
|
787 (disj nil :a :b) nil
|
rlm@10
|
788
|
rlm@10
|
789 (disj #{} :a) #{}
|
rlm@10
|
790 (disj #{} :a :b) #{}
|
rlm@10
|
791
|
rlm@10
|
792 (disj #{:a} :a) #{}
|
rlm@10
|
793 (disj #{:a} :a :b) #{}
|
rlm@10
|
794 (disj #{:a} :c) #{:a}
|
rlm@10
|
795
|
rlm@10
|
796 (disj #{:a :b :c :d} :a) #{:b :c :d}
|
rlm@10
|
797 (disj #{:a :b :c :d} :a :d) #{:b :c}
|
rlm@10
|
798 (disj #{:a :b :c :d} :a :b :c) #{:d}
|
rlm@10
|
799 (disj #{:a :b :c :d} :d :a :c :b) #{}
|
rlm@10
|
800
|
rlm@10
|
801 (disj #{nil} :a) #{nil}
|
rlm@10
|
802 (disj #{nil} #{}) #{nil}
|
rlm@10
|
803 (disj #{nil} nil) #{}
|
rlm@10
|
804
|
rlm@10
|
805 (disj #{#{}} nil) #{#{}}
|
rlm@10
|
806 (disj #{#{}} #{}) #{}
|
rlm@10
|
807 (disj #{#{nil}} #{nil}) #{} ))
|
rlm@10
|
808
|
rlm@10
|
809
|
rlm@10
|
810 ;; *** Queues ***
|
rlm@10
|
811
|
rlm@10
|
812 (deftest test-queues
|
rlm@10
|
813 (let [EMPTY clojure.lang.PersistentQueue/EMPTY]
|
rlm@10
|
814 (are [x y] (= x y)
|
rlm@10
|
815 EMPTY EMPTY
|
rlm@10
|
816 (into EMPTY (range 50)) (into EMPTY (range 50))
|
rlm@10
|
817 (range 5) (into EMPTY (range 5))
|
rlm@10
|
818 (range 1 6) (-> EMPTY
|
rlm@10
|
819 (into (range 6))
|
rlm@10
|
820 pop))
|
rlm@10
|
821 (are [x y] (not= x y)
|
rlm@10
|
822 (range 5) (into EMPTY (range 6))
|
rlm@10
|
823 (range 6) (into EMPTY (range 5))
|
rlm@10
|
824 (range 0 6) (-> EMPTY
|
rlm@10
|
825 (into (range 6))
|
rlm@10
|
826 pop)
|
rlm@10
|
827 (range 1 6) (-> EMPTY
|
rlm@10
|
828 (into (range 7))
|
rlm@10
|
829 pop))))
|
rlm@10
|
830
|