diff options
Diffstat (limited to 'test/clojure/test_clojure')
29 files changed, 4303 insertions, 0 deletions
diff --git a/test/clojure/test_clojure/agents.clj b/test/clojure/test_clojure/agents.clj new file mode 100644 index 00000000..044e68ee --- /dev/null +++ b/test/clojure/test_clojure/agents.clj @@ -0,0 +1,41 @@ +;; Copyright (c) Shawn Hoover. All rights reserved. The use and +;; distribution terms for this software are covered by the Eclipse Public +;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which can +;; be found in the file epl-v10.html at the root of this distribution. By +;; using this software in any fashion, you are agreeing to be bound by the +;; terms of this license. You must not remove this notice, or any other, +;; from this software. + +(ns clojure.test-clojure.agents + (:use clojure.test)) + +(deftest handle-all-throwables-during-agent-actions + ;; Bug fixed in r1198; previously hung Clojure or didn't report agent errors + ;; after OutOfMemoryError, yet wouldn't execute new actions. + (let [agt (agent nil)] + (send agt (fn [state] (throw (Throwable. "just testing Throwables")))) + (try + ;; Let the action finish; eat the "agent has errors" error that bubbles up + (await agt) + (catch RuntimeException _)) + (is (instance? Throwable (first (agent-errors agt)))) + (is (= 1 (count (agent-errors agt)))) + + ;; And now send an action that should work + (clear-agent-errors agt) + (is (= nil @agt)) + (send agt nil?) + (await agt) + (is (true? @agt)))) + + +; http://clojure.org/agents + +; agent +; deref, @-reader-macro, agent-errors +; send send-off clear-agent-errors +; await await-for +; set-validator get-validator +; add-watch remove-watch +; shutdown-agents + diff --git a/test/clojure/test_clojure/atoms.clj b/test/clojure/test_clojure/atoms.clj new file mode 100644 index 00000000..7ac36fcc --- /dev/null +++ b/test/clojure/test_clojure/atoms.clj @@ -0,0 +1,18 @@ +;; Copyright (c) Frantisek Sodomka. All rights reserved. The use and +;; distribution terms for this software are covered by the Eclipse Public +;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which can +;; be found in the file epl-v10.html at the root of this distribution. By +;; using this software in any fashion, you are agreeing to be bound by the +;; terms of this license. You must not remove this notice, or any other, +;; from this software. + +(ns clojure.test-clojure.atoms + (:use clojure.test)) + +; http://clojure.org/atoms + +; atom +; deref, @-reader-macro +; swap! reset! +; compare-and-set! + diff --git a/test/clojure/test_clojure/clojure_set.clj b/test/clojure/test_clojure/clojure_set.clj new file mode 100644 index 00000000..9faf3410 --- /dev/null +++ b/test/clojure/test_clojure/clojure_set.clj @@ -0,0 +1,117 @@ +;; Copyright (c) Frantisek Sodomka. All rights reserved. The use and +;; distribution terms for this software are covered by the Eclipse Public +;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which can +;; be found in the file epl-v10.html at the root of this distribution. By +;; using this software in any fashion, you are agreeing to be bound by the +;; terms of this license. You must not remove this notice, or any other, +;; from this software. + +(ns clojure.test-clojure.clojure-set + (:use clojure.test) + (:require [clojure.set :as set])) + + +(deftest test-union + (are [x y] (= x y) + (set/union) #{} + + ; identity + (set/union #{}) #{} + (set/union #{1}) #{1} + (set/union #{1 2 3}) #{1 2 3} + + ; 2 sets, at least one is empty + (set/union #{} #{}) #{} + (set/union #{} #{1}) #{1} + (set/union #{} #{1 2 3}) #{1 2 3} + (set/union #{1} #{}) #{1} + (set/union #{1 2 3} #{}) #{1 2 3} + + ; 2 sets + (set/union #{1} #{2}) #{1 2} + (set/union #{1} #{1 2}) #{1 2} + (set/union #{2} #{1 2}) #{1 2} + (set/union #{1 2} #{3}) #{1 2 3} + (set/union #{1 2} #{2 3}) #{1 2 3} + + ; 3 sets, some are empty + (set/union #{} #{} #{}) #{} + (set/union #{1} #{} #{}) #{1} + (set/union #{} #{1} #{}) #{1} + (set/union #{} #{} #{1}) #{1} + (set/union #{1 2} #{2 3} #{}) #{1 2 3} + + ; 3 sets + (set/union #{1 2} #{3 4} #{5 6}) #{1 2 3 4 5 6} + (set/union #{1 2} #{2 3} #{1 3 4}) #{1 2 3 4} + + ; different data types + (set/union #{1 2} #{:a :b} #{nil} #{false true} #{\c "abc"} #{[] [1 2]} + #{{} {:a 1}} #{#{} #{1 2}}) + #{1 2 :a :b nil false true \c "abc" [] [1 2] {} {:a 1} #{} #{1 2}} + + ; different types of sets + (set/union (hash-set) (hash-set 1 2) (hash-set 2 3)) + (hash-set 1 2 3) + (set/union (sorted-set) (sorted-set 1 2) (sorted-set 2 3)) + (sorted-set 1 2 3) + (set/union (hash-set) (hash-set 1 2) (hash-set 2 3) + (sorted-set) (sorted-set 4 5) (sorted-set 5 6)) + (hash-set 1 2 3 4 5 6) ; also equals (sorted-set 1 2 3 4 5 6) +)) + + +(deftest test-intersection + ; at least one argument is needed + (is (thrown? IllegalArgumentException (set/intersection))) + + (are [x y] (= x y) + ; identity + (set/intersection #{}) #{} + (set/intersection #{1}) #{1} + (set/intersection #{1 2 3}) #{1 2 3} + + ; 2 sets, at least one is empty + (set/intersection #{} #{}) #{} + (set/intersection #{} #{1}) #{} + (set/intersection #{} #{1 2 3}) #{} + (set/intersection #{1} #{}) #{} + (set/intersection #{1 2 3} #{}) #{} + + ; 2 sets + (set/intersection #{1 2} #{1 2}) #{1 2} + (set/intersection #{1 2} #{3 4}) #{} + (set/intersection #{1 2} #{1}) #{1} + (set/intersection #{1 2} #{2}) #{2} + (set/intersection #{1 2 4} #{2 3 4 5}) #{2 4} + + ; 3 sets, some are empty + (set/intersection #{} #{} #{}) #{} + (set/intersection #{1} #{} #{}) #{} + (set/intersection #{1} #{1} #{}) #{} + (set/intersection #{1} #{} #{1}) #{} + (set/intersection #{1 2} #{2 3} #{}) #{} + + ; 3 sets + (set/intersection #{1 2} #{2 3} #{5 2}) #{2} + (set/intersection #{1 2 3} #{1 3 4} #{1 3}) #{1 3} + (set/intersection #{1 2 3} #{3 4 5} #{8 2 3}) #{3} + + ; different types of sets + (set/intersection (hash-set 1 2) (hash-set 2 3)) #{2} + (set/intersection (sorted-set 1 2) (sorted-set 2 3)) #{2} + (set/intersection + (hash-set 1 2) (hash-set 2 3) + (sorted-set 1 2) (sorted-set 2 3)) #{2} )) + + +; difference +; +; select +; project +; rename-keys +; rename +; index +; map-invert +; join + diff --git a/test/clojure/test_clojure/clojure_xml.clj b/test/clojure/test_clojure/clojure_xml.clj new file mode 100644 index 00000000..b9ab0829 --- /dev/null +++ b/test/clojure/test_clojure/clojure_xml.clj @@ -0,0 +1,18 @@ +;; Copyright (c) Frantisek Sodomka. All rights reserved. The use and +;; distribution terms for this software are covered by the Eclipse Public +;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which can +;; be found in the file epl-v10.html at the root of this distribution. By +;; using this software in any fashion, you are agreeing to be bound by the +;; terms of this license. You must not remove this notice, or any other, +;; from this software. + +(ns clojure.test-clojure.clojure-xml + (:use clojure.test) + (:require [clojure.xml :as xml])) + + +; parse + +; emit-element +; emit + diff --git a/test/clojure/test_clojure/clojure_zip.clj b/test/clojure/test_clojure/clojure_zip.clj new file mode 100644 index 00000000..b3e53e95 --- /dev/null +++ b/test/clojure/test_clojure/clojure_zip.clj @@ -0,0 +1,45 @@ +;; Copyright (c) Frantisek Sodomka. All rights reserved. The use and +;; distribution terms for this software are covered by the Eclipse Public +;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which can +;; be found in the file epl-v10.html at the root of this distribution. By +;; using this software in any fashion, you are agreeing to be bound by the +;; terms of this license. You must not remove this notice, or any other, +;; from this software. + +(ns clojure.test-clojure.clojure-zip + (:use clojure.test) + (:require [clojure.zip :as zip])) + + +; zipper +; +; seq-zip +; vector-zip +; xml-zip +; +; node +; branch? +; children +; make-node +; path +; lefts +; rights +; down +; up +; root +; right +; rightmost +; left +; leftmost +; +; insert-left +; insert-right +; replace +; edit +; insert-child +; append-child +; next +; prev +; end? +; remove + diff --git a/test/clojure/test_clojure/compilation.clj b/test/clojure/test_clojure/compilation.clj new file mode 100644 index 00000000..03557033 --- /dev/null +++ b/test/clojure/test_clojure/compilation.clj @@ -0,0 +1,36 @@ +;; Copyright (c) Frantisek Sodomka. All rights reserved. The use and +;; distribution terms for this software are covered by the Eclipse Public +;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which can +;; be found in the file epl-v10.html at the root of this distribution. By +;; using this software in any fashion, you are agreeing to be bound by the +;; terms of this license. You must not remove this notice, or any other, +;; from this software. + +(ns clojure.test-clojure.compilation + (:use clojure.test)) + +; http://clojure.org/compilation + +; compile +; gen-class, gen-interface + + +(deftest test-compiler-metadata + (let [m ^#'when] + (are [x y] (= x y) + (list? (:arglists m)) true + (> (count (:arglists m)) 0) true + + (string? (:doc m)) true + (> (.length (:doc m)) 0) true + + (string? (:file m)) true + (> (.length (:file m)) 0) true + + (integer? (:line m)) true + (> (:line m) 0) true + + (:macro m) true + (:name m) 'when ))) + + diff --git a/test/clojure/test_clojure/control.clj b/test/clojure/test_clojure/control.clj new file mode 100644 index 00000000..0b29e205 --- /dev/null +++ b/test/clojure/test_clojure/control.clj @@ -0,0 +1,114 @@ +;; Copyright (c) Frantisek Sodomka. All rights reserved. The use and +;; distribution terms for this software are covered by the Eclipse Public +;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which can +;; be found in the file epl-v10.html at the root of this distribution. By +;; using this software in any fashion, you are agreeing to be bound by the +;; terms of this license. You must not remove this notice, or any other, +;; from this software. +;; +;; Test "flow control" constructs. +;; + +(ns clojure.test-clojure.control + (:use clojure.test + [clojure.test-clojure.test-utils :only (exception)])) + +;; *** Helper functions *** + +(defn maintains-identity [f] + (are [x] (= (f x) x) + nil + false true + 0 42 + 0.0 3.14 + 2/3 + 0M 1M + \c + "" "abc" + 'sym + :kw + () '(1 2) + [] [1 2] + {} {:a 1 :b 2} + #{} #{1 2} )) + + +; http://clojure.org/special_forms +; http://clojure.org/macros + +(deftest test-do + (are [x y] (= x y) + ; no params => nil + (do) nil + + ; return last + (do 1) 1 + (do 1 2) 2 + (do 1 2 3 4 5) 5 + + ; evaluate and return last + (let [a (atom 0)] + (do (reset! a (+ @a 1)) ; 1 + (reset! a (+ @a 1)) ; 2 + (reset! a (+ @a 1)) ; 3 + @a)) 3 ) + + ; identity (= (do x) x) + (maintains-identity (fn [_] (do _))) ) + + +; loop/recur +; throw, try + +; [if (logic.clj)], if-not, if-let +; when, when-not, when-let, when-first + + +(deftest test-cond + (are [x y] (= x y) + (cond) nil + + (cond nil true) nil + (cond false true) nil + + (cond true 1 true (exception)) 1 + (cond nil 1 false 2 true 3 true 4) 3 + (cond nil 1 false 2 true 3 true (exception)) 3 ) + + ; false + (are [x] (= (cond x :a true :b) :b) + nil false ) + + ; true + (are [x] (= (cond x :a true :b) :a) + true + 0 42 + 0.0 3.14 + 2/3 + 0M 1M + \c + "" "abc" + 'sym + :kw + () '(1 2) + [] [1 2] + {} {:a 1 :b 2} + #{} #{1 2} ) + + ; evaluation + (are [x y] (= x y) + (cond (> 3 2) (+ 1 2) true :result true (exception)) 3 + (cond (< 3 2) (+ 1 2) true :result true (exception)) :result ) + + ; identity (= (cond true x) x) + (maintains-identity (fn [_] (cond true _))) ) + + +; condp + +; [for, doseq (for.clj)] + +; dotimes, while + +; locking, monitor-enter, monitor-exit + diff --git a/test/clojure/test_clojure/data_structures.clj b/test/clojure/test_clojure/data_structures.clj new file mode 100644 index 00000000..edca3955 --- /dev/null +++ b/test/clojure/test_clojure/data_structures.clj @@ -0,0 +1,734 @@ +;; Copyright (c) Frantisek Sodomka. All rights reserved. The use and +;; distribution terms for this software are covered by the Eclipse Public +;; License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which can +;; be found in the file epl-v10.html at the root of this distribution. By +;; using this software in any fashion, you are agreeing to be bound by the +;; terms of this license. You must not remove this notice, or any other, +;; from this software. +;; + +(ns clojure.test-clojure.data-structures + (:use clojure.test)) + + +;; *** Helper functions *** + +(defn diff [s1 s2] + (seq (reduce disj (set s1) (set s2)))) + + +;; *** General *** + +(defstruct equality-struct :a :b) + +(deftest test-equality + ; nil is not equal to any other value + (are [x] (not (= nil x)) + true false + 0 0.0 + \space + "" #"" + () [] #{} {} + (lazy-seq nil) ; SVN 1292: fixed (= (lazy-seq nil) nil) + (lazy-seq ()) + (lazy-seq []) + (lazy-seq {}) + (lazy-seq #{}) + (lazy-seq "") + (lazy-seq (into-array [])) + (new Object) ) + + ; numbers equality across types (see tests below - NOT IMPLEMENTED YET) + + ; ratios + (is (= 1/2 0.5)) + (is (= 1/1000 0.001)) + (is (not= 2/3 0.6666666666666666)) + + ; vectors equal other seqs by items equality + (are [x y] (= x y) + '() [] ; regression fixed in r1208; was not equal + '(1) [1] + '(1 2) [1 2] + + [] '() ; same again, but vectors first + [1] '(1) + [1 2] '(1 2) ) + (is (not= [1 2] '(2 1))) ; order of items matters + + ; list and vector vs. set and map + (are [x y] (not= x y) + ; only () equals [] + () #{} + () {} + [] #{} + [] {} + #{} {} + ; only '(1) equals [1] + '(1) #{1} + [1] #{1} ) + + ; sorted-map, hash-map and array-map - classes differ, but content is equal + +;; TODO: reimplement all-are with new do-template? +;; (all-are (not= (class _1) (class _2)) +;; (sorted-map :a 1) +;; (hash-map :a 1) +;; (array-map :a 1)) +;; (all-are (= _1 _2) +;; (sorted-map) +;; (hash-map) +;; (array-map)) +;; (all-are (= _1 _2) +;; (sorted-map :a 1) +;; (hash-map :a 1) +;; (array-map :a 1)) +;; (all-are (= _1 _2) +;; (sorted-map :a 1 :z 3 :c 2) +;; (hash-map :a 1 :z 3 :c 2) +;; (array-map :a 1 :z 3 :c 2)) + + ; struct-map vs. sorted-map, hash-map and array-map + (are [x] (and (not= (class (struct equality-struct 1 2)) (class x)) + (= (struct equality-struct 1 2) x)) + (sorted-map :a 1 :b 2) + (hash-map :a 1 :b 2) + (array-map :a 1 :b 2)) + + ; sorted-set vs. hash-set + (is (not= (class (sorted-set 1)) (class (hash-set 1)))) + (are [x y] (= x y) + (sorted-set) (hash-set) + (sorted-set 1) (hash-set 1) + (sorted-set 3 2 1) (hash-set 3 2 1) )) + + +;; *** Collections *** + +(deftest test-count + (are [x y] (= x y) + (count nil) 0 + + (count ()) 0 + (count '(1)) 1 + (count '(1 2 3)) 3 + + (count []) 0 + (count [1]) 1 + (count [1 2 3]) 3 + + (count #{}) 0 + (count #{1}) 1 + (count #{1 2 3}) 3 + + (count {}) 0 + (count {:a 1}) 1 + (count {:a 1 :b 2 :c 3}) 3 + + (count "") 0 + (count "a") 1 + (count "abc") 3 + + (count (into-array [])) 0 + (count (into-array [1])) 1 + (count (into-array [1 2 3])) 3 + + (count (java.util.ArrayList. [])) 0 + (count (java.util.ArrayList. [1])) 1 + (count (java.util.ArrayList. [1 2 3])) 3 + + (count (java.util.HashMap. {})) 0 + (count (java.util.HashMap. {:a 1})) 1 + (count (java.util.HashMap. {:a 1 :b 2 :c 3})) 3 ) + + ; different types + (are [x] (= (count [x]) 1) + nil true false + 0 0.0 "" \space + () [] #{} {} )) + + +(deftest test-conj + ; doesn't work on strings or arrays + (is (thrown? ClassCastException (conj "" \a))) + (is (thrown? ClassCastException (conj (into-array []) 1))) + + (are [x y] (= x y) + (conj nil 1) '(1) + (conj nil 3 2 1) '(1 2 3) + + (conj nil nil) '(nil) + (conj nil nil nil) '(nil nil) + (conj nil nil nil 1) '(1 nil nil) + + ; list -> conj puts the item at the front of the list + (conj () 1) '(1) + (conj () 1 2) '(2 1) + + (conj '(2 3) 1) '(1 2 3) + (conj '(2 3) 1 4 3) '(3 4 1 2 3) + + (conj () nil) '(nil) + (conj () ()) '(()) + + ; vector -> conj puts the item at the end of the vector + (conj [] 1) [1] + (conj [] 1 2) [1 2] + + (conj [2 3] 1) [2 3 1] + (conj [2 3] 1 4 3) [2 3 1 4 3] + + (conj [] nil) [nil] + (conj [] []) [[]] + + ; map -> conj expects another (possibly single entry) map as the item, + ; and returns a new map which is the old map plus the entries + ; from the new, which may overwrite entries of the old. + ; conj also accepts a MapEntry or a vector of two items (key and value). + (conj {} {}) {} + (conj {} {:a 1}) {:a 1} + (conj {} {:a 1 :b 2}) {:a 1 :b 2} + (conj {} {:a 1 :b 2} {:c 3}) {:a 1 :b 2 :c 3} + (conj {} {:a 1 :b 2} {:a 3 :c 4}) {:a 3 :b 2 :c 4} + + (conj {:a 1} {:a 7}) {:a 7} + (conj {:a 1} {:b 2}) {:a 1 :b 2} + (conj {:a 1} {:a 7 :b 2}) {:a 7 :b 2} + (conj {:a 1} {:a 7 :b 2} {:c 3}) {:a 7 :b 2 :c 3} + (conj {:a 1} {:a 7 :b 2} {:b 4 :c 5}) {:a 7 :b 4 :c 5} + + (conj {} (first {:a 1})) {:a 1} ; MapEntry + (conj {:a 1} (first {:b 2})) {:a 1 :b 2} + (conj {:a 1} (first {:a 7})) {:a 7} + (conj {:a 1} (first {:b 2}) (first {:a 5})) {:a 5 :b 2} + + (conj {} [:a 1]) {:a 1} ; vector + (conj {:a 1} [:b 2]) {:a 1 :b 2} + (conj {:a 1} [:a 7]) {:a 7} + (conj {:a 1} [:b 2] [:a 5]) {:a 5 :b 2} + + (conj {} {nil {}}) {nil {}} + (conj {} {{} nil}) {{} nil} + (conj {} {{} {}}) {{} {}} + + ; set + (conj #{} 1) #{1} + (conj #{} 1 2 3) #{1 2 3} + + (conj #{2 3} 1) #{3 1 2} + (conj #{3 2} 1) #{1 2 3} + + (conj #{2 3} 2) #{2 3} + (conj #{2 3} 2 3) #{2 3} + (conj #{2 3} 4 1 2 3) #{1 2 3 4} + + (conj #{} nil) #{nil} + (conj #{} #{}) #{#{}} )) + + +;; *** Lists and Vectors *** + +(deftest test-peek + ; doesn't work for sets and maps + (is (thrown? ClassCastException (peek #{1}))) + (is (thrown? ClassCastException (peek {:a 1}))) + + (are [x y] (= x y) + (peek nil) nil + + ; list = first + (peek ()) nil + (peek '(1)) 1 + (peek '(1 2 3)) 1 + + (peek '(nil)) nil ; special cases + (peek '(1 nil)) 1 + (peek '(nil 2)) nil + (peek '(())) () + (peek '(() nil)) () + (peek '(() 2 nil)) () + + ; vector = last + (peek []) nil + (peek [1]) 1 + (peek [1 2 3]) 3 + + (peek [nil]) nil ; special cases + (peek [1 nil]) nil + (peek [nil 2]) 2 + (peek [[]]) [] + (peek [[] nil]) nil + (peek [[] 2 nil]) nil )) + + +(deftest test-pop + ; doesn't work for sets and maps + (is (thrown? ClassCastException (pop #{1}))) + (is (thrown? ClassCastException (pop #{:a 1}))) + + ; collection cannot be empty + (is (thrown? IllegalStateException (pop ()))) + (is (thrown? IllegalStateException (pop []))) + + (are [x y] (= x y) + (pop nil) nil + + ; list - pop first + (pop '(1)) () + (pop '(1 2 3)) '(2 3) + + (pop '(nil)) () + (pop '(1 nil)) '(nil) + (pop '(nil 2)) '(2) + (pop '(())) () + (pop '(() nil)) '(nil) + (pop '(() 2 nil)) '(2 nil) + + ; vector - pop last + (pop [1]) [] + (pop [1 2 3]) [1 2] + + (pop [nil]) [] + (pop [1 nil]) [1] + (pop [nil 2]) [nil] + (pop [[]]) [] + (pop [[] nil]) [[]] + (pop [[] 2 nil]) [[] 2] )) + + +;; *** Lists (IPersistentList) *** + +(deftest test-list + (are [x] (list? x) + () + '() + (list) + (list 1 2 3) ) + + ; order is important + (are [x y] (not (= x y)) + (list 1 2) (list 2 1) + (list 3 1 2) (list 1 2 3) ) + + (are [x y] (= x y) + '() () + (list) '() + (list 1) '(1) + (list 1 2) '(1 2) + + ; nesting + (list 1 (list 2 3) (list 3 (list 4 5 (list 6 (list 7))))) + '(1 (2 3) (3 (4 5 (6 (7))))) + + ; different data structures + (list true false nil) + '(true false nil) + (list 1 2.5 2/3 "ab" \x 'cd :kw) + '(1 2.5 2/3 "ab" \x cd :kw) + (list (list 1 2) [3 4] {:a 1 :b 2} #{:c :d}) + '((1 2) [3 4] {:a 1 :b 2} #{:c :d}) + + ; evaluation + (list (+ 1 2) [(+ 2 3) 'a] (list (* 2 3) 8)) + '(3 [5 a] (6 8)) + + ; special cases + (list nil) '(nil) + (list 1 nil) '(1 nil) + (list nil 2) '(nil 2) + (list ()) '(()) + (list 1 ()) '(1 ()) + (list () 2) '(() 2) )) + + +;; *** Maps (IPersistentMap) *** + +(deftest test-find + (are [x y] (= x y) + (find {} :a) nil + + (find {:a 1} :a) [:a 1] + (find {:a 1} :b) nil + + (find {:a 1 :b 2} :a) [:a 1] + (find {:a 1 :b 2} :b) [:b 2] + (find {:a 1 :b 2} :c) nil + + (find {} nil) nil + (find {:a 1} nil) nil + (find {:a 1 :b 2} nil) nil )) + + +(deftest test-contains? + ; contains? is designed to work preferably on maps and sets + (are [x y] (= x y) + (contains? {} :a) false + (contains? {} nil) false + + (contains? {:a 1} :a) true + (contains? {:a 1} :b) false + (contains? {:a 1} nil) false + + (contains? {:a 1 :b 2} :a) true + (contains? {:a 1 :b 2} :b) true + (contains? {:a 1 :b 2} :c) false + (contains? {:a 1 :b 2} nil) false + + ; sets + (contains? #{} 1) false + (contains? #{} nil) false + + (contains? #{1} 1) true + (contains? #{1} 2) false + (contains? #{1} nil) false + + (contains? #{1 2 3} 1) true + (contains? #{1 2 3} 3) true + (contains? #{1 2 3} 10) false + (contains? #{1 2 3} nil) false) + + ; numerically indexed collections (e.g. vectors and Java arrays) + ; => test if the numeric key is WITHIN THE RANGE OF INDEXES + (are [x y] (= x y) + (contains? [] 0) false + (contains? [] -1) false + (contains? [] 1) false + + (contains? [1] 0) true + (contains? [1] -1) false + (contains? [1] 1) false + + (contains? [1 2 3] 0) true + (contains? [1 2 3] 2) true + (contains? [1 2 3] 3) false + (contains? [1 2 3] -1) false + + ; arrays + (contains? (into-array []) 0) false + (contains? (into-array []) -1) false + (contains? (into-array []) 1) false + + (contains? (into-array [1]) 0) true + (contains? (into-array [1]) -1) false + (contains? (into-array [1]) 1) false + + (contains? (into-array [1 2 3]) 0) true + (contains? (into-array [1 2 3]) 2) true + (contains? (into-array [1 2 3]) 3) false + (contains? (into-array [1 2 3]) -1) false) + + ; 'contains?' operates constant or logarithmic time, + ; it WILL NOT perform a linear search for a value. + (are [x] (= x false) + (contains? '(1 2 3) 0) + (contains? '(1 2 3) 1) + (contains? '(1 2 3) 3) + (contains? '(1 2 3) 10) + (contains? '(1 2 3) nil) + (contains? '(1 2 3) ()) )) + + +(deftest test-keys + (are [x y] (= x y) ; other than map data structures + (keys ()) nil + (keys []) nil + (keys #{}) nil + (keys "") nil ) + + (are [x y] (= x y) + ; (class {:a 1}) => clojure.lang.PersistentArrayMap + (keys {}) nil + (keys {:a 1}) '(:a) + (diff (keys {:a 1 :b 2}) '(:a :b)) nil ; (keys {:a 1 :b 2}) '(:a :b) + + ; (class (sorted-map :a 1)) => clojure.lang.PersistentTreeMap + (keys (sorted-map)) nil + (keys (sorted-map :a 1)) '(:a) + (diff (keys (sorted-map :a 1 :b 2)) '(:a :b)) nil ; (keys (sorted-map :a 1 :b 2)) '(:a :b) + + ; (class (hash-map :a 1)) => clojure.lang.PersistentHashMap + (keys (hash-map)) nil + (keys (hash-map :a 1)) '(:a) + (diff (keys (hash-map :a 1 :b 2)) '(:a :b)) nil )) ; (keys (hash-map :a 1 :b 2)) '(:a :b) + + +(deftest test-vals + (are [x y] (= x y) ; other than map data structures + (vals ()) nil + (vals []) nil + (vals #{}) nil + (vals "") nil ) + + (are [x y] (= x y) + ; (class {:a 1}) => clojure.lang.PersistentArrayMap + (vals {}) nil + (vals {:a 1}) '(1) + (diff (vals {:a 1 :b 2}) '(1 2)) nil ; (vals {:a 1 :b 2}) '(1 2) + + ; (class (sorted-map :a 1)) => clojure.lang.PersistentTreeMap + (vals (sorted-map)) nil + (vals (sorted-map :a 1)) '(1) + (diff (vals (sorted-map :a 1 :b 2)) '(1 2)) nil ; (vals (sorted-map :a 1 :b 2)) '(1 2) + + ; (class (hash-map :a 1)) => clojure.lang.PersistentHashMap + (vals (hash-map)) nil + (vals (hash-map :a 1)) '(1) + (diff (vals (hash-map :a 1 :b 2)) '(1 2)) nil )) ; (vals (hash-map :a 1 :b 2)) '(1 2) + + +(deftest test-key + (are [x] (= (key (first (hash-map x :value))) x) + nil + false true + 0 42 + 0.0 3.14 + 2/3 + 0M 1M + \c + "" "abc" + 'sym + :kw + () '(1 2) + [] [1 2] + {} {:a 1 :b 2} + #{} #{1 2} )) + + +(deftest test-val + (are [x] (= (val (first (hash-map :key x))) x) + nil + false true + 0 42 + 0.0 3.14 + 2/3 + 0M 1M + \c + "" "abc" + 'sym + :kw + () '(1 2) + [] [1 2] + {} {:a 1 :b 2} + #{} #{1 2} )) + + |