summaryrefslogtreecommitdiff
path: root/test/lisp/emacs-lisp
diff options
context:
space:
mode:
Diffstat (limited to 'test/lisp/emacs-lisp')
-rw-r--r--test/lisp/emacs-lisp/benchmark-tests.el2
-rw-r--r--test/lisp/emacs-lisp/bytecomp-tests.el34
-rw-r--r--test/lisp/emacs-lisp/checkdoc-tests.el2
-rw-r--r--test/lisp/emacs-lisp/cl-extra-tests.el2
-rw-r--r--test/lisp/emacs-lisp/cl-generic-tests.el26
-rw-r--r--test/lisp/emacs-lisp/cl-lib-tests.el34
-rw-r--r--test/lisp/emacs-lisp/cl-macs-tests.el500
-rw-r--r--test/lisp/emacs-lisp/cl-print-tests.el4
-rw-r--r--test/lisp/emacs-lisp/cl-seq-tests.el6
-rw-r--r--test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el134
-rw-r--r--test/lisp/emacs-lisp/edebug-tests.el917
-rw-r--r--test/lisp/emacs-lisp/eieio-tests/eieio-test-methodinvoke.el4
-rw-r--r--test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el36
-rw-r--r--test/lisp/emacs-lisp/eieio-tests/eieio-tests.el24
-rw-r--r--test/lisp/emacs-lisp/ert-tests.el21
-rw-r--r--test/lisp/emacs-lisp/ert-x-tests.el2
-rw-r--r--test/lisp/emacs-lisp/faceup-resources/faceup-test-mode.el76
-rw-r--r--test/lisp/emacs-lisp/faceup-resources/faceup-test-this-file-directory.el32
-rw-r--r--test/lisp/emacs-lisp/faceup-resources/files/test1.txt15
-rw-r--r--test/lisp/emacs-lisp/faceup-resources/files/test1.txt.faceup15
-rw-r--r--test/lisp/emacs-lisp/faceup-tests/faceup-test-basics.el269
-rw-r--r--test/lisp/emacs-lisp/faceup-tests/faceup-test-files.el63
-rw-r--r--test/lisp/emacs-lisp/generator-tests.el12
-rw-r--r--test/lisp/emacs-lisp/gv-tests.el147
-rw-r--r--test/lisp/emacs-lisp/let-alist-tests.el2
-rw-r--r--test/lisp/emacs-lisp/lisp-mode-tests.el28
-rw-r--r--test/lisp/emacs-lisp/lisp-tests.el33
-rw-r--r--test/lisp/emacs-lisp/map-tests.el20
-rw-r--r--test/lisp/emacs-lisp/nadvice-tests.el2
-rw-r--r--test/lisp/emacs-lisp/package-tests.el2
-rw-r--r--test/lisp/emacs-lisp/pcase-tests.el2
-rw-r--r--test/lisp/emacs-lisp/pp-tests.el2
-rw-r--r--test/lisp/emacs-lisp/regexp-opt-tests.el2
-rw-r--r--test/lisp/emacs-lisp/ring-tests.el2
-rw-r--r--test/lisp/emacs-lisp/rmc-tests.el41
-rw-r--r--test/lisp/emacs-lisp/rx-tests.el12
-rw-r--r--test/lisp/emacs-lisp/seq-tests.el2
-rw-r--r--test/lisp/emacs-lisp/subr-x-tests.el315
-rw-r--r--test/lisp/emacs-lisp/tabulated-list-test.el2
-rw-r--r--test/lisp/emacs-lisp/testcover-resources/testcases.el50
-rw-r--r--test/lisp/emacs-lisp/testcover-tests.el14
-rw-r--r--test/lisp/emacs-lisp/thunk-tests.el52
-rw-r--r--test/lisp/emacs-lisp/timer-tests.el2
43 files changed, 2729 insertions, 233 deletions
diff --git a/test/lisp/emacs-lisp/benchmark-tests.el b/test/lisp/emacs-lisp/benchmark-tests.el
index 14426aeec41..e1b67f1ed17 100644
--- a/test/lisp/emacs-lisp/benchmark-tests.el
+++ b/test/lisp/emacs-lisp/benchmark-tests.el
@@ -15,7 +15,7 @@
;; 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/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Code:
diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el b/test/lisp/emacs-lisp/bytecomp-tests.el
index d15bd8b6e65..f508c365427 100644
--- a/test/lisp/emacs-lisp/bytecomp-tests.el
+++ b/test/lisp/emacs-lisp/bytecomp-tests.el
@@ -21,7 +21,7 @@
;; 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/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@@ -512,7 +512,9 @@ bytecompiled code, and their results compared.")
`(let ((,file-name-var (make-temp-file "emacs")))
(unwind-protect
(progn ,@body)
- (delete-file ,file-name-var))))
+ (delete-file ,file-name-var)
+ (let ((elc (concat ,file-name-var ".elc")))
+ (if (file-exists-p elc) (delete-file elc))))))
(ert-deftest bytecomp-tests--unescaped-char-literals ()
"Check that byte compiling warns about unescaped character
@@ -545,6 +547,34 @@ literals (Bug#20852)."
This functionality has been obsolete for more than 10 years already
and will be removed soon. See (elisp)Backquote in the manual.")))))))
+
+(ert-deftest bytecomp-tests-function-put ()
+ "Check `function-put' operates during compilation."
+ (should (boundp 'lread--old-style-backquotes))
+ (bytecomp-tests--with-temp-file source
+ (dolist (form '((function-put 'bytecomp-tests--foo 'foo 1)
+ (function-put 'bytecomp-tests--foo 'bar 2)
+ (defmacro bytecomp-tests--foobar ()
+ `(cons ,(function-get 'bytecomp-tests--foo 'foo)
+ ,(function-get 'bytecomp-tests--foo 'bar)))
+ (defvar bytecomp-tests--foobar 1)
+ (setq bytecomp-tests--foobar (bytecomp-tests--foobar))))
+ (print form (current-buffer)))
+ (write-region (point-min) (point-max) source nil 'silent)
+ (byte-compile-file source t)
+ (should (equal bytecomp-tests--foobar (cons 1 2)))))
+
+(ert-deftest bytecomp-tests--test-no-warnings-with-advice ()
+ (defun f ())
+ (define-advice f (:around (oldfun &rest args) test)
+ (apply oldfun args))
+ (with-current-buffer (get-buffer-create "*Compile-Log*")
+ (let ((inhibit-read-only t)) (erase-buffer)))
+ (test-byte-comp-compile-and-load t '(defun f ()))
+ (with-current-buffer (get-buffer-create "*Compile-Log*")
+ (goto-char (point-min))
+ (should-not (search-forward "Warning" nil t))))
+
;; Local Variables:
;; no-byte-compile: t
;; End:
diff --git a/test/lisp/emacs-lisp/checkdoc-tests.el b/test/lisp/emacs-lisp/checkdoc-tests.el
index 69985506f78..d832a862280 100644
--- a/test/lisp/emacs-lisp/checkdoc-tests.el
+++ b/test/lisp/emacs-lisp/checkdoc-tests.el
@@ -17,7 +17,7 @@
;; 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/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
diff --git a/test/lisp/emacs-lisp/cl-extra-tests.el b/test/lisp/emacs-lisp/cl-extra-tests.el
index 5b2371e7b95..c37caa1aab7 100644
--- a/test/lisp/emacs-lisp/cl-extra-tests.el
+++ b/test/lisp/emacs-lisp/cl-extra-tests.el
@@ -15,7 +15,7 @@
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see `http://www.gnu.org/licenses/'.
+;; along with this program. If not, see `https://www.gnu.org/licenses/'.
;;; Code:
diff --git a/test/lisp/emacs-lisp/cl-generic-tests.el b/test/lisp/emacs-lisp/cl-generic-tests.el
index 0768e31f7e6..9b2b04bcca4 100644
--- a/test/lisp/emacs-lisp/cl-generic-tests.el
+++ b/test/lisp/emacs-lisp/cl-generic-tests.el
@@ -17,7 +17,7 @@
;; 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/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@@ -219,5 +219,29 @@
(should (equal (cl--generic-1 '(5) nil) '("cinq" (5))))
(should (equal (cl--generic-1 '(6) nil) '("six" a))))
+(cl-defgeneric cl-generic-tests--generic (x))
+(cl-defmethod cl-generic-tests--generic ((x string))
+ (message "%s is a string" x))
+(cl-defmethod cl-generic-tests--generic ((x integer))
+ (message "%s is a number" x))
+(cl-defgeneric cl-generic-tests--generic-without-methods (x y))
+(defvar cl-generic-tests--this-file
+ (file-truename (or load-file-name buffer-file-name)))
+
+(ert-deftest cl-generic-tests--method-files--finds-methods ()
+ "`method-files' returns a list of files and methods for a generic function."
+ (let ((retval (cl--generic-method-files 'cl-generic-tests--generic)))
+ (should (equal (length retval) 2))
+ (mapc (lambda (x)
+ (should (equal (car x) cl-generic-tests--this-file))
+ (should (equal (cadr x) 'cl-generic-tests--generic)))
+ retval)
+ (should-not (equal (nth 0 retval) (nth 1 retval)))))
+
+(ert-deftest cl-generic-tests--method-files--nonexistent-methods ()
+ "`method-files' returns nil if asked to find a method which doesn't exist."
+ (should-not (cl--generic-method-files 'cl-generic-tests--undefined-generic))
+ (should-not (cl--generic-method-files 'cl-generic-tests--generic-without-methods)))
+
(provide 'cl-generic-tests)
;;; cl-generic-tests.el ends here
diff --git a/test/lisp/emacs-lisp/cl-lib-tests.el b/test/lisp/emacs-lisp/cl-lib-tests.el
index 65bd97f3b2d..692dd0f72cf 100644
--- a/test/lisp/emacs-lisp/cl-lib-tests.el
+++ b/test/lisp/emacs-lisp/cl-lib-tests.el
@@ -1,4 +1,4 @@
-;;; cl-lib.el --- tests for emacs-lisp/cl-lib.el -*- lexical-binding:t -*-
+;;; cl-lib-tests.el --- tests for emacs-lisp/cl-lib.el -*- lexical-binding:t -*-
;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
@@ -15,7 +15,7 @@
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see `http://www.gnu.org/licenses/'.
+;; along with this program. If not, see `https://www.gnu.org/licenses/'.
;;; Commentary:
@@ -195,15 +195,16 @@
(should (eql (cl-mismatch "Aa" "aA") 0))
(should (eql (cl-mismatch '(a b c) '(a b d)) 2)))
-(ert-deftest cl-lib-test-loop ()
- (should (eql (cl-loop with (a b c) = '(1 2 3) return (+ a b c)) 6)))
-
(ert-deftest cl-lib-keyword-names-versus-values ()
(should (equal
(funcall (cl-function (lambda (&key a b) (list a b)))
:b :a :a 42)
'(42 :a))))
+(ert-deftest cl-lib-empty-keyargs ()
+ (should-error (funcall (cl-function (lambda (&key) 1))
+ :b 1)))
+
(cl-defstruct (mystruct
(:constructor cl-lib--con-1 (&aux (abc 1)))
(:constructor cl-lib--con-2 (&optional def) "Constructor docstring."))
@@ -480,9 +481,6 @@
(should (= 239 (cl-parse-integer "zzef" :radix 16 :start 2)))
(should (= -123 (cl-parse-integer " -123 "))))
-(ert-deftest cl-loop-destructuring-with ()
- (should (equal (cl-loop with (a b c) = '(1 2 3) return (+ a b c)) 6)))
-
(ert-deftest cl-flet-test ()
(should (equal (cl-flet ((f1 (x) x)) (let ((x #'f1)) (funcall x 5))) 5)))
@@ -518,7 +516,25 @@
(ert-deftest cl-lib-symbol-macrolet-2 ()
(should (equal (cl-lib-symbol-macrolet-4+5) (+ 4 5))))
+
+(ert-deftest cl-lib-symbol-macrolet-hide ()
+ ;; bug#26325
+ (should (equal (let ((y 5))
+ (cl-symbol-macrolet ((x y))
+ (list x
+ (let ((x 6)) (list x y))
+ (cl-letf ((x 6)) (list x y)))))
+ '(5 (6 5) (6 6)))))
+
+(defun cl-lib-tests--dummy-function ()
+ ;; Dummy function to see if the file is compiled.
+ t)
+
(ert-deftest cl-lib-defstruct-record ()
+ ;; This test fails when compiled, see Bug#24402/27718.
+ :expected-result (if (byte-code-function-p
+ (symbol-function 'cl-lib-tests--dummy-function))
+ :failed :passed)
(cl-defstruct foo x)
(let ((x (make-foo :x 42)))
(should (recordp x))
@@ -548,4 +564,4 @@
(should cl-old-struct-compat-mode)
(cl-old-struct-compat-mode (if saved 1 -1))))
-;;; cl-lib.el ends here
+;;; cl-lib-tests.el ends here
diff --git a/test/lisp/emacs-lisp/cl-macs-tests.el b/test/lisp/emacs-lisp/cl-macs-tests.el
new file mode 100644
index 00000000000..575f170af6c
--- /dev/null
+++ b/test/lisp/emacs-lisp/cl-macs-tests.el
@@ -0,0 +1,500 @@
+;;; cl-macs-tests.el --- tests for emacs-lisp/cl-macs.el -*- lexical-binding:t -*-
+
+;; Copyright (C) 2017 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; This program 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.
+;;
+;; This program 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 this program. If not, see `https://www.gnu.org/licenses/'.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'cl-macs)
+(require 'ert)
+
+
+;;;; cl-loop tests -- many adapted from Steele's CLtL2
+
+;;; ANSI 6.1.1.7 Destructuring
+(ert-deftest cl-macs-loop-and-assignment ()
+ ;; Bug#6583
+ :expected-result :failed
+ (should (equal (cl-loop for numlist in '((1 2 4.0) (5 6 8.3) (8 9 10.4))
+ for a = (cl-first numlist)
+ and b = (cl-second numlist)
+ and c = (cl-third numlist)
+ collect (list c b a))
+ '((4.0 2 1) (8.3 6 5) (10.4 9 8)))))
+
+(ert-deftest cl-macs-loop-destructure ()
+ (should (equal (cl-loop for (a b c) in '((1 2 4.0) (5 6 8.3) (8 9 10.4))
+ collect (list c b a))
+ '((4.0 2 1) (8.3 6 5) (10.4 9 8)))))
+
+(ert-deftest cl-macs-loop-destructure-nil ()
+ (should (equal (cl-loop for (a nil b) = '(1 2 3)
+ do (cl-return (list a b)))
+ '(1 3))))
+
+(ert-deftest cl-macs-loop-destructure-cons ()
+ (should (equal (cl-loop for ((a . b) (c . d)) in
+ '(((1.2 . 2.4) (3 . 4)) ((3.4 . 4.6) (5 . 6)))
+ collect (list a b c d))
+ '((1.2 2.4 3 4) (3.4 4.6 5 6)))))
+
+(ert-deftest cl-loop-destructuring-with ()
+ (should (equal (cl-loop with (a b c) = '(1 2 3) return (+ a b c)) 6)))
+
+;;; 6.1.2.1.1 The for-as-arithmetic subclause
+(ert-deftest cl-macs-loop-for-as-arith ()
+ "Test various for-as-arithmetic subclauses."
+ :expected-result :failed
+ (should (equal (cl-loop for i to 10 by 3 collect i)
+ '(0 3 6 9)))
+ (should (equal (cl-loop for i upto 3 collect i)
+ '(0 1 2 3)))
+ (should (equal (cl-loop for i below 3 collect i)
+ '(0 1 2)))
+ (should (equal (cl-loop for i below 10 by 2 collect i)
+ '(0 2 4 6 8)))
+ (should (equal (cl-loop for i downfrom 10 above 4 by 2 collect i)
+ '(10 8 6)))
+ (should (equal (cl-loop for i from 10 downto 1 by 3 collect i)
+ '(10 7 4 1)))
+ (should (equal (cl-loop for i above 0 by 2 downfrom 10 collect i)
+ '(10 8 6 4 2)))
+ (should (equal (cl-loop for i downto 10 from 15 collect i)
+ '(15 14 13 12 11 10))))
+
+(ert-deftest cl-macs-loop-for-as-arith-order-side-effects ()
+ "Test side effects generated by different arithmetic phrase order."
+ :expected-result :failed
+ (should
+ (equal (let ((x 1)) (cl-loop for i from x to 10 by (cl-incf x) collect i))
+ '(1 3 5 7 9)))
+ (should
+ (equal (let ((x 1)) (cl-loop for i from x by (cl-incf x) to 10 collect i))
+ '(1 3 5 7 9)))
+ (should
+ (equal (let ((x 1)) (cl-loop for i to 10 from x by (cl-incf x) collect i))
+ '(1 3 5 7 9)))
+ (should
+ (equal (let ((x 1)) (cl-loop for i to 10 by (cl-incf x) from x collect i))
+ '(2 4 6 8 10)))
+ (should
+ (equal (let ((x 1)) (cl-loop for i by (cl-incf x) from x to 10 collect i))
+ '(2 4 6 8 10)))
+ (should
+ (equal (let ((x 1)) (cl-loop for i by (cl-incf x) to 10 from x collect i))
+ '(2 4 6 8 10))))
+
+(ert-deftest cl-macs-loop-for-as-arith-invalid ()
+ "Test for invalid phrase combinations."
+ :expected-result :failed
+ ;; Mixing arithmetic-up and arithmetic-down* subclauses
+ (should-error (cl-loop for i downfrom 10 below 20 collect i))
+ (should-error (cl-loop for i upfrom 20 above 10 collect i))
+ (should-error (cl-loop for i upto 10 by 2 downfrom 5))
+ ;; Repeated phrases
+ (should-error (cl-loop for i from 10 to 20 above 10))
+ (should-error (cl-loop for i from 10 to 20 upfrom 0))
+ (should-error (cl-loop for i by 2 to 10 by 5))
+ ;; negative step
+ (should-error (cl-loop for i by -1))
+ ;; no step given for a downward loop
+ (should-error (cl-loop for i downto -5 collect i)))
+
+
+;;; 6.1.2.1.2 The for-as-in-list subclause
+(ert-deftest cl-macs-loop-for-as-in-list ()
+ (should (equal (cl-loop for x in '(1 2 3 4 5 6) collect (* x x))
+ '(1 4 9 16 25 36)))
+ (should (equal (cl-loop for x in '(1 2 3 4 5 6) by #'cddr collect (* x x))
+ '(1 9 25))))
+
+;;; 6.1.2.1.3 The for-as-on-list subclause
+(ert-deftest cl-macs-loop-for-as-on-list ()
+ (should (equal (cl-loop for x on '(1 2 3 4) collect x)
+ '((1 2 3 4) (2 3 4) (3 4) (4))))
+ (should (equal (cl-loop as (item) on '(1 2 3 4) by #'cddr collect item)
+ '(1 3))))
+
+;;; 6.1.2.1.4 The for-as-equals-then subclause
+(ert-deftest cl-macs-loop-for-as-equals-then ()
+ (should (equal (cl-loop for item = 1 then (+ item 10)
+ repeat 5
+ collect item)
+ '(1 11 21 31 41)))
+ (should (equal (cl-loop for x below 5 for y = nil then x collect (list x y))
+ '((0 nil) (1 1) (2 2) (3 3) (4 4))))
+ (should (equal (cl-loop for x below 5 and y = nil then x collect (list x y))
+ '((0 nil) (1 0) (2 1) (3 2) (4 3))))
+ (should (equal (cl-loop for x below 3 for y = (+ 10 x) nconc (list x y))
+ '(0 10 1 11 2 12)))
+ (should (equal (cl-loop with start = 5
+ for x = start then (cl-incf start)
+ repeat 5
+ collect x)
+ '(5 6 7 8 9))))
+
+;;; 6.1.2.1.5 The for-as-across subclause
+(ert-deftest cl-macs-loop-for-as-across ()
+ (should (string= (cl-loop for x across "aeiou"
+ concat (char-to-string x))
+ "aeiou"))
+ (should (equal (cl-loop for v across (vector 1 2 3) vconcat (vector v (+ 10 v)))
+ [1 11 2 12 3 13])))
+
+;;; 6.1.2.1.6 The for-as-hash subclause
+(ert-deftest cl-macs-loop-for-as-hash ()
+ ;; example in Emacs manual 4.7.3
+ (should (equal (let ((hash (make-hash-table)))
+ (setf (gethash 1 hash) 10)
+ (setf (gethash "test" hash) "string")
+ (setf (gethash 'test hash) 'value)
+ (cl-loop for k being the hash-keys of hash
+ using (hash-values v)
+ collect (list k v)))
+ '((1 10) ("test" "string") (test value)))))
+
+;;; 6.1.2.2 Local Variable Initializations
+(ert-deftest cl-macs-loop-with ()
+ (should (equal (cl-loop with a = 1
+ with b = (+ a 2)
+ with c = (+ b 3)
+ return (list a b c))
+ '(1 3 6)))
+ (should (equal (let ((a 5)
+ (b 10))
+ (cl-loop with a = 1
+ and b = (+ a 2)
+ and c = (+ b 3)
+ return (list a b c)))
+ '(1 7 13)))
+ (should (and (equal (cl-loop for i below 3 with loop-with
+ do (push (* i i) loop-with)
+ finally (cl-return loop-with))
+ '(4 1 0))
+ (not (boundp 'loop-with)))))
+
+;;; 6.1.3 Value Accumulation Clauses
+(ert-deftest cl-macs-loop-accum ()
+ (should (equal (cl-loop for name in '(fred sue alice joe june)
+ for kids in '((bob ken) () () (kris sunshine) ())
+ collect name
+ append kids)
+ '(fred bob ken sue alice joe kris sunshine june))))
+
+(ert-deftest cl-macs-loop-collect ()
+ (should (equal (cl-loop for i in '(bird 3 4 turtle (1 . 4) horse cat)
+ when (symbolp i) collect i)
+ '(bird turtle horse cat)))
+ (should (equal (cl-loop for i from 1 to 10
+ if (cl-oddp i) collect i)
+ '(1 3 5 7 9)))
+ (should (equal (cl-loop for i in '(a b c d e f g) by #'cddr
+ collect i into my-list
+ finally return (nbutlast my-list))
+ '(a c e))))
+
+(ert-deftest cl-macs-loop-append/nconc ()
+ (should (equal (cl-loop for x in '((a) (b) ((c)))
+ append x)
+ '(a b (c))))
+ (should (equal (cl-loop for i upfrom 0
+ as x in '(a b (c))
+ nconc (if (cl-evenp i) (list x) nil))
+ '(a (c)))))
+
+(ert-deftest cl-macs-loop-count ()
+ (should (eql (cl-loop for i in '(a b nil c nil d e)
+ count i)
+ 5)))
+
+(ert-deftest cl-macs-loop-max/min ()
+ (should (eql (cl-loop for i in '(2 1 5 3 4)
+ maximize i)
+ 5))
+ (should (eql (cl-loop for i in '(2 1 5 3 4)
+ minimize i)
+ 1))
+ (should (equal (cl-loop with series = '(4.3 1.2 5.7)
+ for v in series
+ minimize (round v) into min-result
+ maximize (round v) into max-result
+ collect (list min-result max-result))
+ '((4 4) (1 4) (1 6)))))
+
+(ert-deftest cl-macs-loop-sum ()
+ (should (eql (cl-loop for i in '(1 2 3 4 5)
+ sum i)
+ 15))
+ (should (eql (cl-loop with series = '(1.2 4.3 5.7)
+ for v in series
+ sum (* 2.0 v))
+ 22.4)))
+
+;;; 6.1.4 Termination Test Clauses
+(ert-deftest cl-macs-loop-repeat ()
+ (should (equal (cl-loop with n = 4
+ repeat (1+ n)
+ collect n)
+ '(4 4 4 4 4)))
+ (should (equal (cl-loop for i upto 5
+ repeat 3
+ collect i)
+ '(0 1 2))))
+
+(ert-deftest cl-macs-loop-always ()
+ (should (cl-loop for i from 0 to 10
+ always (< i 11)))
+ (should-not (cl-loop for i from 0 to 10
+ always (< i 9)
+ finally (cl-return "you won't see this"))))
+
+(ert-deftest cl-macs-loop-never ()
+ (should (cl-loop for i from 0 to 10
+ never (> i 11)))
+ (should-not (cl-loop never t
+ finally (cl-return "you won't see this"))))
+
+(ert-deftest cl-macs-loop-thereis ()
+ (should (eql (cl-loop for i from 0
+ thereis (when (> i 10) i))
+ 11))
+ (should (string= (cl-loop thereis "Here is my value"
+ finally (cl-return "you won't see this"))
+ "Here is my value"))
+ (should (cl-loop for i to 10
+ thereis (> i 11)
+ finally (cl-return i))))
+
+(ert-deftest cl-macs-loop-anon-collection-conditional ()
+ "Always/never/thereis should error when used with an anonymous
+collection clause."
+ :expected-result :failed
+ (should-error (cl-loop always nil collect t))
+ (should-error (cl-loop never t nconc t))
+ (should-error (cl-loop thereis t append t)))
+
+(ert-deftest cl-macs-loop-while ()
+ (should (equal (let ((stack '(a b c d e f)))
+ (cl-loop while stack
+ for item = (length stack) then (pop stack)
+ collect item))
+ '(6 a b c d e f))))
+
+(ert-deftest cl-macs-loop-until ()
+ (should (equal (cl-loop for i to 100
+ collect 10
+ until (= i 3)
+ collect i)
+ '(10 0 10 1 10 2 10))))
+
+;;; 6.1.5 Unconditional Execution Clauses
+(ert-deftest cl-macs-loop-do ()
+ (should (equal (cl-loop with list
+ for i from 1 to 3
+ do
+ (push 10 list)
+ (push i list)
+ finally (cl-return list))
+ '(3 10 2 10 1 10)))
+ (should (equal (cl-loop with res = 0
+ for i from 1 to 10
+ doing (cl-incf res i)
+ finally (cl-return res))
+ 55))
+ (should (equal (cl-loop for i from 10
+ do (when (= i 15)
+ (cl-return i))
+ finally (cl-return 0))
+ 15)))
+
+;;; 6.1.6 Conditional Execution Clauses
+(ert-deftest cl-macs-loop-when ()
+ (should (equal (cl-loop for i in '(1 2 3 4 5 6)
+ when (and (> i 3) i)
+ collect it)
+ '(4 5 6)))
+ (should (eql (cl-loop for i in '(1 2 3 4 5 6)
+ when (and (> i 3) i)
+ return it)
+ 4))
+
+ (should (equal (cl-loop for elt in '(1 a 2 "a" (3 4) 5 6)
+ when (numberp elt)
+ when (cl-evenp elt) collect elt into even
+ else collect elt into odd
+ else
+ when (symbolp elt) collect elt into syms
+ else collect elt into other
+ finally return (list even odd syms other))
+ '((2 6) (1 5) (a) ("a" (3 4))))))
+
+(ert-deftest cl-macs-loop-if ()
+ (should (equal (cl-loop for i to 5
+ if (cl-evenp i)
+ collect i
+ and when (and (= i 2) 'two)
+ collect it
+ and if (< i 3)
+ collect "low")
+ '(0 2 two "low" 4)))
+ (should (equal (cl-loop for i to 5
+ if (cl-evenp i)
+ collect i
+ and when (and (= i 2) 'two)
+ collect it
+ end
+ and if (< i 3)
+ collect "low")
+ '(0 "low" 2 two "low" 4)))
+ (should (equal (cl-loop with funny-numbers = '(6 13 -1)
+ for x below 10
+ if (cl-evenp x)
+ collect x into evens
+ else
+ collect x into odds
+ and if (memq x funny-numbers) return (cdr it)
+ finally return (vector odds evens))
+ [(1 3 5 7 9) (0 2 4 6 8)])))
+
+(ert-deftest cl-macs-loop-unless ()
+ (should (equal (cl-loop for i to 5
+ unless (= i 3)
+ collect i
+ else
+ collect 'three)
+ '(0 1 2 three 4 5))))
+
+
+;;; 6.1.7.1 Control Transfer Clauses
+(ert-deftest cl-macs-loop-named ()
+ (should (eql (cl-loop named finished
+ for i to 10
+ when (> (* i i) 30)
+ do (cl-return-from finished i))
+ 6)))
+
+;;; 6.1.7.2 Initial and Final Execution
+(ert-deftest cl-macs-loop-initially ()
+ (should (equal (let ((var (list 1 2 3 4 5)))
+ (cl-loop for i in var
+ collect i
+ initially
+ (setf (car var) 10)
+ (setf (cadr var) 20)))
+ '(10 20 3 4 5))))
+
+(ert-deftest cl-macs-loop-finally ()
+ (should (eql (cl-loop for i from 10
+ finally
+ (cl-incf i 10)
+ (cl-return i)
+ while (< i 20))
+ 30)))
+
+;;; Emacs extensions to loop
+(ert-deftest cl-macs-loop-in-ref ()
+ (should (equal (cl-loop with my-list = (list 1 2 3 4 5)
+ for x in-ref my-list
+ do (cl-incf x)
+ finally return my-list)
+ '(2 3 4 5 6))))
+
+(ert-deftest cl-macs-loop-across-ref ()
+ (should (equal (cl-loop with my-vec = ["one" "two" "three"]
+ for x across-ref my-vec
+ do (setf (aref x 0) (upcase (aref x 0)))
+ finally return my-vec)
+ ["One" "Two" "Three"])))
+
+(ert-deftest cl-macs-loop-being-elements ()
+ (should (equal (let ((var "StRiNG"))
+ (cl-loop for x being the elements of var
+ collect (downcase x)))
+ (string-to-list "string"))))
+
+(ert-deftest cl-macs-loop-being-elements-of-ref ()
+ (should (equal (let ((var (list 1 2 3 4 5)))
+ (cl-loop for x being the elements of-ref var
+ do (cl-incf x)
+ finally return var))
+ '(2 3 4 5 6))))
+
+(ert-deftest cl-macs-loop-being-symbols ()
+ (should (eq (cl-loop for sym being the symbols
+ when (eq sym 'cl-loop)
+ return 'cl-loop)
+ 'cl-loop)))
+
+(ert-deftest cl-macs-loop-being-keymap ()
+ (should (equal (let ((map (make-sparse-keymap))
+ (parent (make-sparse-keymap))
+ res)
+ (define-key map "f" #'forward-char)
+ (define-key map "b" #'backward-char)
+ (define-key parent "n" #'next-line)
+ (define-key parent "p" #'previous-line)
+ (set-keymap-parent map parent)
+ (cl-loop for b being the key-bindings of map
+ using (key-codes c)
+ do (push (list c b) res))
+ (cl-loop for s being the key-seqs of map
+ using (key-bindings b)
+ do (push (list (cl-copy-seq s) b) res))
+ res)
+ '(([?n] next-line) ([?p] previous-line)
+ ([?f] forward-char) ([?b] backward-char)
+ (?n next-line) (?p previous-line)
+ (?f forward-char) (?b backward-char)))))
+
+(ert-deftest cl-macs-loop-being-overlays ()
+ (should (equal (let ((ov (make-overlay (point) (point))))
+ (overlay-put ov 'prop "test")
+ (cl-loop for o being the overlays
+ when (eq o ov)
+ return (overlay-get o 'prop)))
+ "test")))
+
+(ert-deftest cl-macs-loop-being-frames ()
+ (should (eq (cl-loop with selected = (selected-frame)
+ for frame being the frames
+ when (eq frame selected)
+ return frame)
+ (selected-frame))))
+
+(ert-deftest cl-macs-loop-being-windows ()
+ (should (eq (cl-loop with selected = (selected-window)
+ for window being the windows
+ when (eq window selected)
+ return window)
+ (selected-window))))
+
+(ert-deftest cl-macs-loop-being-buffers ()
+ (should (eq (cl-loop with current = (current-buffer)
+ for buffer being the buffers
+ when (eq buffer current)
+ return buffer)
+ (current-buffer))))
+
+(ert-deftest cl-macs-loop-vconcat ()
+ (should (equal (cl-loop for x in (list 1 2 3 4 5)
+ vconcat (vector (1+ x)))
+ [2 3 4 5 6])))
+
+;;; cl-macs-tests.el ends here
diff --git a/test/lisp/emacs-lisp/cl-print-tests.el b/test/lisp/emacs-lisp/cl-print-tests.el
index dfbe18d7844..a5dd5abf46b 100644
--- a/test/lisp/emacs-lisp/cl-print-tests.el
+++ b/test/lisp/emacs-lisp/cl-print-tests.el
@@ -15,7 +15,7 @@
;; 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/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@@ -34,7 +34,7 @@
(let ((print-circle t))
(should (equal (cl-prin1-to-string `((x . ,x) (y . ,x)))
"((x . #1=#s(cl-print--test :a 1 :b 2)) (y . #1#))")))
- (should (string-match "\\`#f(compiled-function (x) .*\n\n.*)\\'"
+ (should (string-match "\\`#f(compiled-function (x) \"[^\"]+\" [^\)]*)\\'"
(cl-prin1-to-string (symbol-function #'caar))))))
(ert-deftest cl-print-tests-2 ()
diff --git a/test/lisp/emacs-lisp/cl-seq-tests.el b/test/lisp/emacs-lisp/cl-seq-tests.el
index 61e3d720331..8c0d55663ca 100644
--- a/test/lisp/emacs-lisp/cl-seq-tests.el
+++ b/test/lisp/emacs-lisp/cl-seq-tests.el
@@ -17,7 +17,7 @@
;; 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/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@@ -27,7 +27,7 @@
(require 'cl-seq)
(ert-deftest cl-union-test-00 ()
- "Test for http://debbugs.gnu.org/22729 ."
+ "Test for https://debbugs.gnu.org/22729 ."
(let ((str1 "foo")
(str2 (make-string 3 ?o)))
;; Emacs may make two string literals eql when reading.
@@ -293,7 +293,7 @@ Body are forms defining the test."
(should (= 3 (cl-search (nthcdr 2 list) list2)))))
(ert-deftest cl-seq-test-bug24264 ()
- "Test for http://debbugs.gnu.org/24264 ."
+ "Test for https://debbugs.gnu.org/24264 ."
(let ((list (append (make-list 8000005 1) '(8)))
(list2 (make-list 8000005 2)))
(should (cl-position 8 list))
diff --git a/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el b/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el
new file mode 100644
index 00000000000..ca49dcd213d
--- /dev/null
+++ b/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el
@@ -0,0 +1,134 @@
+;;; edebug-test-code.el --- Sample code for the Edebug test suite
+
+;; Copyright (C) 2017 Free Software Foundation, Inc.
+
+;; Author: Gemini Lasswell
+
+;; This file is part of GNU Emacs.
+
+;; This program 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.
+;;
+;; This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This file contains sample code used by edebug-tests.el.
+;; Before evaluation, it will be preprocessed by
+;; `edebug-tests-setup-code-file' which will remove all tags
+;; between !'s and save their positions for use by the tests.
+
+;;; Code:
+
+(defun edebug-test-code-fac (n)
+ !start!(if !step!(< 0 n)
+ (* n (edebug-test-code-fac (1- n)))!mult!
+ 1))
+
+(defun edebug-test-code-concat (a b flag)
+ !start!(if flag!flag!
+ !then-start!(concat a!then-a! b!then-b!)!then-concat!
+ !else-start!(concat b!else-b! a!else-a!)!else-concat!)!if!)
+
+(defun edebug-test-code-range (num)
+ !start!(let ((index 0)
+ (result nil))
+ (while (< index num)!test!
+ (push index result)!loop!
+ (cl-incf index))!end-loop!
+ (nreverse result)))
+
+(defun edebug-test-code-choices (input)
+ !start!(cond
+ ((eq input 0) "zero")
+ ((eq input 7) 42)
+ (t !edebug!(edebug))))
+
+(defvar edebug-test-code-total nil)
+
+(defun edebug-test-code-multiply (times value)
+ !start!(setq edebug-test-code-total 0)
+ (cl-dotimes (index times)
+ (setq edebug-test-code-total (+ edebug-test-code-total value))!setq!)
+ edebug-test-code-total)
+
+(defun edebug-test-code-format-vector-node (node)
+ !start!(concat "["
+ (apply 'concat (mapcar 'edebug-test-code-format-node node))!apply!
+ "]"))
+
+(defun edebug-test-code-format-list-node (node)
+ !start!(concat "{"
+ (apply 'concat (mapcar 'edebug-test-code-format-node node))!apply!
+ "}"))
+
+(defun edebug-test-code-format-node (node)
+ !start!(cond
+ (!vectorp!(vectorp node!vnode!)!vtest! !vbefore!(edebug-test-code-format-vector-node node))
+ ((listp node) (edebug-test-code-format-list-node node))
+ (t (format "%s" node))))
+
+(defvar edebug-test-code-flavor "strawberry")
+
+(defmacro edebug-test-code-with-flavor (new-flavor &rest body)
+ (declare (debug (form body))
+ (indent 1))
+ `(let ((edebug-test-code-flavor ,new-flavor))
+ ,@body))
+
+(defun edebug-test-code-try-flavors ()
+ (let* (tried)
+ (push edebug-test-code-flavor tried)
+ !macro!(edebug-test-code-with-flavor "chocolate"
+ (push edebug-test-code-flavor tried))
+ tried)!end!)
+
+(unless (featurep 'edebug-tests-nutty)!nutty!
+ !setq!(setq edebug-test-code-flavor (car (edebug-test-code-try-flavors)))!end-setq!)!end-unless!
+
+(cl-defgeneric edebug-test-code-emphasize (x))
+(cl-defmethod edebug-test-code-emphasize ((x integer))
+ !start!(format "The number is not %s or %s, but %s!"
+ (1+ x) (1- x) x))
+(cl-defmethod edebug-test-code-emphasize ((x string))
+ !start!(format "***%s***" x))
+
+(defun edebug-test-code-use-methods ()
+ (list
+ !number!(edebug-test-code-emphasize 100)
+ !string!(edebug-test-code-emphasize "yes")))
+
+(defun edebug-test-code-make-lambda (n)
+ (lambda (x) (+ x!x! n)))
+
+(defun edebug-test-code-use-lambda ()
+ !start!(mapcar (edebug-test-code-make-lambda 10) '(1 2 3)))
+
+(defun edebug-test-code-circular-read-syntax ()
+ '(#1=a . #1#))
+
+(defun edebug-test-code-hash-read-syntax ()
+ !start!(list #("abcd" 1 3 (face italic))
+ #x01ff))
+
+(defun edebug-test-code-empty-string-list ()
+ !start!(list "")!step!)
+
+(defun edebug-test-code-current-buffer ()
+ !start!(with-current-buffer (get-buffer-create "*edebug-test-code-buffer*")
+ !body!(format "current-buffer: %s" (current-buffer))))
+
+(defun edebug-test-code-use-destructuring-bind ()
+ (let ((two 2) (three 3))
+ (cl-destructuring-bind (x . y) (cons two three) (+ x!x! y!y!))))
+
+(provide 'edebug-test-code)
+;;; edebug-test-code.el ends here
diff --git a/test/lisp/emacs-lisp/edebug-tests.el b/test/lisp/emacs-lisp/edebug-tests.el
new file mode 100644
index 00000000000..f6c016cdf80
--- /dev/null
+++ b/test/lisp/emacs-lisp/edebug-tests.el
@@ -0,0 +1,917 @@
+;;; edebug-tests.el --- Edebug test suite -*- lexical-binding:t -*-
+
+;; Copyright (C) 2017 Free Software Foundation, Inc.
+
+;; Author: Gemini Lasswell
+
+;; This file is part of GNU Emacs.
+
+;; This program 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.
+;;
+;; This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; These tests focus on Edebug's user interface for setting
+;; breakpoints, stepping through and tracing code, and evaluating
+;; values used by the code. In addition there are some tests of
+;; Edebug's reader. There are large parts of Edebug's functionality
+;; not covered by these tests, including coverage testing, macro
+;; specifications, and the eval list buffer.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'ert)
+(require 'ert-x)
+(require 'edebug)
+(require 'kmacro)
+
+;; Use `eval-and-compile' because this is used by the macro
+;; `edebug-tests-deftest'.
+(eval-and-compile
+ (defvar edebug-tests-sample-code-file
+ (expand-file-name
+ "edebug-resources/edebug-test-code.el"
+ (file-name-directory (or (bound-and-true-p byte-compile-current-file)
+ load-file-name
+ buffer-file-name)))
+ "Name of file containing code samples for Edebug tests."))
+
+(defvar edebug-tests-temp-file nil
+ "Name of temp file containing sample code stripped of stop point symbols.")
+(defvar edebug-tests-stop-points nil
+ "An alist of alists mapping function symbol -> stop point name -> marker.
+Used by the tests to refer to locations in `edebug-tests-temp-file'.")
+(defvar edebug-tests-messages nil
+ "Messages collected during execution of the current test.")
+
+(defvar edebug-tests-@-result 'no-result
+ "Return value of `edebug-tests-func', or no-result if there isn't one yet.")
+
+(defvar edebug-tests-failure-in-post-command nil
+ "An error trapped in `edebug-tests-post-command'.
+Since `should' failures which happen inside `post-command-hook' will
+be trapped by the command loop, this preserves them until we get
+back to the top level.")
+
+(defvar edebug-tests-keymap
+ (let ((map (make-sparse-keymap)))
+ (define-key map "@" 'edebug-tests-call-instrumented-func)
+ (define-key map "C-u" 'universal-argument)
+ (define-key map "C-p" 'previous-line)
+ (define-key map "C-n" 'next-line)
+ (define-key map "C-b" 'backward-char)
+ (define-key map "C-a" 'move-beginning-of-line)
+ (define-key map "C-e" 'move-end-of-line)
+ (define-key map "C-k" 'kill-line)
+ (define-key map "M-x" 'execute-extended-command)
+ (define-key map "C-M-x" 'eval-defun)
+ (define-key map "C-x X b" 'edebug-set-breakpoint)
+ (define-key map "C-x X w" 'edebug-where)
+ map)
+ "Keys used by the keyboard macros in Edebug's tests.")
+
+;;; Macros for defining tests:
+
+(defmacro edebug-tests-with-default-config (&rest body)
+ "Create a consistent environment for an Edebug test BODY to run in."
+ (declare (debug (body)))
+ `(cl-letf* (
+ ;; These defcustoms are set to their original value.
+ (edebug-setup-hook nil)
+ (edebug-all-defs nil)
+ (edebug-all-forms nil)
+ (edebug-eval-macro-args nil)
+ (edebug-save-windows t)
+ (edebug-save-displayed-buffer-points nil)
+ (edebug-initial-mode 'step)
+ (edebug-trace nil)
+ (edebug-test-coverage nil)
+ (edebug-print-length 50)
+ (edebug-print-level 50)
+ (edebug-print-circle t)
+ (edebug-unwrap-results nil)
+ (edebug-on-error t)
+ (edebug-on-quit t)
+ (edebug-global-break-condition nil)
+ (edebug-sit-for-seconds 1)
+
+ ;; sit-on interferes with keyboard macros.
+ (edebug-sit-on-break nil)
+ (edebug-continue-kbd-macro t))
+ ,@body))
+
+(defmacro edebug-tests-with-normal-env (&rest body)
+ "Set up the environment for an Edebug test BODY, run it, and clean up."
+ (declare (debug (body)))
+ `(edebug-tests-with-default-config
+ (let ((edebug-tests-failure-in-post-command nil)
+ (edebug-tests-temp-file (make-temp-file "edebug-tests-" nil ".el")))
+ (edebug-tests-setup-code-file edebug-tests-temp-file)
+ (ert-with-message-capture
+ edebug-tests-messages
+ (unwind-protect
+ (with-current-buffer (find-file edebug-tests-temp-file)
+ (read-only-mode)
+ (setq lexical-binding t)
+ (eval-buffer)
+ ,@body
+ (when edebug-tests-failure-in-post-command
+ (signal (car edebug-tests-failure-in-post-command)
+ (cdr edebug-tests-failure-in-post-command))))
+ (unload-feature 'edebug-test-code)
+ (with-current-buffer (find-file-noselect edebug-tests-temp-file)
+ (set-buffer-modified-p nil))
+ (ignore-errors (kill-buffer (find-file-noselect
+ edebug-tests-temp-file)))
+ (ignore-errors (delete-file edebug-tests-temp-file)))))))
+
+;; The following macro and its support functions implement an extension
+;; to keyboard macros to allow interleaving of keyboard macro
+;; events with evaluation of Lisp expressions. The Lisp expressions
+;; are called from within `post-command-hook', which is a strategy
+;; inspired by `kmacro-step-edit-macro'.
+
+;; Some of the details necessary to get this to work with Edebug are:
+;; -- ERT's `should' macros raise errors, and errors within
+;; `post-command-hook' are trapped by the command loop. The
+;; workaround is to trap and save an error inside the hook
+;; function and reraise it after the macro exits.
+;; -- `edebug-continue-kbd-macro' must be non-nil.
+;; -- Edebug calls `exit-recursive-edit' which turns off keyboard
+;; macro execution. Solved with an advice wrapper for
+;; `exit-recursive-edit' which preserves the keyboard macro state.
+
+(defmacro edebug-tests-run-kbd-macro (&rest macro)
+ "Run a MACRO consisting of both keystrokes and test assertions.
+MACRO should be a list, where each item is either a keyboard
+macro segment (in string or vector form) or a Lisp expression.
+Convert the macro segments into keyboard macros and execute them.
+After the execution of the last event of each segment, evaluate
+the Lisp expressions following the segment."
+ (let ((prepared (edebug-tests-prepare-macro macro)))
+ `(edebug-tests-run-macro ,@prepared)))
+
+;; Make support functions for edebug-tests-run-kbd-macro
+;; available at compile time.
+(eval-and-compile
+ (defun edebug-tests-prepare-macro (macro)
+ "Prepare a MACRO for execution.
+MACRO should be a list containing strings, vectors, and Lisp
+forms. Convert the strings and vectors to keyboard macros in
+vector representation and concatenate them to make a single
+keyboard macro. Also build a list of the same length as the
+number of events in the keyboard macro. Each item in that list
+will contain the code to evaluate after the corresponding event
+in the keyboard macro, either nil or a thunk built from the forms
+in the original list. Return a list containing the keyboard
+macro as the first item, followed by the list of thunks and/or
+nils."
+ (cl-loop
+ for item = (pop macro)
+ while item
+ for segment = (read-kbd-macro item)
+ for thunk = (edebug-tests-wrap-thunk
+ (cl-loop
+ for form in macro
+ until (or (stringp form) (vectorp form))
+ collect form
+ do (pop macro)))
+ vconcat segment into segments
+ append (edebug-tests-pad-thunk-list (length segment) thunk)
+ into thunk-list
+
+ finally return (cons segments thunk-list)))
+
+ (defun edebug-tests-wrap-thunk (body)
+ "If BODY is non-nil, wrap it with a lambda form."
+ (when body
+ `(lambda () ,@body)))
+
+ (defun edebug-tests-pad-thunk-list (length thunk)
+ "Return a list with LENGTH elements with THUNK in the last position.
+All other elements will be nil."
+ (let ((thunk-seg (make-list length nil)))
+ (setf (car (last thunk-seg)) thunk)
+ thunk-seg)))
+
+;;; Support for test execution:
+
+(defvar edebug-tests-thunks nil
+ "List containing thunks to run after each command in a keyboard macro.")
+(defvar edebug-tests-kbd-macro-index nil
+ "Index into `edebug-tests-run-unpacked-kbd-macro's current keyboard macro.")
+
+(defun edebug-tests-run-macro (kbdmac &rest thunks)
+ "Run a keyboard macro and execute a thunk after each command in it.
+KBDMAC should be a vector of events and THUNKS a list of the
+same length containing thunks and/or nils. Run the macro, and
+after the execution of every command in the macro (which may not
+be the same as every keystroke) execute the thunk at the same
+index."
+ (let* ((edebug-tests-thunks thunks)
+ (edebug-tests-kbd-macro-index 0)
+ saved-local-map)
+ (with-current-buffer (find-file-noselect edebug-tests-temp-file)
+ (setq saved-local-map overriding-local-map)
+ (setq overriding-local-map edebug-tests-keymap)
+ (add-hook 'post-command-hook 'edebug-tests-post-command))
+ (advice-add 'exit-recursive-edit
+ :around 'edebug-tests-preserve-keyboard-macro-state)
+ (unwind-protect
+ (kmacro-call-macro nil nil nil kbdmac)
+ (advice-remove 'exit-recursive-edit
+ 'edebug-tests-preserve-keyboard-macro-state)
+ (with-current-buffer (find-file-noselect edebug-tests-temp-file)
+ (setq overriding-local-map saved-local-map)
+ (remove-hook 'post-command-hook 'edebug-tests-post-command)))))
+
+(defun edebug-tests-preserve-keyboard-macro-state (orig &rest args)
+ "Call ORIG with ARGS preserving the value of `executing-kbd-macro'.
+Useful to prevent `exit-recursive-edit' from stopping the current
+keyboard macro."
+ (let ((executing-kbd-macro executing-kbd-macro))
+ (apply orig args)))
+
+(defun edebug-tests-post-command ()
+ "Run the thunk from `edebug-tests-thunks' matching the keyboard macro index."
+ (when (and edebug-tests-kbd-macro-index
+ (> executing-kbd-macro-index edebug-tests-kbd-macro-index))
+ (let ((thunk (nth (1- executing-kbd-macro-index) edebug-tests-thunks)))
+ (when thunk
+ (condition-case err
+ (funcall thunk)
+ (error
+ (setq edebug-tests-failure-in-post-command err)
+ (signal (car err) (cdr err)))))
+ (setq edebug-tests-kbd-macro-index executing-kbd-macro-index))))
+
+(defvar edebug-tests-func nil
+ "Instrumented function used to launch Edebug.")
+(defvar edebug-tests-args nil
+ "Arguments for `edebug-tests-func'.")
+
+(defun edebug-tests-setup-@ (def-name args edebug-it)
+ "Set up the binding for @ in `edebug-tests-keymap'.
+Find a definition for DEF-NAME in the current buffer and evaluate it.
+Set globals so that `edebug-tests-call-instrumented-func' which
+is bound to @ for edebug-tests' keyboard macros will call it with
+ARGS. EDEBUG-IT is passed through to `eval-defun'."
+ (edebug-tests-locate-def def-name)
+ (eval-defun edebug-it)
+ (let* ((full-name (concat "edebug-test-code-" def-name))
+ (sym (intern-soft full-name)))
+ (should (and sym (fboundp sym)))
+ (setq edebug-tests-func sym
+ edebug-tests-args args)
+ (setq edebug-tests-@-result 'no-result)))
+
+(defun edebug-tests-call-instrumented-func ()
+ "Call `edebug-tests-func' with `edebug-tests-args' and save the results."
+ (interactive)
+ (let ((result (apply edebug-tests-func edebug-tests-args)))
+ (should (eq edebug-tests-@-result 'no-result))
+ (setq edebug-tests-@-result result)))
+
+(defun edebug-tests-should-be-at (def-name point-name)
+ "Require that point be at the location in DEF-NAME named POINT-NAME.
+DEF-NAME should be the suffix of a definition in the code samples
+file (the part after \"edebug-tests\")."
+ (let ((stop-point (edebug-tests-get-stop-point def-name point-name)))
+ (should (eq (current-buffer) (find-file-noselect edebug-tests-temp-file)))
+ (should (eql (point) stop-point))))
+
+(defun edebug-tests-get-stop-point (def-name point-name)
+ "Return the position in DEF-NAME of the stop point named POINT-NAME.
+DEF-NAME should be the suffix of a definition in the code samples
+file (the part after \"edebug-tests\")."
+ (let* ((full-name (concat "edebug-test-code-" def-name))(stop-point
+ (cdr (assoc point-name
+ (cdr (assoc full-name edebug-tests-stop-points))))))
+ (unless stop-point
+ (ert-fail (format "%s not found in %s" point-name full-name)))
+ stop-point))
+
+(defun edebug-tests-should-match-result-in-messages (value)
+ "Require that VALUE (a string) match an Edebug result in *Messages*.
+Then clear edebug-tests' saved messages."
+ (should (string-match-p (concat "Result: " (regexp-quote value) "$")
+ edebug-tests-messages))
+ (setq edebug-tests-messages ""))
+
+(defun edebug-tests-locate-def (def-name)
+ "Search for a definition of DEF-NAME from the start of the current buffer.
+Place point at the end of DEF-NAME in the buffer."
+ (goto-char (point-min))
+ (re-search-forward (concat "def\\S-+ edebug-test-code-" def-name)))
+
+(defconst edebug-tests-start-of-next-def-regexp "^(\\S-*def\\S-+ \\(\\S-+\\)"
+ "Regexp used to match the start of a definition.")
+(defconst edebug-tests-stop-point-regexp "!\\(\\S-+?\\)!"
+ "Regexp used to match a stop point annotation in the sample code.")
+
+;;; Set up buffer containing code samples:
+
+(defmacro edebug-tests-deduplicate (name names-and-numbers)
+ "Return a unique variation on NAME.
+NAME should be a string and NAMES-AND-NUMBERS an alist which can
+be used by this macro to retain state. If NAME for example is
+\"symbol\" then the first and subsequent uses of this macro will
+evaluate to \"symbol\", \"symbol-1\", \"symbol-2\", etc."
+ (let ((g-name (gensym))
+ (g-duplicate (gensym)))
+ `(let* ((,g-name ,name)
+ (,g-duplicate (assoc ,g-name ,names-and-numbers)))
+ (if (null ,g-duplicate)
+ (progn
+ (push (cons ,g-name 0) ,names-and-numbers)
+ ,g-name)
+ (cl-incf (cdr ,g-duplicate))
+ (format "%s-%s" ,g-name (cdr ,g-duplicate))))))
+
+(defun edebug-tests-setup-code-file (tmpfile)
+ "Extract stop points and loadable code from the sample code file.
+Write the loadable code to a buffer for TMPFILE, and set
+`edebug-tests-stop-points' to a map from defined symbols to stop
+point names to positions in the file."
+ (with-current-buffer (find-file-noselect edebug-tests-sample-code-file)
+ (let ((marked-up-code (buffer-string)))
+ (with-temp-file tmpfile
+ (insert marked-up-code))))
+
+ (with-current-buffer (find-file-noselect tmpfile)
+ (let ((stop-points
+ ;; Delete all the !name! annotations from the code, but remember
+ ;; their names and where they were in an alist.
+ (cl-loop
+ initially (goto-char (point-min))
+ while (re-search-forward edebug-tests-stop-point-regexp nil t)
+ for name = (match-string-no-properties 1)
+ do (replace-match "")
+ collect (cons name (point))))
+ names-and-numbers)
+
+ ;; Now build an alist mapping definition names to annotation
+ ;; names and positions.
+ ;; If duplicate symbols exist in the file, enter them in the
+ ;; alist as symbol, symbol-1, symbol-2 etc.
+ (setq edebug-tests-stop-points
+ (cl-loop
+ initially (goto-char (point-min))
+ while (re-search-forward edebug-tests-start-of-next-def-regexp
+ nil t)
+ for name =
+ (edebug-tests-deduplicate (match-string-no-properties 1)
+ names-and-numbers)
+ for end-of-def =
+ (save-match-data
+ (save-excursion
+ (re-search-forward edebug-tests-start-of-next-def-regexp
+ nil 0)
+ (point)))
+ collect (cons name
+ (cl-loop
+ while (and stop-points
+ (< (cdar stop-points) end-of-def))
+ collect (pop stop-points))))))))
+
+;;; Tests
+
+(ert-deftest edebug-tests-check-keymap ()
+ "Verify that `edebug-mode-map' is compatible with these tests.
+If this test fails, one of two things is true. Either your
+customizations modify `edebug-mode-map', in which case starting
+Emacs with the -Q flag should fix the problem, or
+`edebug-mode-map' has changed in edebug.el, in which case this
+test and possibly others should be updated."
+ ;; The reason verify-keybinding is a macro instead of a function is
+ ;; that in the event of a failure, it makes the keybinding that
+ ;; failed show up in ERT's output.
+ (cl-macrolet ((verify-keybinding (key binding)
+ `(should (eq (lookup-key edebug-mode-map ,key)
+ ,binding))))
+ (verify-keybinding " " 'edebug-step-mode)
+ (verify-keybinding "n" 'edebug-next-mode)
+ (verify-keybinding "g" 'edebug-go-mode)
+ (verify-keybinding "G" 'edebug-Go-nonstop-mode)
+ (verify-keybinding "t" 'edebug-trace-mode)
+ (verify-keybinding "T" 'edebug-Trace-fast-mode)
+ (verify-keybinding "c" 'edebug-continue-mode)
+ (verify-keybinding "C" 'edebug-Continue-fast-mode)
+ (verify-keybinding "f" 'edebug-forward-sexp)
+ (verify-keybinding "h" 'edebug-goto-here)
+ (verify-keybinding "I" 'edebug-instrument-callee)
+ (verify-keybinding "i" 'edebug-step-in)
+ (verify-keybinding "o" 'edebug-step-out)
+ (verify-keybinding "q" 'top-level)
+ (verify-keybinding "Q" 'edebug-top-level-nonstop)
+ (verify-keybinding "a" 'abort-recursive-edit)
+ (verify-keybinding "S" 'edebug-stop)
+ (verify-keybinding "b" 'edebug-set-breakpoint)
+ (verify-keybinding "u" 'edebug-unset-breakpoint)
+ (verify-keybinding "B" 'edebug-next-breakpoint)
+ (verify-keybinding "x" 'edebug-set-conditional-breakpoint)
+ (verify-keybinding "X" 'edebug-set-global-break-condition)
+ (verify-keybinding "r" 'edebug-previous-result)
+ (verify-keybinding "e" 'edebug-eval-expression)
+ (verify-keybinding "\C-x\C-e" 'edebug-eval-last-sexp)
+ (verify-keybinding "E" 'edebug-visit-eval-list)
+ (verify-keybinding "w" 'edebug-where)
+ (verify-keybinding "v" 'edebug-view-outside) ;; maybe obsolete??
+ (verify-keybinding "p" 'edebug-bounce-point)
+ (verify-keybinding "P" 'edebug-view-outside) ;; same as v
+ (verify-keybinding "W" 'edebug-toggle-save-windows)
+ (verify-keybinding "?" 'edebug-help)
+ (verify-keybinding "d" 'edebug-backtrace)
+ (verify-keybinding "-" 'negative-argument)
+ (verify-keybinding "=" 'edebug-temp-display-freq-count)))
+
+(ert-deftest edebug-tests-stop-point-at-start-of-first-instrumented-function ()
+ "Edebug stops at the beginning of an instrumented function."
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "fac" '(0) t)
+ (edebug-tests-run-kbd-macro
+ "@" (edebug-tests-should-be-at "fac" "start")
+ "SPC" (edebug-tests-should-be-at "fac" "step")
+ "g" (should (equal edebug-tests-@-result 1)))))
+
+(ert-deftest edebug-tests-step-showing-evaluation-results ()
+ "Edebug prints expression evaluation results to the echo area."
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "concat" '("x" "y" nil) t)
+ (edebug-tests-run-kbd-macro
+ "@" (edebug-tests-should-be-at "concat" "start")
+ "SPC" (edebug-tests-should-be-at "concat" "flag")
+ (edebug-tests-should-match-result-in-messages "nil")
+ "SPC" (edebug-tests-should-be-at "concat" "else-start")
+ "SPC" (edebug-tests-should-be-at "concat" "else-b")
+ (edebug-tests-should-match-result-in-messages "\"y\"")
+ "SPC" (edebug-tests-should-be-at "concat" "else-a")
+ (edebug-tests-should-match-result-in-messages "\"x\"")
+ "SPC" (edebug-tests-should-be-at "concat" "else-concat")
+ (edebug-tests-should-match-result-in-messages "\"yx\"")
+ "SPC" (edebug-tests-should-be-at "concat" "if")
+ (edebug-tests-should-match-result-in-messages "\"yx\"")
+ "SPC" (should (equal edebug-tests-@-result "yx")))))
+
+(ert-deftest edebug-tests-set-breakpoint-at-point ()
+ "Edebug can set a breakpoint at point."
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "concat" '("x" "y" t) t)
+ (edebug-tests-run-kbd-macro
+ "@" (edebug-tests-should-be-at "concat" "start")
+ "C-n C-e b C-n" ; Move down, set a breakpoint and move away.
+ "g" (edebug-tests-should-be-at "concat" "then-concat")
+ (edebug-tests-should-match-result-in-messages "\"xy\"")
+ "g" (should (equal edebug-tests-@-result "xy")))))
+
+(ert-deftest edebug-tests-set-temporary-breakpoint-at-point ()
+ "Edebug can set a temporary breakpoint at point."
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "range" '(3) t)
+ (edebug-tests-run-kbd-macro
+ "@" (edebug-tests-should-be-at "range" "start")
+ "C-n C-n C-n C-e" ; Move down to the end of a sexp in the loop.
+ "C-u b" ; Set a temporary breakpoint.
+ "C-n" ; Move away.
+ "g" (edebug-tests-should-be-at "range" "loop")
+ (edebug-tests-should-match-result-in-messages "(0)")
+ "g" (should (equal edebug-tests-@-result '(0 1 2))))))
+
+(ert-deftest edebug-tests-clear-breakpoint ()
+ "Edebug can clear a breakpoint."
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "range" '(3) t)
+ (edebug-tests-run-kbd-macro
+ "@"
+ (message "after @")
+ (edebug-tests-should-be-at "range" "start")
+ "C-n C-n C-n C-e b C-n" ; Move down, set a breakpoint and move away.
+ "g" (edebug-tests-should-be-at "range" "loop")
+ (edebug-tests-should-match-result-in-messages "(0)")
+ "g" (edebug-tests-should-be-at "range" "loop")
+ (edebug-tests-should-match-result-in-messages "(1 0)")
+ "u" ; Unset the breakpoint.
+ "g" (should (equal edebug-tests-@-result '(0 1 2))))))
+
+(ert-deftest edebug-tests-move-point-to-next-breakpoint ()
+ "Edebug can move point to the next breakpoint."
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "concat" '("a" "b" nil) t)
+ (edebug-tests-run-kbd-macro
+ "@" (edebug-tests-should-be-at "concat" "start")
+ "C-n C-e b" ; Move down, set a breakpoint.
+ "C-n b" ; Set another breakpoint on the next line.
+ "C-p C-p C-p" ; Move back up.
+ "B" (edebug-tests-should-be-at "concat" "then-concat")
+ "B" (edebug-tests-should-be-at "concat" "else-concat")
+ "G" (should (equal edebug-tests-@-result "ba")))))
+
+(ert-deftest edebug-tests-move-point-back-to-stop-point ()
+ "Edebug can move point back to a stop point."
+ (edebug-tests-with-normal-env
+ (let ((test-buffer (get-buffer-create "edebug-tests-temp")))
+ (edebug-tests-setup-@ "fac" '(4) t)
+ (edebug-tests-run-kbd-macro
+ "@" (edebug-tests-should-be-at "fac" "start")
+ "C-n w" (edebug-tests-should-be-at "fac" "start")
+ (pop-to-buffer test-buffer)
+ "C-x X w" (edebug-tests-should-be-at "fac" "start")
+ "g" (should (equal edebug-tests-@-result 24)))
+ (ignore-errors (kill-buffer test-buffer)))))
+
+(ert-deftest edebug-tests-jump-to-point ()
+ "Edebug can stop at a temporary breakpoint at point."
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "range" '(3) t)
+ (edebug-tests-run-kbd-macro
+ "@" (edebug-tests-should-be-at "range" "start")
+ "C-n C-n C-n C-e" ; Move down to the end of a sexp in the loop.
+ "h" (edebug-tests-should-be-at "range" "loop")
+ (edebug-tests-should-match-result-in-messages "(0)")
+ "g" (should (equal edebug-tests-@-result '(0 1 2))))))
+
+(ert-deftest edebug-tests-jump-forward-one-sexp ()
+ "Edebug can run the program for one expression."
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "range" '(3) t)
+ (edebug-tests-run-kbd-macro
+ "@" (edebug-tests-should-be-at "range" "start")
+ "SPC SPC f" (edebug-tests-should-be-at "range" "test")
+ "g" (should (equal edebug-tests-@-result '(0 1 2))))))
+
+(ert-deftest edebug-tests-run-out-of-containing-sexp ()
+ "Edebug can run the program until the end of the containing sexp."
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "range" '(3) t)
+ (edebug-tests-run-kbd-macro
+ "@" (edebug-tests-should-be-at "range" "start")
+ "SPC SPC f" (edebug-tests-should-be-at "range" "test")
+ "o" (edebug-tests-should-be-at "range" "end-loop")
+ (edebug-tests-should-match-result-in-messages "nil")
+ "g" (should (equal edebug-tests-@-result '(0 1 2))))))
+
+(ert-deftest edebug-tests-observe-breakpoint-in-source ()
+ "Edebug will stop at a breakpoint embedded in source code."
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "choices" '(8) t)
+ (edebug-tests-run-kbd-macro
+ "@" (edebug-tests-should-be-at "choices" "start")
+ "g" (edebug-tests-should-be-at "choices" "edebug")
+ "g" (should (equal edebug-tests-@-result nil)))))
+
+(ert-deftest edebug-tests-set-conditional-breakpoint ()
+ "Edebug can set and observe a conditional breakpoint."
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "fac" '(5) t)
+ (edebug-tests-run-kbd-macro
+ "@" (edebug-tests-should-be-at "fac" "start")
+ ;; Set conditional breakpoint at end of next line.
+ "C-n C-e x (eql SPC n SPC 3) RET"
+ "g" (edebug-tests-should-be-at "fac" "mult")
+ (edebug-tests-should-match-result-in-messages "6 (#o6, #x6, ?\\C-f)")
+ "g" (should (equal edebug-tests-@-result 120)))))
+
+(ert-deftest edebug-tests-error-trying-to-set-breakpoint-in-uninstrumented-code
+ ()
+ "Edebug refuses to set a breakpoint in uninstrumented code."
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "fac" '(5) t)
+ (let* ((debug-on-error nil)
+ (edebug-on-error nil)
+ error-message
+ (command-error-function (lambda (&rest args)
+ (setq error-message (cadar args)))))
+ (edebug-tests-run-kbd-macro
+ "@" (edebug-tests-should-be-at "fac" "start")
+ "C-u 10 C-n" ; Move down and out of instrumented function.
+ "b" (should (string-match-p "Not inside instrumented form"
+ error-message))
+ ;; The error stopped the keyboard macro. Start it again.
+ (should-not executing-kbd-macro)
+ (setq executing-kbd-macro t)
+ "g"))))
+
+(ert-deftest edebug-tests-set-and-break-on-global-condition ()
+ "Edebug can break when a global condition becomes true."
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "multiply" '(5 3) t)
+ (edebug-tests-run-kbd-macro
+ "@" (edebug-tests-should-be-at "multiply" "start")
+ "X (> SPC edebug-test-code-total SPC 10) RET"
+ (should edebug-global-break-condition)
+ "g" (edebug-tests-should-be-at "multiply" "setq")
+ (should (eql (symbol-value 'edebug-test-code-total) 12))
+ "X C-a C-k nil RET" ; Remove suggestion before entering nil.
+ "g" (should (equal edebug-tests-@-result 15)))))
+
+(ert-deftest edebug-tests-trace-showing-results-at-stop-points ()
+ "Edebug can trace execution, showing results at stop points."
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "concat" '("x" "y" nil) t)
+ (edebug-tests-run-kbd-macro
+ "@" (edebug-tests-should-be-at "concat" "start")
+ "T" (should (string-match-p
+ (concat "Result: nil\n.*?"
+ "Result: \"y\"\n.*?"
+ "Result: \"x\"\n.*?"
+ "Result: \"yx\"\n.*?"
+ "Result: \"yx\"\n")
+ edebug-tests-messages))
+ (should (equal edebug-tests-@-result "yx")))))
+
+(ert-deftest edebug-tests-trace-showing-results-at-breakpoints ()
+ "Edebug can trace execution, showing results at breakpoints."
+ (edebug-tests-with-normal-env
+ (edebug-tests-locate-def "format-vector-node")
+ (edebug-tests-run-kbd-macro "C-u C-M-x C-n C-n C-e C-x X b")
+ (edebug-tests-locate-def "format-list-node")
+ (edebug-tests-run-kbd-macro "C-u C-M-x C-n C-n C-e C-x X b")
+ (edebug-tests-setup-@ "format-node" '(([a b] [c d])) t)
+ (edebug-tests-run-kbd-macro
+ "@" (edebug-tests-should-be-at "format-node" "start")
+ "C" (should (string-match-p
+ (concat "Result: \"ab\"\n.*?"
+ "Result: \"cd\"\n.*?"
+ "Result: \"\\[ab]\\[cd]\"\n")
+ edebug-tests-messages))
+ (should (equal edebug-tests-@-result "{[ab][cd]}")))))
+
+(ert-deftest edebug-tests-trace-function-call-and-return ()
+ "Edebug can create a trace of function calls and returns."
+ (edebug-tests-with-normal-env
+ (edebug-tests-locate-def "format-vector-node")
+ (eval-defun t)
+ (edebug-tests-locate-def "format-list-node")
+ (eval-defun t)
+ (edebug-tests-setup-@ "format-node" '((a [b])) t)
+ (let ((edebug-trace t)
+ (trace-start (with-current-buffer
+ (get-buffer-create edebug-trace-buffer) (point-max))))
+ (edebug-tests-run-kbd-macro
+ "@" (edebug-tests-should-be-at "format-node" "start")
+ "g" (should (equal edebug-tests-@-result "{a[b]}")))
+ (with-current-buffer edebug-trace-buffer
+ (should (string=
+ "{ edebug-test-code-format-node args: ((a [b]))
+:{ edebug-test-code-format-list-node args: ((a [b]))
+::{ edebug-test-code-format-node args: (a)
+::} edebug-test-code-format-node result: a
+::{ edebug-test-code-format-node args: ([b])
+:::{ edebug-test-code-format-vector-node args: ([b])
+::::{ edebug-test-code-format-node args: (b)
+::::} edebug-test-code-format-node result: b
+:::} edebug-test-code-format-vector-node result: [b]
+::} edebug-test-code-format-node result: [b]
+:} edebug-test-code-format-list-node result: {a[b]}
+} edebug-test-code-format-node result: {a[b]}
+" (buffer-substring trace-start (point-max))))))))
+
+(ert-deftest edebug-tests-evaluate-expressions ()
+ "Edebug can evaluate an expression in the context outside of itself."
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "range" '(2) t)
+ (edebug-tests-run-kbd-macro
+ "@" (edebug-tests-should-be-at "range" "start")
+ "SPC SPC f" (edebug-tests-should-be-at "range" "test")
+ (edebug-tests-should-match-result-in-messages "t")
+ "e (- SPC num SPC index) RET"
+ ;; Edebug just prints the result without "Result:"
+ (should (string-match-p
+ (regexp-quote "2 (#o2, #x2, ?\\C-b)")
+ edebug-tests-messages))
+ "g" (should (equal edebug-tests-@-result '(0 1))))
+
+ ;; Do it again with lexical-binding turned off.
+ (setq lexical-binding nil)
+ (eval-buffer)
+ (should-not lexical-binding)
+ (edebug-tests-setup-@ "range" '(2) t)
+ (edebug-tests-run-kbd-macro
+ "@" (edebug-tests-should-be-at "range" "start")
+ "SPC SPC f" (edebug-tests-should-be-at "range" "test")
+ (edebug-tests-should-match-result-in-messages "t")
+ "e (- SPC num SPC index) RET"
+ ;; Edebug just prints the result without "Result:"
+ (should (string-match-p
+ (regexp-quote "2 (#o2, #x2, ?\\C-b)")
+ edebug-tests-messages))
+ "g" (should (equal edebug-tests-@-result '(0 1))))))
+
+(ert-deftest edebug-tests-step-into-function ()
+ "Edebug can step into a function."
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "format-node" '([b]) t)
+ (edebug-tests-run-kbd-macro
+ "@" (edebug-tests-should-be-at "format-node" "start")
+ "SPC SPC SPC SPC"
+ (edebug-tests-should-be-at "format-node" "vbefore")
+ "i" (edebug-tests-should-be-at "format-vector-node" "start")
+ "g" (should (equal edebug-tests-@-result "[b]")))))
+
+(ert-deftest edebug-tests-error-stepping-into-subr ()
+ "Edebug refuses to step into a C function."
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "format-node" '([b]) t)
+ (let* ((debug-on-error nil)
+ (edebug-on-error nil)
+ error-message
+ (command-error-function (lambda (&rest args)
+ (setq error-message (cl-cadar args)))))
+ (edebug-tests-run-kbd-macro
+ "@" (edebug-tests-should-be-at "format-node" "start")
+ "SPC" (edebug-tests-should-be-at "format-node" "vectorp")
+ "i" (should (string-match-p "vectorp is a built-in function"
+ error-message))
+ ;; The error stopped the keyboard macro. Start it again.
+ (should-not executing-kbd-macro)
+ (setq executing-kbd-macro t)
+ "g" (should (equal edebug-tests-@-result "[b]"))))))
+
+(ert-deftest edebug-tests-step-into-macro-error ()
+ "Edebug gives an error on trying to step into a macro (Bug#26847)."
+ :expected-result :failed
+ (ert-fail "Forcing failure because letting this test run aborts the others.")
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "try-flavors" nil t)
+ (let* ((debug-on-error nil)
+ (edebug-on-error nil)
+ (error-message "")
+ (command-error-function (lambda (&rest args)
+ (setq error-message (cl-cadar args)))))
+ (edebug-tests-run-kbd-macro
+ "@ SPC SPC SPC SPC SPC"
+ (edebug-tests-should-be-at "try-flavors" "macro")
+ "i" (should (string-match-p "edebug-test-code-try-flavors is a macro"
+ error-message))
+ ;; The error stopped the keyboard macro. Start it again.
+ (should-not executing-kbd-macro)
+ (setq executing-kbd-macro t)
+ "g" (should (equal edebug-tests-@-result
+ '("chocolate" "strawberry")))))))
+
+(ert-deftest edebug-tests-step-into-generic-method ()
+ "Edebug can step into a generic method (Bug#22294)."
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "use-methods" nil t)
+ (edebug-tests-run-kbd-macro
+ "@ SPC" (edebug-tests-should-be-at "use-methods" "number")
+ "i" (edebug-tests-should-be-at "emphasize-1" "start")
+ "gg" (should (equal edebug-tests-@-result
+ '("The number is not 101 or 99, but 100!"
+ "***yes***"))))))
+
+(ert-deftest edebug-tests-break-in-lambda-out-of-defining-context ()
+ "Edebug observes a breakpoint in a lambda executed out of defining context."
+ (edebug-tests-with-normal-env
+ (edebug-tests-locate-def "make-lambda")
+ (eval-defun t)
+ (goto-char (edebug-tests-get-stop-point "make-lambda" "x"))
+ (edebug-set-breakpoint t)
+ (edebug-tests-setup-@ "use-lambda" nil t)
+ (edebug-tests-run-kbd-macro
+ "@g" (edebug-tests-should-be-at "make-lambda" "x")
+ (edebug-tests-should-match-result-in-messages "1 (#o1, #x1, ?\\C-a)")
+ "g" (should (equal edebug-tests-@-result '(11 12 13))))))
+
+(ert-deftest edebug-tests-respects-initial-mode ()
+ "Edebug can stop first at breakpoint instead of first instrumented function."
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "fac" '(4) t)
+ (goto-char (edebug-tests-get-stop-point "fac" "mult"))
+ (edebug-set-breakpoint t)
+ (setq edebug-initial-mode 'go)
+ (edebug-tests-run-kbd-macro
+ "@" (edebug-tests-should-be-at "fac" "mult")
+ (edebug-tests-should-match-result-in-messages "1 (#o1, #x1, ?\\C-a)")
+ "G" (should (equal edebug-tests-@-result 24)))))
+
+(ert-deftest edebug-tests-step-through-non-definition ()
+ "Edebug can step through a non-defining form."
+ (edebug-tests-with-normal-env
+ (goto-char (edebug-tests-get-stop-point "try-flavors" "end-unless"))
+ (edebug-tests-run-kbd-macro
+ "C-u C-M-x"
+ "SPC SPC" (edebug-tests-should-be-at "try-flavors" "nutty")
+ (edebug-tests-should-match-result-in-messages "nil")
+ "SPC" (edebug-tests-should-be-at "try-flavors" "setq")
+ "f" (edebug-tests-should-be-at "try-flavors" "end-setq")
+ (edebug-tests-should-match-result-in-messages "\"chocolate\"")
+ "g")))
+
+(ert-deftest edebug-tests-conditional-breakpoints-can-use-lexical-variables ()
+ "Edebug can set a conditional breakpoint using a lexical variable. Bug#12685"
+ (edebug-tests-with-normal-env
+ (should lexical-binding)
+ (edebug-tests-setup-@ "fac" '(5) t)
+ (edebug-tests-run-kbd-macro
+ "@" (edebug-tests-should-be-at "fac" "start")
+ ;; Set conditional breakpoint at end of next line.
+ "C-n C-e x (eql SPC n SPC 3) RET"
+ "g" (edebug-tests-should-be-at "fac" "mult")
+ (edebug-tests-should-match-result-in-messages
+ "6 (#o6, #x6, ?\\C-f)"))))
+
+(ert-deftest edebug-tests-writable-buffer-state-is-preserved ()
+ "On Edebug exit writable buffers are still writable (Bug#14144)."
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "choices" '(0) t)
+ (read-only-mode -1)
+ (edebug-tests-run-kbd-macro
+ "@g" (should (equal edebug-tests-@-result "zero")))
+ (barf-if-buffer-read-only)))
+
+(ert-deftest edebug-tests-list-containing-empty-string-result-printing ()
+ "Edebug correctly prints a list containing only an empty string (Bug#17934)."
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "empty-string-list" nil t)
+ (edebug-tests-run-kbd-macro
+ "@ SPC" (edebug-tests-should-be-at
+ "empty-string-list" "step")
+ (edebug-tests-should-match-result-in-messages "(\"\")")
+ "g")))
+
+(ert-deftest edebug-tests-evaluation-of-current-buffer-bug-19611 ()
+ "Edebug can evaluate `current-buffer' in correct context. (Bug#19611)."
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "current-buffer" nil t)
+ (edebug-tests-run-kbd-macro
+ "@" (edebug-tests-should-be-at
+ "current-buffer" "start")
+ "SPC SPC SPC" (edebug-tests-should-be-at
+ "current-buffer" "body")
+ "e (current-buffer) RET"
+ ;; Edebug just prints the result without "Result:"
+ (should (string-match-p
+ (regexp-quote "*edebug-test-code-buffer*")
+ edebug-tests-messages))
+ "g" (should (equal edebug-tests-@-result
+ "current-buffer: *edebug-test-code-buffer*")))))
+
+(ert-deftest edebug-tests-trivial-backquote ()
+ "Edebug can instrument a trivial backquote expression (Bug#23651)."
+ (edebug-tests-with-normal-env
+ (read-only-mode -1)
+ (delete-region (point-min) (point-max))
+ (insert "`1")
+ (read-only-mode)
+ (edebug-eval-defun nil)
+ (should (string-match-p (regexp-quote "1 (#o1, #x1, ?\\C-a)")
+ edebug-tests-messages))
+ (setq edebug-tests-messages "")
+
+ (setq edebug-initial-mode 'go)
+ ;; In Bug#23651 Edebug would hang reading `1.
+ (edebug-eval-defun t)))
+
+(ert-deftest edebug-tests-trivial-comma ()
+ "Edebug can read a trivial comma expression (Bug#23651)."
+ (edebug-tests-with-normal-env
+ (read-only-mode -1)
+ (delete-region (point-min) (point-max))
+ (insert ",1")
+ (read-only-mode)
+ (should-error (edebug-eval-defun t))))
+
+(ert-deftest edebug-tests-circular-read-syntax ()
+ "Edebug can instrument code using circular read object syntax (Bug#23660)."
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "circular-read-syntax" nil t)
+ (edebug-tests-run-kbd-macro
+ "@" (should (eql (car edebug-tests-@-result)
+ (cdr edebug-tests-@-result))))))
+
+(ert-deftest edebug-tests-hash-read-syntax ()
+ "Edebug can instrument code which uses # read syntax (Bug#25068)."
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "hash-read-syntax" nil t)
+ (edebug-tests-run-kbd-macro
+ "@g" (should (equal edebug-tests-@-result
+ '(#("abcd" 1 3 (face italic)) 511))))))
+
+(ert-deftest edebug-tests-dotted-forms ()
+ "Edebug can instrument code matching the tail of a dotted spec (Bug#6415)."
+ (edebug-tests-with-normal-env
+ (edebug-tests-setup-@ "use-destructuring-bind" nil t)
+ (edebug-tests-run-kbd-macro
+ "@ SPC SPC SPC SPC SPC SPC"
+ (edebug-tests-should-be-at "use-destructuring-bind" "x")
+ (edebug-tests-should-match-result-in-messages "2 (#o2, #x2, ?\\C-b)")
+ "SPC"
+ (edebug-tests-should-be-at "use-destructuring-bind" "y")
+ (edebug-tests-should-match-result-in-messages "3 (#o3, #x3, ?\\C-c)")
+ "g"
+ (should (equal edebug-tests-@-result 5)))))
+
+(provide 'edebug-tests)
+;;; edebug-tests.el ends here
diff --git a/test/lisp/emacs-lisp/eieio-tests/eieio-test-methodinvoke.el b/test/lisp/emacs-lisp/eieio-tests/eieio-test-methodinvoke.el
index 241ca65122d..818b3e76a1e 100644
--- a/test/lisp/emacs-lisp/eieio-tests/eieio-test-methodinvoke.el
+++ b/test/lisp/emacs-lisp/eieio-tests/eieio-test-methodinvoke.el
@@ -18,7 +18,7 @@
;; 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/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;;
@@ -192,7 +192,7 @@
(ert-deftest eieio-test-method-order-list-6 ()
;; FIXME repeated intermittent failures on hydra (bug#24503)
;; ((:STATIC C) (:STATIC C-base1) (:STATIC C-base2)) != ((:STATIC C))")
- (skip-unless (not (getenv "NIX_STORE")))
+ (skip-unless (not (getenv "EMACS_HYDRA_CI")))
(let ((eieio-test-method-order-list nil)
(ans '(
(:STATIC C)
diff --git a/test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el b/test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el
index da4cc5f51f3..738711c9c84 100644
--- a/test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el
+++ b/test/lisp/emacs-lisp/eieio-tests/eieio-test-persist.el
@@ -17,7 +17,7 @@
;; 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/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;;
@@ -104,7 +104,7 @@ This is usually a symbol that starts with `:'."
;;; Slot Writers
;;
-;; Replica of the test in eieio-tests.el -
+;; Replica of the test in eieio-tests.el -
(defclass persist-:printer (eieio-persistent)
((slot1 :initarg :slot1
@@ -164,7 +164,7 @@ persistent class.")
"persist wos 1"
:pnp (persist-not-persistent "pnp 1" :slot1 3)
:file (concat default-directory "test-ps3.pt"))))
-
+
(persist-test-save-and-compare persist-wos)
(delete-file (oref persist-wos file))))
@@ -187,14 +187,36 @@ persistent class.")
(ert-deftest eieio-test-non-persistent-as-slot-child ()
(let ((persist-woss
- (persistent-with-objs-slot-subs
+ (persistent-with-objs-slot-subs
"persist woss 1"
:pnp (persist-not-persistent-subclass "pnps 1" :slot1 3)
:file (concat default-directory "test-ps4.pt"))))
-
+
(persist-test-save-and-compare persist-woss)
(delete-file (oref persist-woss file))))
+;; A slot that can contain one of two different classes, to exercise
+;; the `or' slot type.
+
+(defclass persistent-random-class ()
+ ())
+
+(defclass persistent-multiclass-slot (eieio-persistent)
+ ((slot1 :initarg :slot1
+ :type (or persistent-random-class null persist-not-persistent))
+ (slot2 :initarg :slot2
+ :type (or persist-not-persistent persist-random-class null))))
+
+(ert-deftest eieio-test-multiple-class-slot ()
+ (let ((persist
+ (persistent-multiclass-slot "random string"
+ :slot1 (persistent-random-class)
+ :slot2 (persist-not-persistent)
+ :file (concat default-directory "test-ps5.pt"))))
+ (unwind-protect
+ (persist-test-save-and-compare persist)
+ (ignore-errors (delete-file (oref persist file))))))
+
;;; Slot with a list of Objects
;;
;; A slot that contains another object that isn't persistent
@@ -206,13 +228,13 @@ persistent class.")
(ert-deftest eieio-test-slot-with-list-of-objects ()
(let ((persist-wols
- (persistent-with-objs-list-slot
+ (persistent-with-objs-list-slot
"persist wols 1"
:pnp (list (persist-not-persistent "pnp 1" :slot1 3)
(persist-not-persistent "pnp 2" :slot1 4)
(persist-not-persistent "pnp 3" :slot1 5))
:file (concat default-directory "test-ps5.pt"))))
-
+
(persist-test-save-and-compare persist-wols)
(delete-file (oref persist-wols file))))
diff --git a/test/lisp/emacs-lisp/eieio-tests/eieio-tests.el b/test/lisp/emacs-lisp/eieio-tests/eieio-tests.el
index c34560ab585..454f2aaca0e 100644
--- a/test/lisp/emacs-lisp/eieio-tests/eieio-tests.el
+++ b/test/lisp/emacs-lisp/eieio-tests/eieio-tests.el
@@ -18,7 +18,7 @@
;; 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/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;;
@@ -887,15 +887,33 @@ Subclasses to override slot attributes.")
(should (= (length (eieio-build-class-alist 'opt-test1 nil)) 2))
(should (= (length (eieio-build-class-alist 'opt-test1 t)) 1)))
+(mapatoms (lambda (a)
+ (when (and (fboundp a)
+ (string-match "\\`cl--?generic"
+ (symbol-name a)))
+ (trace-function-background a))))
+
(defclass eieio--testing () ())
(defmethod constructor :static ((_x eieio--testing) newname &rest _args)
(list newname 2))
+(defun eieio-test-dump-trace ()
+ (message "%s" (with-current-buffer "*trace-output*"
+ (goto-char (point-min))
+ (while (re-search-forward "[\0-\010\013-\037]" nil t)
+ (insert (prog1 (format "\\%03o" (char-before))
+ (delete-char -1))))
+ (buffer-string))))
+(eieio-test-dump-trace)
+
(ert-deftest eieio-test-37-obsolete-name-in-constructor ()
;; FIXME repeated intermittent failures on hydra (bug#24503)
- (skip-unless (not (getenv "NIX_STORE")))
- (should (equal (eieio--testing "toto") '("toto" 2))))
+ (with-current-buffer "*trace-output*"
+ (erase-buffer))
+ (unwind-protect
+ (should (equal (eieio--testing "toto") '("toto" 2)))
+ (eieio-test-dump-trace)))
(ert-deftest eieio-autoload ()
"Tests to see whether reftex-auc has been autoloaded"
diff --git a/test/lisp/emacs-lisp/ert-tests.el b/test/lisp/emacs-lisp/ert-tests.el
index fc5790c3659..b620a662846 100644
--- a/test/lisp/emacs-lisp/ert-tests.el
+++ b/test/lisp/emacs-lisp/ert-tests.el
@@ -17,7 +17,7 @@
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see `http://www.gnu.org/licenses/'.
+;; along with this program. If not, see `https://www.gnu.org/licenses/'.
;;; Commentary:
@@ -294,6 +294,15 @@ failed or if there was a problem."
"the error signaled was a subtype of the expected type")))))
))
+(ert-deftest ert-test-should-error-argument ()
+ "Errors due to evaluating arguments should not break tests."
+ (should-error (identity (/ 1 0))))
+
+(ert-deftest ert-test-should-error-macroexpansion ()
+ "Errors due to expanding macros should not break tests."
+ (cl-macrolet ((test () (error "Foo")))
+ (should-error (test))))
+
(ert-deftest ert-test-skip-unless ()
;; Don't skip.
(let ((test (make-ert-test :body (lambda () (skip-unless t)))))
@@ -352,7 +361,7 @@ This macro is used to test if macroexpansion in `should' works."
(let ((abc (ert-get-test 'ert-test-abc)))
(should (equal (ert-test-tags abc) '(bar)))
(should (equal (ert-test-documentation abc) "foo")))
- (should (equal (symbol-file 'ert-test-deftest 'ert-deftest)
+ (should (equal (symbol-file 'ert-test-deftest 'ert--test)
(symbol-file 'ert-test--which-file 'defun)))
(ert-deftest ert-test-def () :expected-result ':passed)
@@ -367,12 +376,8 @@ This macro is used to test if macroexpansion in `should' works."
(test (make-ert-test :body test-body))
(result (ert-run-test test)))
(should (ert-test-failed-p result))
- (with-temp-buffer
- (ert--print-backtrace (ert-test-failed-backtrace result))
- (goto-char (point-min))
- (end-of-line)
- (let ((first-line (buffer-substring-no-properties (point-min) (point))))
- (should (equal first-line (format " %S()" test-body)))))))
+ (should (eq (nth 1 (car (ert-test-failed-backtrace result)))
+ 'signal))))
(ert-deftest ert-test-messages ()
:tags '(:causes-redisplay)
diff --git a/test/lisp/emacs-lisp/ert-x-tests.el b/test/lisp/emacs-lisp/ert-x-tests.el
index 4615d08e303..0cc89ac9977 100644
--- a/test/lisp/emacs-lisp/ert-x-tests.el
+++ b/test/lisp/emacs-lisp/ert-x-tests.el
@@ -18,7 +18,7 @@
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see `http://www.gnu.org/licenses/'.
+;; along with this program. If not, see `https://www.gnu.org/licenses/'.
;;; Commentary:
diff --git a/test/lisp/emacs-lisp/faceup-resources/faceup-test-mode.el b/test/lisp/emacs-lisp/faceup-resources/faceup-test-mode.el
new file mode 100644
index 00000000000..ec2cf272368
--- /dev/null
+++ b/test/lisp/emacs-lisp/faceup-resources/faceup-test-mode.el
@@ -0,0 +1,76 @@
+;;; faceup-test-mode.el --- Dummy major mode for testing `faceup'.
+
+;; Copyright (C) 2014-2017 Free Software Foundation, Inc.
+
+;; Author: Anders Lindgren
+;; Keywords: languages, faces
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Dummy major-mode for testing `faceup', a regression test system for
+;; font-lock keywords (syntax highlighting rules for Emacs).
+;;
+;; This mode use `syntax-propertize' to set the `syntax-table'
+;; property on "<" and ">" in "<TEXT>" to make them act like
+;; parentheses.
+;;
+;; This mode also sets the `help-echo' property on the text WARNING,
+;; the effect is that Emacs displays a tooltip when you move your
+;; mouse on to the text.
+
+;;; Code:
+
+(defvar faceup-test-mode-syntax-table
+ (make-syntax-table)
+ "Syntax table for `faceup-test-mode'.")
+
+(defvar faceup-test-font-lock-keywords
+ '(("\\_<WARNING\\_>"
+ (0 (progn
+ (add-text-properties (match-beginning 0)
+ (match-end 0)
+ '(help-echo "Baloon tip: Fly smoothly!"))
+ font-lock-warning-face))))
+ "Highlight rules for `faceup-test-mode'.")
+
+(defun faceup-test-syntax-propertize (start end)
+ (goto-char start)
+ (funcall
+ (syntax-propertize-rules
+ ("\\(<\\)\\([^<>\n]*\\)\\(>\\)"
+ (1 "() ")
+ (3 ")( ")))
+ start end))
+
+(defmacro faceup-test-define-prog-mode (mode name &rest args)
+ "Define a major mode for a programming language.
+If `prog-mode' is defined, inherit from it."
+ (declare (indent defun))
+ `(define-derived-mode
+ ,mode ,(and (fboundp 'prog-mode) 'prog-mode)
+ ,name ,@args))
+
+(faceup-test-define-prog-mode faceup-test-mode "faceup-test"
+ "Dummy major mode for testing `faceup', a test system for font-lock."
+ (set (make-local-variable 'syntax-propertize-function)
+ #'faceup-test-syntax-propertize)
+ (setq font-lock-defaults '(faceup-test-font-lock-keywords nil)))
+
+(provide 'faceup-test-mode)
+
+;;; faceup-test-mode.el ends here
diff --git a/test/lisp/emacs-lisp/faceup-resources/faceup-test-this-file-directory.el b/test/lisp/emacs-lisp/faceup-resources/faceup-test-this-file-directory.el
new file mode 100644
index 00000000000..e9d8b7074c2
--- /dev/null
+++ b/test/lisp/emacs-lisp/faceup-resources/faceup-test-this-file-directory.el
@@ -0,0 +1,32 @@
+;;; faceup-test-this-file-directory.el --- Support file for faceup tests
+
+;; Copyright (C) 2014-2017 Free Software Foundation, Inc.
+
+;; Author: Anders Lindgren
+;; Keywords: languages, faces
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Support file for `faceup-test-basics.el'. This file is used to test
+;; `faceup-this-file-directory' in various contexts.
+
+;;; Code:
+
+(defvar faceup-test-this-file-directory (faceup-this-file-directory))
+
+;;; faceup-test-this-file-directory.el ends here
diff --git a/test/lisp/emacs-lisp/faceup-resources/files/test1.txt b/test/lisp/emacs-lisp/faceup-resources/files/test1.txt
new file mode 100644
index 00000000000..d971f364c2d
--- /dev/null
+++ b/test/lisp/emacs-lisp/faceup-resources/files/test1.txt
@@ -0,0 +1,15 @@
+This is a test of `faceup', a regression test system for font-lock
+keywords. It should use major mode `faceup-test-mode'.
+
+WARNING: The first word on this line should use
+`font-lock-warning-face', and a tooltip should be displayed if the
+mouse pointer is moved over it.
+
+In this mode "<" and ">" are parentheses, but only when on the same
+line without any other "<" and ">" characters between them.
+<OK> <NOT <OK> >
+<
+NOT OK
+>
+
+test1.txt ends here.
diff --git a/test/lisp/emacs-lisp/faceup-resources/files/test1.txt.faceup b/test/lisp/emacs-lisp/faceup-resources/files/test1.txt.faceup
new file mode 100644
index 00000000000..7d4938adf17
--- /dev/null
+++ b/test/lisp/emacs-lisp/faceup-resources/files/test1.txt.faceup
@@ -0,0 +1,15 @@
+This is a test of `faceup', a regression test system for font-lock
+keywords. It should use major mode `faceup-test-mode'.
+
+«(help-echo):"Baloon tip: Fly smoothly!":«w:WARNING»»: The first word on this line should use
+`font-lock-warning-face', and a tooltip should be displayed if the
+mouse pointer is moved over it.
+
+In this mode «s:"«(syntax-table):(4 . 41):<»"» and «s:"«(syntax-table):(5 . 40):>»"» are parentheses, but only when on the same
+line without any other «s:"«(syntax-table):(4 . 41):<»"» and «s:"«(syntax-table):(5 . 40):>»"» characters between them.
+«(syntax-table):(4 . 41):<»OK«(syntax-table):(5 . 40):>» <NOT «(syntax-table):(4 . 41):<»OK«(syntax-table):(5 . 40):>» >
+<
+NOT OK
+>
+
+test1.txt ends here.
diff --git a/test/lisp/emacs-lisp/faceup-tests/faceup-test-basics.el b/test/lisp/emacs-lisp/faceup-tests/faceup-test-basics.el
new file mode 100644
index 00000000000..fd58c1bbca6
--- /dev/null
+++ b/test/lisp/emacs-lisp/faceup-tests/faceup-test-basics.el
@@ -0,0 +1,269 @@
+;;; faceup-test-basics.el --- Tests for the `faceup' package.
+
+;; Copyright (C) 2014-2017 Free Software Foundation, Inc.
+
+;; Author: Anders Lindgren
+;; Keywords: languages, faces
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Basic tests for the `faceup' package.
+
+;;; Code:
+
+(eval-when-compile (require 'cl-lib))
+(require 'faceup)
+
+(ert-deftest faceup-functions ()
+ "Test primitive functions."
+ (should (equal (faceup-normalize-face-property '()) '()))
+ (should (equal (faceup-normalize-face-property 'a) '(a)))
+ (should (equal (faceup-normalize-face-property '(a)) '(a)))
+ (should (equal (faceup-normalize-face-property '(:x t)) '((:x t))))
+ (should (equal (faceup-normalize-face-property '(:x t a)) '((:x t))))
+ (should (equal (faceup-normalize-face-property '(:x t a b)) '((:x t))))
+ (should (equal (faceup-normalize-face-property '(a :x t)) '(a (:x t))))
+ (should (equal (faceup-normalize-face-property '(a b :x t))
+ '(a b (:x t))))
+
+ (should (equal (faceup-normalize-face-property '(:x t :y nil))
+ '((:y nil) (:x t))))
+ (should (equal (faceup-normalize-face-property '(:x t :y nil a))
+ '((:y nil) (:x t))))
+ (should (equal (faceup-normalize-face-property '(:x t :y nil a b))
+ '((:y nil) (:x t))))
+ (should (equal (faceup-normalize-face-property '(a :x t :y nil))
+ '(a (:y nil) (:x t))))
+ (should (equal (faceup-normalize-face-property '(a b :x t :y nil))
+ '(a b (:y nil) (:x t)))))
+
+
+(ert-deftest faceup-markup-basics ()
+ (should (equal (faceup-markup-string "") ""))
+ (should (equal (faceup-markup-string "test") "test")))
+
+(ert-deftest faceup-markup-escaping ()
+ (should (equal (faceup-markup-string "«") "««"))
+ (should (equal (faceup-markup-string "«A«B«C«") "««A««B««C««"))
+ (should (equal (faceup-markup-string "»") "«»"))
+ (should (equal (faceup-markup-string "»A»B»C»") "«»A«»B«»C«»")))
+
+(ert-deftest faceup-markup-plain ()
+ ;; UU
+ ;; ABCDEF
+ (should (equal (faceup-markup-string
+ #("ABCDEF" 2 4 (face underline)))
+ "AB«U:CD»EF")))
+
+(ert-deftest faceup-markup-plain-full-text ()
+ ;; UUUUUU
+ ;; ABCDEF
+ (should (equal (faceup-markup-string
+ #("ABCDEF" 0 6 (face underline)))
+ "«U:ABCDEF»")))
+
+(ert-deftest faceup-markup-anonymous-face ()
+ ;; AA
+ ;; ABCDEF
+ (should (equal (faceup-markup-string
+ #("ABCDEF" 2 4 (face (:underline t))))
+ "AB«:(:underline t):CD»EF")))
+
+(ert-deftest faceup-markup-anonymous-face-2keys ()
+ ;; AA
+ ;; ABCDEF
+ (should (equal (faceup-markup-string
+ #("ABCDEF" 2 4 (face (:foo t :bar nil))))
+ "AB«:(:foo t):«:(:bar nil):CD»»EF"))
+ ;; Plist in list.
+ (should (equal (faceup-markup-string
+ #("ABCDEF" 2 4 (face ((:foo t :bar nil)))))
+ "AB«:(:foo t):«:(:bar nil):CD»»EF"))
+ ;; Two plists.
+ (should (equal (faceup-markup-string
+ #("ABCDEF" 2 4 (face ((:foo t) (:bar nil)))))
+ "AB«:(:bar nil):«:(:foo t):CD»»EF")))
+
+(ert-deftest faceup-markup-anonymous-nested ()
+ ;; AA
+ ;; IIII
+ ;; ABCDEF
+ (should (equal (faceup-markup-string
+ #("ABCDEF"
+ 1 2 (face ((:foo t)))
+ 2 4 (face ((:bar t) (:foo t)))
+ 4 5 (face ((:foo t)))))
+ "A«:(:foo t):B«:(:bar t):CD»E»F")))
+
+(ert-deftest faceup-markup-nested ()
+ ;; UU
+ ;; IIII
+ ;; ABCDEF
+ (should (equal (faceup-markup-string
+ #("ABCDEF"
+ 1 2 (face italic)
+ 2 4 (face (underline italic))
+ 4 5 (face italic)))
+ "A«I:B«U:CD»E»F")))
+
+(ert-deftest faceup-markup-overlapping ()
+ ;; UUU
+ ;; III
+ ;; ABCDEF
+ (should (equal (faceup-markup-string
+ #("ABCDEF"
+ 1 2 (face italic)
+ 2 4 (face (underline italic))
+ 4 5 (face underline)))
+ "A«I:B«U:CD»»«U:E»F"))
+ ;; III
+ ;; UUU
+ ;; ABCDEF
+ (should (equal (faceup-markup-string
+ #("ABCDEF"
+ 1 2 (face italic)
+ 2 4 (face (italic underline))
+ 4 5 (face underline)))
+ "A«I:B»«U:«I:CD»E»F")))
+
+(ert-deftest faceup-markup-multi-face ()
+ ;; More than one face at the same location.
+ ;;
+ ;; The property to the front takes precedence, it is rendered as the
+ ;; innermost parenthesis pair.
+ (should (equal (faceup-markup-string
+ #("ABCDEF" 2 4 (face (underline italic))))
+ "AB«I:«U:CD»»EF"))
+ (should (equal (faceup-markup-string
+ #("ABCDEF" 2 4 (face (italic underline))))
+ "AB«U:«I:CD»»EF"))
+ ;; Equal ranges, full text.
+ (should (equal (faceup-markup-string
+ #("ABCDEF" 0 6 (face (underline italic))))
+ "«I:«U:ABCDEF»»"))
+ ;; Ditto, with stray markup characters.
+ (should (equal (faceup-markup-string
+ #("AB«CD»EF" 0 8 (face (underline italic))))
+ "«I:«U:AB««CD«»EF»»")))
+
+(ert-deftest faceup-markup-multi-property ()
+ (let ((faceup-properties '(alpha beta gamma)))
+ ;; One property.
+ (should (equal (faceup-markup-string
+ #("ABCDEF" 2 4 (alpha (a l p h a))))
+ "AB«(alpha):(a l p h a):CD»EF"))
+
+ ;; Two properties, inner enclosed.
+ (should (equal (faceup-markup-string
+ (let ((s (copy-sequence "ABCDEFGHIJ")))
+ (set-text-properties 2 8 '(alpha (a l p h a)) s)
+ (font-lock-append-text-property 4 6 'beta '(b e t a) s)
+ s))
+ "AB«(alpha):(a l p h a):CD«(beta):(b e t a):EF»GH»IJ"))
+
+ ;; Two properties, same end
+ (should (equal (faceup-markup-string
+ (let ((s (copy-sequence "ABCDEFGH")))
+ (set-text-properties 2 6 '(alpha (a)) s)
+ (add-text-properties 4 6 '(beta (b)) s)
+ s))
+ "AB«(alpha):(a):CD«(beta):(b):EF»»GH"))
+
+ ;; Two properties, overlap.
+ (should (equal (faceup-markup-string
+ (let ((s (copy-sequence "ABCDEFGHIJ")))
+ (set-text-properties 2 6 '(alpha (a)) s)
+ (add-text-properties 4 8 '(beta (b)) s)
+ s))
+ "AB«(alpha):(a):CD«(beta):(b):EF»»«(beta):(b):GH»IJ"))))
+
+
+(ert-deftest faceup-clean ()
+ "Test the clean features of `faceup'."
+ (should (equal (faceup-clean-string "") ""))
+ (should (equal (faceup-clean-string "test") "test"))
+ (should (equal (faceup-clean-string "AB«U:CD»EF") "ABCDEF"))
+ (should (equal (faceup-clean-string "«U:ABCDEF»") "ABCDEF"))
+ (should (equal (faceup-clean-string "A«I:B«U:CD»E»F") "ABCDEF"))
+ (should (equal (faceup-clean-string "A«I:B«U:CD»»«U:E»F") "ABCDEF"))
+ (should (equal (faceup-clean-string "AB«I:«U:CD»»EF") "ABCDEF"))
+ (should (equal (faceup-clean-string "«I:«U:ABCDEF»»") "ABCDEF"))
+ (should (equal (faceup-clean-string "«(foo)I:ABC»DEF") "ABCDEF"))
+ (should (equal (faceup-clean-string "«:(:foo t):ABC»DEF") "ABCDEF"))
+ ;; Escaped markup characters.
+ (should (equal (faceup-clean-string "««") "«"))
+ (should (equal (faceup-clean-string "«»") "»"))
+ (should (equal (faceup-clean-string "A«I:B«U:CD»«»»«U:E»F") "ABCD»EF")))
+
+
+(ert-deftest faceup-render ()
+ "Test the render features of `faceup'."
+ (should (equal (faceup-render-string "") ""))
+ (should (equal (faceup-render-string "««") "«"))
+ (should (equal (faceup-render-string "«»") "»"))
+ (should (equal (faceup-render-string "A«I:B«U:CD»«»»«U:E»F") "ABCD»EF")))
+
+
+(defvar faceup-test-resources-directory
+ (concat (file-name-directory
+ (substring (faceup-this-file-directory) 0 -1))
+ "faceup-resources/")
+ "The `faceup-resources' directory.")
+
+
+(defvar faceup-test-this-file-directory nil
+ "The result of `faceup-this-file-directory' in various contexts.
+
+This is set by the file test support file
+`faceup-test-this-file-directory.el'.")
+
+
+(ert-deftest faceup-directory ()
+ "Test `faceup-this-file-directory'."
+ (let ((file (concat faceup-test-resources-directory
+ "faceup-test-this-file-directory.el"))
+ (load-file-name nil))
+ ;; Test normal load.
+ (makunbound 'faceup-test-this-file-directory)
+ (load file nil :nomessage)
+ (should (equal faceup-test-this-file-directory
+ faceup-test-resources-directory))
+ ;; Test `eval-buffer'.
+ (makunbound 'faceup-test-this-file-directory)
+ (save-excursion
+ (find-file file)
+ (eval-buffer))
+ (should (equal faceup-test-this-file-directory
+ faceup-test-resources-directory))
+ ;; Test `eval-defun'.
+ (makunbound 'faceup-test-this-file-directory)
+ (save-excursion
+ (find-file file)
+ (save-excursion
+ (goto-char (point-min))
+ (while (not (eobp))
+ ;; Note: In batch mode, this prints the result of the
+ ;; evaluation. Unfortunately, this is hard to fix.
+ (eval-defun nil)
+ (forward-sexp))))
+ (should (equal faceup-test-this-file-directory
+ faceup-test-resources-directory))))
+
+(provide 'faceup-test-basics)
+
+;;; faceup-test-basics.el ends here
diff --git a/test/lisp/emacs-lisp/faceup-tests/faceup-test-files.el b/test/lisp/emacs-lisp/faceup-tests/faceup-test-files.el
new file mode 100644
index 00000000000..0f136862094
--- /dev/null
+++ b/test/lisp/emacs-lisp/faceup-tests/faceup-test-files.el
@@ -0,0 +1,63 @@
+;;; faceup-test-files.el --- Self test of `faceup' using dummy major mode.
+
+;; Copyright (C) 2014-2017 Free Software Foundation, Inc.
+
+;; Author: Anders Lindgren
+;; Keywords: languages, faces
+
+;; 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 <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Self test of `faceup' with a major mode that sets both the
+;; `syntax-table' and the `echo-help' property.
+;;
+;; This file can also be seen as a blueprint of test cases for real
+;; major modes.
+
+;;; Code:
+
+(require 'faceup)
+
+;; Note: The byte compiler needs the value to load `faceup-test-mode',
+;; hence the `eval-and-compile'.
+(eval-and-compile
+ (defvar faceup-test-files-dir (faceup-this-file-directory)
+ "The directory of this file."))
+
+(require 'faceup-test-mode
+ (concat faceup-test-files-dir
+ "../faceup-resources/"
+ "faceup-test-mode.el"))
+
+(defun faceup-test-files-check-one (file)
+ "Test that FILE is fontified as the .faceup file describes.
+
+FILE is interpreted as relative to this source directory."
+ (let ((faceup-properties '(face syntax-table help-echo)))
+ (faceup-test-font-lock-file 'faceup-test-mode
+ (concat
+ faceup-test-files-dir
+ "../faceup-resources/"
+ file))))
+(faceup-defexplainer faceup-test-files-check-one)
+
+(ert-deftest faceup-files ()
+ (should (faceup-test-files-check-one "files/test1.txt")))
+
+(provide 'faceup-test-files)
+
+;;; faceup-test-files.el ends here
diff --git a/test/lisp/emacs-lisp/generator-tests.el b/test/lisp/emacs-lisp/generator-tests.el
index 1a567ac70fc..cbb136ae919 100644
--- a/test/lisp/emacs-lisp/generator-tests.el
+++ b/test/lisp/emacs-lisp/generator-tests.el
@@ -18,7 +18,7 @@
;; 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/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@@ -282,3 +282,13 @@ identical output.
(ert-deftest cps-test-declarations-preserved ()
(should (equal (documentation 'generator-with-docstring) "Documentation!"))
(should (equal (get 'generator-with-docstring 'lisp-indent-function) 5)))
+
+(ert-deftest cps-iter-lambda-with-dynamic-binding ()
+ "`iter-lambda' with dynamic binding produces correct result (bug#25965)."
+ (should (= 1
+ (iter-next
+ (funcall (iter-lambda ()
+ (let* ((fill-column 10) ;;any special variable will do
+ (i 0)
+ (j (setq i (1+ i))))
+ (iter-yield i))))))))
diff --git a/test/lisp/emacs-lisp/gv-tests.el b/test/lisp/emacs-lisp/gv-tests.el
new file mode 100644
index 00000000000..93f70827133
--- /dev/null
+++ b/test/lisp/emacs-lisp/gv-tests.el
@@ -0,0 +1,147 @@
+;;; 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 <https://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
diff --git a/test/lisp/emacs-lisp/let-alist-tests.el b/test/lisp/emacs-lisp/let-alist-tests.el
index d04645709e4..edcfe8a5291 100644
--- a/test/lisp/emacs-lisp/let-alist-tests.el
+++ b/test/lisp/emacs-lisp/let-alist-tests.el
@@ -15,7 +15,7 @@
;; 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/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Code:
diff --git a/test/lisp/emacs-lisp/lisp-mode-tests.el b/test/lisp/emacs-lisp/lisp-mode-tests.el
index 582041cfc2d..6bc916f6c35 100644
--- a/test/lisp/emacs-lisp/lisp-mode-tests.el
+++ b/test/lisp/emacs-lisp/lisp-mode-tests.el
@@ -13,7 +13,7 @@
;; 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/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Code:
@@ -198,6 +198,32 @@ Expected initialization file: `%s'\"
(indent-region (point-min) (point-max))
(should (equal (buffer-string) correct)))))
+(ert-deftest lisp-comment-indent-1 ()
+ (with-temp-buffer
+ (insert "\
+\(let ( ;sf
+ (x 3))
+ 4)")
+ (let ((indent-tabs-mode nil)
+ (correct (buffer-string)))
+ (emacs-lisp-mode)
+ (goto-char (point-min))
+ (comment-indent)
+ (should (equal (buffer-string) correct)))))
+
+(ert-deftest lisp-comment-indent-2 ()
+ (with-temp-buffer
+ (insert "\
+\(let (;;sf
+ (x 3))
+ 4)")
+ (let ((indent-tabs-mode nil)
+ (correct (buffer-string)))
+ (emacs-lisp-mode)
+ (goto-char (point-min))
+ (comment-indent)
+ (should (equal (buffer-string) correct)))))
+
(provide 'lisp-mode-tests)
;;; lisp-mode-tests.el ends here
diff --git a/test/lisp/emacs-lisp/lisp-tests.el b/test/lisp/emacs-lisp/lisp-tests.el
index ddbf378683b..654d949d388 100644
--- a/test/lisp/emacs-lisp/lisp-tests.el
+++ b/test/lisp/emacs-lisp/lisp-tests.el
@@ -19,7 +19,7 @@
;; 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/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@@ -589,5 +589,36 @@ region."
(should (= (point) before))
(should (= (mark) after))))
+(ert-deftest lisp-fill-paragraph-colon ()
+ "Keywords below Emacs Lisp docstrings should not be filled (Bug#24622).
+Keywords inside docstrings should be filled (Bug#7751)."
+ (elisp-tests-with-temp-buffer
+ "
+\(defcustom custom value
+ \"First\n
+Second\n
+=!inside=Third line\"
+ =!keywords=:type 'sexp
+ :version \"26.1\"
+ :group 'lisp-tests)"
+ (goto-char inside)
+ (fill-paragraph)
+ (goto-char keywords)
+ (beginning-of-line)
+ (should (looking-at " :type 'sexp\n :version \"26.1\"\n :")))
+ (elisp-tests-with-temp-buffer
+ "
+\(defun foo ()
+ \"Summary.
+=!inside=Testing keywords: :one :two :three\"
+ (body))" ; FIXME: Remove parens around body to test Bug#28937 once it's fixed
+ (goto-char inside)
+ (let ((emacs-lisp-docstring-fill-column 30))
+ (fill-paragraph))
+ (forward-line)
+ (should (looking-at ":three"))
+ (end-of-line)
+ (should-not (eq (preceding-char) ?\)))))
+
(provide 'lisp-tests)
;;; lisp-tests.el ends here
diff --git a/test/lisp/emacs-lisp/map-tests.el b/test/lisp/emacs-lisp/map-tests.el
index 07e85cc5391..a434c9bd066 100644
--- a/test/lisp/emacs-lisp/map-tests.el
+++ b/test/lisp/emacs-lisp/map-tests.el
@@ -18,7 +18,7 @@
;; 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/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@@ -36,7 +36,7 @@ Each map is built from the following alist data:
Evaluate BODY for each created map.
\(fn (var map) body)"
- (declare (indent 1) (debug t))
+ (declare (indent 1) (debug (symbolp body)))
(let ((alist (make-symbol "alist"))
(vec (make-symbol "vec"))
(ht (make-symbol "ht")))
@@ -63,6 +63,13 @@ Evaluate BODY for each created map.
(with-maps-do map
(should (= 5 (map-elt map 7 5)))))
+(ert-deftest test-map-elt-testfn ()
+ (let ((map (list (cons "a" 1) (cons "b" 2)))
+ ;; Make sure to use a non-eq "a", even when compiled.
+ (noneq-key (string ?a)))
+ (should-not (map-elt map noneq-key))
+ (should (map-elt map noneq-key nil 'equal))))
+
(ert-deftest test-map-elt-with-nil-value ()
(should (null (map-elt '((a . 1)
(b))
@@ -94,6 +101,15 @@ Evaluate BODY for each created map.
(should (eq (map-elt alist 2)
'b))))
+(ert-deftest test-map-put-testfn-alist ()
+ (let ((alist (list (cons "a" 1) (cons "b" 2)))
+ ;; Make sure to use a non-eq "a", even when compiled.
+ (noneq-key (string ?a)))
+ (map-put alist noneq-key 3 'equal)
+ (should-not (cddr alist))
+ (map-put alist noneq-key 9)
+ (should (cddr alist))))
+
(ert-deftest test-map-put-return-value ()
(let ((ht (make-hash-table)))
(should (eq (map-put ht 'a 'hello) 'hello))))
diff --git a/test/lisp/emacs-lisp/nadvice-tests.el b/test/lisp/emacs-lisp/nadvice-tests.el
index b228da6cdb8..5cee61ee67d 100644
--- a/test/lisp/emacs-lisp/nadvice-tests.el
+++ b/test/lisp/emacs-lisp/nadvice-tests.el
@@ -15,7 +15,7 @@
;; 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/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
diff --git a/test/lisp/emacs-lisp/package-tests.el b/test/lisp/emacs-lisp/package-tests.el
index 62fdc751fb5..33209d3d990 100644
--- a/test/lisp/emacs-lisp/package-tests.el
+++ b/test/lisp/emacs-lisp/package-tests.el
@@ -18,7 +18,7 @@
;; 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/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
diff --git a/test/lisp/emacs-lisp/pcase-tests.el b/test/lisp/emacs-lisp/pcase-tests.el
index ef0b2f6b246..3bd14ed4b42 100644
--- a/test/lisp/emacs-lisp/pcase-tests.el
+++ b/test/lisp/emacs-lisp/pcase-tests.el
@@ -15,7 +15,7 @@
;; 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/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
diff --git a/test/lisp/emacs-lisp/pp-tests.el b/test/lisp/emacs-lisp/pp-tests.el
index b9ed79c7749..aed2d3770fb 100644
--- a/test/lisp/emacs-lisp/pp-tests.el
+++ b/test/lisp/emacs-lisp/pp-tests.el
@@ -15,7 +15,7 @@
;; 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/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Code:
diff --git a/test/lisp/emacs-lisp/regexp-opt-tests.el b/test/lisp/emacs-lisp/regexp-opt-tests.el
index 92626317052..4beb7bfa1ca 100644
--- a/test/lisp/emacs-lisp/regexp-opt-tests.el
+++ b/test/lisp/emacs-lisp/regexp-opt-tests.el
@@ -19,7 +19,7 @@
;; 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/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Code:
diff --git a/test/lisp/emacs-lisp/ring-tests.el b/test/lisp/emacs-lisp/ring-tests.el
index c869f9dc875..00bcf8401c4 100644
--- a/test/lisp/emacs-lisp/ring-tests.el
+++ b/test/lisp/emacs-lisp/ring-tests.el
@@ -18,7 +18,7 @@
;; 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/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
diff --git a/test/lisp/emacs-lisp/rmc-tests.el b/test/lisp/emacs-lisp/rmc-tests.el
new file mode 100644
index 00000000000..7ab79fda774
--- /dev/null
+++ b/test/lisp/emacs-lisp/rmc-tests.el
@@ -0,0 +1,41 @@
+;;; rmc-tests.el --- Test suite for rmc.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2017 Free Software Foundation, Inc.
+
+;; Author: Tino Calancha <tino.calancha@gmail.com>
+;; Keywords:
+
+;; This program 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.
+
+;; This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'ert)
+(require 'rmc)
+(eval-when-compile (require 'cl-lib))
+
+
+(ert-deftest test-read-multiple-choice ()
+ (dolist (char '(?y ?n))
+ (cl-letf* (((symbol-function #'read-char) (lambda () char))
+ (str (if (eq char ?y) "yes" "no")))
+ (should (equal (list char str)
+ (read-multiple-choice "Do it? " '((?y "yes") (?n "no"))))))))
+
+
+(provide 'rmc-tests)
+;;; rmc-tests.el ends here
diff --git a/test/lisp/emacs-lisp/rx-tests.el b/test/lisp/emacs-lisp/rx-tests.el
index 8b7945c9d27..d9ebb769613 100644
--- a/test/lisp/emacs-lisp/rx-tests.el
+++ b/test/lisp/emacs-lisp/rx-tests.el
@@ -15,7 +15,7 @@
;; 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/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@@ -33,5 +33,15 @@
(number-sequence ?< ?\])
(number-sequence ?- ?:))))))
+(ert-deftest rx-pcase ()
+ (should (equal (pcase "a 1 2 3 1 1 b"
+ ((rx (let u (+ digit)) space
+ (let v (+ digit)) space
+ (let v (+ digit)) space
+ (backref u) space
+ (backref 1))
+ (list u v)))
+ '("1" "3"))))
+
(provide 'rx-tests)
;; rx-tests.el ends here.
diff --git a/test/lisp/emacs-lisp/seq-tests.el b/test/lisp/emacs-lisp/seq-tests.el
index 495cf1e543c..5aa794a43b0 100644
--- a/test/lisp/emacs-lisp/seq-tests.el
+++ b/test/lisp/emacs-lisp/seq-tests.el
@@ -18,7 +18,7 @@
;; 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/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
diff --git a/test/lisp/emacs-lisp/subr-x-tests.el b/test/lisp/emacs-lisp/subr-x-tests.el
index 2b2a5cd0d71..0187f39d15d 100644
--- a/test/lisp/emacs-lisp/subr-x-tests.el
+++ b/test/lisp/emacs-lisp/subr-x-tests.el
@@ -16,7 +16,7 @@
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see <http://www.gnu.org/licenses/>.
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@@ -28,13 +28,13 @@
(require 'subr-x)
-;; if-let tests
+;; `if-let*' tests
-(ert-deftest subr-x-test-if-let-single-binding-expansion ()
+(ert-deftest subr-x-test-if-let*-single-binding-expansion ()
"Test single bindings are expanded properly."
(should (equal
(macroexpand
- '(if-let (a 1)
+ '(if-let* ((a 1))
(- a)
"no"))
'(let* ((a (and t 1)))
@@ -43,53 +43,53 @@
"no"))))
(should (equal
(macroexpand
- '(if-let (a)
+ '(if-let* (a)
(- a)
"no"))
- '(let* ((a (and t nil)))
+ '(let* ((a (and t a)))
(if a
(- a)
"no")))))
-(ert-deftest subr-x-test-if-let-single-symbol-expansion ()
+(ert-deftest subr-x-test-if-let*-single-symbol-expansion ()
"Test single symbol bindings are expanded properly."
(should (equal
(macroexpand
- '(if-let (a)
+ '(if-let* (a)
(- a)
"no"))
- '(let* ((a (and t nil)))
+ '(let* ((a (and t a)))
(if a
(- a)
"no"))))
(should (equal
(macroexpand
- '(if-let (a b c)
+ '(if-let* (a b c)
(- a)
"no"))
- '(let* ((a (and t nil))
- (b (and a nil))
- (c (and b nil)))
+ '(let* ((a (and t a))
+ (b (and a b))
+ (c (and b c)))
(if c
(- a)
"no"))))
(should (equal
(macroexpand
- '(if-let (a (b 2) c)
+ '(if-let* (a (b 2) c)
(- a)
"no"))
- '(let* ((a (and t nil))
+ '(let* ((a (and t a))
(b (and a 2))
- (c (and b nil)))
+ (c (and b c)))
(if c
(- a)
"no")))))
-(ert-deftest subr-x-test-if-let-nil-related-expansion ()
+(ert-deftest subr-x-test-if-let*-nil-related-expansion ()
"Test nil is processed properly."
(should (equal
(macroexpand
- '(if-let (nil)
+ '(if-let* (nil)
(- a)
"no"))
'(let* ((nil (and t nil)))
@@ -98,27 +98,7 @@
"no"))))
(should (equal
(macroexpand
- '(if-let ((nil))
- (- a)
- "no"))
- '(let* ((nil (and t nil)))
- (if nil
- (- a)
- "no"))))
- (should (equal
- (macroexpand
- '(if-let ((a 1) (nil) (b 2))
- (- a)
- "no"))
- '(let* ((a (and t 1))
- (nil (and a nil))
- (b (and nil 2)))
- (if b
- (- a)
- "no"))))
- (should (equal
- (macroexpand
- '(if-let ((a 1) nil (b 2))
+ '(if-let* ((a 1) nil (b 2))
(- a)
"no"))
'(let* ((a (and t 1))
@@ -128,104 +108,106 @@
(- a)
"no")))))
-(ert-deftest subr-x-test-if-let-malformed-binding ()
+(ert-deftest subr-x-test-if-let*-malformed-binding ()
"Test malformed bindings trigger errors."
(should-error (macroexpand
- '(if-let (_ (a 1 1) (b 2) (c 3) d)
+ '(if-let* (_ (a 1 1) (b 2) (c 3) d)
(- a)
"no"))
:type 'error)
(should-error (macroexpand
- '(if-let (_ (a 1) (b 2 2) (c 3) d)
+ '(if-let* (_ (a 1) (b 2 2) (c 3) d)
(- a)
"no"))
:type 'error)
(should-error (macroexpand
- '(if-let (_ (a 1) (b 2) (c 3 3) d)
+ '(if-let* (_ (a 1) (b 2) (c 3 3) d)
(- a)
"no"))
:type 'error)
(should-error (macroexpand
- '(if-let ((a 1 1))
+ '(if-let* ((a 1 1))
(- a)
"no"))
:type 'error))
-(ert-deftest subr-x-test-if-let-true ()
+(ert-deftest subr-x-test-if-let*-true ()
"Test `if-let' with truthy bindings."
(should (equal
- (if-let (a 1)
+ (if-let* ((a 1))
a
"no")
1))
(should (equal
- (if-let ((a 1) (b 2) (c 3))
+ (if-let* ((a 1) (b 2) (c 3))
(list a b c)
"no")
(list 1 2 3))))
-(ert-deftest subr-x-test-if-let-false ()
+(ert-deftest subr-x-test-if-let*-false ()
"Test `if-let' with falsie bindings."
(should (equal
- (if-let (a nil)
+ (if-let* ((a nil))
(list a b c)
"no")
"no"))
(should (equal
- (if-let ((a nil) (b 2) (c 3))
+ (if-let* ((a nil) (b 2) (c 3))
(list a b c)
"no")
"no"))
(should (equal
- (if-let ((a 1) (b nil) (c 3))
+ (if-let* ((a 1) (b nil) (c 3))
(list a b c)
"no")
"no"))
(should (equal
- (if-let ((a 1) (b 2) (c nil))
+ (if-let* ((a 1) (b 2) (c nil))
(list a b c)
"no")
"no"))
(should (equal
- (if-let (z (a 1) (b 2) (c 3))
- (list a b c)
- "no")
+ (let (z)
+ (if-let* (z (a 1) (b 2) (c 3))
+ (list a b c)
+ "no"))
"no"))
(should (equal
- (if-let ((a 1) (b 2) (c 3) d)
- (list a b c)
- "no")
+ (let (d)
+ (if-let* ((a 1) (b 2) (c 3) d)
+ (list a b c)
+ "no"))
"no")))
-(ert-deftest subr-x-test-if-let-bound-references ()
+(ert-deftest subr-x-test-if-let*-bound-references ()
"Test `if-let' bindings can refer to already bound symbols."
(should (equal
- (if-let ((a (1+ 0)) (b (1+ a)) (c (1+ b)))
+ (if-let* ((a (1+ 0)) (b (1+ a)) (c (1+ b)))
(list a b c)
"no")
(list 1 2 3))))
-(ert-deftest subr-x-test-if-let-and-laziness-is-preserved ()
+(ert-deftest subr-x-test-if-let*-and-laziness-is-preserved ()
"Test `if-let' respects `and' laziness."
(let (a-called b-called c-called)
(should (equal
- (if-let ((a nil)
- (b (setq b-called t))
- (c (setq c-called t)))
+ (if-let* ((a nil)
+ (b (setq b-called t))
+ (c (setq c-called t)))
"yes"
(list a-called b-called c-called))
(list nil nil nil))))
(let (a-called b-called c-called)
(should (equal
- (if-let ((a (setq a-called t))
- (b nil)
- (c (setq c-called t)))
+ (if-let* ((a (setq a-called t))
+ (b nil)
+ (c (setq c-called t)))
"yes"
(list a-called b-called c-called))
(list t nil nil))))
(let (a-called b-called c-called)
(should (equal
- (if-let ((a (setq a-called t))
+ (if-let* ((a (setq a-called t))
(b (setq b-called t))
(c nil)
(d (setq c-called t)))
@@ -234,13 +216,13 @@
(list t t nil)))))
-;; when-let tests
+;; `when-let*' tests
-(ert-deftest subr-x-test-when-let-body-expansion ()
+(ert-deftest subr-x-test-when-let*-body-expansion ()
"Test body allows for multiple sexps wrapping with progn."
(should (equal
(macroexpand
- '(when-let (a 1)
+ '(when-let* ((a 1))
(message "opposite")
(- a)))
'(let* ((a (and t 1)))
@@ -249,79 +231,46 @@
(message "opposite")
(- a)))))))
-(ert-deftest subr-x-test-when-let-single-binding-expansion ()
- "Test single bindings are expanded properly."
- (should (equal
- (macroexpand
- '(when-let (a 1)
- (- a)))
- '(let* ((a (and t 1)))
- (if a
- (- a)))))
- (should (equal
- (macroexpand
- '(when-let (a)
- (- a)))
- '(let* ((a (and t nil)))
- (if a
- (- a))))))
-
-(ert-deftest subr-x-test-when-let-single-symbol-expansion ()
+(ert-deftest subr-x-test-when-let*-single-symbol-expansion ()
"Test single symbol bindings are expanded properly."
(should (equal
(macroexpand
- '(when-let (a)
+ '(when-let* (a)
(- a)))
- '(let* ((a (and t nil)))
+ '(let* ((a (and t a)))
(if a
(- a)))))
(should (equal
(macroexpand
- '(when-let (a b c)
+ '(when-let* (a b c)
(- a)))
- '(let* ((a (and t nil))
- (b (and a nil))
- (c (and b nil)))
+ '(let* ((a (and t a))
+ (b (and a b))
+ (c (and b c)))
(if c
(- a)))))
(should (equal
(macroexpand
- '(when-let (a (b 2) c)
+ '(when-let* (a (b 2) c)
(- a)))
- '(let* ((a (and t nil))
+ '(let* ((a (and t a))
(b (and a 2))
- (c (and b nil)))
+ (c (and b c)))
(if c
(- a))))))
-(ert-deftest subr-x-test-when-let-nil-related-expansion ()
+(ert-deftest subr-x-test-when-let*-nil-related-expansion ()
"Test nil is processed properly."
(should (equal
(macroexpand
- '(when-let (nil)
- (- a)))
- '(let* ((nil (and t nil)))
- (if nil
- (- a)))))
- (should (equal
- (macroexpand
- '(when-let ((nil))
+ '(when-let* (nil)
(- a)))
'(let* ((nil (and t nil)))
(if nil
(- a)))))
(should (equal
(macroexpand
- '(when-let ((a 1) (nil) (b 2))
- (- a)))
- '(let* ((a (and t 1))
- (nil (and a nil))
- (b (and nil 2)))
- (if b
- (- a)))))
- (should (equal
- (macroexpand
- '(when-let ((a 1) nil (b 2))
+ '(when-let* ((a 1) nil (b 2))
(- a)))
'(let* ((a (and t 1))
(nil (and a nil))
@@ -329,108 +278,176 @@
(if b
(- a))))))
-(ert-deftest subr-x-test-when-let-malformed-binding ()
+(ert-deftest subr-x-test-when-let*-malformed-binding ()
"Test malformed bindings trigger errors."
(should-error (macroexpand
- '(when-let (_ (a 1 1) (b 2) (c 3) d)
+ '(when-let* (_ (a 1 1) (b 2) (c 3) d)
(- a)))
:type 'error)
(should-error (macroexpand
- '(when-let (_ (a 1) (b 2 2) (c 3) d)
+ '(when-let* (_ (a 1) (b 2 2) (c 3) d)
(- a)))
:type 'error)
(should-error (macroexpand
- '(when-let (_ (a 1) (b 2) (c 3 3) d)
+ '(when-let* (_ (a 1) (b 2) (c 3 3) d)
(- a)))
:type 'error)
(should-error (macroexpand
- '(when-let ((a 1 1))
+ '(when-let* ((a 1 1))
(- a)))
:type 'error))
-(ert-deftest subr-x-test-when-let-true ()
+(ert-deftest subr-x-test-when-let*-true ()
"Test `when-let' with truthy bindings."
(should (equal
- (when-let (a 1)
+ (when-let* ((a 1))
a)
1))
(should (equal
- (when-let ((a 1) (b 2) (c 3))
+ (when-let* ((a 1) (b 2) (c 3))
(list a b c))
(list 1 2 3))))
-(ert-deftest subr-x-test-when-let-false ()
+(ert-deftest subr-x-test-when-let*-false ()
"Test `when-let' with falsie bindings."
(should (equal
- (when-let (a nil)
+ (when-let* ((a nil))
(list a b c)
"no")
nil))
(should (equal
- (when-let ((a nil) (b 2) (c 3))
+ (when-let* ((a nil) (b 2) (c 3))
(list a b c)
"no")
nil))
(should (equal
- (when-let ((a 1) (b nil) (c 3))
+ (when-let* ((a 1) (b nil) (c 3))
(list a b c)
"no")
nil))
(should (equal
- (when-let ((a 1) (b 2) (c nil))
+ (when-let* ((a 1) (b 2) (c nil))
(list a b c)
"no")
nil))
(should (equal
- (when-let (z (a 1) (b 2) (c 3))
- (list a b c)
- "no")
+ (let (z)
+ (when-let* (z (a 1) (b 2) (c 3))
+ (list a b c)
+ "no"))
nil))
(should (equal
- (when-let ((a 1) (b 2) (c 3) d)
- (list a b c)
- "no")
+ (let (d)
+ (when-let* ((a 1) (b 2) (c 3) d)
+ (list a b c)
+ "no"))
nil)))
-(ert-deftest subr-x-test-when-let-bound-references ()
+(ert-deftest subr-x-test-when-let*-bound-references ()
"Test `when-let' bindings can refer to already bound symbols."
(should (equal
- (when-let ((a (1+ 0)) (b (1+ a)) (c (1+ b)))
+ (when-let* ((a (1+ 0)) (b (1+ a)) (c (1+ b)))
(list a b c))
(list 1 2 3))))
-(ert-deftest subr-x-test-when-let-and-laziness-is-preserved ()
+(ert-deftest subr-x-test-when-let*-and-laziness-is-preserved ()
"Test `when-let' respects `and' laziness."
(let (a-called b-called c-called)
(should (equal
(progn
- (when-let ((a nil)
- (b (setq b-called t))
- (c (setq c-called t)))
+ (when-let* ((a nil)
+ (b (setq b-called t))
+ (c (setq c-called t)))
"yes")
(list a-called b-called c-called))
(list nil nil nil))))
(let (a-called b-called c-called)
(should (equal
(progn
- (when-let ((a (setq a-called t))
- (b nil)
- (c (setq c-called t)))
+ (when-let* ((a (setq a-called t))
+ (b nil)
+ (c (setq c-called t)))
"yes")
(list a-called b-called c-called))
(list t nil nil))))
(let (a-called b-called c-called)
(should (equal
(progn
- (when-let ((a (setq a-called t))
- (b (setq b-called t))
- (c nil)
- (d (setq c-called t)))
+ (when-let* ((a (setq a-called t))
+ (b (setq b-called t))
+ (c nil)
+ (d (setq c-called t)))
"yes")
(list a-called b-called c-called))
(list t t nil)))))
+;; `and-let*' tests
+
+;; Adapted from the Guile tests
+;; https://git.savannah.gnu.org/cgit/guile.git/tree/test-suite/tests/srfi-2.test
+
+(ert-deftest subr-x-and-let*-test-empty-varlist ()
+ (should (equal 1 (and-let* () 1)))
+ (should (equal 2 (and-let* () 1 2)))
+ (should (equal t (and-let* ()))))
+
+(ert-deftest subr-x-and-let*-test-group-1 ()
+ (should (equal nil (let ((x nil)) (and-let* (x)))))
+ (should (equal 1 (let ((x 1)) (and-let* (x)))))
+ (should (equal nil (and-let* ((x nil)))))
+ (should (equal 1 (and-let* ((x 1)))))
+ ;; The error doesn't trigger when compiled: the compiler will give
+ ;; a warning and then drop the erroneous code. Therefore, use
+ ;; `eval' to avoid compilation.
+ (should-error (eval '(and-let* (nil (x 1))) lexical-binding)
+ :type 'setting-constant)
+ (should (equal nil (and-let* ((nil) (x 1)))))
+ (should-error (eval '(and-let* (2 (x 1))) lexical-binding)
+ :type 'wrong-type-argument)
+ (should (equal 1 (and-let* ((2) (x 1)))))
+ (should (equal 2 (and-let* ((x 1) (2)))))
+ (should (equal nil (let ((x nil)) (and-let* (x) x))))
+ (should (equal "" (let ((x "")) (and-let* (x) x))))
+ (should (equal "" (let ((x "")) (and-let* (x)))))
+ (should (equal 2 (let ((x 1)) (and-let* (x) (+ x 1)))))
+ (should (equal nil (let ((x nil)) (and-let* (x) (+ x 1)))))
+ (should (equal 2 (let ((x 1)) (and-let* (((> x 0))) (+ x 1)))))
+ (should (equal t (let ((x 1)) (and-let* (((> x 0)))))))
+ (should (equal nil (let ((x 0)) (and-let* (((> x 0))) (+ x 1)))))
+ (should (equal 3
+ (let ((x 1)) (and-let* (((> x 0)) (x (+ x 1))) (+ x 1))))))
+
+(ert-deftest subr-x-and-let*-test-rebind ()
+ (should
+ (equal 4
+ (let ((x 1))
+ (and-let* (((> x 0)) (x (+ x 1)) (x (+ x 1))) (+ x 1))))))
+
+(ert-deftest subr-x-and-let*-test-group-2 ()
+ (should
+ (equal 2 (let ((x 1)) (and-let* (x ((> x 0))) (+ x 1)))))
+ (should
+ (equal 2 (let ((x 1)) (and-let* (((progn x)) ((> x 0))) (+ x 1)))))
+ (should (equal nil (let ((x 0)) (and-let* (x ((> x 0))) (+ x 1)))))
+ (should (equal nil (let ((x nil)) (and-let* (x ((> x 0))) (+ x 1)))))
+ (should
+ (equal nil (let ((x nil)) (and-let* (((progn x)) ((> x 0))) (+ x 1))))))
+
+(ert-deftest subr-x-and-let*-test-group-3 ()
+ (should
+ (equal nil (let ((x 1)) (and-let* (x (y (- x 1)) ((> y 0))) (/ x y)))))
+ (should
+ (equal nil (let ((x 0)) (and-let* (x (y (- x 1)) ((> y 0))) (/ x y)))))
+ (should
+ (equal nil
+ (let ((x nil)) (and-let* (x (y (- x 1)) ((> y 0))) (/ x y)))))
+ (should
+ (equal (/ 3.0 2)
+ (let ((x 3.0)) (and-let* (x (y (- x 1)) ((> y 0))) (/ x y))))))
+
+
+
;; Thread first tests
(ert-deftest subr-x-test-thread-first-no-forms ()
diff --git a/test/lisp/emacs-lisp/tabulated-list-test.el b/test/lisp/emacs-lisp/tabulated-list-test.el
index b3a09ee375c..30a4f8f61b4 100644
--- a/test/lisp/emacs-lisp/tabulated-list-test.el
+++ b/test/lisp/emacs-lisp/tabulated-list-test.el
@@ -17,7 +17,7 @@
;; 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/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Code:
diff --git a/test/lisp/emacs-lisp/testcover-resources/testcases.el b/test/lisp/emacs-lisp/testcover-resources/testcases.el
index 1eb791a993c..6a9612db05a 100644
--- a/test/lisp/emacs-lisp/testcover-resources/testcases.el
+++ b/test/lisp/emacs-lisp/testcover-resources/testcases.el
@@ -17,7 +17,7 @@
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see `http://www.gnu.org/licenses/'.
+;; along with this program. If not, see `https://www.gnu.org/licenses/'.
;;; Commentary:
@@ -53,7 +53,6 @@
;; ==== constants-bug-25316 ====
"Testcover doesn't splotch constants."
-:expected-result :failed
;; ====
(defconst testcover-testcase-const "apples")
(defun testcover-testcase-zero () 0)
@@ -76,7 +75,6 @@
;; ==== customize-defcustom-bug-25326 ====
"Testcover doesn't prevent testing of defcustom values."
-:expected-result :failed
;; ====
(defgroup testcover-testcase nil
"Test case for testcover"
@@ -135,7 +133,6 @@
;; ==== 1-value-symbol-bug-25316 ====
"Wrapping a form with 1value prevents splotching."
-:expected-result :failed
;; ====
(defun testcover-testcase-always-zero (num)
(- num%%% num%%%)%%%)
@@ -230,7 +227,6 @@
;; ==== quotes-within-backquotes-bug-25316 ====
"Forms to instrument are found within quotes within backquotes."
-:expected-result :failed
;; ====
(defun testcover-testcase-make-list ()
(list 'defun 'defvar))
@@ -296,7 +292,6 @@
;; ==== backquote-1value-bug-24509 ====
"Commas within backquotes are recognized as non-1value."
-:expected-result :failed
;; ====
(defmacro testcover-testcase-lambda (&rest body)
`(lambda () ,@body))
@@ -320,7 +315,6 @@
;; ==== pcase-bug-24688 ====
"Testcover copes with condition-case within backquoted list."
-:expected-result :failed
;; ====
(defun testcover-testcase-pcase (form)
(pcase form%%%
@@ -335,7 +329,6 @@
;; ==== defun-in-backquote-bug-11307-and-24743 ====
"Testcover handles defun forms within backquoted list."
-:expected-result :failed
;; ====
(defmacro testcover-testcase-defun (name &rest body)
(declare (debug (symbolp def-body)))
@@ -348,7 +341,6 @@
;; ==== closure-1value-bug ====
"Testcover does not mark closures as 1value."
-:expected-result :failed
;; ====
;; -*- lexical-binding:t -*-
(setq testcover-testcase-foo nil)
@@ -365,7 +357,6 @@
;; ==== by-value-vs-by-reference-bug-25351 ====
"An object created by a 1value expression may be modified by other code."
-:expected-result :failed
;; ====
(defun testcover-testcase-ab ()
(list 'a 'b))
@@ -396,9 +387,16 @@
(should (equal '(a b c) (testcover-testcase-dotted-bq nil '(d e))))
(should (equal '(a b c d e) (testcover-testcase-dotted-bq t '(d e))))
+;; ==== quoted-backquote ====
+"Testcover correctly instruments the quoted backquote symbol."
+;; ====
+(defun testcover-testcase-special-symbols ()
+ (list '\` '\, '\,@))
+
+(should (equal '(\` \, \,@) (testcover-testcase-special-symbols)))
+
;; ==== backquoted-vector-bug-25316 ====
"Testcover reinstruments within backquoted vectors."
-:expected-result :failed
;; ====
(defun testcover-testcase-vec (a b c)
`[,a%%% ,(list b%%% c%%%)%%%]%%%)
@@ -415,7 +413,6 @@
;; ==== vector-in-macro-spec-bug-25316 ====
"Testcover reinstruments within vectors."
-:expected-result :failed
;; ====
(defmacro testcover-testcase-nth-case (arg vec)
(declare (indent 1)
@@ -435,7 +432,6 @@
;; ==== mapcar-is-not-compose ====
"Mapcar with 1value arguments is not 1value."
-:expected-result :failed
;; ====
(defvar testcover-testcase-num 0)
(defun testcover-testcase-add-num (n)
@@ -450,10 +446,10 @@
;; ==== function-with-edebug-spec-bug-25316 ====
"Functions can have edebug specs too.
-See c-make-font-lock-search-function for an example in the Emacs
-sources. The other issue is that it's ok to use quote in an
-edebug spec, so testcover needs to cope with that."
-:expected-result :failed
+See `c-make-font-lock-search-function' for an example in the
+Emacs sources. `c-make-font-lock-search-function''s Edebug spec
+also contains a quote. See comment in `testcover-analyze-coverage'
+regarding the odd-looking coverage result for the quoted form."
;; ====
(defun testcover-testcase-make-function (forms)
`(lambda (flag) (if flag 0 ,@forms%%%))%%%)
@@ -462,7 +458,7 @@ edebug spec, so testcover needs to cope with that."
(("quote" (&rest def-form))))
(defun testcover-testcase-thing ()
- (testcover-testcase-make-function '((+ 1 (+ 2 (+ 3 (+ 4 5))))))%%%)
+ (testcover-testcase-make-function '(!!!(+ 1 !!!(+ 2 !!!(+ 3 !!!(+ 4 5)%%%)%%%)%%%)%%%))%%%)
(defun testcover-testcase-use-thing ()
(funcall (testcover-testcase-thing)%%% nil)%%%)
@@ -490,4 +486,22 @@ edebug spec, so testcover needs to cope with that."
(should (eq (testcover-testcase-how-do-i-know-you "Liz") 'unknown))
+;; ==== circular-lists-bug-24402 ====
+"Testcover captures and ignores circular list errors."
+;; ====
+(defun testcover-testcase-cyc1 (a)
+ (let ((ls (make-list 10 a%%%)%%%))
+ (nconc ls%%% ls%%%)
+ ls)) ; The lack of a mark here is due to an ignored circular list error.
+(testcover-testcase-cyc1 1)
+(testcover-testcase-cyc1 1)
+(defun testcover-testcase-cyc2 (a b)
+ (let ((ls1 (make-list 10 a%%%)%%%)
+ (ls2 (make-list 10 b)))
+ (nconc ls2 ls2)
+ (nconc ls1%%% ls2)
+ ls1))
+(testcover-testcase-cyc2 1 2)
+(testcover-testcase-cyc2 1 4)
+
;; testcases.el ends here.
diff --git a/test/lisp/emacs-lisp/testcover-tests.el b/test/lisp/emacs-lisp/testcover-tests.el
index d31379c3aa2..2e03488b306 100644
--- a/test/lisp/emacs-lisp/testcover-tests.el
+++ b/test/lisp/emacs-lisp/testcover-tests.el
@@ -17,7 +17,7 @@
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see `http://www.gnu.org/licenses/'.
+;; along with this program. If not, see `https://www.gnu.org/licenses/'.
;;; Commentary:
@@ -124,14 +124,12 @@ arguments for `testcover-start'."
(save-current-buffer
(set-buffer (find-file-noselect tempfile))
;; Fail the test if the debugger tries to become active,
- ;; which will happen if Testcover's reinstrumentation
- ;; leaves an edebug-enter in the code. This will also
- ;; prevent debugging these tests using Edebug.
- (cl-letf (((symbol-function #'edebug-enter)
+ ;; which can happen if Testcover fails to attach itself
+ ;; correctly. Note that this will prevent debugging
+ ;; these tests using Edebug.
+ (cl-letf (((symbol-function #'edebug-default-enter)
(lambda (&rest _args)
- (ert-fail
- (concat "Debugger invoked during test run "
- "(possible edebug-enter not replaced)")))))
+ (ert-fail "Debugger invoked during test run"))))
(dolist (byte-compile '(t nil))
(testcover-tests-unmarkup-region (point-min) (point-max))
(unwind-protect
diff --git a/test/lisp/emacs-lisp/thunk-tests.el b/test/lisp/emacs-lisp/thunk-tests.el
index 89bf1f50113..a63ce289e8a 100644
--- a/test/lisp/emacs-lisp/thunk-tests.el
+++ b/test/lisp/emacs-lisp/thunk-tests.el
@@ -18,7 +18,7 @@
;; 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/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@@ -51,5 +51,55 @@
(thunk-force thunk)
(should (= x 1))))
+
+
+;; thunk-let tests
+
+(ert-deftest thunk-let-basic-test ()
+ "Test whether bindings are established."
+ (should (equal (thunk-let ((x 1) (y 2)) (+ x y)) 3)))
+
+(ert-deftest thunk-let*-basic-test ()
+ "Test whether bindings are established."
+ (should (equal (thunk-let* ((x 1) (y (+ 1 x))) (+ x y)) 3)))
+
+(ert-deftest thunk-let-bound-vars-cant-be-set-test ()
+ "Test whether setting a `thunk-let' bound variable fails."
+ (should-error
+ (eval '(thunk-let ((x 1)) (let ((y 7)) (setq x (+ x y)) (* 10 x))) t)))
+
+(ert-deftest thunk-let-laziness-test ()
+ "Test laziness of `thunk-let'."
+ (should
+ (equal (let ((x-evalled nil)
+ (y-evalled nil))
+ (thunk-let ((x (progn (setq x-evalled t) (+ 1 2)))
+ (y (progn (setq y-evalled t) (+ 3 4))))
+ (let ((evalled-y y))
+ (list x-evalled y-evalled evalled-y))))
+ (list nil t 7))))
+
+(ert-deftest thunk-let*-laziness-test ()
+ "Test laziness of `thunk-let*'."
+ (should
+ (equal (let ((x-evalled nil)
+ (y-evalled nil)
+ (z-evalled nil)
+ (a-evalled nil))
+ (thunk-let* ((x (progn (setq x-evalled t) (+ 1 1)))
+ (y (progn (setq y-evalled t) (+ x 1)))
+ (z (progn (setq z-evalled t) (+ y 1)))
+ (a (progn (setq a-evalled t) (+ z 1))))
+ (let ((evalled-z z))
+ (list x-evalled y-evalled z-evalled a-evalled evalled-z))))
+ (list t t t nil 4))))
+
+(ert-deftest thunk-let-bad-binding-test ()
+ "Test whether a bad binding causes an error when expanding."
+ (should-error (macroexpand '(thunk-let ((x 1 1)) x)))
+ (should-error (macroexpand '(thunk-let (27) x)))
+ (should-error (macroexpand '(thunk-let x x))))
+
+
(provide 'thunk-tests)
;;; thunk-tests.el ends here
diff --git a/test/lisp/emacs-lisp/timer-tests.el b/test/lisp/emacs-lisp/timer-tests.el
index b12a365ff3b..916625cac3a 100644
--- a/test/lisp/emacs-lisp/timer-tests.el
+++ b/test/lisp/emacs-lisp/timer-tests.el
@@ -15,7 +15,7 @@
;; 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/>.
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary: