/
clean.clj
125 lines (108 loc) · 4.95 KB
/
clean.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
(ns leiningen.test.clean
(:use [clojure.test]
[clojure.java.io :only [file make-parents writer]]
[leiningen.clean :only [clean]]
[leiningen.test.helper :only [sample-project]]))
(def target-1 (:target-path sample-project))
(def target-2 (str (file (:root sample-project) "target-2")))
(def target-3 (str (file (:root sample-project) "target-3")))
(def target-dirs (map file [target-1 target-2 target-3]))
(def delete-calls (atom '()))
(defn mock-delete-files
"This implementation of delete-files-recursively will simply track the parameters passed in a state atom."
[& params]
(swap! delete-calls #(cons params %)))
(use-fixtures :each
(fn [f]
;; start each test with empty state.
(swap! delete-calls empty)
;; The original delete-file-recursively is potentially destructive, so let's mock it.
(with-redefs [leiningen.clean/delete-file-recursively mock-delete-files]
(f))))
(defn assert-cleaned
"Asserts that the mock was called for the given target path."
[test-path]
(is (some #(= test-path (first %)) @delete-calls)
(format "delete-files-recursively was not called for %s" test-path)))
(defn relative-to-absolute-project-path
"Converts a relative path to an absolute path within the sample project"
[path]
(str (file (:root sample-project) path)))
(deftest test-default-clean-target
(clean sample-project)
(is (= target-1 (ffirst @delete-calls))))
(deftest test-explicit-clean-targets-with-keywords
(let [modified-project
(assoc sample-project
:target-path-2 target-2
:clean-targets [:target-path :target-path-2])]
(clean modified-project)
(assert-cleaned target-1)
(assert-cleaned target-2)))
(deftest test-explicit-clean-targets-with-vector-of-keywords
(testing "clean targets that are deeply nested in the project map"
(let [modified-project
(assoc sample-project
:nest-1 {:nest-2 {:target-path-3 target-3}}
:clean-targets [[:nest-1 :nest-2 :target-path-3]])]
(clean modified-project)
(assert-cleaned target-3))))
(deftest test-explicit-clean-targets-with-valid-string-paths
(let [modified-project
(assoc sample-project
:clean-targets [target-2 target-3])]
(clean modified-project)
(assert-cleaned target-2)
(assert-cleaned target-3)))
(deftest test-explicit-clean-targets-with-invalid-string-paths
;; These are non-existent paths outside the project root -
;; used in case someone tries to execute them with out the
;; fixture. Deleting "/" might be bad for your mental health.
(testing "should not delete ancestor paths of the project root"
(doseq [test-dir ["../../xyz" "/xyz"]]
(let [modified-project
(assoc sample-project
:clean-targets [test-dir])]
(is (thrown-with-msg? java.io.IOException #"project root"
(clean modified-project))))))
(testing "should not delete protected project paths"
(doseq [path-key [:test-paths :resource-paths :source-paths :java-source-paths]]
(let [test-path (relative-to-absolute-project-path "test-path")
modified-project
(assoc sample-project
path-key [test-path]
:clean-targets [test-path])]
(is (thrown-with-msg? java.io.IOException #"non-target"
(clean modified-project))))))
(testing "should not delete project.clj"
(let [modified-project
(assoc sample-project
:clean-targets [(relative-to-absolute-project-path "project.clj")])]
(is (thrown-with-msg? java.io.IOException #"non-target"
(clean modified-project)))))
(testing "should not delete docs"
(let [modified-project
(assoc sample-project
:clean-targets [(relative-to-absolute-project-path "doc/stuff.doc")])]
(is (thrown-with-msg? java.io.IOException #"non-target"
(clean modified-project))))))
(deftest test-protect-metadata-override
;; This will override the sanity check by adding :protect false to
;; the metadata for :clean-targets. Again, this could be destructive
;; so I'm using a non-existent protected directory. The result will
;; be that our mock delete-file-recursively will get called, and
;; no exceptions should be thrown.
(testing "override protected path sanity checking"
(doseq [test-dir
(concat ["../../xyz" "/xyz"]
(map relative-to-absolute-project-path
["xsrc" "xtest" "xresources"
"doc/foo" "project.clj"]))]
(let [modified-project
(assoc sample-project
:test-paths [(relative-to-absolute-project-path "xtest")]
:resource-paths [(relative-to-absolute-project-path "xresources")]
:source-paths [(relative-to-absolute-project-path "xsrc")]
:clean-targets ^{:protect false} [test-dir])]
(clean modified-project)
(assert-cleaned test-dir)))))