From 4a38fc35663f8d8dfca349acc0b80a7aebe90e02 Mon Sep 17 00:00:00 2001
From: Matt Clark <matt.clark.1@gmail.com>
Date: Sun, 7 Feb 2010 20:57:17 -0400
Subject: [PATCH 2/2] removed assert-args macro borrowed from core and replaced it with :pre conditions. Added :pre to all user facing functions.

---
 src/main/clojure/clojure/contrib/mock.clj |  111 +++++++++++++---------------
 1 files changed, 52 insertions(+), 59 deletions(-)

diff --git a/src/main/clojure/clojure/contrib/mock.clj b/src/main/clojure/clojure/contrib/mock.clj
index e8d1abc..7da68b4 100644
--- a/src/main/clojure/clojure/contrib/mock.clj
+++ b/src/main/clojure/clojure/contrib/mock.clj
@@ -7,7 +7,7 @@
 ;;  License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which can
 ;;  be found in the file epl-v10.html at the root of this distribution.  By
 ;;  using this software in any fashion, you are agreeing to be bound by the
-;;  terms of this license.  You must not remove this notice, or any other,
+;;  terms of this license.  You must not remove this notice, or any other
 ;;  from this software.
 ;;------------------------------------------------------------------------------
 
@@ -19,39 +19,39 @@
   ;; Mock uses bindings to wrap the functions that are being tested and
   ;; then validates the invocation count at the end. The expect macro is the
   ;; main entry point and it is given a vector of binding pairs.
-  ;; The first of each pair names the dependent function you want to override,
+  ;; The first of each pair names the dependent function you want to override
   ;; while the second is a hashmap containing the mock description, usually
   ;; created via the simple helper methods described below.
   ;;
   ;; Usage:
   ;;
   ;; there are one or more dependent functions:
-  
+
   (defn dep-fn1 [] "time consuming calculation in 3rd party library")
   (defn dep-fn2 [x] "function with undesirable side effects while testing")
-  
+
   ;; then we have the code under test that calls these other functions:
-  
+
   (defn my-code-under-test [] (dep-fn1) (dep-fn2 "a") (+ 2 2))
 
   ;; to test this code, we simply surround it with an expect macro within
   ;; the test:
-  
+
   (expect [dep-fn1 (times 1)
            dep-fn2 (times 1 (has-args [#(= "a" %)]))]
-    (my-code-under-test))
+          (my-code-under-test))
 
-  ;; When an expectation fails during execution of the function under test,
+  ;; When an expectation fails during execution of the function under test
   ;; an error condition function is called with the name of the function
   ;; being mocked, the expected form and the actual value. These
   ;; error functions can be overridden to allow easy integration into
   ;; test frameworks such as test-is by reporting errors in the function
   ;; overrides.
-  
+
   ) ;; end comment
 
 (ns clojure.contrib.mock
-  #^{:author "Matt Clark",
+  #^{:author "Matt Clark"
      :doc "function mocking/expectations for Clojure" }
   (:use [clojure.contrib.seq :only (positions)]
         [clojure.contrib.def :only (defmacro-)]))
@@ -64,24 +64,24 @@
 (defn report-problem
   {:dynamic true}
   ([function expected actual]
-    (report-problem function expected actual "Expectation not met."))
+     (report-problem function expected actual "Expectation not met."))
   ([function expected actual message]
-    (prn (str message " Function name: " function
-           " expected: " expected " actual: " actual))))
+     (prn (str message " Function name: " function
+               " expected: " expected " actual: " actual))))
 
 (defn no-matching-function-signature
-  {:dynamic true} 
+  {:dynamic true}
   [function expected actual]
   (report-problem function expected actual
-    "No matching real function signature for given argument count."))
+                  "No matching real function signature for given argument count."))
 
-(defn unexpected-args 
+(defn unexpected-args
   {:dynamic true}
   [function expected actual i]
   (report-problem function expected actual
-    (str "Argument " i " has an unexpected value for function.")))
+                  (str "Argument " i " has an unexpected value for function.")))
 
