branch: scratch/el-mock
commit e5ff8a688a167c5cdf5d2f2d45f67ea1c054b225
Author: Johan Andersson <johan.rej...@gmail.com>
Commit: Johan Andersson <johan.rej...@gmail.com>

    Add el-mock.el
---
 el-mock.el | 739 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 739 insertions(+)

diff --git a/el-mock.el b/el-mock.el
new file mode 100644
index 0000000000..0521ed9622
--- /dev/null
+++ b/el-mock.el
@@ -0,0 +1,739 @@
+;;; el-mock.el --- Tiny Mock and Stub framework in Emacs Lisp
+
+;; Copyright (C) 2008, 2010, 2012  rubikitch
+
+;; Author: rubikitch <rubiki...@ruby-lang.org>
+;; Version: 1.24
+;; Keywords: lisp, testing, unittest
+;; URL: http://www.emacswiki.org/cgi-bin/wiki/download/el-mock.el
+
+;; This file is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; Emacs Lisp Mock is a library for mocking and stubbing using
+;; readable syntax. Most commonly Emacs Lisp Mock is used in
+;; conjunction with Emacs Lisp Expectations, but it can be used in
+;; other contexts.
+
+;;; Commands:
+;;
+;; Below are complete command list:
+;;
+;;
+;;; Customizable Options:
+;;
+;; Below are customizable option list:
+;;
+
+;; Emacs Lisp Mock provides two scope interface of mock and stub:
+;; `with-mock' and `mocklet'. `with-mock' only defines a
+;; scope. `mocklet' is more sophisticated interface than `with-mock':
+;; `mocklet' defines local mock and stub like `let', `flet', and
+;; `macrolet'.
+
+;; Within `with-mock' body (or argument function specified in
+;; `mock-protect'), you can create a mock and a stub. To create a
+;; stub, use `stub' macro. To create a mock, use `mock' macro.
+  
+;; For further information: see docstrings.
+;; [EVAL IT] (describe-function 'with-mock)
+;; [EVAL IT] (describe-function 'mocklet)
+;; [EVAL IT] (describe-function 'stub)
+;; [EVAL IT] (describe-function 'mock)
+
+
+;;; Bug Report:
+;;
+;; If you have problem, send a bug report via M-x mock-send-bug-report.
+;; The step is:
+;;  0) Setup mail in Emacs, the easiest way is:
+;;       (setq user-mail-address "your@mail.address")
+;;       (setq user-full-name "Your Full Name")
+;;       (setq smtpmail-smtp-server "your.smtp.server.jp")
+;;       (setq mail-user-agent 'message-user-agent)
+;;       (setq message-send-mail-function 'message-smtpmail-send-it)
+;;  1) Be sure to use the LATEST version of el-mock.el.
+;;  2) Enable debugger. M-x toggle-debug-on-error or (setq debug-on-error t)
+;;  3) Use Lisp version instead of compiled one: (load "el-mock.el")
+;;  4) Do it!
+;;  5) If you got an error, please do not close *Backtrace* buffer.
+;;  6) M-x mock-send-bug-report and M-x insert-buffer *Backtrace*
+;;  7) Describe the bug using a precise recipe.
+;;  8) Type C-c C-c to send.
+;;  # If you are a Japanese, please write in Japanese:-)
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+(require 'advice)
+
+(defvar -stubbed-functions nil)
+(defvar -mocked-functions nil)
+(defvar mock-verify-list nil)
+(defvar in-mocking nil)
+
+;;;; stub setup/teardown
+(defun stub/setup (funcsym value)
+  (mock-suppress-redefinition-message
+   (lambda ()
+     (when (fboundp funcsym)
+       (put funcsym 'mock-original-func (symbol-function funcsym)))
+     (ad-safe-fset funcsym `(lambda (&rest x) ,value)))))
+
+(defun stub/teardown (funcsym)
+  (mock-suppress-redefinition-message
+   (lambda ()
+     (let ((func (get funcsym 'mock-original-func)))
+       (if (not func)
+           (fmakunbound funcsym)
+         (ad-safe-fset funcsym func)
+         ;; may be unadviced
+         )))))
+    
+;;;; mock setup/teardown
+(defun mock/setup (func-spec value times)
+  (mock-suppress-redefinition-message
+   (lambda ()
+     (let ((funcsym (car func-spec)))
+       (when (fboundp funcsym)
+         (put funcsym 'mock-original-func (symbol-function funcsym)))
+       (put funcsym 'mock-call-count 0)
+       (ad-safe-fset funcsym
+                     `(lambda (&rest actual-args)
+                        (incf (get ',funcsym 'mock-call-count))
+                        (add-to-list 'mock-verify-list
+                                     (list ',funcsym ',(cdr func-spec) 
actual-args ,times))
+                        ,value))))))
+
+(defun not-called/setup (funcsym)
+  (mock-suppress-redefinition-message
+   (lambda ()
+     (let ()
+       (when (fboundp funcsym)
+         (put funcsym 'mock-original-func (symbol-function funcsym)))
+       (ad-safe-fset funcsym
+                     `(lambda (&rest actual-args)
+                        (signal 'mock-error '(called))))))))
+
+(defalias 'mock/teardown 'stub/teardown)
+
+;;;; mock verify
+(put 'mock-error 'error-conditions '(mock-error error))
+(put 'mock-error 'error-message "Mock error")
+(defun mock-verify ()
+  (loop for f in -mocked-functions
+        when (equal 0 (get f 'mock-call-count))
+        do (signal 'mock-error (list 'not-called f)))
+  (loop for args in mock-verify-list
+        do
+        (apply 'mock-verify-args args)))
+
+(defun mock-verify-args (funcsym expected-args actual-args expected-times)
+  (loop for e in expected-args
+        for a in actual-args
+        do
+        (unless (eq e '*)               ; `*' is wildcard argument
+          (unless (equal (eval e) a)
+            (signal 'mock-error (list (cons funcsym expected-args)
+                                      (cons funcsym actual-args))))))
+  (let ((actual-times (or (get funcsym 'mock-call-count) 0)))
+    (and expected-times (/= expected-times actual-times)
+         (signal 'mock-error (list (cons funcsym expected-args)
+                                   :expected-times expected-times
+                                   :actual-times actual-times)))))
+;;;; stub/mock provider
+(defun mock-protect (body-fn)
+  "The substance of `with-mock' macro.
+Prepare for mock/stub, call BODY-FN, and teardown mock/stub.
+
+For developer:
+When you adapt Emacs Lisp Mock to a testing framework, wrap test method around 
this function."
+  (let (mock-verify-list
+        -stubbed-functions
+        -mocked-functions
+        (in-mocking t)
+        any-error)
+    ;; (setplist 'mock-original-func nil)
+    ;; (setplist 'mock-call-count nil)
+    (unwind-protect
+        (condition-case e
+            (funcall body-fn)
+          (error (setq any-error e)))
+      (mapc #'stub/teardown -stubbed-functions)
+      (unwind-protect
+          (if any-error
+              (signal (car any-error) (cdr any-error))
+            (mock-verify))
+        (mapc #'mock/teardown -mocked-functions)))))
+
+;;;; message hack
+(defun mock-suppress-redefinition-message (func)
+  "Erase \"ad-handle-definition: `%s' got redefined\" message."
+  (prog1
+      (funcall func)
+    (message "")))
+(put 'mock-syntax-error 'error-conditions '(mock-syntax-error error))
+(put 'mock-syntax-error 'error-message "Mock syntax error")
+
+;;;; User interface
+(defmacro with-mock (&rest body)
+  "Execute the forms in BODY. You can use `mock' and `stub' in BODY.
+The value returned is the value of the last form in BODY.
+After executing BODY, mocks and stubs are guaranteed to be released.
+
+Example:
+  (with-mock
+    (stub fooz => 2)
+    (fooz 9999))                  ; => 2
+"
+  `(mock-protect
+    (lambda () ,@body)))
+(defalias 'with-stub 'with-mock)
+
+(defmacro stub (function &rest rest)
+  "Create a stub for FUNCTION.
+Stubs are temporary functions which accept any arguments and return constant 
value.
+Stubs are removed outside `with-mock' (`with-stub' is an alias) and `mocklet'.
+
+Synopsis:
+* (stub FUNCTION)
+  Create a FUNCTION stub which returns nil.
+* (stub FUNCTION => RETURN-VALUE)
+  Create a FUNCTION stub which returns RETURN-VALUE.
+
+
+Example:
+  (with-mock
+    (stub foo)
+    (stub bar => 1)
+    (and (null (foo)) (= (bar 7) 1)))     ; => t
+"
+  (let ((value (cond ((plist-get rest '=>))
+                     ((memq '=> rest) nil)
+                     ((null rest) nil)
+                     (t (signal 'mock-syntax-error '("Use `(stub FUNC)' or 
`(stub FUNC => RETURN-VALUE)'"))))))
+    `(if (not in-mocking)
+         (error "Do not use `stub' outside")
+       (stub/setup ',function ',value)
+       (push ',function -stubbed-functions))))
+
+(defmacro mock (func-spec &rest rest)
+    "Create a mock for function described by FUNC-SPEC.
+Mocks are temporary functions which accept specified arguments and return 
constant value.
+If mocked functions are not called or called by different arguments, an 
`mock-error' occurs.
+Mocks are removed outside `with-mock' and `mocklet'.
+
+Synopsis:
+* (mock (FUNCTION ARGS...))
+  Create a FUNCTION mock which returns nil.
+* (mock (FUNCTION ARGS...) => RETURN-VALUE)
+  Create a FUNCTION mock which returns RETURN-VALUE.
+* (mock (FUNCTION ARGS...) :times N)
+  FUNCTION must be called N times.
+* (mock (FUNCTION ARGS...) => RETURN-VALUE :times N)
+  Create a FUNCTION mock which returns RETURN-VALUE.
+  FUNCTION must be called N times.
+
+Wildcard:
+The `*' is a special symbol: it accepts any value for that argument position.
+
+Example:
+  (with-mock
+    (mock (f * 2) => 3)
+    (mock (g 3))
+    (and (= (f 9 2) 3) (null (g 3))))     ; => t
+  (with-mock
+    (mock (g 3))
+    (g 7))                                ; (mock-error (g 3) (g 7))
+"
+  (let* ((times (plist-get rest :times))
+         (value (cond ((plist-get rest '=>))
+                      ((memq '=> rest) nil)
+                      ((null rest) nil)
+                      ((not times) (signal 'mock-syntax-error '("Use `(mock 
FUNC-SPEC)' or `(mock FUNC-SPEC => RETURN-VALUE)'"))))))
+    `(if (not in-mocking)
+         (error "Do not use `mock' outside")
+       (mock/setup ',func-spec ',value ,times)
+       (push ',(car func-spec) -mocked-functions))))
+
+(defmacro not-called (function)
+  "Create a not-called mock for FUNCTION.
+Not-called mocks are temporary functions which raises an error when called.
+If not-called functions are called, an `mock-error' occurs.
+Not-called mocks are removed outside `with-mock' and `mocklet'.
+
+Synopsis:
+* (not-called FUNCTION)
+  Create a FUNCTION not-called mock.
+
+Example:
+  (with-mock
+    (not-called f)
+    t)     ; => t
+  (with-mock
+    (not-called g)
+    (g 7)) ; => (mock-error called)
+"
+  (let ()
+    `(if (not in-mocking)
+         (error "Do not use `not-called' outside")
+       (not-called/setup ',function)
+       (push ',function -mocked-functions))))
+
+
+(defun mock-parse-spec (spec)
+  (cons 'progn
+        (mapcar (lambda (args)
+                  (if (eq (cadr args) 'not-called)
+                      `(not-called ,(car args))
+                    (cons (if (consp (car args)) 'mock 'stub)
+                        args)))
+                spec)))
+
+(defun mocklet-function (spec body-func)
+  (with-mock
+    (eval (mock-parse-spec spec))
+    (funcall body-func)))
+
+(defmacro mocklet (speclist &rest body)
+  "`let'-like interface of `with-mock', `mock', `not-called' and `stub'.
+
+Create mocks and stubs described by SPECLIST then execute the forms in BODY.
+SPECLIST is a list of mock/not-called/stub spec.
+The value returned is the value of the last form in BODY.
+After executing BODY, mocks and stubs are guaranteed to be released.
+
+Synopsis of spec:
+Spec is arguments of `mock', `not-called' or `stub'.
+* ((FUNCTION ARGS...))                  : mock which returns nil
+* ((FUNCTION ARGS...) => RETURN-VALUE)  ; mock which returns RETURN-VALUE
+* ((FUNCTION ARGS...) :times N )        ; mock to be called N times
+* ((FUNCTION ARGS...) => RETURN-VALUE :times N )  ; mock to be called N times
+* (FUNCTION)                            : stub which returns nil
+* (FUNCTION => RETURN-VALUE)            ; stub which returns RETURN-VALUE
+* (FUNCTION not-called)                 ; not-called FUNCTION
+
+Example:
+  (mocklet (((mock-nil 1))
+            ((mock-1 *) => 1)
+            (stub-nil)
+            (stub-2 => 2))
+    (and (null (mock-nil 1))    (= (mock-1 4) 1)
+         (null (stub-nil 'any)) (= (stub-2) 2))) ; => t
+"
+  `(mocklet-function ',speclist (lambda () ,@body)))
+
+(defalias 'stublet 'mocklet)
+
+(put 'with-mock 'lisp-indent-function 0)
+(put 'with-stub 'lisp-indent-function 0)
+(put 'mocklet 'lisp-indent-function 1)
+(put 'stublet 'lisp-indent-function 1)
+
+;;;; Bug report
+(defvar mock-maintainer-mail-address
+  (concat "rubiki" "tch@ru" "by-lang.org"))
+(defvar mock-bug-report-salutation
+  "Describe bug below, using a precise recipe.
+
+When I executed M-x ...
+
+How to send a bug report:
+  1) Be sure to use the LATEST version of el-mock.el.
+  2) Enable debugger. M-x toggle-debug-on-error or (setq debug-on-error t)
+  3) Use Lisp version instead of compiled one: (load \"el-mock.el\")
+  4) If you got an error, please paste *Backtrace* buffer.
+  5) Type C-c C-c to send.
+# If you are a Japanese, please write in Japanese:-)")
+(defun mock-send-bug-report ()
+  (interactive)
+  (reporter-submit-bug-report
+   mock-maintainer-mail-address
+   "el-mock.el"
+   (apropos-internal "^mock-" 'boundp)
+   nil nil
+   mock-bug-report-salutation))
+
+;;;; unit test
+(dont-compile
+  (when (fboundp 'expectations)
+    (expectations
+      (desc "stub setup/teardown")
+      (expect 2
+        (stub/setup 'foo 2)
+        (prog1
+            (foo 1 2 3)
+          (stub/teardown 'foo)))
+      (expect nil
+        (stub/setup 'foox 2)
+        (foox 1 2 3)
+        (stub/teardown 'foox)
+        (fboundp 'foox))
+      (desc "with-mock interface")
+      (expect 9801
+        (with-mock
+          9801))
+      (desc "stub macro")
+      (expect nil
+        (with-mock
+          (stub hogehoges)
+          (hogehoges 75)))
+      (expect 2
+        (with-mock
+          (stub fooz => 2)
+          (fooz 9999)))
+      (expect nil
+        (with-mock
+          (stub fooz => 2)
+          (fooz 3))
+        (fboundp 'fooz))
+      (expect nil
+        (with-mock
+          (stub hoge)                   ;omission of return value
+          (hoge)))
+      (expect 'hoge
+        (with-mock
+          (stub me => 'hoge)
+          (me 1)))
+      (expect 34
+        (with-mock
+          (stub me => (+ 3 31))
+          (me 1)))
+      ;; TODO defie mock-syntax-error / detect mock-syntax-error in 
expectations 
+      (desc "abused stub macro")
+      (expect (error mock-syntax-error '("Use `(stub FUNC)' or `(stub FUNC => 
RETURN-VALUE)'"))
+        (with-mock
+          (stub fooz 7)))
+      (expect (error-message "Do not use `stub' outside")
+        (let (in-mocking) ; while executing `expect', `in-mocking' is t.
+          (stub hahahaha)))
+      (desc "mock macro")
+      (expect 2
+        (with-mock
+          (mock (foom 5) => 2)
+          (foom 5)))
+      (expect 3
+        (with-mock
+          (mock (foo 5) => 2)
+          (mock (bar 7) => 1)
+          (+ (foo 5) (bar 7))))
+      (expect 3
+        (flet ((plus () (+ (foo 5) (bar 7))))
+          (with-mock
+            (mock (foo 5) => 2)
+            (mock (bar 7) => 1)
+            (plus))))
+      (expect 1
+        (with-mock
+          (mock (f * 2) => 1)
+          (f 1 2)))
+      (expect 1
+        (with-mock
+          (mock (f * (1+ 1)) => (+ 0 1)) ;evaluated
+          (f 1 2)))
+      (expect nil
+        (with-mock
+          (mock (f 2))                  ;omission of return value
+          (f 2)))
+      (expect 'hoge
+        (with-mock
+          (mock (me 1) => 'hoge)
+          (me 1)))
+      (expect 34
+        (with-mock
+          (mock (me 1) => (+ 3 31))
+          (me 1)))
+
+      (desc "unfulfilled mock")
+      (expect (error mock-error '((foom 5) (foom 6)))
+        (with-mock
+          (mock (foom 5) => 2)
+          (foom 6)))
+      (expect (error mock-error '((bar 7) (bar 8)))
+        (with-mock
+          (mock (foo 5) => 2)
+          (mock (bar 7) => 1)
+          (+ (foo 5) (bar 8))))
+      (expect (error mock-error '(not-called foo))
+        (with-mock
+          (mock (foo 5) => 2)))
+      (expect (error mock-error '(not-called foo))
+        (with-mock
+          (mock (vi 5) => 2)
+          (mock (foo 5) => 2)
+          (vi 5)))
+      (expect (error mock-error '((f 2) (f 4)))
+        (with-mock
+          (mock (f 2))                  ;omission of return value
+          (f 4)))
+      (expect (error-message "error-in-test1")
+        (defun test1 () (error "error-in-test1"))
+        (with-mock
+          (mock (test2))
+          (test1)))
+      (desc "abused mock macro")
+      (expect (error mock-syntax-error '("Use `(mock FUNC-SPEC)' or `(mock 
FUNC-SPEC => RETURN-VALUE)'"))
+        (with-mock
+          (mock (fooz) 7)))
+      (expect (error-message "Do not use `mock' outside")
+        (let (in-mocking) ; while executing `expect', `in-mocking' is t.
+          (mock (hahahaha))))
+
+      (desc "mock with stub")
+      (expect 8
+        (with-mock
+          (mock (f 1 2) => 3)
+          (stub hoge => 5)
+          (+ (f 1 2) (hoge 'a))))
+      (expect (error mock-error '((f 1 2) (f 3 4)))
+        (with-mock
+          (mock (f 1 2) => 3)
+          (stub hoge => 5)
+          (+ (f 3 4) (hoge 'a))))
+
+      (desc "with-stub is an alias of with-mock")
+      (expect 'with-mock
+        (symbol-function 'with-stub))
+
+      (desc "stublet is an alias of mocklet")
+      (expect 'mocklet
+        (symbol-function 'stublet))
+
+      (desc "mock-parse-spec")
+      (expect '(progn
+                 (mock (f 1 2) => 3)
+                 (stub hoge => 5))
+        (mock-parse-spec
+         '(((f 1 2) => 3)
+           (hoge    => 5))))
+      (expect '(progn
+                 (not-called g))
+        (mock-parse-spec
+         '((g not-called))))
+
+      (desc "mocklet")
+      (expect 8
+        (mocklet (((f 1 2) => 3)
+                  (hoge    => 5))
+          (+ (f 1 2) (hoge 'a))))
+      (expect 2
+        (mocklet ((foo => 2))
+          (foo 1 2 3)))
+      (expect 3
+        (defun defined-func (x) 3)
+        (prog1
+            (mocklet ((defined-func => 3))
+              (defined-func 3))
+          (fmakunbound 'defined-func)))
+      (expect nil
+        (mocklet ((f))                  ;omission of return value
+          (f 91)))
+      (expect nil
+        (mocklet (((f 76)))             ;omission of return value
+          (f 76)))
+      (expect 5
+        (mocklet ((a => 3)
+                  (b => 2))
+          1                             ;multiple exprs
+          (+ (a 999) (b 7))))
+
+      (desc "stub for defined function")
+      (expect "xxx"
+        (defun blah (x) (* x 2))
+        (prog1
+            (let ((orig (symbol-function 'blah)))
+              (mocklet ((blah => "xxx"))
+                (blah "xx")))
+          (fmakunbound 'blah)))
+      (expect t
+        (defun blah (x) (* x 2))
+        (prog1
+            (let ((orig (symbol-function 'blah)))
+              (mocklet ((blah => "xx"))
+                (blah "xx"))
+              (equal orig (symbol-function 'blah)))
+          (fmakunbound 'blah)))
+
+      (desc "stub for adviced function")
+      (expect "xxx"
+        (mock-suppress-redefinition-message ;silence redefinition warning
+         (lambda () 
+           (defun fugaga (x) (* x 2))
+           (defadvice fugaga (around test activate)
+             (setq ad-return-value (concat "[" ad-return-value "]")))
+           (prog1
+               (let ((orig (symbol-function 'fugaga)))
+                 (mocklet ((fugaga => "xxx"))
+                   (fugaga "aaaaa")))
+             (fmakunbound 'fugaga)))))
+      (expect t
+        (mock-suppress-redefinition-message
+         (lambda ()
+           (defun fugaga (x) (* x 2))
+           (defadvice fugaga (around test activate)
+             (setq ad-return-value (concat "[" ad-return-value "]")))
+           (prog1
+               (let ((orig (symbol-function 'fugaga)))
+                 (mocklet ((fugaga => "xx"))
+                   (fugaga "aaaaa"))
+                 (equal orig (symbol-function 'fugaga)))
+             (fmakunbound 'fugaga)))))
+
+      (desc "mock for adviced function")
+      (expect "xx"
+        (mock-suppress-redefinition-message
+         (lambda ()
+           (defun fugaga (x) (* x 2))
+           (defadvice fugaga (around test activate)
+             (setq ad-return-value (concat "[" ad-return-value "]")))
+           (prog1
+               (let ((orig (symbol-function 'fugaga)))
+                 (mocklet (((fugaga "aaaaa") => "xx"))
+                   (fugaga "aaaaa")))
+             (fmakunbound 'fugaga)))))
+      (expect t
+        (mock-suppress-redefinition-message
+         (lambda ()
+           (defun fugaga (x) (* x 2))
+           (defadvice fugaga (around test activate)
+             (setq ad-return-value (concat "[" ad-return-value "]")))
+           (prog1
+               (let ((orig (symbol-function 'fugaga)))
+                 (mocklet (((fugaga "aaaaa") => "xx"))
+                   (fugaga "aaaaa"))
+                 (equal orig (symbol-function 'fugaga)))
+             (fmakunbound 'fugaga)))))
+      (desc "not-called macro")
+      (expect 'ok
+        (with-mock
+          (not-called foom)
+          'ok))
+      (desc "mocklet/notcalled")
+      (expect 'ok
+        (mocklet ((foom not-called))
+          'ok))
+      (desc "unfulfilled not-called")
+      (expect (error mock-error '(called))
+        (with-mock
+          (not-called hoge)
+          (hoge 1)))
+      (desc "abused not-called macro")
+      (expect (error-message "Do not use `not-called' outside")
+        (let (in-mocking) ; while executing `expect', `in-mocking' is t.
+          (not-called hahahaha)))
+      (desc "not-called for adviced function")
+      (expect "not-called"
+        (mock-suppress-redefinition-message ;silence redefinition warning
+         (lambda () 
+           (defun fugaga (x) (* x 2))
+           (defadvice fugaga (around test activate)
+             (setq ad-return-value (concat "[" ad-return-value "]")))
+           (prog1
+               (let ((orig (symbol-function 'fugaga)))
+                 (mocklet ((fugaga not-called))
+                   "not-called"))
+             (fmakunbound 'fugaga)))))
+      (expect t
+        (mock-suppress-redefinition-message
+         (lambda ()
+           (defun fugaga (x) (* x 2))
+           (defadvice fugaga (around test activate)
+             (setq ad-return-value (concat "[" ad-return-value "]")))
+           (prog1
+               (let ((orig (symbol-function 'fugaga)))
+                 (mocklet ((fugaga not-called))
+                   "not-called")
+                 (equal orig (symbol-function 'fugaga)))
+             (fmakunbound 'fugaga)))))
+      (desc ":times mock")
+      (expect 'ok
+        (with-mock
+          (mock (foo 1) => 2 :times 2)
+          (foo 1)
+          (foo 1)
+          'ok))
+      (expect 'ok
+        (with-mock
+          (mock (foo *) => 2 :times 2)
+          (foo 1)
+          (foo 2)
+          'ok))
+      (expect 'ok
+        (with-mock
+          (mock (foo 1) :times 2)
+          (foo 1)
+          (foo 1)
+          'ok))
+      (expect 'ok
+        (with-mock
+          (mock (foo *) :times 2)
+          (foo 1)
+          (foo 2)
+          'ok))
+      ;; FIXME
+      ;; (expect 'ok
+      ;;   (with-mock
+      ;;     (mock (foo 1) => 2 :times 2)
+      ;;     (foo 1)
+      ;;     (foo 1)
+      ;;     (foo 2)
+      ;;     'ok))
+      (expect (error mock-error '((foo 1) :expected-times 2 :actual-times 1))
+        (with-mock
+          (mock (foo 1) :times 2)
+          (foo 1)
+          'ok))
+      (expect (error mock-error '((foo *) :expected-times 2 :actual-times 1))
+        (with-mock
+          (mock (foo *) :times 2)
+          (foo 1)
+          'ok))
+      (expect (error mock-error '((foo 1) (foo 2)))
+        (with-mock
+          (mock (foo 1) :times 2)
+          (foo 2)
+          'ok))
+      (expect (error mock-error '(not-called foo))
+        (with-mock
+          (mock (foo 1) :times 2)
+          'ok))
+      (expect (error mock-error '((foo 1) :expected-times 2 :actual-times 1))
+        (with-mock
+          (mock (foo 1) => 2 :times 2)
+          (foo 1)
+          'ok))
+      (expect (error mock-error '((foo *) :expected-times 2 :actual-times 1))
+        (with-mock
+          (mock (foo *) => 2 :times 2)
+          (foo 1)
+          'ok))
+      (expect (error mock-error '((foo 1) (foo 2)))
+        (with-mock
+          (mock (foo 1) => 2 :times 2)
+          (foo 2)
+          'ok))
+      (expect (error mock-error '(not-called foo))
+        (with-mock
+          (mock (foo 1) => 2 :times 2)
+          'ok))
+      )))
+
+(provide 'el-mock)
+
+;; How to save (DO NOT REMOVE!!)
+;; (emacswiki-post "el-mock.el")
+;;; el-mock.el ends here

Reply via email to