Commits

Chris Turner committed 17e9286

Refactored out parse individual check to ensure the function is only run once for each arguement-set

Comments (0)

Files changed (1)

src/clojure/spec/spec.clj

 exception "
 ")))
 
-(defstruct spec-result :fname :args :let-bindings :spec :sysout :actual-result :test-result)
+(defstruct spec-result :spec :test-passed)
 
-(defmacro parse-individual-spec [fname args let-bindings spec]
-  `(let ~let-bindings
-     (let [sysout# (new java.io.StringWriter)
-           actual# (testit ~fname ~args sysout#)
-           test-result# (let [~'value     (actual# :value)
-                              ~'exception (actual# :exception)
-                              ~'sysout    (str sysout#)]
-                          ~spec)]
-       (struct spec-result '~fname '~args '~let-bindings '~spec (str sysout#) actual# test-result#))))
+(defmacro verify-individual-spec [spec]
+  `(fn [actual# sysout#]
+     (struct spec-result '~spec (let [~'value     (actual# :value)
+                                      ~'exception (actual# :exception)
+                                      ~'sysout    sysout#]
+                                  ~spec))))
 
 (defmacro parse-spec [fname & args]
-  (let [[let-bindings spec] (if (vector? (first args))
-                              [(first args) (frest args)]
-                              [[] (first args)])
-        spec-args (first spec)
-        all-specs (map (fn [sp] `(parse-individual-spec ~fname ~spec-args ~let-bindings ~sp))
-                       (rest spec))]
+  (let [[let-bindings args] (if (vector? (first args))
+                              [(first args) (rest args)]
+                              [[]           args])
+        [spec-args & specs] (first args)
+        verified-fns (map (fn [sp] `(verify-individual-spec ~sp)) specs)]
     `(fn []
-       (doseq verification-value# (list ~@all-specs)
-         (when-not (:test-result verification-value#)
-           (throw (new Exception
-                       (pr-failure '~fname '~spec-args '~let-bindings (:spec verification-value#)
-                                   (:actual-result verification-value#) (:sysout verification-value#))))))
+       (let ~let-bindings
+         (let [sysout# (new java.io.StringWriter)
+               actual# (testit ~fname ~spec-args sysout#)
+               sysout# (str sysout#)]
+           (doseq verified-fn# (list ~@verified-fns)
+             (let [verification-value# (verified-fn# actual# sysout#)]
+               (when-not (:test-passed verification-value#)
+                 (throw (new Exception
+                             (pr-failure '~fname '~spec-args '~let-bindings (:spec verification-value#)
+                                         (:actual-result verification-value#) (:sysout verification-value#)))))))))
        true)))
 
 
        (.contains value "   Where:\n\ta = 1\n\tb = 2"))
   )
 
-(defspec parse-individual-spec
-  ([+ [] [] (= value 0)]
-      (= (value :sysout) "")
-      (= (-> value :actual-result :value) 0)
-      (= (value :test-result) true))
-  ([+ [1] [] (= value 0)]
-      (= (value :sysout) "")
-      (= (-> value :actual-result :value) 1)
-      (= (value :test-result) false))
-  ;Supports let bindings
-  ([+ [] [a 0] (= value a)]
-      (= (value :sysout) "")
-      (= (-> value :actual-result :value) 0)
-      (= (value :test-result) true))
-  ([+ [] [a 1] (= value a)]
-      (= (value :sysout) "")
-      (= (-> value :actual-result :value) 0)
-      (= (value :test-result) false))
+(defspec verify-individual-spec [value-1 {:value 1, :exception nil}
+                                 exception-foo {:value nil, :exception (Exception. "foo")}]
+  ([(= value 1)]
+      (= (:spec (value value-1 "")) '(= value 1))
+      (= (:test-passed (value value-1 "")) true))
+  ([(= value 2)]
+      (= (:spec (value value-1 "")) '(= value 2))
+      (= (:test-passed (value value-1 "")) false))
+  ([(= (.getMessage exception) "foo")]
+      (= (:spec (value exception-foo "")) '(= (.getMessage exception) "foo"))
+      (= (:test-passed (value exception-foo "")) true))
   )
 
 (defspec parse-spec