-(defn incorrect-invocation-count 
+(defn incorrect-invocation-count
   {:dynamic true}
   [function expected actual]
   (report-problem function expected actual "Unexpected invocation count."))
@@ -92,7 +92,7 @@
 
 
 (defn- has-arg-count-match?
-  "Given the sequence of accepted argument vectors for a function,
+  "Given the sequence of accepted argument vectors for a function
 returns true if at least one matches the given-count value."
   [arg-lists given-count]
   (some #(let [[ind] (positions #{'&} %)]
@@ -108,9 +108,9 @@ function. If no argslist meta data is available for the function, it is
 not called."
   [fn-name args]
   (let [arg-count (count args)
-            arg-lists (:arglists (meta (resolve fn-name)))]
-        (if (and arg-lists (not (has-arg-count-match? arg-lists arg-count)))
-          (no-matching-function-signature fn-name arg-lists args))))
+        arg-lists (:arglists (meta (resolve fn-name)))]
+    (if (and arg-lists (not (has-arg-count-match? arg-lists arg-count)))
+      (no-matching-function-signature fn-name arg-lists args))))
 
 
 (defn make-arg-checker
@@ -123,10 +123,10 @@ of the mock info object created by make-mock."
   (let [sanitized-preds (map (fn [v] (if (fn? v) v #(= v %))) arg-preds)]
     (fn [fn-name & args]
       (every? true?
-        (map (fn [pred arg pred-form i] (if (pred arg) true
-                                          (unexpected-args fn-name
-                                            pred-form arg i)))
-          sanitized-preds args arg-pred-forms (iterate inc 0))))))
+              (map (fn [pred arg pred-form i] (if (pred arg) true
+                                                  (unexpected-args fn-name
+                                                                   pred-form arg i)))
+                   sanitized-preds args arg-pred-forms (iterate inc 0))))))
 
 
 (defn make-count-checker
@@ -136,33 +136,23 @@ name of the associated dependency and the invocation count as arguments."
   [pred pred-form]
   (let [pred-fn (if (integer? pred) #(= pred %) pred)]
     (fn [fn-name v] (if (pred-fn v) true
-                      (incorrect-invocation-count fn-name pred-form v)))))
-
-; Borrowed from clojure core. Remove if this ever becomes public there.
-(defmacro- assert-args
-  [fnname & pairs]
-  `(do (when-not ~(first pairs)
-         (throw (IllegalArgumentException.
-                  ~(str fnname " requires " (second pairs)))))
-     ~(let [more (nnext pairs)]
-        (when more
-          (list* `assert-args fnname more)))))
+                        (incorrect-invocation-count fn-name pred-form v)))))
 
 (defn make-mock
   "creates a vector containing the following information for the named function:
-1. dependent function replacement - verifies signature, calls arg checker,
+1. dependent function replacement - verifies signature, calls arg checker
 increases count, returns return value.
 2. an atom containing the invocation count
 3. the invocation count checker function
 4. a symbol of the name of the function being replaced."
   [fn-name expectation-hash]
-  (assert-args make-mock
-    (map? expectation-hash) "a map of expectations")
+  {:pre [(map? expectation-hash)
+         (symbol? fn-name)]}
   (let [arg-checker (or (expectation-hash :has-args) (fn [& args] true))
         count-atom (atom 0)
         ret-fn (or
-                 (expectation-hash :calls)
-                 (fn [& args] (expectation-hash :returns)))]
+                (expectation-hash :calls)
+                (fn [& args] (expectation-hash :returns)))]
     [(fn [& args]
        (has-matching-signature? fn-name args)
        (apply arg-checker fn-name args)
@@ -178,10 +168,10 @@ increases count, returns return value.
 count checker for each dependency."
   [mock-data] (doseq [[mfn i checker fn-name] mock-data] (checker fn-name @i)))
 
-(defn #^{:private true} make-bindings [expect-bindings mock-data-sym]
+(defn- make-bindings [expect-bindings mock-data-sym]
   `[~@(interleave (map #(first %) (partition 2 expect-bindings))
-        (map (fn [i] `(nth (nth ~mock-data-sym ~i) 0))
-          (range (quot (count expect-bindings) 2))))])
+                  (map (fn [i] `(nth (nth ~mock-data-sym ~i) 0))
+                       (range (quot (count expect-bindings) 2))))])
 
 
 ;;------------------------------------------------------------------------------
@@ -215,7 +205,9 @@ Usage:
 (returns ret-value expectation-hash?)"
 
   ([val] (returns val {}))
-  ([val expectation-hash] (assoc expectation-hash :returns val)))
+  ([val expectation-hash]
+   {:pre [(map? expectation-hash)]}
+   (assoc expectation-hash :returns val)))
 
 
 (defn calls
@@ -227,7 +219,9 @@ Usage:
 (calls some-fn expectation-hash?)"
 
   ([val] (calls val {}))
-  ([val expectation-hash] (assoc expectation-hash :calls val)))
+  ([val expectation-hash]
+   {:pre [(map? expectation-hash)]}
+   (assoc expectation-hash :calls val)))
 
 
 (defmacro has-args
@@ -241,10 +235,10 @@ Usage:
 (has-args [arg-pred-1 arg-pred-2 ... arg-pred-n] expectation-hash?)"
 
   ([arg-pred-forms] `(has-args ~arg-pred-forms {}))
-  ([arg-pred-forms expect-hash-form]
-    (assert-args has-args
-      (vector? arg-pred-forms) "a vector of argument predicates")
-    `(assoc ~expect-hash-form :has-args
+  ([arg-pred-forms expectation-hash]
+   {:pre [(vector? arg-pred-forms)
+          (map? expectation-hash)]}
+    `(assoc ~expectation-hash :has-args
        (make-arg-checker ~arg-pred-forms '~arg-pred-forms))))
 
 
@@ -261,25 +255,24 @@ Usage:
 (times n expectation-hash)"
   ([times-fn] `(times ~times-fn {}))
   ([times-fn expectation-hash]
-    `(assoc ~expectation-hash :times (make-count-checker ~times-fn '~times-fn))))
+   {:pre [(map? expectation-hash)]}
+   `(assoc ~expectation-hash :times (make-count-checker ~times-fn '~times-fn))))
 
 
 ;-------------------------------------------------------------------------------
 ; The main expect macro.
 (defmacro expect
- "Use expect to redirect calls to dependent functions that are made within the
-code under test. Instead of calling the functions that would normally be used,
+  "Use expect to redirect calls to dependent functions that are made within the
+code under test. Instead of calling the functions that would normally be used
 temporary stubs are used, which can verify function parameters and call counts.
 Return values of overridden functions can also be specified as needed.
 Usage:
 (expect [dep-fn (has-args [arg-pred1] (times n (returns x)))]
-  (function-under-test a b c))"
+        (function-under-test a b c))"
 
   [expect-bindings & body]
-  (assert-args expect
-    (vector? expect-bindings) "a vector of expectation bindings"
-    (even? (count expect-bindings))
-    "an even number of forms in expectation bindings")
+   {:pre [(vector? expect-bindings)
+          (even? (count expect-bindings))]}
   (let [mock-data (gensym "mock-data_")]
     `(let [~mock-data (map (fn [args#]
                              (apply clojure.contrib.mock/make-mock args#))
-- 
1.6.3.3

