--- /dev/null
+;;; gv-tests.el --- tests for gv.el -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2017 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs 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 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs 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. If not, see <http://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(eval-when-compile (require 'cl-lib))
+
+(cl-defmacro gv-tests--in-temp-dir ((elvar elcvar)
+ (&rest filebody)
+ &rest body)
+ (declare (indent 2))
+ `(let ((default-directory (make-temp-file "gv-test" t)))
+ (unwind-protect
+ (let ((,elvar "gv-test-deffoo.el")
+ (,elcvar "gv-test-deffoo.elc"))
+ (with-temp-file ,elvar
+ (insert ";; -*- lexical-binding: t; -*-\n")
+ (dolist (form ',filebody)
+ (pp form (current-buffer))))
+ ,@body)
+ (delete-directory default-directory t))))
+
+(ert-deftest gv-define-expander-in-file ()
+ (gv-tests--in-temp-dir (el elc)
+ ((gv-define-setter gv-test-foo (newval cons)
+ `(setcar ,cons ,newval))
+ (defvar gv-test-pair (cons 1 2))
+ (setf (gv-test-foo gv-test-pair) 99)
+ (message "%d" (car gv-test-pair)))
+ (with-temp-buffer
+ (call-process (concat invocation-directory invocation-name)
+ nil '(t t) nil
+ "-Q" "-batch" "--eval" (prin1-to-string `(byte-compile-file ,el))
+ "-l" elc)
+ (should (equal (buffer-string) "99\n")))))
+
+(ert-deftest gv-define-expander-in-file-twice ()
+ (gv-tests--in-temp-dir (el elc)
+ ((gv-define-setter gv-test-foo (newval cons)
+ `(setcar ,cons ,newval))
+ (defvar gv-test-pair (cons 1 2))
+ (setf (gv-test-foo gv-test-pair) 99)
+ (gv-define-setter gv-test-foo (newval cons)
+ `(setcdr ,cons ,newval))
+ (setf (gv-test-foo gv-test-pair) 42)
+ (message "%S" gv-test-pair))
+ (with-temp-buffer
+ (call-process (concat invocation-directory invocation-name)
+ nil '(t t) nil
+ "-Q" "-batch" "--eval" (prin1-to-string `(byte-compile-file ,el))
+ "-l" elc)
+ (should (equal (buffer-string) "(99 . 42)\n")))))
+
+(ert-deftest gv-dont-define-expander-in-file ()
+ ;; The expander is defined while we are compiling the file, even
+ ;; though it's inside (when nil ...) because the compiler won't
+ ;; analyze the conditional.
+ :expected-result :failed
+ (gv-tests--in-temp-dir (el elc)
+ ((when nil (gv-define-setter gv-test-foo (newval cons)
+ `(setcar ,cons ,newval)))
+ (defvar gv-test-pair (cons 1 2))
+ (setf (gv-test-foo gv-test-pair) 99)
+ (message "%d" (car gv-test-pair)))
+ (with-temp-buffer
+ (call-process (concat invocation-directory invocation-name)
+ nil '(t t) nil
+ "-Q" "-batch" "--eval" (prin1-to-string `(byte-compile-file ,el))
+ "-l" elc)
+ (should (equal (buffer-string)
+ "Symbol's function definition is void: \\(setf\\ gv-test-foo\\)\n")))))
+
+(ert-deftest gv-define-expander-in-function ()
+ ;; The expander is not defined while we are compiling the file, the
+ ;; compiler won't handle gv definitions not at top-level.
+ :expected-result :failed
+ (gv-tests--in-temp-dir (el elc)
+ ((defun foo ()
+ (gv-define-setter gv-test-foo (newval cons)
+ `(setcar ,cons ,newval))
+ t)
+ (defvar gv-test-pair (cons 1 2))
+ (setf (gv-test-foo gv-test-pair) 99)
+ (message "%d" (car gv-test-pair)))
+ (with-temp-buffer
+ (call-process (concat invocation-directory invocation-name)
+ nil '(t t) nil
+ "-Q" "-batch" "--eval" (prin1-to-string `(byte-compile-file ,el))
+ "-l" elc)
+ (should (equal (buffer-string) "99\n")))))
+
+(ert-deftest gv-define-expander-out-of-file ()
+ (gv-tests--in-temp-dir (el elc)
+ ((gv-define-setter gv-test-foo (newval cons)
+ `(setcar ,cons ,newval))
+ (defvar gv-test-pair (cons 1 2)))
+ (with-temp-buffer
+ (call-process (concat invocation-directory invocation-name)
+ nil '(t t) nil
+ "-Q" "-batch" "--eval" (prin1-to-string `(byte-compile-file ,el))
+ "-l" elc
+ "--eval"
+ (prin1-to-string '(progn (setf (gv-test-foo gv-test-pair) 99)
+ (message "%d" (car gv-test-pair)))))
+ (should (equal (buffer-string) "99\n")))))
+
+(ert-deftest gv-dont-define-expander-other-file ()
+ (gv-tests--in-temp-dir (el elc)
+ ((if nil (gv-define-setter gv-test-foo (newval cons)
+ `(setcar ,cons ,newval)))
+ (defvar gv-test-pair (cons 1 2)))
+ (with-temp-buffer
+ (call-process (concat invocation-directory invocation-name)
+ nil '(t t) nil
+ "-Q" "-batch" "--eval" (prin1-to-string `(byte-compile-file ,el))
+ "-l" elc
+ "--eval"
+ (prin1-to-string '(progn (setf (gv-test-foo gv-test-pair) 99)
+ (message "%d" (car gv-test-pair)))))
+ (should (equal (buffer-string)
+ "Symbol's function definition is void: \\(setf\\ gv-test-foo\\)\n")))))
+
+;; `ert-deftest' messes up macroexpansion when the test file itself is
+;; compiled (see Bug #24402).
+
+;; Local Variables:
+;; no-byte-compile: t
+;; End:
+
+;;; gv-tests.el ends here