annotate src/clojure/test_clojure/data_structures.clj @ 10:ef7dbbd6452c

added clojure source goodness
author Robert McIntyre <rlm@mit.edu>
date Sat, 21 Aug 2010 06:25:44 -0400
parents
children
rev   line source
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