Permalink
Browse files

Write some final unit tests (Issue #70).

  • Loading branch information...
1 parent 75dd487 commit c938f83b41738de266decb591c8aad84a2d75b43 @emezeske committed Apr 12, 2012
@@ -86,14 +86,6 @@
:crossovers crossovers
:builds builds}})
-(defmacro quietly [& forms]
- `(binding [*out* (new java.io.StringWriter)]
- ~@forms))
-
-(defn run-cljsbuild [& args]
- (quietly
- (apply cljsbuild args)))
-
(defn hook-success [& args]
0)
@@ -110,11 +102,11 @@
~@forms))
(fact "fail when no arguments present"
- (run-cljsbuild project) => 1)
+ (cljsbuild project) => 1)
(fact "once/auto call eval-in-project with the right args"
(doseq [command ["once" "auto"]]
- (run-cljsbuild project command) => 0
+ (cljsbuild project command) => 0
(provided
(subproject/eval-in-project
project
@@ -127,7 +119,7 @@
(doseq [[command watch?] {"once" false "auto" true}
extra-args [[] [build-id]]]
(with-compiler-bindings
- (apply run-cljsbuild project command extra-args)) => 0
+ (apply cljsbuild project command extra-args)) => 0
(provided
(cljsbuild.crossover/copy-crossovers
crossover-path
@@ -142,24 +134,21 @@
(fact "bad build IDs are detected"
(with-compiler-bindings
- (run-cljsbuild project "once" "wrong-build-id")) => (throws Exception))
+ (cljsbuild project "once" "wrong-build-id")) => (throws Exception))
(fact "clean calls cleanup-files"
(with-compiler-bindings
- (run-cljsbuild project "clean")) => 0
+ (cljsbuild project "clean")) => 0
(with-compiler-bindings
- (quietly
- (clean-hook hook-success project))) => 0
+ (clean-hook hook-success project)) => 0
(with-compiler-bindings
- (quietly
- (clean-hook hook-failure project))) => 0
+ (clean-hook hook-failure project)) => 0
(against-background
(cljsbuild.clean/cleanup-files compiler) => nil :times 1))
(fact "compile-hook calls through to the compiler when task succeeds"
(with-compiler-bindings
- (quietly
- (compile-hook hook-success project))) => 0
+ (compile-hook hook-success project)) => 0
(provided
(cljsbuild.crossover/copy-crossovers
crossover-path
@@ -174,8 +163,7 @@
(fact "compile-hook does not call through to the compiler when task fails"
(with-compiler-bindings
- (quietly
- (compile-hook hook-failure project))) => 1
+ (compile-hook hook-failure project)) => 1
(provided
(cljsbuild.crossover/copy-crossovers
anything
@@ -193,15 +181,13 @@
(let [parsed-commands [(config/parse-shell-command test-command)]]
(fact "tests work correctly"
(with-compiler-bindings
- (run-cljsbuild project "test")) => 0
+ (cljsbuild project "test")) => 0
(with-compiler-bindings
- (run-cljsbuild project "test" test-command-id)) => 0
+ (cljsbuild project "test" test-command-id)) => 0
(with-compiler-bindings
- (quietly
- (test-hook hook-success project))) => 0
+ (test-hook hook-success project)) => 0
(with-compiler-bindings
- (quietly
- (test-hook hook-failure project))) => 1
+ (test-hook hook-failure project)) => 1
(against-background
(cljsbuild.crossover/copy-crossovers
crossover-path
@@ -222,22 +208,22 @@
(fact "repl-listen calls run-repl-listen"
(with-repl-bindings
- (run-cljsbuild project "repl-listen")) => 0
+ (cljsbuild project "repl-listen")) => 0
(provided
(cljsbuild.repl.listen/run-repl-listen repl-listen-port anything) => nil :times 1))
(fact "repl-launch with no ID fails"
(with-repl-bindings
- (run-cljsbuild project "repl-launch")) => (throws Exception))
+ (cljsbuild project "repl-launch")) => (throws Exception))
(fact "repl-launch with bad ID fails"
(with-repl-bindings
- (run-cljsbuild project "repl-launch" "wrong-repl-launch-id")) => (throws Exception))
+ (cljsbuild project "repl-launch" "wrong-repl-launch-id")) => (throws Exception))
(fact "repl-launch calls run-repl-launch"
(let [parsed-command (config/parse-shell-command repl-launch-command)]
(with-repl-bindings
- (run-cljsbuild project "repl-launch" repl-launch-command-id)) => 0
+ (cljsbuild project "repl-launch" repl-launch-command-id)) => 0
(provided
(cljsbuild.repl.listen/run-repl-launch
repl-listen-port
@@ -246,7 +232,7 @@
(fact "repl-rhino calls run-repl-rhino"
(with-repl-bindings
- (run-cljsbuild project "repl-rhino")) => 0
+ (cljsbuild project "repl-rhino")) => 0
(provided
(cljsbuild.repl.rhino/run-repl-rhino) => nil :times 1))
@@ -257,8 +243,7 @@
input-filespecs [{:type :bytes :path "/i/j" :bytes "fake-1"}]
project-filespecs [{:type :bytes :path "/a/b" :bytes "fake-2"}]
all-filespecs (concat input-filespecs project-filespecs)]
- (quietly
- (jar-hook jar-task project out-file input-filespecs)) => 0
+ (jar-hook jar-task project out-file input-filespecs) => 0
(provided
(jar-task project out-file all-filespecs) => 0
(jar/get-filespecs project) => project-filespecs)))
@@ -7,37 +7,48 @@
[cljs.compiler :as compiler]
[fs.core :as fs]))
-(def lock (Object.))
+(defonce lock (Object.))
-(defn- apply-safe [f & args]
+(defn- apply-safe [f args]
(locking lock
(apply f args)
(flush)))
(defn- println-safe [& args]
(apply-safe println args))
+(def reset-color "\u001b[0m")
+(def foreground-red "\u001b[31m")
+(def foreground-green "\u001b[32m")
+
+(defn- colorizer [c]
+ (fn [& args]
+ (str c (apply str args) reset-color)))
+
+(def red (colorizer foreground-red))
+(def green (colorizer foreground-green))
+
(defn- elapsed [started-at]
(let [elapsed-us (- (. System (nanoTime)) started-at)]
(with-precision 2
(str (/ (double elapsed-us) 1000000000) " seconds"))))
-(defn- notify-cljs [command message]
+(defn- notify-cljs [command message colorizer]
(when (:bell command)
(apply-safe print \u0007))
(when (seq (:shell command))
(try
(util/sh (assoc command :shell (map #(if (= % "%") message %) (:shell command))))
(catch Throwable e
- (println-safe "Error running :notify-command:")
+ (println-safe (red "Error running :notify-command:"))
(pst+ e))))
- (println-safe message))
+ (println-safe (colorizer message)))
(defn- compile-cljs [cljs-path compiler-options notify-command
- warn-on-undeclared]
+ warn-on-undeclared?]
(let [output-file (:output-to compiler-options)
output-file-dir (fs/parent output-file)]
- (println-safe (str "Compiling " output-file " from " cljs-path "..."))
+ (println-safe (str "Compiling \"" output-file "\" from \"" cljs-path "\"..."))
(flush)
; FIXME: I do not trust the ClojureScript compiler's cljs/js caching in the
; output-dir. It seems to forget to rebuild things sometimes, and
@@ -46,17 +57,21 @@
(fs/delete-dir (:output-dir compiler-options))
(when output-file-dir
(fs/mkdirs output-file-dir))
- (let [started-at (. System (nanoTime))]
+ (let [started-at (System/nanoTime)]
(try
- (binding [compiler/*cljs-warn-on-undeclared* warn-on-undeclared]
+ (binding [compiler/*cljs-warn-on-undeclared* warn-on-undeclared?]
(build cljs-path compiler-options))
- (notify-cljs notify-command (str output-file " compiled in " (elapsed started-at) "."))
+ (notify-cljs
+ notify-command
+ (str "Successfully compiled \"" output-file "\" in " (elapsed started-at) ".") green)
(catch Throwable e
- (notify-cljs notify-command " Failed!")
+ (notify-cljs
+ notify-command
+ (str "Compiling \"" output-file "\" failed:") red)
(pst+ e))))))
(defn run-compiler [cljs-path crossover-path compiler-options notify-command
- warn-on-undeclared watch?]
+ warn-on-undeclared? watch?]
(loop [last-dependency-mtimes {}]
(let [output-file (:output-to compiler-options)
output-mtime (if (fs/exists? output-file) (fs/mod-time output-file) 0)
@@ -68,7 +83,7 @@
(not= last-dependency-mtimes dependency-mtimes)
(some #(< output-mtime %) dependency-mtimes))
(compile-cljs cljs-path compiler-options notify-command
- warn-on-undeclared))
+ warn-on-undeclared?))
(when watch?
(Thread/sleep 100)
(recur dependency-mtimes)))))
@@ -44,7 +44,7 @@
(defn- truncate-uri-path [uri n]
(if uri
(let [uri-path (.getPath uri)]
- (subs uri-path 0 (- (.length uri-path) n)))
+ (subs uri-path 0 (- (count uri-path) n)))
nil))
(defn- ns-to-path [ns]
@@ -55,11 +55,11 @@
(defn- find-crossover [crossover]
(let [ns-path (ns-to-path crossover)
as-dir (resource ns-path)
- dir-parent (truncate-uri-path as-dir (.length ns-path))
+ dir-parent (truncate-uri-path as-dir (count ns-path))
recurse-dirs (recurse-resource-dir as-dir)
ns-file-path (str ns-path ".clj")
as-file (resource ns-file-path)
- file-parent (truncate-uri-path as-file (.length ns-file-path))
+ file-parent (truncate-uri-path as-file (count ns-file-path))
all-resources (conj
(map vector (repeat dir-parent) recurse-dirs)
[file-parent as-file])
@@ -71,19 +71,28 @@
(fail "Unable to find crossover: " crossover))
resources))
-(defn- find-crossovers [crossovers]
+(defn find-crossovers [crossovers]
(distinct
(mapcat find-crossover crossovers)))
-(defn- crossover-needs-update? [from-resource to-file]
- (let [exists (fs/exists? to-file)]
- (or
- (not exists)
- (and
- ; We can't determine the mtime for jar resources; they'll just
- ; be copied once and that's it.
- (= "file" (.getProtocol from-resource))
- (> (fs/mod-time (.getPath from-resource)) (fs/mod-time to-file))))))
+(defn crossover-needs-update? [from-resource to-file]
+ (or
+ (not (fs/exists? to-file))
+ (and
+ ; We can't determine the mtime for jar resources; they'll just
+ ; be copied once and that's it.
+ (= "file" (.getProtocol from-resource))
+ (> (fs/mod-time (.getPath from-resource)) (fs/mod-time to-file)))))
+
+(defn write-crossover
+ "Write a temp file and atomically rename to the real file
+to prevent the compiler from reading a half-written file."
+ [from-resource to-file]
+ (let [temp-file (str to-file ".tmp")]
+ (spit temp-file (filtered-crossover-file from-resource))
+ (fs/rename temp-file to-file)
+ ; Mark the file as read-only, to hopefully warn the user not to modify it.
+ (fs/chmod "-w" to-file)))
(defn copy-crossovers [crossover-path crossovers]
(let [from-resources (find-crossovers crossovers)
@@ -92,10 +101,4 @@
(fs/mkdirs dir))
(doseq [[[_ from-resource] to-file] (zipmap from-resources to-files)]
(when (crossover-needs-update? from-resource to-file)
- (let [temp-file (str to-file ".tmp")]
- ; Write a temp file and atomically rename to the real file
- ; to prevent the compiler from reading a half-written file
- (spit temp-file (filtered-crossover-file from-resource))
- (fs/rename temp-file to-file)
- ; Mark the file as read-only, to hopefully warn the user not to modify it.
- (fs/chmod "-w" to-file))))))
+ (write-crossover from-resource to-file)))))
@@ -9,5 +9,6 @@
(let [output-to "a"
output-dir "b"]
(cleanup-files {:output-to output-to :output-dir output-dir}) => nil
- (provided (fs/delete output-to) => nil :times 1)
- (provided (fs/delete-dir output-dir) => nil :times 1)))
+ (provided
+ (fs/delete output-to) => nil :times 1
+ (fs/delete-dir output-dir) => nil :times 1)))
@@ -0,0 +1,37 @@
+(ns cljsbuild.test.compiler
+ (:use
+ cljsbuild.compiler
+ midje.sweet)
+ (:require
+ [cljs.closure :as cljs]
+ [cljsbuild.util :as util]
+ [clojure.java.io :as io]
+ [fs.core :as fs]))
+
+(def cljs-path "src-cljs")
+(def crossover-path "crossovers")
+(def output-to "output-to")
+(def compiler-options
+ {:output-to output-to
+ :output-dir "output-dir"
+ :optimizations :advanced
+ :pretty-print false})
+(def notify-command nil)
+(def warn-on-undeclared? true)
+(def watch? false)
+
+(fact "run-compiler calls cljs/build correctly"
+ (run-compiler
+ cljs-path
+ crossover-path
+ compiler-options
+ notify-command
+ warn-on-undeclared?
+ watch?) => nil
+ (provided
+ (fs/exists? output-to) => false :times 1
+ (util/find-files cljs-path #{"cljs"}) => ["src-cljs/a.cljs"] :times 1
+ (util/find-files crossover-path #{"cljs"}) => ["crossovers/b.cljs"] :times 1
+ (fs/mod-time "src-cljs/a.cljs") => 1000 :times 1
+ (fs/mkdirs anything) => nil
+ (cljs/build cljs-path compiler-options) => nil :times 1))
@@ -0,0 +1,42 @@
+(ns cljsbuild.test.crossover
+ (:use
+ cljsbuild.crossover
+ midje.sweet)
+ (:require
+ [clojure.java.io :as io]
+ [fs.core :as fs]))
+
+(def crossover-path "/project/crossovers")
+(def crossovers '[a a.a a.b])
+
+(fact
+ (copy-crossovers crossover-path crossovers) => nil
+ (provided
+ (find-crossovers crossovers)=>
+ [["/project/src" (io/file "/project/src/a.clj")]
+ ["/project/src" (io/file "/project/src/a/a.clj")]
+ ["/project/src" (io/file "/project/src/a/b.clj")]] :times 1
+ (fs/mkdirs anything) => nil
+ (crossover-needs-update? anything anything) => true
+ (write-crossover anything anything) => nil :times 3))
+
+(def cljsbuild-remove ";*CLJSBUILD-REMOVE*;")
+(def clojurescript-source
+ (str
+ "(ns a)
+ " cljsbuild-remove "
+ (def a 5)"))
+
+(defn- tempfile []
+ (doto (fs/temp-file) .deleteOnExit))
+
+(let [from-resource (tempfile)
+ to-file (tempfile)]
+ (spit from-resource clojurescript-source)
+ (fact "crossover files are copied/edited correctly"
+ (write-crossover from-resource to-file) => anything
+ (.indexOf (slurp to-file) cljsbuild-remove) => -1))
+
+; TODO: It would be nice to test more of the crossover features, but they
+; are pretty heavily dependent on interop and resources, which makes
+; that difficult.
Oops, something went wrong.

0 comments on commit c938f83

Please sign in to comment.