(ns clojure.tools.namespace.dependency-test (:use clojure.test clojure.tools.namespace.dependency)) ;; building a graph like: ;; ;; :a ;; / | ;; :b | ;; \ | ;; :c ;; | ;; :d ;; (def g1 (-> (graph) (depend :b :a) ; "B depends on A" (depend :c :b) ; "C depends on B" (depend :c :a) ; "C depends on A" (depend :d :c))) ; "D depends on C" ;; 'one 'five ;; | | ;; 'two | ;; / \ | ;; / \ | ;; / \ / ;; 'three 'four ;; | / ;; 'six / ;; | / ;; | / ;; | / ;; 'seven ;; (def g2 (-> (graph) (depend 'two 'one) (depend 'three 'two) (depend 'four 'two) (depend 'four 'five) (depend 'six 'three) (depend 'seven 'six) (depend 'seven 'four))) ;; :level0 ;; / | | \ ;; ----- | | ----- ;; / | | \ ;; :level1a :level1b :level1c :level1d ;; \ | | / ;; ----- | | ----- ;; \ | | / ;; :level2 ;; / | | \ ;; ----- | | ----- ;; / | | \ ;; :level3a :level3b :level3c :level3d ;; \ | | / ;; ----- | | ----- ;; \ | | / ;; :level4 ;; ;; ... and so on in a repeating pattern like that, up to :level26 (def g3 (-> (graph) (depend :level1a :level0) (depend :level1b :level0) (depend :level1c :level0) (depend :level1d :level0) (depend :level2 :level1a) (depend :level2 :level1b) (depend :level2 :level1c) (depend :level2 :level1d) (depend :level3a :level2) (depend :level3b :level2) (depend :level3c :level2) (depend :level3d :level2) (depend :level4 :level3a) (depend :level4 :level3b) (depend :level4 :level3c) (depend :level4 :level3d) (depend :level5a :level4) (depend :level5b :level4) (depend :level5c :level4) (depend :level5d :level4) (depend :level6 :level5a) (depend :level6 :level5b) (depend :level6 :level5c) (depend :level6 :level5d) (depend :level7a :level6) (depend :level7b :level6) (depend :level7c :level6) (depend :level7d :level6) (depend :level8 :level7a) (depend :level8 :level7b) (depend :level8 :level7c) (depend :level8 :level7d) (depend :level9a :level8) (depend :level9b :level8) (depend :level9c :level8) (depend :level9d :level8) (depend :level10 :level9a) (depend :level10 :level9b) (depend :level10 :level9c) (depend :level10 :level9d) (depend :level11a :level10) (depend :level11b :level10) (depend :level11c :level10) (depend :level11d :level10) (depend :level12 :level11a) (depend :level12 :level11b) (depend :level12 :level11c) (depend :level12 :level11d) (depend :level13a :level12) (depend :level13b :level12) (depend :level13c :level12) (depend :level13d :level12) (depend :level14 :level13a) (depend :level14 :level13b) (depend :level14 :level13c) (depend :level14 :level13d) (depend :level15a :level14) (depend :level15b :level14) (depend :level15c :level14) (depend :level15d :level14) (depend :level16 :level15a) (depend :level16 :level15b) (depend :level16 :level15c) (depend :level16 :level15d) (depend :level17a :level16) (depend :level17b :level16) (depend :level17c :level16) (depend :level17d :level16) (depend :level18 :level17a) (depend :level18 :level17b) (depend :level18 :level17c) (depend :level18 :level17d) (depend :level19a :level18) (depend :level19b :level18) (depend :level19c :level18) (depend :level19d :level18) (depend :level20 :level19a) (depend :level20 :level19b) (depend :level20 :level19c) (depend :level20 :level19d) (depend :level21a :level20) (depend :level21b :level20) (depend :level21c :level20) (depend :level21d :level20) (depend :level22 :level21a) (depend :level22 :level21b) (depend :level22 :level21c) (depend :level22 :level21d) (depend :level23a :level22) (depend :level23b :level22) (depend :level23c :level22) (depend :level23d :level22) (depend :level24 :level23a) (depend :level24 :level23b) (depend :level24 :level23c) (depend :level24 :level23d) (depend :level25a :level24) (depend :level25b :level24) (depend :level25c :level24) (depend :level25d :level24) (depend :level26 :level25a) (depend :level26 :level25b) (depend :level26 :level25c) (depend :level26 :level25d))) (deftest t-transitive-dependencies (is (= #{:a :c :b} (transitive-dependencies g1 :d))) (is (= '#{two four six one five three} (transitive-dependencies g2 'seven)))) (deftest t-transitive-dependencies-deep (is (= #{:level0 :level1a :level1b :level1c :level1d :level2 :level3a :level3b :level3c :level3d :level4 :level5a :level5b :level5c :level5d :level6 :level7a :level7b :level7c :level7d :level8 :level9a :level9b :level9c :level9d :level10 :level11a :level11b :level11c :level11d :level12 :level13a :level13b :level13c :level13d :level14 :level15a :level15b :level15c :level15d :level16 :level17a :level17b :level17c :level17d :level18 :level19a :level19b :level19c :level19d :level20 :level21a :level21b :level21c :level21d :level22 :level23a :level23b :level23c :level23d} (transitive-dependencies g3 :level24))) (is (= #{:level0 :level1a :level1b :level1c :level1d :level2 :level3a :level3b :level3c :level3d :level4 :level5a :level5b :level5c :level5d :level6 :level7a :level7b :level7c :level7d :level8 :level9a :level9b :level9c :level9d :level10 :level11a :level11b :level11c :level11d :level12 :level13a :level13b :level13c :level13d :level14 :level15a :level15b :level15c :level15d :level16 :level17a :level17b :level17c :level17d :level18 :level19a :level19b :level19c :level19d :level20 :level21a :level21b :level21c :level21d :level22 :level23a :level23b :level23c :level23d :level24 :level25a :level25b :level25c :level25d} (transitive-dependencies g3 :level26)))) (deftest t-transitive-dependents (is (= '#{four seven} (transitive-dependents g2 'five))) (is (= '#{four seven six three} (transitive-dependents g2 'two)))) (defn- before? "True if x comes before y in an ordered collection." [coll x y] (loop [[item & more] (seq coll)] (cond (nil? item) true ; end of the seq (= x item) true ; x comes first (= y item) false :else (recur more)))) (deftest t-before (is (true? (before? [:a :b :c :d] :a :b))) (is (true? (before? [:a :b :c :d] :b :c))) (is (false? (before? [:a :b :c :d] :d :c))) (is (false? (before? [:a :b :c :d] :c :a)))) (deftest t-topo-comparator-1 (let [sorted (sort (topo-comparator g1) [:d :a :b :foo])] (are [x y] (before? sorted x y) :a :b :a :d :a :foo :b :d :b :foo :d :foo))) (deftest t-topo-comparator-2 (let [sorted (sort (topo-comparator g2) '[three seven nine eight five])] (are [x y] (before? sorted x y) 'three 'seven 'three 'eight 'three 'nine 'five 'eight 'five 'nine 'seven 'eight 'seven 'nine))) (deftest t-topo-sort (let [sorted (topo-sort g2)] (are [x y] (before? sorted x y) 'one 'two 'one 'three 'one 'four 'one 'six 'one 'seven 'two 'three 'two 'four 'two 'six 'two 'seven 'three 'six 'three 'seven 'four 'seven 'five 'four 'five 'seven 'six 'seven))) (deftest t-no-cycles (is (thrown? Exception (-> (graph) (depend :a :b) (depend :b :c) (depend :c :a))))) (deftest t-no-self-cycles (is (thrown? Exception (-> (graph) (depend :a :b) (depend :a :a)))))