Skip to content

Commit cde0527

Browse files
authored
Merge pull request cloverage#124 from rm-hull/feature/test-rename
Test namespaces rename - fixes cloverage#113
2 parents 9fa1d14 + 671c425 commit cde0527

7 files changed

+416
-412
lines changed
+238
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
(ns cloverage.coverage-test
2+
(:require [clojure.test :as t]
3+
[cloverage.coverage :as cov]
4+
[cloverage.instrument :as inst]
5+
[riddley.walk :as rw])
6+
(:import java.io.File))
7+
8+
(defn- denamespace [tree]
9+
"Helper function to allow backticking w/o namespace interpolation."
10+
(cond (seq? tree) (map denamespace tree)
11+
(symbol? tree) (symbol (name tree))
12+
:else tree))
13+
14+
(def sample-file
15+
"cloverage/sample.clj")
16+
17+
(defn coverage-fixture [f]
18+
(binding [cov/*covered* (atom [])
19+
cov/*instrumented-ns* "NO_SUCH_NAMESPACE"]
20+
(f)))
21+
22+
(t/use-fixtures :each coverage-fixture)
23+
24+
(def output-dir "out")
25+
26+
(defn expand=
27+
"Check that two expressions are equal modulo recursive macroexpansion."
28+
[f1 f2]
29+
(let [e1 (rw/macroexpand-all f1)
30+
e2 (rw/macroexpand-all f2)]
31+
(= e1 e2)))
32+
33+
(t/deftest preserves-type-hint
34+
(t/is (= 'long
35+
;; top level type hint always worked, but ones nested in :list did not
36+
(-> (inst/wrap #'cov/track-coverage 0 '(prn ^long (long 0)))
37+
rw/macroexpand-all
38+
(nth 2) ; (do (cloverage/cover 0) (...)
39+
(nth 1) ; ((do (cloverage/cover 1) prn) (...))
40+
(nth 2) ; (do (cloverage/cover 2) (...))
41+
meta
42+
:tag))))
43+
44+
;; TODO: all test-wrap-X tests should be split in one test that checks
45+
;; whether wrap works correctly, and one that checks track-coverage.
46+
(t/deftest test-wrap-primitives
47+
(t/is (expand= `(cov/capture 0 1) (inst/wrap #'cov/track-coverage 0 1)))
48+
(t/is (expand= `(cov/capture 1 "foo") (inst/wrap #'cov/track-coverage 0 "foo")))
49+
(t/is (expand= `(cov/capture 2 ~'bar) (inst/wrap #'cov/track-coverage 0 'bar)))
50+
(t/is (expand= `(cov/capture 3 ~'true) (inst/wrap #'cov/track-coverage 0 'true)))
51+
(t/is (expand= '(1 "foo" bar true)
52+
(map :form @cov/*covered*))))
53+
54+
(t/deftest test-wrap-vector
55+
(t/is (expand= `(cov/capture 0
56+
[(cov/capture 1 1)
57+
(cov/capture 2 "foo")
58+
(cov/capture 3 ~'bar)])
59+
(inst/wrap #'cov/track-coverage 0 '[1 "foo" bar]))))
60+
61+
(t/deftest test-wrap-map
62+
(let [wrapped (rw/macroexpand-all (inst/wrap #'cov/track-coverage 0 '{:a apple :b banana}))]
63+
(t/is (or
64+
(expand= `(cov/capture 0 {(cov/capture 1 :a) (cov/capture 2 ~'apple)
65+
(cov/capture 3 :b) (cov/capture 4 ~'banana)})
66+
wrapped)
67+
(expand= `(cov/capture 0 {(cov/capture 1 :b) (cov/capture 2 ~'banana)
68+
(cov/capture 3 :a) (cov/capture 4 ~'apple)})
69+
wrapped)))))
70+
71+
(t/deftest test-wrap-list
72+
(t/is (expand= `(cov/capture 0 ((cov/capture 1 +) (cov/capture 2 1)
73+
(cov/capture 3 2)))
74+
(inst/wrap #'cov/track-coverage 0 `(+ 1 2)))))
75+
76+
;; XXX: the order that forms are registered is now from outside in. Bad?
77+
(t/deftest test-wrap-fn
78+
(t/is (expand= `(cov/capture 0 (~(symbol "fn")
79+
[~'a] (cov/capture 1 ~'a)))
80+
(inst/wrap #'cov/track-coverage 0
81+
'(fn [a] a)))
82+
"Unnamed fn with single overload")
83+
(t/is (expand= `(cov/capture 2 (~(symbol "fn")
84+
([~'a] (cov/capture 3 ~'a))
85+
([~'a ~'b] (cov/capture 4 ~'b))))
86+
(inst/wrap #'cov/track-coverage 0 '(fn ([a] a) ([a b] b))))
87+
"Unnamed fn with multiple overloads")
88+
(t/is (expand= `(cov/capture 5 (~(symbol "fn") ~'foo
89+
[~'a] (cov/capture 6 ~'a)))
90+
(inst/wrap #'cov/track-coverage 0
91+
'(fn foo [a] a)))
92+
"Named fn with single overload")
93+
(t/is (expand= `(cov/capture 7 (~(symbol "fn") ~'foo
94+
([~'a] (cov/capture 8 ~'a))
95+
([~'a ~'b] (cov/capture 9 ~'b))))
96+
(inst/wrap #'cov/track-coverage 0 '(fn foo ([a] a) ([a b] b))))
97+
"Named fn with multiple overloads"))
98+
99+
(t/deftest test-wrap-def
100+
(t/is (expand= `(cov/capture 0 (~(symbol "def") ~'foobar))
101+
(inst/wrap #'cov/track-coverage 0 '(def foobar))))
102+
(t/is (expand= `(cov/capture 1 (~(symbol "def") ~'foobar (cov/capture 2 1)))
103+
(inst/wrap #'cov/track-coverage 0 '(def foobar 1)))))
104+
105+
(t/deftest test-wrap-let
106+
(t/is (expand= `(cov/capture 0 (~(symbol "let") []))
107+
(inst/wrap #'cov/track-coverage 0 '(let []))))
108+
(t/is (expand= `(cov/capture 1 (~(symbol "let") [~'a (cov/capture 2 1)]))
109+
(inst/wrap #'cov/track-coverage 0 '(let [a 1]))))
110+
(t/is (expand= `(cov/capture 3 (~(symbol "let") [~'a (cov/capture 4 1)
111+
~'b (cov/capture 5 2)]))
112+
(inst/wrap #'cov/track-coverage 0 '(let [a 1 b 2]))))
113+
(t/is (expand= `(cov/capture 6 (~(symbol "let") [~'a (cov/capture 7 1)
114+
~'b (cov/capture 8 2)]
115+
(cov/capture 9 ~'a)))
116+
(inst/wrap #'cov/track-coverage 0 '(let [a 1 b 2] a)))))
117+
118+
(t/deftest test-wrap-cond
119+
(t/is (expand= `(cov/capture 0 nil)
120+
(inst/wrap #'cov/track-coverage 0 '(cond)))))
121+
122+
(t/deftest test-wrap-overloads
123+
(t/is (expand= `(([~'a] (cov/capture 0 ~'a))
124+
([~'a ~'b] (cov/capture 1 ~'a) (cov/capture 2 ~'b)))
125+
(inst/wrap-overloads #'cov/track-coverage 0 '(([a] a)
126+
([a b] a b)))))
127+
(t/is (expand= `([~'a] (cov/capture 3 ~'a))
128+
(inst/wrap-overloads #'cov/track-coverage 0 '([a] a)))))
129+
130+
(t/deftest test-wrap-for
131+
(t/is (not (nil? (inst/wrap #'cov/track-coverage 0 '(for [i (range 5)] i))))))
132+
133+
(t/deftest test-wrap-str
134+
(inst/wrap #'cov/track-coverage 0
135+
'(defn -main [& args]
136+
(doseq [file (file-seq ".")]
137+
(println "File is" file)))))
138+
139+
(t/deftest test-eval-atomic
140+
(t/is (= 1 (eval (inst/wrap #'cov/track-coverage 0 1))))
141+
(t/is (= :foo (eval (inst/wrap #'cov/track-coverage 0 :foo))))
142+
(t/is (= "foo" (eval (inst/wrap #'cov/track-coverage 0 "foo"))))
143+
(t/is (= + (eval (inst/wrap #'cov/track-coverage 0 '+)))))
144+
145+
(t/deftest test-eval-expr
146+
(t/is (= 5 (eval (inst/wrap #'cov/track-coverage 0 '(+ 2 3))))))
147+
148+
(t/deftest test-eval-do
149+
(t/is (= 4 (eval (inst/wrap #'cov/track-coverage 0 '(do 4))))))
150+
151+
(t/deftest test-eval-ns
152+
(eval (inst/wrap #'cov/track-coverage 0 '(ns foo.bar)))
153+
(t/is (= (count (filter :tracked @cov/*covered*)) (count (filter :covered @cov/*covered*)))))
154+
155+
(t/deftest test-eval-case
156+
(doseq [x '[a b 3 #{3} fallthrough]]
157+
(t/is (= (str x) (eval (inst/wrap #'cov/track-coverage 0
158+
(denamespace `(case '~x
159+
a "a"
160+
b "b"
161+
3 "3"
162+
#{3} "#{3}"
163+
"fallthrough")))))))
164+
(t/is (thrown? IllegalArgumentException
165+
(eval (inst/wrap #'cov/track-coverage 0 (case 1))))))
166+
167+
;; non-local and public to easily access in eval
168+
;; tests are not ran from the namespace they're defined in
169+
(def ran-finally (atom nil))
170+
(t/deftest test-eval-try
171+
(t/is (= :caught
172+
(eval (inst/wrap #'cov/track-coverage 0
173+
'(try (swap! cloverage.coverage-test/ran-finally (constantly false))
174+
(throw (Exception. "try-catch test"))
175+
(catch Exception e
176+
:caught)
177+
(finally
178+
(swap! cloverage.coverage-test/ran-finally (constantly true))))))))
179+
(= true @ran-finally))
180+
181+
(defn find-form [cov form]
182+
(some #(and (= form (:form %)) %) cov))
183+
184+
(t/deftest test-instrument-gets-lines
185+
(inst/instrument #'cov/track-coverage
186+
'cloverage.sample)
187+
(let [cov @cov/*covered*
188+
found (find-form cov '(+ 1 2))]
189+
#_(with-out-writer "out/foo"
190+
(doseq [form-info cov]
191+
(println form-info)))
192+
#_(println "Form is" )
193+
(t/is found)
194+
(t/is (:line found))
195+
(t/is (find-form cov '(inc (m c 0))))))
196+
197+
(t/deftest test-wrap-new
198+
(t/is (expand= `(cov/capture 0 (~'new java.io.File (cov/capture 1 "foo/bar")))
199+
(inst/wrap #'cov/track-coverage 0 '(new java.io.File "foo/bar")))))
200+
201+
(defn- compare-colls [& colls]
202+
"Given N collections compares them. Returns true if collections have same
203+
elements (order does not matter)."
204+
(apply = (map frequencies colls)))
205+
206+
(t/deftest test-find-nses
207+
(t/testing "empty sequence is returned when neither paths nor regexs are provided"
208+
(t/is (empty? (cov/find-nses nil []))))
209+
(t/testing "all namespaces in a directory get returned when only path is provided"
210+
(t/is (compare-colls (cov/find-nses "test/cloverage/sample" [])
211+
["cloverage.sample.dummy-sample"
212+
"cloverage.sample.read-eval-sample"
213+
"cloverage.sample.multibyte-sample"])))
214+
(t/testing "only matching namespaces (from classpath) are returned when only
215+
regex patterns are provided:"
216+
(t/testing "single pattern case"
217+
(t/is (= (cov/find-nses nil [#"^cloverage\.sample\.read.*$"])
218+
["cloverage.sample.read-eval-sample"])))
219+
(t/testing "multiple patterns case"
220+
(t/is (compare-colls (cov/find-nses nil [#"^cloverage\.sample\.read.*$"
221+
#"^cloverage\..*coverage.*$"])
222+
["cloverage.sample.read-eval-sample"
223+
"cloverage.coverage-test"
224+
"cloverage.coverage"]))))
225+
(t/testing "only matching namespaces from a directory are returned when both path
226+
and patterns are provided"
227+
(t/is (= (cov/find-nses "test/cloverage/sample" [#".*dummy.*"])
228+
["cloverage.sample.dummy-sample"]))))
229+
230+
(t/deftest test-main
231+
(binding [cloverage.coverage/*exit-after-test* false]
232+
(t/is (=
233+
(cloverage.coverage/-main
234+
"-o" "out"
235+
"--text" "--html" "--raw" "--emma-xml" "--coveralls"
236+
"-x" "cloverage.sample"
237+
"cloverage.sample")
238+
0))))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
(ns cloverage.dependency-test
2+
(:require [cloverage.dependency :as cd]
3+
[clojure.test :as t]))
4+
5+
6+
(def ns-fixtures {
7+
;; sources snipped from incanter : https://github.com/liebke/incanter
8+
:incanter-core
9+
{:ns-source
10+
'(ns ^{:doc "This is the core numerics library for Incanter.
11+
It provides functions for vector- and matrix-based
12+
mathematical operations and the core data manipulation
13+
functions for Incanter.
14+
15+
This library is built on Parallel Colt
16+
(http://sites.google.com/site/piotrwendykier/software/parallelcolt)
17+
an extension of the Colt numerics library
18+
(http://acs.lbl.gov/~hoschek/colt/).
19+
"
20+
:author "David Edgar Liebke"}
21+
22+
incanter.core
23+
24+
(:use [incanter internal]
25+
[incanter.infix :only (infix-to-prefix defop)]
26+
[clojure.set :only (difference)])
27+
(:import (incanter Matrix)
28+
(cern.colt.matrix.tdouble DoubleMatrix2D
29+
DoubleFactory2D
30+
DoubleFactory1D)
31+
(cern.colt.matrix.tdouble.algo DenseDoubleAlgebra
32+
DoubleFormatter)
33+
(cern.colt.matrix.tdouble.algo.decomposition DenseDoubleCholeskyDecomposition
34+
DenseDoubleSingularValueDecomposition
35+
DenseDoubleEigenvalueDecomposition
36+
DenseDoubleLUDecomposition
37+
DenseDoubleQRDecomposition)
38+
(cern.jet.math.tdouble DoubleFunctions DoubleArithmetic)
39+
(cern.colt.function.tdouble DoubleDoubleFunction DoubleFunction)
40+
(cern.colt.list.tdouble DoubleArrayList)
41+
(cern.jet.stat.tdouble DoubleDescriptive Gamma)
42+
(javax.swing JTable JScrollPane JFrame)
43+
(java.util Vector)))
44+
:expected '[incanter.core #{incanter.internal incanter.infix clojure.set}]}
45+
46+
:incanter-bayes
47+
{:ns-source
48+
'(ns ^{:doc "This is library provides functions for performing
49+
basic Bayesian modeling and inference.
50+
"
51+
:author "David Edgar Liebke"}
52+
incanter.bayes
53+
(:use [incanter.core :only (matrix mmult mult div minus trans ncol nrow
54+
plus to-list decomp-cholesky solve half-vectorize
55+
vectorize symmetric-matrix identity-matrix kronecker
56+
bind-columns)]
57+
[incanter.stats :only (sample-normal sample-gamma sample-dirichlet
58+
sample-inv-wishart sample-mvn mean)]))
59+
:expected '[incanter.bayes #{incanter.core incanter.stats}]}
60+
:parkour-dseq
61+
{:ns-source
62+
'(ns parkour.io.dseq
63+
(:require [clojure.core.protocols :as ccp]
64+
[clojure.core.reducers :as r]
65+
[parkour (conf :as conf) (cstep :as cstep) (wrapper :as w)]
66+
[parkour.mapreduce (source :as src)]
67+
[parkour.io.dseq (mapred :as mr1) (mapreduce :as mr2)]
68+
[parkour.util :refer [ignore-errors]])
69+
(:import [java.io Closeable Writer]
70+
[clojure.lang IObj]))
71+
:expected '[parkour.io.dseq
72+
#{clojure.core.protocols clojure.core.reducers parkour.conf
73+
parkour.cstep parkour.wrapper parkour.mapreduce.source
74+
parkour.io.dseq.mapred parkour.io.dseq.mapreduce
75+
parkour.util}]}})
76+
77+
(t/deftest test-dependency-extraction
78+
(doall (for [[ns-name
79+
{ns-form :ns-source expected :expected}] (seq ns-fixtures)]
80+
(let [result (cd/dependency-libs ns-form)]
81+
;; wrap in seq to work around lack of LazySeq.toString
82+
(t/is (= expected result)
83+
(str "Parsing " ns-name
84+
" should give " expected
85+
" but got " result ))))))
86+
87+
(t/deftest test-dependency-sort
88+
(let [dep-lists [['first #{'fourth}]
89+
['second #{'fourth 'first}]
90+
['third #{}]
91+
['fourth #{'fifth}]
92+
['fifth #{}]]
93+
result (cd/dependency-sort dep-lists)
94+
index-map (zipmap result (range))
95+
]
96+
(t/is (not (nil? result)) "Dependency sort should not be nil.")
97+
(doseq [[name deps] dep-lists]
98+
(let [my-index (get index-map name)]
99+
(doseq [dep deps]
100+
(t/is (< (get index-map dep) my-index)
101+
(str "Prerequisite " dep " of " name " should be loaded before,"
102+
" but isn't: " result)))))))

0 commit comments

Comments
 (0)