aboutsummaryrefslogtreecommitdiffstats
path: root/test/src/eval-tests.el
diff options
context:
space:
mode:
Diffstat (limited to 'test/src/eval-tests.el')
-rw-r--r--test/src/eval-tests.el206
1 files changed, 187 insertions, 19 deletions
diff --git a/test/src/eval-tests.el b/test/src/eval-tests.el
index 7ff60dd01c4..bb2f04e8ee1 100644
--- a/test/src/eval-tests.el
+++ b/test/src/eval-tests.el
@@ -1,6 +1,6 @@
1;;; eval-tests.el --- unit tests for src/eval.c -*- lexical-binding: t; -*- 1;;; eval-tests.el --- unit tests for src/eval.c -*- lexical-binding: t; -*-
2 2
3;; Copyright (C) 2016-2017 Free Software Foundation, Inc. 3;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
4 4
5;; Author: Philipp Stephani <phst@google.com> 5;; Author: Philipp Stephani <phst@google.com>
6 6
@@ -26,28 +26,53 @@
26;;; Code: 26;;; Code:
27 27
28(require 'ert) 28(require 'ert)
29(eval-when-compile (require 'cl-lib))
30(require 'subr-x)
29 31
30(ert-deftest eval-tests--bug24673 () 32(ert-deftest eval-tests--bug24673 ()
31 "Checks that Bug#24673 has been fixed." 33 "Check that Bug#24673 has been fixed."
32 ;; This should not crash. 34 ;; This should not crash.
33 (should-error (funcall '(closure)) :type 'invalid-function)) 35 (should-error (funcall '(closure)) :type 'invalid-function))
34 36
35(defvar byte-compile-debug) 37(defvar byte-compile-debug)
36 38
37(ert-deftest eval-tests--bugs-24912-and-24913 () 39(ert-deftest eval-tests--bugs-24912-and-24913 ()
38 "Checks that Emacs doesnt accept weird argument lists. 40 "Check that Emacs doesn't accept weird argument lists.
39Bug#24912 and Bug#24913." 41Bug#24912 and Bug#24913."
40 (dolist (args '((&optional) (&rest) (&optional &rest) (&rest &optional) 42 (dolist (lb '(t false))
41 (&optional &rest a) (&optional a &rest) 43 (ert-info ((prin1-to-string lb) :prefix "lexical-binding: ")
42 (&rest a &optional) (&rest &optional a) 44 (let ((lexical-binding lb))
43 (&optional &optional) (&optional &optional a) 45 (dolist (args '((&rest &optional)
44 (&optional a &optional b) 46 (&rest a &optional) (&rest &optional a)
45 (&rest &rest) (&rest &rest a) 47 (&optional &optional) (&optional &optional a)
46 (&rest a &rest b))) 48 (&optional a &optional b)
47 (should-error (eval `(funcall (lambda ,args)) t) :type 'invalid-function) 49 (&rest &rest) (&rest &rest a)
48 (should-error (byte-compile-check-lambda-list args)) 50 (&rest a &rest b)
49 (let ((byte-compile-debug t)) 51 (&rest) (&optional &rest)
50 (should-error (eval `(byte-compile (lambda ,args)) t))))) 52 ))
53 (ert-info ((prin1-to-string args) :prefix "args: ")
54 (should-error
55 (eval `(funcall (lambda ,args)) lb) :type 'invalid-function)
56 (should-error (byte-compile-check-lambda-list args))
57 (let ((byte-compile-debug t))
58 (should-error (eval `(byte-compile (lambda ,args)) lb)))))))))
59
60(ert-deftest eval-tests-accept-empty-optional ()
61 "Check that Emacs accepts empty &optional arglists.
62Bug#24912."
63 (dolist (lb '(t false))
64 (ert-info ((prin1-to-string lb) :prefix "lexical-binding: ")
65 (let ((lexical-binding lb))
66 (dolist (args '((&optional) (&optional &rest a)))
67 (ert-info ((prin1-to-string args) :prefix "args: ")
68 (let ((fun `(lambda ,args 'ok)))
69 (ert-info ("eval")
70 (should (eq (funcall (eval fun lb)) 'ok)))
71 (ert-info ("byte comp check")
72 (byte-compile-check-lambda-list args))
73 (ert-info ("bytecomp")
74 (let ((byte-compile-debug t))
75 (should (eq (funcall (byte-compile fun)) 'ok)))))))))))
51 76
52 77
53(dolist (form '(let let*)) 78(dolist (form '(let let*))
@@ -61,22 +86,165 @@ Bug#24912 and Bug#24913."
61 86
62(ert-deftest eval-tests--if-dot-string () 87(ert-deftest eval-tests--if-dot-string ()
63 "Check that Emacs rejects (if . \"string\")." 88 "Check that Emacs rejects (if . \"string\")."
64 (should-error (eval '(if . "abc")) :type 'wrong-type-argument) 89 (should-error (eval '(if . "abc") nil) :type 'wrong-type-argument)
90 (should-error (eval '(if . "abc") t) :type 'wrong-type-argument)
65 (let ((if-tail (list '(setcdr if-tail "abc") t))) 91 (let ((if-tail (list '(setcdr if-tail "abc") t)))
66 (should-error (eval (cons 'if if-tail)))) 92 (should-error (eval (cons 'if if-tail) nil) :type 'void-variable)
93 (should-error (eval (cons 'if if-tail) t) :type 'void-variable))
67 (let ((if-tail (list '(progn (setcdr if-tail "abc") nil) t))) 94 (let ((if-tail (list '(progn (setcdr if-tail "abc") nil) t)))
68 (should-error (eval (cons 'if if-tail))))) 95 (should-error (eval (cons 'if if-tail) nil) :type 'void-variable)
96 (should-error (eval (cons 'if if-tail) t) :type 'void-variable)))
69 97
70(ert-deftest eval-tests--let-with-circular-defs () 98(ert-deftest eval-tests--let-with-circular-defs ()
71 "Check that Emacs reports an error for (let VARS ...) when VARS is circular." 99 "Check that Emacs reports an error for (let VARS ...) when VARS is circular."
72 (let ((vars (list 'v))) 100 (let ((vars (list 'v)))
73 (setcdr vars vars) 101 (setcdr vars vars)
74 (dolist (let-sym '(let let*)) 102 (dolist (let-sym '(let let*))
75 (should-error (eval (list let-sym vars)))))) 103 (should-error (eval (list let-sym vars) nil)))))
76 104
77(ert-deftest eval-tests--mutating-cond () 105(ert-deftest eval-tests--mutating-cond ()
78 "Check that Emacs doesn't crash on a cond clause that mutates during eval." 106 "Check that Emacs doesn't crash on a cond clause that mutates during eval."
79 (let ((clauses (list '((progn (setcdr clauses "ouch") nil))))) 107 (let ((clauses (list '((progn (setcdr clauses "ouch") nil)))))
80 (should-error (eval (cons 'cond clauses))))) 108 (should-error (eval (cons 'cond clauses) nil))
109 (should-error (eval (cons 'cond clauses) t))))
110
111(ert-deftest defvar/bug31072 ()
112 "Check that Bug#31072 is fixed."
113 (should-error (eval '(defvar 1) t) :type 'wrong-type-argument))
114
115(ert-deftest defvaralias-overwrite-warning ()
116 "Test for Bug#5950."
117 (defvar eval-tests--foo)
118 (setq eval-tests--foo 2)
119 (defvar eval-tests--foo-alias)
120 (setq eval-tests--foo-alias 1)
121 (cl-letf (((symbol-function 'display-warning)
122 (lambda (type &rest _)
123 (throw 'got-warning type))))
124 ;; Warn if we lose a value through aliasing.
125 (should (equal
126 '(defvaralias losing-value eval-tests--foo-alias)
127 (catch 'got-warning
128 (defvaralias 'eval-tests--foo-alias 'eval-tests--foo))))
129 ;; Don't warn if we don't.
130 (makunbound 'eval-tests--foo-alias)
131 (should (eq 'no-warning
132 (catch 'got-warning
133 (defvaralias 'eval-tests--foo-alias 'eval-tests--foo)
134 'no-warning)))))
135
136(ert-deftest eval-tests-byte-code-being-evaluated-is-protected-from-gc ()
137 "Regression test for Bug#33014.
138Check that byte-compiled objects being executed by exec-byte-code
139are found on the stack and therefore not garbage collected."
140 (should (string= (eval-tests-33014-func)
141 "before after: ok foo: (e) bar: (a b c d e) baz: a bop: c")))
142
143(defvar eval-tests-33014-var "ok")
144(defun eval-tests-33014-func ()
145 "A function which has a non-trivial constants vector when byte-compiled."
146 (let ((result "before "))
147 (eval-tests-33014-redefine)
148 (garbage-collect)
149 (setq result (concat result (format "after: %s" eval-tests-33014-var)))
150 (let ((vals '(0 1 2 3))
151 (things '(a b c d e)))
152 (dolist (val vals)
153 (setq result
154 (concat result " "
155 (cond
156 ((= val 0) (format "foo: %s" (last things)))
157 ((= val 1) (format "bar: %s" things))
158 ((= val 2) (format "baz: %s" (car things)))
159 (t (format "bop: %s" (nth 2 things))))))))
160 result))
161
162(defun eval-tests-33014-redefine ()
163 "Remove the Lisp reference to the byte-compiled object."
164 (setf (symbol-function #'eval-tests-33014-func) nil))
165
166(ert-deftest eval-tests-19790-backquote-comma-dot-substitution ()
167 "Regression test for Bug#19790.
168Don't handle destructive splicing in backquote expressions (like
169in Common Lisp). Instead, make sure substitution in backquote
170expressions works for identifiers starting with period."
171 (should (equal (let ((.x 'identity)) (eval `(,.x 'ok) nil)) 'ok))
172 (should (equal (let ((.x 'identity)) (eval `(,.x 'ok) t)) 'ok)))
173
174(ert-deftest eval-tests/backtrace-in-batch-mode ()
175 (let ((emacs (expand-file-name invocation-name invocation-directory)))
176 (skip-unless (file-executable-p emacs))
177 (with-temp-buffer
178 (let ((status (call-process emacs nil t nil
179 "--quick" "--batch"
180 (concat "--eval="
181 (prin1-to-string
182 '(progn
183 (defun foo () (error "Boo"))
184 (foo)))))))
185 (should (natnump status))
186 (should-not (eql status 0)))
187 (goto-char (point-min))
188 (ert-info ((concat "Process output:\n" (buffer-string)))
189 (search-forward " foo()")
190 (search-forward " normal-top-level()")))))
191
192(ert-deftest eval-tests/backtrace-in-batch-mode/inhibit ()
193 (let ((emacs (expand-file-name invocation-name invocation-directory)))
194 (skip-unless (file-executable-p emacs))
195 (with-temp-buffer
196 (let ((status (call-process
197 emacs nil t nil
198 "--quick" "--batch"
199 (concat "--eval="
200 (prin1-to-string
201 '(progn
202 (defun foo () (error "Boo"))
203 (let ((backtrace-on-error-noninteractive nil))
204 (foo))))))))
205 (should (natnump status))
206 (should-not (eql status 0)))
207 (should (equal (string-trim (buffer-string)) "Boo")))))
208
209(ert-deftest eval-tests/backtrace-in-batch-mode/demoted-errors ()
210 (let ((emacs (expand-file-name invocation-name invocation-directory)))
211 (skip-unless (file-executable-p emacs))
212 (with-temp-buffer
213 (should (eql 0 (call-process emacs nil t nil
214 "--quick" "--batch"
215 (concat "--eval="
216 (prin1-to-string
217 '(with-demoted-errors "Error: %S"
218 (error "Boo")))))))
219 (goto-char (point-min))
220 (should (equal (string-trim (buffer-string))
221 "Error: (error \"Boo\")")))))
222
223(ert-deftest eval-tests/funcall-with-delayed-message ()
224 ;; Check that `funcall-with-delayed-message' displays its message before
225 ;; its function terminates iff the timeout is short enough.
226
227 ;; This also serves as regression test for bug#55628 where a short
228 ;; timeout was rounded up to the next whole second.
229 (dolist (params '((0.8 0.4)
230 (0.1 0.8)))
231 (let ((timeout (nth 0 params))
232 (work-time (nth 1 params)))
233 (ert-info ((prin1-to-string params) :prefix "params: ")
234 (with-current-buffer "*Messages*"
235 (let ((inhibit-read-only t))
236 (erase-buffer))
237 (let ((stop (+ (float-time) work-time)))
238 (funcall-with-delayed-message
239 timeout "timed out"
240 (lambda ()
241 (while (< (float-time) stop))
242 (message "finished"))))
243 (let ((expected-messages
244 (if (< timeout work-time)
245 "timed out\nfinished"
246 "finished")))
247 (should (equal (string-trim (buffer-string))
248 expected-messages))))))))
81 249
82;;; eval-tests.el ends here 250;;; eval-tests.el ends here