aboutsummaryrefslogtreecommitdiffstats
path: root/test/src
diff options
context:
space:
mode:
authorStefan Monnier2022-09-25 16:15:16 -0400
committerStefan Monnier2022-09-25 16:15:16 -0400
commit650c20f1ca4e07591a727e1cfcc74b3363d15985 (patch)
tree85d11f6437cde22f410c25e0e5f71a3131ebd07d /test/src
parent8869332684c2302b5ba1ead4568bbc7ba1c0183e (diff)
parent4b85ae6a24380fb67a3315eaec9233f17a872473 (diff)
downloademacs-650c20f1ca4e07591a727e1cfcc74b3363d15985.tar.gz
emacs-650c20f1ca4e07591a727e1cfcc74b3363d15985.zip
Merge 'master' into noverlay
Diffstat (limited to 'test/src')
-rw-r--r--test/src/alloc-tests.el13
-rw-r--r--test/src/buffer-tests.el823
-rw-r--r--test/src/callint-tests.el68
-rw-r--r--test/src/callproc-tests.el42
-rw-r--r--test/src/casefiddle-tests.el46
-rw-r--r--test/src/character-tests.el47
-rw-r--r--test/src/charset-tests.el16
-rw-r--r--test/src/chartab-tests.el32
-rw-r--r--test/src/cmds-tests.el20
-rw-r--r--test/src/coding-tests.el97
-rw-r--r--test/src/comp-resources/comp-test-45603.el29
-rw-r--r--test/src/comp-resources/comp-test-funcs-dyn.el50
-rw-r--r--test/src/comp-resources/comp-test-funcs.el713
-rw-r--r--test/src/comp-resources/comp-test-pure.el40
-rw-r--r--test/src/comp-tests.el1480
-rw-r--r--test/src/data-tests.el344
-rw-r--r--test/src/decompress-tests.el28
-rw-r--r--test/src/doc-tests.el89
-rw-r--r--test/src/editfns-tests.el319
-rw-r--r--test/src/emacs-module-resources/mod-test.c868
-rw-r--r--test/src/emacs-module-tests.el425
-rw-r--r--test/src/emacs-tests.el249
-rw-r--r--test/src/eval-tests.el206
-rw-r--r--test/src/fileio-tests.el127
-rw-r--r--test/src/filelock-tests.el217
-rw-r--r--test/src/floatfns-tests.el168
-rw-r--r--test/src/fns-tests.el1059
-rw-r--r--test/src/font-tests.el34
-rw-r--r--test/src/image-tests.el69
-rw-r--r--test/src/indent-tests.el61
-rw-r--r--test/src/inotify-tests.el39
-rw-r--r--test/src/json-tests.el343
-rw-r--r--test/src/keyboard-tests.el74
-rw-r--r--test/src/keymap-tests.el403
-rw-r--r--test/src/lcms-tests.el13
-rw-r--r--test/src/lread-resources/lazydoc.elbin0 -> 171 bytes
-rw-r--r--test/src/lread-resources/somelib.el7
-rw-r--r--test/src/lread-resources/somelib2.el7
-rw-r--r--test/src/lread-tests.el242
-rw-r--r--test/src/marker-tests.el4
-rw-r--r--test/src/minibuf-tests.el28
-rw-r--r--test/src/print-tests.el498
-rw-r--r--test/src/process-tests.el991
-rw-r--r--test/src/regex-emacs-tests.el (renamed from test/src/regex-tests.el)256
-rw-r--r--test/src/regex-resources/BOOST.tests4
-rw-r--r--test/src/search-tests.el42
-rw-r--r--test/src/sqlite-tests.el244
-rw-r--r--test/src/syntax-resources/syntax-comments.txt94
-rw-r--r--test/src/syntax-tests.el441
-rw-r--r--test/src/textprop-tests.el6
-rw-r--r--test/src/thread-tests.el218
-rw-r--r--test/src/timefns-tests.el264
-rw-r--r--test/src/undo-tests.el55
-rw-r--r--test/src/xdisp-tests.el182
-rw-r--r--test/src/xfaces-tests.el57
-rw-r--r--test/src/xml-tests.el43
56 files changed, 11446 insertions, 888 deletions
diff --git a/test/src/alloc-tests.el b/test/src/alloc-tests.el
index aff480c6b66..967833e1903 100644
--- a/test/src/alloc-tests.el
+++ b/test/src/alloc-tests.el
@@ -1,6 +1,6 @@
1;;; alloc-tests.el --- alloc tests -*- lexical-binding: t -*- 1;;; alloc-tests.el --- alloc tests -*- lexical-binding: t -*-
2 2
3;; Copyright (C) 2015-2017 Free Software Foundation, Inc. 3;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
4 4
5;; Author: Daniel Colascione <dancol@dancol.org> 5;; Author: Daniel Colascione <dancol@dancol.org>
6;; Keywords: 6;; Keywords:
@@ -30,7 +30,7 @@
30(require 'cl-lib) 30(require 'cl-lib)
31 31
32(ert-deftest finalizer-object-type () 32(ert-deftest finalizer-object-type ()
33 (should (equal (type-of (make-finalizer nil)) 'finalizer))) 33 (should (equal (type-of (make-finalizer #'ignore)) 'finalizer)))
34 34
35(ert-deftest record-1 () 35(ert-deftest record-1 ()
36 (let ((x (record 'foo 1 2 3))) 36 (let ((x (record 'foo 1 2 3)))
@@ -51,3 +51,12 @@
51 (should-not (eq x y)) 51 (should-not (eq x y))
52 (dotimes (i 4) 52 (dotimes (i 4)
53 (should (eql (aref x i) (aref y i)))))) 53 (should (eql (aref x i) (aref y i))))))
54
55;; Bug#39207
56(ert-deftest aset-nbytes-change ()
57 (let ((s (make-string 1 ?a)))
58 (dolist (c (list 10003 ?b 128 ?c ?d (max-char) ?e))
59 (aset s 0 c)
60 (should (equal s (make-string 1 c))))))
61
62;;; alloc-tests.el ends here
diff --git a/test/src/buffer-tests.el b/test/src/buffer-tests.el
index 153aea3a20b..a12d15bc798 100644
--- a/test/src/buffer-tests.el
+++ b/test/src/buffer-tests.el
@@ -1,6 +1,6 @@
1;;; buffer-tests.el --- tests for buffer.c functions -*- lexical-binding: t -*- 1;;; buffer-tests.el --- tests for buffer.c functions -*- lexical-binding: t -*-
2 2
3;; Copyright (C) 2015-2017 Free Software Foundation, Inc. 3;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
4 4
5;; This file is part of GNU Emacs. 5;; This file is part of GNU Emacs.
6 6
@@ -21,6 +21,201 @@
21 21
22(require 'ert) 22(require 'ert)
23(require 'seq) 23(require 'seq)
24(require 'ert-x)
25(require 'cl-lib)
26(require 'let-alist)
27
28(defun overlay-tests-start-recording-modification-hooks (overlay)
29 "Start recording modification hooks on OVERLAY.
30
31Always overwrites the `insert-in-front-hooks',
32`modification-hooks' and `insert-behind-hooks' properties. Any
33recorded history from a previous call is erased.
34
35The history is stored in a property on the overlay itself. Call
36`overlay-tests-get-recorded-modification-hooks' to retrieve the
37recorded calls conveniently."
38 (dolist (hooks-property '(insert-in-front-hooks
39 modification-hooks
40 insert-behind-hooks))
41 (overlay-put
42 overlay
43 hooks-property
44 (list (lambda (ov &rest args)
45 (message " %S called on %S with args %S" hooks-property ov args)
46 (should inhibit-modification-hooks)
47 (should (eq ov overlay))
48 (push (list hooks-property args)
49 (overlay-get overlay
50 'recorded-modification-hook-calls)))))
51 (overlay-put overlay 'recorded-modification-hook-calls nil)))
52
53(defun overlay-tests-get-recorded-modification-hooks (overlay)
54 "Extract the recorded calls made to modification hooks on OVERLAY.
55
56Must be preceded by a call to
57`overlay-tests-start-recording-modification-hooks' on OVERLAY.
58
59Returns a list. Each element of the list represents a recorded
60call to a particular modification hook.
61
62Each call is itself a sub-list where the first element is a
63symbol matching the modification hook property (one of
64`insert-in-front-hooks', `modification-hooks' or
65`insert-behind-hooks') and the second element is the list of
66arguments passed to the hook. The first hook argument, the
67overlay itself, is omitted to make test result verification
68easier."
69 (reverse (overlay-get overlay
70 'recorded-modification-hook-calls)))
71
72(ert-deftest overlay-modification-hooks ()
73 "Test the basic functionality of overlay modification hooks.
74
75This exercises hooks registered on the `insert-in-front-hooks',
76`modification-hooks' and `insert-behind-hooks' overlay
77properties."
78 ;; This is a data driven test loop. Each test case is described
79 ;; by an alist. The test loop initializes a new temporary buffer
80 ;; for each case, creates an overlay, registers modification hooks
81 ;; on the overlay, modifies the buffer, and then verifies which
82 ;; modification hooks (if any) were called for the overlay, as
83 ;; well as which arguments were passed to the hooks.
84 ;;
85 ;; The following keys are available in the alist:
86 ;;
87 ;; `buffer-text': the initial buffer text of the temporary buffer.
88 ;; Defaults to "1234".
89 ;;
90 ;; `overlay-beg' and `overlay-end': the begin and end positions of
91 ;; the overlay under test. Defaults to 2 and 4 respectively.
92 ;;
93 ;; `insert-at': move to the given position and insert the string
94 ;; "x" into the test case's buffer.
95 ;;
96 ;; `replace': replace the first occurrence of the given string in
97 ;; the test case's buffer with "x". The test will fail if the
98 ;; string is not found.
99 ;;
100 ;; `expected-calls': a description of the expected buffer
101 ;; modification hooks. See
102 ;; `overlay-tests-get-recorded-modification-hooks' for the format.
103 ;; May be omitted, in which case the test will insist that no
104 ;; modification hooks are called.
105 ;;
106 ;; The test will fail itself in the degenerate case where no
107 ;; buffer modifications are requested.
108 (dolist (test-case
109 '(
110 ;; Remember that the default buffer text is "1234" and
111 ;; the default overlay begins at position 2 and ends at
112 ;; position 4. Most of the test cases below assume
113 ;; this.
114
115 ;; TODO: (info "(elisp) Special Properties") says this
116 ;; about `modification-hooks': "Furthermore, insertion
117 ;; will not modify any existing character, so this hook
118 ;; will only be run when removing some characters,
119 ;; replacing them with others, or changing their
120 ;; text-properties." So, why are modification-hooks
121 ;; being called when inserting at position 3 below?
122 ((insert-at . 1))
123 ((insert-at . 2)
124 (expected-calls . ((insert-in-front-hooks (nil 2 2))
125 (insert-in-front-hooks (t 2 3 0)))))
126 ((insert-at . 3)
127 (expected-calls . ((modification-hooks (nil 3 3))
128 (modification-hooks (t 3 4 0)))))
129 ((insert-at . 4)
130 (expected-calls . ((insert-behind-hooks (nil 4 4))
131 (insert-behind-hooks (t 4 5 0)))))
132 ((insert-at . 5))
133
134 ;; Replacing text never calls `insert-in-front-hooks'
135 ;; or `insert-behind-hooks'. It calls
136 ;; `modification-hooks' if the overlay covers any text
137 ;; that has changed.
138 ((replace . "1"))
139 ((replace . "2")
140 (expected-calls . ((modification-hooks (nil 2 3))
141 (modification-hooks (t 2 3 1)))))
142 ((replace . "3")
143 (expected-calls . ((modification-hooks (nil 3 4))
144 (modification-hooks (t 3 4 1)))))
145 ((replace . "4"))
146 ((replace . "12")
147 (expected-calls . ((modification-hooks (nil 1 3))
148 (modification-hooks (t 1 2 2)))))
149 ((replace . "23")
150 (expected-calls . ((modification-hooks (nil 2 4))
151 (modification-hooks (t 2 3 2)))))
152 ((replace . "34")
153 (expected-calls . ((modification-hooks (nil 3 5))
154 (modification-hooks (t 3 4 2)))))
155 ((replace . "123")
156 (expected-calls . ((modification-hooks (nil 1 4))
157 (modification-hooks (t 1 2 3)))))
158 ((replace . "234")
159 (expected-calls . ((modification-hooks (nil 2 5))
160 (modification-hooks (t 2 3 3)))))
161 ((replace . "1234")
162 (expected-calls . ((modification-hooks (nil 1 5))
163 (modification-hooks (t 1 2 4)))))
164
165 ;; Inserting at the position of a zero-length overlay
166 ;; calls both `insert-in-front-hooks' and
167 ;; `insert-behind-hooks'.
168 ((buffer-text . "") (overlay-beg . 1) (overlay-end . 1)
169 (insert-at . 1)
170 (expected-calls . ((insert-in-front-hooks
171 (nil 1 1))
172 (insert-behind-hooks
173 (nil 1 1))
174 (insert-in-front-hooks
175 (t 1 2 0))
176 (insert-behind-hooks
177 (t 1 2 0)))))))
178 (message "BEGIN overlay-modification-hooks test-case %S" test-case)
179
180 ;; All three hooks ignore the overlay's `front-advance' and
181 ;; `rear-advance' option, so test both ways while expecting the same
182 ;; result.
183 (dolist (advance '(nil t))
184 (message " advance is %S" advance)
185 (let-alist test-case
186 (with-temp-buffer
187 ;; Set up the temporary buffer and overlay as specified by
188 ;; the test case.
189 (insert (or .buffer-text "1234"))
190 (let ((overlay (make-overlay
191 (or .overlay-beg 2)
192 (or .overlay-end 4)
193 nil
194 advance advance)))
195 (message " (buffer-string) is %S" (buffer-string))
196 (message " overlay is %S" overlay)
197 (overlay-tests-start-recording-modification-hooks overlay)
198
199 ;; Modify the buffer, possibly inducing calls to the
200 ;; overlay's modification hooks.
201 (should (or .insert-at .replace))
202 (when .insert-at
203 (goto-char .insert-at)
204 (insert "x")
205 (message " inserted \"x\" at %S, buffer-string now %S"
206 .insert-at (buffer-string)))
207 (when .replace
208 (goto-char (point-min))
209 (search-forward .replace)
210 (replace-match "x")
211 (message " replaced %S with \"x\"" .replace))
212
213 ;; Verify that the expected and actual modification hook
214 ;; calls match.
215 (should (equal
216 .expected-calls
217 (overlay-tests-get-recorded-modification-hooks
218 overlay)))))))))
24 219
25(ert-deftest overlay-modification-hooks-message-other-buf () 220(ert-deftest overlay-modification-hooks-message-other-buf ()
26 "Test for bug#21824. 221 "Test for bug#21824.
@@ -46,34 +241,80 @@ with parameters from the *Messages* buffer modification."
46 (should (eq buf (current-buffer)))) 241 (should (eq buf (current-buffer))))
47 (when msg-ov (delete-overlay msg-ov)))))) 242 (when msg-ov (delete-overlay msg-ov))))))
48 243
244(ert-deftest overlay-modification-hooks-deleted-overlay ()
245 "Test for bug#30823."
246 (let ((check-point nil)
247 (ov-delete nil)
248 (ov-set nil))
249 (with-temp-buffer
250 (insert "abc")
251 (setq ov-set (make-overlay 1 3))
252 (overlay-put ov-set 'modification-hooks
253 (list (lambda (_o after &rest _args)
254 (and after (setq check-point t)))))
255 (setq ov-delete (make-overlay 1 3))
256 (overlay-put ov-delete 'modification-hooks
257 (list (lambda (o after &rest _args)
258 (and (not after) (delete-overlay o)))))
259 (goto-char 2)
260 (insert "1")
261 (should (eq check-point t)))))
262
49(ert-deftest test-generate-new-buffer-name-bug27966 () 263(ert-deftest test-generate-new-buffer-name-bug27966 ()
50 (should-not (string-equal "nil" 264 (should-not (string-equal "nil"
51 (progn (get-buffer-create "nil") 265 (progn (get-buffer-create "nil")
52 (generate-new-buffer-name "nil"))))) 266 (generate-new-buffer-name "nil")))))
53 267
54 268(ert-deftest test-buffer-base-buffer-indirect ()
55;; +===================================================================================+ 269 (with-temp-buffer
270 (let* ((ind-buf-name (generate-new-buffer-name "indbuf"))
271 (ind-buf (make-indirect-buffer (current-buffer) ind-buf-name)))
272 (should (eq (buffer-base-buffer ind-buf) (current-buffer))))))
273
274(ert-deftest test-buffer-base-buffer-non-indirect ()
275 (with-temp-buffer
276 (should (eq (buffer-base-buffer (current-buffer)) nil))))
277
278(ert-deftest overlay-evaporation-after-killed-buffer ()
279 (let* ((ols (with-temp-buffer
280 (insert "toto")
281 (list
282 (make-overlay (point-min) (point-max))
283 (make-overlay (point-min) (point-max))
284 (make-overlay (point-min) (point-max)))))
285 (ol (nth 1 ols)))
286 (overlay-put ol 'evaporate t)
287 ;; Evaporation within move-overlay of an overlay that was deleted because
288 ;; of a kill-buffer, triggered an assertion failure in unchain_both.
289 (with-temp-buffer
290 (insert "toto")
291 (move-overlay ol (point-min) (point-min)))))
292
293
294;; +==========================================================================+
56;; | Overlay test setup 295;; | Overlay test setup
57;; +===================================================================================+ 296;; +==========================================================================+
58 297
59(eval-when-compile 298(eval-and-compile
60 (defun make-overlay-test-name (fn x y) 299 (defun buffer-tests--make-test-name (fn x y)
61 (intern (format "test-%s-%s-%s" fn x y)))) 300 (intern (format "buffer-tests--%s-%s-%s" fn x y))))
62 301
63(defun unmake-ov-test-name (symbol) 302(defun buffer-tests--unmake-test-name (symbol)
64 (let ((name (if (stringp symbol) symbol (symbol-name symbol)))) 303 (let ((name (if (stringp symbol) symbol (symbol-name symbol))))
65 (when (string-match "\\`test-\\(.*\\)-\\(.*\\)-\\(.*\\)\\'" name) 304 (when (string-match "\\`buffer-tests--\\(.*\\)-\\(.*\\)-\\(.*\\)\\'" name)
66 (list (match-string 1 name) (match-string 2 name) (match-string 3 name))))) 305 (list (match-string 1 name)
306 (match-string 2 name)
307 (match-string 3 name)))))
67 308
68(defmacro deftest-make-overlay-1 (id args) 309(defmacro deftest-make-overlay-1 (id args)
69 (declare (indent 1)) 310 (declare (indent 1))
70 `(ert-deftest ,(make-overlay-test-name 'make-overlay 1 id) () 311 `(ert-deftest ,(buffer-tests--make-test-name 'make-overlay 1 id) ()
71 (with-temp-buffer 312 (with-temp-buffer
72 (should ,(cons 'make-overlay args))))) 313 (should ,(cons 'make-overlay args)))))
73 314
74(defmacro deftest-make-overlay-2 (id args condition) 315(defmacro deftest-make-overlay-2 (id args condition)
75 (declare (indent 1)) 316 (declare (indent 1))
76 `(ert-deftest ,(make-overlay-test-name 'make-overlay 2 id) () 317 `(ert-deftest ,(buffer-tests--make-test-name 'make-overlay 2 id) ()
77 (with-temp-buffer 318 (with-temp-buffer
78 (should-error 319 (should-error
79 ,(cons 'make-overlay args) 320 ,(cons 'make-overlay args)
@@ -84,7 +325,7 @@ with parameters from the *Messages* buffer modification."
84 (declare (indent 1)) 325 (declare (indent 1))
85 (cl-destructuring-bind (start end sstart send) 326 (cl-destructuring-bind (start end sstart send)
86 (append start-end-args start-end-should) 327 (append start-end-args start-end-should)
87 `(ert-deftest ,(make-overlay-test-name 'overlay-start/end 1 id) () 328 `(ert-deftest ,(buffer-tests--make-test-name 'overlay-start/end 1 id) ()
88 (with-temp-buffer 329 (with-temp-buffer
89 (insert (make-string 9 ?\n)) 330 (insert (make-string 9 ?\n))
90 (let ((ov (make-overlay ,start ,end))) 331 (let ((ov (make-overlay ,start ,end)))
@@ -93,25 +334,26 @@ with parameters from the *Messages* buffer modification."
93 334
94(defmacro deftest-overlay-buffer-1 (id arg-expr should-expr) 335(defmacro deftest-overlay-buffer-1 (id arg-expr should-expr)
95 (declare (indent 1)) 336 (declare (indent 1))
96 `(ert-deftest ,(make-overlay-test-name 'overlay-buffer 1 id) () 337 `(ert-deftest ,(buffer-tests--make-test-name 'overlay-buffer 1 id) ()
97 (with-temp-buffer 338 (with-temp-buffer
98 (should (equal (overlay-buffer (make-overlay 1 1 ,arg-expr)) 339 (should (equal (overlay-buffer (make-overlay 1 1 ,arg-expr))
99 ,should-expr))))) 340 ,should-expr)))))
100 341
101(defmacro deftest-overlayp-1 (id arg-expr should-expr) 342(defmacro deftest-overlayp-1 (id arg-expr should-expr)
102 (declare (indent 1)) 343 (declare (indent 1))
103 `(ert-deftest ,(make-overlay-test-name 'overlay-buffer 1 id) () 344 `(ert-deftest ,(buffer-tests--make-test-name 'overlayp 1 id) ()
104 (with-temp-buffer 345 (with-temp-buffer
105 (should (equal ,should-expr (overlayp ,arg-expr)))))) 346 (should (equal ,should-expr (overlayp ,arg-expr))))))
106 347
107(defmacro deftest-next-overlay-change-1 (id pos result &rest ov-tuple) 348(defmacro deftest-next-overlay-change-1 (id pos result &rest ov-tuple)
108 `(ert-deftest ,(make-overlay-test-name 'next-overlay-change 1 id) () 349 `(ert-deftest ,(buffer-tests--make-test-name 'next-overlay-change 1 id) ()
109 (let ((tuple (copy-sequence ',ov-tuple))) 350 (let ((tuple (copy-sequence ',ov-tuple)))
110 (with-temp-buffer 351 (with-temp-buffer
111 (insert (make-string (max 100 (if tuple 352 (insert (make-string (max 100 (if tuple
112 (apply #'max 353 (apply #'max
113 (mapcar 354 (mapcar
114 (lambda (m) (apply #'max m)) tuple)) 355 (lambda (m) (apply #'max m))
356 tuple))
115 0)) 357 0))
116 ?\n)) 358 ?\n))
117 (dolist (tup tuple) 359 (dolist (tup tuple)
@@ -120,13 +362,14 @@ with parameters from the *Messages* buffer modification."
120 ,result)))))) 362 ,result))))))
121 363
122(defmacro deftest-previous-overlay-change-1 (id pos result &rest ov-tuple) 364(defmacro deftest-previous-overlay-change-1 (id pos result &rest ov-tuple)
123 `(ert-deftest ,(make-overlay-test-name 'previous-overlay-change 1 id) () 365 `(ert-deftest ,(buffer-tests--make-test-name 'previous-overlay-change 1 id) ()
124 (let ((tuple ',ov-tuple)) 366 (let ((tuple ',ov-tuple))
125 (with-temp-buffer 367 (with-temp-buffer
126 (insert (make-string (max 100 (if tuple 368 (insert (make-string (max 100 (if tuple
127 (apply #'max 369 (apply #'max
128 (mapcar 370 (mapcar
129 (lambda (m) (apply #'max m)) tuple)) 371 (lambda (m) (apply #'max m))
372 tuple))
130 0)) 373 0))
131 ?\n)) 374 ?\n))
132 (dolist (tup tuple) 375 (dolist (tup tuple)
@@ -135,7 +378,7 @@ with parameters from the *Messages* buffer modification."
135 ,result)))))) 378 ,result))))))
136 379
137(defmacro deftest-overlays-at-1 (id pos result &rest ov-triple) 380(defmacro deftest-overlays-at-1 (id pos result &rest ov-triple)
138 `(ert-deftest ,(make-overlay-test-name 'overlays-at 1 id) () 381 `(ert-deftest ,(buffer-tests--make-test-name 'overlays-at 1 id) ()
139 (let ((pos* ,pos)) 382 (let ((pos* ,pos))
140 (with-temp-buffer 383 (with-temp-buffer
141 (insert (make-string 100 ?\s)) 384 (insert (make-string 100 ?\s))
@@ -150,7 +393,7 @@ with parameters from the *Messages* buffer modification."
150 (should (memq (overlay-get ov 'tag) ',result)))))))) 393 (should (memq (overlay-get ov 'tag) ',result))))))))
151 394
152(defmacro deftest-overlays-in-1 (id beg end result &rest ov-triple) 395(defmacro deftest-overlays-in-1 (id beg end result &rest ov-triple)
153 `(ert-deftest ,(make-overlay-test-name 'overlays-in 1 id) () 396 `(ert-deftest ,(buffer-tests--make-test-name 'overlays-in 1 id) ()
154 (let ((beg* ,beg) 397 (let ((beg* ,beg)
155 (end* ,end)) 398 (end* ,end))
156 (with-temp-buffer 399 (with-temp-buffer
@@ -176,39 +419,42 @@ with parameters from the *Messages* buffer modification."
176 ,@body)))) 419 ,@body))))
177 420
178(defmacro deftest-overlays-equal-1 (id result ov1-args ov2-args) 421(defmacro deftest-overlays-equal-1 (id result ov1-args ov2-args)
179 `(ert-deftest ,(make-overlay-test-name 'overlays-equal 1 id) () 422 `(ert-deftest ,(buffer-tests--make-test-name 'overlays-equal 1 id) ()
180 (cl-labels ((create-overlay (args) 423 (cl-flet ((create-overlay (args)
181 (cl-destructuring-bind (start end &optional fa ra &rest properties) 424 (cl-destructuring-bind (start end &optional fa ra
182 args 425 &rest properties)
183 (let ((ov (make-overlay start end nil fa ra))) 426 args
184 (while properties 427 (let ((ov (make-overlay start end nil fa ra)))
185 (overlay-put ov (pop properties) (pop properties))) 428 (while properties
186 ov)))) 429 (overlay-put ov (pop properties) (pop properties)))
430 ov))))
187 (with-temp-buffer 431 (with-temp-buffer
188 (insert (make-string 1024 ?\s)) 432 (insert (make-string 1024 ?\s))
189 (should (,(if result 'identity 'not) 433 (should (,(if result 'identity 'not)
190 (equal (create-overlay ',ov1-args) 434 (equal (create-overlay ',ov1-args)
191 (create-overlay ',ov2-args)))))))) 435 (create-overlay ',ov2-args))))))))
192
193 436
194(defun find-ert-overlay-test (name) 437
195 (let ((test (unmake-ov-test-name name))) 438(defun buffer-tests--find-ert-test (name)
439 (let ((test (buffer-tests--unmake-test-name name)))
196 (or (and test 440 (or (and test
197 (cl-destructuring-bind (fn x y) 441 (cl-destructuring-bind (fn x y)
198 test 442 test
199 (let ((regexp (format "deftest-%s-%s +%s" fn x y))) 443 (let ((regexp (format "deftest-%s-%s +%s" fn x y)))
200 (re-search-forward regexp nil t)))) 444 (re-search-forward regexp nil t))))
201 (let ((find-function-regexp-alist 445 (let ((find-function-regexp-alist
202 (cl-remove 'find-ert-overlay-test find-function-regexp-alist :key #'cdr))) 446 (cl-remove #'buffer-tests--find-ert-test
203 (find-function-do-it name 'ert-deftest 'switch-to-buffer-other-window))))) 447 find-function-regexp-alist :key #'cdr)))
448 (find-function-do-it name 'ert-deftest
449 #'switch-to-buffer-other-window)))))
204 450
205(add-to-list 'find-function-regexp-alist 451(add-to-list 'find-function-regexp-alist
206 '(ert-deftest . find-ert-overlay-test)) 452 `(ert-deftest . ,#'buffer-tests--find-ert-test))
207 453
208 454
209;; +===================================================================================+ 455;; +==========================================================================+
210;; | make-overlay 456;; | make-overlay
211;; +===================================================================================+ 457;; +==========================================================================+
212 458
213;; Test if making an overlay succeeds. 459;; Test if making an overlay succeeds.
214(deftest-make-overlay-1 A (1 1)) 460(deftest-make-overlay-1 A (1 1))
@@ -237,12 +483,12 @@ with parameters from the *Messages* buffer modification."
237(deftest-make-overlay-2 I (1 [1]) wrong-type-argument) 483(deftest-make-overlay-2 I (1 [1]) wrong-type-argument)
238(deftest-make-overlay-2 J (1 1 (with-temp-buffer 484(deftest-make-overlay-2 J (1 1 (with-temp-buffer
239 (current-buffer))) 485 (current-buffer)))
240 error) 486 error)
241 487
242 488
243;; +===================================================================================+ 489;; +==========================================================================+
244;; | overlay-start/end 490;; | overlay-start/end
245;; +===================================================================================+ 491;; +==========================================================================+
246 492
247;; Test if the overlays return proper positions. point-max of the 493;; Test if the overlays return proper positions. point-max of the
248;; buffer will equal 10. ARG RESULT 494;; buffer will equal 10. ARG RESULT
@@ -253,7 +499,8 @@ with parameters from the *Messages* buffer modification."
253(deftest-overlay-start/end-1 E (1 11) (1 10)) 499(deftest-overlay-start/end-1 E (1 11) (1 10))
254(deftest-overlay-start/end-1 F (1 most-positive-fixnum) (1 10)) 500(deftest-overlay-start/end-1 F (1 most-positive-fixnum) (1 10))
255(deftest-overlay-start/end-1 G (most-positive-fixnum 1) (1 10)) 501(deftest-overlay-start/end-1 G (most-positive-fixnum 1) (1 10))
256(deftest-overlay-start/end-1 H (most-positive-fixnum most-positive-fixnum) (10 10)) 502(deftest-overlay-start/end-1 H (most-positive-fixnum most-positive-fixnum)
503 (10 10))
257(deftest-overlay-start/end-1 I (100 11) (10 10)) 504(deftest-overlay-start/end-1 I (100 11) (10 10))
258(deftest-overlay-start/end-1 J (11 100) (10 10)) 505(deftest-overlay-start/end-1 J (11 100) (10 10))
259(deftest-overlay-start/end-1 K (0 1) (1 1)) 506(deftest-overlay-start/end-1 K (0 1) (1 1))
@@ -264,10 +511,10 @@ with parameters from the *Messages* buffer modification."
264 (should-not (overlay-start (with-temp-buffer (make-overlay 1 1)))) 511 (should-not (overlay-start (with-temp-buffer (make-overlay 1 1))))
265 (should-not (overlay-end (with-temp-buffer (make-overlay 1 1))))) 512 (should-not (overlay-end (with-temp-buffer (make-overlay 1 1)))))
266 513
267 514
268;; +===================================================================================+ 515;; +==========================================================================+
269;; | overlay-buffer 516;; | overlay-buffer
270;; +===================================================================================+ 517;; +==========================================================================+
271 518
272;; Test if overlay-buffer returns appropriate values. 519;; Test if overlay-buffer returns appropriate values.
273(deftest-overlay-buffer-1 A (current-buffer) (current-buffer)) 520(deftest-overlay-buffer-1 A (current-buffer) (current-buffer))
@@ -276,10 +523,10 @@ with parameters from the *Messages* buffer modification."
276 (should-error (make-overlay 523 (should-error (make-overlay
277 1 1 (with-temp-buffer (current-buffer))))) 524 1 1 (with-temp-buffer (current-buffer)))))
278 525
279 526
280;; +===================================================================================+ 527;; +==========================================================================+
281;; | overlayp 528;; | overlayp
282;; +===================================================================================+ 529;; +==========================================================================+
283 530
284;; Check the overlay predicate. 531;; Check the overlay predicate.
285(deftest-overlayp-1 A (make-overlay 1 1) t) 532(deftest-overlayp-1 A (make-overlay 1 1) t)
@@ -298,10 +545,10 @@ with parameters from the *Messages* buffer modification."
298(deftest-overlayp-1 N (selected-window) nil) 545(deftest-overlayp-1 N (selected-window) nil)
299(deftest-overlayp-1 O (selected-frame) nil) 546(deftest-overlayp-1 O (selected-frame) nil)
300 547
301 548
302;; +===================================================================================+ 549;; +==========================================================================+
303;; | overlay equality 550;; | overlay equality
304;; +===================================================================================+ 551;; +==========================================================================+
305 552
306(deftest-overlays-equal-1 A t (1 1) (1 1)) 553(deftest-overlays-equal-1 A t (1 1) (1 1))
307(deftest-overlays-equal-1 B t (5 10) (5 10)) 554(deftest-overlays-equal-1 B t (5 10) (5 10))
@@ -313,10 +560,10 @@ with parameters from the *Messages* buffer modification."
313(deftest-overlays-equal-1 H t (10 20 nil nil foo 42) (10 20 nil nil foo 42)) 560(deftest-overlays-equal-1 H t (10 20 nil nil foo 42) (10 20 nil nil foo 42))
314(deftest-overlays-equal-1 I nil (10 20 nil nil foo 42) (10 20 nil nil foo 43)) 561(deftest-overlays-equal-1 I nil (10 20 nil nil foo 42) (10 20 nil nil foo 43))
315 562
316 563
317;; +===================================================================================+ 564;; +==========================================================================+
318;; | overlay-lists 565;; | overlay-lists
319;; +===================================================================================+ 566;; +==========================================================================+
320 567
321;; Check whether overlay-lists returns something sensible. 568;; Check whether overlay-lists returns something sensible.
322(ert-deftest test-overlay-lists-1 () 569(ert-deftest test-overlay-lists-1 ()
@@ -330,10 +577,10 @@ with parameters from the *Messages* buffer modification."
330 (should (= 10 (length list))) 577 (should (= 10 (length list)))
331 (should (seq-every-p #'overlayp list))))) 578 (should (seq-every-p #'overlayp list)))))
332 579
333 580
334;; +===================================================================================+ 581;; +==========================================================================+
335;; | overlay-put/get/properties 582;; | overlay-put/get/properties
336;; +===================================================================================+ 583;; +==========================================================================+
337 584
338;; Test if overlay-put properties can be retrieved by overlay-get and 585;; Test if overlay-put properties can be retrieved by overlay-get and
339;; overlay-properties. 586;; overlay-properties.
@@ -361,10 +608,10 @@ with parameters from the *Messages* buffer modification."
361 ;; Check if overlay-properties is a subset. 608 ;; Check if overlay-properties is a subset.
362 (should (= (length (overlay-properties ov)) (* n 2)))))) 609 (should (= (length (overlay-properties ov)) (* n 2))))))
363 610
364 611
365;; +===================================================================================+ 612;; +==========================================================================+
366;; | next-overlay-change 613;; | next-overlay-change
367;; +===================================================================================+ 614;; +==========================================================================+
368 615
369;; Test if next-overlay-change returns RESULT if called with POS in a 616;; Test if next-overlay-change returns RESULT if called with POS in a
370;; buffer with overlays corresponding to OVS and point-max >= 100. 617;; buffer with overlays corresponding to OVS and point-max >= 100.
@@ -383,14 +630,14 @@ with parameters from the *Messages* buffer modification."
383(deftest-next-overlay-change-1 I 10 (point-max) (10 10)) 630(deftest-next-overlay-change-1 I 10 (point-max) (10 10))
384(deftest-next-overlay-change-1 J 20 (point-max) (10 10)) 631(deftest-next-overlay-change-1 J 20 (point-max) (10 10))
385;; 2 non-empty, non-intersecting 632;; 2 non-empty, non-intersecting
386(deftest-next-overlay-change-1 D 10 20 (20 30) (40 50)) 633(deftest-next-overlay-change-1 D2 10 20 (20 30) (40 50))
387(deftest-next-overlay-change-1 E 35 40 (20 30) (40 50)) 634(deftest-next-overlay-change-1 E2 35 40 (20 30) (40 50))
388(deftest-next-overlay-change-1 F 60 (point-max) (20 30) (40 50)) 635(deftest-next-overlay-change-1 F2 60 (point-max) (20 30) (40 50))
389(deftest-next-overlay-change-1 G 30 40 (20 30) (40 50)) 636(deftest-next-overlay-change-1 G2 30 40 (20 30) (40 50))
390(deftest-next-overlay-change-1 H 50 (point-max) (20 30) (40 50)) 637(deftest-next-overlay-change-1 H2 50 (point-max) (20 30) (40 50))
391;; 2 non-empty, intersecting 638;; 2 non-empty, intersecting
392(deftest-next-overlay-change-1 I 10 20 (20 30) (25 35)) 639(deftest-next-overlay-change-1 I2 10 20 (20 30) (25 35))
393(deftest-next-overlay-change-1 J 20 25 (20 30) (25 35)) 640(deftest-next-overlay-change-1 J2 20 25 (20 30) (25 35))
394(deftest-next-overlay-change-1 K 23 25 (20 30) (25 35)) 641(deftest-next-overlay-change-1 K 23 25 (20 30) (25 35))
395(deftest-next-overlay-change-1 L 25 30 (20 30) (25 35)) 642(deftest-next-overlay-change-1 L 25 30 (20 30) (25 35))
396(deftest-next-overlay-change-1 M 28 30 (20 30) (25 35)) 643(deftest-next-overlay-change-1 M 28 30 (20 30) (25 35))
@@ -420,11 +667,11 @@ with parameters from the *Messages* buffer modification."
420(deftest-next-overlay-change-1 k 30 (point-max) (20 20) (20 30)) 667(deftest-next-overlay-change-1 k 30 (point-max) (20 20) (20 30))
421(deftest-next-overlay-change-1 l 40 (point-max) (20 20) (20 30)) 668(deftest-next-overlay-change-1 l 40 (point-max) (20 20) (20 30))
422;; 1 empty, 1 non-empty, intersecting at end 669;; 1 empty, 1 non-empty, intersecting at end
423(deftest-next-overlay-change-1 h 10 20 (30 30) (20 30)) 670(deftest-next-overlay-change-1 h2 10 20 (30 30) (20 30))
424(deftest-next-overlay-change-1 i 20 30 (30 30) (20 30)) 671(deftest-next-overlay-change-1 i2 20 30 (30 30) (20 30))
425(deftest-next-overlay-change-1 j 25 30 (30 30) (20 30)) 672(deftest-next-overlay-change-1 j2 25 30 (30 30) (20 30))
426(deftest-next-overlay-change-1 k 30 (point-max) (20 20) (20 30)) 673(deftest-next-overlay-change-1 k2 30 (point-max) (20 20) (20 30))
427(deftest-next-overlay-change-1 l 40 (point-max) (20 20) (20 30)) 674(deftest-next-overlay-change-1 l2 40 (point-max) (20 20) (20 30))
428;; 1 empty, 1 non-empty, intersecting in the middle 675;; 1 empty, 1 non-empty, intersecting in the middle
429(deftest-next-overlay-change-1 m 10 20 (25 25) (20 30)) 676(deftest-next-overlay-change-1 m 10 20 (25 25) (20 30))
430(deftest-next-overlay-change-1 n 20 25 (25 25) (20 30)) 677(deftest-next-overlay-change-1 n 20 25 (25 25) (20 30))
@@ -452,10 +699,10 @@ with parameters from the *Messages* buffer modification."
452 (58 66) (41 10) (9 67) (28 88) (27 43) 699 (58 66) (41 10) (9 67) (28 88) (27 43)
453 (24 27) (48 36) (5 90) (61 9)) 700 (24 27) (48 36) (5 90) (61 9))
454 701
455 702
456;; +===================================================================================+ 703;; +==========================================================================+
457;; | previous-overlay-change. 704;; | previous-overlay-change.
458;; +===================================================================================+ 705;; +==========================================================================+
459 706
460;; Same for previous-overlay-change. 707;; Same for previous-overlay-change.
461;; 1 non-empty overlay 708;; 1 non-empty overlay
@@ -471,14 +718,14 @@ with parameters from the *Messages* buffer modification."
471(deftest-previous-overlay-change-1 I 10 1 (10 10)) 718(deftest-previous-overlay-change-1 I 10 1 (10 10))
472(deftest-previous-overlay-change-1 J 20 10 (10 10)) 719(deftest-previous-overlay-change-1 J 20 10 (10 10))
473;; 2 non-empty, non-intersecting 720;; 2 non-empty, non-intersecting
474(deftest-previous-overlay-change-1 D 10 1 (20 30) (40 50)) 721(deftest-previous-overlay-change-1 D2 10 1 (20 30) (40 50))
475(deftest-previous-overlay-change-1 E 35 30 (20 30) (40 50)) 722(deftest-previous-overlay-change-1 E2 35 30 (20 30) (40 50))
476(deftest-previous-overlay-change-1 F 60 50 (20 30) (40 50)) 723(deftest-previous-overlay-change-1 F2 60 50 (20 30) (40 50))
477(deftest-previous-overlay-change-1 G 30 20 (20 30) (40 50)) 724(deftest-previous-overlay-change-1 G2 30 20 (20 30) (40 50))
478(deftest-previous-overlay-change-1 H 50 40 (20 30) (40 50)) 725(deftest-previous-overlay-change-1 H2 50 40 (20 30) (40 50))
479;; 2 non-empty, intersecting 726;; 2 non-empty, intersecting
480(deftest-previous-overlay-change-1 I 10 1 (20 30) (25 35)) 727(deftest-previous-overlay-change-1 I2 10 1 (20 30) (25 35))
481(deftest-previous-overlay-change-1 J 20 1 (20 30) (25 35)) 728(deftest-previous-overlay-change-1 J2 20 1 (20 30) (25 35))
482(deftest-previous-overlay-change-1 K 23 20 (20 30) (25 35)) 729(deftest-previous-overlay-change-1 K 23 20 (20 30) (25 35))
483(deftest-previous-overlay-change-1 L 25 20 (20 30) (25 35)) 730(deftest-previous-overlay-change-1 L 25 20 (20 30) (25 35))
484(deftest-previous-overlay-change-1 M 28 25 (20 30) (25 35)) 731(deftest-previous-overlay-change-1 M 28 25 (20 30) (25 35))
@@ -513,7 +760,7 @@ with parameters from the *Messages* buffer modification."
513(deftest-previous-overlay-change-1 o 25 20 (30 30) (20 30)) 760(deftest-previous-overlay-change-1 o 25 20 (30 30) (20 30))
514(deftest-previous-overlay-change-1 p 30 20 (20 20) (20 30)) 761(deftest-previous-overlay-change-1 p 30 20 (20 20) (20 30))
515(deftest-previous-overlay-change-1 q 40 30 (20 20) (20 30)) 762(deftest-previous-overlay-change-1 q 40 30 (20 20) (20 30))
516;; 1 empty, 1 non-empty, intersectig in the middle 763;; 1 empty, 1 non-empty, intersecting in the middle
517(deftest-previous-overlay-change-1 r 10 1 (25 25) (20 30)) 764(deftest-previous-overlay-change-1 r 10 1 (25 25) (20 30))
518(deftest-previous-overlay-change-1 s 20 1 (25 25) (20 30)) 765(deftest-previous-overlay-change-1 s 20 1 (25 25) (20 30))
519(deftest-previous-overlay-change-1 t 25 20 (25 25) (20 30)) 766(deftest-previous-overlay-change-1 t 25 20 (25 25) (20 30))
@@ -540,10 +787,10 @@ with parameters from the *Messages* buffer modification."
540 (58 66) (41 10) (9 67) (28 88) (27 43) 787 (58 66) (41 10) (9 67) (28 88) (27 43)
541 (24 27) (48 36) (5 90) (61 9)) 788 (24 27) (48 36) (5 90) (61 9))
542 789
543 790
544;; +===================================================================================+ 791;; +==========================================================================+
545;; | overlays-at 792;; | overlays-at
546;; +===================================================================================+ 793;; +==========================================================================+
547 794
548 795
549;; Test whether overlay-at returns RESULT at POS after overlays OVL were 796;; Test whether overlay-at returns RESULT at POS after overlays OVL were
@@ -568,36 +815,36 @@ with parameters from the *Messages* buffer modification."
568(deftest-overlays-at-1 P 50 () (a 10 20) (b 30 40)) 815(deftest-overlays-at-1 P 50 () (a 10 20) (b 30 40))
569 816
570;; 2 non-empty overlays intersecting 817;; 2 non-empty overlays intersecting
571(deftest-overlays-at-1 G 1 () (a 10 30) (b 20 40)) 818(deftest-overlays-at-1 G2 1 () (a 10 30) (b 20 40))
572(deftest-overlays-at-1 H 10 (a) (a 10 30) (b 20 40)) 819(deftest-overlays-at-1 H2 10 (a) (a 10 30) (b 20 40))
573(deftest-overlays-at-1 I 15 (a) (a 10 30) (b 20 40)) 820(deftest-overlays-at-1 I2 15 (a) (a 10 30) (b 20 40))
574(deftest-overlays-at-1 K 20 (a b) (a 10 30) (b 20 40)) 821(deftest-overlays-at-1 K2 20 (a b) (a 10 30) (b 20 40))
575(deftest-overlays-at-1 L 25 (a b) (a 10 30) (b 20 40)) 822(deftest-overlays-at-1 L2 25 (a b) (a 10 30) (b 20 40))
576(deftest-overlays-at-1 M 30 (b) (a 10 30) (b 20 40)) 823(deftest-overlays-at-1 M2 30 (b) (a 10 30) (b 20 40))
577(deftest-overlays-at-1 N 35 (b) (a 10 30) (b 20 40)) 824(deftest-overlays-at-1 N2 35 (b) (a 10 30) (b 20 40))
578(deftest-overlays-at-1 O 40 () (a 10 30) (b 20 40)) 825(deftest-overlays-at-1 O2 40 () (a 10 30) (b 20 40))
579(deftest-overlays-at-1 P 50 () (a 10 30) (b 20 40)) 826(deftest-overlays-at-1 P2 50 () (a 10 30) (b 20 40))
580 827
581;; 2 non-empty overlays continuous 828;; 2 non-empty overlays continuous
582(deftest-overlays-at-1 G 1 () (a 10 20) (b 20 30)) 829(deftest-overlays-at-1 G3 1 () (a 10 20) (b 20 30))
583(deftest-overlays-at-1 H 10 (a) (a 10 20) (b 20 30)) 830(deftest-overlays-at-1 H3 10 (a) (a 10 20) (b 20 30))
584(deftest-overlays-at-1 I 15 (a) (a 10 20) (b 20 30)) 831(deftest-overlays-at-1 I3 15 (a) (a 10 20) (b 20 30))
585(deftest-overlays-at-1 K 20 (b) (a 10 20) (b 20 30)) 832(deftest-overlays-at-1 K3 20 (b) (a 10 20) (b 20 30))
586(deftest-overlays-at-1 L 25 (b) (a 10 20) (b 20 30)) 833(deftest-overlays-at-1 L3 25 (b) (a 10 20) (b 20 30))
587(deftest-overlays-at-1 M 30 () (a 10 20) (b 20 30)) 834(deftest-overlays-at-1 M3 30 () (a 10 20) (b 20 30))
588 835
589;; overlays-at never returns empty overlays. 836;; overlays-at never returns empty overlays.
590(deftest-overlays-at-1 N 1 (a) (a 1 60) (c 1 1) (b 30 30) (d 50 50)) 837(deftest-overlays-at-1 N3 1 (a) (a 1 60) (c 1 1) (b 30 30) (d 50 50))
591(deftest-overlays-at-1 O 20 (a) (a 1 60) (c 1 1) (b 30 30) (d 50 50)) 838(deftest-overlays-at-1 O3 20 (a) (a 1 60) (c 1 1) (b 30 30) (d 50 50))
592(deftest-overlays-at-1 P 30 (a) (a 1 60) (c 1 1) (b 30 30) (d 50 50)) 839(deftest-overlays-at-1 P3 30 (a) (a 1 60) (c 1 1) (b 30 30) (d 50 50))
593(deftest-overlays-at-1 Q 40 (a) (a 1 60) (c 1 1) (b 30 30) (d 50 50)) 840(deftest-overlays-at-1 Q 40 (a) (a 1 60) (c 1 1) (b 30 30) (d 50 50))
594(deftest-overlays-at-1 R 50 (a) (a 1 60) (c 1 1) (b 30 30) (d 50 50)) 841(deftest-overlays-at-1 R 50 (a) (a 1 60) (c 1 1) (b 30 30) (d 50 50))
595(deftest-overlays-at-1 S 60 () (a 1 60) (c 1 1) (b 30 30) (d 50 50)) 842(deftest-overlays-at-1 S 60 () (a 1 60) (c 1 1) (b 30 30) (d 50 50))
596 843
597;; behaviour at point-min and point-max 844;; behavior at point-min and point-max
598(ert-deftest test-overlays-at-2 () 845(ert-deftest test-overlays-at-2 ()
599 (cl-macrolet ((should-length (n list) 846 (cl-macrolet ((should-length (n list)
600 `(should (= ,n (length ,list))))) 847 `(should (= ,n (length ,list)))))
601 (with-temp-buffer 848 (with-temp-buffer
602 (insert (make-string 100 ?\s)) 849 (insert (make-string 100 ?\s))
603 (make-overlay 1 (point-max)) 850 (make-overlay 1 (point-max))
@@ -613,10 +860,10 @@ with parameters from the *Messages* buffer modification."
613 (should-length 1 (overlays-at 15)) 860 (should-length 1 (overlays-at 15))
614 (should-length 1 (overlays-at (point-max)))))) 861 (should-length 1 (overlays-at (point-max))))))
615 862
616 863
617;; +===================================================================================+ 864;; +==========================================================================+
618;; | overlay-in 865;; | overlay-in
619;; +===================================================================================+ 866;; +==========================================================================+
620 867
621 868
622;; Test whether overlays-in returns RES in BEG,END after overlays OVL were 869;; Test whether overlays-in returns RES in BEG,END after overlays OVL were
@@ -691,10 +938,10 @@ with parameters from the *Messages* buffer modification."
691(deftest-overlays-in-1 af 10 11 (a) (a 10 10)) 938(deftest-overlays-in-1 af 10 11 (a) (a 10 10))
692 939
693 940
694;; behaviour at point-max 941;; behavior at point-max
695(ert-deftest test-overlays-in-2 () 942(ert-deftest test-overlays-in-2 ()
696 (cl-macrolet ((should-length (n list) 943 (cl-macrolet ((should-length (n list)
697 `(should (= ,n (length ,list))))) 944 `(should (= ,n (length ,list)))))
698 (with-temp-buffer 945 (with-temp-buffer
699 (insert (make-string 100 ?\s)) 946 (insert (make-string 100 ?\s))
700 (make-overlay (point-max) (point-max)) 947 (make-overlay (point-max) (point-max))
@@ -703,13 +950,13 @@ with parameters from the *Messages* buffer modification."
703 (should-length 2 (overlays-in 1 (point-max))) 950 (should-length 2 (overlays-in 1 (point-max)))
704 (should-length 1 (overlays-in (point-max) (point-max))) 951 (should-length 1 (overlays-in (point-max) (point-max)))
705 (narrow-to-region 1 50) 952 (narrow-to-region 1 50)
706 (should-length 0 (overlays-in 1 (point-max))) 953 (should-length 1 (overlays-in 1 (point-max)))
707 (should-length 1 (overlays-in (point-max) (point-max)))))) 954 (should-length 1 (overlays-in (point-max) (point-max))))))
708 955
709 956
710;; +===================================================================================+ 957;; +==========================================================================+
711;; | overlay-recenter 958;; | overlay-recenter
712;; +===================================================================================+ 959;; +==========================================================================+
713 960
714;; This function is a noop in the overlay tree branch. 961;; This function is a noop in the overlay tree branch.
715(ert-deftest test-overlay-recenter () 962(ert-deftest test-overlay-recenter ()
@@ -720,10 +967,10 @@ with parameters from the *Messages* buffer modification."
720 (make-overlay i (1+ i)) 967 (make-overlay i (1+ i))
721 (should-not (overlay-recenter i))))) 968 (should-not (overlay-recenter i)))))
722 969
723 970
724;; +===================================================================================+ 971;; +==========================================================================+
725;; | move-overlay 972;; | move-overlay
726;; +===================================================================================+ 973;; +==========================================================================+
727 974
728;; buffer nil with live overlay 975;; buffer nil with live overlay
729(ert-deftest test-move-overlay-1 () 976(ert-deftest test-move-overlay-1 ()
@@ -767,23 +1014,9 @@ with parameters from the *Messages* buffer modification."
767 (should-not (overlay-end ov)) 1014 (should-not (overlay-end ov))
768 (should-not (overlay-buffer ov)))) 1015 (should-not (overlay-buffer ov))))
769 1016
770;; This used to fail. 1017;; +==========================================================================+
771(ert-deftest test-move-overlay-5 ()
772 (skip-unless (fboundp 'overlay-tree))
773 (with-temp-buffer
774 (insert (make-string 1 ?.))
775 (let ((other (make-overlay 1 1)))
776 (make-overlay 1 1)
777 (insert "()")
778 (move-overlay other (point-max) (1+ (point-max)) (current-buffer))
779 (delete-overlay other))
780 (should (= (plist-get (car (with-no-warnings (overlay-tree))) :limit)
781 1))))
782
783
784;; +===================================================================================+
785;; | delete-(all-)overlay 1018;; | delete-(all-)overlay
786;; +===================================================================================+ 1019;; +==========================================================================+
787 1020
788;; delete live overlay 1021;; delete live overlay
789(ert-deftest test-delete-overlay-1 () 1022(ert-deftest test-delete-overlay-1 ()
@@ -814,22 +1047,22 @@ with parameters from the *Messages* buffer modification."
814 (should-not (delete-all-overlays (current-buffer))) 1047 (should-not (delete-all-overlays (current-buffer)))
815 (should-not (delete-all-overlays)))) 1048 (should-not (delete-all-overlays))))
816 1049
817 1050
818;; +===================================================================================+ 1051;; +==========================================================================+
819;; | get-char-property(-and-overlay) 1052;; | get-char-property(-and-overlay)
820;; +===================================================================================+ 1053;; +==========================================================================+
821 1054
822;; FIXME: TBD 1055;; FIXME: TBD
823 1056
824 1057
825;; +===================================================================================+ 1058;; +==========================================================================+
826;; | Moving by insertions 1059;; | Moving by insertions
827;; +===================================================================================+ 1060;; +==========================================================================+
828 1061
829(defmacro deftest-moving-insert-1 (id beg-end insert sbeg-send fa ra) 1062(defmacro deftest-moving-insert-1 (id beg-end insert sbeg-send fa ra)
830 (cl-destructuring-bind (beg end ipos ilen sbeg send fa ra) 1063 (cl-destructuring-bind (beg end ipos ilen sbeg send fa ra)
831 (append beg-end insert sbeg-send (list fa ra) nil) 1064 (append beg-end insert sbeg-send (list fa ra) nil)
832 `(ert-deftest ,(make-overlay-test-name 'moving-insert 1 id) () 1065 `(ert-deftest ,(buffer-tests--make-test-name 'moving-insert 1 id) ()
833 (test-with-overlay-in-buffer (ov ,beg ,end ,fa ,ra) 1066 (test-with-overlay-in-buffer (ov ,beg ,end ,fa ,ra)
834 (should (= ,beg (overlay-start ov))) 1067 (should (= ,beg (overlay-start ov)))
835 (should (= ,end (overlay-end ov))) 1068 (should (= ,end (overlay-end ov)))
@@ -931,21 +1164,21 @@ with parameters from the *Messages* buffer modification."
931 (should (= 25 (overlay-start right))) 1164 (should (= 25 (overlay-start right)))
932 (should (= 75 (overlay-end right))) 1165 (should (= 75 (overlay-end right)))
933 ;; Try to detect the error, by removing left. The should fail 1166 ;; Try to detect the error, by removing left. The should fail
934 ;; an eassert, since it won't be found by a reular tree 1167 ;; an eassert, since it won't be found by a regular tree
935 ;; traversal - in theory. 1168 ;; traversal - in theory.
936 (delete-overlay left) 1169 (delete-overlay left)
937 (should (= 2 (length (overlays-in 1 (point-max)))))))) 1170 (should (= 2 (length (overlays-in 1 (point-max))))))))
938 1171
939 1172
940 1173
941;; +===================================================================================+ 1174;; +==========================================================================+
942;; | Moving by deletions 1175;; | Moving by deletions
943;; +===================================================================================+ 1176;; +==========================================================================+
944 1177
945(defmacro deftest-moving-delete-1 (id beg-end delete sbeg-send fa ra) 1178(defmacro deftest-moving-delete-1 (id beg-end delete sbeg-send fa ra)
946 (cl-destructuring-bind (beg end dpos dlen sbeg send fa ra) 1179 (cl-destructuring-bind (beg end dpos dlen sbeg send fa ra)
947 (append beg-end delete sbeg-send (list fa ra) nil) 1180 (append beg-end delete sbeg-send (list fa ra) nil)
948 `(ert-deftest ,(make-overlay-test-name 'moving-delete 1 id) () 1181 `(ert-deftest ,(buffer-tests--make-test-name 'moving-delete 1 id) ()
949 (test-with-overlay-in-buffer (ov ,beg ,end ,fa ,ra) 1182 (test-with-overlay-in-buffer (ov ,beg ,end ,fa ,ra)
950 (should (= ,beg (overlay-start ov))) 1183 (should (= ,beg (overlay-start ov)))
951 (should (= ,end (overlay-end ov))) 1184 (should (= ,end (overlay-end ov)))
@@ -1002,12 +1235,12 @@ with parameters from the *Messages* buffer modification."
1002(deftest-moving-delete-1 e (15 15) (5 5) (10 10) t t) 1235(deftest-moving-delete-1 e (15 15) (5 5) (10 10) t t)
1003(deftest-moving-delete-1 f (15 15) (15 3) (15 15) t t) 1236(deftest-moving-delete-1 f (15 15) (15 3) (15 15) t t)
1004 1237
1005 1238
1006;; +===================================================================================+ 1239;; +==========================================================================+
1007;; | make-indirect-buffer 1240;; | make-indirect-buffer
1008;; +===================================================================================+ 1241;; +==========================================================================+
1009 1242
1010;; Check if overlays are cloned/seperate from indirect buffer. 1243;; Check if overlays are cloned/separate from indirect buffer.
1011(ert-deftest test-make-indirect-buffer-1 () 1244(ert-deftest test-make-indirect-buffer-1 ()
1012 (with-temp-buffer 1245 (with-temp-buffer
1013 (dotimes (_ 10) (make-overlay 1 1)) 1246 (dotimes (_ 10) (make-overlay 1 1))
@@ -1045,22 +1278,22 @@ with parameters from the *Messages* buffer modification."
1045 (kill-buffer indirect)))))) 1278 (kill-buffer indirect))))))
1046 1279
1047 1280
1048 1281
1049;; +===================================================================================+ 1282;; +==========================================================================+
1050;; | buffer-swap-text 1283;; | buffer-swap-text
1051;; +===================================================================================+ 1284;; +==========================================================================+
1052 1285
1053(defmacro test-with-temp-buffers (vars &rest body) 1286(defmacro buffer-tests--with-temp-buffers (vars &rest body)
1054 (declare (indent 1) (debug (sexp &rest form))) 1287 (declare (indent 1) (debug (sexp &rest form)))
1055 (if (null vars) 1288 (if (null vars)
1056 `(progn ,@body) 1289 `(progn ,@body)
1057 `(with-temp-buffer 1290 `(with-temp-buffer
1058 (let ((,(car vars) (current-buffer))) 1291 (let ((,(car vars) (current-buffer)))
1059 (test-with-temp-buffers ,(cdr vars) ,@body))))) 1292 (buffer-tests--with-temp-buffers ,(cdr vars) ,@body)))))
1060 1293
1061;; basic 1294;; basic
1062(ert-deftest test-buffer-swap-text-1 () 1295(ert-deftest test-buffer-swap-text-1 ()
1063 (test-with-temp-buffers (buffer other) 1296 (buffer-tests--with-temp-buffers (buffer other)
1064 (with-current-buffer buffer 1297 (with-current-buffer buffer
1065 (let ((ov (make-overlay 1 1))) 1298 (let ((ov (make-overlay 1 1)))
1066 (buffer-swap-text other) 1299 (buffer-swap-text other)
@@ -1070,8 +1303,8 @@ with parameters from the *Messages* buffer modification."
1070 (should (eq ov (car (overlays-in 1 1))))))))) 1303 (should (eq ov (car (overlays-in 1 1)))))))))
1071 1304
1072;; properties 1305;; properties
1073(ert-deftest test-buffer-swap-text-1 () 1306(ert-deftest test-buffer-swap-text-2 ()
1074 (test-with-temp-buffers (buffer other) 1307 (buffer-tests--with-temp-buffers (buffer other)
1075 (with-current-buffer other 1308 (with-current-buffer other
1076 (overlay-put (make-overlay 1 1) 'buffer 'other)) 1309 (overlay-put (make-overlay 1 1) 'buffer 'other))
1077 (with-current-buffer buffer 1310 (with-current-buffer buffer
@@ -1083,10 +1316,10 @@ with parameters from the *Messages* buffer modification."
1083 (should (= 1 (length (overlays-in 1 1)))) 1316 (should (= 1 (length (overlays-in 1 1))))
1084 (should (eq (overlay-get (car (overlays-in 1 1)) 'buffer) 'buffer))))) 1317 (should (eq (overlay-get (car (overlays-in 1 1)) 'buffer) 'buffer)))))
1085 1318
1086 1319
1087;; +===================================================================================+ 1320;; +==========================================================================+
1088;; | priorities 1321;; | priorities
1089;; +===================================================================================+ 1322;; +==========================================================================+
1090 1323
1091(ert-deftest test-overlay-priorities-1 () 1324(ert-deftest test-overlay-priorities-1 ()
1092 (with-temp-buffer 1325 (with-temp-buffer
@@ -1107,10 +1340,10 @@ with parameters from the *Messages* buffer modification."
1107 (overlay-put ov 'value i))) 1340 (overlay-put ov 'value i)))
1108 (should (eq 9 (get-char-property 1 'value))))) 1341 (should (eq 9 (get-char-property 1 'value)))))
1109 1342
1110 1343
1111;; +===================================================================================+ 1344;; +==========================================================================+
1112;; | Other 1345;; | Other
1113;; +===================================================================================+ 1346;; +==========================================================================+
1114 1347
1115(defun test-overlay-regions () 1348(defun test-overlay-regions ()
1116 (sort (mapcar (lambda (ov) 1349 (sort (mapcar (lambda (ov)
@@ -1226,9 +1459,10 @@ with parameters from the *Messages* buffer modification."
1226 (nonempty-eob (make-overlay 4 5)) 1459 (nonempty-eob (make-overlay 4 5))
1227 (empty-eob (make-overlay 5 5))) 1460 (empty-eob (make-overlay 5 5)))
1228 (set-buffer-multibyte nil) 1461 (set-buffer-multibyte nil)
1229 (cl-macrolet ((ovshould (ov begin end) 1462 (cl-macrolet
1230 `(should (equal (list (overlay-start ,ov) (overlay-end ,ov)) 1463 ((ovshould (ov begin end)
1231 (list ,begin ,end))))) 1464 `(should (equal (list (overlay-start ,ov) (overlay-end ,ov))
1465 (list ,begin ,end)))))
1232 (ovshould nonempty-bob 1 3) 1466 (ovshould nonempty-bob 1 3)
1233 (ovshould empty-bob 1 1) 1467 (ovshould empty-bob 1 1)
1234 (ovshould empty 3 3) 1468 (ovshould empty 3 3)
@@ -1257,9 +1491,10 @@ with parameters from the *Messages* buffer modification."
1257 (nonempty-eob-end (make-overlay 6 9)) 1491 (nonempty-eob-end (make-overlay 6 9))
1258 (empty-eob (make-overlay 9 9))) 1492 (empty-eob (make-overlay 9 9)))
1259 (set-buffer-multibyte t) 1493 (set-buffer-multibyte t)
1260 (cl-macrolet ((ovshould (ov begin end) 1494 (cl-macrolet
1261 `(should (equal (list (overlay-start ,ov) (overlay-end ,ov)) 1495 ((ovshould (ov begin end)
1262 (list ,begin ,end))))) 1496 `(should (equal (list (overlay-start ,ov) (overlay-end ,ov))
1497 (list ,begin ,end)))))
1263 (ovshould nonempty-bob-end 1 2) 1498 (ovshould nonempty-bob-end 1 2)
1264 (ovshould nonempty-bob-beg 1 2) 1499 (ovshould nonempty-bob-beg 1 2)
1265 (ovshould empty-bob 1 1) 1500 (ovshould empty-bob 1 1)
@@ -1280,6 +1515,7 @@ with parameters from the *Messages* buffer modification."
1280;; | Autogenerated insert/delete/narrow tests 1515;; | Autogenerated insert/delete/narrow tests
1281;; +===================================================================================+ 1516;; +===================================================================================+
1282 1517
1518(when nil ;; Let's comment these out for now.
1283 1519
1284;; (defun test-overlay-generate-test (name) 1520;; (defun test-overlay-generate-test (name)
1285;; (interactive) 1521;; (interactive)
@@ -7733,4 +7969,247 @@ with parameters from the *Messages* buffer modification."
7733 (101 . 138) 7969 (101 . 138)
7734 (103 . 103)))))) 7970 (103 . 103))))))
7735 7971
7972) ;; End of `when nil' for autogenerated insert/delete/narrow tests.
7973
7974(ert-deftest buffer-multibyte-overlong-sequences ()
7975 (dolist (uni '("\xE0\x80\x80"
7976 "\xF0\x80\x80\x80"
7977 "\xF8\x8F\xBF\xBF\x80"))
7978 (let ((multi (string-to-multibyte uni)))
7979 (should
7980 (string-equal
7981 multi
7982 (with-temp-buffer
7983 (set-buffer-multibyte nil)
7984 (insert uni)
7985 (set-buffer-multibyte t)
7986 (buffer-string)))))))
7987
7988;; https://debbugs.gnu.org/33492
7989(ert-deftest buffer-tests-buffer-local-variables-undo ()
7990 "Test that `buffer-undo-list' appears in `buffer-local-variables'."
7991 (with-temp-buffer
7992 (should (assq 'buffer-undo-list (buffer-local-variables)))))
7993
7994(ert-deftest buffer-tests-inhibit-buffer-hooks ()
7995 "Test `get-buffer-create' argument INHIBIT-BUFFER-HOOKS."
7996 (let* (run-bluh (bluh (lambda () (setq run-bluh t))))
7997 (unwind-protect
7998 (let* ( run-kbh (kbh (lambda () (setq run-kbh t)))
7999 run-kbqf (kbqf (lambda () (setq run-kbqf t))) )
8000
8001 ;; Inhibited.
8002 (add-hook 'buffer-list-update-hook bluh)
8003 (with-current-buffer (generate-new-buffer " foo" t)
8004 (add-hook 'kill-buffer-hook kbh nil t)
8005 (add-hook 'kill-buffer-query-functions kbqf nil t)
8006 (kill-buffer))
8007 (with-temp-buffer (ignore))
8008 (with-output-to-string (ignore))
8009 (should-not run-bluh)
8010 (should-not run-kbh)
8011 (should-not run-kbqf)
8012
8013 ;; Not inhibited.
8014 (with-current-buffer (generate-new-buffer " foo")
8015 (should run-bluh)
8016 (add-hook 'kill-buffer-hook kbh nil t)
8017 (add-hook 'kill-buffer-query-functions kbqf nil t)
8018 (kill-buffer))
8019 (should run-kbh)
8020 (should run-kbqf))
8021 (remove-hook 'buffer-list-update-hook bluh))))
8022
8023(ert-deftest buffer-tests-inhibit-buffer-hooks-indirect ()
8024 "Indirect buffers do not call `get-buffer-create'."
8025 (dolist (inhibit '(nil t))
8026 (let ((base (get-buffer-create "foo" inhibit)))
8027 (unwind-protect
8028 (dotimes (_i 11)
8029 (let* (flag*
8030 (flag (lambda () (prog1 t (setq flag* t))))
8031 (indirect (make-indirect-buffer base "foo[indirect]" nil
8032 inhibit)))
8033 (unwind-protect
8034 (progn
8035 (with-current-buffer indirect
8036 (add-hook 'kill-buffer-query-functions flag nil t))
8037 (kill-buffer indirect)
8038 (if inhibit
8039 (should-not flag*)
8040 (should flag*)))
8041 (let (kill-buffer-query-functions)
8042 (when (buffer-live-p indirect)
8043 (kill-buffer indirect))))))
8044 (let (kill-buffer-query-functions)
8045 (when (buffer-live-p base)
8046 (kill-buffer base)))))))
8047
8048(ert-deftest zero-length-overlays-and-not ()
8049 (with-temp-buffer
8050 (insert "hello")
8051 (let ((long-overlay (make-overlay 2 4))
8052 (zero-overlay (make-overlay 3 3)))
8053 ;; Exclude.
8054 (should (= (length (overlays-at 3)) 1))
8055 (should (eq (car (overlays-at 3)) long-overlay))
8056 ;; Include.
8057 (should (= (length (overlays-in 3 3)) 2))
8058 (should (memq long-overlay (overlays-in 3 3)))
8059 (should (memq zero-overlay (overlays-in 3 3))))))
8060
8061(ert-deftest test-remove-overlays ()
8062 (with-temp-buffer
8063 (insert "foo")
8064 (make-overlay (point) (point))
8065 (should (= (length (overlays-in (point-min) (point-max))) 1))
8066 (remove-overlays)
8067 (should (= (length (overlays-in (point-min) (point-max))) 0)))
8068
8069 (with-temp-buffer
8070 (insert "foo")
8071 (goto-char 2)
8072 (make-overlay (point) (point))
8073 ;; We only count zero-length overlays at the end of the buffer.
8074 (should (= (length (overlays-in 1 2)) 0))
8075 (narrow-to-region 1 2)
8076 ;; We've now narrowed, so the zero-length overlay is at the end of
8077 ;; the (accessible part of the) buffer.
8078 (should (= (length (overlays-in 1 2)) 1))
8079 (remove-overlays)
8080 (should (= (length (overlays-in (point-min) (point-max))) 0))))
8081
8082(ert-deftest test-kill-buffer-auto-save-default ()
8083 (ert-with-temp-file file
8084 (let (auto-save)
8085 ;; Always answer yes.
8086 (cl-letf (((symbol-function #'yes-or-no-p) (lambda (_) t)))
8087 (unwind-protect
8088 (progn
8089 (find-file file)
8090 (auto-save-mode t)
8091 (insert "foo\n")
8092 (should buffer-auto-save-file-name)
8093 (setq auto-save buffer-auto-save-file-name)
8094 (do-auto-save)
8095 (should (file-exists-p auto-save))
8096 (kill-buffer (current-buffer))
8097 (should (file-exists-p auto-save)))
8098 (when auto-save
8099 (ignore-errors (delete-file auto-save))))))))
8100
8101(ert-deftest test-kill-buffer-auto-save-delete ()
8102 (ert-with-temp-file file
8103 (let (auto-save)
8104 (should (file-exists-p file))
8105 (setq kill-buffer-delete-auto-save-files t)
8106 ;; Always answer yes.
8107 (cl-letf (((symbol-function #'yes-or-no-p) (lambda (_) t)))
8108 (unwind-protect
8109 (progn
8110 (find-file file)
8111 (auto-save-mode t)
8112 (insert "foo\n")
8113 (should buffer-auto-save-file-name)
8114 (setq auto-save buffer-auto-save-file-name)
8115 (do-auto-save)
8116 (should (file-exists-p auto-save))
8117 ;; This should delete the auto-save file.
8118 (kill-buffer (current-buffer))
8119 (should-not (file-exists-p auto-save)))
8120 (ignore-errors (delete-file file))
8121 (when auto-save
8122 (ignore-errors (delete-file auto-save)))))
8123 ;; Answer no to deletion.
8124 (cl-letf (((symbol-function #'yes-or-no-p)
8125 (lambda (prompt)
8126 (not (string-search "Delete auto-save file" prompt)))))
8127 (unwind-protect
8128 (progn
8129 (find-file file)
8130 (auto-save-mode t)
8131 (insert "foo\n")
8132 (should buffer-auto-save-file-name)
8133 (setq auto-save buffer-auto-save-file-name)
8134 (do-auto-save)
8135 (should (file-exists-p auto-save))
8136 ;; This should not delete the auto-save file.
8137 (kill-buffer (current-buffer))
8138 (should (file-exists-p auto-save)))
8139 (when auto-save
8140 (ignore-errors (delete-file auto-save))))))))
8141
8142(ert-deftest test-buffer-modifications ()
8143 (ert-with-temp-file file
8144 (with-current-buffer (find-file file)
8145 (auto-save-mode 1)
8146 (should-not (buffer-modified-p))
8147 (insert "foo")
8148 (should (buffer-modified-p))
8149 (should-not (eq (buffer-modified-p) 'autosaved))
8150 (do-auto-save nil t)
8151 (should (eq (buffer-modified-p) 'autosaved))
8152 (with-silent-modifications
8153 (put-text-property 1 3 'face 'bold))
8154 (should (eq (buffer-modified-p) 'autosaved))
8155 (save-buffer)
8156 (should-not (buffer-modified-p))
8157 (with-silent-modifications
8158 (put-text-property 1 3 'face 'italic))
8159 (should-not (buffer-modified-p)))))
8160
8161(ert-deftest test-restore-buffer-modified-p ()
8162 (ert-with-temp-file file
8163 ;; This avoids the annoying "foo and bar are the same file" on
8164 ;; MS-Windows.
8165 (setq file (file-truename file))
8166 (with-current-buffer (find-file file)
8167 (auto-save-mode 1)
8168 (should-not (eq (buffer-modified-p) t))
8169 (insert "foo")
8170 (should (buffer-modified-p))
8171 (restore-buffer-modified-p nil)
8172 (should-not (buffer-modified-p))
8173 (insert "bar")
8174 (do-auto-save nil t)
8175 (should (eq (buffer-modified-p) 'autosaved))
8176 (insert "zot")
8177 (restore-buffer-modified-p 'autosaved)
8178 (should (eq (buffer-modified-p) 'autosaved))
8179
8180 ;; Clean up.
8181 (when (file-exists-p buffer-auto-save-file-name)
8182 (delete-file buffer-auto-save-file-name))))
8183
8184 (ert-with-temp-file file
8185 (setq file (file-truename file))
8186 (with-current-buffer (find-file file)
8187 (auto-save-mode 1)
8188 (should-not (eq (buffer-modified-p) t))
8189 (insert "foo")
8190 (should (buffer-modified-p))
8191 (should-not (eq (buffer-modified-p) 'autosaved))
8192 (restore-buffer-modified-p 'autosaved)
8193 (should (eq (buffer-modified-p) 'autosaved)))))
8194
8195(ert-deftest test-buffer-chars-modified-ticks ()
8196 "Test `buffer-chars-modified-tick'."
8197 (setq temporary-file-directory (file-truename temporary-file-directory))
8198 (let ((text "foobar")
8199 f1 f2)
8200 (unwind-protect
8201 (progn
8202 (setq f1 (make-temp-file "buf-modiff-tests")
8203 f2 (make-temp-file "buf-modiff-tests"))
8204 (with-current-buffer (find-file f1)
8205 (should (= (buffer-chars-modified-tick) 1))
8206 (should (= (buffer-chars-modified-tick) (buffer-modified-tick)))
8207 (write-region text nil f2 nil 'silent)
8208 (insert-file-contents f2)
8209 (should (= (buffer-chars-modified-tick) (buffer-modified-tick)))
8210 (should (> (buffer-chars-modified-tick) 1))))
8211 (if f1 (delete-file f1))
8212 (if f2 (delete-file f2))
8213 )))
8214
7736;;; buffer-tests.el ends here 8215;;; buffer-tests.el ends here
diff --git a/test/src/callint-tests.el b/test/src/callint-tests.el
new file mode 100644
index 00000000000..5a633fdc2bd
--- /dev/null
+++ b/test/src/callint-tests.el
@@ -0,0 +1,68 @@
1;;; callint-tests.el --- unit tests for callint.c -*- lexical-binding: t; -*-
2
3;; Copyright (C) 2018-2022 Free Software Foundation, Inc.
4
5;; Author: Philipp Stephani <phst@google.com>
6
7;; This file is part of GNU Emacs.
8
9;; GNU Emacs is free software: you can redistribute it and/or modify
10;; it under the terms of the GNU General Public License as published by
11;; the Free Software Foundation, either version 3 of the License, or
12;; (at your option) any later version.
13
14;; GNU Emacs is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;; GNU General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
20;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
21
22;;; Commentary:
23
24;; Unit tests for src/callint.c.
25
26;;; Code:
27
28(require 'ert)
29
30(ert-deftest call-interactively/incomplete-multibyte-sequence ()
31 "Check that Bug#30004 is fixed."
32 (let* ((text-quoting-style 'grave)
33 (data (should-error (call-interactively (lambda () (interactive "\xFF"))))))
34 (should
35 (equal
36 (cdr data)
37 '("Invalid control letter `\u00FF' (#o377, #x00ff) in interactive calling string")))))
38
39(ert-deftest call-interactively/embedded-nulls ()
40 "Check that Bug#30005 is fixed."
41 (should (equal (let ((unread-command-events '(?a ?b)))
42 (call-interactively (lambda (a b)
43 (interactive "ka\0a: \nkb: ")
44 (list a b))))
45 '("a" "b"))))
46
47(ert-deftest call-interactively-prune-command-history ()
48 "Check that Bug#31211 is fixed."
49 (let ((history-length 1)
50 (command-history ()))
51 (dotimes (_ (1+ history-length))
52 (call-interactively #'ignore t))
53 (should (= (length command-history) history-length))))
54
55(defun callint-test-int-args (foo bar &optional zot)
56 (declare (interactive-args
57 (bar 10)
58 (zot 11)))
59 (interactive (list 1 1 1))
60 (+ foo bar zot))
61
62(ert-deftest test-interactive-args ()
63 (let ((history-length 1)
64 (command-history ()))
65 (should (= (call-interactively 'callint-test-int-args t) 3))
66 (should (equal command-history '((callint-test-int-args 1 10 11))))))
67
68;;; callint-tests.el ends here
diff --git a/test/src/callproc-tests.el b/test/src/callproc-tests.el
index fcba6914a5d..f44c7e199f6 100644
--- a/test/src/callproc-tests.el
+++ b/test/src/callproc-tests.el
@@ -1,6 +1,6 @@
1;;; callproc-tests.el --- callproc.c tests -*- lexical-binding: t -*- 1;;; callproc-tests.el --- callproc.c tests -*- 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;; This file is part of GNU Emacs. 5;; This file is part of GNU Emacs.
6 6
@@ -17,6 +17,11 @@
17;; You should have received a copy of the GNU General Public License 17;; You should have received a copy of the GNU General Public License
18;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. 18;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
19 19
20
21;;; Commentary:
22;;
23;; Unit tests for src/callproc.c.
24
20;;; Code: 25;;; Code:
21 26
22(require 'ert) 27(require 'ert)
@@ -37,3 +42,38 @@
37 (split-string-and-unquote (buffer-string))) 42 (split-string-and-unquote (buffer-string)))
38 (should (equal initial-shell "nil")) 43 (should (equal initial-shell "nil"))
39 (should-not (equal initial-shell shell)))) 44 (should-not (equal initial-shell shell))))
45
46(ert-deftest call-process-w32-debug-spawn-error ()
47 "Check that debugger runs on `call-process' failure (Bug#33016)."
48 (skip-unless (eq system-type 'windows-nt))
49 (let* ((debug-on-error t)
50 (have-called-debugger nil)
51 (debugger (lambda (&rest _)
52 (setq have-called-debugger t)
53 ;; Allow entering the debugger later in the same
54 ;; test run, before going back to the command
55 ;; loop.
56 (setq internal-when-entered-debugger -1))))
57 (should (eq :got-error ;; NOTE: `should-error' would inhibit debugger.
58 (condition-case-unless-debug ()
59 ;; On MS-Windows, "nul.FOO" resolves to the null
60 ;; device, and thus acts like an always-empty
61 ;; file, for any FOO, in any directory. So
62 ;; c:/null.exe passes Emacs' test for the file's
63 ;; existence, and ensures we hit an error in the
64 ;; w32 process spawn code.
65 (call-process "c:/nul.exe")
66 (error :got-error))))
67 (should have-called-debugger)))
68
69(ert-deftest call-process-region-entire-buffer-with-delete ()
70 "Check that Bug#40576 is fixed."
71 (let ((emacs (expand-file-name invocation-name invocation-directory)))
72 (skip-unless (file-executable-p emacs))
73 (with-temp-buffer
74 (insert "Buffer contents\n")
75 (should
76 (eq (call-process-region nil nil emacs :delete nil nil "--version") 0))
77 (should (eq (buffer-size) 0)))))
78
79;;; callproc-tests.el ends here
diff --git a/test/src/casefiddle-tests.el b/test/src/casefiddle-tests.el
index 0a9b6c20ec9..652af417293 100644
--- a/test/src/casefiddle-tests.el
+++ b/test/src/casefiddle-tests.el
@@ -1,6 +1,6 @@
1;;; casefiddle-tests.el --- tests for casefiddle.c functions -*- lexical-binding: t -*- 1;;; casefiddle-tests.el --- tests for casefiddle.c functions -*- lexical-binding: t -*-
2 2
3;; Copyright (C) 2015-2016 Free Software Foundation, Inc. 3;; Copyright (C) 2015-2016, 2018-2022 Free Software Foundation, Inc.
4 4
5;; This file is part of GNU Emacs. 5;; This file is part of GNU Emacs.
6 6
@@ -57,7 +57,7 @@
57 errors))) 57 errors)))
58 (setq expected (cdr expected))))) 58 (setq expected (cdr expected)))))
59 (when errors 59 (when errors
60 (ert-fail (mapconcat (lambda (line) line) (nreverse errors) ""))))) 60 (ert-fail (mapconcat #'identity (nreverse errors))))))
61 61
62 62
63(defconst casefiddle-tests--characters 63(defconst casefiddle-tests--characters
@@ -98,7 +98,7 @@
98 errors))) 98 errors)))
99 (setq props (cdr props) tabs (cdr tabs) expected (cdr expected))))) 99 (setq props (cdr props) tabs (cdr tabs) expected (cdr expected)))))
100 (when errors 100 (when errors
101 (mapconcat (lambda (line) line) (nreverse errors) ""))))) 101 (mapconcat #'identity (nreverse errors))))))
102 102
103 103
104(ert-deftest casefiddle-tests-casing-character () 104(ert-deftest casefiddle-tests-casing-character ()
@@ -116,7 +116,7 @@
116 errors))) 116 errors)))
117 (setq funcs (cdr funcs) expected (cdr expected))))) 117 (setq funcs (cdr funcs) expected (cdr expected)))))
118 (when errors 118 (when errors
119 (mapconcat (lambda (line) line) (nreverse errors) ""))))) 119 (mapconcat (lambda (line) line) (nreverse errors))))))
120 120
121 121
122(ert-deftest casefiddle-tests-casing-word () 122(ert-deftest casefiddle-tests-casing-word ()
@@ -196,7 +196,7 @@
196 ("fish" "FISH" "fish" "Fish" "Fish") 196 ("fish" "FISH" "fish" "Fish" "Fish")
197 ("Straße" "STRASSE" "straße" "Straße" "Straße") 197 ("Straße" "STRASSE" "straße" "Straße" "Straße")
198 198
199 ;; The word repeated twice to test behaviour at the end of a word 199 ;; The word repeated twice to test behavior at the end of a word
200 ;; inside of an input string as well as at the end of the string. 200 ;; inside of an input string as well as at the end of the string.
201 ("ΌΣΟΣ ΌΣΟΣ" "ΌΣΟΣ ΌΣΟΣ" "όσος όσος" "Όσος Όσος" "ΌΣΟΣ ΌΣΟΣ") 201 ("ΌΣΟΣ ΌΣΟΣ" "ΌΣΟΣ ΌΣΟΣ" "όσος όσος" "Όσος Όσος" "ΌΣΟΣ ΌΣΟΣ")
202 ;; What should be done with sole sigma? It is ‘final’ but on the 202 ;; What should be done with sole sigma? It is ‘final’ but on the
@@ -247,7 +247,8 @@
247 ;; input upcase downcase [titlecase] 247 ;; input upcase downcase [titlecase]
248 (dolist (test '((?a ?A ?a) (?A ?A ?a) 248 (dolist (test '((?a ?A ?a) (?A ?A ?a)
249 (?ł ?Ł ?ł) (?Ł ?Ł ?ł) 249 (?ł ?Ł ?ł) (?Ł ?Ł ?ł)
250 (?ß ?ß ?ß) (?ẞ ?ẞ ?ß) 250 ;; We char-upcase ß to ẞ; see bug #11309.
251 (?ß ?ẞ ?ß) (?ẞ ?ẞ ?ß)
251 (?ⅷ ?Ⅷ ?ⅷ) (?Ⅷ ?Ⅷ ?ⅷ) 252 (?ⅷ ?Ⅷ ?ⅷ) (?Ⅷ ?Ⅷ ?ⅷ)
252 (?DŽ ?DŽ ?dž ?Dž) (?Dž ?DŽ ?dž ?Dž) (?dž ?DŽ ?dž ?Dž))) 253 (?DŽ ?DŽ ?dž ?Dž) (?Dž ?DŽ ?dž ?Dž) (?dž ?DŽ ?dž ?Dž)))
253 (let ((ch (car test)) 254 (let ((ch (car test))
@@ -259,5 +260,38 @@
259 (should (eq tc (capitalize ch))) 260 (should (eq tc (capitalize ch)))
260 (should (eq tc (upcase-initials ch)))))) 261 (should (eq tc (upcase-initials ch))))))
261 262
263(defvar casefiddle-oldfunc region-extract-function)
264
265(defun casefiddle-loopfunc (method)
266 (if (eq method 'bounds)
267 (let ((looping (list '(1 . 1))))
268 (setcdr looping looping))
269 (funcall casefiddle-oldfunc method)))
270
271(defun casefiddle-badfunc (method)
272 (if (eq method 'bounds)
273 '(())
274 (funcall casefiddle-oldfunc method)))
275
276(ert-deftest casefiddle-invalid-region-extract-function ()
277 (dolist (region-extract-function '(casefiddle-badfunc casefiddle-loopfunc))
278 (with-temp-buffer
279 (should-error (upcase-region nil nil t)))))
280
281(ert-deftest casefiddle-turkish ()
282 (skip-unless (member "tr_TR.utf8" (get-locale-names)))
283 ;; See bug#50752. The point is that unibyte and multibyte strings
284 ;; are upcased differently in the "dotless i" case in Turkish,
285 ;; turning ASCII into non-ASCII, which is very unusual.
286 (with-locale-environment "tr_TR.utf8"
287 (should (string-equal (downcase "I ı") "ı ı"))
288 (should (string-equal (downcase "İ i") "i̇ i"))
289 (should (string-equal (downcase "I") "i"))
290 (should (string-equal (capitalize "bIte") "Bite"))
291 (should (string-equal (capitalize "bIté") "Bıté"))
292 (should (string-equal (capitalize "indIa") "India"))
293 ;; This does not work -- it produces "Indıa".
294 ;;(should (string-equal (capitalize "indIá") "İndıa"))
295 ))
262 296
263;;; casefiddle-tests.el ends here 297;;; casefiddle-tests.el ends here
diff --git a/test/src/character-tests.el b/test/src/character-tests.el
new file mode 100644
index 00000000000..f83bac333d7
--- /dev/null
+++ b/test/src/character-tests.el
@@ -0,0 +1,47 @@
1;;; character-tests.el --- tests for character.c -*- lexical-binding:t -*-
2
3;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
4
5;; This file is part of GNU Emacs.
6
7;; GNU Emacs is free software: you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation, either version 3 of the License, or
10;; (at your option) any later version.
11
12;; GNU Emacs is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; GNU General Public License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
19
20;;; Code:
21
22(require 'ert)
23
24(ert-deftest character-test-string-width ()
25 "Test `string-width' with and without compositions."
26 (should (= (string-width "1234") 4))
27 (should (= (string-width "12\t34") (+ 4 tab-width)))
28 (should (= (string-width "áëòç") 4))
29 (should (= (string-width "áëòç") 4))
30 (should (= (string-width "הַרְבֵּה אַהֲבָה") 9))
31 (should (= (string-width "1234" 1 3) 2))
32 (should (= (string-width "1234" nil -1) 3))
33 (should (= (string-width "1234" 2) 2))
34 (should-error (string-width "1234" nil 5))
35 (should-error (string-width "1234" -5))
36 (should (= (string-width "12\t34") (+ 4 tab-width)))
37 (should (= (string-width "1234\t56") (+ 6 tab-width)))
38 (should (= (string-width "áëòç") 4))
39 (should (= (string-width "áëòç" nil 3) 3))
40 (should (= (string-width "áëòç" 1 3) 2))
41 (should (= (string-width "áëòç" nil 2) 1))
42 (should (= (string-width "áëòç" nil 3) 2))
43 (should (= (string-width "áëòç" nil 4) 2))
44 (should (= (string-width "הַרְבֵּה אַהֲבָה") 9))
45 (should (= (string-width "הַרְבֵּה אַהֲבָה" nil 8) 4)))
46
47;;; character-tests.el ends here
diff --git a/test/src/charset-tests.el b/test/src/charset-tests.el
index c3f09ec1a0a..51eb040e77a 100644
--- a/test/src/charset-tests.el
+++ b/test/src/charset-tests.el
@@ -1,26 +1,30 @@
1;;; charset-tests.el --- Tests for charset.c 1;;; charset-tests.el --- Tests for charset.c -*- lexical-binding: t -*-
2 2
3;; Copyright 2017 Free Software Foundation, Inc. 3;; Copyright 2017-2022 Free Software Foundation, Inc.
4 4
5;; This program is free software; you can redistribute it and/or modify 5;; This file is part of GNU Emacs.
6
7;; GNU Emacs is free software: you can redistribute it and/or modify
6;; it under the terms of the GNU General Public License as published by 8;; it under the terms of the GNU General Public License as published by
7;; the Free Software Foundation, either version 3 of the License, or 9;; the Free Software Foundation, either version 3 of the License, or
8;; (at your option) any later version. 10;; (at your option) any later version.
9 11
10;; This program is distributed in the hope that it will be useful, 12;; GNU Emacs is distributed in the hope that it will be useful,
11;; but WITHOUT ANY WARRANTY; without even the implied warranty of 13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
12;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13;; GNU General Public License for more details. 15;; GNU General Public License for more details.
14 16
15;; You should have received a copy of the GNU General Public License 17;; You should have received a copy of the GNU General Public License
16;; along with this program. If not, see <https://www.gnu.org/licenses/>. 18;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
17 19
18;;; Code: 20;;; Code:
19 21
20(require 'ert) 22(require 'ert)
21 23
22(ert-deftest charset-decode-char () 24(ert-deftest charset-decode-char ()
23 "Test decode-char." 25 "Test `decode-char'."
24 (should-error (decode-char 'ascii 0.5))) 26 (should-error (decode-char 'ascii 0.5)))
25 27
26(provide 'charset-tests) 28(provide 'charset-tests)
29
30;;; charset-tests.el ends here
diff --git a/test/src/chartab-tests.el b/test/src/chartab-tests.el
index 2c57f27ff8b..e4c4b065376 100644
--- a/test/src/chartab-tests.el
+++ b/test/src/chartab-tests.el
@@ -1,21 +1,23 @@
1;;; chartab-tests.el --- Tests for char-tab.c 1;;; chartab-tests.el --- Tests for char-tab.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: Eli Zaretskii <eliz@gnu.org> 5;; Author: Eli Zaretskii <eliz@gnu.org>
6 6
7;; This program is free software; you can redistribute it and/or modify 7;; This file is part of GNU Emacs.
8
9;; GNU Emacs is free software: you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by 10;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation, either version 3 of the License, or 11;; the Free Software Foundation, either version 3 of the License, or
10;; (at your option) any later version. 12;; (at your option) any later version.
11 13
12;; This program is distributed in the hope that it will be useful, 14;; GNU Emacs is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; GNU General Public License for more details. 17;; GNU General Public License for more details.
16 18
17;; You should have received a copy of the GNU General Public License 19;; You should have received a copy of the GNU General Public License
18;; along with this program. If not, see <https://www.gnu.org/licenses/>. 20;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
19 21
20;;; Code: 22;;; Code:
21 23
@@ -47,5 +49,25 @@
47 (#xe0e00 . #xe0ef6) 49 (#xe0e00 . #xe0ef6)
48 ))) 50 )))
49 51
52(ert-deftest chartab-test-char-table-p ()
53 (should (char-table-p (make-char-table 'foo)))
54 (should (not (char-table-p (make-hash-table)))))
55
56(ert-deftest chartab-test-char-table-subtype ()
57 (should (eq (char-table-subtype (make-char-table 'foo)) 'foo)))
58
59(ert-deftest chartab-test-char-table-parent ()
60 (should (eq (char-table-parent (make-char-table 'foo)) nil))
61 (let ((parent (make-char-table 'foo))
62 (child (make-char-table 'bar)))
63 (set-char-table-parent child parent)
64 (should (eq (char-table-parent child) parent))))
65
66(ert-deftest chartab-test-char-table-extra-slot ()
67 ;; Use any type with extra slots, e.g. 'case-table.
68 (let ((tbl (make-char-table 'case-table)))
69 (set-char-table-extra-slot tbl 1 'bar)
70 (should (eq (char-table-extra-slot tbl 1) 'bar))))
71
50(provide 'chartab-tests) 72(provide 'chartab-tests)
51;;; chartab-tests.el ends here 73;;; chartab-tests.el ends here
diff --git a/test/src/cmds-tests.el b/test/src/cmds-tests.el
index a545d0e08b5..73e933eb372 100644
--- a/test/src/cmds-tests.el
+++ b/test/src/cmds-tests.el
@@ -1,22 +1,24 @@
1;;; cmds-tests.el --- Testing some Emacs commands 1;;; cmds-tests.el --- Testing some Emacs commands -*- lexical-binding: t -*-
2 2
3;; Copyright (C) 2013-2017 Free Software Foundation, Inc. 3;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
4 4
5;; Author: Nicolas Richard <youngfrog@members.fsf.org> 5;; Author: Nicolas Richard <youngfrog@members.fsf.org>
6;; Keywords: 6;; Keywords:
7 7
8;; This program is free software; you can redistribute it and/or modify 8;; This file is part of GNU Emacs.
9
10;; GNU Emacs is free software: you can redistribute it and/or modify
9;; it under the terms of the GNU General Public License as published by 11;; it under the terms of the GNU General Public License as published by
10;; the Free Software Foundation, either version 3 of the License, or 12;; the Free Software Foundation, either version 3 of the License, or
11;; (at your option) any later version. 13;; (at your option) any later version.
12 14
13;; This program is distributed in the hope that it will be useful, 15;; GNU Emacs is distributed in the hope that it will be useful,
14;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16;; GNU General Public License for more details. 18;; GNU General Public License for more details.
17 19
18;; You should have received a copy of the GNU General Public License 20;; You should have received a copy of the GNU General Public License
19;; along with this program. If not, see <https://www.gnu.org/licenses/>. 21;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
20 22
21;;; Commentary: 23;;; Commentary:
22 24
@@ -30,5 +32,13 @@
30 (let ((last-command-event ?a)) 32 (let ((last-command-event ?a))
31 (should-error (self-insert-command -1)))) 33 (should-error (self-insert-command -1))))
32 34
35(ert-deftest forward-line-with-bignum ()
36 (with-temp-buffer
37 (insert "x\n")
38 (let ((shortage (forward-line (1- most-negative-fixnum))))
39 (should (= shortage most-negative-fixnum)))
40 (let ((shortage (forward-line (+ 2 most-positive-fixnum))))
41 (should (= shortage (1+ most-positive-fixnum))))))
42
33(provide 'cmds-tests) 43(provide 'cmds-tests)
34;;; cmds-tests.el ends here 44;;; cmds-tests.el ends here
diff --git a/test/src/coding-tests.el b/test/src/coding-tests.el
index e0cefa94356..f65d575d0c2 100644
--- a/test/src/coding-tests.el
+++ b/test/src/coding-tests.el
@@ -1,6 +1,6 @@
1;;; coding-tests.el --- tests for text encoding and decoding 1;;; coding-tests.el --- tests for text encoding and decoding -*- lexical-binding: t -*-
2 2
3;; Copyright (C) 2013-2017 Free Software Foundation, Inc. 3;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
4 4
5;; Author: Eli Zaretskii <eliz@gnu.org> 5;; Author: Eli Zaretskii <eliz@gnu.org>
6;; Author: Kenichi Handa <handa@gnu.org> 6;; Author: Kenichi Handa <handa@gnu.org>
@@ -56,21 +56,22 @@
56 (set-buffer-multibyte nil) 56 (set-buffer-multibyte nil)
57 (insert (encode-coding-string "あ" 'euc-jp) "\xd" "\n") 57 (insert (encode-coding-string "あ" 'euc-jp) "\xd" "\n")
58 (decode-coding-region (point-min) (point-max) 'euc-jp-dos) 58 (decode-coding-region (point-min) (point-max) 'euc-jp-dos)
59 (should-not (string-match-p "\^M" (buffer-string))))) 59 (should-not (string-search "\^M" (buffer-string)))))
60 60
61;; Return the contents (specified by CONTENT-TYPE; ascii, latin, or 61;; Return the contents (specified by CONTENT-TYPE; ascii, latin, or
62;; binary) of a test file. 62;; binary) of a test file.
63(defun coding-tests-file-contents (content-type) 63(defun coding-tests-file-contents (content-type)
64 (let* ((ascii "ABCDEFGHIJKLMNOPQRSTUVWXYZ\n") 64 (with-suppressed-warnings ((obsolete string-as-unibyte))
65 (latin (concat ascii "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ\n")) 65 (let* ((ascii "ABCDEFGHIJKLMNOPQRSTUVWXYZ\n")
66 (binary (string-to-multibyte 66 (latin (concat ascii "ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ\n"))
67 (concat (string-as-unibyte latin) 67 (binary (string-to-multibyte
68 (unibyte-string #xC0 #xC1 ?\n))))) 68 (concat (string-as-unibyte latin)
69 (cond ((eq content-type 'ascii) ascii) 69 (unibyte-string #xC0 #xC1 ?\n)))))
70 ((eq content-type 'latin) latin) 70 (cond ((eq content-type 'ascii) ascii)
71 ((eq content-type 'binary) binary) 71 ((eq content-type 'latin) latin)
72 (t 72 ((eq content-type 'binary) binary)
73 (error "Invalid file content type: %s" content-type))))) 73 (t
74 (error "Invalid file content type: %s" content-type))))))
74 75
75;; Generate FILE with CONTENTS encoded by CODING-SYSTEM. 76;; Generate FILE with CONTENTS encoded by CODING-SYSTEM.
76;; whose encoding specified by CODING-SYSTEM. 77;; whose encoding specified by CODING-SYSTEM.
@@ -143,7 +144,7 @@
143;; Optional 5th arg TRANSLATOR is a function to translate the original 144;; Optional 5th arg TRANSLATOR is a function to translate the original
144;; file contents to match with the expected result of decoding. For 145;; file contents to match with the expected result of decoding. For
145;; instance, when a file of dos eol-type is read by unix eol-type, 146;; instance, when a file of dos eol-type is read by unix eol-type,
146;; `decode-test-lf-to-crlf' must be specified. 147;; `coding-tests-lf-to-crlf' must be specified.
147 148
148(defun coding-tests (content-type write-coding read-coding detected-coding 149(defun coding-tests (content-type write-coding read-coding detected-coding
149 &optional translator) 150 &optional translator)
@@ -296,7 +297,7 @@
296;;; decoder, not for regression testing. 297;;; decoder, not for regression testing.
297 298
298(defun generate-ascii-file () 299(defun generate-ascii-file ()
299 (dotimes (i 100000) 300 (dotimes (_i 100000)
300 (insert-char ?a 80) 301 (insert-char ?a 80)
301 (insert "\n"))) 302 (insert "\n")))
302 303
@@ -309,13 +310,13 @@
309 (insert "\n"))) 310 (insert "\n")))
310 311
311(defun generate-mostly-nonascii-file () 312(defun generate-mostly-nonascii-file ()
312 (dotimes (i 30000) 313 (dotimes (_i 30000)
313 (insert-char ?a 80) 314 (insert-char ?a 80)
314 (insert "\n")) 315 (insert "\n"))
315 (dotimes (i 20000) 316 (dotimes (_i 20000)
316 (insert-char ?À 80) 317 (insert-char ?À 80)
317 (insert "\n")) 318 (insert "\n"))
318 (dotimes (i 10000) 319 (dotimes (_i 10000)
319 (insert-char ?あ 80) 320 (insert-char ?あ 80)
320 (insert "\n"))) 321 (insert "\n")))
321 322
@@ -359,7 +360,7 @@
359 (delete-region (point-min) (point)))))) 360 (delete-region (point-min) (point))))))
360 361
361(defun benchmark-decoder () 362(defun benchmark-decoder ()
362 (let ((gc-cons-threshold 4000000)) 363 (let ((gc-cons-threshold (max gc-cons-threshold 4000000)))
363 (insert "Without optimization:\n") 364 (insert "Without optimization:\n")
364 (dolist (files test-file-list) 365 (dolist (files test-file-list)
365 (dolist (file (cdr files)) 366 (dolist (file (cdr files))
@@ -375,9 +376,59 @@
375 (with-temp-buffer (insert-file-contents (car file)))))) 376 (with-temp-buffer (insert-file-contents (car file))))))
376 (insert (format "%s: %s\n" (car file) result))))))) 377 (insert (format "%s: %s\n" (car file) result)))))))
377 378
378;; Local Variables: 379(ert-deftest coding-nocopy-trivial ()
379;; byte-compile-warnings: (not obsolete) 380 "Check that the NOCOPY parameter works for the trivial coding system."
380;; End: 381 (let ((s "abc"))
382 (should-not (eq (decode-coding-string s nil nil) s))
383 (should (eq (decode-coding-string s nil t) s))
384 (should-not (eq (encode-coding-string s nil nil) s))
385 (should (eq (encode-coding-string s nil t) s))))
386
387(ert-deftest coding-nocopy-ascii ()
388 "Check that the NOCOPY parameter works for ASCII-only strings."
389 (let* ((uni (apply #'string (number-sequence 0 127)))
390 (multi (string-to-multibyte uni)))
391 (dolist (s (list uni multi))
392 ;; Encodings without EOL conversion.
393 (dolist (coding '(us-ascii-unix iso-latin-1-unix utf-8-unix))
394 (should-not (eq (decode-coding-string s coding nil) s))
395 (should-not (eq (encode-coding-string s coding nil) s))
396 (should (eq (decode-coding-string s coding t) s))
397 (should (eq (encode-coding-string s coding t) s))
398 (should (eq last-coding-system-used coding)))
399
400 ;; With EOL conversion inhibited.
401 (let ((inhibit-eol-conversion t))
402 (dolist (coding '(us-ascii iso-latin-1 utf-8))
403 (should-not (eq (decode-coding-string s coding nil) s))
404 (should-not (eq (encode-coding-string s coding nil) s))
405 (should (eq (decode-coding-string s coding t) s))
406 (should (eq (encode-coding-string s coding t) s))))))
407
408 ;; Check identity decoding with EOL conversion for ASCII except CR.
409 (let* ((uni (apply #'string (delq ?\r (number-sequence 0 127))))
410 (multi (string-to-multibyte uni)))
411 (dolist (s (list uni multi))
412 (dolist (coding '(us-ascii-dos iso-latin-1-dos utf-8-dos mac-roman-mac))
413 (should-not (eq (decode-coding-string s coding nil) s))
414 (should (eq (decode-coding-string s coding t) s)))))
415
416 ;; Check identity encoding with EOL conversion for ASCII except LF.
417 (let* ((uni (apply #'string (delq ?\n (number-sequence 0 127))))
418 (multi (string-to-multibyte uni)))
419 (dolist (s (list uni multi))
420 (dolist (coding '(us-ascii-dos iso-latin-1-dos utf-8-dos mac-roman-mac))
421 (should-not (eq (encode-coding-string s coding nil) s))
422 (should (eq (encode-coding-string s coding t) s))))))
423
424
425(ert-deftest coding-check-coding-systems-region ()
426 (should (equal (check-coding-systems-region "aå" nil '(utf-8))
427 nil))
428 (should (equal (check-coding-systems-region "aåbγc" nil
429 '(utf-8 iso-latin-1 us-ascii))
430 '((iso-latin-1 3) (us-ascii 1 3))))
431 (should-error (check-coding-systems-region "å" nil '(bad-coding-system))))
381 432
382(provide 'coding-tests) 433(provide 'coding-tests)
383;; coding-tests.el ends here 434;;; coding-tests.el ends here
diff --git a/test/src/comp-resources/comp-test-45603.el b/test/src/comp-resources/comp-test-45603.el
new file mode 100644
index 00000000000..65147ee0156
--- /dev/null
+++ b/test/src/comp-resources/comp-test-45603.el
@@ -0,0 +1,29 @@
1;;; -*- lexical-binding: t; -*-
2
3;; Reduced from ivy.el.
4
5(defvar comp-test-45603-last)
6(defvar comp-test-45603-mark-prefix)
7(defvar comp-test-45603-directory)
8(defvar comp-test-45603-marked-candidates)
9
10(defun comp-test-45603--call-marked (_action)
11 (let* ((prefix-len (length comp-test-45603-mark-prefix))
12 (marked-candidates
13 (mapcar
14 (lambda (s)
15 (let ((cand (substring s prefix-len)))
16 (if comp-test-45603-directory
17 (expand-file-name cand comp-test-45603-directory)
18 cand)))
19 comp-test-45603-marked-candidates))
20 (_multi-action (comp-test-45603--get-multi-action comp-test-45603-last)))
21 marked-candidates))
22
23(defalias 'comp-test-45603--file-local-name
24 (if (fboundp 'file-local-name)
25 #'file-local-name
26 (lambda (file)
27 (or (file-remote-p file 'localname) file))))
28
29(provide 'comp-test-45603)
diff --git a/test/src/comp-resources/comp-test-funcs-dyn.el b/test/src/comp-resources/comp-test-funcs-dyn.el
new file mode 100644
index 00000000000..07f8671c6d9
--- /dev/null
+++ b/test/src/comp-resources/comp-test-funcs-dyn.el
@@ -0,0 +1,50 @@
1;;; comp-test-funcs-dyn.el --- compilation unit tested by comp-tests.el -*- lexical-binding: nil; -*-
2
3;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
4
5;; Author: Andrea Corallo <akrl@sdf.org>
6
7;; This file is part of GNU Emacs.
8
9;; GNU Emacs is free software: you can redistribute it and/or modify
10;; it under the terms of the GNU General Public License as published by
11;; the Free Software Foundation, either version 3 of the License, or
12;; (at your option) any later version.
13
14;; GNU Emacs is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;; GNU General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
20;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
21
22;;; Commentary:
23
24;;; Code:
25
26(require 'cl-lib)
27
28(defun comp-tests-ffuncall-callee-dyn-f (a b)
29 (list a b))
30
31(defun comp-tests-ffuncall-callee-opt-dyn-f (a b &optional c d)
32 (list a b c d))
33
34(defun comp-tests-ffuncall-callee-rest-dyn-f (a b &rest c)
35 (list a b c))
36
37(defun comp-tests-ffuncall-callee-opt-rest-dyn-f (a b &optional c &rest d)
38 (list a b c d))
39
40(defun comp-tests-cl-macro-exp-f ()
41 (cl-loop for xxx in '(a b)
42 for yyy = xxx
43 collect xxx))
44
45(cl-defun comp-tests-cl-uninterned-arg-parse-f (a &optional b &aux)
46 (list a b))
47
48(provide 'comp-test-dyn-funcs)
49
50;;; comp-test-funcs-dyn.el ends here
diff --git a/test/src/comp-resources/comp-test-funcs.el b/test/src/comp-resources/comp-test-funcs.el
new file mode 100644
index 00000000000..9092f040c80
--- /dev/null
+++ b/test/src/comp-resources/comp-test-funcs.el
@@ -0,0 +1,713 @@
1;;; comp-test-funcs.el --- compilation unit tested by comp-tests.el -*- lexical-binding: t; -*-
2
3;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
4
5;; Author: Andrea Corallo <akrl@sdf.org>
6
7;; This file is part of GNU Emacs.
8
9;; GNU Emacs is free software: you can redistribute it and/or modify
10;; it under the terms of the GNU General Public License as published by
11;; the Free Software Foundation, either version 3 of the License, or
12;; (at your option) any later version.
13
14;; GNU Emacs is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;; GNU General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
20;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
21
22;;; Commentary:
23
24;;; Code:
25
26(defvar comp-tests-var1 3)
27
28(defun comp-tests-varref-f ()
29 comp-tests-var1)
30
31(defun comp-tests-list-f ()
32 (list 1 2 3))
33(defun comp-tests-list2-f (a b c)
34 (list a b c))
35(defun comp-tests-car-f (x)
36 ;; Bcar
37 (car x))
38(defun comp-tests-cdr-f (x)
39 ;; Bcdr
40 (cdr x))
41(defun comp-tests-car-safe-f (x)
42 ;; Bcar_safe
43 (car-safe x))
44(defun comp-tests-cdr-safe-f (x)
45 ;; Bcdr_safe
46 (cdr-safe x))
47
48(defun comp-tests-cons-car-f ()
49 (car (cons 1 2)))
50(defun comp-tests-cons-cdr-f (x)
51 (cdr (cons 'foo x)))
52
53(defun comp-tests-hint-fixnum-f (n)
54 (1+ (comp-hint-fixnum n)))
55
56(defun comp-tests-hint-cons-f (c)
57 (car (comp-hint-cons c)))
58
59(defun comp-tests-varset0-f ()
60 (setq comp-tests-var1 55))
61(defun comp-tests-varset1-f ()
62 (setq comp-tests-var1 66)
63 4)
64
65(defun comp-tests-length-f ()
66 (length '(1 2 3)))
67
68(defun comp-tests-aref-aset-f ()
69 (let ((vec (make-vector 3 0)))
70 (aset vec 2 100)
71 (aref vec 2)))
72
73(defvar comp-tests-var2 3)
74(defun comp-tests-symbol-value-f ()
75 (symbol-value 'comp-tests-var2))
76
77(defun comp-tests-concat-f (x)
78 (concat "a" "b" "c" "d"
79 (concat "a" "b" "c" (concat "a" "b" (concat "foo" x)))))
80
81(defun comp-tests-ffuncall-callee-f (x y z)
82 (list x y z))
83
84(defun comp-tests-ffuncall-callee-optional-f (a b &optional c d)
85 (list a b c d))
86
87(defun comp-tests-ffuncall-callee-rest-f (a b &rest c)
88 (list a b c))
89
90(defun comp-tests-ffuncall-callee-more8-f (p1 p2 p3 p4 p5 p6 p7 p8 p9 p10)
91 ;; More then 8 args.
92 (list p1 p2 p3 p4 p5 p6 p7 p8 p9 p10))
93
94(defun comp-tests-ffuncall-callee-more8-rest-f (p1 p2 p3 p4 p5 p6 p7 p8 p9 &rest p10)
95 ;; More then 8 args.
96 (list p1 p2 p3 p4 p5 p6 p7 p8 p9 p10))
97
98(defun comp-tests-ffuncall-native-f ()
99 "Call a primitive with no dedicate op."
100 (make-vector 1 nil))
101
102(defun comp-tests-ffuncall-native-rest-f ()
103 "Call a primitive with no dedicate op with &rest."
104 (vector 1 2 3))
105
106(defun comp-tests-ffuncall-apply-many-f (x)
107 (apply #'list x))
108
109(defun comp-tests-ffuncall-lambda-f (x)
110 (let ((fun (lambda (x)
111 (1+ x))))
112 (funcall fun x)))
113
114(defun comp-tests-jump-table-1-f (x)
115 (pcase x
116 ('x 'a)
117 ('y 'b)
118 (_ 'c)))
119
120(defun comp-tests-jump-table-2-f (x)
121 (pcase x
122 ("aaa" 'a)
123 ("bbb" 'b)))
124
125(defun comp-tests-conditionals-1-f (x)
126 ;; Generate goto-if-nil
127 (if x 1 2))
128(defun comp-tests-conditionals-2-f (x)
129 ;; Generate goto-if-nil-else-pop
130 (when x
131 1340))
132
133(defun comp-tests-fixnum-1-minus-f (x)
134 ;; Bsub1
135 (1- x))
136(defun comp-tests-fixnum-1-plus-f (x)
137 ;; Badd1
138 (1+ x))
139(defun comp-tests-fixnum-minus-f (x)
140 ;; Bnegate
141 (- x))
142
143(defun comp-tests-eqlsign-f (x y)
144 ;; Beqlsign
145 (= x y))
146(defun comp-tests-gtr-f (x y)
147 ;; Bgtr
148 (> x y))
149(defun comp-tests-lss-f (x y)
150 ;; Blss
151 (< x y))
152(defun comp-tests-les-f (x y)
153 ;; Bleq
154 (<= x y))
155(defun comp-tests-geq-f (x y)
156 ;; Bgeq
157 (>= x y))
158
159(defun comp-tests-setcar-f (x y)
160 (setcar x y)
161 x)
162(defun comp-tests-setcdr-f (x y)
163 (setcdr x y)
164 x)
165
166(defun comp-bubble-sort-f (list)
167 (let ((i (length list)))
168 (while (> i 1)
169 (let ((b list))
170 (while (cdr b)
171 (when (< (cadr b) (car b))
172 (setcar b (prog1 (cadr b)
173 (setcdr b (cons (car b) (cddr b))))))
174 (setq b (cdr b))))
175 (setq i (1- i)))
176 list))
177
178(defun comp-tests-consp-f (x)
179 ;; Bconsp
180 (consp x))
181(defun comp-tests-setcar2-f (x)
182 ;; Bsetcar
183 (setcar x 3))
184
185(defun comp-tests-integerp-f (x)
186 ;; Bintegerp
187 (integerp x))
188(defun comp-tests-numberp-f (x)
189 ;; Bnumberp
190 (numberp x))
191
192(defun comp-tests-discardn-f (_x)
193 ;; BdiscardN
194 (1+ (let ((a 1)
195 (_b)
196 (_c))
197 a)))
198(defun comp-tests-insertn-f (a b c d)
199 ;; Binsert
200 (insert a b c d))
201
202(defun comp-tests-err-arith-f ()
203 (/ 1 0))
204(defun comp-tests-err-foo-f ()
205 (error "Foo"))
206
207(defun comp-tests-condition-case-0-f ()
208 ;; Bpushhandler Bpophandler
209 (condition-case
210 err
211 (comp-tests-err-arith-f)
212 (arith-error (concat "arith-error "
213 (error-message-string err)
214 " catched"))
215 (error (concat "error "
216 (error-message-string err)
217 " catched"))))
218(defun comp-tests-condition-case-1-f ()
219 ;; Bpushhandler Bpophandler
220 (condition-case
221 err
222 (comp-tests-err-foo-f)
223 (arith-error (concat "arith-error "
224 (error-message-string err)
225 " catched"))
226 (error (concat "error "
227 (error-message-string err)
228 " catched"))))
229(defun comp-tests-catch-f (f)
230 (catch 'foo
231 (funcall f)))
232(defun comp-tests-throw-f (x)
233 (throw 'foo x))
234
235(defun comp-tests-buff0-f ()
236 (with-temp-buffer
237 (insert "foo")
238 (buffer-string)))
239
240(defun comp-tests-lambda-return-f ()
241 (lambda (x) (1+ x)))
242
243(defun comp-tests-fib-f (n)
244 (cond ((= n 0) 0)
245 ((= n 1) 1)
246 (t (+ (comp-tests-fib-f (- n 1))
247 (comp-tests-fib-f (- n 2))))))
248
249(defmacro comp-tests-macro-m (x)
250 x)
251
252(defun comp-tests-string-trim-f (url)
253 (string-trim url))
254
255(defun comp-tests-trampoline-removal-f ()
256 (make-hash-table))
257
258(defun comp-tests-signal-f ()
259 (signal 'foo t))
260
261(defun comp-tests-func-call-removal-f ()
262 (let ((a 10)
263 (b 3))
264 (% a b)))
265
266(defun comp-tests-doc-f ()
267 "A nice docstring."
268 t)
269
270(defun comp-test-interactive-form0-f (dir)
271 (interactive "D")
272 dir)
273
274(defun comp-test-interactive-form1-f (x y)
275 (interactive '(1 2))
276 (+ x y))
277
278(defun comp-test-interactive-form2-f ()
279 (interactive))
280
281(defun comp-test-40187-2-f ()
282 'foo)
283
284(defalias 'comp-test-40187-1-f (symbol-function 'comp-test-40187-2-f))
285
286(defun comp-test-40187-2-f ()
287 'bar)
288
289(defun comp-test-speed--1-f ()
290 (declare (speed -1))
291 3)
292
293(defun comp-test-42360-f (str end-column
294 &optional start-column padding ellipsis
295 ellipsis-text-property)
296 ;; From `truncate-string-to-width'. A large enough function to
297 ;; potentially use all registers and that is modifying local
298 ;; variables inside condition-case.
299 (let ((str-len (length str))
300 (_str-width 14)
301 (_ellipsis-width 3)
302 (idx 0)
303 (column 0)
304 (head-padding "") (tail-padding "")
305 ch last-column last-idx from-idx)
306 (condition-case nil
307 (while (< column start-column)
308 (setq ch (aref str idx)
309 column (+ column (char-width ch))
310 idx (1+ idx)))
311 (args-out-of-range (setq idx str-len)))
312 (if (< column start-column)
313 (if padding (make-string end-column padding) "")
314 (when (and padding (> column start-column))
315 (setq head-padding (make-string (- column start-column) padding)))
316 (setq from-idx idx)
317 (when (>= end-column column)
318 (condition-case nil
319 (while (< column end-column)
320 (setq last-column column
321 last-idx idx
322 ch (aref str idx)
323 column (+ column (char-width ch))
324 idx (1+ idx)))
325 (args-out-of-range (setq idx str-len)))
326 (when (> column end-column)
327 (setq column last-column
328 idx last-idx))
329 (when (and padding (< column end-column))
330 (setq tail-padding (make-string (- end-column column) padding))))
331 (if (and ellipsis-text-property
332 (not (equal ellipsis ""))
333 idx)
334 (concat head-padding
335 (substring str from-idx idx)
336 (propertize (substring str idx) 'display (or ellipsis "")))
337 (concat head-padding (substring str from-idx idx)
338 tail-padding ellipsis)))))
339
340(defun comp-test-primitive-advice-f (x y)
341 (declare (speed 2))
342 (+ x y))
343
344(defun comp-test-primitive-redefine-f (x y)
345 (declare (speed 2))
346 (- x y))
347
348(defsubst comp-test-defsubst-f ()
349 t)
350
351(defvar comp-test-and-3-var 1)
352(defun comp-test-and-3-f (x)
353 (and (atom x)
354 comp-test-and-3-var
355 2))
356
357(defun comp-test-copy-insn-f (insn)
358 ;; From `comp-copy-insn'.
359 (if (consp insn)
360 (let (result)
361 (while (consp insn)
362 (let ((newcar (car insn)))
363 (if (or (consp (car insn)) (comp-mvar-p (car insn)))
364 (setf newcar (comp-copy-insn (car insn))))
365 (push newcar result))
366 (setf insn (cdr insn)))
367 (nconc (nreverse result)
368 (if (comp-mvar-p insn) (comp-copy-insn insn) insn)))
369 (if (comp-mvar-p insn)
370 (copy-comp-mvar insn)
371 insn)))
372
373(defun comp-test-cond-rw-1-1-f ())
374
375(defun comp-test-cond-rw-1-2-f ()
376 (let ((it (comp-test-cond-rw-1-1-f))
377 (key 't))
378 (if (or (equal it key)
379 (eq key t))
380 it
381 nil)))
382
383(defun comp-test-44968-f (start end)
384 (let ((dirlist)
385 (dir (expand-file-name start))
386 (end (expand-file-name end)))
387 (while (not (or (equal dir (car dirlist))
388 (file-equal-p dir end)))
389 (push dir dirlist)
390 (setq dir (directory-file-name (file-name-directory dir))))
391 (nreverse dirlist)))
392
393(defun comp-test-45342-f (n)
394 (pcase n
395 (1 " ➊") (2 " ➋") (3 " ➌") (4 " ➍") (5 " ➎") (6 " ➏")
396 (7 " ➐") (8 " ➑") (9 " ➒") (10 " ➓") (_ "")))
397
398(defun comp-test-assume-double-neg-f (collection value)
399 ;; Reduced from `auth-source-search-collection'.
400 (when (atom collection)
401 (setq collection (list collection)))
402 (or (eq value t)
403 ;; value is (not (member t))
404 (eq collection value)
405 ;; collection is t, not (member t)!
406 (member value collection)))
407
408(defun comp-test-assume-in-loop-1-f (arg)
409 ;; Reduced from `comint-delim-arg'.
410 (let ((args nil)
411 (pos 0)
412 (len (length arg)))
413 (while (< pos len)
414 (let ((start pos))
415 (while (< pos len)
416 (setq pos (1+ pos)))
417 (setq args (cons (substring arg start pos) args))))
418 args))
419
420(defun comp-test-45376-1-f ()
421 ;; Reduced from `eshell-ls-find-column-lengths'.
422 (let* (res
423 (len 2)
424 (i 0)
425 (j 0))
426 (while (< j len)
427 (if (= i len)
428 (setq i 0))
429 (setq res (cons i res)
430 j (1+ j)
431 i (1+ i)))
432 res))
433
434(defun comp-test-45376-2-f ()
435 ;; Also reduced from `eshell-ls-find-column-lengths'.
436 (let* ((x 1)
437 res)
438 (while x
439 (let* ((y 4)
440 (i 0))
441 (while (> y 0)
442 (when (= i x)
443 (setq i 0))
444 (setf res (cons i res))
445 (setq y (1- y)
446 i (1+ i)))
447 (if (>= x 3)
448 (setq x nil)
449 (setq x (1+ x)))))
450 res))
451
452(defun comp-test-not-cons-f (x)
453 ;; Reduced from `cl-copy-list'.
454 (if (consp x)
455 (print x)
456 (car x)))
457
458(defun comp-test-45576-f ()
459 ;; Reduced from `eshell-find-alias-function'.
460 (let ((sym (intern-soft "eval")))
461 (if (and (functionp sym)
462 '(eshell-ls eshell-pred eshell-prompt eshell-script
463 eshell-term eshell-unix))
464 sym)))
465
466(defun comp-test-45635-f (&rest args)
467 ;; Reduced from `set-face-attribute'.
468 (let ((spec args)
469 family)
470 (while spec
471 (cond ((eq (car spec) :family)
472 (setq family (cadr spec))))
473 (setq spec (cddr spec)))
474 (when (and (stringp family)
475 (string-match "\\([^-]*\\)-\\([^-]*\\)" family))
476 (setq family (match-string 2 family)))
477 (when (or (stringp family)
478 (eq family 'unspecified))
479 family)))
480
481;; This function doesn't have a doc string on purpose.
482(defun comp-test-46670-1-f (_)
483 "foo")
484
485(defun comp-test-46670-2-f (s)
486 (and (equal (comp-test-46670-1-f (length s)) s)
487 s))
488
489(cl-defun comp-test-46824-1-f ()
490 (let ((next-repos '(1)))
491 (while t
492 (let ((_recipe (car next-repos)))
493 (cl-block loop
494 (while t
495 (let ((err
496 (condition-case e
497 (progn
498 (setq next-repos
499 (cdr next-repos))
500 (cl-return-from loop))
501 (error e))))
502 (format "%S"
503 (error-message-string err))))))
504 (cl-return-from comp-test-46824-1-f))))
505
506(defun comp-test-47868-1-f ()
507 " ")
508
509(defun comp-test-47868-2-f ()
510 #(" " 0 1 (face font-lock-keyword-face)))
511
512(defun comp-test-47868-3-f ()
513 " ")
514
515(defun comp-test-47868-4-f ()
516 #(" " 0 1 (face font-lock-keyword-face)))
517
518(defun comp-test-48029-nonascii-žžž-f (arg)
519 (when arg t))
520
521
522;;;;;;;;;;;;;;;;;;;;
523;; Tromey's tests ;;
524;;;;;;;;;;;;;;;;;;;;
525
526;; Test Bconsp.
527(defun comp-test-consp (x) (consp x))
528
529;; Test Blistp.
530(defun comp-test-listp (x) (listp x))
531
532;; Test Bstringp.
533(defun comp-test-stringp (x) (stringp x))
534
535;; Test Bsymbolp.
536(defun comp-test-symbolp (x) (symbolp x))
537
538;; Test Bintegerp.
539(defun comp-test-integerp (x) (integerp x))
540
541;; Test Bnumberp.
542(defun comp-test-numberp (x) (numberp x))
543
544;; Test Badd1.
545(defun comp-test-add1 (x) (1+ x))
546
547;; Test Bsub1.
548(defun comp-test-sub1 (x) (1- x))
549
550;; Test Bneg.
551(defun comp-test-negate (x) (- x))
552
553;; Test Bnot.
554(defun comp-test-not (x) (not x))
555
556;; Test Bbobp, Beobp, Bpoint, Bpoint_min, Bpoint_max.
557(defun comp-test-bobp () (bobp))
558(defun comp-test-eobp () (eobp))
559(defun comp-test-point () (point))
560(defun comp-test-point-min () (point-min))
561(defun comp-test-point-max () (point-max))
562
563;; Test Bcar and Bcdr.
564(defun comp-test-car (x) (car x))
565(defun comp-test-cdr (x) (cdr x))
566
567;; Test Bcar_safe and Bcdr_safe.
568(defun comp-test-car-safe (x) (car-safe x))
569(defun comp-test-cdr-safe (x) (cdr-safe x))
570
571;; Test Beq.
572(defun comp-test-eq (x y) (eq x y))
573
574;; Test Bgotoifnil.
575(defun comp-test-if (x y) (if x x y))
576
577;; Test Bgotoifnilelsepop.
578(defun comp-test-and (x y) (and x y))
579
580;; Test Bgotoifnonnilelsepop.
581(defun comp-test-or (x y) (or x y))
582
583;; Test Bsave_excursion.
584(defun comp-test-save-excursion ()
585 (save-excursion
586 (insert "XYZ")))
587
588;; Test Bcurrent_buffer.
589(defun comp-test-current-buffer () (current-buffer))
590
591;; Test Bgtr.
592(defun comp-test-> (a b)
593 (> a b))
594
595;; Test Bpushcatch.
596(defun comp-test-catch (&rest l)
597 (catch 'done
598 (dolist (v l)
599 (when (> v 23)
600 (throw 'done v)))))
601
602;; Test Bmemq.
603(defun comp-test-memq (val list)
604 (memq val list))
605
606;; Test BlistN.
607(defun comp-test-listN (x)
608 (list x x x x x x x x x x x x x x x x))
609
610;; Test BconcatN.
611(defun comp-test-concatN (x)
612 (concat x x x x x x))
613
614;; Test optional and rest arguments.
615(defun comp-test-opt-rest (a &optional b &rest c)
616 (list a b c))
617
618;; Test for too many arguments.
619(defun comp-test-opt (a &optional b)
620 (cons a b))
621
622;; Test for unwind-protect.
623(defvar comp-test-up-val nil)
624(defun comp-test-unwind-protect (fun)
625 (setq comp-test-up-val nil)
626 (unwind-protect
627 (progn
628 (setq comp-test-up-val 23)
629 (funcall fun)
630 (setq comp-test-up-val 24))
631 (setq comp-test-up-val 999)))
632
633;; Non tested functions that proved just to be difficult to compile.
634
635(defun comp-test-callee (_ __) t)
636(defun comp-test-silly-frame1 (x)
637 ;; Check robustness against dead code.
638 (cl-case x
639 (0 (comp-test-callee
640 (pcase comp-tests-var1
641 (1 1)
642 (2 2))
643 3))))
644
645(defun comp-test-silly-frame2 (_token)
646 ;; Check robustness against dead code.
647 (while c
648 (cl-case c
649 (?< 1)
650 (?> 2))))
651
652(defun comp-test-big-interactive (filename &optional force arg load)
653 "Check non trivial interactive form using `byte-recompile-file'."
654 (interactive
655 (let ((file buffer-file-name)
656 (file-name nil)
657 (file-dir nil))
658 (and file
659 (derived-mode-p 'emacs-lisp-mode)
660 (setq file-name (file-name-nondirectory file)
661 file-dir (file-name-directory file)))
662 (list (read-file-name (if current-prefix-arg
663 "Byte compile file: "
664 "Byte recompile file: ")
665 file-dir file-name nil)
666 current-prefix-arg)))
667 (let ((dest (byte-compile-dest-file filename))
668 ;; Expand now so we get the current buffer's defaults
669 (filename (expand-file-name filename)))
670 (if (if (file-exists-p dest)
671 ;; File was already compiled
672 ;; Compile if forced to, or filename newer
673 (or force
674 (file-newer-than-file-p filename dest))
675 (and arg
676 (or (eq 0 arg)
677 (y-or-n-p (concat "Compile "
678 filename "? ")))))
679 (progn
680 (if (and noninteractive (not byte-compile-verbose))
681 (message "Compiling %s..." filename))
682 (byte-compile-file filename))
683 (when load
684 (load (if (file-exists-p dest) dest filename)))
685 'no-byte-compile)))
686
687(defun comp-test-no-return-1 (x)
688 (while x
689 (error "Foo")))
690
691(defun comp-test-no-return-2 (x)
692 (cond
693 ((eql x '2) t)
694 ((error "Bar") nil)))
695
696(defun comp-test-no-return-3 ())
697(defun comp-test-no-return-4 (x)
698 (when x
699 (error "Foo")
700 (while (comp-test-no-return-3)
701 (comp-test-no-return-3))))
702
703(defun comp-test-=-nan (x)
704 (when (= x 0.0e+NaN)
705 x))
706
707(defun comp-test-=-infinity (x)
708 (when (= x 1.0e+INF)
709 x))
710
711(provide 'comp-test-funcs)
712
713;;; comp-test-funcs.el ends here
diff --git a/test/src/comp-resources/comp-test-pure.el b/test/src/comp-resources/comp-test-pure.el
new file mode 100644
index 00000000000..788739e04cc
--- /dev/null
+++ b/test/src/comp-resources/comp-test-pure.el
@@ -0,0 +1,40 @@
1;;; comp-test-pure.el --- compilation unit tested by comp-tests.el -*- lexical-binding: t; -*-
2
3;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
4
5;; Author: Andrea Corallo <akrl@sdf.org>
6
7;; This file is part of GNU Emacs.
8
9;; GNU Emacs is free software: you can redistribute it and/or modify
10;; it under the terms of the GNU General Public License as published by
11;; the Free Software Foundation, either version 3 of the License, or
12;; (at your option) any later version.
13
14;; GNU Emacs is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;; GNU General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
20;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
21
22;;; Commentary:
23
24;;; Code:
25
26(defun comp-tests-pure-callee-f (x)
27 (1+ x))
28
29(defun comp-tests-pure-caller-f ()
30 (comp-tests-pure-callee-f 3))
31
32(defun comp-tests-pure-fibn-f (a b count)
33 (if (= count 0)
34 b
35 (comp-tests-pure-fibn-f (+ a b) a (- count 1))))
36
37(defun comp-tests-pure-fibn-entry-f ()
38 (comp-tests-pure-fibn-f 1 0 20))
39
40;;; comp-test-pure.el ends here
diff --git a/test/src/comp-tests.el b/test/src/comp-tests.el
new file mode 100644
index 00000000000..1edbd1777c6
--- /dev/null
+++ b/test/src/comp-tests.el
@@ -0,0 +1,1480 @@
1;;; comp-tests.el --- unit tests for src/comp.c -*- lexical-binding: t; -*-
2
3;; Copyright (C) 2019-2022 Free Software Foundation, Inc.
4
5;; Author: Andrea Corallo <akrl@sdf.org>
6
7;; This file is part of GNU Emacs.
8
9;; GNU Emacs is free software: you can redistribute it and/or modify
10;; it under the terms of the GNU General Public License as published by
11;; the Free Software Foundation, either version 3 of the License, or
12;; (at your option) any later version.
13
14;; GNU Emacs is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;; GNU General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
20;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
21
22;;; Commentary:
23
24;; Unit tests for src/comp.c.
25
26;;; Code:
27
28(require 'ert)
29(require 'ert-x)
30(require 'cl-lib)
31(require 'comp)
32(require 'comp-cstr)
33
34(eval-and-compile
35 (defconst comp-test-src (ert-resource-file "comp-test-funcs.el"))
36 (defconst comp-test-dyn-src (ert-resource-file "comp-test-funcs-dyn.el")))
37
38(when (native-comp-available-p)
39 (message "Compiling tests...")
40 (load (native-compile comp-test-src))
41 (load (native-compile comp-test-dyn-src)))
42
43;; Load the test code here so the compiler can check the function
44;; names used in this file.
45(require 'comp-test-funcs comp-test-src)
46(require 'comp-test-dyn-funcs comp-test-dyn-src) ;Non-standard feature name!
47
48(defmacro comp-deftest (name args &rest docstring-and-body)
49 "Define a test for the native compiler tagging it as :nativecomp."
50 (declare (indent defun)
51 (doc-string 3))
52 `(ert-deftest ,(intern (concat "comp-tests-" (symbol-name name))) ,args
53 :tags '(:nativecomp)
54 ,@(and (stringp (car docstring-and-body))
55 (list (pop docstring-and-body)))
56 ;; Some of the tests leave spill files behind -- so create a
57 ;; sub-dir where native-comp can do its work, and then delete it
58 ;; at the end.
59 (ert-with-temp-directory dir
60 (let ((temporary-file-directory dir))
61 ,@docstring-and-body))))
62
63
64
65(ert-deftest comp-tests-bootstrap ()
66 "Compile the compiler and load it to compile it-self.
67Check that the resulting binaries do not differ."
68 :tags '(:expensive-test :nativecomp)
69 (ert-with-temp-file comp1-src
70 :suffix "-comp-stage1.el"
71 (ert-with-temp-file comp2-src
72 :suffix "-comp-stage2.el"
73 (let* ((byte+native-compile t) ; FIXME HACK
74 (comp-src (expand-file-name "../../../lisp/emacs-lisp/comp.el"
75 (ert-resource-directory)))
76 ;; Can't use debug symbols.
77 (native-comp-debug 0))
78 (copy-file comp-src comp1-src t)
79 (copy-file comp-src comp2-src t)
80 (let ((load-no-native t))
81 (load (concat comp-src "c") nil nil t t))
82 (should-not (subr-native-elisp-p (symbol-function 'native-compile)))
83 (message "Compiling stage1...")
84 (let* ((t0 (current-time))
85 (comp1-eln (native-compile comp1-src)))
86 (message "Done in %d secs" (float-time (time-since t0)))
87 (load comp1-eln nil nil t t)
88 (should (subr-native-elisp-p (symbol-function 'native-compile)))
89 (message "Compiling stage2...")
90 (let ((t0 (current-time))
91 (comp2-eln (native-compile comp2-src)))
92 (message "Done in %d secs" (float-time (time-since t0)))
93 (message "Comparing %s %s" comp1-eln comp2-eln)
94 (should (= (call-process "cmp" nil nil nil comp1-eln comp2-eln) 0))))))))
95
96(comp-deftest provide ()
97 "Testing top level provide."
98 (should (featurep 'comp-test-funcs)))
99
100(comp-deftest varref ()
101 "Testing varref."
102 (should (= (comp-tests-varref-f) 3)))
103
104(comp-deftest list ()
105 "Testing cons car cdr."
106 (should (equal (comp-tests-list-f) '(1 2 3)))
107 (should (equal (comp-tests-list2-f 1 2 3) '(1 2 3)))
108 (should (= (comp-tests-car-f '(1 . 2)) 1))
109 (should (null (comp-tests-car-f nil)))
110 (should-error (comp-tests-car-f 3)
111 :type 'wrong-type-argument)
112 (should (= (comp-tests-cdr-f '(1 . 2)) 2))
113 (should (null (comp-tests-cdr-f nil)))
114 (should-error (comp-tests-cdr-f 3)
115 :type 'wrong-type-argument)
116 (should (= (comp-tests-car-safe-f '(1 . 2)) 1))
117 (should (null (comp-tests-car-safe-f 'a)))
118 (should (= (comp-tests-cdr-safe-f '(1 . 2)) 2))
119 (should (null (comp-tests-cdr-safe-f 'a))))
120
121(comp-deftest comp-tests-cons-car-cdr ()
122 "Testing cons car cdr."
123 (should (= (comp-tests-cons-car-f) 1))
124 (should (= (comp-tests-cons-cdr-f 3) 3)))
125
126(comp-deftest varset ()
127 "Testing varset."
128 (comp-tests-varset0-f)
129 (should (= comp-tests-var1 55))
130
131 (should (= (comp-tests-varset1-f) 4))
132 (should (= comp-tests-var1 66)))
133
134(comp-deftest length ()
135 "Testing length."
136 (should (= (comp-tests-length-f) 3)))
137
138(comp-deftest aref-aset ()
139 "Testing aref and aset."
140 (should (= (comp-tests-aref-aset-f) 100)))
141
142(comp-deftest symbol-value ()
143 "Testing aref and aset."
144 (should (= (comp-tests-symbol-value-f) 3)))
145
146(comp-deftest concat ()
147 "Testing concatX opcodes."
148 (should (string= (comp-tests-concat-f "bar") "abcdabcabfoobar")))
149
150(comp-deftest ffuncall ()
151 "Test calling conventions."
152
153 ;; (defun comp-tests-ffuncall-caller-f ()
154 ;; (comp-tests-ffuncall-callee-f 1 2 3))
155
156 ;; (should (equal (comp-tests-ffuncall-caller-f) '(1 2 3)))
157
158 ;; ;; After it gets compiled
159 ;; (native-compile #'comp-tests-ffuncall-callee-f)
160 ;; (should (equal (comp-tests-ffuncall-caller-f) '(1 2 3)))
161
162 ;; ;; Recompiling the caller once with callee already compiled
163 ;; (defun comp-tests-ffuncall-caller-f ()
164 ;; (comp-tests-ffuncall-callee-f 1 2 3))
165 ;; (should (equal (comp-tests-ffuncall-caller-f) '(1 2 3)))
166
167 (should (equal (comp-tests-ffuncall-callee-optional-f 1 2 3 4)
168 '(1 2 3 4)))
169 (should (equal (comp-tests-ffuncall-callee-optional-f 1 2 3)
170 '(1 2 3 nil)))
171 (should (equal (comp-tests-ffuncall-callee-optional-f 1 2)
172 '(1 2 nil nil)))
173
174 (should (equal (comp-tests-ffuncall-callee-rest-f 1 2)
175 '(1 2 nil)))
176 (should (equal (comp-tests-ffuncall-callee-rest-f 1 2 3)
177 '(1 2 (3))))
178 (should (equal (comp-tests-ffuncall-callee-rest-f 1 2 3 4)
179 '(1 2 (3 4))))
180
181 (should (equal (comp-tests-ffuncall-callee-more8-f 1 2 3 4 5 6 7 8 9 10)
182 '(1 2 3 4 5 6 7 8 9 10)))
183
184 (should (equal (comp-tests-ffuncall-callee-more8-rest-f 1 2 3 4 5 6 7 8 9 10 11)
185 '(1 2 3 4 5 6 7 8 9 (10 11))))
186
187 (should (equal (comp-tests-ffuncall-native-f) [nil]))
188
189 (should (equal (comp-tests-ffuncall-native-rest-f) [1 2 3]))
190
191 (should (equal (comp-tests-ffuncall-apply-many-f '(1 2 3))
192 '(1 2 3)))
193
194 (should (= (comp-tests-ffuncall-lambda-f 1) 2)))
195
196(comp-deftest jump-table ()
197 "Testing jump tables"
198 (should (eq (comp-tests-jump-table-1-f 'x) 'a))
199 (should (eq (comp-tests-jump-table-1-f 'y) 'b))
200 (should (eq (comp-tests-jump-table-1-f 'xxx) 'c))
201
202 ;; Jump table not with eq as test
203 (should (eq (comp-tests-jump-table-2-f "aaa") 'a))
204 (should (eq (comp-tests-jump-table-2-f "bbb") 'b)))
205
206(comp-deftest conditionals ()
207 "Testing conditionals."
208 (should (= (comp-tests-conditionals-1-f t) 1))
209 (should (= (comp-tests-conditionals-1-f nil) 2))
210 (should (= (comp-tests-conditionals-2-f t) 1340))
211 (should (eq (comp-tests-conditionals-2-f nil) nil)))
212
213(comp-deftest fixnum ()
214 "Testing some fixnum inline operation."
215 (should (= (comp-tests-fixnum-1-minus-f 10) 9))
216 (should (= (comp-tests-fixnum-1-minus-f most-negative-fixnum)
217 (1- most-negative-fixnum)))
218 (should-error (comp-tests-fixnum-1-minus-f 'a)
219 :type 'wrong-type-argument)
220 (should (= (comp-tests-fixnum-1-plus-f 10) 11))
221 (should (= (comp-tests-fixnum-1-plus-f most-positive-fixnum)
222 (1+ most-positive-fixnum)))
223 (should-error (comp-tests-fixnum-1-plus-f 'a)
224 :type 'wrong-type-argument)
225 (should (= (comp-tests-fixnum-minus-f 10) -10))
226 (should (= (comp-tests-fixnum-minus-f most-negative-fixnum)
227 (- most-negative-fixnum)))
228 (should-error (comp-tests-fixnum-minus-f 'a)
229 :type 'wrong-type-argument))
230
231(comp-deftest type-hints ()
232 "Just test compiler hints are transparent in this case."
233 ;; FIXME we should really check they are also effective.
234 (should (= (comp-tests-hint-fixnum-f 3) 4))
235 (should (= (comp-tests-hint-cons-f (cons 1 2)) 1)))
236
237(comp-deftest arith-comp ()
238 "Testing arithmetic comparisons."
239 (should (eq (comp-tests-eqlsign-f 4 3) nil))
240 (should (eq (comp-tests-eqlsign-f 3 3) t))
241 (should (eq (comp-tests-eqlsign-f 2 3) nil))
242 (should (eq (comp-tests-gtr-f 4 3) t))
243 (should (eq (comp-tests-gtr-f 3 3) nil))
244 (should (eq (comp-tests-gtr-f 2 3) nil))
245 (should (eq (comp-tests-lss-f 4 3) nil))
246 (should (eq (comp-tests-lss-f 3 3) nil))
247 (should (eq (comp-tests-lss-f 2 3) t))
248 (should (eq (comp-tests-les-f 4 3) nil))
249 (should (eq (comp-tests-les-f 3 3) t))
250 (should (eq (comp-tests-les-f 2 3) t))
251 (should (eq (comp-tests-geq-f 4 3) t))
252 (should (eq (comp-tests-geq-f 3 3) t))
253 (should (eq (comp-tests-geq-f 2 3) nil)))
254
255(comp-deftest setcarcdr ()
256 "Testing setcar setcdr."
257 (should (equal (comp-tests-setcar-f '(10 . 10) 3) '(3 . 10)))
258 (should (equal (comp-tests-setcdr-f '(10 . 10) 3) '(10 . 3)))
259 (should-error (comp-tests-setcar-f 3 10)
260 :type 'wrong-type-argument)
261 (should-error (comp-tests-setcdr-f 3 10)
262 :type 'wrong-type-argument))
263
264(comp-deftest bubble-sort ()
265 "Run bubble sort."
266 (let* ((list1 (mapcar #'random (make-list 1000 most-positive-fixnum)))
267 (list2 (copy-sequence list1)))
268 (should (equal (comp-bubble-sort-f list1)
269 (sort list2 #'<)))))
270
271(comp-deftest apply ()
272 "Test some inlined list functions."
273 (should (eq (comp-tests-consp-f '(1)) t))
274 (should (eq (comp-tests-consp-f 1) nil))
275 (let ((x (cons 1 2)))
276 (should (= (comp-tests-setcar2-f x) 3))
277 (should (equal x '(3 . 2)))))
278
279(comp-deftest num-inline ()
280 "Test some inlined number functions."
281 (should (eq (comp-tests-integerp-f 1) t))
282 (should (eq (comp-tests-integerp-f '(1)) nil))
283 (should (eq (comp-tests-integerp-f 3.5) nil))
284 (should (eq (comp-tests-integerp-f (1+ most-negative-fixnum)) t))
285
286 (should (eq (comp-tests-numberp-f 1) t))
287 (should (eq (comp-tests-numberp-f 'a) nil))
288 (should (eq (comp-tests-numberp-f 3.5) t)))
289
290(comp-deftest stack ()
291 "Test some stack operation."
292 (should (= (comp-tests-discardn-f 10) 2))
293 (should (string= (with-temp-buffer
294 (comp-tests-insertn-f "a" "b" "c" "d")
295 (buffer-string))
296 "abcd")))
297
298(comp-deftest non-locals ()
299 "Test non locals."
300 (should (string= (comp-tests-condition-case-0-f)
301 "arith-error Arithmetic error catched"))
302 (should (string= (comp-tests-condition-case-1-f)
303 "error Foo catched"))
304 (should (= (comp-tests-catch-f
305 (lambda () (throw 'foo 3)))
306 3))
307 (should (= (catch 'foo
308 (comp-tests-throw-f 3)))))
309
310(comp-deftest gc ()
311 "Try to do some longer computation to let the GC kick in."
312 (dotimes (_ 100000)
313 (comp-tests-cons-cdr-f 3))
314 (should (= (comp-tests-cons-cdr-f 3) 3)))
315
316(comp-deftest buffer ()
317 (should (string= (comp-tests-buff0-f) "foo")))
318
319(comp-deftest lambda-return ()
320 (let ((f (comp-tests-lambda-return-f)))
321 (should (subr-native-elisp-p f))
322 (should (= (funcall f 3) 4))))
323
324(comp-deftest recursive ()
325 (should (= (comp-tests-fib-f 10) 55)))
326
327(comp-deftest macro ()
328 "Just check we can define macros"
329 (should (macrop (symbol-function 'comp-tests-macro-m))))
330
331(comp-deftest string-trim ()
332 (should (string= (comp-tests-string-trim-f "dsaf ") "dsaf")))
333
334(comp-deftest trampoline-removal ()
335 ;; This tests that we can call primitives with no dedicated bytecode.
336 ;; At speed >= 2 the trampoline will not be used.
337 (should (hash-table-p (comp-tests-trampoline-removal-f))))
338
339(comp-deftest signal ()
340 (should (equal (condition-case err
341 (comp-tests-signal-f)
342 (t err))
343 '(foo . t))))
344
345(comp-deftest func-call-removal ()
346 ;; See `comp-propagate-insn' `comp-function-call-remove'.
347 (should (= (comp-tests-func-call-removal-f) 1)))
348
349(comp-deftest doc ()
350 (should (string= (documentation #'comp-tests-doc-f)
351 "A nice docstring."))
352 ;; Check a preloaded function, we can't use `comp-tests-doc-f' now
353 ;; as this is loaded manually with no .elc.
354 (should (string-match "\\.*.elc\\'" (symbol-file #'error))))
355
356(comp-deftest interactive-form ()
357 (should (equal (interactive-form #'comp-test-interactive-form0-f)
358 '(interactive "D")))
359 (should (equal (interactive-form #'comp-test-interactive-form1-f)
360 '(interactive '(1 2))))
361 (should (equal (interactive-form #'comp-test-interactive-form2-f)
362 '(interactive nil)))
363 (should (cl-every #'commandp '(comp-test-interactive-form0-f
364 comp-test-interactive-form1-f
365 comp-test-interactive-form2-f)))
366 (should-not (commandp #'comp-tests-doc-f)))
367
368(declare-function comp-tests-free-fun-f nil)
369
370(comp-deftest free-fun ()
371 "Check we are able to compile a single function."
372 (eval '(defun comp-tests-free-fun-f ()
373 "Some doc."
374 (interactive)
375 3)
376 t)
377 (native-compile #'comp-tests-free-fun-f)
378
379 (should (subr-native-elisp-p (symbol-function 'comp-tests-free-fun-f)))
380 (should (= (comp-tests-free-fun-f) 3))
381 (should (string= (documentation #'comp-tests-free-fun-f)
382 "Some doc."))
383 (should (commandp #'comp-tests-free-fun-f))
384 (should (equal (interactive-form #'comp-tests-free-fun-f)
385 '(interactive))))
386
387(declare-function comp-tests/free\fun-f nil)
388
389(comp-deftest free-fun-silly-name ()
390 "Check we are able to compile a single function."
391 (eval '(defun comp-tests/free\fun-f ()) t)
392 (native-compile #'comp-tests/free\fun-f)
393 (should (subr-native-elisp-p (symbol-function 'comp-tests/free\fun-f))))
394
395(comp-deftest bug-40187 ()
396 "Check function name shadowing.
397https://lists.gnu.org/archive/html/bug-gnu-emacs/2020-03/msg00914.html."
398 (should (eq (comp-test-40187-1-f) 'foo))
399 (should (eq (comp-test-40187-2-f) 'bar)))
400
401(comp-deftest speed--1 ()
402 "Check that at speed -1 we do not native compile."
403 (should (= (comp-test-speed--1-f) 3))
404 (should-not (subr-native-elisp-p (symbol-function 'comp-test-speed--1-f))))
405
406(comp-deftest bug-42360 ()
407 "<https://lists.gnu.org/archive/html/bug-gnu-emacs/2020-07/msg00418.html>."
408 (should (string= (comp-test-42360-f "Nel mezzo del " 18 0 32 "yyy" nil)
409 "Nel mezzo del yyy")))
410
411(comp-deftest bug-44968 ()
412 "<https://lists.gnu.org/archive/html/bug-gnu-emacs/2020-11/msg02357.html>"
413 (comp-test-44968-f "/tmp/test/foo" "/tmp"))
414
415(comp-deftest bug-45342 ()
416 "Preserve multibyte immediate strings.
417<https://lists.gnu.org/archive/html/bug-gnu-emacs/2020-12/msg01771.html>"
418 (should (string= " ➊" (comp-test-45342-f 1))))
419
420(comp-deftest assume-double-neg ()
421 "In fwprop assumptions (not (not (member x))) /= (member x)."
422 (should-not (comp-test-assume-double-neg-f "bar" "foo")))
423
424(comp-deftest assume-in-loop-1 ()
425 "Broken call args assumptions lead to infinite loop."
426 (should (equal (comp-test-assume-in-loop-1-f "cd") '("cd"))))
427
428(comp-deftest bug-45376-1 ()
429 "<https://lists.gnu.org/archive/html/bug-gnu-emacs/2020-12/msg01883.html>"
430 (should (equal (comp-test-45376-1-f) '(1 0))))
431
432(comp-deftest bug-45376-2 ()
433 "<https://lists.gnu.org/archive/html/bug-gnu-emacs/2020-12/msg01883.html>"
434 (should (equal (comp-test-45376-2-f) '(0 2 1 0 1 0 1 0 0 0 0 0))))
435
436(defvar comp-test-primitive-advice)
437(comp-deftest primitive-advice ()
438 "Test effectiveness of primitive advising."
439 (let (comp-test-primitive-advice
440 (f (lambda (&rest args)
441 (setq comp-test-primitive-advice args))))
442 (advice-add #'+ :before f)
443 (unwind-protect
444 (progn
445 (should (= (comp-test-primitive-advice-f 3 4) 7))
446 (should (equal comp-test-primitive-advice '(3 4))))
447 (advice-remove #'+ f))))
448
449(defvar comp-test-primitive-redefine-args)
450(comp-deftest primitive-redefine ()
451 "Test effectiveness of primitive redefinition."
452 (cl-letf ((comp-test-primitive-redefine-args nil)
453 ((symbol-function '-)
454 (lambda (&rest args)
455 (setq comp-test-primitive-redefine-args args)
456 'xxx)))
457 (should (eq (comp-test-primitive-redefine-f 10 2) 'xxx))
458 (should (equal comp-test-primitive-redefine-args '(10 2)))))
459
460(comp-deftest compile-forms ()
461 "Verify lambda form native compilation."
462 (should-error (native-compile '(+ 1 foo)))
463 (let ((lexical-binding t)
464 (f (native-compile '(lambda (x) (1+ x)))))
465 (should (subr-native-elisp-p f))
466 (should (= (funcall f 2) 3)))
467 (let* ((lexical-binding nil)
468 (f (native-compile '(lambda (x) (1+ x)))))
469 (should (subr-native-elisp-p f))
470 (should (= (funcall f 2) 3))))
471
472(comp-deftest comp-test-defsubst ()
473 ;; Bug#42664, Bug#43280, Bug#44209.
474 (should-not (subr-native-elisp-p (symbol-function 'comp-test-defsubst-f))))
475
476(comp-deftest primitive-redefine-compile-44221 ()
477 "Test the compiler still works while primitives are redefined (bug#44221)."
478 (cl-letf (((symbol-function 'delete-region)
479 (lambda (_ _))))
480 (should (subr-native-elisp-p
481 (native-compile
482 '(lambda ()
483 (delete-region (point-min) (point-max))))))))
484
485(comp-deftest and-3 ()
486 (should (= (comp-test-and-3-f t) 2))
487 (should (null (comp-test-and-3-f '(1 2)))))
488
489(comp-deftest copy-insn ()
490 (should (equal (comp-test-copy-insn-f '(1 2 3 (4 5 6)))
491 '(1 2 3 (4 5 6))))
492 (should (null (comp-test-copy-insn-f nil))))
493
494(comp-deftest cond-rw-1 ()
495 "Check cond-rw does not break target blocks with multiple predecessor."
496 (should (null (comp-test-cond-rw-1-2-f))))
497
498(comp-deftest not-cons-1 ()
499 (should-not (comp-test-not-cons-f nil)))
500
501(comp-deftest 45576-1 ()
502 "Functionp satisfies also symbols.
503<https://lists.gnu.org/archive/html/bug-gnu-emacs/2021-01/msg00029.html>."
504 (should (eq (comp-test-45576-f) 'eval)))
505
506(comp-deftest 45635-1 ()
507 "<https://lists.gnu.org/archive/html/bug-gnu-emacs/2021-01/msg00158.html>."
508 (should (string= (comp-test-45635-f :height 180 :family "PragmataPro Liga")
509 "PragmataPro Liga")))
510
511(comp-deftest 46670-1 ()
512 "<https://lists.gnu.org/archive/html/bug-gnu-emacs/2021-02/msg01413.html>"
513 (should (string= (comp-test-46670-2-f "foo") "foo"))
514 (should (equal (subr-type (symbol-function 'comp-test-46670-2-f))
515 '(function (t) t))))
516
517(comp-deftest 46824-1 ()
518 "<https://lists.gnu.org/archive/html/bug-gnu-emacs/2021-02/msg01949.html>"
519 (should (equal (comp-test-46824-1-f) nil)))
520
521(comp-deftest comp-test-47868-1 ()
522 "Verify string hash consing strategy.
523
524<https://lists.gnu.org/archive/html/bug-gnu-emacs/2021-04/msg00921.html>"
525 (should-not (equal-including-properties (comp-test-47868-1-f)
526 (comp-test-47868-2-f)))
527 (should (eq (comp-test-47868-1-f) (comp-test-47868-3-f)))
528 (should (eq (comp-test-47868-2-f) (comp-test-47868-4-f))))
529
530(comp-deftest 48029-1 ()
531 "<https://lists.gnu.org/archive/html/bug-gnu-emacs/2022-07/msg00666.html>"
532 (should (subr-native-elisp-p
533 (symbol-function 'comp-test-48029-nonascii-žžž-f))))
534
535
536;;;;;;;;;;;;;;;;;;;;;
537;; Tromey's tests. ;;
538;;;;;;;;;;;;;;;;;;;;;
539
540(comp-deftest consp ()
541 (should-not (comp-test-consp 23))
542 (should-not (comp-test-consp nil))
543 (should (comp-test-consp '(1 . 2))))
544
545(comp-deftest listp ()
546 (should-not (comp-test-listp 23))
547 (should (comp-test-listp nil))
548 (should (comp-test-listp '(1 . 2))))
549
550(comp-deftest stringp ()
551 (should-not (comp-test-stringp 23))
552 (should-not (comp-test-stringp nil))
553 (should (comp-test-stringp "hi")))
554
555(comp-deftest symbolp ()
556 (should-not (comp-test-symbolp 23))
557 (should-not (comp-test-symbolp "hi"))
558 (should (comp-test-symbolp 'whatever)))
559
560(comp-deftest integerp ()
561 (should (comp-test-integerp 23))
562 (should-not (comp-test-integerp 57.5))
563 (should-not (comp-test-integerp "hi"))
564 (should-not (comp-test-integerp 'whatever)))
565
566(comp-deftest numberp ()
567 (should (comp-test-numberp 23))
568 (should (comp-test-numberp 57.5))
569 (should-not (comp-test-numberp "hi"))
570 (should-not (comp-test-numberp 'whatever)))
571
572(comp-deftest add1 ()
573 (should (eq (comp-test-add1 23) 24))
574 (should (eq (comp-test-add1 -17) -16))
575 (should (eql (comp-test-add1 1.0) 2.0))
576 (should-error (comp-test-add1 nil)
577 :type 'wrong-type-argument))
578
579(comp-deftest sub1 ()
580 (should (eq (comp-test-sub1 23) 22))
581 (should (eq (comp-test-sub1 -17) -18))
582 (should (eql (comp-test-sub1 1.0) 0.0))
583 (should-error (comp-test-sub1 nil)
584 :type 'wrong-type-argument))
585
586(comp-deftest negate ()
587 (should (eq (comp-test-negate 23) -23))
588 (should (eq (comp-test-negate -17) 17))
589 (should (eql (comp-test-negate 1.0) -1.0))
590 (should-error (comp-test-negate nil)
591 :type 'wrong-type-argument))
592
593(comp-deftest not ()
594 (should (eq (comp-test-not 23) nil))
595 (should (eq (comp-test-not nil) t))
596 (should (eq (comp-test-not t) nil)))
597
598(comp-deftest bobp-and-eobp ()
599 (with-temp-buffer
600 (should (comp-test-bobp))
601 (should (comp-test-eobp))
602 (insert "hi")
603 (goto-char (point-min))
604 (should (eq (comp-test-point-min) (point-min)))
605 (should (eq (comp-test-point) (point-min)))
606 (should (comp-test-bobp))
607 (should-not (comp-test-eobp))
608 (goto-char (point-max))
609 (should (eq (comp-test-point-max) (point-max)))
610 (should (eq (comp-test-point) (point-max)))
611 (should-not (comp-test-bobp))
612 (should (comp-test-eobp))))
613
614(comp-deftest car-cdr ()
615 (let ((pair '(1 . b)))
616 (should (eq (comp-test-car pair) 1))
617 (should (eq (comp-test-car nil) nil))
618 (should-error (comp-test-car 23)
619 :type 'wrong-type-argument)
620 (should (eq (comp-test-cdr pair) 'b))
621 (should (eq (comp-test-cdr nil) nil))
622 (should-error (comp-test-cdr 23)
623 :type 'wrong-type-argument)))
624
625(comp-deftest car-cdr-safe ()
626 (let ((pair '(1 . b)))
627 (should (eq (comp-test-car-safe pair) 1))
628 (should (eq (comp-test-car-safe nil) nil))
629 (should (eq (comp-test-car-safe 23) nil))
630 (should (eq (comp-test-cdr-safe pair) 'b))
631 (should (eq (comp-test-cdr-safe nil) nil))
632 (should (eq (comp-test-cdr-safe 23) nil))))
633
634(comp-deftest eq ()
635 (should (comp-test-eq 'a 'a))
636 (should (comp-test-eq 5 5))
637 (should-not (comp-test-eq 'a 'b)))
638
639(comp-deftest if ()
640 (should (eq (comp-test-if 'a 'b) 'a))
641 (should (eq (comp-test-if 0 23) 0))
642 (should (eq (comp-test-if nil 'b) 'b)))
643
644(comp-deftest and ()
645 (should (eq (comp-test-and 'a 'b) 'b))
646 (should (eq (comp-test-and 0 23) 23))
647 (should (eq (comp-test-and nil 'b) nil)))
648
649(comp-deftest or ()
650 (should (eq (comp-test-or 'a 'b) 'a))
651 (should (eq (comp-test-or 0 23) 0))
652 (should (eq (comp-test-or nil 'b) 'b)))
653
654(comp-deftest save-excursion ()
655 (with-temp-buffer
656 (comp-test-save-excursion)
657 (should (eq (point) (point-min)))
658 (should (eq (comp-test-current-buffer) (current-buffer)))))
659
660(comp-deftest > ()
661 (should (eq (comp-test-> 0 23) nil))
662 (should (eq (comp-test-> 23 0) t)))
663
664(comp-deftest catch ()
665 (should (eq (comp-test-catch 0 1 2 3 4) nil))
666 (should (eq (comp-test-catch 20 21 22 23 24 25 26 27 28) 24)))
667
668(comp-deftest memq ()
669 (should (equal (comp-test-memq 0 '(5 4 3 2 1 0)) '(0)))
670 (should (eq (comp-test-memq 72 '(5 4 3 2 1 0)) nil)))
671
672(comp-deftest listN ()
673 (should (equal (comp-test-listN 57)
674 '(57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57))))
675
676(comp-deftest concatN ()
677 (should (equal (comp-test-concatN "x") "xxxxxx")))
678
679(comp-deftest opt-rest ()
680 (should (equal (comp-test-opt-rest 1) '(1 nil nil)))
681 (should (equal (comp-test-opt-rest 1 2) '(1 2 nil)))
682 (should (equal (comp-test-opt-rest 1 2 3) '(1 2 (3))))
683 (should (equal (comp-test-opt-rest 1 2 56 57 58)
684 '(1 2 (56 57 58)))))
685
686(comp-deftest opt ()
687 (should (equal (comp-test-opt 23) '(23)))
688 (should (equal (comp-test-opt 23 24) '(23 . 24)))
689 (should-error (comp-test-opt)
690 :type 'wrong-number-of-arguments)
691 (should-error (comp-test-opt nil 24 97)
692 :type 'wrong-number-of-arguments))
693
694(comp-deftest unwind-protect ()
695 (comp-test-unwind-protect 'ignore)
696 (should (eq comp-test-up-val 999))
697 (condition-case nil
698 (comp-test-unwind-protect (lambda () (error "HI")))
699 (error
700 nil))
701 (should (eq comp-test-up-val 999)))
702
703
704;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
705;; Tests for dynamic scope. ;;
706;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
707
708(comp-deftest dynamic-ffuncall ()
709 "Test calling convention for dynamic binding."
710
711 (should (equal (comp-tests-ffuncall-callee-dyn-f 1 2)
712 '(1 2)))
713
714 (should (equal (comp-tests-ffuncall-callee-opt-dyn-f 1 2 3 4)
715 '(1 2 3 4)))
716 (should (equal (comp-tests-ffuncall-callee-opt-dyn-f 1 2 3)
717 '(1 2 3 nil)))
718 (should (equal (comp-tests-ffuncall-callee-opt-dyn-f 1 2)
719 '(1 2 nil nil)))
720
721 (should (equal (comp-tests-ffuncall-callee-rest-dyn-f 1 2)
722 '(1 2 nil)))
723 (should (equal (comp-tests-ffuncall-callee-rest-dyn-f 1 2 3)
724 '(1 2 (3))))
725 (should (equal (comp-tests-ffuncall-callee-rest-dyn-f 1 2 3 4)
726 '(1 2 (3 4))))
727
728 (should (equal (comp-tests-ffuncall-callee-opt-rest-dyn-f 1 2)
729 '(1 2 nil nil)))
730 (should (equal (comp-tests-ffuncall-callee-opt-rest-dyn-f 1 2 3)
731 '(1 2 3 nil)))
732 (should (equal (comp-tests-ffuncall-callee-opt-rest-dyn-f 1 2 3 4)
733 '(1 2 3 (4)))))
734
735(comp-deftest dynamic-arity ()
736 "Test func-arity on dynamic scope functions."
737 (should (equal '(2 . 2)
738 (func-arity #'comp-tests-ffuncall-callee-dyn-f)))
739 (should (equal '(2 . 4)
740 (func-arity #'comp-tests-ffuncall-callee-opt-dyn-f)))
741 (should (equal '(2 . many)
742 (func-arity #'comp-tests-ffuncall-callee-rest-dyn-f)))
743 (should (equal '(2 . many)
744 (func-arity #'comp-tests-ffuncall-callee-opt-rest-dyn-f))))
745
746(comp-deftest dynamic-help-arglist ()
747 "Test `help-function-arglist' works on lisp/d (bug#42572)."
748 (should (equal (help-function-arglist
749 (symbol-function 'comp-tests-ffuncall-callee-opt-rest-dyn-f)
750 t)
751 '(a b &optional c &rest d))))
752
753(comp-deftest cl-macro-exp ()
754 "Verify CL macro expansion (bug#42088)."
755 (should (equal (comp-tests-cl-macro-exp-f) '(a b))))
756
757(comp-deftest cl-uninterned-arg-parse-f ()
758 "Verify the parsing of a lambda list with uninterned symbols (bug#42120)."
759 (should (equal (comp-tests-cl-uninterned-arg-parse-f 1 2)
760 '(1 2))))
761
762
763;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
764;; Middle-end specific tests. ;;
765;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
766
767(defun comp-tests-mentioned-p-1 (x insn)
768 (cl-loop for y in insn
769 when (cond
770 ((consp y) (comp-tests-mentioned-p x y))
771 ((and (comp-mvar-p y) (comp-cstr-imm-vld-p y))
772 (equal (comp-cstr-imm y) x))
773 (t (equal x y)))
774 return t))
775
776(defun comp-tests-mentioned-p (x insn)
777 "Check if X is actively mentioned in INSN."
778 (unless (eq (car-safe insn)
779 'comment)
780 (comp-tests-mentioned-p-1 x insn)))
781
782(defun comp-tests-map-checker (func-name checker)
783 "Apply CHECKER to each insn of FUNC-NAME.
784Return a list of results."
785 (cl-loop
786 with func-c-name = (comp-c-func-name (or func-name 'anonymous-lambda) "F" t)
787 with f = (gethash func-c-name (comp-ctxt-funcs-h comp-ctxt))
788 for bb being each hash-value of (comp-func-blocks f)
789 nconc
790 (cl-loop
791 for insn in (comp-block-insns bb)
792 collect (funcall checker insn))))
793
794(defun comp-tests-tco-checker (_)
795 "Check that inside `comp-tests-tco-f' we have no recursion."
796 (should
797 (cl-notany
798 #'identity
799 (comp-tests-map-checker
800 'comp-tests-tco-f
801 (lambda (insn)
802 (or (comp-tests-mentioned-p 'comp-tests-tco-f insn)
803 (comp-tests-mentioned-p (comp-c-func-name 'comp-tests-tco-f "F" t)
804 insn)))))))
805
806(declare-function comp-tests-tco-f nil)
807
808(comp-deftest tco ()
809 "Check for tail recursion elimination."
810 (let ((native-comp-speed 3)
811 ;; Disable ipa-pure otherwise `comp-tests-tco-f' gets
812 ;; optimized-out.
813 (comp-disabled-passes '(comp-ipa-pure))
814 (comp-post-pass-hooks '((comp-tco comp-tests-tco-checker)
815 (comp-final comp-tests-tco-checker))))
816 (eval '(defun comp-tests-tco-f (a b count)
817 (if (= count 0)
818 b
819 (comp-tests-tco-f (+ a b) a (- count 1))))
820 t)
821 (native-compile #'comp-tests-tco-f)
822 (should (subr-native-elisp-p (symbol-function 'comp-tests-tco-f)))
823 (should (= (comp-tests-tco-f 1 0 10) 55))))
824
825(defun comp-tests-fw-prop-checker-1 (_)
826 "Check that inside `comp-tests-fw-prop-f' `concat' and `length' are folded."
827 (should
828 (cl-notany
829 #'identity
830 (comp-tests-map-checker
831 'comp-tests-fw-prop-1-f
832 (lambda (insn)
833 (or (comp-tests-mentioned-p 'concat insn)
834 (comp-tests-mentioned-p 'length insn)))))))
835
836(declare-function comp-tests-fw-prop-1-f nil)
837
838(comp-deftest fw-prop-1 ()
839 "Some tests for forward propagation."
840 (let ((native-comp-speed 2)
841 (comp-post-pass-hooks '((comp-final comp-tests-fw-prop-checker-1))))
842 (eval '(defun comp-tests-fw-prop-1-f ()
843 (let* ((a "xxx")
844 (b "yyy")
845 (c (concat a b))) ; <= has to optimize
846 (length c))) ; <= has to optimize
847 t)
848 (native-compile #'comp-tests-fw-prop-1-f)
849 (should (subr-native-elisp-p (symbol-function 'comp-tests-fw-prop-1-f)))
850 (should (= (comp-tests-fw-prop-1-f) 6))))
851
852(defun comp-tests-check-ret-type-spec (func-form ret-type)
853 (let ((lexical-binding t)
854 (native-comp-speed 2)
855 (f-name (cl-second func-form)))
856 (eval func-form t)
857 (native-compile f-name)
858 (should (equal (cl-third (subr-type (symbol-function f-name)))
859 ret-type))))
860
861(cl-eval-when (compile eval load)
862 (defconst comp-tests-type-spec-tests
863 ;; Why we quote everything here, you ask? So that values of
864 ;; `most-positive-fixnum' and `most-negative-fixnum', which can be
865 ;; architecture-dependent, do not end up hardcoded in the
866 ;; resulting byte-compiled file, and thus we could run the same
867 ;; .elc file on several architectures without fear.
868 '(
869 ;; 1
870 ((defun comp-tests-ret-type-spec-f (x)
871 x)
872 't)
873
874 ;; 2
875 ((defun comp-tests-ret-type-spec-f ()
876 1)
877 '(integer 1 1))
878
879 ;; 3
880 ((defun comp-tests-ret-type-spec-f (x)
881 (if x 1 3))
882 '(or (integer 1 1) (integer 3 3)))
883
884 ;; 4
885 ((defun comp-tests-ret-type-spec-f (x)
886 (let (y)
887 (if x
888 (setf y 1)
889 (setf y 2))
890 y))
891 '(integer 1 2))
892
893 ;; 5
894 ((defun comp-tests-ret-type-spec-f (x)
895 (let (y)
896 (if x
897 (setf y 1)
898 (setf y 3))
899 y))
900 '(or (integer 1 1) (integer 3 3)))
901
902 ;; 6
903 ((defun comp-tests-ret-type-spec-f (x)
904 (if x
905 (list x)
906 3))
907 '(or cons (integer 3 3)))
908
909 ;; 7
910 ((defun comp-tests-ret-type-spec-f (x)
911 (if x
912 'foo
913 3))
914 '(or (member foo) (integer 3 3)))
915
916 ;; 8
917 ((defun comp-tests-ret-type-spec-f (x)
918 (if (eq x 3)
919 x
920 'foo))
921 '(or (member foo) (integer 3 3)))
922
923 ;; 9
924 ((defun comp-tests-ret-type-spec-f (x)
925 (if (eq 3 x)
926 x
927 'foo))
928 '(or (member foo) (integer 3 3)))
929
930 ;; 10
931 ((defun comp-tests-ret-type-spec-f (x)
932 (if (eql x 3)
933 x
934 'foo))
935 '(or (member foo) (integer 3 3)))
936
937 ;; 11
938 ((defun comp-tests-ret-type-spec-f (x)
939 (if (eql 3 x)
940 x
941 'foo))
942 '(or (member foo) (integer 3 3)))
943
944 ;; 12
945 ((defun comp-tests-ret-type-spec-f (x)
946 (if (eql x 3)
947 'foo
948 x))
949 '(not (integer 3 3)))
950
951 ;; 13
952 ((defun comp-tests-ret-type-spec-f (x y)
953 (if (= x y)
954 x
955 'foo))
956 '(or (member foo) marker number))
957
958 ;; 14
959 ((defun comp-tests-ret-type-spec-f (x)
960 (comp-hint-fixnum x))
961 `(integer ,most-negative-fixnum ,most-positive-fixnum))
962
963 ;; 15
964 ((defun comp-tests-ret-type-spec-f (x)
965 (comp-hint-cons x))
966 'cons)
967
968 ;; 16
969 ((defun comp-tests-ret-type-spec-f (x)
970 (let (y)
971 (when x
972 (setf y 4))
973 y))
974 '(or null (integer 4 4)))
975
976 ;; 17
977 ((defun comp-tests-ret-type-spec-f ()
978 (let (x
979 (y 3))
980 (setf x y)
981 y))
982 '(integer 3 3))
983
984 ;; 18
985 ((defun comp-tests-ret-type-spec-f (x)
986 (let ((y 3))
987 (when x
988 (setf y x))
989 y))
990 't)
991
992 ;; 19
993 ((defun comp-tests-ret-type-spec-f (x y)
994 (eq x y))
995 'boolean)
996
997 ;; 20
998 ((defun comp-tests-ret-type-spec-f (x)
999 (when x
1000 'foo))
1001 '(or (member foo) null))
1002
1003 ;; 21
1004 ((defun comp-tests-ret-type-spec-f (x)
1005 (unless x
1006 'foo))
1007 '(or (member foo) null))
1008
1009 ;; 22
1010 ((defun comp-tests-ret-type-spec-f (x)
1011 (when (> x 3)
1012 x))
1013 '(or null float (integer 4 *)))
1014
1015 ;; 23
1016 ((defun comp-tests-ret-type-spec-f (x)
1017 (when (>= x 3)
1018 x))
1019 '(or null float (integer 3 *)))
1020
1021 ;; 24
1022 ((defun comp-tests-ret-type-spec-f (x)
1023 (when (< x 3)
1024 x))
1025 '(or null float (integer * 2)))
1026
1027 ;; 25
1028 ((defun comp-tests-ret-type-spec-f (x)
1029 (when (<= x 3)
1030 x))
1031 '(or null float (integer * 3)))
1032
1033 ;; 26
1034 ((defun comp-tests-ret-type-spec-f (x)
1035 (when (> 3 x)
1036 x))
1037 '(or null float (integer * 2)))
1038
1039 ;; 27
1040 ((defun comp-tests-ret-type-spec-f (x)
1041 (when (>= 3 x)
1042 x))
1043 '(or null float (integer * 3)))
1044
1045 ;; 28
1046 ((defun comp-tests-ret-type-spec-f (x)
1047 (when (< 3 x)
1048 x))
1049 '(or null float (integer 4 *)))
1050
1051 ;; 29
1052 ((defun comp-tests-ret-type-spec-f (x)
1053 (when (<= 3 x)
1054 x))
1055 '(or null float (integer 3 *)))
1056
1057 ;; 30
1058 ((defun comp-tests-ret-type-spec-f (x)
1059 (let ((y 3))
1060 (when (> x y)
1061 x)))
1062 '(or null float (integer 4 *)))
1063
1064 ;; 31
1065 ((defun comp-tests-ret-type-spec-f (x)
1066 (let ((y 3))
1067 (when (> y x)
1068 x)))
1069 '(or null float (integer * 2)))
1070
1071 ;; 32
1072 ((defun comp-tests-ret-type-spec-f (x)
1073 (when (and (> x 3)
1074 (< x 10))
1075 x))
1076 '(or null float (integer 4 9)))
1077
1078 ;; 33
1079 ((defun comp-tests-ret-type-spec-f (x)
1080 (when (or (> x 3)
1081 (< x 10))
1082 x))
1083 '(or null float integer))
1084
1085 ;; 34
1086 ((defun comp-tests-ret-type-spec-f (x)
1087 (when (or (< x 3)
1088 (> x 10))
1089 x))
1090 '(or null float (integer * 2) (integer 11 *)))
1091
1092 ;; 35 No float range support.
1093 ((defun comp-tests-ret-type-spec-f (x)
1094 (when (> x 1.0)
1095 x))
1096 '(or null marker number))
1097
1098 ;; 36
1099 ((defun comp-tests-ret-type-spec-f (x y)
1100 (when (and (> x 3)
1101 (> y 2))
1102 (+ x y)))
1103 '(or null float (integer 7 *)))
1104
1105 ;; 37
1106 ;; SBCL: (OR REAL NULL)
1107 ((defun comp-tests-ret-type-spec-f (x y)
1108 (when (and (<= x 3)
1109 (<= y 2))
1110 (+ x y)))
1111 '(or null float (integer * 5)))
1112
1113 ;; 38
1114 ((defun comp-tests-ret-type-spec-f (x y)
1115 (when (and (< 1 x 5)
1116 (< 1 y 5))
1117 (+ x y)))
1118 '(or null float (integer 4 8)))
1119
1120 ;; 39
1121 ;; SBCL gives: (OR REAL NULL)
1122 ((defun comp-tests-ret-type-spec-f (x y)
1123 (when (and (<= 1 x 10)
1124 (<= 2 y 3))
1125 (+ x y)))
1126 '(or null float (integer 3 13)))
1127
1128 ;; 40
1129 ;; SBCL: (OR REAL NULL)
1130 ((defun comp-tests-ret-type-spec-f (x y)
1131 (when (and (<= 1 x 10)
1132 (<= 2 y 3))
1133 (- x y)))
1134 '(or null float (integer -2 8)))
1135
1136 ;; 41
1137 ((defun comp-tests-ret-type-spec-f (x y)
1138 (when (and (<= 1 x)
1139 (<= 2 y 3))
1140 (- x y)))
1141 '(or null float (integer -2 *)))
1142
1143 ;; 42
1144 ((defun comp-tests-ret-type-spec-f (x y)
1145 (when (and (<= 1 x 10)
1146 (<= 2 y))
1147 (- x y)))
1148 '(or null float (integer * 8)))
1149
1150 ;; 43
1151 ((defun comp-tests-ret-type-spec-f (x y)
1152 (when (and (<= x 10)
1153 (<= 2 y))
1154 (- x y)))
1155 '(or null float (integer * 8)))
1156
1157 ;; 44
1158 ((defun comp-tests-ret-type-spec-f (x y)
1159 (when (and (<= x 10)
1160 (<= y 3))
1161 (- x y)))
1162 '(or null float integer))
1163
1164 ;; 45
1165 ((defun comp-tests-ret-type-spec-f (x y)
1166 (when (and (<= 2 x)
1167 (<= 3 y))
1168 (- x y)))
1169 '(or null float integer))
1170
1171 ;; 46
1172 ;; SBCL: (OR (RATIONAL (6) (30)) (SINGLE-FLOAT 6.0 30.0)
1173 ;; (DOUBLE-FLOAT 6.0d0 30.0d0) NULL)
1174 ((defun comp-tests-ret-type-spec-f (x y z i j k)
1175 (when (and (< 1 x 5)
1176 (< 1 y 5)
1177 (< 1 z 5)
1178 (< 1 i 5)
1179 (< 1 j 5)
1180 (< 1 k 5))
1181 (+ x y z i j k)))
1182 '(or null float (integer 12 24)))
1183
1184 ;; 47
1185 ((defun comp-tests-ret-type-spec-f (x)
1186 (when (<= 1 x 5)
1187 (1+ x)))
1188 '(or null float (integer 2 6)))
1189
1190 ;;48
1191 ((defun comp-tests-ret-type-spec-f (x)
1192 (when (<= 1 x 5)
1193 (1- x)))
1194 '(or null float (integer 0 4)))
1195
1196 ;; 49
1197 ((defun comp-tests-ret-type-spec-f ()
1198 (error "Foo"))
1199 'nil)
1200
1201 ;; 50
1202 ((defun comp-tests-ret-type-spec-f (x)
1203 (if (stringp x)
1204 x
1205 'bar))
1206 '(or (member bar) string))
1207
1208 ;; 51
1209 ((defun comp-tests-ret-type-spec-f (x)
1210 (if (stringp x)
1211 'bar
1212 x))
1213 '(not string))
1214
1215 ;; 52
1216 ((defun comp-tests-ret-type-spec-f (x)
1217 (if (integerp x)
1218 x
1219 'bar))
1220 '(or (member bar) integer))
1221
1222 ;; 53
1223 ((defun comp-tests-ret-type-spec-f (x)
1224 (when (integerp x)
1225 x))
1226 '(or null integer))
1227
1228 ;; 54
1229 ((defun comp-tests-ret-type-spec-f (x)
1230 (unless (symbolp x)
1231 x))
1232 't)
1233
1234 ;; 55
1235 ((defun comp-tests-ret-type-spec-f (x)
1236 (unless (integerp x)
1237 x))
1238 '(not integer))
1239
1240 ;; 56
1241 ((defun comp-tests-ret-type-spec-f (x)
1242 (cl-ecase x
1243 (1 (message "one"))
1244 (5 (message "five")))
1245 x)
1246 't
1247 ;; FIXME improve `comp-cond-cstrs-target-mvar' to cross block
1248 ;; boundary if necessary as this should return:
1249 ;; (or (integer 1 1) (integer 5 5))
1250 )
1251
1252 ;; 57
1253 ((defun comp-tests-ret-type-spec-f (x)
1254 (unless (or (eq x 'foo)
1255 (eql x 3))
1256 (error "Not foo or 3"))
1257 x)
1258 '(or (member foo) (integer 3 3)))
1259
1260 ;;58
1261 ((defun comp-tests-ret-type-spec-f (x y)
1262 (if (and (natnump x)
1263 (natnump y)
1264 (<= x y))
1265 x
1266 (error "")))
1267 '(integer 0 *))
1268
1269 ;; 59
1270 ((defun comp-tests-ret-type-spec-f (x y)
1271 (if (and (>= x 3)
1272 (<= y 10)
1273 (<= x y))
1274 x
1275 (error "")))
1276 '(or float (integer 3 10)))
1277
1278 ;; 60
1279 ((defun comp-tests-ret-type-spec-f (x y)
1280 (if (and (<= x 10)
1281 (>= y 3)
1282 (>= x y))
1283 x
1284 (error "")))
1285 '(or float (integer 3 10)))
1286
1287 ;; 61
1288 ((defun comp-tests-ret-type-spec-f (x)
1289 (if (= x 1.0)
1290 x
1291 (error "")))
1292 '(or (member 1.0) (integer 1 1)))
1293
1294 ;; 62
1295 ((defun comp-tests-ret-type-spec-f (x)
1296 (if (= x 1.0)
1297 x
1298 (error "")))
1299 '(or (member 1.0) (integer 1 1)))
1300
1301 ;; 63
1302 ((defun comp-tests-ret-type-spec-f (x)
1303 (if (= x 1.1)
1304 x
1305 (error "")))
1306 '(member 1.1))
1307
1308 ;; 64
1309 ((defun comp-tests-ret-type-spec-f (x)
1310 (if (= x 1)
1311 x
1312 (error "")))
1313 '(or (member 1.0) (integer 1 1)))
1314
1315 ;; 65
1316 ((defun comp-tests-ret-type-spec-f (x)
1317 (if (= x 1)
1318 x
1319 (error "")))
1320 '(or (member 1.0) (integer 1 1)))
1321
1322 ;; 66
1323 ((defun comp-tests-ret-type-spec-f (x)
1324 (if (eql x 0.0)
1325 x
1326 (error "")))
1327 'float)
1328
1329 ;; 67
1330 ((defun comp-tests-ret-type-spec-f (x)
1331 (if (equal x '(1 2 3))
1332 x
1333 (error "")))
1334 'cons)
1335
1336 ;; 68
1337 ((defun comp-tests-ret-type-spec-f (x)
1338 (if (and (floatp x)
1339 (= x 1))
1340 x
1341 (error "")))
1342 ;; Conservative (see cstr relax in `comp-cstr-=').
1343 '(or (member 1.0) (integer 1 1)))
1344
1345 ;; 69
1346 ((defun comp-tests-ret-type-spec-f (x)
1347 (if (and (integer x)
1348 (= x 1))
1349 x
1350 (error "")))
1351 ;; Conservative (see cstr relax in `comp-cstr-=').
1352 '(or (member 1.0) (integer 1 1)))
1353
1354 ;; 70
1355 ((defun comp-tests-ret-type-spec-f (x y)
1356 (if (and (floatp x)
1357 (integerp y)
1358 (= x y))
1359 x
1360 (error "")))
1361 '(or float integer))
1362
1363 ;; 71
1364 ((defun comp-tests-ret-type-spec-f (x)
1365 (if (= x 0.0)
1366 x
1367 (error "")))
1368 '(or (member -0.0 0.0) (integer 0 0)))
1369
1370 ;; 72
1371 ((defun comp-tests-ret-type-spec-f (x)
1372 (unless (= x 0.0)
1373 (error ""))
1374 (unless (eql x -0.0)
1375 (error ""))
1376 x)
1377 'float)
1378
1379 ;; 73
1380 ((defun comp-tests-ret-type-spec-f (x)
1381 (when (eql x 1.0)
1382 (error ""))
1383 x)
1384 't)
1385
1386 ;; 74
1387 ((defun comp-tests-ret-type-spec-f (x)
1388 (if (eq x 0)
1389 (error "")
1390 (1+ x)))
1391 'number)))
1392
1393 (defun comp-tests-define-type-spec-test (number x)
1394 `(comp-deftest ,(intern (format "ret-type-spec-%d" number)) ()
1395 ,(format "Type specifier test number %d." number)
1396 (let ((comp-ctxt (make-comp-cstr-ctxt)))
1397 (comp-tests-check-ret-type-spec ',(car x) ,(cadr x))))))
1398
1399(defmacro comp-tests-define-type-spec-tests ()
1400 "Define all type specifier tests."
1401 `(progn
1402 ,@(cl-loop
1403 for test in comp-tests-type-spec-tests
1404 for n from 1
1405 collect (comp-tests-define-type-spec-test n test))))
1406
1407(comp-tests-define-type-spec-tests)
1408
1409(defun comp-tests-pure-checker-1 (_)
1410 "Check that inside `comp-tests-pure-caller-f' `comp-tests-pure-callee-f' is
1411folded."
1412 (should
1413 (cl-notany
1414 #'identity
1415 (comp-tests-map-checker
1416 'comp-tests-pure-caller-f
1417 (lambda (insn)
1418 (or (comp-tests-mentioned-p 'comp-tests-pure-callee-f insn)
1419 (comp-tests-mentioned-p (comp-c-func-name
1420 'comp-tests-pure-callee-f "F" t)
1421 insn)))))))
1422
1423(defun comp-tests-pure-checker-2 (_)
1424 "Check that `comp-tests-pure-fibn-f' is folded."
1425 (should
1426 (cl-notany
1427 #'identity
1428 (comp-tests-map-checker
1429 'comp-tests-pure-fibn-entry-f
1430 (lambda (insn)
1431 (or (comp-tests-mentioned-p 'comp-tests-pure-fibn-f insn)
1432 (comp-tests-mentioned-p (comp-c-func-name 'comp-tests-pure-fibn-f "F" t)
1433 insn)))))))
1434
1435(comp-deftest pure ()
1436 "Some tests for pure functions optimization."
1437 (let ((native-comp-speed 3)
1438 (comp-post-pass-hooks '((comp-final comp-tests-pure-checker-1
1439 comp-tests-pure-checker-2))))
1440 (load (native-compile (ert-resource-file "comp-test-pure.el")))
1441 (declare-function comp-tests-pure-caller-f nil)
1442 (declare-function comp-tests-pure-fibn-entry-f nil)
1443
1444 (should (subr-native-elisp-p (symbol-function 'comp-tests-pure-caller-f)))
1445 (should (= (comp-tests-pure-caller-f) 4))
1446
1447 (should (subr-native-elisp-p (symbol-function 'comp-tests-pure-fibn-entry-f)))
1448 (should (= (comp-tests-pure-fibn-entry-f) 6765))))
1449
1450(defvar comp-tests-cond-rw-checked-function nil
1451 "Function to be checked.")
1452(defun comp-tests-cond-rw-checker-val (_)
1453 "Check we manage to propagate the correct return value."
1454 (should
1455 (cl-some
1456 #'identity
1457 (comp-tests-map-checker
1458 comp-tests-cond-rw-checked-function
1459 (lambda (insn)
1460 (pcase insn
1461 (`(return ,mvar)
1462 (and (comp-cstr-imm-vld-p mvar)
1463 (eql (comp-cstr-imm mvar) 123)))))))))
1464
1465(defvar comp-tests-cond-rw-expected-type nil
1466 "Type to expect in `comp-tests-cond-rw-checker-type'.")
1467(defun comp-tests-cond-rw-checker-type (_)
1468 "Check we manage to propagate the correct return type."
1469 (should
1470 (cl-some
1471 #'identity
1472 (comp-tests-map-checker
1473 comp-tests-cond-rw-checked-function
1474 (lambda (insn)
1475 (pcase insn
1476 (`(return ,mvar)
1477 (equal (comp-mvar-typeset mvar)
1478 comp-tests-cond-rw-expected-type))))))))
1479
1480;;; comp-tests.el ends here
diff --git a/test/src/data-tests.el b/test/src/data-tests.el
index 374d1689b9e..463a894d095 100644
--- a/test/src/data-tests.el
+++ b/test/src/data-tests.el
@@ -1,6 +1,6 @@
1;;; data-tests.el --- tests for src/data.c 1;;; data-tests.el --- tests for src/data.c -*- lexical-binding:t -*-
2 2
3;; Copyright (C) 2013-2017 Free Software Foundation, Inc. 3;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
4 4
5;; This file is part of GNU Emacs. 5;; This file is part of GNU Emacs.
6 6
@@ -23,13 +23,21 @@
23 23
24(require 'cl-lib) 24(require 'cl-lib)
25 25
26(defconst data-tests--float-greater-than-fixnums (+ 1.0 most-positive-fixnum)
27 "A floating-point value that is greater than all fixnums.
28It is also as small as conveniently possible, to make the tests sharper.
29Adding 1.0 to `most-positive-fixnum' should suffice on all
30practical Emacs platforms, since the result is a power of 2 and
31this is exactly representable and is greater than
32`most-positive-fixnum', which is just less than a power of 2.")
33
26(ert-deftest data-tests-= () 34(ert-deftest data-tests-= ()
27 (should-error (=)) 35 (should-error (=))
28 (should (= 1)) 36 (should (= 1))
29 (should (= 2 2)) 37 (should (= 2 2))
30 (should (= 9 9 9 9 9 9 9 9 9)) 38 (should (= 9 9 9 9 9 9 9 9 9))
31 (should (= most-negative-fixnum (float most-negative-fixnum))) 39 (should (= most-negative-fixnum (float most-negative-fixnum)))
32 (should-not (= most-positive-fixnum (+ 1.0 most-positive-fixnum))) 40 (should-not (= most-positive-fixnum data-tests--float-greater-than-fixnums))
33 (should-not (apply #'= '(3 8 3))) 41 (should-not (apply #'= '(3 8 3)))
34 (should-error (= 9 9 'foo)) 42 (should-error (= 9 9 'foo))
35 ;; Short circuits before getting to bad arg 43 ;; Short circuits before getting to bad arg
@@ -40,7 +48,7 @@
40 (should (< 1)) 48 (should (< 1))
41 (should (< 2 3)) 49 (should (< 2 3))
42 (should (< -6 -1 0 2 3 4 8 9 999)) 50 (should (< -6 -1 0 2 3 4 8 9 999))
43 (should (< 0.5 most-positive-fixnum (+ 1.0 most-positive-fixnum))) 51 (should (< 0.5 most-positive-fixnum data-tests--float-greater-than-fixnums))
44 (should-not (apply #'< '(3 8 3))) 52 (should-not (apply #'< '(3 8 3)))
45 (should-error (< 9 10 'foo)) 53 (should-error (< 9 10 'foo))
46 ;; Short circuits before getting to bad arg 54 ;; Short circuits before getting to bad arg
@@ -51,7 +59,7 @@
51 (should (> 1)) 59 (should (> 1))
52 (should (> 3 2)) 60 (should (> 3 2))
53 (should (> 6 1 0 -2 -3 -4 -8 -9 -999)) 61 (should (> 6 1 0 -2 -3 -4 -8 -9 -999))
54 (should (> (+ 1.0 most-positive-fixnum) most-positive-fixnum 0.5)) 62 (should (> data-tests--float-greater-than-fixnums most-positive-fixnum 0.5))
55 (should-not (apply #'> '(3 8 3))) 63 (should-not (apply #'> '(3 8 3)))
56 (should-error (> 9 8 'foo)) 64 (should-error (> 9 8 'foo))
57 ;; Short circuits before getting to bad arg 65 ;; Short circuits before getting to bad arg
@@ -62,7 +70,7 @@
62 (should (<= 1)) 70 (should (<= 1))
63 (should (<= 2 3)) 71 (should (<= 2 3))
64 (should (<= -6 -1 -1 0 0 0 2 3 4 8 999)) 72 (should (<= -6 -1 -1 0 0 0 2 3 4 8 999))
65 (should (<= 0.5 most-positive-fixnum (+ 1.0 most-positive-fixnum))) 73 (should (<= 0.5 most-positive-fixnum data-tests--float-greater-than-fixnums))
66 (should-not (apply #'<= '(3 8 3 3))) 74 (should-not (apply #'<= '(3 8 3 3)))
67 (should-error (<= 9 10 'foo)) 75 (should-error (<= 9 10 'foo))
68 ;; Short circuits before getting to bad arg 76 ;; Short circuits before getting to bad arg
@@ -73,7 +81,7 @@
73 (should (>= 1)) 81 (should (>= 1))
74 (should (>= 3 2)) 82 (should (>= 3 2))
75 (should (>= 666 1 0 0 -2 -3 -3 -3 -4 -8 -8 -9 -999)) 83 (should (>= 666 1 0 0 -2 -3 -3 -3 -4 -8 -8 -9 -999))
76 (should (>= (+ 1.0 most-positive-fixnum) most-positive-fixnum)) 84 (should (>= data-tests--float-greater-than-fixnums most-positive-fixnum))
77 (should-not (apply #'>= '(3 8 3))) 85 (should-not (apply #'>= '(3 8 3)))
78 (should-error (>= 9 8 'foo)) 86 (should-error (>= 9 8 'foo))
79 ;; Short circuits before getting to bad arg 87 ;; Short circuits before getting to bad arg
@@ -97,7 +105,7 @@
97 (should (= 2 (min 3 2))) 105 (should (= 2 (min 3 2)))
98 (should (= -999 (min 666 1 0 0 -2 -3 -3 -3 -4 -8 -8 -9 -999))) 106 (should (= -999 (min 666 1 0 0 -2 -3 -3 -3 -4 -8 -8 -9 -999)))
99 (should (= most-positive-fixnum 107 (should (= most-positive-fixnum
100 (min (+ 1.0 most-positive-fixnum) most-positive-fixnum))) 108 (min data-tests--float-greater-than-fixnums most-positive-fixnum)))
101 (should (= 3 (apply #'min '(3 8 3)))) 109 (should (= 3 (apply #'min '(3 8 3))))
102 (should-error (min 9 8 'foo)) 110 (should-error (min 9 8 'foo))
103 (should-error (min (make-marker))) 111 (should-error (min (make-marker)))
@@ -105,15 +113,17 @@
105 (should (isnan (min 0.0e+NaN))) 113 (should (isnan (min 0.0e+NaN)))
106 (should (isnan (min 0.0e+NaN 1 2))) 114 (should (isnan (min 0.0e+NaN 1 2)))
107 (should (isnan (min 1.0 0.0e+NaN))) 115 (should (isnan (min 1.0 0.0e+NaN)))
108 (should (isnan (min 1.0 0.0e+NaN 1.1)))) 116 (should (isnan (min 1.0 0.0e+NaN 1.1)))
117 (should (isnan (min 1.0 0.0e+NaN 1.1 (1+ most-positive-fixnum))))
118 (should (isnan (max 1.0 0.0e+NaN 1.1 (1+ most-positive-fixnum)))))
109 119
110(defun data-tests-popcnt (byte) 120(defun data-tests-popcnt (byte)
111 "Calculate the Hamming weight of BYTE." 121 "Calculate the Hamming weight of BYTE."
112 (if (< byte 0) 122 (if (< byte 0)
113 (setq byte (lognot byte))) 123 (setq byte (lognot byte)))
114 (setq byte (- byte (logand (lsh byte -1) #x55555555))) 124 (if (zerop byte)
115 (setq byte (+ (logand byte #x33333333) (logand (lsh byte -2) #x33333333))) 125 0
116 (lsh (* (logand (+ byte (lsh byte -4)) #x0f0f0f0f) #x01010101) -24)) 126 (+ (logand byte 1) (data-tests-popcnt (ash byte -1)))))
117 127
118(ert-deftest data-tests-logcount () 128(ert-deftest data-tests-logcount ()
119 (should (cl-loop for n in (number-sequence -255 255) 129 (should (cl-loop for n in (number-sequence -255 255)
@@ -164,7 +174,7 @@
164 sum 1)) 174 sum 1))
165 175
166(defun test-bool-vector-bv-from-hex-string (desc) 176(defun test-bool-vector-bv-from-hex-string (desc)
167 (let (bv nchars nibbles) 177 (let (bv nibbles)
168 (dolist (c (string-to-list desc)) 178 (dolist (c (string-to-list desc))
169 (push (string-to-number 179 (push (string-to-number
170 (char-to-string c) 180 (char-to-string c)
@@ -176,29 +186,28 @@
176 (dotimes (_ 4) 186 (dotimes (_ 4)
177 (aset bv i (> (logand 1 n) 0)) 187 (aset bv i (> (logand 1 n) 0))
178 (cl-incf i) 188 (cl-incf i)
179 (setf n (lsh n -1))))) 189 (setf n (ash n -1)))))
180 bv)) 190 bv))
181 191
182(defun test-bool-vector-to-hex-string (bv) 192(defun test-bool-vector-to-hex-string (bv)
183 (let (nibbles (v (cl-coerce bv 'list))) 193 (let (nibbles (v (cl-coerce bv 'list)))
184 (while v 194 (while v
185 (push (logior 195 (push (logior
186 (lsh (if (nth 0 v) 1 0) 0) 196 (ash (if (nth 0 v) 1 0) 0)
187 (lsh (if (nth 1 v) 1 0) 1) 197 (ash (if (nth 1 v) 1 0) 1)
188 (lsh (if (nth 2 v) 1 0) 2) 198 (ash (if (nth 2 v) 1 0) 2)
189 (lsh (if (nth 3 v) 1 0) 3)) 199 (ash (if (nth 3 v) 1 0) 3))
190 nibbles) 200 nibbles)
191 (setf v (nthcdr 4 v))) 201 (setf v (nthcdr 4 v)))
192 (mapconcat (lambda (n) (format "%X" n)) 202 (mapconcat (lambda (n) (format "%X" n))
193 (nreverse nibbles) 203 (nreverse nibbles))))
194 "")))
195 204
196(defun test-bool-vector-count-consecutive-tc (desc) 205(defun test-bool-vector-count-consecutive-tc (desc)
197 "Run a test case for bool-vector-count-consecutive. 206 "Run a test case for `bool-vector-count-consecutive'.
198DESC is a string describing the test. It is a sequence of 207DESC is a string describing the test. It is a sequence of
199hexadecimal digits describing the bool vector. We exhaustively 208hexadecimal digits describing the bool vector. We exhaustively
200test all counts at all possible positions in the vector by 209test all counts at all possible positions in the vector by
201comparing the subr with a much slower lisp implementation." 210comparing the subr with a much slower Lisp implementation."
202 (let ((bv (test-bool-vector-bv-from-hex-string desc))) 211 (let ((bv (test-bool-vector-bv-from-hex-string desc)))
203 (cl-loop 212 (cl-loop
204 for lf in '(nil t) 213 for lf in '(nil t)
@@ -234,9 +243,9 @@ comparing the subr with a much slower lisp implementation."
234 243
235(defun test-bool-vector-apply-mock-op (mock a b c) 244(defun test-bool-vector-apply-mock-op (mock a b c)
236 "Compute (slowly) the correct result of a bool-vector set operation." 245 "Compute (slowly) the correct result of a bool-vector set operation."
237 (let (changed nv) 246 (let (changed)
238 (cl-assert (eql (length b) (length c))) 247 (cl-assert (eql (length b) (length c)))
239 (if a (setf nv a) 248 (unless a
240 (setf a (make-bool-vector (length b) nil)) 249 (setf a (make-bool-vector (length b) nil))
241 (setf changed t)) 250 (setf changed t))
242 251
@@ -314,7 +323,7 @@ comparing the subr with a much slower lisp implementation."
314 323
315(defvar binding-test-some-local 'some) 324(defvar binding-test-some-local 'some)
316(with-current-buffer binding-test-buffer-A 325(with-current-buffer binding-test-buffer-A
317 (set (make-local-variable 'binding-test-some-local) 'local)) 326 (setq-local binding-test-some-local 'local))
318 327
319(ert-deftest binding-test-manual () 328(ert-deftest binding-test-manual ()
320 "A test case from the elisp manual." 329 "A test case from the elisp manual."
@@ -328,13 +337,55 @@ comparing the subr with a much slower lisp implementation."
328 (should (eq binding-test-some-local 'local)))) 337 (should (eq binding-test-some-local 'local))))
329 338
330(ert-deftest binding-test-setq-default () 339(ert-deftest binding-test-setq-default ()
331 "Test that a setq-default has no effect when there is a local binding." 340 "Test that a `setq-default' has no effect when there is a local binding."
332 (with-current-buffer binding-test-buffer-B 341 (with-current-buffer binding-test-buffer-B
333 ;; This variable is not local in this buffer. 342 ;; This variable is not local in this buffer.
334 (let ((binding-test-some-local 'something-else)) 343 (let ((binding-test-some-local 'something-else))
335 (setq-default binding-test-some-local 'new-default)) 344 (setq-default binding-test-some-local 'new-default))
336 (should (eq binding-test-some-local 'some)))) 345 (should (eq binding-test-some-local 'some))))
337 346
347(ert-deftest data-tests--let-buffer-local ()
348 (let ((blvar (make-symbol "blvar")))
349 (set-default blvar nil)
350 (make-variable-buffer-local blvar)
351
352 (dolist (var (list blvar 'left-margin))
353 (let ((def (default-value var)))
354 (with-temp-buffer
355 (should (equal def (symbol-value var)))
356 (cl-progv (list var) (list 42)
357 (should (equal (symbol-value var) 42))
358 (should (equal (default-value var) (symbol-value var)))
359 (set var 123)
360 (should (not (local-variable-p var)))
361 (should (equal (symbol-value var) 123))
362 (should (equal (default-value var) (symbol-value var)))) ;bug#44733
363 (should (equal (symbol-value var) def))
364 (should (equal (default-value var) (symbol-value var))))
365 (should (equal (default-value var) def))))))
366
367(ert-deftest data-tests--let-buffer-local-no-unwind-other-buffers ()
368 "Test that a let-binding for a buffer-local unwinds only current-buffer."
369 (let ((blvar (make-symbol "blvar")))
370 (set-default blvar 0)
371 (make-variable-buffer-local blvar)
372 (dolist (var (list blvar 'left-margin))
373 (let* ((def (default-value var))
374 (newdef (+ def 1))
375 (otherbuf (generate-new-buffer "otherbuf")))
376 (with-temp-buffer
377 (cl-progv (list var) (list newdef)
378 (with-current-buffer otherbuf
379 (set var 123)
380 (should (local-variable-p var))
381 (should (equal (symbol-value var) 123))
382 (should (equal (default-value var) newdef))))
383 (with-current-buffer otherbuf
384 (should (local-variable-p var))
385 (should (equal (symbol-value var) 123))
386 (should (equal (default-value var) def)))
387 )))))
388
338(ert-deftest binding-test-makunbound () 389(ert-deftest binding-test-makunbound ()
339 "Tests of makunbound, from the manual." 390 "Tests of makunbound, from the manual."
340 (with-current-buffer binding-test-buffer-B 391 (with-current-buffer binding-test-buffer-B
@@ -347,30 +398,62 @@ comparing the subr with a much slower lisp implementation."
347 (eq binding-test-some-local 'outer)))))) 398 (eq binding-test-some-local 'outer))))))
348 399
349(ert-deftest binding-test-defvar-bool () 400(ert-deftest binding-test-defvar-bool ()
350 "Test DEFVAR_BOOL" 401 "Test DEFVAR_BOOL."
351 (let ((display-hourglass 5)) 402 (let ((display-hourglass 5))
352 (should (eq display-hourglass t)))) 403 (should (eq display-hourglass t))))
353 404
354(ert-deftest binding-test-defvar-int () 405(ert-deftest binding-test-defvar-int ()
355 "Test DEFVAR_INT" 406 "Test DEFVAR_INT."
356 (should-error (setq gc-cons-threshold 5.0) :type 'wrong-type-argument)) 407 (should-error (setq gc-cons-threshold 5.0) :type 'wrong-type-argument))
357 408
358(ert-deftest binding-test-set-constant-t () 409(ert-deftest binding-test-set-constant-t ()
359 "Test setting the constant t" 410 "Test setting the constant t."
360 (with-no-warnings (should-error (setq t 'bob) :type 'setting-constant))) 411 (with-no-warnings (should-error (setq t 'bob) :type 'setting-constant)))
361 412
362(ert-deftest binding-test-set-constant-nil () 413(ert-deftest binding-test-set-constant-nil ()
363 "Test setting the constant nil" 414 "Test setting the constant nil."
364 (with-no-warnings (should-error (setq nil 'bob) :type 'setting-constant))) 415 (with-no-warnings (should-error (setq nil 'bob) :type 'setting-constant)))
365 416
366(ert-deftest binding-test-set-constant-keyword () 417(ert-deftest binding-test-set-constant-keyword ()
367 "Test setting a keyword constant" 418 "Test setting a keyword constant."
368 (with-no-warnings (should-error (setq :keyword 'bob) :type 'setting-constant))) 419 (with-no-warnings (should-error (setq :keyword 'bob) :type 'setting-constant)))
369 420
370(ert-deftest binding-test-set-constant-nil () 421(ert-deftest binding-test-set-constant-itself ()
371 "Test setting a keyword to itself" 422 "Test setting a keyword to itself."
372 (with-no-warnings (should (setq :keyword :keyword)))) 423 (with-no-warnings (should (setq :keyword :keyword))))
373 424
425(ert-deftest data-tests--set-default-per-buffer ()
426 :expected-result t ;; Not fixed yet!
427 ;; FIXME: Performance tests are inherently unreliable.
428 ;; Using wall-clock time makes it even worse, so don't bother unless
429 ;; we have the primitive to measure cpu-time.
430 (skip-unless (fboundp 'current-cpu-time))
431 ;; Test performance of set-default on DEFVAR_PER_BUFFER variables.
432 ;; More specifically, test the problem seen in bug#41029 where setting
433 ;; the default value of a variable takes time proportional to the
434 ;; number of buffers.
435 (when (fboundp 'current-cpu-time) ; silence byte-compiler
436 (let* ((fun #'error)
437 (test (lambda ()
438 (with-temp-buffer
439 (let ((st (car (current-cpu-time))))
440 (dotimes (_ 1000)
441 (let ((case-fold-search 'data-test))
442 ;; Use an indirection through a mutable var
443 ;; to try and make sure the byte-compiler
444 ;; doesn't optimize away the let bindings.
445 (funcall fun)))
446 ;; FIXME: Handle the wraparound, if any.
447 (- (car (current-cpu-time)) st)))))
448 (_ (setq fun #'ignore))
449 (time1 (funcall test))
450 (bufs (mapcar (lambda (_) (generate-new-buffer " data-test"))
451 (make-list 1000 nil)))
452 (time2 (funcall test)))
453 (mapc #'kill-buffer bufs)
454 ;; Don't divide one time by the other since they may be 0.
455 (should (< time2 (* time1 5))))))
456
374;; More tests to write - 457;; More tests to write -
375;; kill-local-variable 458;; kill-local-variable
376;; defconst; can modify 459;; defconst; can modify
@@ -474,7 +557,7 @@ comparing the subr with a much slower lisp implementation."
474 (should-have-watch-data `(data-tests-lvar 3 set ,buf1))) 557 (should-have-watch-data `(data-tests-lvar 3 set ,buf1)))
475 (should-have-watch-data `(data-tests-lvar 1 unlet ,buf1)) 558 (should-have-watch-data `(data-tests-lvar 1 unlet ,buf1))
476 (setq-default data-tests-lvar 4) 559 (setq-default data-tests-lvar 4)
477 (should-have-watch-data `(data-tests-lvar 4 set nil)) 560 (should-have-watch-data '(data-tests-lvar 4 set nil))
478 (with-temp-buffer 561 (with-temp-buffer
479 (setq buf2 (current-buffer)) 562 (setq buf2 (current-buffer))
480 (setq data-tests-lvar 1) 563 (setq data-tests-lvar 1)
@@ -491,7 +574,7 @@ comparing the subr with a much slower lisp implementation."
491 (kill-all-local-variables) 574 (kill-all-local-variables)
492 (should-have-watch-data `(data-tests-lvar nil makunbound ,buf2))) 575 (should-have-watch-data `(data-tests-lvar nil makunbound ,buf2)))
493 (setq-default data-tests-lvar 4) 576 (setq-default data-tests-lvar 4)
494 (should-have-watch-data `(data-tests-lvar 4 set nil)) 577 (should-have-watch-data '(data-tests-lvar 4 set nil))
495 (makunbound 'data-tests-lvar) 578 (makunbound 'data-tests-lvar)
496 (should-have-watch-data '(data-tests-lvar nil makunbound nil)) 579 (should-have-watch-data '(data-tests-lvar nil makunbound nil))
497 (setq data-tests-lvar 5) 580 (setq data-tests-lvar 5)
@@ -499,3 +582,194 @@ comparing the subr with a much slower lisp implementation."
499 (remove-variable-watcher 'data-tests-lvar collect-watch-data) 582 (remove-variable-watcher 'data-tests-lvar collect-watch-data)
500 (setq data-tests-lvar 6) 583 (setq data-tests-lvar 6)
501 (should (null watch-data))))) 584 (should (null watch-data)))))
585
586(ert-deftest data-tests-kill-all-local-variables () ;bug#30846
587 (with-temp-buffer
588 (setq-local data-tests-foo1 1)
589 (setq-local data-tests-foo2 2)
590 (setq-local data-tests-foo3 3)
591 (let ((oldfoo2 nil))
592 (add-variable-watcher 'data-tests-foo2
593 (lambda (&rest _)
594 (setq oldfoo2 (bound-and-true-p data-tests-foo2))))
595 (kill-all-local-variables)
596 (should (equal oldfoo2 '2)) ;Watcher is run before changing the var.
597 (should (not (or (bound-and-true-p data-tests-foo1)
598 (bound-and-true-p data-tests-foo2)
599 (bound-and-true-p data-tests-foo3)))))))
600
601(ert-deftest data-tests-bignum ()
602 (should (bignump (+ most-positive-fixnum 1)))
603 (let ((f0 (+ (float most-positive-fixnum) 1))
604 (f-1 (- (float most-negative-fixnum) 1))
605 (b0 (+ most-positive-fixnum 1))
606 (b-1 (- most-negative-fixnum 1)))
607 (should (> b0 -1))
608 (should (> b0 f-1))
609 (should (> b0 b-1))
610 (should (>= b0 -1))
611 (should (>= b0 f-1))
612 (should (>= b0 b-1))
613 (should (>= b-1 b-1))
614
615 (should (< -1 b0))
616 (should (< f-1 b0))
617 (should (< b-1 b0))
618 (should (<= -1 b0))
619 (should (<= f-1 b0))
620 (should (<= b-1 b0))
621 (should (<= b-1 b-1))
622
623 (should (= (+ f0 b0) (+ b0 f0)))
624 (should (= (+ f0 b-1) (+ b-1 f0)))
625 (should (= (+ f-1 b0) (+ b0 f-1)))
626 (should (= (+ f-1 b-1) (+ b-1 f-1)))
627
628 (should (= (* f0 b0) (* b0 f0)))
629 (should (= (* f0 b-1) (* b-1 f0)))
630 (should (= (* f-1 b0) (* b0 f-1)))
631 (should (= (* f-1 b-1) (* b-1 f-1)))
632
633 (should (= b0 f0))
634 (should (= b0 b0))
635
636 (should (/= b0 f-1))
637 (should (/= b0 b-1))
638
639 (should (/= b0 0.0e+NaN))
640 (should (/= b-1 0.0e+NaN))))
641
642(ert-deftest data-tests-+ ()
643 (should-not (fixnump (+ most-positive-fixnum most-positive-fixnum)))
644 (should (> (+ most-positive-fixnum most-positive-fixnum) most-positive-fixnum))
645 (should (eq (- (+ most-positive-fixnum most-positive-fixnum)
646 (+ most-positive-fixnum most-positive-fixnum))
647 0)))
648
649(ert-deftest data-tests-/ ()
650 (let* ((x (* most-positive-fixnum 8))
651 (y (* most-negative-fixnum 8))
652 (z (- y)))
653 (should (= most-positive-fixnum (/ x 8)))
654 (should (= most-negative-fixnum (/ y 8)))
655 (should (= -1 (/ y z)))
656 (should (= -1 (/ z y)))
657 (should (= 0 (/ x (* 2 x))))
658 (should (= 0 (/ y (* 2 y))))
659 (should (= 0 (/ z (* 2 z))))))
660
661(ert-deftest data-tests-number-predicates ()
662 (should (fixnump 0))
663 (should (fixnump most-negative-fixnum))
664 (should (fixnump most-positive-fixnum))
665 (should (integerp (+ most-positive-fixnum 1)))
666 (should (integer-or-marker-p (+ most-positive-fixnum 1)))
667 (should (numberp (+ most-positive-fixnum 1)))
668 (should (number-or-marker-p (+ most-positive-fixnum 1)))
669 (should (natnump (+ most-positive-fixnum 1)))
670 (should-not (fixnump (+ most-positive-fixnum 1)))
671 (should (bignump (+ most-positive-fixnum 1))))
672
673(ert-deftest data-tests-number-to-string ()
674 (let* ((s "99999999999999999999999999999")
675 (v (read s)))
676 (should (equal (number-to-string v) s))))
677
678(ert-deftest data-tests-1+ ()
679 (should (> (1+ most-positive-fixnum) most-positive-fixnum))
680 (should (fixnump (1+ (1- most-negative-fixnum)))))
681
682(ert-deftest data-tests-1- ()
683 (should (< (1- most-negative-fixnum) most-negative-fixnum))
684 (should (fixnump (1- (1+ most-positive-fixnum)))))
685
686(ert-deftest data-tests-logand ()
687 (should (= -1 (logand) (logand -1) (logand -1 -1)))
688 (let ((n (1+ most-positive-fixnum)))
689 (should (= (logand -1 n) n)))
690 (let ((n (* 2 most-negative-fixnum)))
691 (should (= (logand -1 n) n))))
692
693(ert-deftest data-tests-logcount-2 ()
694 (should (= (logcount (read "#xffffffffffffffffffffffffffffffff")) 128)))
695
696(ert-deftest data-tests-logior ()
697 (should (= -1 (logior -1) (logior -1 -1)))
698 (should (= -1 (logior most-positive-fixnum most-negative-fixnum))))
699
700(ert-deftest data-tests-logxor ()
701 (should (= -1 (logxor -1) (logxor -1 -1 -1)))
702 (let ((n (1+ most-positive-fixnum)))
703 (should (= (logxor -1 n) (lognot n)))))
704
705(ert-deftest data-tests-minmax ()
706 (let ((a (- most-negative-fixnum 1))
707 (b (+ most-positive-fixnum 1))
708 (c 0))
709 (should (= (min a b c) a))
710 (should (= (max a b c) b))))
711
712(defun data-tests-check-sign (x y)
713 (should (eq (cl-signum x) (cl-signum y))))
714
715(ert-deftest data-tests-%-mod ()
716 (let* ((b1 (+ most-positive-fixnum 1))
717 (nb1 (- b1))
718 (b3 (+ most-positive-fixnum 3))
719 (nb3 (- b3)))
720 (data-tests-check-sign (% 1 3) (% b1 b3))
721 (data-tests-check-sign (mod 1 3) (mod b1 b3))
722 (data-tests-check-sign (% 1 -3) (% b1 nb3))
723 (data-tests-check-sign (mod 1 -3) (mod b1 nb3))
724 (data-tests-check-sign (% -1 3) (% nb1 b3))
725 (data-tests-check-sign (mod -1 3) (mod nb1 b3))
726 (data-tests-check-sign (% -1 -3) (% nb1 nb3))
727 (data-tests-check-sign (mod -1 -3) (mod nb1 nb3))))
728
729(ert-deftest data-tests-mod-0 ()
730 (dolist (num (list (1- most-negative-fixnum) -1 0 1
731 (1+ most-positive-fixnum)))
732 (should-error (mod num 0)))
733 (when (ignore-errors (/ 0.0 0))
734 (should (equal (abs (mod 0.0 0)) (abs (- 0.0 (/ 0.0 0)))))))
735
736(ert-deftest data-tests-ash-lsh ()
737 (should (= (ash most-negative-fixnum 1)
738 (* most-negative-fixnum 2)))
739 (should (= (ash 0 (* 2 most-positive-fixnum)) 0))
740 (should (= (ash 1000 (* 2 most-negative-fixnum)) 0))
741 (should (= (ash -1000 (* 2 most-negative-fixnum)) -1))
742 (should (= (ash (* 2 most-negative-fixnum) (* 2 most-negative-fixnum)) -1))
743 (should (= (ash (* 2 most-negative-fixnum) -1)
744 most-negative-fixnum))
745 (with-suppressed-warnings ((suspicious lsh))
746 (should (= (lsh most-negative-fixnum 1)
747 (* most-negative-fixnum 2)))
748 (should (= (lsh most-positive-fixnum -1) (/ most-positive-fixnum 2)))
749 (should (= (lsh most-negative-fixnum -1) (lsh (- most-negative-fixnum) -1)))
750 (should (= (lsh -1 -1) most-positive-fixnum))
751 (should-error (lsh (1- most-negative-fixnum) -1))))
752
753(ert-deftest data-tests-make-local-forwarded-var () ;bug#34318
754 ;; Boy, this bug is tricky to trigger. You need to:
755 ;; - call make-local-variable on a forwarded var (i.e. one that
756 ;; has a corresponding C var linked via DEFVAR_(LISP|INT|BOOL))
757 ;; - cause the C code to modify this variable from the C side of the
758 ;; forwarding, but this needs to happen before the var is accessed
759 ;; from the Lisp side and before we switch to another buffer.
760 ;; The trigger in bug#34318 doesn't exist any more because the C code has
761 ;; changed. Instead I found the trigger below.
762 (with-temp-buffer
763 (setq last-coding-system-used 'bug34318)
764 (make-local-variable 'last-coding-system-used)
765 ;; This should set last-coding-system-used to `no-conversion'.
766 (decode-coding-string "hello" nil)
767 (should (equal (list last-coding-system-used
768 (default-value 'last-coding-system-used))
769 '(no-conversion bug34318)))))
770
771(ert-deftest data-tests-make_symbol_constant ()
772 "Can't set variable marked with 'make_symbol_constant'."
773 (should-error (setq most-positive-fixnum 1) :type 'setting-constant))
774
775;;; data-tests.el ends here
diff --git a/test/src/decompress-tests.el b/test/src/decompress-tests.el
index 8a6f4d1fb95..47d67b7bda4 100644
--- a/test/src/decompress-tests.el
+++ b/test/src/decompress-tests.el
@@ -1,6 +1,6 @@
1;;; decompress-tests.el --- Test suite for decompress. 1;;; decompress-tests.el --- Test suite for decompress. -*- lexical-binding: t -*-
2 2
3;; Copyright (C) 2013-2017 Free Software Foundation, Inc. 3;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
4 4
5;; Author: Lars Ingebrigtsen <larsi@gnus.org> 5;; Author: Lars Ingebrigtsen <larsi@gnus.org>
6 6
@@ -23,23 +23,25 @@
23 23
24(require 'ert) 24(require 'ert)
25 25
26(declare-function zlib-decompress-region "decompress.c")
27
26(defvar zlib-tests-data-directory 28(defvar zlib-tests-data-directory
27 (expand-file-name "data/decompress" (getenv "EMACS_TEST_DIRECTORY")) 29 (expand-file-name "data/decompress" (getenv "EMACS_TEST_DIRECTORY"))
28 "Directory containing zlib test data.") 30 "Directory containing zlib test data.")
29 31
30(ert-deftest zlib--decompress () 32(ert-deftest zlib--decompress ()
31 "Test decompressing a gzipped file." 33 "Test decompressing a gzipped file."
32 (when (and (fboundp 'zlib-available-p) 34 (skip-unless (and (fboundp 'zlib-available-p)
33 (zlib-available-p)) 35 (zlib-available-p)))
34 (should (string= 36 (should (string=
35 (with-temp-buffer 37 (with-temp-buffer
36 (set-buffer-multibyte nil) 38 (set-buffer-multibyte nil)
37 (insert-file-contents-literally 39 (insert-file-contents-literally
38 (expand-file-name "foo.gz" zlib-tests-data-directory)) 40 (expand-file-name "foo.gz" zlib-tests-data-directory))
39 (zlib-decompress-region (point-min) (point-max)) 41 (zlib-decompress-region (point-min) (point-max))
40 (buffer-string)) 42 (buffer-string))
41 "foo\n")))) 43 "foo\n")))
42 44
43(provide 'decompress-tests) 45(provide 'decompress-tests)
44 46
45;;; decompress-tests.el ends here. 47;;; decompress-tests.el ends here
diff --git a/test/src/doc-tests.el b/test/src/doc-tests.el
index d8e4320bc6f..ee4f02347ec 100644
--- a/test/src/doc-tests.el
+++ b/test/src/doc-tests.el
@@ -1,92 +1,43 @@
1;;; doc-tests.el --- Tests for doc.c 1;;; doc-tests.el --- tests for doc.c functions -*- lexical-binding: t -*-
2 2
3;; Copyright (C) 2016-2017 Free Software Foundation, Inc. 3;; Copyright (C) 2022 Free Software Foundation, Inc.
4 4
5;; Author: Eli Zaretskii <eliz@gnu.org> 5;; This file is part of GNU Emacs.
6 6
7;; This program is free software; you can redistribute it and/or modify 7;; GNU Emacs is free software: you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by 8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation, either version 3 of the License, or 9;; the Free Software Foundation, either version 3 of the License, or
10;; (at your option) any later version. 10;; (at your option) any later version.
11 11
12;; This program is distributed in the hope that it will be useful, 12;; GNU Emacs is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of 13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; GNU General Public License for more details. 15;; GNU General Public License for more details.
16 16
17;; You should have received a copy of the GNU General Public License 17;; You should have received a copy of the GNU General Public License
18;; along with this program. If not, see <https://www.gnu.org/licenses/>. 18;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
19 19
20;;; Code: 20;;; Code:
21 21
22(require 'ert) 22(require 'ert)
23 23
24(ert-deftest doc-test-substitute-command-keys () 24(ert-deftest doc-tests-documentation/c-primitive ()
25 ;; Bindings. 25 (should (stringp (documentation 'defalias))))
26 (should (string= (substitute-command-keys "foo \\[goto-char]") "foo M-g c"))
27 ;; Cannot use string= here, as that compares unibyte and multibyte
28 ;; strings not equal.
29 (should (compare-strings
30 (substitute-command-keys "\200 \\[goto-char]") nil nil
31 "\200 M-g c" nil nil))
32 ;; Literals.
33 (should (string= (substitute-command-keys "foo \\=\\[goto-char]")
34 "foo \\[goto-char]"))
35 (should (string= (substitute-command-keys "foo \\=\\=")
36 "foo \\="))
37 ;; Keymaps.
38 (should (string= (substitute-command-keys
39 "\\{minibuffer-local-must-match-map}")
40 "\
41key binding
42--- -------
43 26
44C-g abort-recursive-edit 27(ert-deftest doc-tests-documentation/preloaded ()
45TAB minibuffer-complete 28 (should (stringp (documentation 'defun))))
46C-j minibuffer-complete-and-exit
47RET minibuffer-complete-and-exit
48ESC Prefix Command
49SPC minibuffer-complete-word
50? minibuffer-completion-help
51<C-tab> file-cache-minibuffer-complete
52<XF86Back> previous-history-element
53<XF86Forward> next-history-element
54<down> next-line-or-history-element
55<next> next-history-element
56<prior> switch-to-completions
57<up> previous-line-or-history-element
58 29
59M-v switch-to-completions 30(ert-deftest doc-tests-documentation/autoloaded-macro ()
31 (skip-unless noninteractive)
32 (should (autoloadp (symbol-function 'benchmark-run)))
33 (should (stringp (documentation 'benchmark-run)))) ; See Bug#52969.
60 34
61M-n next-history-element 35(ert-deftest doc-tests-documentation/autoloaded-defun ()
62M-p previous-history-element 36 (skip-unless noninteractive)
63M-r previous-matching-history-element 37 (should (autoloadp (symbol-function 'tetris)))
64M-s next-matching-history-element 38 (should (stringp (documentation 'tetris)))) ; See Bug#52969.
65 39
66")) 40(ert-deftest doc-tests-quoting-style ()
67 (should (string= 41 (should (memq (text-quoting-style) '(grave straight curve))))
68 (substitute-command-keys
69 "\\<minibuffer-local-must-match-map>\\[abort-recursive-edit]")
70 "C-g"))
71 ;; Allow any style of quotes, since the terminal might not support
72 ;; UTF-8.
73 (should (string-match
74 "\nUses keymap [`‘']foobar-map['’], which is not currently defined.\n"
75 (substitute-command-keys "\\{foobar-map}")))
76 ;; Quotes.
77 (should (let ((text-quoting-style 'grave))
78 (string= (substitute-command-keys "quotes `like this'")
79 "quotes `like this'")))
80 (should (let ((text-quoting-style 'grave))
81 (string= (substitute-command-keys "quotes ‘like this’")
82 "quotes ‘like this’")))
83 (should (let ((text-quoting-style 'straight))
84 (string= (substitute-command-keys "quotes `like this'")
85 "quotes 'like this'")))
86 ;; Bugs.
87 (should (string= (substitute-command-keys "\\[foobar") "\\[foobar"))
88 (should (string= (substitute-command-keys "\\=") "\\="))
89 )
90 42
91(provide 'doc-tests)
92;;; doc-tests.el ends here 43;;; doc-tests.el ends here
diff --git a/test/src/editfns-tests.el b/test/src/editfns-tests.el
index 70dc9372fad..5fe896fbbd1 100644
--- a/test/src/editfns-tests.el
+++ b/test/src/editfns-tests.el
@@ -1,21 +1,21 @@
1;;; editfns-tests.el -- tests for editfns.c 1;;; editfns-tests.el --- tests for editfns.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;; This file is part of GNU Emacs. 5;; This file is part of GNU Emacs.
6 6
7;; This program is free software; you can redistribute it and/or modify 7;; GNU Emacs is free software: you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by 8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation, either version 3 of the License, or 9;; the Free Software Foundation, either version 3 of the License, or
10;; (at your option) any later version. 10;; (at your option) any later version.
11 11
12;; This program is distributed in the hope that it will be useful, 12;; GNU Emacs is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of 13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; GNU General Public License for more details. 15;; GNU General Public License for more details.
16 16
17;; You should have received a copy of the GNU General Public License 17;; You should have received a copy of the GNU General Public License
18;; along with this program. If not, see <https://www.gnu.org/licenses/>. 18;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
19 19
20;;; Code: 20;;; Code:
21 21
@@ -23,16 +23,16 @@
23 23
24(ert-deftest format-properties () 24(ert-deftest format-properties ()
25 ;; Bug #23730 25 ;; Bug #23730
26 (should (ert-equal-including-properties 26 (should (equal-including-properties
27 (format (propertize "%d" 'face '(:background "red")) 1) 27 (format (propertize "%d" 'face '(:background "red")) 1)
28 #("1" 0 1 (face (:background "red"))))) 28 #("1" 0 1 (face (:background "red")))))
29 (should (ert-equal-including-properties 29 (should (equal-including-properties
30 (format (propertize "%2d" 'face '(:background "red")) 1) 30 (format (propertize "%2d" 'face '(:background "red")) 1)
31 #(" 1" 0 2 (face (:background "red"))))) 31 #(" 1" 0 2 (face (:background "red")))))
32 (should (ert-equal-including-properties 32 (should (equal-including-properties
33 (format (propertize "%02d" 'face '(:background "red")) 1) 33 (format (propertize "%02d" 'face '(:background "red")) 1)
34 #("01" 0 2 (face (:background "red"))))) 34 #("01" 0 2 (face (:background "red")))))
35 (should (ert-equal-including-properties 35 (should (equal-including-properties
36 (format (concat (propertize "%2d" 'x 'X) 36 (format (concat (propertize "%2d" 'x 'X)
37 (propertize "a" 'a 'A) 37 (propertize "a" 'a 'A)
38 (propertize "b" 'b 'B)) 38 (propertize "b" 'b 'B))
@@ -40,27 +40,27 @@
40 #(" 1ab" 0 2 (x X) 2 3 (a A) 3 4 (b B)))) 40 #(" 1ab" 0 2 (x X) 2 3 (a A) 3 4 (b B))))
41 41
42 ;; Bug #5306 42 ;; Bug #5306
43 (should (ert-equal-including-properties 43 (should (equal-including-properties
44 (format "%.10s" 44 (format "%.10s"
45 (concat "1234567890aaaa" 45 (concat "1234567890aaaa"
46 (propertize "12345678901234567890" 'xxx 25))) 46 (propertize "12345678901234567890" 'xxx 25)))
47 "1234567890")) 47 "1234567890"))
48 (should (ert-equal-including-properties 48 (should (equal-including-properties
49 (format "%.10s" 49 (format "%.10s"
50 (concat "123456789" 50 (concat "123456789"
51 (propertize "12345678901234567890" 'xxx 25))) 51 (propertize "12345678901234567890" 'xxx 25)))
52 #("1234567891" 9 10 (xxx 25)))) 52 #("1234567891" 9 10 (xxx 25))))
53 53
54 ;; Bug #23859 54 ;; Bug #23859
55 (should (ert-equal-including-properties 55 (should (equal-including-properties
56 (format "%4s" (propertize "hi" 'face 'bold)) 56 (format "%4s" (propertize "hi" 'face 'bold))
57 #(" hi" 2 4 (face bold)))) 57 #(" hi" 2 4 (face bold))))
58 58
59 ;; Bug #23897 59 ;; Bug #23897
60 (should (ert-equal-including-properties 60 (should (equal-including-properties
61 (format "%s" (concat (propertize "01234" 'face 'bold) "56789")) 61 (format "%s" (concat (propertize "01234" 'face 'bold) "56789"))
62 #("0123456789" 0 5 (face bold)))) 62 #("0123456789" 0 5 (face bold))))
63 (should (ert-equal-including-properties 63 (should (equal-including-properties
64 (format "%s" (concat (propertize "01" 'face 'bold) 64 (format "%s" (concat (propertize "01" 'face 'bold)
65 (propertize "23" 'face 'underline) 65 (propertize "23" 'face 'underline)
66 "45")) 66 "45"))
@@ -68,27 +68,69 @@
68 ;; The last property range is extended to include padding on the 68 ;; The last property range is extended to include padding on the
69 ;; right, but the first range is not extended to the left to include 69 ;; right, but the first range is not extended to the left to include
70 ;; padding on the left! 70 ;; padding on the left!
71 (should (ert-equal-including-properties 71 (should (equal-including-properties
72 (format "%12s" (concat (propertize "01234" 'face 'bold) "56789")) 72 (format "%12s" (concat (propertize "01234" 'face 'bold) "56789"))
73 #(" 0123456789" 2 7 (face bold)))) 73 #(" 0123456789" 2 7 (face bold))))
74 (should (ert-equal-including-properties 74 (should (equal-including-properties
75 (format "%-12s" (concat (propertize "01234" 'face 'bold) "56789")) 75 (format "%-12s" (concat (propertize "01234" 'face 'bold) "56789"))
76 #("0123456789 " 0 5 (face bold)))) 76 #("0123456789 " 0 5 (face bold))))
77 (should (ert-equal-including-properties 77 (should (equal-including-properties
78 (format "%10s" (concat (propertize "01" 'face 'bold) 78 (format "%10s" (concat (propertize "01" 'face 'bold)
79 (propertize "23" 'face 'underline) 79 (propertize "23" 'face 'underline)
80 "45")) 80 "45"))
81 #(" 012345" 4 6 (face bold) 6 8 (face underline)))) 81 #(" 012345" 4 6 (face bold) 6 8 (face underline))))
82 (should (ert-equal-including-properties 82 (should (equal-including-properties
83 (format "%-10s" (concat (propertize "01" 'face 'bold) 83 (format "%-10s" (concat (propertize "01" 'face 'bold)
84 (propertize "23" 'face 'underline) 84 (propertize "23" 'face 'underline)
85 "45")) 85 "45"))
86 #("012345 " 0 2 (face bold) 2 4 (face underline)))) 86 #("012345 " 0 2 (face bold) 2 4 (face underline))))
87 (should (ert-equal-including-properties 87 (should (equal-including-properties
88 (format "%-10s" (concat (propertize "01" 'face 'bold) 88 (format "%-10s" (concat (propertize "01" 'face 'bold)
89 (propertize "23" 'face 'underline) 89 (propertize "23" 'face 'underline)
90 (propertize "45" 'face 'italic))) 90 (propertize "45" 'face 'italic)))
91 #("012345 " 0 2 (face bold) 2 4 (face underline) 4 10 (face italic))))) 91 #("012345 "
92 0 2 (face bold) 2 4 (face underline) 4 10 (face italic))))
93 ;; Bug #38191
94 (should (equal-including-properties
95 (format (propertize "‘foo’ %s bar" 'face 'bold) "xxx")
96 #("‘foo’ xxx bar" 0 13 (face bold))))
97 ;; Bug #32404
98 (should (equal-including-properties
99 (format (concat (propertize "%s" 'face 'bold)
100 ""
101 (propertize "%s" 'face 'error))
102 "foo" "bar")
103 #("foobar" 0 3 (face bold) 3 6 (face error))))
104 (should (equal-including-properties
105 (format (concat "%s" (propertize "%s" 'face 'error)) "foo" "bar")
106 #("foobar" 3 6 (face error))))
107 (should (equal-including-properties
108 (format (concat "%s " (propertize "%s" 'face 'error)) "foo" "bar")
109 #("foo bar" 4 7 (face error))))
110 ;; Bug #46317
111 (let ((s (propertize "X" 'prop "val")))
112 (should (equal-including-properties
113 (format (concat "%3s/" s) 12)
114 #(" 12/X" 4 5 (prop "val"))))
115 (should (equal-including-properties
116 (format (concat "%3S/" s) 12)
117 #(" 12/X" 4 5 (prop "val"))))
118 (should (equal-including-properties
119 (format (concat "%3d/" s) 12)
120 #(" 12/X" 4 5 (prop "val"))))
121 (should (equal-including-properties
122 (format (concat "%-3s/" s) 12)
123 #("12 /X" 4 5 (prop "val"))))
124 (should (equal-including-properties
125 (format (concat "%-3S/" s) 12)
126 #("12 /X" 4 5 (prop "val"))))
127 (should (equal-including-properties
128 (format (concat "%-3d/" s) 12)
129 #("12 /X" 4 5 (prop "val"))))))
130
131(ert-deftest propertize/error-even-number-of-args ()
132 "Number of args for `propertize' must be odd."
133 (should-error (propertize "foo" 'bar) :type 'wrong-number-of-arguments))
92 134
93;; Tests for bug#5131. 135;; Tests for bug#5131.
94(defun transpose-test-reverse-word (start end) 136(defun transpose-test-reverse-word (start end)
@@ -106,8 +148,8 @@
106 "Validate character position to byte position translation." 148 "Validate character position to byte position translation."
107 (let ((bytes '())) 149 (let ((bytes '()))
108 (dotimes (pos len) 150 (dotimes (pos len)
109 (setq bytes (add-to-list 'bytes (position-bytes (1+ pos)) t))) 151 (push (position-bytes (1+ pos)) bytes))
110 bytes)) 152 (nreverse bytes)))
111 153
112(ert-deftest transpose-ascii-regions-test () 154(ert-deftest transpose-ascii-regions-test ()
113 (with-temp-buffer 155 (with-temp-buffer
@@ -136,54 +178,59 @@
136(ert-deftest format-c-float () 178(ert-deftest format-c-float ()
137 (should-error (format "%c" 0.5))) 179 (should-error (format "%c" 0.5)))
138 180
139;;; Check format-time-string with various TZ settings. 181;;; Test for Bug#29609.
140;;; Use only POSIX-compatible TZ values, since the tests should work 182(ert-deftest format-sharp-0-x ()
141;;; even if tzdb is not in use. 183 (should (string-equal (format "%#08x" #x10) "0x000010"))
142(ert-deftest format-time-string-with-zone () 184 (should (string-equal (format "%#05X" #x10) "0X010"))
143 ;; Don’t use (0 0 0 0) as the test case, as there are too many bugs 185 (should (string-equal (format "%#04x" 0) "0000")))
144 ;; in MS-Windows (and presumably other) C libraries when formatting 186
145 ;; time stamps near the Epoch of 1970-01-01 00:00:00 UTC, and this 187
146 ;; test is for GNU Emacs, not for C runtimes. Instead, look before 188;;; Tests for Bug#30408.
147 ;; you leap: "look" is the timestamp just before the first leap 189
148 ;; second on 1972-06-30 23:59:60 UTC, so it should format to the 190(ert-deftest format-%d-large-float ()
149 ;; same string regardless of whether the underlying C library 191 (should (string-equal (format "%d" 18446744073709551616.0)
150 ;; ignores leap seconds, while avoiding circa-1970 glitches. 192 "18446744073709551616"))
151 ;; 193 (should (string-equal (format "%d" -18446744073709551616.0)
152 ;; Similarly, stick to the limited set of time zones that are 194 "-18446744073709551616")))
153 ;; supported by both POSIX and MS-Windows: exactly 3 ASCII letters 195
154 ;; in the abbreviation, and no DST. 196(ert-deftest format-%x-large-float ()
155 (let ((look '(1202 22527 999999 999999)) 197 (should (string-equal (format "%x" 18446744073709551616.0)
156 (format "%Y-%m-%d %H:%M:%S.%3N %z (%Z)")) 198 "10000000000000000")))
157 ;; UTC. 199(ert-deftest read-large-integer ()
158 (should (string-equal 200 (should (eq (type-of (read (format "%d0" most-negative-fixnum))) 'integer))
159 (format-time-string "%Y-%m-%d %H:%M:%S.%3N %z" look t) 201 (should (eq (type-of (read (format "%+d" (* -8.0 most-negative-fixnum))))
160 "1972-06-30 23:59:59.999 +0000")) 202 'integer))
161 ;; "UTC0". 203 (should (eq (type-of (read (substring (format "%d" most-negative-fixnum) 1)))
162 (should (string-equal 204 'integer))
163 (format-time-string format look "UTC0") 205 (should (eq (type-of (read (format "#x%x" most-negative-fixnum)))
164 "1972-06-30 23:59:59.999 +0000 (UTC)")) 206 'integer))
165 ;; Negative UTC offset, as a Lisp list. 207 (should (eq (type-of (read (format "#o%o" most-negative-fixnum)))
166 (should (string-equal 208 'integer))
167 (format-time-string format look '(-28800 "PST")) 209 (should (eq (type-of (read (format "#32rG%x" most-positive-fixnum)))
168 "1972-06-30 15:59:59.999 -0800 (PST)")) 210 'integer))
169 ;; Negative UTC offset, as a Lisp integer. 211 (dolist (fmt '("%d" "%s" "#o%o" "#x%x"))
170 (should (string-equal 212 (dolist (val (list most-negative-fixnum (1+ most-negative-fixnum)
171 (format-time-string format look -28800) 213 -1 0 1
172 ;; MS-Windows build replaces unrecognizable TZ values, 214 (1- most-positive-fixnum) most-positive-fixnum))
173 ;; such as "-08", with "ZZZ". 215 (should (eq val (read (format fmt val)))))
174 (if (eq system-type 'windows-nt) 216 (dolist (val (list (1+ most-positive-fixnum)
175 "1972-06-30 15:59:59.999 -0800 (ZZZ)" 217 (* 2 (1+ most-positive-fixnum))
176 "1972-06-30 15:59:59.999 -0800 (-08)"))) 218 (* 4 (1+ most-positive-fixnum))
177 ;; Positive UTC offset that is not an hour multiple, as a string. 219 (* 8 (1+ most-positive-fixnum))
178 (should (string-equal 220 18446744073709551616.0))
179 (format-time-string format look "IST-5:30") 221 (should (= val (read (format fmt val)))))))
180 "1972-07-01 05:29:59.999 +0530 (IST)")))) 222
181 223(ert-deftest format-%o-negative-float ()
182;;; This should not dump core. 224 (should (string-equal (format "%o" -1e-37) "0")))
183(ert-deftest format-time-string-with-outlandish-zone () 225
184 (should (stringp 226;; Bug#31938
185 (format-time-string "%Y-%m-%d %H:%M:%S.%3N %z" nil 227(ert-deftest format-%d-float ()
186 (concat (make-string 2048 ?X) "0"))))) 228 (should (string-equal (format "%d" -1.1) "-1"))
229 (should (string-equal (format "%d" -0.9) "0"))
230 (should (string-equal (format "%d" -0.0) "0"))
231 (should (string-equal (format "%d" 0.0) "0"))
232 (should (string-equal (format "%d" 0.9) "0"))
233 (should (string-equal (format "%d" 1.1) "1")))
187 234
188(ert-deftest format-with-field () 235(ert-deftest format-with-field ()
189 (should (equal (format "First argument %2$s, then %3$s, then %1$s" 1 2 3) 236 (should (equal (format "First argument %2$s, then %3$s, then %1$s" 1 2 3)
@@ -247,4 +294,136 @@
247 (buffer-string) 294 (buffer-string)
248 "foo bar baz qux")))))) 295 "foo bar baz qux"))))))
249 296
297(ert-deftest replace-buffer-contents-bug31837 ()
298 (switch-to-buffer "a")
299 (insert-char (char-from-name "SMILE"))
300 (insert "1234")
301 (switch-to-buffer "b")
302 (insert-char (char-from-name "SMILE"))
303 (insert "5678")
304 (replace-buffer-contents "a")
305 (should (equal (buffer-substring-no-properties (point-min) (point-max))
306 (concat (string (char-from-name "SMILE")) "1234"))))
307
308(ert-deftest delete-region-undo-markers-1 ()
309 "Make sure we don't end up with freed markers reachable from Lisp."
310 ;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=30931#40
311 (with-temp-buffer
312 (insert "1234567890")
313 (setq buffer-undo-list nil)
314 (narrow-to-region 2 5)
315 ;; `save-restriction' in a narrowed buffer creates two markers
316 ;; representing the current restriction.
317 (save-restriction
318 (widen)
319 ;; Any markers *within* the deleted region are put onto the undo
320 ;; list.
321 (delete-region 1 6))
322 ;; (princ (format "%S" buffer-undo-list) #'external-debugging-output)
323 ;; `buffer-undo-list' is now
324 ;; (("12345" . 1) (#<temp-marker1> . -1) (#<temp-marker2> . 1))
325 ;;
326 ;; If temp-marker1 or temp-marker2 are freed prematurely, calling
327 ;; `type-of' on them will cause Emacs to abort. Calling
328 ;; `garbage-collect' will also abort if it finds any reachable
329 ;; freed objects.
330 (should (eq (type-of (car (nth 1 buffer-undo-list))) 'marker))
331 (should (eq (type-of (car (nth 2 buffer-undo-list))) 'marker))
332 (garbage-collect)))
333
334(ert-deftest delete-region-undo-markers-2 ()
335 "Make sure we don't end up with freed markers reachable from Lisp."
336 ;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=30931#55
337 (with-temp-buffer
338 (insert "1234567890")
339 (setq buffer-undo-list nil)
340 ;; signal_before_change creates markers delimiting a change
341 ;; region.
342 (let ((before-change-functions
343 (list (lambda (beg end)
344 (delete-region (1- beg) (1+ end))))))
345 (delete-region 2 5))
346 ;; (princ (format "%S" buffer-undo-list) #'external-debugging-output)
347 ;; `buffer-undo-list' is now
348 ;; (("678" . 1) ("12345" . 1) (#<marker in no buffer> . -1)
349 ;; (#<temp-marker1> . -1) (#<temp-marker2> . -4))
350 ;;
351 ;; If temp-marker1 or temp-marker2 are freed prematurely, calling
352 ;; `type-of' on them will cause Emacs to abort. Calling
353 ;; `garbage-collect' will also abort if it finds any reachable
354 ;; freed objects.
355 (should (eq (type-of (car (nth 3 buffer-undo-list))) 'marker))
356 (should (eq (type-of (car (nth 4 buffer-undo-list))) 'marker))
357 (garbage-collect)))
358
359(ert-deftest format-bignum ()
360 (let* ((s1 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
361 (v1 (read (concat "#x" s1)))
362 (s2 "99999999999999999999999999999999")
363 (v2 (read s2))
364 (v3 #x-3ffffffffffffffe000000000000000))
365 (should (> v1 most-positive-fixnum))
366 (should (equal (format "%X" v1) s1))
367 (should (> v2 most-positive-fixnum))
368 (should (equal (format "%d" v2) s2))
369 (should (equal (format "%d" v3) "-5316911983139663489309385231907684352"))
370 (should (equal (format "%+d" v3) "-5316911983139663489309385231907684352"))
371 (should (equal (format "%+d" (- v3))
372 "+5316911983139663489309385231907684352"))
373 (should (equal (format "% d" (- v3))
374 " 5316911983139663489309385231907684352"))
375 (should (equal (format "%o" v3)
376 "-37777777777777777777600000000000000000000"))
377 (should (equal (format "%#50.40x" v3)
378 " -0x000000003ffffffffffffffe000000000000000"))
379 (should (equal (format "%-#50.40x" v3)
380 "-0x000000003ffffffffffffffe000000000000000 "))))
381
382(ert-deftest test-group-name ()
383 (let ((group-name (group-name (group-gid))))
384 ;; If the GID has no associated entry in /etc/group there's no
385 ;; name for it and `group-name' should return nil!
386 (should (or (null group-name) (stringp group-name))))
387 (should-error (group-name 'foo))
388 (cond
389 ((memq system-type '(windows-nt ms-dos))
390 (should-not (group-name 123456789)))
391 ((executable-find "getent")
392 (with-temp-buffer
393 (let (stat name)
394 (dolist (gid (list 0 1212345 (group-gid)))
395 (erase-buffer)
396 (setq stat (ignore-errors
397 (call-process "getent" nil '(t nil) nil "group"
398 (number-to-string gid))))
399 (setq name (group-name gid))
400 (goto-char (point-min))
401 (cond ((eq stat 0)
402 (if (looking-at "\\([[:alnum:]_-]+\\):")
403 (should (string= (match-string 1) name))))
404 ((eq stat 2)
405 (should-not name)))))))))
406
407(ert-deftest test-translate-region-internal ()
408 (with-temp-buffer
409 (let ((max-char #16r3FFFFF)
410 (tt (make-char-table 'translation-table)))
411 (aset tt max-char ?*)
412 (insert max-char)
413 (translate-region-internal (point-min) (point-max) tt)
414 (should (string-equal (buffer-string) "*")))))
415
416(ert-deftest find-fields ()
417 (with-temp-buffer
418 (insert "foo" (propertize "bar" 'field 'bar) "zot")
419 (goto-char (point-min))
420 (should (= (field-beginning) (point-min)))
421 (should (= (field-end) 4))
422 (goto-char 5)
423 (should (= (field-beginning) 4))
424 (should (= (field-end) 7))
425 (goto-char 8)
426 (should (= (field-beginning) 7))
427 (should (= (field-end) (point-max)))))
428
250;;; editfns-tests.el ends here 429;;; editfns-tests.el ends here
diff --git a/test/src/emacs-module-resources/mod-test.c b/test/src/emacs-module-resources/mod-test.c
new file mode 100644
index 00000000000..187af821c22
--- /dev/null
+++ b/test/src/emacs-module-resources/mod-test.c
@@ -0,0 +1,868 @@
1/* Test GNU Emacs modules.
2
3Copyright 2015-2022 Free Software Foundation, Inc.
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation, either version 3 of the License, or (at
10your option) any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
19
20#include "config.h"
21
22#undef NDEBUG
23#include <assert.h>
24
25#include <errno.h>
26#include <limits.h>
27#include <stdbool.h>
28#include <stdint.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <time.h>
33
34#ifdef WINDOWSNT
35/* Cannot include <process.h> because of the local header by the same
36 name, sigh. */
37uintptr_t _beginthread (void (__cdecl *)(void *), unsigned, void *);
38# if !defined __x86_64__
39# define ALIGN_STACK __attribute__((force_align_arg_pointer))
40# endif
41# include <windows.h> /* for Sleep */
42#else /* !WINDOWSNT */
43# include <pthread.h>
44# include <unistd.h>
45#endif
46
47#include <gmp.h>
48#include <emacs-module.h>
49
50int plugin_is_GPL_compatible;
51
52#if INTPTR_MAX <= 0
53# error "INTPTR_MAX misconfigured"
54#elif INTPTR_MAX <= INT_MAX || INTPTR_MAX <= LONG_MAX
55# define pT "ld"
56# define pZ "lu"
57# define T_TYPE long
58# define Z_TYPE unsigned long
59#elif INTPTR_MAX <= INT64_MAX
60# ifdef __MINGW32__
61# define pT "lld"
62# define pZ "llu"
63# define T_TYPE long long
64# define Z_TYPE unsigned long long
65# else
66# define pT "ld"
67# define pZ "lu"
68# define T_TYPE long
69# define Z_TYPE unsigned long
70# endif
71#else
72# error "INTPTR_MAX too large"
73#endif
74
75/* Always return symbol 't'. */
76static emacs_value
77Fmod_test_return_t (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
78 void *data)
79{
80 return env->intern (env, "t");
81}
82
83/* Expose simple sum function. */
84static intmax_t
85sum (intmax_t a, intmax_t b)
86{
87 return a + b;
88}
89
90static emacs_value
91Fmod_test_sum (emacs_env *env, ptrdiff_t nargs, emacs_value args[], void *data)
92{
93 assert (nargs == 2);
94 assert ((uintptr_t) data == 0x1234);
95
96 intmax_t a = env->extract_integer (env, args[0]);
97 intmax_t b = env->extract_integer (env, args[1]);
98
99 intmax_t r = sum (a, b);
100
101 return env->make_integer (env, r);
102}
103
104
105/* Signal '(error 56). */
106static emacs_value
107Fmod_test_signal (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
108 void *data)
109{
110 assert (env->non_local_exit_check (env) == emacs_funcall_exit_return);
111 env->non_local_exit_signal (env, env->intern (env, "error"),
112 env->make_integer (env, 56));
113 return NULL;
114}
115
116
117/* Throw '(tag 65). */
118static emacs_value
119Fmod_test_throw (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
120 void *data)
121{
122 assert (env->non_local_exit_check (env) == emacs_funcall_exit_return);
123 env->non_local_exit_throw (env, env->intern (env, "tag"),
124 env->make_integer (env, 65));
125 return NULL;
126}
127
128
129/* Call argument function, catch all non-local exists and return
130 either normal result or a list describing the non-local exit. */
131static emacs_value
132Fmod_test_non_local_exit_funcall (emacs_env *env, ptrdiff_t nargs,
133 emacs_value args[], void *data)
134{
135 assert (nargs == 1);
136 emacs_value result = env->funcall (env, args[0], 0, NULL);
137 emacs_value non_local_exit_symbol, non_local_exit_data;
138 enum emacs_funcall_exit code
139 = env->non_local_exit_get (env, &non_local_exit_symbol,
140 &non_local_exit_data);
141 switch (code)
142 {
143 case emacs_funcall_exit_return:
144 return result;
145 case emacs_funcall_exit_signal:
146 {
147 env->non_local_exit_clear (env);
148 emacs_value Flist = env->intern (env, "list");
149 emacs_value list_args[] = {env->intern (env, "signal"),
150 non_local_exit_symbol, non_local_exit_data};
151 return env->funcall (env, Flist, 3, list_args);
152 }
153 case emacs_funcall_exit_throw:
154 {
155 env->non_local_exit_clear (env);
156 emacs_value Flist = env->intern (env, "list");
157 emacs_value list_args[] = {env->intern (env, "throw"),
158 non_local_exit_symbol, non_local_exit_data};
159 return env->funcall (env, Flist, 3, list_args);
160 }
161 }
162
163 /* Never reached. */
164 return env->intern (env, "nil");;
165}
166
167
168/* Return a global reference. */
169static emacs_value
170Fmod_test_globref_make (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
171 void *data)
172{
173 /* Make a big string and make it global. */
174 char str[26 * 100];
175 for (int i = 0; i < sizeof str; i++)
176 str[i] = 'a' + (i % 26);
177
178 /* We don't need to null-terminate str. */
179 emacs_value lisp_str = env->make_string (env, str, sizeof str);
180 return env->make_global_ref (env, lisp_str);
181}
182
183/* Create a few global references from arguments and free them. */
184static emacs_value
185Fmod_test_globref_free (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
186 void *data)
187{
188 emacs_value refs[10];
189 for (int i = 0; i < 10; i++)
190 {
191 refs[i] = env->make_global_ref (env, args[i % nargs]);
192 }
193 for (int i = 0; i < 10; i++)
194 {
195 env->free_global_ref (env, refs[i]);
196 }
197 return env->intern (env, "ok");
198}
199
200/* Treat a local reference as global and free it. Module assertions
201 should detect this case even if a global reference representing the
202 same object also exists. */
203
204static emacs_value
205Fmod_test_globref_invalid_free (emacs_env *env, ptrdiff_t nargs,
206 emacs_value *args, void *data)
207{
208 emacs_value local = env->make_integer (env, 9876);
209 env->make_global_ref (env, local);
210 env->free_global_ref (env, local); /* Not allowed. */
211 return env->intern (env, "nil");
212}
213
214/* Allocate and free global references in a different order. */
215
216static emacs_value
217Fmod_test_globref_reordered (emacs_env *env, ptrdiff_t nargs,
218 emacs_value *args, void *data)
219{
220 emacs_value booleans[2] = {
221 env->intern (env, "nil"),
222 env->intern (env, "t"),
223 };
224 emacs_value local = env->intern (env, "foo");
225 emacs_value globals[4] = {
226 env->make_global_ref (env, local),
227 env->make_global_ref (env, local),
228 env->make_global_ref (env, env->intern (env, "foo")),
229 env->make_global_ref (env, env->intern (env, "bar")),
230 };
231 emacs_value elements[4];
232 for (int i = 0; i < 4; ++i)
233 elements[i] = booleans[env->eq (env, globals[i], local)];
234 emacs_value ret = env->funcall (env, env->intern (env, "list"), 4, elements);
235 env->free_global_ref (env, globals[2]);
236 env->free_global_ref (env, globals[1]);
237 env->free_global_ref (env, globals[3]);
238 env->free_global_ref (env, globals[0]);
239 return ret;
240}
241
242
243/* Return a copy of the argument string where every 'a' is replaced
244 with 'b'. */
245static emacs_value
246Fmod_test_string_a_to_b (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
247 void *data)
248{
249 emacs_value lisp_str = args[0];
250 ptrdiff_t size = 0;
251 char * buf = NULL;
252
253 env->copy_string_contents (env, lisp_str, buf, &size);
254 buf = malloc (size);
255 env->copy_string_contents (env, lisp_str, buf, &size);
256
257 for (ptrdiff_t i = 0; i + 1 < size; i++)
258 if (buf[i] == 'a')
259 buf[i] = 'b';
260
261 emacs_value ret = env->make_string (env, buf, size - 1);
262 free (buf);
263 return ret;
264}
265
266
267/* Return a unibyte string. */
268static emacs_value
269Fmod_test_return_unibyte (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
270 void *data)
271{
272 const char *string = "foo\x00zot";
273 return env->make_unibyte_string (env, string, 7);
274}
275
276
277/* Embedded pointers in lisp objects. */
278
279/* C struct (pointer to) that will be embedded. */
280struct super_struct
281{
282 int amazing_int;
283 char large_unused_buffer[512];
284};
285
286static void signal_errno (emacs_env *, char const *);
287
288/* Return a new user-pointer to a super_struct, with amazing_int set
289 to the passed parameter. */
290static emacs_value
291Fmod_test_userptr_make (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
292 void *data)
293{
294 struct super_struct *p = calloc (1, sizeof *p);
295 if (!p)
296 {
297 signal_errno (env, "calloc");
298 return NULL;
299 }
300 p->amazing_int = env->extract_integer (env, args[0]);
301 return env->make_user_ptr (env, free, p);
302}
303
304/* Return the amazing_int of a passed 'user-pointer to a super_struct'. */
305static emacs_value
306Fmod_test_userptr_get (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
307 void *data)
308{
309 struct super_struct *p = env->get_user_ptr (env, args[0]);
310 return env->make_integer (env, p->amazing_int);
311}
312
313
314/* Fill vector in args[0] with value in args[1]. */
315static emacs_value
316Fmod_test_vector_fill (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
317 void *data)
318{
319 emacs_value vec = args[0];
320 emacs_value val = args[1];
321 ptrdiff_t size = env->vec_size (env, vec);
322 for (ptrdiff_t i = 0; i < size; i++)
323 env->vec_set (env, vec, i, val);
324 return env->intern (env, "t");
325}
326
327
328/* Return whether all elements of vector in args[0] are 'eq' to value
329 in args[1]. */
330static emacs_value
331Fmod_test_vector_eq (emacs_env *env, ptrdiff_t nargs, emacs_value args[],
332 void *data)
333{
334 emacs_value vec = args[0];
335 emacs_value val = args[1];
336 ptrdiff_t size = env->vec_size (env, vec);
337 for (ptrdiff_t i = 0; i < size; i++)
338 if (!env->eq (env, env->vec_get (env, vec, i), val))
339 return env->intern (env, "nil");
340 return env->intern (env, "t");
341}
342
343static emacs_value invalid_stored_value;
344
345/* The next two functions perform a possibly-invalid operation: they
346 store a value in a static variable and load it. This causes
347 undefined behavior if the environment that the value was created
348 from is no longer live. The module assertions check for this
349 error. */
350
351static emacs_value
352Fmod_test_invalid_store (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
353 void *data)
354{
355 return invalid_stored_value = env->make_integer (env, 123);
356}
357
358static emacs_value
359Fmod_test_invalid_load (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
360 void *data)
361{
362 return invalid_stored_value;
363}
364
365/* The next function works in conjunction with the two previous ones.
366 It stows away a copy of the object created by
367 `Fmod_test_invalid_store' in a global reference. Module assertions
368 should still detect the invalid load of the local reference. */
369
370static emacs_value global_copy_of_invalid_stored_value;
371
372static emacs_value
373Fmod_test_invalid_store_copy (emacs_env *env, ptrdiff_t nargs,
374 emacs_value *args, void *data)
375{
376 emacs_value local = Fmod_test_invalid_store (env, 0, NULL, NULL);
377 return global_copy_of_invalid_stored_value
378 = env->make_global_ref (env, local);
379}
380
381/* An invalid finalizer: Finalizers are run during garbage collection,
382 where Lisp code can't be executed. -module-assertions tests for
383 this case. */
384
385static emacs_env *current_env;
386
387static void
388invalid_finalizer (void *ptr)
389{
390 current_env->intern (current_env, "nil");
391}
392
393static emacs_value
394Fmod_test_invalid_finalizer (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
395 void *data)
396{
397 current_env = env;
398 env->make_user_ptr (env, invalid_finalizer, NULL);
399 return env->intern (env, "nil");
400}
401
402static void
403signal_system_error (emacs_env *env, int error, const char *function)
404{
405 const char *message = strerror (error);
406 emacs_value message_value = env->make_string (env, message, strlen (message));
407 emacs_value symbol = env->intern (env, "file-error");
408 emacs_value elements[2]
409 = {env->make_string (env, function, strlen (function)), message_value};
410 emacs_value data = env->funcall (env, env->intern (env, "list"), 2, elements);
411 env->non_local_exit_signal (env, symbol, data);
412}
413
414static void
415signal_errno (emacs_env *env, const char *function)
416{
417 signal_system_error (env, errno, function);
418}
419
420#ifdef CLOCK_REALTIME
421
422/* Whether A <= B. */
423static bool
424timespec_le (struct timespec a, struct timespec b)
425{
426 return (a.tv_sec < b.tv_sec
427 || (a.tv_sec == b.tv_sec && a.tv_nsec <= b.tv_nsec));
428}
429
430/* A long-running operation that occasionally calls `should_quit' or
431 `process_input'. */
432
433static emacs_value
434Fmod_test_sleep_until (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
435 void *data)
436{
437 assert (nargs == 2);
438 const struct timespec until = env->extract_time (env, args[0]);
439 if (env->non_local_exit_check (env))
440 return NULL;
441 const bool process_input = env->is_not_nil (env, args[1]);
442 const struct timespec amount = { .tv_nsec = 10000000 };
443 while (true)
444 {
445 struct timespec now;
446 if (clock_gettime (CLOCK_REALTIME, &now) != 0)
447 return NULL;
448 if (timespec_le (until, now))
449 break;
450 if (nanosleep (&amount, NULL) && errno != EINTR)
451 {
452 signal_errno (env, "nanosleep");
453 return NULL;
454 }
455 if ((process_input
456 && env->process_input (env) == emacs_process_input_quit)
457 || env->should_quit (env))
458 return NULL;
459 }
460 return env->intern (env, "finished");
461}
462#endif
463
464static emacs_value
465Fmod_test_add_nanosecond (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
466 void *data)
467{
468 assert (nargs == 1);
469 struct timespec time = env->extract_time (env, args[0]);
470 assert (time.tv_nsec >= 0);
471 assert (time.tv_nsec < 2000000000); /* possible leap second */
472 time.tv_nsec++;
473 return env->make_time (env, time);
474}
475
476static void
477signal_error (emacs_env *env, const char *message)
478{
479 emacs_value data = env->make_string (env, message, strlen (message));
480 env->non_local_exit_signal (env, env->intern (env, "error"),
481 env->funcall (env, env->intern (env, "list"), 1,
482 &data));
483}
484
485static void
486memory_full (emacs_env *env)
487{
488 signal_error (env, "Memory exhausted");
489}
490
491enum
492{
493 max_count = ((SIZE_MAX < PTRDIFF_MAX ? SIZE_MAX : PTRDIFF_MAX)
494 / sizeof (emacs_limb_t))
495};
496
497static bool
498extract_big_integer (emacs_env *env, emacs_value arg, mpz_t result)
499{
500 int sign;
501 ptrdiff_t count;
502 bool success = env->extract_big_integer (env, arg, &sign, &count, NULL);
503 if (!success)
504 return false;
505 if (sign == 0)
506 {
507 mpz_set_ui (result, 0);
508 return true;
509 }
510 enum { order = -1, size = sizeof (emacs_limb_t), endian = 0, nails = 0 };
511 assert (0 < count && count <= max_count);
512 emacs_limb_t *magnitude = malloc (count * size);
513 if (magnitude == NULL)
514 {
515 memory_full (env);
516 return false;
517 }
518 success = env->extract_big_integer (env, arg, NULL, &count, magnitude);
519 assert (success);
520 mpz_import (result, count, order, size, endian, nails, magnitude);
521 free (magnitude);
522 if (sign < 0)
523 mpz_neg (result, result);
524 return true;
525}
526
527static emacs_value
528make_big_integer (emacs_env *env, const mpz_t value)
529{
530 if (mpz_sgn (value) == 0)
531 return env->make_integer (env, 0);
532 /* See
533 https://gmplib.org/manual/Integer-Import-and-Export.html#index-Export. */
534 enum
535 {
536 order = -1,
537 size = sizeof (emacs_limb_t),
538 endian = 0,
539 nails = 0,
540 numb = 8 * size - nails
541 };
542 size_t count = (mpz_sizeinbase (value, 2) + numb - 1) / numb;
543 if (max_count < count)
544 {
545 memory_full (env);
546 return NULL;
547 }
548 emacs_limb_t *magnitude = malloc (count * size);
549 if (magnitude == NULL)
550 {
551 memory_full (env);
552 return NULL;
553 }
554 size_t written;
555 mpz_export (magnitude, &written, order, size, endian, nails, value);
556 assert (written == count);
557 assert (count <= PTRDIFF_MAX);
558 emacs_value result = env->make_big_integer (env, mpz_sgn (value),
559 (ptrdiff_t) count, magnitude);
560 free (magnitude);
561 return result;
562}
563
564#ifdef CLOCK_REALTIME
565static emacs_value
566Fmod_test_nanoseconds (emacs_env *env, ptrdiff_t nargs, emacs_value *args, void *data) {
567 assert (nargs == 1);
568 struct timespec time = env->extract_time (env, args[0]);
569 mpz_t nanoseconds;
570 assert (LONG_MIN <= time.tv_sec && time.tv_sec <= LONG_MAX);
571 mpz_init_set_si (nanoseconds, time.tv_sec);
572 mpz_mul_ui (nanoseconds, nanoseconds, 1000000000);
573 assert (0 <= time.tv_nsec && time.tv_nsec <= ULONG_MAX);
574 mpz_add_ui (nanoseconds, nanoseconds, time.tv_nsec);
575 emacs_value result = make_big_integer (env, nanoseconds);
576 mpz_clear (nanoseconds);
577 return result;
578}
579#endif
580
581static emacs_value
582Fmod_test_double (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
583 void *data)
584{
585 assert (nargs == 1);
586 emacs_value arg = args[0];
587 mpz_t value;
588 mpz_init (value);
589 extract_big_integer (env, arg, value);
590 mpz_mul_ui (value, value, 2);
591 emacs_value result = make_big_integer (env, value);
592 mpz_clear (value);
593 return result;
594}
595
596static int function_data;
597static int finalizer_calls_with_correct_data;
598static int finalizer_calls_with_incorrect_data;
599
600static void
601finalizer (void *data)
602{
603 if (data == &function_data)
604 ++finalizer_calls_with_correct_data;
605 else
606 ++finalizer_calls_with_incorrect_data;
607}
608
609static emacs_value
610Fmod_test_make_function_with_finalizer (emacs_env *env, ptrdiff_t nargs,
611 emacs_value *args, void *data)
612{
613 emacs_value fun
614 = env->make_function (env, 2, 2, Fmod_test_sum, NULL, &function_data);
615 env->set_function_finalizer (env, fun, finalizer);
616 if (env->get_function_finalizer (env, fun) != finalizer)
617 signal_error (env, "Invalid finalizer");
618 return fun;
619}
620
621static emacs_value
622Fmod_test_function_finalizer_calls (emacs_env *env, ptrdiff_t nargs,
623 emacs_value *args, void *data)
624{
625 emacs_value Flist = env->intern (env, "list");
626 emacs_value list_args[]
627 = {env->make_integer (env, finalizer_calls_with_correct_data),
628 env->make_integer (env, finalizer_calls_with_incorrect_data)};
629 return env->funcall (env, Flist, 2, list_args);
630}
631
632static void
633sleep_for_half_second (void)
634{
635 /* mingw.org's MinGW has nanosleep, but MinGW64 doesn't. */
636#ifdef WINDOWSNT
637 Sleep (500);
638#else
639 const struct timespec sleep = { .tv_nsec = 500000000 };
640 if (nanosleep (&sleep, NULL) != 0)
641 perror ("nanosleep");
642#endif
643}
644
645#ifdef WINDOWSNT
646static void ALIGN_STACK
647#else
648static void *
649#endif
650write_to_pipe (void *arg)
651{
652 /* We sleep a bit to test that writing to a pipe is indeed possible
653 if no environment is active. */
654 sleep_for_half_second ();
655 FILE *stream = arg;
656 /* The string below should be identical to the one we compare with
657 in emacs-module-tests.el:module/async-pipe. */
658 if (fputs ("data from thread", stream) < 0)
659 perror ("fputs");
660 if (fclose (stream) != 0)
661 perror ("close");
662#ifndef WINDOWSNT
663 return NULL;
664#endif
665}
666
667static emacs_value
668Fmod_test_async_pipe (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
669 void *data)
670{
671 assert (nargs == 1);
672 int fd = env->open_channel (env, args[0]);
673 if (env->non_local_exit_check (env) != emacs_funcall_exit_return)
674 return NULL;
675 FILE *stream = fdopen (fd, "w");
676 if (stream == NULL)
677 {
678 signal_errno (env, "fdopen");
679 return NULL;
680 }
681#ifdef WINDOWSNT
682 uintptr_t thd = _beginthread (write_to_pipe, 0, stream);
683 int error = (thd == (uintptr_t)-1L) ? errno : 0;
684#else /* !WINDOWSNT */
685 pthread_t thread;
686 int error
687 = pthread_create (&thread, NULL, write_to_pipe, stream);
688#endif
689 if (error != 0)
690 {
691 signal_system_error (env, error, "thread create");
692 if (fclose (stream) != 0)
693 perror ("fclose");
694 return NULL;
695 }
696 return env->intern (env, "nil");
697}
698
699static emacs_value
700Fmod_test_identity (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
701 void *data)
702{
703 assert (nargs == 1);
704 return args[0];
705}
706
707static emacs_value
708Fmod_test_funcall (emacs_env *env, ptrdiff_t nargs, emacs_value *args,
709 void *data)
710{
711 assert (0 < nargs);
712 return env->funcall (env, args[0], nargs - 1, args + 1);
713}
714
715static emacs_value
716Fmod_test_make_string (emacs_env *env, ptrdiff_t nargs,
717 emacs_value *args, void *data)
718{
719 assert (nargs == 2);
720 intmax_t length_arg = env->extract_integer (env, args[0]);
721 if (env->non_local_exit_check (env) != emacs_funcall_exit_return)
722 return args[0];
723 if (length_arg < 0 || SIZE_MAX < length_arg)
724 {
725 signal_error (env, "Invalid string length");
726 return args[0];
727 }
728 size_t length = (size_t) length_arg;
729 bool multibyte = env->is_not_nil (env, args[1]);
730 char *buffer = length == 0 ? NULL : malloc (length);
731 if (buffer == NULL && length != 0)
732 {
733 memory_full (env);
734 return args[0];
735 }
736 memset (buffer, 'a', length);
737 emacs_value ret = multibyte ? env->make_string (env, buffer, length)
738 : env->make_unibyte_string (env, buffer, length);
739 free (buffer);
740 return ret;
741}
742
743/* Lisp utilities for easier readability (simple wrappers). */
744
745/* Provide FEATURE to Emacs. */
746static void
747provide (emacs_env *env, const char *feature)
748{
749 emacs_value Qfeat = env->intern (env, feature);
750 emacs_value Qprovide = env->intern (env, "provide");
751 emacs_value args[] = { Qfeat };
752
753 env->funcall (env, Qprovide, 1, args);
754}
755
756/* Bind NAME to FUN. */
757static void
758bind_function (emacs_env *env, const char *name, emacs_value Sfun)
759{
760 emacs_value Qdefalias = env->intern (env, "defalias");
761 emacs_value Qsym = env->intern (env, name);
762 emacs_value args[] = { Qsym, Sfun };
763
764 env->funcall (env, Qdefalias, 2, args);
765}
766
767/* Module init function. */
768int
769emacs_module_init (struct emacs_runtime *ert)
770{
771 /* These smoke tests don't use _Static_assert because too many
772 compilers lack support for _Static_assert. */
773 assert (0 < EMACS_LIMB_MAX);
774 assert (1000000000 <= ULONG_MAX);
775
776 /* Check that EMACS_MAJOR_VERSION is defined and an integral
777 constant. */
778 char dummy[EMACS_MAJOR_VERSION];
779 assert (27 <= sizeof dummy);
780
781 if (ert->size < sizeof *ert)
782 {
783 fprintf (stderr, "Runtime size of runtime structure (%"pT" bytes) "
784 "smaller than compile-time size (%"pZ" bytes)",
785 (T_TYPE) ert->size, (Z_TYPE) sizeof (*ert));
786 return 1;
787 }
788
789 emacs_env *env = ert->get_environment (ert);
790
791 if (env->size < sizeof *env)
792 {
793 fprintf (stderr, "Runtime size of environment structure (%"pT" bytes) "
794 "smaller than compile-time size (%"pZ" bytes)",
795 (T_TYPE) env->size, (Z_TYPE) sizeof (*env));
796 return 2;
797 }
798
799#define DEFUN(lsym, csym, amin, amax, doc, data) \
800 bind_function (env, lsym, \
801 env->make_function (env, amin, amax, csym, doc, data))
802
803 DEFUN ("mod-test-return-t", Fmod_test_return_t, 1, 1, NULL, NULL);
804 DEFUN ("mod-test-sum", Fmod_test_sum, 2, 2, "Return A + B\n\n(fn a b)",
805 (void *) (uintptr_t) 0x1234);
806 DEFUN ("mod-test-signal", Fmod_test_signal, 0, 0, NULL, NULL);
807 DEFUN ("mod-test-throw", Fmod_test_throw, 0, 0, NULL, NULL);
808 DEFUN ("mod-test-non-local-exit-funcall", Fmod_test_non_local_exit_funcall,
809 1, 1, NULL, NULL);
810 DEFUN ("mod-test-globref-make", Fmod_test_globref_make, 0, 0, NULL, NULL);
811 DEFUN ("mod-test-globref-free", Fmod_test_globref_free, 4, 4, NULL, NULL);
812 DEFUN ("mod-test-globref-invalid-free", Fmod_test_globref_invalid_free, 0, 0,
813 NULL, NULL);
814 DEFUN ("mod-test-globref-reordered", Fmod_test_globref_reordered, 0, 0, NULL,
815 NULL);
816 DEFUN ("mod-test-string-a-to-b", Fmod_test_string_a_to_b, 1, 1, NULL, NULL);
817 DEFUN ("mod-test-return-unibyte", Fmod_test_return_unibyte, 0, 0, NULL, NULL);
818 DEFUN ("mod-test-userptr-make", Fmod_test_userptr_make, 1, 1, NULL, NULL);
819 DEFUN ("mod-test-userptr-get", Fmod_test_userptr_get, 1, 1, NULL, NULL);
820 DEFUN ("mod-test-vector-fill", Fmod_test_vector_fill, 2, 2, NULL, NULL);
821 DEFUN ("mod-test-vector-eq", Fmod_test_vector_eq, 2, 2, NULL, NULL);
822 DEFUN ("mod-test-invalid-store", Fmod_test_invalid_store, 0, 0, NULL, NULL);
823 DEFUN ("mod-test-invalid-store-copy", Fmod_test_invalid_store_copy, 0, 0,
824 NULL, NULL);
825 DEFUN ("mod-test-invalid-load", Fmod_test_invalid_load, 0, 0, NULL, NULL);
826 DEFUN ("mod-test-invalid-finalizer", Fmod_test_invalid_finalizer, 0, 0,
827 NULL, NULL);
828#ifdef CLOCK_REALTIME
829 DEFUN ("mod-test-sleep-until", Fmod_test_sleep_until, 2, 2, NULL, NULL);
830#endif
831 DEFUN ("mod-test-add-nanosecond", Fmod_test_add_nanosecond, 1, 1, NULL, NULL);
832#ifdef CLOCK_REALTIME
833 DEFUN ("mod-test-nanoseconds", Fmod_test_nanoseconds, 1, 1, NULL, NULL);
834#endif
835 DEFUN ("mod-test-double", Fmod_test_double, 1, 1, NULL, NULL);
836 DEFUN ("mod-test-make-function-with-finalizer",
837 Fmod_test_make_function_with_finalizer, 0, 0, NULL, NULL);
838 DEFUN ("mod-test-function-finalizer-calls",
839 Fmod_test_function_finalizer_calls, 0, 0, NULL, NULL);
840 DEFUN ("mod-test-async-pipe", Fmod_test_async_pipe, 1, 1, NULL, NULL);
841 DEFUN ("mod-test-funcall", Fmod_test_funcall, 1, emacs_variadic_function,
842 NULL, NULL);
843 DEFUN ("mod-test-make-string", Fmod_test_make_string, 2, 2, NULL, NULL);
844
845#undef DEFUN
846
847 emacs_value constant_fn
848 = env->make_function (env, 0, 0, Fmod_test_return_t, NULL, NULL);
849 env->make_interactive (env, constant_fn, env->intern (env, "nil"));
850 bind_function (env, "mod-test-return-t-int", constant_fn);
851
852 emacs_value identity_fn
853 = env->make_function (env, 1, 1, Fmod_test_identity, NULL, NULL);
854 const char *interactive_spec = "i";
855 env->make_interactive (env, identity_fn,
856 env->make_string (env, interactive_spec,
857 strlen (interactive_spec)));
858 bind_function (env, "mod-test-identity", identity_fn);
859
860 /* We allocate lots of values to trigger bugs in the frame allocator during
861 initialization. */
862 int count = 10000; /* larger than value_frame_size in emacs-module.c */
863 for (int i = 0; i < count; ++i)
864 env->make_integer (env, i);
865
866 provide (env, "mod-test");
867 return 0;
868}
diff --git a/test/src/emacs-module-tests.el b/test/src/emacs-module-tests.el
index 4b41fc21c20..1099fd04678 100644
--- a/test/src/emacs-module-tests.el
+++ b/test/src/emacs-module-tests.el
@@ -1,6 +1,6 @@
1;;; Test GNU Emacs modules. 1;;; emacs-module-tests.el --- Test GNU Emacs modules. -*- lexical-binding: t; -*-
2 2
3;; Copyright 2015-2017 Free Software Foundation, Inc. 3;; Copyright 2015-2022 Free Software Foundation, Inc.
4 4
5;; This file is part of GNU Emacs. 5;; This file is part of GNU Emacs.
6 6
@@ -17,7 +17,25 @@
17;; You should have received a copy of the GNU General Public License 17;; You should have received a copy of the GNU General Public License
18;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ 18;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
19 19
20;;; Commentary:
21
22;; Unit tests for the dynamic module facility. See Info node `(elisp)
23;; Writing Dynamic Modules'. These tests make use of a small test
24;; module in the "emacs-module-resources" directory.
25
26;;; Code:
27;;; Prelude
28
29(require 'cl-lib)
20(require 'ert) 30(require 'ert)
31(require 'ert-x)
32(require 'help-fns)
33(require 'subr-x)
34
35;; Catch information for bug#50902.
36(when (getenv "EMACS_EMBA_CI")
37 (start-process-shell-command
38 "*timeout*" nil (format "sleep 60; kill -ABRT %d" (emacs-pid))))
21 39
22(defconst mod-test-emacs 40(defconst mod-test-emacs
23 (expand-file-name invocation-name invocation-directory) 41 (expand-file-name invocation-name invocation-directory)
@@ -25,15 +43,21 @@
25 43
26(eval-and-compile 44(eval-and-compile
27 (defconst mod-test-file 45 (defconst mod-test-file
28 (substitute-in-file-name 46 (expand-file-name "../test/src/emacs-module-resources/mod-test"
29 "$EMACS_TEST_DIRECTORY/data/emacs-module/mod-test") 47 invocation-directory)
30 "File name of the module test file.")) 48 "File name of the module test file."))
31 49
32(require 'mod-test mod-test-file) 50(require 'mod-test mod-test-file)
33 51
34;; 52(cl-defgeneric emacs-module-tests--generic (_))
35;; Basic tests. 53
36;; 54(cl-defmethod emacs-module-tests--generic ((_ module-function))
55 'module-function)
56
57(cl-defmethod emacs-module-tests--generic ((_ user-ptr))
58 'user-ptr)
59
60;;; Basic tests
37 61
38(ert-deftest mod-test-sum-test () 62(ert-deftest mod-test-sum-test ()
39 (should (= (mod-test-sum 1 2) 3)) 63 (should (= (mod-test-sum 1 2) 3))
@@ -43,8 +67,9 @@
43 (should (eq 0 67 (should (eq 0
44 (string-match 68 (string-match
45 (concat "#<module function " 69 (concat "#<module function "
46 "\\(at \\(0x\\)?[0-9a-fA-F]+\\( from .*\\)?" 70 "\\(at \\(0x\\)?[[:xdigit:]]+ "
47 "\\|Fmod_test_sum from .*\\)>") 71 "with data 0x1234\\( from .*\\)?"
72 "\\|Fmod_test_sum with data 0x1234 from .*\\)>")
48 (prin1-to-string (nth 1 descr))))) 73 (prin1-to-string (nth 1 descr)))))
49 (should (= (nth 2 descr) 3))) 74 (should (= (nth 2 descr) 3)))
50 (should-error (mod-test-sum "1" 2) :type 'wrong-type-argument) 75 (should-error (mod-test-sum "1" 2) :type 'wrong-type-argument)
@@ -57,12 +82,12 @@
57 (when (< #x1fffffff most-positive-fixnum) 82 (when (< #x1fffffff most-positive-fixnum)
58 (should (= (mod-test-sum 1 #x1fffffff) 83 (should (= (mod-test-sum 1 #x1fffffff)
59 (1+ #x1fffffff))) 84 (1+ #x1fffffff)))
60 (should (= (mod-test-sum -1 #x20000000) 85 (should (= (mod-test-sum -1 (1+ #x1fffffff))
61 #x1fffffff))) 86 #x1fffffff)))
62 (should-error (mod-test-sum 1 most-positive-fixnum) 87 (should (= (mod-test-sum 1 most-positive-fixnum)
63 :type 'overflow-error) 88 (1+ most-positive-fixnum)))
64 (should-error (mod-test-sum -1 most-negative-fixnum) 89 (should (= (mod-test-sum -1 most-negative-fixnum)
65 :type 'overflow-error)) 90 (1- most-negative-fixnum))))
66 91
67(ert-deftest mod-test-sum-docstring () 92(ert-deftest mod-test-sum-docstring ()
68 (should (string= (documentation 'mod-test-sum) "Return A + B\n\n(fn a b)"))) 93 (should (string= (documentation 'mod-test-sum) "Return A + B\n\n(fn a b)")))
@@ -73,18 +98,19 @@ This test needs to be changed whenever the implementation
73changes." 98changes."
74 (let ((func (symbol-function #'mod-test-sum))) 99 (let ((func (symbol-function #'mod-test-sum)))
75 (should (module-function-p func)) 100 (should (module-function-p func))
101 (should (functionp func))
76 (should (equal (type-of func) 'module-function)) 102 (should (equal (type-of func) 'module-function))
103 (should (eq (emacs-module-tests--generic func) 'module-function))
77 (should (string-match-p 104 (should (string-match-p
78 (rx bos "#<module function " 105 (rx bos "#<module function "
79 (or "Fmod_test_sum" 106 (or "Fmod_test_sum"
80 (and "at 0x" (+ hex-digit))) 107 (and "at 0x" (+ hex-digit)))
108 " with data 0x1234"
81 (? " from " (* nonl) "mod-test" (* nonl) ) 109 (? " from " (* nonl) "mod-test" (* nonl) )
82 ">" eos) 110 ">" eos)
83 (prin1-to-string func))))) 111 (prin1-to-string func)))))
84 112
85;; 113;;; Non-local exists (throw, signal)
86;; Non-local exists (throw, signal).
87;;
88 114
89(ert-deftest mod-test-non-local-exit-signal-test () 115(ert-deftest mod-test-non-local-exit-signal-test ()
90 (should-error (mod-test-signal)) 116 (should-error (mod-test-signal))
@@ -121,14 +147,14 @@ changes."
121 (should (equal (mod-test-non-local-exit-funcall (lambda () (throw 'tag 32))) 147 (should (equal (mod-test-non-local-exit-funcall (lambda () (throw 'tag 32)))
122 '(throw tag 32)))) 148 '(throw tag 32))))
123 149
124;; 150;;; String tests
125;; String tests.
126;;
127 151
128(defun multiply-string (s n) 152(defun multiply-string (s n)
153 "Return N copies of S concatenated together."
129 (let ((res "")) 154 (let ((res ""))
130 (dotimes (i n res) 155 (dotimes (_ n)
131 (setq res (concat res s))))) 156 (setq res (concat res s)))
157 res))
132 158
133(ert-deftest mod-test-globref-make-test () 159(ert-deftest mod-test-globref-make-test ()
134 (let ((mod-str (mod-test-globref-make)) 160 (let ((mod-str (mod-test-globref-make))
@@ -136,12 +162,16 @@ changes."
136 (garbage-collect) ;; XXX: not enough to really test but it's something.. 162 (garbage-collect) ;; XXX: not enough to really test but it's something..
137 (should (string= ref-str mod-str)))) 163 (should (string= ref-str mod-str))))
138 164
165(ert-deftest mod-test-globref-free-test ()
166 (should (eq (mod-test-globref-free 1 'a "test" 'b) 'ok)))
167
168(ert-deftest mod-test-globref-reordered ()
169 (should (equal (mod-test-globref-reordered) '(t t t nil))))
170
139(ert-deftest mod-test-string-a-to-b-test () 171(ert-deftest mod-test-string-a-to-b-test ()
140 (should (string= (mod-test-string-a-to-b "aaa") "bbb"))) 172 (should (string= (mod-test-string-a-to-b "aaa") "bbb")))
141 173
142;; 174;;; User-pointer tests
143;; User-pointer tests.
144;;
145 175
146(ert-deftest mod-test-userptr-fun-test () 176(ert-deftest mod-test-userptr-fun-test ()
147 (let* ((n 42) 177 (let* ((n 42)
@@ -149,14 +179,13 @@ changes."
149 (r (mod-test-userptr-get v))) 179 (r (mod-test-userptr-get v)))
150 180
151 (should (eq (type-of v) 'user-ptr)) 181 (should (eq (type-of v) 'user-ptr))
182 (should (eq (emacs-module-tests--generic v) 'user-ptr))
152 (should (integerp r)) 183 (should (integerp r))
153 (should (= r n)))) 184 (should (= r n))))
154 185
155;; TODO: try to test finalizer 186;; TODO: try to test finalizer
156 187
157;; 188;;; Vector tests
158;; Vector tests.
159;;
160 189
161(ert-deftest mod-test-vector-test () 190(ert-deftest mod-test-vector-test ()
162 (dolist (s '(2 10 100 1000)) 191 (dolist (s '(2 10 100 1000))
@@ -182,20 +211,6 @@ changes."
182 (should (equal (help-function-arglist #'mod-test-sum) 211 (should (equal (help-function-arglist #'mod-test-sum)
183 '(arg1 arg2)))) 212 '(arg1 arg2))))
184 213
185(defmacro module--with-temp-directory (name &rest body)
186 "Bind NAME to the name of a temporary directory and evaluate BODY.
187NAME must be a symbol. Delete the temporary directory after BODY
188exits normally or non-locally. NAME will be bound to the
189directory name (not the directory file name) of the temporary
190directory."
191 (declare (indent 1))
192 (cl-check-type name symbol)
193 `(let ((,name (file-name-as-directory
194 (make-temp-file "emacs-module-test" :directory))))
195 (unwind-protect
196 (progn ,@body)
197 (delete-directory ,name :recursive))))
198
199(defmacro module--test-assertion (pattern &rest body) 214(defmacro module--test-assertion (pattern &rest body)
200 "Test that PATTERN matches the assertion triggered by BODY. 215 "Test that PATTERN matches the assertion triggered by BODY.
201Run Emacs as a subprocess, load the test module `mod-test-file', 216Run Emacs as a subprocess, load the test module `mod-test-file',
@@ -204,7 +219,7 @@ assertion message that matches PATTERN. PATTERN is evaluated and
204must evaluate to a regular expression string." 219must evaluate to a regular expression string."
205 (declare (indent 1)) 220 (declare (indent 1))
206 ;; To contain any core dumps. 221 ;; To contain any core dumps.
207 `(module--with-temp-directory tempdir 222 `(ert-with-temp-directory tempdir
208 (with-temp-buffer 223 (with-temp-buffer
209 (let* ((default-directory tempdir) 224 (let* ((default-directory tempdir)
210 (status (call-process mod-test-emacs nil t nil 225 (status (call-process mod-test-emacs nil t nil
@@ -231,10 +246,12 @@ must evaluate to a regular expression string."
231 (point) (point-max)))))))) 246 (point) (point-max))))))))
232 247
233(ert-deftest module--test-assertions--load-non-live-object () 248(ert-deftest module--test-assertions--load-non-live-object ()
234 "Check that -module-assertions verify that non-live objects 249 "Check that -module-assertions verify that non-live objects aren't accessed."
235aren’t accessed." 250 :tags (if (getenv "EMACS_EMBA_CI") '(:unstable))
236 (skip-unless (file-executable-p mod-test-emacs)) 251 (skip-unless (or (file-executable-p mod-test-emacs)
237 ;; This doesn’t yet cause undefined behavior. 252 (and (eq system-type 'windows-nt)
253 (file-executable-p (concat mod-test-emacs ".exe")))))
254 ;; This doesn't yet cause undefined behavior.
238 (should (eq (mod-test-invalid-store) 123)) 255 (should (eq (mod-test-invalid-store) 123))
239 (module--test-assertion (rx "Emacs value not found in " 256 (module--test-assertion (rx "Emacs value not found in "
240 (+ digit) " values of " 257 (+ digit) " values of "
@@ -244,12 +261,322 @@ aren’t accessed."
244 (mod-test-invalid-store) 261 (mod-test-invalid-store)
245 (mod-test-invalid-load))) 262 (mod-test-invalid-load)))
246 263
264(ert-deftest module--test-assertions--load-non-live-object-with-global-copy ()
265 "Check that -module-assertions verify that non-live objects aren't accessed.
266This differs from `module--test-assertions-load-non-live-object'
267in that it stows away a global reference. The module assertions
268should nevertheless detect the invalid load."
269 :tags (if (getenv "EMACS_EMBA_CI") '(:unstable))
270 (skip-unless (or (file-executable-p mod-test-emacs)
271 (and (eq system-type 'windows-nt)
272 (file-executable-p (concat mod-test-emacs ".exe")))))
273 ;; This doesn't yet cause undefined behavior.
274 (should (eq (mod-test-invalid-store-copy) 123))
275 (module--test-assertion (rx "Emacs value not found in "
276 (+ digit) " values of "
277 (+ digit) " environments\n")
278 ;; Storing and reloading a local value causes undefined behavior,
279 ;; which should be detected by the module assertions.
280 (mod-test-invalid-store-copy)
281 (mod-test-invalid-load)))
282
247(ert-deftest module--test-assertions--call-emacs-from-gc () 283(ert-deftest module--test-assertions--call-emacs-from-gc ()
248 "Check that -module-assertions prevents calling Emacs functions 284 "Check that -module-assertions prevents calling Emacs functions
249during garbage collection." 285during garbage collection."
250 (skip-unless (file-executable-p mod-test-emacs)) 286 :tags (if (getenv "EMACS_EMBA_CI") '(:unstable))
287 (skip-unless (or (file-executable-p mod-test-emacs)
288 (and (eq system-type 'windows-nt)
289 (file-executable-p (concat mod-test-emacs ".exe")))))
251 (module--test-assertion 290 (module--test-assertion
252 (rx "Module function called during garbage collection\n") 291 (rx "Module function called during garbage collection\n")
253 (mod-test-invalid-finalizer))) 292 (mod-test-invalid-finalizer)
293 (garbage-collect)))
294
295(ert-deftest module--test-assertions--globref-invalid-free ()
296 "Check that -module-assertions detects invalid freeing of a
297local reference."
298 :tags (if (getenv "EMACS_EMBA_CI") '(:unstable))
299 (skip-unless (or (file-executable-p mod-test-emacs)
300 (and (eq system-type 'windows-nt)
301 (file-executable-p (concat mod-test-emacs ".exe")))))
302 (module--test-assertion
303 (rx "Global value was not found in list of " (+ digit) " globals")
304 (mod-test-globref-invalid-free)
305 (garbage-collect)))
306
307(ert-deftest module/describe-function-1 ()
308 "Check that Bug#30163 is fixed."
309 (with-temp-buffer
310 (let ((standard-output (current-buffer))
311 (text-quoting-style 'grave)
312 (fill-column 200)) ; prevent line breaks when filling
313 (describe-function-1 #'mod-test-sum)
314 (goto-char (point-min))
315 (while (re-search-forward "`[^']*/src/emacs-module-resources/" nil t)
316 (replace-match "`src/emacs-module-resources/"))
317 (should (equal
318 (buffer-substring-no-properties 1 (point-max))
319 (format "a module function in `src/emacs-module-resources/mod-test%s'.
320
321(mod-test-sum a b)
322
323Return A + B
324
325"
326 module-file-suffix))))))
327
328(ert-deftest module/load-history ()
329 "Check that Bug#30164 is fixed."
330 (load mod-test-file)
331 (cl-destructuring-bind (file &rest entries) (car load-history)
332 (should (equal (file-name-sans-extension file) mod-test-file))
333 (should (member '(provide . mod-test) entries))
334 (should (member '(defun . mod-test-sum) entries))))
335
336(ert-deftest mod-test-sleep-until ()
337 "Check that `mod-test-sleep-until' either returns normally or quits.
338Interactively, you can try hitting \\[keyboard-quit] to quit."
339 (skip-unless (fboundp 'mod-test-sleep-until))
340 (dolist (arg '(nil t))
341 ;; Guard against some caller setting `inhibit-quit'.
342 (with-local-quit
343 (condition-case nil
344 (should (eq (with-local-quit
345 ;; Because `inhibit-quit' is nil here, the next
346 ;; form either quits or returns `finished'.
347 (mod-test-sleep-until
348 ;; Interactively, run for 5 seconds to give the
349 ;; user time to quit. In batch mode, run only
350 ;; briefly since the user can't quit.
351 (time-add nil (if noninteractive 0.1 5))
352 ;; should_quit or process_input
353 arg))
354 'finished))
355 (quit)))))
356
357(ert-deftest mod-test-add-nanosecond/valid ()
358 (dolist (input (list
359 ;; Some realistic examples.
360 (current-time) (time-to-seconds)
361 (encode-time 12 34 5 6 7 2019 t)
362 ;; Various legacy timestamp forms.
363 '(123 456) '(123 456 789) '(123 456 789 6000)
364 ;; Corner case: this will result in a nanosecond
365 ;; value of 1000000000 after addition. The module
366 ;; code should handle this correctly.
367 '(123 65535 999999 999000)
368 ;; Seconds since the epoch.
369 123 123.45
370 ;; New (TICKS . HZ) format.
371 '(123456789 . 1000000000)))
372 (ert-info ((format "input: %s" input))
373 (let ((result (mod-test-add-nanosecond input))
374 (desired-result
375 (let ((hz 1000000000))
376 (time-add (time-convert input hz) (cons 1 hz)))))
377 (should (consp result))
378 (should (integerp (car result)))
379 (should (integerp (cdr result)))
380 (should (cl-plusp (cdr result)))
381 (should (time-equal-p result desired-result))))))
382
383(ert-deftest mod-test-add-nanosecond/nil ()
384 (should (<= (float-time (mod-test-add-nanosecond nil))
385 (+ (float-time) 1e-9))))
386
387(ert-deftest mod-test-add-nanosecond/invalid ()
388 (dolist (input '(1.0e+INF 1.0e-INF 0.0e+NaN (123) (123.45 6 7) "foo" [1 2]))
389 (ert-info ((format "input: %s" input))
390 (should-error (mod-test-add-nanosecond input)))))
391
392(ert-deftest mod-test-nanoseconds ()
393 "Test truncation when converting to `struct timespec'."
394 (skip-unless (fboundp 'mod-test-nanoseconds))
395 (dolist (test-case '((0 . 0)
396 (-1 . -1000000000)
397 ((1 . 1000000000) . 1)
398 ((-1 . 1000000000) . -1)
399 ((1 . 1000000000000) . 0)
400 ((-1 . 1000000000000) . -1)
401 ((999 . 1000000000000) . 0)
402 ((-999 . 1000000000000) . -1)
403 ((1000 . 1000000000000) . 1)
404 ((-1000 . 1000000000000) . -1)
405 ((0 0 0 1) . 0)
406 ((0 0 0 -1) . -1)))
407 (let ((input (car test-case))
408 (expected (cdr test-case)))
409 (ert-info ((format "input: %S, expected result: %d" input expected))
410 (should (= (mod-test-nanoseconds input) expected))))))
411
412(ert-deftest mod-test-double ()
413 (skip-unless (fboundp 'mod-test-double))
414 (dolist (input (list 0 1 2 -1 42 12345678901234567890
415 most-positive-fixnum (1+ most-positive-fixnum)
416 most-negative-fixnum (1- most-negative-fixnum)))
417 (ert-info ((format "input: %d" input))
418 (should (= (mod-test-double input) (* 2 input))))))
419
420(ert-deftest module-darwin-secondary-suffix ()
421 "Check that on Darwin, both .so and .dylib suffixes work.
422See Bug#36226."
423 (skip-unless (eq system-type 'darwin))
424 (should (member ".dylib" load-suffixes))
425 (should (member ".so" load-suffixes))
426 ;; Preserve the old `load-history'. This is needed for some of the
427 ;; other unit tests that indirectly rely on `load-history'.
428 (let ((load-history load-history)
429 (dylib (concat mod-test-file ".dylib"))
430 (so (concat mod-test-file ".so")))
431 (should (file-regular-p dylib))
432 (should-not (file-exists-p so))
433 (add-name-to-file dylib so)
434 (unwind-protect
435 (load so nil nil :nosuffix :must-suffix)
436 (delete-file so))))
437
438(ert-deftest module/function-finalizer ()
439 "Test that module function finalizers are properly called."
440 ;; We create and leak a couple of module functions with attached
441 ;; finalizer. Creating only one function risks spilling it to the
442 ;; stack, where it wouldn't be garbage-collected. However, with one
443 ;; hundred functions, there should be at least one that's
444 ;; unreachable.
445 (dotimes (_ 100)
446 (mod-test-make-function-with-finalizer))
447 (cl-destructuring-bind (valid-before invalid-before)
448 (mod-test-function-finalizer-calls)
449 (should (zerop invalid-before))
450 (garbage-collect)
451 (cl-destructuring-bind (valid-after invalid-after)
452 (mod-test-function-finalizer-calls)
453 (should (zerop invalid-after))
454 ;; We don't require exactly 100 invocations of the finalizer,
455 ;; but at least one.
456 (should (> valid-after valid-before)))))
457
458(ert-deftest module/async-pipe ()
459 "Check that writing data from another thread works."
460 (skip-unless (not (eq system-type 'windows-nt))) ; FIXME!
461 (with-temp-buffer
462 (let ((process (make-pipe-process :name "module/async-pipe"
463 :buffer (current-buffer)
464 :coding 'utf-8-unix
465 :noquery t)))
466 (unwind-protect
467 (progn
468 (mod-test-async-pipe process)
469 (should (accept-process-output process 1))
470 ;; The string below must be identical to what
471 ;; mod-test.c:write_to_pipe produces.
472 (should (equal (buffer-string) "data from thread")))
473 (delete-process process)))))
474
475(ert-deftest module/interactive/return-t ()
476 (should (functionp (symbol-function #'mod-test-return-t)))
477 (should (module-function-p (symbol-function #'mod-test-return-t)))
478 (should-not (commandp #'mod-test-return-t))
479 (should-not (commandp (symbol-function #'mod-test-return-t)))
480 (should-not (interactive-form #'mod-test-return-t))
481 (should-not (interactive-form (symbol-function #'mod-test-return-t)))
482 (should-error (call-interactively #'mod-test-return-t)
483 :type 'wrong-type-argument))
484
485(ert-deftest module/interactive/return-t-int ()
486 (should (functionp (symbol-function #'mod-test-return-t-int)))
487 (should (module-function-p (symbol-function #'mod-test-return-t-int)))
488 (should (commandp #'mod-test-return-t-int))
489 (should (commandp (symbol-function #'mod-test-return-t-int)))
490 (should (equal (interactive-form #'mod-test-return-t-int) '(interactive)))
491 (should (equal (interactive-form (symbol-function #'mod-test-return-t-int))
492 '(interactive)))
493 (should (eq (mod-test-return-t-int) t))
494 (should (eq (call-interactively #'mod-test-return-t-int) t)))
495
496(ert-deftest module/interactive/identity ()
497 (should (functionp (symbol-function #'mod-test-identity)))
498 (should (module-function-p (symbol-function #'mod-test-identity)))
499 (should (commandp #'mod-test-identity))
500 (should (commandp (symbol-function #'mod-test-identity)))
501 (should (equal (interactive-form #'mod-test-identity) '(interactive "i")))
502 (should (equal (interactive-form (symbol-function #'mod-test-identity))
503 '(interactive "i")))
504 (should (eq (mod-test-identity 123) 123))
505 (should-not (call-interactively #'mod-test-identity)))
506
507(ert-deftest module/unibyte ()
508 (let ((result (mod-test-return-unibyte)))
509 (should (stringp result))
510 (should (not (multibyte-string-p (mod-test-return-unibyte))))
511 (should (equal result "foo\x00zot"))))
512
513(cl-defstruct (emacs-module-tests--variable
514 (:constructor nil)
515 (:constructor emacs-module-tests--make-variable
516 (name
517 &aux
518 (mutex (make-mutex name))
519 (condvar (make-condition-variable mutex name))))
520 (:copier nil))
521 "A variable that's protected by a mutex."
522 value
523 (mutex nil :read-only t :type mutex)
524 (condvar nil :read-only t :type condition-variable))
525
526(defun emacs-module-tests--wait-for-variable (variable desired)
527 (with-mutex (emacs-module-tests--variable-mutex variable)
528 (while (not (eq (emacs-module-tests--variable-value variable) desired))
529 (condition-wait (emacs-module-tests--variable-condvar variable)))))
530
531(defun emacs-module-tests--change-variable (variable new)
532 (with-mutex (emacs-module-tests--variable-mutex variable)
533 (setf (emacs-module-tests--variable-value variable) new)
534 (condition-notify (emacs-module-tests--variable-condvar variable) :all)))
535
536(ert-deftest emacs-module-tests/interleaved-threads ()
537 (let* ((state-1 (emacs-module-tests--make-variable "1"))
538 (state-2 (emacs-module-tests--make-variable "2"))
539 (thread-1
540 (make-thread
541 (lambda ()
542 (emacs-module-tests--change-variable state-1 'before-module)
543 (mod-test-funcall
544 (lambda ()
545 (emacs-module-tests--change-variable state-1 'in-module)
546 (emacs-module-tests--wait-for-variable state-2 'in-module)))
547 (emacs-module-tests--change-variable state-1 'after-module))
548 "thread 1"))
549 (thread-2
550 (make-thread
551 (lambda ()
552 (emacs-module-tests--change-variable state-2 'before-module)
553 (emacs-module-tests--wait-for-variable state-1 'in-module)
554 (mod-test-funcall
555 (lambda ()
556 (emacs-module-tests--change-variable state-2 'in-module)
557 (emacs-module-tests--wait-for-variable state-1 'after-module)))
558 (emacs-module-tests--change-variable state-2 'after-module))
559 "thread 2")))
560 (thread-join thread-1)
561 (thread-join thread-2)))
562
563(ert-deftest mod-test-make-string/empty ()
564 (dolist (multibyte '(nil t))
565 (ert-info ((format "Multibyte: %s" multibyte))
566 (let ((got (mod-test-make-string 0 multibyte)))
567 (should (stringp got))
568 (should (string-empty-p got))
569 (should (eq (multibyte-string-p got) multibyte))))))
570
571(ert-deftest mod-test-make-string/nonempty ()
572 (dolist (multibyte '(nil t))
573 (ert-info ((format "Multibyte: %s" multibyte))
574 (let ((first (mod-test-make-string 1 multibyte))
575 (second (mod-test-make-string 1 multibyte)))
576 (should (stringp first))
577 (should (eql (length first) 1))
578 (should (eq (multibyte-string-p first) multibyte))
579 (should (string-equal first second))
580 (should-not (eq first second))))))
254 581
255;;; emacs-module-tests.el ends here 582;;; emacs-module-tests.el ends here
diff --git a/test/src/emacs-tests.el b/test/src/emacs-tests.el
new file mode 100644
index 00000000000..52888135c12
--- /dev/null
+++ b/test/src/emacs-tests.el
@@ -0,0 +1,249 @@
1;;; emacs-tests.el --- unit tests for emacs.c -*- lexical-binding: t; -*-
2
3;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
4
5;; This file is part of GNU Emacs.
6
7;; GNU Emacs is free software: you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published
9;; by the Free Software Foundation, either version 3 of the License,
10;; or (at your option) any later version.
11
12;; GNU Emacs is distributed in the hope that it will be useful, but
13;; WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15;; General Public License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
19
20;;; Commentary:
21
22;; Unit tests for src/emacs.c.
23
24;;; Code:
25
26(require 'cl-lib)
27(require 'ert)
28(require 'ert-x) ; ert-with-temp-file
29(require 'rx)
30(require 'subr-x)
31
32(defconst emacs-tests--lib-src
33 (substitute-in-file-name "$EMACS_TEST_DIRECTORY/../lib-src/")
34 "Location of the lib-src directory.")
35
36(ert-deftest emacs-tests/seccomp/absent-file ()
37 (skip-unless (string-match-p (rx bow "SECCOMP" eow)
38 system-configuration-features))
39 (let ((emacs
40 (expand-file-name invocation-name invocation-directory))
41 (process-environment nil))
42 (skip-unless (file-executable-p emacs))
43 (should-not (file-exists-p "/does-not-exist.bpf"))
44 (should-not
45 (eql (call-process emacs nil nil nil
46 "--quick" "--batch"
47 "--seccomp=/does-not-exist.bpf")
48 0))))
49
50(ert-deftest emacs-tests/seccomp/empty-file ()
51 (skip-unless (string-match-p (rx bow "SECCOMP" eow)
52 system-configuration-features))
53 (let ((emacs
54 (expand-file-name invocation-name invocation-directory))
55 (process-environment nil))
56 (skip-unless (file-executable-p emacs))
57 (ert-with-temp-file filter
58 :prefix "seccomp-invalid-" :suffix ".bpf"
59 ;; The --seccomp option is processed early, without filename
60 ;; handlers. Therefore remote or quoted filenames wouldn't
61 ;; work.
62 (should-not (file-remote-p filter))
63 (cl-callf file-name-unquote filter)
64 ;; According to the Seccomp man page, a filter must have at
65 ;; least one element, so Emacs should reject an empty file.
66 (should-not
67 (eql (call-process emacs nil nil nil
68 "--quick" "--batch"
69 (concat "--seccomp=" filter))
70 0)))))
71
72(ert-deftest emacs-tests/seccomp/file-too-large ()
73 (skip-unless (string-match-p (rx bow "SECCOMP" eow)
74 system-configuration-features))
75 (let ((emacs
76 (expand-file-name invocation-name invocation-directory))
77 (process-environment nil)
78 ;; This value should be correct on all supported systems.
79 (ushort-max #xFFFF)
80 ;; Either 8 or 16, but 16 should be large enough in all cases.
81 (filter-size 16))
82 (skip-unless (file-executable-p emacs))
83 (ert-with-temp-file filter
84 :prefix "seccomp-too-large-" :suffix ".bpf"
85 :text (make-string (* (1+ ushort-max) filter-size) ?a)
86 ;; The --seccomp option is processed early, without filename
87 ;; handlers. Therefore remote or quoted filenames wouldn't
88 ;; work.
89 (should-not (file-remote-p filter))
90 (cl-callf file-name-unquote filter)
91 ;; The filter count must fit into an `unsigned short'. A bigger
92 ;; file should be rejected.
93 (should-not
94 (eql (call-process emacs nil nil nil
95 "--quick" "--batch"
96 (concat "--seccomp=" filter))
97 0)))))
98
99(ert-deftest emacs-tests/seccomp/invalid-file-size ()
100 (skip-unless (string-match-p (rx bow "SECCOMP" eow)
101 system-configuration-features))
102 (let ((emacs
103 (expand-file-name invocation-name invocation-directory))
104 (process-environment nil))
105 (skip-unless (file-executable-p emacs))
106 (ert-with-temp-file filter
107 :prefix "seccomp-invalid-" :suffix ".bpf" :text "123456"
108 ;; The --seccomp option is processed early, without filename
109 ;; handlers. Therefore remote or quoted filenames wouldn't
110 ;; work.
111 (should-not (file-remote-p filter))
112 (cl-callf file-name-unquote filter)
113 ;; The Seccomp filter file must have a file size that's a
114 ;; multiple of the size of struct sock_filter, which is 8 or 16,
115 ;; but never 6.
116 (should-not
117 (eql (call-process emacs nil nil nil
118 "--quick" "--batch"
119 (concat "--seccomp=" filter))
120 0)))))
121
122(ert-deftest emacs-tests/seccomp/allows-stdout ()
123 (skip-unless (string-match-p (rx bow "SECCOMP" eow)
124 system-configuration-features))
125 (let ((emacs
126 (expand-file-name invocation-name invocation-directory))
127 (filter (expand-file-name "seccomp-filter.bpf"
128 emacs-tests--lib-src))
129 (process-environment nil))
130 (skip-unless (file-executable-p emacs))
131 (skip-unless (file-readable-p filter))
132 ;; The --seccomp option is processed early, without filename
133 ;; handlers. Therefore remote or quoted filenames wouldn't work.
134 (should-not (file-remote-p filter))
135 (cl-callf file-name-unquote filter)
136 (with-temp-buffer
137 (let ((start-time (current-time))
138 (status (call-process
139 emacs nil t nil
140 "--quick" "--batch"
141 (concat "--seccomp=" filter)
142 (format "--eval=%S" '(message "Hi"))))
143 (end-time (current-time)))
144 (ert-info ((emacs-tests--seccomp-debug start-time end-time))
145 (should (eql status 0)))
146 (should (equal (string-trim (buffer-string)) "Hi"))))))
147
148(ert-deftest emacs-tests/seccomp/forbids-subprocess ()
149 (skip-unless (string-match-p (rx bow "SECCOMP" eow)
150 system-configuration-features))
151 (let ((emacs
152 (expand-file-name invocation-name invocation-directory))
153 (filter (expand-file-name "seccomp-filter.bpf"
154 emacs-tests--lib-src))
155 (process-environment nil))
156 (skip-unless (file-executable-p emacs))
157 (skip-unless (file-readable-p filter))
158 ;; The --seccomp option is processed early, without filename
159 ;; handlers. Therefore remote or quoted filenames wouldn't work.
160 (should-not (file-remote-p filter))
161 (cl-callf file-name-unquote filter)
162 (with-temp-buffer
163 (let ((start-time (current-time))
164 (status
165 (call-process
166 emacs nil t nil
167 "--quick" "--batch"
168 (concat "--seccomp=" filter)
169 (format "--eval=%S" `(call-process ,emacs nil nil nil
170 "--version"))))
171 (end-time (current-time)))
172 (ert-info ((emacs-tests--seccomp-debug start-time end-time))
173 (should-not (eql status 0)))))))
174
175(ert-deftest emacs-tests/bwrap/allows-stdout ()
176 (let ((bash (executable-find "bash"))
177 (bwrap (executable-find "bwrap"))
178 (emacs
179 (expand-file-name invocation-name invocation-directory))
180 (filter (expand-file-name "seccomp-filter-exec.bpf"
181 emacs-tests--lib-src))
182 (process-environment nil))
183 (skip-unless bash)
184 (skip-unless bwrap)
185 (skip-unless (file-executable-p emacs))
186 (skip-unless (file-readable-p filter))
187 (should-not (file-remote-p bwrap))
188 (should-not (file-remote-p emacs))
189 (should-not (file-remote-p filter))
190 (with-temp-buffer
191 (let* ((command
192 (concat
193 (mapconcat #'shell-quote-argument
194 `(,(file-name-unquote bwrap)
195 "--ro-bind" "/" "/"
196 "--seccomp" "20"
197 "--"
198 ,(file-name-unquote emacs)
199 "--quick" "--batch"
200 ,(format "--eval=%S" '(message "Hi")))
201 " ")
202 " 20< "
203 (shell-quote-argument (file-name-unquote filter))))
204 (start-time (current-time))
205 (status (call-process bash nil t nil "-c" command))
206 (end-time (current-time)))
207 (ert-info ((emacs-tests--seccomp-debug start-time end-time))
208 (should (eql status 0)))
209 (should (equal (string-trim (buffer-string)) "Hi"))))))
210
211(defun emacs-tests--seccomp-debug (start-time end-time)
212 "Return potentially useful debugging information for Seccomp.
213Assume that the current buffer contains subprocess output for the
214failing process. START-TIME and END-TIME are time values between
215which the process was running."
216 ;; Add a bit of slack for the timestamps.
217 (cl-callf time-subtract start-time 5)
218 (cl-callf time-add end-time 5)
219 (with-output-to-string
220 (princ "Process output:")
221 (terpri)
222 (princ (buffer-substring-no-properties (point-min) (point-max)))
223 ;; Search audit logs for Seccomp messages.
224 (when-let ((ausearch (executable-find "ausearch")))
225 (terpri)
226 (princ "Potentially relevant Seccomp audit events:")
227 (terpri)
228 (let ((process-environment '("LC_TIME=C")))
229 (call-process ausearch nil standard-output nil
230 "--message" "SECCOMP"
231 "--start"
232 (format-time-string "%D" start-time)
233 (format-time-string "%T" start-time)
234 "--end"
235 (format-time-string "%D" end-time)
236 (format-time-string "%T" end-time)
237 "--interpret")))
238 ;; Print coredump information if available.
239 (when-let ((coredumpctl (executable-find "coredumpctl")))
240 (terpri)
241 (princ "Potentially useful coredump information:")
242 (terpri)
243 (call-process coredumpctl nil standard-output nil
244 "info"
245 "--since" (format-time-string "%F %T" start-time)
246 "--until" (format-time-string "%F %T" end-time)
247 "--no-pager"))))
248
249;;; emacs-tests.el ends here
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
diff --git a/test/src/fileio-tests.el b/test/src/fileio-tests.el
index 01c280d2752..08582c8a862 100644
--- a/test/src/fileio-tests.el
+++ b/test/src/fileio-tests.el
@@ -1,6 +1,6 @@
1;;; unit tests for src/fileio.c -*- lexical-binding: t; -*- 1;;; fileio-tests.el --- unit tests for src/fileio.c -*- lexical-binding: t; -*-
2 2
3;; Copyright 2017 Free Software Foundation, Inc. 3;; Copyright 2017-2022 Free Software Foundation, Inc.
4 4
5;; This file is part of GNU Emacs. 5;; This file is part of GNU Emacs.
6 6
@@ -17,6 +17,8 @@
17;; You should have received a copy of the GNU General Public License 17;; You should have received a copy of the GNU General Public License
18;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. 18;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
19 19
20;;; Code:
21
20(require 'ert) 22(require 'ert)
21 23
22(defun try-link (target link) 24(defun try-link (target link)
@@ -95,3 +97,124 @@ Also check that an encoding error can appear in a symlink."
95 (should (equal (file-name-as-directory "d:/abc/") "d:/abc/")) 97 (should (equal (file-name-as-directory "d:/abc/") "d:/abc/"))
96 (should (equal (file-name-as-directory "D:\\abc/") "d:/abc/")) 98 (should (equal (file-name-as-directory "D:\\abc/") "d:/abc/"))
97 (should (equal (file-name-as-directory "D:/abc//") "d:/abc//"))) 99 (should (equal (file-name-as-directory "D:/abc//") "d:/abc//")))
100
101(ert-deftest fileio-tests--relative-HOME ()
102 "Test that `expand-file-name' works even when HOME is relative."
103 (let ((process-environment (copy-sequence process-environment)))
104 (setenv "HOME" "a/b/c")
105 (should (equal (expand-file-name "~/foo")
106 (expand-file-name "a/b/c/foo")))
107 (when (memq system-type '(ms-dos windows-nt))
108 ;; Test expansion of drive-relative file names.
109 (setenv "HOME" "x:foo")
110 (should (equal (expand-file-name "~/bar") "x:/foo/bar")))))
111
112(ert-deftest fileio-tests--insert-file-interrupt ()
113 (let ((text "-*- coding: binary -*-\n\xc3\xc3help")
114 f)
115 (unwind-protect
116 (progn
117 (setq f (make-temp-file "ftifi"))
118 (write-region text nil f nil 'silent)
119 (with-temp-buffer
120 (catch 'toto
121 (let ((set-auto-coding-function (lambda (&rest _) (throw 'toto nil))))
122 (insert-file-contents f)))
123 (goto-char (point-min))
124 (unless (eobp)
125 (forward-line 1)
126 (let ((c1 (char-after)))
127 (forward-char 1)
128 (should (equal c1 (char-before)))
129 (should (equal c1 (char-after)))))))
130 (if f (delete-file f)))))
131
132(ert-deftest fileio-tests--relative-default-directory ()
133 "Test `expand-file-name' when `default-directory' is relative."
134 (let ((default-directory "some/relative/name"))
135 (should (file-name-absolute-p (expand-file-name "foo"))))
136 (let* ((default-directory "~foo")
137 (name (expand-file-name "bar")))
138 (should (and (file-name-absolute-p name)
139 (not (eq (aref name 0) ?~))))))
140
141(ert-deftest fileio-tests--expand-file-name-null-bytes ()
142 "Test that `expand-file-name' checks for null bytes in filenames."
143 (should-error (expand-file-name (concat "file" (char-to-string ?\0) ".txt"))
144 :type 'wrong-type-argument)
145 (should-error (expand-file-name "file.txt" (concat "dir" (char-to-string ?\0)))
146 :type 'wrong-type-argument)
147 (let ((default-directory (concat "dir" (char-to-string ?\0))))
148 (should-error (expand-file-name "file.txt") :type 'wrong-type-argument)))
149
150(ert-deftest fileio-tests--file-name-absolute-p ()
151 "Test `file-name-absolute-p'."
152 (dolist (suffix '("" "/" "//" "/foo" "/foo/" "/foo//" "/foo/bar"))
153 (unless (string-equal suffix "")
154 (should (file-name-absolute-p suffix)))
155 (should (file-name-absolute-p (concat "~" suffix)))
156 (when (user-full-name user-login-name)
157 (should (file-name-absolute-p (concat "~" user-login-name suffix))))
158 (unless (user-full-name "nosuchuser")
159 (should (not (file-name-absolute-p (concat "~nosuchuser" suffix)))))))
160
161(ert-deftest fileio-tests--circular-after-insert-file-functions ()
162 "Test `after-insert-file-functions' as a circular list."
163 (let ((f (make-temp-file "fileio"))
164 (after-insert-file-functions (list 'identity)))
165 (setcdr after-insert-file-functions after-insert-file-functions)
166 (write-region "hello\n" nil f nil 'silent)
167 (should-error (insert-file-contents f) :type 'circular-list)
168 (delete-file f)))
169
170(ert-deftest fileio-tests/null-character ()
171 (should-error (file-exists-p "/foo\0bar")
172 :type 'wrong-type-argument))
173
174(ert-deftest fileio-tests/file-name-concat ()
175 (should (equal (file-name-concat "foo" "bar") "foo/bar"))
176 (should (equal (file-name-concat "foo" "bar") "foo/bar"))
177 (should (equal (file-name-concat "foo" "bar" "zot") "foo/bar/zot"))
178 (should (equal (file-name-concat "foo/" "bar") "foo/bar"))
179 (should (equal (file-name-concat "foo//" "bar") "foo//bar"))
180 (should (equal (file-name-concat "foo/" "bar/" "zot") "foo/bar/zot"))
181 (should (equal (file-name-concat "fóo" "bar") "fóo/bar"))
182 (should (equal (file-name-concat "foo" "bár") "foo/bár"))
183 (should (equal (file-name-concat "fóo" "bár") "fóo/bár"))
184 (let ((string (make-string 5 ?a)))
185 (should (not (multibyte-string-p string)))
186 (aset string 2 255)
187 (should (not (multibyte-string-p string)))
188 (should (equal (file-name-concat "fóo" string) "fóo/aa\377aa")))
189 (should (equal (file-name-concat "foo") "foo"))
190 (should (equal (file-name-concat "foo/") "foo/"))
191 (should (equal (file-name-concat "foo" "") "foo"))
192 (should (equal (file-name-concat "foo" "" "" "" nil) "foo"))
193 (should (equal (file-name-concat "" "bar") "bar"))
194 (should (equal (file-name-concat "" "") "")))
195
196(ert-deftest fileio-tests--non-regular-insert ()
197 (skip-unless (file-exists-p "/dev/urandom"))
198 (with-temp-buffer
199 (set-buffer-multibyte nil)
200 (should-error (insert-file-contents "/dev/urandom" nil 5 10))
201 (insert-file-contents "/dev/urandom" nil nil 10)
202 (should (= (buffer-size) 10))))
203
204(defun fileio-tests--identity-expand-handler (_ file &rest _)
205 file)
206(put 'fileio-tests--identity-expand-handler 'operations '(expand-file-name))
207
208(ert-deftest fileio--file-name-case-insensitive-p ()
209 ;; Check that we at least don't crash if given nonexisting files
210 ;; without a directory (bug#56443).
211
212 ;; Use an identity file-name handler, as if called by `ffap'.
213 (let* ((file-name-handler-alist
214 '(("^mailto:" . fileio-tests--identity-expand-handler)))
215 (file "mailto:snowball@hell.com"))
216 ;; Check that `expand-file-name' is identity for this name.
217 (should (equal (expand-file-name file nil) file))
218 (file-name-case-insensitive-p file)))
219
220;;; fileio-tests.el ends here
diff --git a/test/src/filelock-tests.el b/test/src/filelock-tests.el
new file mode 100644
index 00000000000..97642669a0d
--- /dev/null
+++ b/test/src/filelock-tests.el
@@ -0,0 +1,217 @@
1;;; filelock-tests.el --- test file locking -*- lexical-binding: t; -*-
2
3;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
4
5;; This file is part of GNU Emacs.
6
7;; GNU Emacs is free software; you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation, either version 3 of the License, or
10;; (at your option) any later version.
11
12;; GNU Emacs is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; GNU General Public License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with this program. If not, see <https://www.gnu.org/licenses/>.
19
20;;; Commentary:
21
22;; This file tests code in src/filelock.c and, to some extent, the
23;; related code in src/fileio.c.
24;;
25;; See also (info "(emacs)Interlocking") and (info "(elisp)File Locks")
26
27;;; Code:
28
29(require 'cl-macs)
30(require 'ert)
31(require 'ert-x)
32(require 'seq)
33
34(defmacro filelock-tests--fixture (&rest body)
35 "Call BODY under a test fixture.
36Create a test directory and a buffer whose `buffer-file-name' and
37`buffer-file-truename' are a file within it, then call BODY.
38Finally, delete the buffer and the test directory."
39 (declare (debug (body)))
40 `(ert-with-temp-directory temp-dir
41 (let ((name (concat (file-name-as-directory temp-dir)
42 "userfile"))
43 (create-lockfiles t))
44 (with-temp-buffer
45 (setq buffer-file-name name
46 buffer-file-truename name)
47 (unwind-protect
48 (save-current-buffer
49 ,@body)
50 ;; Set `buffer-file-truename' nil to prevent unlocking,
51 ;; which might prompt the user and/or signal errors.
52 (setq buffer-file-name nil
53 buffer-file-truename nil))))))
54
55(defun filelock-tests--make-lock-name (file-name)
56 "Return the lock file name for FILE-NAME.
57Equivalent logic in Emacs proper is implemented in C and
58unavailable to Lisp."
59 (concat (file-name-directory (expand-file-name file-name))
60 ".#"
61 (file-name-nondirectory file-name)))
62
63(defun filelock-tests--spoil-lock-file (file-name)
64 "Spoil the lock file for FILE-NAME.
65Cause Emacs to report errors for various file locking operations
66on FILE-NAME going forward. Create a file that is incompatible
67with Emacs' file locking protocol, but uses the same name as
68FILE-NAME's lock file. A directory file is used, which is
69portable in practice."
70 (make-directory (filelock-tests--make-lock-name file-name)))
71
72(defun filelock-tests--unspoil-lock-file (file-name)
73 "Remove the lock file spoiler for FILE-NAME.
74See `filelock-tests--spoil-lock-file'."
75 (delete-directory (filelock-tests--make-lock-name file-name) t))
76
77(defun filelock-tests--should-be-locked ()
78 "Abort the current test if the current buffer is not locked.
79Exception: on systems without lock file support, aborts the
80current test if the current file is locked (which should never
81the case)."
82 (if (eq system-type 'ms-dos)
83 (should-not (file-locked-p buffer-file-truename))
84 (should (file-locked-p buffer-file-truename))))
85
86(ert-deftest filelock-tests-lock-unlock-no-errors ()
87 "Check that locking and unlocking works without error."
88 (filelock-tests--fixture
89 (should-not (file-locked-p (buffer-file-name)))
90
91 ;; Inserting text should lock the buffer's file.
92 (insert "this locks the buffer's file")
93 (filelock-tests--should-be-locked)
94 (unlock-buffer)
95 (set-buffer-modified-p nil)
96 (should-not (file-locked-p (buffer-file-name)))
97
98 ;; `set-buffer-modified-p' should lock the buffer's file.
99 (set-buffer-modified-p t)
100 (filelock-tests--should-be-locked)
101 (unlock-buffer)
102 (should-not (file-locked-p (buffer-file-name)))
103
104 (should-not (file-locked-p (buffer-file-name)))))
105
106(ert-deftest filelock-tests-lock-spoiled ()
107 "Check `lock-buffer'."
108 (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support
109 (filelock-tests--fixture
110 (filelock-tests--spoil-lock-file buffer-file-truename)
111 ;; FIXME: errors when locking a file are ignored; should they be?
112 (set-buffer-modified-p t)
113 (filelock-tests--unspoil-lock-file buffer-file-truename)
114 (should-not (file-locked-p buffer-file-truename))))
115
116(ert-deftest filelock-tests-file-locked-p-spoiled ()
117 "Check that `file-locked-p' fails if the lockfile is \"spoiled\"."
118 (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support
119 (filelock-tests--fixture
120 (filelock-tests--spoil-lock-file buffer-file-truename)
121 (let ((err (should-error (file-locked-p (buffer-file-name)))))
122 (should (equal (seq-subseq err 0 2)
123 (if (eq system-type 'windows-nt)
124 '(permission-denied "Testing file lock")
125 '(file-error "Testing file lock")))))))
126
127(ert-deftest filelock-tests-unlock-spoiled ()
128 "Check that `unlock-buffer' fails if the lockfile is \"spoiled\"."
129 (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support
130 (filelock-tests--fixture
131 ;; Set the buffer modified with file locking temporarily disabled.
132 (let ((create-lockfiles nil))
133 (set-buffer-modified-p t))
134 (should-not (file-locked-p buffer-file-truename))
135 (filelock-tests--spoil-lock-file buffer-file-truename)
136
137 ;; Errors from `unlock-buffer' should call
138 ;; `userlock--handle-unlock-error' (bug#46397).
139 (cl-letf (((symbol-function 'userlock--handle-unlock-error)
140 (lambda (err) (signal (car err) (cdr err)))))
141 (should (equal
142 (if (eq system-type 'windows-nt)
143 '(permission-denied "Unlocking file")
144 '(file-error "Unlocking file"))
145 (seq-subseq (should-error (unlock-buffer)) 0 2))))))
146
147(ert-deftest filelock-tests-kill-buffer-spoiled ()
148 "Check that `kill-buffer' fails if a lockfile is \"spoiled\"."
149 (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support
150 (filelock-tests--fixture
151 ;; Set the buffer modified with file locking temporarily disabled.
152 (let ((create-lockfiles nil))
153 (set-buffer-modified-p t))
154 (should-not (file-locked-p buffer-file-truename))
155 (filelock-tests--spoil-lock-file buffer-file-truename)
156
157 ;; Kill the current buffer. Because the buffer is modified Emacs
158 ;; will attempt to unlock it. Temporarily bind `yes-or-no-p' to a
159 ;; function that fakes a "yes" answer for the "Buffer modified;
160 ;; kill anyway?" prompt.
161 ;;
162 ;; File errors from unlocking files should call
163 ;; `userlock--handle-unlock-error' (bug#46397).
164 (cl-letf (((symbol-function 'yes-or-no-p) #'always)
165 ((symbol-function 'userlock--handle-unlock-error)
166 (lambda (err) (signal (car err) (cdr err)))))
167 (should (equal
168 (if (eq system-type 'windows-nt)
169 '(permission-denied "Unlocking file")
170 '(file-error "Unlocking file"))
171 (seq-subseq (should-error (kill-buffer)) 0 2))))))
172
173(ert-deftest filelock-tests-detect-external-change ()
174 "Check that an external file modification is reported."
175 (skip-unless (not (eq system-type 'ms-dos))) ; no filelock support
176 (skip-unless (executable-find "touch"))
177 (skip-unless (executable-find "echo"))
178 (dolist (cl '(t nil))
179 (filelock-tests--fixture
180 (let ((create-lockfiles cl))
181 (write-region "foo" nil (buffer-file-name))
182 (revert-buffer nil 'noconfirm)
183 (should-not (file-locked-p (buffer-file-name)))
184
185 ;; Just changing the file modification on disk doesn't hurt,
186 ;; because file contents in buffer and on disk look equal.
187 (shell-command (format "touch %s" (buffer-file-name)))
188 (insert "bar")
189 (when cl (filelock-tests--should-be-locked))
190
191 ;; Bug#53207: with `create-lockfiles' nil, saving the buffer
192 ;; results in a prompt.
193 (cl-letf (((symbol-function 'yes-or-no-p)
194 (lambda (_) (ert-fail "Test failed unexpectedly"))))
195 (save-buffer))
196 (should-not (file-locked-p (buffer-file-name)))
197
198 ;; Changing the file contents on disk hurts when buffer is
199 ;; modified. There shall be a query, which we answer.
200 ;; *Messages* buffer is checked for prompt.
201 (shell-command (format "echo bar >>%s" (buffer-file-name)))
202 (cl-letf (((symbol-function 'read-char-choice)
203 (lambda (prompt &rest _) (message "%s" prompt) ?y)))
204 (ert-with-message-capture captured-messages
205 ;; `ask-user-about-supersession-threat' does not work in
206 ;; batch mode, let's simulate interactiveness.
207 (let (noninteractive)
208 (insert "baz"))
209 (should (string-match-p
210 (format
211 "^%s changed on disk; really edit the buffer\\?"
212 (file-name-nondirectory (buffer-file-name)))
213 captured-messages))))
214 (when cl (filelock-tests--should-be-locked))))))
215
216(provide 'filelock-tests)
217;;; filelock-tests.el ends here
diff --git a/test/src/floatfns-tests.el b/test/src/floatfns-tests.el
index aa4e55e4897..aa709e3c2f5 100644
--- a/test/src/floatfns-tests.el
+++ b/test/src/floatfns-tests.el
@@ -1,6 +1,6 @@
1;;; floatfns-tests.el --- tests for floating point operations 1;;; floatfns-tests.el --- tests for floating point operations -*- lexical-binding: t -*-
2 2
3;; Copyright 2017 Free Software Foundation, Inc. 3;; Copyright 2017-2022 Free Software Foundation, Inc.
4 4
5;; This file is part of GNU Emacs. 5;; This file is part of GNU Emacs.
6 6
@@ -17,13 +17,77 @@
17;; You should have received a copy of the GNU General Public License 17;; You should have received a copy of the GNU General Public License
18;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. 18;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
19 19
20;;; Code:
21
20(require 'ert) 22(require 'ert)
21 23
24(ert-deftest floatfns-tests-cos ()
25 (should (= (cos 0) 1.0))
26 (should (= (cos float-pi) -1.0)))
27
28(ert-deftest floatfns-tests-sin ()
29 (should (= (sin 0) 0.0)))
30
31(ert-deftest floatfns-tests-tan ()
32 (should (= (tan 0) 0.0)))
33
34(ert-deftest floatfns-tests-isnan ()
35 (should (isnan 0.0e+NaN))
36 (should (isnan -0.0e+NaN))
37 (should-error (isnan "foo") :type 'wrong-type-argument))
38
39(ert-deftest floatfns-tests-exp ()
40 (should (= (exp 0) 1.0)))
41
42(ert-deftest floatfns-tests-expt ()
43 (should (= (expt 2 8) 256)))
44
45(ert-deftest floatfns-tests-log ()
46 (should (= (log 1000 10) 3.0)))
47
48(ert-deftest floatfns-tests-sqrt ()
49 (should (= (sqrt 25) 5)))
50
51(ert-deftest floatfns-tests-abs ()
52 (should (= (abs 10) 10))
53 (should (= (abs -10) 10)))
54
55(ert-deftest floatfns-tests-logb ()
56 (should (= (logb 10000) 13)))
57
58(ert-deftest floatfns-tests-ceiling ()
59 (should (= (ceiling 0.5) 1)))
60
61(ert-deftest floatfns-tests-floor ()
62 (should (= (floor 1.5) 1)))
63
64(ert-deftest floatfns-tests-round ()
65 (should (= (round 1.49999999999) 1))
66 (should (= (round 1.50000000000) 2))
67 (should (= (round 1.50000000001) 2)))
68
69(ert-deftest floatfns-tests-truncate ()
70 (should (= (truncate float-pi) 3)))
71
72(ert-deftest floatfns-tests-fceiling ()
73 (should (= (fceiling 0.5) 1.0)))
74
75(ert-deftest floatfns-tests-ffloor ()
76 (should (= (ffloor 1.5) 1.0)))
77
78(ert-deftest floatfns-tests-fround ()
79 (should (= (fround 1.49999999999) 1.0))
80 (should (= (fround 1.50000000000) 2.0))
81 (should (= (fround 1.50000000001) 2.0)))
82
83(ert-deftest floatfns-tests-ftruncate ()
84 (should (= (ftruncate float-pi) 3.0)))
85
22(ert-deftest divide-extreme-sign () 86(ert-deftest divide-extreme-sign ()
23 (should-error (ceiling most-negative-fixnum -1.0)) 87 (should (= (ceiling most-negative-fixnum -1.0) (- most-negative-fixnum)))
24 (should-error (floor most-negative-fixnum -1.0)) 88 (should (= (floor most-negative-fixnum -1.0) (- most-negative-fixnum)))
25 (should-error (round most-negative-fixnum -1.0)) 89 (should (= (round most-negative-fixnum -1.0) (- most-negative-fixnum)))
26 (should-error (truncate most-negative-fixnum -1.0))) 90 (should (= (truncate most-negative-fixnum -1.0) (- most-negative-fixnum))))
27 91
28(ert-deftest logb-extreme-fixnum () 92(ert-deftest logb-extreme-fixnum ()
29 (should (= (logb most-negative-fixnum) (1+ (logb most-positive-fixnum))))) 93 (should (= (logb most-negative-fixnum) (1+ (logb most-positive-fixnum)))))
@@ -34,4 +98,96 @@
34 (should-error (ftruncate 0) :type 'wrong-type-argument) 98 (should-error (ftruncate 0) :type 'wrong-type-argument)
35 (should-error (fround 0) :type 'wrong-type-argument)) 99 (should-error (fround 0) :type 'wrong-type-argument))
36 100
101(ert-deftest bignum-to-float ()
102 ;; 122 because we want to go as big as possible to provoke a rounding error,
103 ;; but not too big: 2**122 < 10**37 < 2**123, and the C standard says
104 ;; 10**37 <= DBL_MAX so 2**122 cannot overflow as a double.
105 (let ((a (1- (ash 1 122))))
106 (should (or (eql a (1- (floor (float a))))
107 (eql a (floor (float a))))))
108 (should (eql (float (+ most-positive-fixnum 1))
109 (+ (float most-positive-fixnum) 1))))
110
111(ert-deftest bignum-abs ()
112 (should (= most-positive-fixnum
113 (- (abs most-negative-fixnum) 1))))
114
115(ert-deftest bignum-expt ()
116 (dolist (n (list most-positive-fixnum (1+ most-positive-fixnum)
117 most-negative-fixnum (1- most-negative-fixnum)
118 (* 5 most-negative-fixnum)
119 (* 5 (1+ most-positive-fixnum))
120 -2 -1 0 1 2))
121 (should (or (<= n 0) (= (expt 0 n) 0)))
122 (should (= (expt 1 n) 1))
123 (should (or (< n 0) (= (expt -1 n) (if (zerop (logand n 1)) 1 -1))))
124 (should (= (expt n 0) 1))
125 (should (= (expt n 1) n))
126 (should (= (expt n 2) (* n n)))
127 (should (= (expt n 3) (* n n n)))))
128
129(ert-deftest bignum-logb ()
130 (should (= (+ (logb most-positive-fixnum) 1)
131 (logb (+ most-positive-fixnum 1)))))
132
133(ert-deftest bignum-mod ()
134 (should (= 0 (mod (1+ most-positive-fixnum) 2.0))))
135
136(ert-deftest bignum-round ()
137 (let ((ns (list (* most-positive-fixnum most-negative-fixnum)
138 (1- most-negative-fixnum) most-negative-fixnum
139 (1+ most-negative-fixnum) -2 1 1 2
140 (1- most-positive-fixnum) most-positive-fixnum
141 (1+ most-positive-fixnum)
142 (* most-positive-fixnum most-positive-fixnum))))
143 (dolist (n ns)
144 (should (= n (ceiling n)))
145 (should (= n (floor n)))
146 (should (= n (round n)))
147 (should (= n (truncate n)))
148 (let ((-n (- n))
149 (f (float n))
150 (-f (- (float n))))
151 (should (= 1 (round n f) (round -n -f) (round f n) (round -f -n)))
152 (should (= -1 (round -n f) (round n -f) (round f -n) (round -f n))))
153 (dolist (d ns)
154 (let ((q (/ n d))
155 (r (% n d))
156 (same-sign (eq (< n 0) (< d 0))))
157 (should (= (ceiling n d)
158 (+ q (if (and same-sign (not (zerop r))) 1 0))))
159 (should (= (floor n d)
160 (- q (if (and (not same-sign) (not (zerop r))) 1 0))))
161 (should (= (truncate n d) q))
162 (let ((cdelta (abs (- n (* d (ceiling n d)))))
163 (fdelta (abs (- n (* d (floor n d)))))
164 (rdelta (abs (- n (* d (round n d))))))
165 (should (<= rdelta cdelta))
166 (should (<= rdelta fdelta))
167 (should (if (zerop r)
168 (= 0 cdelta fdelta rdelta)
169 (or (/= cdelta fdelta)
170 (zerop (% (round n d) 2)))))))))))
171
172(ert-deftest special-round ()
173 (dolist (f '(ceiling floor round truncate))
174 (let ((ns '(-1e+INF 1e+INF -1 -0.0 0.0 0 1 -1e+NaN 1e+NaN)))
175 (dolist (n ns)
176 (if (not (<= (abs n) 1))
177 (should-error (funcall f n))
178 (should (= n (funcall f n)))
179 (dolist (d '(-1e+INF 1e+INF))
180 (should (eq 0 (funcall f n d)))))
181 (dolist (d ns)
182 (when (or (zerop d) (= (abs n) 1e+INF) (not (= n n)) (not (= d d)))
183 (should-error (funcall f n d))))))))
184
185(ert-deftest big-round ()
186 (should (= (floor 54043195528445955 3)
187 (floor 54043195528445955 3.0)))
188 (should (= (floor 1.7976931348623157e+308 5e-324)
189 (ash (1- (ash 1 53)) 2045))))
190
37(provide 'floatfns-tests) 191(provide 'floatfns-tests)
192
193;;; floatfns-tests.el ends here
diff --git a/test/src/fns-tests.el b/test/src/fns-tests.el
index d751acb7478..fe8df7097a7 100644
--- a/test/src/fns-tests.el
+++ b/test/src/fns-tests.el
@@ -1,21 +1,21 @@
1;;; fns-tests.el --- tests for src/fns.c 1;;; fns-tests.el --- tests for src/fns.c -*- lexical-binding:t -*-
2 2
3;; Copyright (C) 2014-2017 Free Software Foundation, Inc. 3;; Copyright (C) 2014-2022 Free Software Foundation, Inc.
4 4
5;; This file is part of GNU Emacs. 5;; This file is part of GNU Emacs.
6 6
7;; This program is free software: you can redistribute it and/or 7;; GNU Emacs is free software: you can redistribute it and/or modify
8;; modify it under the terms of the GNU General Public License as 8;; it under the terms of the GNU General Public License as published by
9;; published by the Free Software Foundation, either version 3 of the 9;; the Free Software Foundation, either version 3 of the License, or
10;; License, or (at your option) any later version. 10;; (at your option) any later version.
11;; 11
12;; This program is distributed in the hope that it will be useful, but 12;; GNU Emacs is distributed in the hope that it will be useful,
13;; WITHOUT ANY WARRANTY; without even the implied warranty of 13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; General Public License for more details. 15;; GNU General Public License for more details.
16;; 16
17;; You should have received a copy of the GNU General Public License 17;; You should have received a copy of the GNU General Public License
18;; along with this program. If not, see `https://www.gnu.org/licenses/'. 18;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
19 19
20;;; Commentary: 20;;; Commentary:
21 21
@@ -23,6 +23,67 @@
23 23
24(require 'cl-lib) 24(require 'cl-lib)
25 25
26(ert-deftest fns-tests-identity ()
27 (let ((num 12345)) (should (eq (identity num) num)))
28 (let ((str "foo")) (should (eq (identity str) str)))
29 (let ((lst '(11))) (should (eq (identity lst) lst))))
30
31(ert-deftest fns-tests-random ()
32 (should (integerp (random)))
33 (should (>= (random 10) 0))
34 (should (< (random 10) 10)))
35
36(ert-deftest fns-tests-length ()
37 (should (= (length nil) 0))
38 (should (= (length '(1 2 3)) 3))
39 (should (= (length '[1 2 3]) 3))
40 (should (= (length "foo") 3))
41 (should-error (length t)))
42
43(ert-deftest fns-tests-safe-length ()
44 (should (= (safe-length '(1 2 3)) 3)))
45
46(ert-deftest fns-tests-string-bytes ()
47 (should (= (string-bytes "abc") 3)))
48
49;; Test that equality predicates work correctly on NaNs when combined
50;; with hash tables based on those predicates. This was not the case
51;; for eql in Emacs 26.
52(ert-deftest fns-tests-equality-nan ()
53 (dolist (test (list #'eq #'eql #'equal))
54 (let* ((h (make-hash-table :test test))
55 (nan 0.0e+NaN)
56 (-nan (- nan)))
57 (puthash nan t h)
58 (should (eq (funcall test nan -nan) (gethash -nan h))))))
59
60(ert-deftest fns-tests-equal-including-properties ()
61 (should (equal-including-properties "" ""))
62 (should (equal-including-properties "foo" "foo"))
63 (should (equal-including-properties #("foo" 0 3 (a b))
64 (propertize "foo" 'a 'b)))
65 (should (equal-including-properties #("foo" 0 3 (a b c d))
66 (propertize "foo" 'a 'b 'c 'd)))
67 (should (equal-including-properties #("a" 0 1 (k v))
68 #("a" 0 1 (k v))))
69 (should-not (equal-including-properties #("a" 0 1 (k v))
70 #("a" 0 1 (k x))))
71 (should-not (equal-including-properties #("a" 0 1 (k v))
72 #("b" 0 1 (k v))))
73 (should-not (equal-including-properties #("foo" 0 3 (a b c e))
74 (propertize "foo" 'a 'b 'c 'd))))
75
76(ert-deftest fns-tests-equal-including-properties/string-prop-vals ()
77 "Handle string property values. (Bug#6581)"
78 (should (equal-including-properties #("a" 0 1 (k "v"))
79 #("a" 0 1 (k "v"))))
80 (should (equal-including-properties #("foo" 0 3 (a (t)))
81 (propertize "foo" 'a (list t))))
82 (should-not (equal-including-properties #("a" 0 1 (k "v"))
83 #("a" 0 1 (k "x"))))
84 (should-not (equal-including-properties #("a" 0 1 (k "v"))
85 #("b" 0 1 (k "v")))))
86
26(ert-deftest fns-tests-reverse () 87(ert-deftest fns-tests-reverse ()
27 (should-error (reverse)) 88 (should-error (reverse))
28 (should-error (reverse 1)) 89 (should-error (reverse 1))
@@ -38,21 +99,21 @@
38 (should-error (nreverse)) 99 (should-error (nreverse))
39 (should-error (nreverse 1)) 100 (should-error (nreverse 1))
40 (should-error (nreverse (make-char-table 'foo))) 101 (should-error (nreverse (make-char-table 'foo)))
41 (should (equal (nreverse "xyzzy") "yzzyx")) 102 (should (equal (nreverse (copy-sequence "xyzzy")) "yzzyx"))
42 (let ((A [])) 103 (let ((A (vector)))
43 (nreverse A) 104 (nreverse A)
44 (should (equal A []))) 105 (should (equal A [])))
45 (let ((A [0])) 106 (let ((A (vector 0)))
46 (nreverse A) 107 (nreverse A)
47 (should (equal A [0]))) 108 (should (equal A [0])))
48 (let ((A [1 2 3 4])) 109 (let ((A (vector 1 2 3 4)))
49 (nreverse A) 110 (nreverse A)
50 (should (equal A [4 3 2 1]))) 111 (should (equal A [4 3 2 1])))
51 (let ((A [1 2 3 4])) 112 (let ((A (vector 1 2 3 4)))
52 (nreverse A) 113 (nreverse A)
53 (nreverse A) 114 (nreverse A)
54 (should (equal A [1 2 3 4]))) 115 (should (equal A [1 2 3 4])))
55 (let* ((A [1 2 3 4]) 116 (let* ((A (vector 1 2 3 4))
56 (B (nreverse (nreverse A)))) 117 (B (nreverse (nreverse A))))
57 (should (equal A B)))) 118 (should (equal A B))))
58 119
@@ -69,6 +130,49 @@
69 (should (equal [nil nil nil nil nil t t t t t] (vconcat A))) 130 (should (equal [nil nil nil nil nil t t t t t] (vconcat A)))
70 (should (equal [t t t t t nil nil nil nil nil] (vconcat (nreverse A)))))) 131 (should (equal [t t t t t nil nil nil nil nil] (vconcat (nreverse A))))))
71 132
133(defconst fns-tests--string-lessp-cases
134 '((a 97 error)
135 (97 "a" error)
136 ("abc" "abd" t)
137 ("abd" "abc" nil)
138 (abc "abd" t)
139 ("abd" abc nil)
140 (abc abd t)
141 (abd abc nil)
142 ("" "" nil)
143 ("" " " t)
144 (" " "" nil)
145 ("abc" "abcd" t)
146 ("abcd" "abc" nil)
147 ("abc" "abc" nil)
148 (abc abc nil)
149 ("\0" "" nil)
150 ("" "\0" t)
151 ("~" "\x80" t)
152 ("\x80" "\x80" nil)
153 ("\xfe" "\xff" t)
154 ("Munchen" "München" t)
155 ("München" "Munchen" nil)
156 ("München" "München" nil)
157 ("Ré" "Réunion" t)))
158
159
160(ert-deftest fns-tests-string-lessp ()
161 ;; Exercise both `string-lessp' and its alias `string<', both directly
162 ;; and in a function (exercising its bytecode).
163 (dolist (lessp (list #'string-lessp #'string<
164 (lambda (a b) (string-lessp a b))
165 (lambda (a b) (string< a b))))
166 (ert-info ((prin1-to-string lessp) :prefix "function: ")
167 (dolist (case fns-tests--string-lessp-cases)
168 (ert-info ((prin1-to-string case) :prefix "case: ")
169 (pcase case
170 (`(,x ,y error)
171 (should-error (funcall lessp x y)))
172 (`(,x ,y ,expected)
173 (should (equal (funcall lessp x y) expected)))))))))
174
175
72(ert-deftest fns-tests-compare-strings () 176(ert-deftest fns-tests-compare-strings ()
73 (should-error (compare-strings)) 177 (should-error (compare-strings))
74 (should-error (compare-strings "xyzzy" "xyzzy")) 178 (should-error (compare-strings "xyzzy" "xyzzy"))
@@ -119,10 +223,9 @@
119 223
120 ;; In POSIX or C locales, collation order is lexicographic. 224 ;; In POSIX or C locales, collation order is lexicographic.
121 (should (string-collate-lessp "XYZZY" "xyzzy" "POSIX")) 225 (should (string-collate-lessp "XYZZY" "xyzzy" "POSIX"))
122 ;; In a language specific locale, collation order is different. 226 ;; In a language specific locale on MS-Windows, collation order is different.
123 (should (string-collate-lessp 227 (when (eq system-type 'windows-nt)
124 "xyzzy" "XYZZY" 228 (should (string-collate-lessp "xyzzy" "XYZZY" "enu_USA")))
125 (if (eq system-type 'windows-nt) "enu_USA" "en_US.UTF-8")))
126 229
127 ;; Ignore case. 230 ;; Ignore case.
128 (should (string-collate-equalp "xyzzy" "XYZZY" nil t)) 231 (should (string-collate-equalp "xyzzy" "XYZZY" nil t))
@@ -136,14 +239,84 @@
136;; Invalid UTF-8 sequences shall be indicated. How to create such strings? 239;; Invalid UTF-8 sequences shall be indicated. How to create such strings?
137 240
138(ert-deftest fns-tests-sort () 241(ert-deftest fns-tests-sort ()
139 (should (equal (sort '(9 5 2 -1 5 3 8 7 4) (lambda (x y) (< x y))) 242 (should (equal (sort (list 9 5 2 -1 5 3 8 7 4) (lambda (x y) (< x y)))
140 '(-1 2 3 4 5 5 7 8 9))) 243 '(-1 2 3 4 5 5 7 8 9)))
141 (should (equal (sort '(9 5 2 -1 5 3 8 7 4) (lambda (x y) (> x y))) 244 (should (equal (sort (list 9 5 2 -1 5 3 8 7 4) (lambda (x y) (> x y)))
142 '(9 8 7 5 5 4 3 2 -1))) 245 '(9 8 7 5 5 4 3 2 -1)))
143 (should (equal (sort '[9 5 2 -1 5 3 8 7 4] (lambda (x y) (< x y))) 246 (should (equal (sort (vector 9 5 2 -1 5 3 8 7 4) (lambda (x y) (< x y)))
144 [-1 2 3 4 5 5 7 8 9])) 247 [-1 2 3 4 5 5 7 8 9]))
145 (should (equal (sort '[9 5 2 -1 5 3 8 7 4] (lambda (x y) (> x y))) 248 (should (equal (sort (vector 9 5 2 -1 5 3 8 7 4) (lambda (x y) (> x y)))
146 [9 8 7 5 5 4 3 2 -1])) 249 [9 8 7 5 5 4 3 2 -1]))
250 ;; Sort a reversed list and vector.
251 (should (equal
252 (sort (reverse (number-sequence 1 1000)) (lambda (x y) (< x y)))
253 (number-sequence 1 1000)))
254 (should (equal
255 (sort (reverse (vconcat (number-sequence 1 1000)))
256 (lambda (x y) (< x y)))
257 (vconcat (number-sequence 1 1000))))
258 ;; Sort a constant list and vector.
259 (should (equal
260 (sort (make-vector 100 1) (lambda (x y) (> x y)))
261 (make-vector 100 1)))
262 (should (equal
263 (sort (append (make-vector 100 1) nil) (lambda (x y) (> x y)))
264 (append (make-vector 100 1) nil)))
265 ;; Sort a long list and vector with every pair reversed.
266 (let ((vec (make-vector 100000 nil))
267 (logxor-vec (make-vector 100000 nil)))
268 (dotimes (i 100000)
269 (aset logxor-vec i (logxor i 1))
270 (aset vec i i))
271 (should (equal
272 (sort logxor-vec (lambda (x y) (< x y)))
273 vec))
274 (should (equal
275 (sort (append logxor-vec nil) (lambda (x y) (< x y)))
276 (append vec nil))))
277 ;; Sort a list and vector with seven swaps.
278 (let ((vec (make-vector 100 nil))
279 (swap-vec (make-vector 100 nil)))
280 (dotimes (i 100)
281 (aset vec i (- i 50))
282 (aset swap-vec i (- i 50)))
283 (mapc (lambda (p)
284 (let ((tmp (elt swap-vec (car p))))
285 (aset swap-vec (car p) (elt swap-vec (cdr p)))
286 (aset swap-vec (cdr p) tmp)))
287 '((48 . 94) (75 . 77) (33 . 41) (92 . 52)
288 (10 . 96) (1 . 14) (43 . 81)))
289 (should (equal
290 (sort (copy-sequence swap-vec) (lambda (x y) (< x y)))
291 vec))
292 (should (equal
293 (sort (append swap-vec nil) (lambda (x y) (< x y)))
294 (append vec nil))))
295 ;; Check for possible corruption after GC.
296 (let* ((size 3000)
297 (complex-vec (make-vector size nil))
298 (vec (make-vector size nil))
299 (counter 0)
300 (my-counter (lambda ()
301 (if (< counter 500)
302 (cl-incf counter)
303 (setq counter 0)
304 (garbage-collect))))
305 (rand 1)
306 (generate-random
307 (lambda () (setq rand
308 (logand (+ (* rand 1103515245) 12345) 2147483647)))))
309 ;; Make a complex vector and its sorted version.
310 (dotimes (i size)
311 (let ((r (funcall generate-random)))
312 (aset complex-vec i (cons r "a"))
313 (aset vec i (cons r "a"))))
314 ;; Sort it.
315 (should (equal
316 (sort complex-vec
317 (lambda (x y) (funcall my-counter) (< (car x) (car y))))
318 (sort vec 'car-less-than-car))))
319 ;; Check for sorting stability.
147 (should (equal 320 (should (equal
148 (sort 321 (sort
149 (vector 322 (vector
@@ -151,45 +324,51 @@
151 '(9 . "ppp") '(8 . "ttt") '(8 . "eee") '(9 . "fff")) 324 '(9 . "ppp") '(8 . "ttt") '(8 . "eee") '(9 . "fff"))
152 (lambda (x y) (< (car x) (car y)))) 325 (lambda (x y) (< (car x) (car y))))
153 [(8 . "xxx") (8 . "bbb") (8 . "ttt") (8 . "eee") 326 [(8 . "xxx") (8 . "bbb") (8 . "ttt") (8 . "eee")
154 (9 . "aaa") (9 . "zzz") (9 . "ppp") (9 . "fff")]))) 327 (9 . "aaa") (9 . "zzz") (9 . "ppp") (9 . "fff")]))
328 ;; Bug#34104
329 (should (equal (should-error (sort "cba" #'<) :type 'wrong-type-argument)
330 '(wrong-type-argument list-or-vector-p "cba"))))
331
332(defvar w32-collate-ignore-punctuation)
155 333
156(ert-deftest fns-tests-collate-sort () 334(ert-deftest fns-tests-collate-sort ()
157 ;; See https://lists.gnu.org/archive/html/emacs-devel/2015-10/msg02505.html.
158 :expected-result (if (eq system-type 'cygwin) :failed :passed)
159 (skip-unless (fns-tests--collate-enabled-p)) 335 (skip-unless (fns-tests--collate-enabled-p))
160 336
161 ;; Punctuation and whitespace characters are relevant for POSIX. 337 ;; Punctuation and whitespace characters are relevant for POSIX.
162 (should 338 (should
163 (equal 339 (equal
164 (sort '("11" "12" "1 1" "1 2" "1.1" "1.2") 340 (sort (list "11" "12" "1 1" "1 2" "1.1" "1.2")
165 (lambda (a b) (string-collate-lessp a b "POSIX"))) 341 (lambda (a b) (string-collate-lessp a b "POSIX")))
166 '("1 1" "1 2" "1.1" "1.2" "11" "12"))) 342 '("1 1" "1 2" "1.1" "1.2" "11" "12")))
167 ;; Punctuation and whitespace characters are not taken into account 343 ;; Punctuation and whitespace characters are not taken into account
168 ;; for collation in other locales. 344 ;; for collation in other locales, on MS-Windows systems.
169 (should 345 (when (eq system-type 'windows-nt)
170 (equal 346 (should
171 (sort '("11" "12" "1 1" "1 2" "1.1" "1.2") 347 (equal
172 (lambda (a b) 348 (sort (list "11" "12" "1 1" "1 2" "1.1" "1.2")
173 (let ((w32-collate-ignore-punctuation t)) 349 (lambda (a b)
174 (string-collate-lessp 350 (let ((w32-collate-ignore-punctuation t))
175 a b (if (eq system-type 'windows-nt) "enu_USA" "en_US.UTF-8"))))) 351 (string-collate-lessp
176 '("11" "1 1" "1.1" "12" "1 2" "1.2"))) 352 a b "enu_USA"))))
353 '("11" "1 1" "1.1" "12" "1 2" "1.2"))))
177 354
178 ;; Diacritics are different letters for POSIX, they sort lexicographical. 355 ;; Diacritics are different letters for POSIX, they sort lexicographical.
179 (should 356 (should
180 (equal 357 (equal
181 (sort '("Ævar" "Agustín" "Adrian" "Eli") 358 (sort (list "Ævar" "Agustín" "Adrian" "Eli")
182 (lambda (a b) (string-collate-lessp a b "POSIX"))) 359 (lambda (a b) (string-collate-lessp a b "POSIX")))
183 '("Adrian" "Agustín" "Eli" "Ævar"))) 360 '("Adrian" "Agustín" "Eli" "Ævar")))
184 ;; Diacritics are sorted between similar letters for other locales. 361 ;; Diacritics are sorted between similar letters for other locales,
185 (should 362 ;; on MS-Windows systems.
186 (equal 363 (when (eq system-type 'windows-nt)
187 (sort '("Ævar" "Agustín" "Adrian" "Eli") 364 (should
188 (lambda (a b) 365 (equal
189 (let ((w32-collate-ignore-punctuation t)) 366 (sort (list "Ævar" "Agustín" "Adrian" "Eli")
190 (string-collate-lessp 367 (lambda (a b)
191 a b (if (eq system-type 'windows-nt) "enu_USA" "en_US.UTF-8"))))) 368 (let ((w32-collate-ignore-punctuation t))
192 '("Adrian" "Ævar" "Agustín" "Eli")))) 369 (string-collate-lessp
370 a b "enu_USA"))))
371 '("Adrian" "Ævar" "Agustín" "Eli")))))
193 372
194(ert-deftest fns-tests-string-version-lessp () 373(ert-deftest fns-tests-string-version-lessp ()
195 (should (string-version-lessp "foo2.png" "foo12.png")) 374 (should (string-version-lessp "foo2.png" "foo12.png"))
@@ -198,7 +377,7 @@
198 (should (not (string-version-lessp "foo20000.png" "foo12.png"))) 377 (should (not (string-version-lessp "foo20000.png" "foo12.png")))
199 (should (string-version-lessp "foo.png" "foo2.png")) 378 (should (string-version-lessp "foo.png" "foo2.png"))
200 (should (not (string-version-lessp "foo2.png" "foo.png"))) 379 (should (not (string-version-lessp "foo2.png" "foo.png")))
201 (should (equal (sort '("foo12.png" "foo2.png" "foo1.png") 380 (should (equal (sort (list "foo12.png" "foo2.png" "foo1.png")
202 'string-version-lessp) 381 'string-version-lessp)
203 '("foo1.png" "foo2.png" "foo12.png"))) 382 '("foo1.png" "foo2.png" "foo12.png")))
204 (should (string-version-lessp "foo2" "foo1234")) 383 (should (string-version-lessp "foo2" "foo1234"))
@@ -214,11 +393,200 @@
214 (should (equal (func-arity 'format) '(1 . many))) 393 (should (equal (func-arity 'format) '(1 . many)))
215 (require 'info) 394 (require 'info)
216 (should (equal (func-arity 'Info-goto-node) '(1 . 3))) 395 (should (equal (func-arity 'Info-goto-node) '(1 . 3)))
217 (should (equal (func-arity (lambda (&rest x))) '(0 . many))) 396 (should (equal (func-arity (lambda (&rest _x))) '(0 . many)))
218 (should (equal (func-arity (eval (lambda (x &optional y)) nil)) '(1 . 2))) 397 (should (equal (func-arity (eval '(lambda (_x &optional y)) nil)) '(1 . 2)))
219 (should (equal (func-arity (eval (lambda (x &optional y)) t)) '(1 . 2))) 398 (should (equal (func-arity (eval '(lambda (_x &optional y)) t)) '(1 . 2)))
220 (should (equal (func-arity 'let) '(1 . unevalled)))) 399 (should (equal (func-arity 'let) '(1 . unevalled))))
221 400
401(defun fns-tests--string-repeat (s o)
402 (apply 'concat (make-list o s)))
403
404(defmacro fns-tests--with-region (funcname string &rest args)
405 "Apply FUNCNAME in a temp buffer on the region produced by STRING."
406 (declare (indent 1))
407 `(with-temp-buffer
408 (insert ,string)
409 (,funcname (point-min) (point-max) ,@args)
410 (buffer-string)))
411
412(ert-deftest fns-tests-base64-encode-region ()
413 ;; standard variant RFC2045
414 (should (equal (fns-tests--with-region base64-encode-region "") ""))
415 (should (equal (fns-tests--with-region base64-encode-region "f") "Zg=="))
416 (should (equal (fns-tests--with-region base64-encode-region "fo") "Zm8="))
417 (should (equal (fns-tests--with-region base64-encode-region "foo") "Zm9v"))
418 (should (equal (fns-tests--with-region base64-encode-region "foob") "Zm9vYg=="))
419 (should (equal (fns-tests--with-region base64-encode-region "fooba") "Zm9vYmE="))
420 (should (equal (fns-tests--with-region base64-encode-region "foobar") "Zm9vYmFy"))
421 (should (equal (fns-tests--with-region base64-encode-region "\x14\xfb\x9c\x03\xd9\x7e") "FPucA9l+"))
422 (should (equal (fns-tests--with-region base64-encode-region "\x14\xfb\x9c\x03\xd9\x7f") "FPucA9l/")))
423
424(ert-deftest fns-tests-base64-encode-string ()
425 ;; standard variant RFC2045
426 (should (equal (base64-encode-string "") ""))
427 (should (equal (base64-encode-string "f") "Zg=="))
428 (should (equal (base64-encode-string "fo") "Zm8="))
429 (should (equal (base64-encode-string "foo") "Zm9v"))
430 (should (equal (base64-encode-string "foob") "Zm9vYg=="))
431 (should (equal (base64-encode-string "fooba") "Zm9vYmE="))
432 (should (equal (base64-encode-string "foobar") "Zm9vYmFy"))
433 (should (equal (base64-encode-string "\x14\xfb\x9c\x03\xd9\x7e") "FPucA9l+"))
434 (should (equal (base64-encode-string "\x14\xfb\x9c\x03\xd9\x7f") "FPucA9l/"))
435
436 (should-error (base64-encode-string "ƒ"))
437 (should-error (base64-encode-string "ü")))
438
439(ert-deftest fns-test-base64url-encode-region ()
440 ;; url variant with padding
441 (should (equal (fns-tests--with-region base64url-encode-region "") ""))
442 (should (equal (fns-tests--with-region base64url-encode-region "f") "Zg=="))
443 (should (equal (fns-tests--with-region base64url-encode-region "fo") "Zm8="))
444 (should (equal (fns-tests--with-region base64url-encode-region "foo") "Zm9v"))
445 (should (equal (fns-tests--with-region base64url-encode-region "foob") "Zm9vYg=="))
446 (should (equal (fns-tests--with-region base64url-encode-region "fooba") "Zm9vYmE="))
447 (should (equal (fns-tests--with-region base64url-encode-region "foobar") "Zm9vYmFy"))
448 (should (equal (fns-tests--with-region base64url-encode-region "\x14\xfb\x9c\x03\xd9\x7e") "FPucA9l-"))
449 (should (equal (fns-tests--with-region base64url-encode-region "\x14\xfb\x9c\x03\xd9\x7f") "FPucA9l_"))
450
451 ;; url variant no padding
452 (should (equal (fns-tests--with-region base64url-encode-region "" t) ""))
453 (should (equal (fns-tests--with-region base64url-encode-region "f" t) "Zg"))
454 (should (equal (fns-tests--with-region base64url-encode-region "fo" t) "Zm8"))
455 (should (equal (fns-tests--with-region base64url-encode-region "foo" t) "Zm9v"))
456 (should (equal (fns-tests--with-region base64url-encode-region "foob" t) "Zm9vYg"))
457 (should (equal (fns-tests--with-region base64url-encode-region "fooba" t) "Zm9vYmE"))
458 (should (equal (fns-tests--with-region base64url-encode-region "foobar" t) "Zm9vYmFy"))
459 (should (equal (fns-tests--with-region base64url-encode-region "\x14\xfb\x9c\x03\xd9\x7e" t) "FPucA9l-"))
460 (should (equal (fns-tests--with-region base64url-encode-region "\x14\xfb\x9c\x03\xd9\x7f" t) "FPucA9l_"))
461
462
463 ;; url variant no line break no padding
464 (should (equal (fns-tests--with-region base64url-encode-region (fns-tests--string-repeat "f" 100) t)
465 (concat (fns-tests--string-repeat "Zm" 66) "Zg")))
466 (should (equal (fns-tests--with-region base64url-encode-region (fns-tests--string-repeat "fo" 50) t)
467 (concat (fns-tests--string-repeat "Zm9mb2Zv" 16) "Zm9mbw")))
468 (should (equal (fns-tests--with-region base64url-encode-region (fns-tests--string-repeat "foo" 25) t)
469 (fns-tests--string-repeat "Zm9v" 25)))
470 (should (equal (fns-tests--with-region base64url-encode-region (fns-tests--string-repeat "foob" 15) t)
471 (fns-tests--string-repeat "Zm9vYmZvb2Jmb29i" 5)))
472 (should (equal (fns-tests--with-region base64url-encode-region (fns-tests--string-repeat "fooba" 15) t)
473 (fns-tests--string-repeat "Zm9vYmFmb29iYWZvb2Jh" 5)))
474 (should (equal (fns-tests--with-region base64url-encode-region (fns-tests--string-repeat "foobar" 15) t)
475 (concat (fns-tests--string-repeat "Zm9vYmFyZm9vYmFy" 7) "Zm9vYmFy")))
476 (should (equal (fns-tests--with-region base64url-encode-region (fns-tests--string-repeat "\x14\xfb\x9c\x03\xd9\x7e" 10) t)
477 (fns-tests--string-repeat "FPucA9l-" 10)))
478 (should (equal (fns-tests--with-region base64url-encode-region (fns-tests--string-repeat "\x14\xfb\x9c\x03\xd9\x7f" 10) t)
479 (fns-tests--string-repeat "FPucA9l_" 10)))
480
481 (should-error (fns-tests--with-region base64url-encode-region "ƒ"))
482 (should-error (fns-tests--with-region base64url-encode-region "ü")))
483
484
485(ert-deftest fns-test-base64url-encode-string ()
486 ;; url variant with padding
487 (should (equal (base64url-encode-string "") ""))
488 (should (equal (base64url-encode-string "f") "Zg=="))
489 (should (equal (base64url-encode-string "fo") "Zm8="))
490 (should (equal (base64url-encode-string "foo") "Zm9v"))
491 (should (equal (base64url-encode-string "foob") "Zm9vYg=="))
492 (should (equal (base64url-encode-string "fooba") "Zm9vYmE="))
493 (should (equal (base64url-encode-string "foobar") "Zm9vYmFy"))
494 (should (equal (base64url-encode-string "\x14\xfb\x9c\x03\xd9\x7e") "FPucA9l-"))
495 (should (equal (base64url-encode-string "\x14\xfb\x9c\x03\xd9\x7f") "FPucA9l_"))
496
497 ;; url variant no padding
498 (should (equal (base64url-encode-string "" t) ""))
499 (should (equal (base64url-encode-string "f" t) "Zg"))
500 (should (equal (base64url-encode-string "fo" t) "Zm8"))
501 (should (equal (base64url-encode-string "foo" t) "Zm9v"))
502 (should (equal (base64url-encode-string "foob" t) "Zm9vYg"))
503 (should (equal (base64url-encode-string "fooba" t) "Zm9vYmE"))
504 (should (equal (base64url-encode-string "foobar" t) "Zm9vYmFy"))
505 (should (equal (base64url-encode-string "\x14\xfb\x9c\x03\xd9\x7e" t) "FPucA9l-"))
506 (should (equal (base64url-encode-string "\x14\xfb\x9c\x03\xd9\x7f" t) "FPucA9l_"))
507
508
509 ;; url variant no line break no padding
510 (should (equal (base64url-encode-string (fns-tests--string-repeat "f" 100) t) (concat (fns-tests--string-repeat "Zm" 66) "Zg")))
511 (should (equal (base64url-encode-string (fns-tests--string-repeat "fo" 50) t) (concat (fns-tests--string-repeat "Zm9mb2Zv" 16) "Zm9mbw")))
512 (should (equal (base64url-encode-string (fns-tests--string-repeat "foo" 25) t) (fns-tests--string-repeat "Zm9v" 25)))
513 (should (equal (base64url-encode-string (fns-tests--string-repeat "foob" 15) t) (fns-tests--string-repeat "Zm9vYmZvb2Jmb29i" 5)))
514 (should (equal (base64url-encode-string (fns-tests--string-repeat "fooba" 15) t) (fns-tests--string-repeat "Zm9vYmFmb29iYWZvb2Jh" 5)))
515 (should (equal (base64url-encode-string (fns-tests--string-repeat "foobar" 15) t) (concat (fns-tests--string-repeat "Zm9vYmFyZm9vYmFy" 7) "Zm9vYmFy")))
516 (should (equal (base64url-encode-string (fns-tests--string-repeat "\x14\xfb\x9c\x03\xd9\x7e" 10) t) (fns-tests--string-repeat "FPucA9l-" 10)))
517 (should (equal (base64url-encode-string (fns-tests--string-repeat "\x14\xfb\x9c\x03\xd9\x7f" 10) t) (fns-tests--string-repeat "FPucA9l_" 10)))
518
519 (should-error (base64url-encode-string "ƒ"))
520 (should-error (base64url-encode-string "ü")))
521
522(ert-deftest fns-tests-base64-decode-string ()
523 ;; standard variant RFC2045
524 (should (equal (base64-decode-string "") ""))
525 (should (equal (base64-decode-string "Zg==") "f"))
526 (should (equal (base64-decode-string "Zm8=") "fo"))
527 (should (equal (base64-decode-string "Zm9v") "foo"))
528 (should (equal (base64-decode-string "Zm9vYg==") "foob"))
529 (should (equal (base64-decode-string "Zm9vYmE=") "fooba"))
530 (should (equal (base64-decode-string "Zm9vYmFy") "foobar"))
531 (should (equal (base64-decode-string "FPucA9l+") "\x14\xfb\x9c\x03\xd9\x7e"))
532 (should (equal (base64-decode-string "FPucA9l/") "\x14\xfb\x9c\x03\xd9\x7f"))
533
534 ;; no padding
535 (should (equal (base64-decode-string "" t) ""))
536 (should (equal (base64-decode-string "Zg" t) "f"))
537 (should (equal (base64-decode-string "Zm8" t) "fo"))
538 (should (equal (base64-decode-string "Zm9v" t) "foo"))
539 (should (equal (base64-decode-string "Zm9vYg" t) "foob"))
540 (should (equal (base64-decode-string "Zm9vYmE" t) "fooba"))
541 (should (equal (base64-decode-string "Zm9vYmFy" t) "foobar"))
542
543 ;; url variant with padding
544 (should (equal (base64-decode-string "") ""))
545 (should (equal (base64-decode-string "Zg==" t) "f") )
546 (should (equal (base64-decode-string "Zm8=" t) "fo"))
547 (should (equal (base64-decode-string "Zm9v" t) "foo"))
548 (should (equal (base64-decode-string "Zm9vYg==" t) "foob"))
549 (should (equal (base64-decode-string "Zm9vYmE=" t) "fooba"))
550 (should (equal (base64-decode-string "Zm9vYmFy" t) "foobar"))
551 (should (equal (base64-decode-string "FPucA9l-" t) "\x14\xfb\x9c\x03\xd9\x7e"))
552 (should (equal (base64-decode-string "FPucA9l_" t) "\x14\xfb\x9c\x03\xd9\x7f"))
553
554 ;; url variant no padding
555 (should (equal (base64-decode-string "") ""))
556 (should (equal (base64-decode-string "Zg" t) "f"))
557 (should (equal (base64-decode-string "Zm8" t) "fo"))
558 (should (equal (base64-decode-string "Zm9v" t) "foo"))
559 (should (equal (base64-decode-string "Zm9vYg" t) "foob"))
560 (should (equal (base64-decode-string "Zm9vYmE" t) "fooba"))
561 (should (equal (base64-decode-string "Zm9vYmFy" t) "foobar"))
562 (should (equal (base64-decode-string "FPucA9l-" t) "\x14\xfb\x9c\x03\xd9\x7e"))
563 (should (equal (base64-decode-string "FPucA9l_" t) "\x14\xfb\x9c\x03\xd9\x7f"))
564
565
566 ;; url variant no line break no padding
567 (should (equal (base64-decode-string (concat (fns-tests--string-repeat "Zm" 66) "Zg") t)
568 (fns-tests--string-repeat "f" 100)))
569 (should (equal (base64-decode-string (concat (fns-tests--string-repeat "Zm9mb2Zv" 16) "Zm9mbw") t)
570 (fns-tests--string-repeat "fo" 50)))
571 (should (equal (base64-decode-string (fns-tests--string-repeat "Zm9v" 25) t)
572 (fns-tests--string-repeat "foo" 25)))
573 (should (equal (base64-decode-string (fns-tests--string-repeat "Zm9vYmZvb2Jmb29i" 5) t)
574 (fns-tests--string-repeat "foob" 15)))
575 (should (equal (base64-decode-string (fns-tests--string-repeat "Zm9vYmFmb29iYWZvb2Jh" 5) t)
576 (fns-tests--string-repeat "fooba" 15)))
577 (should (equal (base64-decode-string (concat (fns-tests--string-repeat "Zm9vYmFyZm9vYmFy" 7) "Zm9vYmFy") t)
578 (fns-tests--string-repeat "foobar" 15)))
579 (should (equal (base64-decode-string (fns-tests--string-repeat "FPucA9l-" 10) t)
580 (fns-tests--string-repeat "\x14\xfb\x9c\x03\xd9\x7e" 10)))
581 (should (equal (base64-decode-string (fns-tests--string-repeat "FPucA9l_" 10) t)
582 (fns-tests--string-repeat "\x14\xfb\x9c\x03\xd9\x7f" 10)))
583
584 ;; errors check
585 (should (eq :got-error (condition-case () (base64-decode-string "Zg=") (error :got-error))))
586 (should (eq :got-error (condition-case () (base64-decode-string "Zm9vYmE") (error :got-error))))
587 (should (eq :got-error (condition-case () (base64-decode-string "Zm9vYmFy=") (error :got-error))))
588 (should (eq :got-error (condition-case () (base64-decode-string "Zg=Zg=") (error :got-error)))))
589
222(ert-deftest fns-tests-hash-buffer () 590(ert-deftest fns-tests-hash-buffer ()
223 (should (equal (sha1 "foo") "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33")) 591 (should (equal (sha1 "foo") "0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"))
224 (should (equal (with-temp-buffer 592 (should (equal (with-temp-buffer
@@ -235,13 +603,30 @@
235 (buffer-hash)) 603 (buffer-hash))
236 (sha1 "foo")))) 604 (sha1 "foo"))))
237 605
606(ert-deftest fns-tests-mapconcat ()
607 (should (string= (mapconcat #'identity '()) ""))
608 (should (string= (mapconcat #'identity '("a" "b")) "ab"))
609 (should (string= (mapconcat #'identity '() "_") ""))
610 (should (string= (mapconcat #'identity '("A") "_") "A"))
611 (should (string= (mapconcat #'identity '("A" "B") "_") "A_B"))
612 (should (string= (mapconcat #'identity '("A" "B" "C") "_") "A_B_C"))
613 ;; non-ASCII strings
614 (should (string= (mapconcat #'identity '("Ä" "ø" "☭" "தமிழ்") "_漢字_")
615 "Ä_漢字_ø_漢字_☭_漢字_தமிழ்"))
616 ;; vector
617 (should (string= (mapconcat #'identity ["a" "b"]) "ab"))
618 ;; bool-vector
619 (should (string= (mapconcat #'identity [nil nil]) ""))
620 (should-error (mapconcat #'identity [nil nil t])
621 :type 'wrong-type-argument))
622
238(ert-deftest fns-tests-mapcan () 623(ert-deftest fns-tests-mapcan ()
239 (should-error (mapcan)) 624 (should-error (mapcan))
240 (should-error (mapcan #'identity)) 625 (should-error (mapcan #'identity))
241 (should-error (mapcan #'identity (make-char-table 'foo))) 626 (should-error (mapcan #'identity (make-char-table 'foo)))
242 (should (equal (mapcan #'list '(1 2 3)) '(1 2 3))) 627 (should (equal (mapcan #'list (list 1 2 3)) '(1 2 3)))
243 ;; `mapcan' is destructive 628 ;; `mapcan' is destructive
244 (let ((data '((foo) (bar)))) 629 (let ((data (list (list 'foo) (list 'bar))))
245 (should (equal (mapcan #'identity data) '(foo bar))) 630 (should (equal (mapcan #'identity data) '(foo bar)))
246 (should (equal data '((foo bar) (bar)))))) 631 (should (equal data '((foo bar) (bar))))))
247 632
@@ -467,24 +852,6 @@
467 (should-not (plist-get d1 3)) 852 (should-not (plist-get d1 3))
468 (should-not (plist-get d2 3)))) 853 (should-not (plist-get d2 3))))
469 854
470(ert-deftest test-cycle-lax-plist-get ()
471 (let ((c1 (cyc1 1))
472 (c2 (cyc2 1 2))
473 (d1 (dot1 1))
474 (d2 (dot2 1 2)))
475 (should (lax-plist-get c1 1))
476 (should (lax-plist-get c2 1))
477 (should (lax-plist-get d1 1))
478 (should (lax-plist-get d2 1))
479 (should-error (lax-plist-get c1 2) :type 'circular-list)
480 (should (lax-plist-get c2 2))
481 (should-error (lax-plist-get d1 2) :type 'wrong-type-argument)
482 (should (lax-plist-get d2 2))
483 (should-error (lax-plist-get c1 3) :type 'circular-list)
484 (should-error (lax-plist-get c2 3) :type 'circular-list)
485 (should-error (lax-plist-get d1 3) :type 'wrong-type-argument)
486 (should-error (lax-plist-get d2 3) :type 'wrong-type-argument)))
487
488(ert-deftest test-cycle-plist-member () 855(ert-deftest test-cycle-plist-member ()
489 (let ((c1 (cyc1 1)) 856 (let ((c1 (cyc1 1))
490 (c2 (cyc2 1 2)) 857 (c2 (cyc2 1 2))
@@ -521,24 +888,6 @@
521 (should-error (plist-put d1 3 3) :type 'wrong-type-argument) 888 (should-error (plist-put d1 3 3) :type 'wrong-type-argument)
522 (should-error (plist-put d2 3 3) :type 'wrong-type-argument))) 889 (should-error (plist-put d2 3 3) :type 'wrong-type-argument)))
523 890
524(ert-deftest test-cycle-lax-plist-put ()
525 (let ((c1 (cyc1 1))
526 (c2 (cyc2 1 2))
527 (d1 (dot1 1))
528 (d2 (dot2 1 2)))
529 (should (lax-plist-put c1 1 1))
530 (should (lax-plist-put c2 1 1))
531 (should (lax-plist-put d1 1 1))
532 (should (lax-plist-put d2 1 1))
533 (should-error (lax-plist-put c1 2 2) :type 'circular-list)
534 (should (lax-plist-put c2 2 2))
535 (should-error (lax-plist-put d1 2 2) :type 'wrong-type-argument)
536 (should (lax-plist-put d2 2 2))
537 (should-error (lax-plist-put c1 3 3) :type 'circular-list)
538 (should-error (lax-plist-put c2 3 3) :type 'circular-list)
539 (should-error (lax-plist-put d1 3 3) :type 'wrong-type-argument)
540 (should-error (lax-plist-put d2 3 3) :type 'wrong-type-argument)))
541
542(ert-deftest test-cycle-equal () 891(ert-deftest test-cycle-equal ()
543 (should-error (equal (cyc1 1) (cyc1 1))) 892 (should-error (equal (cyc1 1) (cyc1 1)))
544 (should-error (equal (cyc2 1 2) (cyc2 1 2)))) 893 (should-error (equal (cyc2 1 2) (cyc2 1 2))))
@@ -548,31 +897,529 @@
548 (should-error (nconc (cyc2 1 2) 'tail) :type 'circular-list)) 897 (should-error (nconc (cyc2 1 2) 'tail) :type 'circular-list))
549 898
550(ert-deftest plist-get/odd-number-of-elements () 899(ert-deftest plist-get/odd-number-of-elements ()
551 "Test that plist-get doesnt signal an error on degenerate plists." 900 "Test that `plist-get' doesn't signal an error on degenerate plists."
552 (should-not (plist-get '(:foo 1 :bar) :bar))) 901 (should-not (plist-get '(:foo 1 :bar) :bar)))
553 902
554(ert-deftest lax-plist-get/odd-number-of-elements ()
555 "Check for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=27726."
556 (should (equal (should-error (lax-plist-get '(:foo 1 :bar) :bar)
557 :type 'wrong-type-argument)
558 '(wrong-type-argument plistp (:foo 1 :bar)))))
559
560(ert-deftest plist-put/odd-number-of-elements () 903(ert-deftest plist-put/odd-number-of-elements ()
561 "Check for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=27726." 904 "Check for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=27726."
562 (should (equal (should-error (plist-put '(:foo 1 :bar) :zot 2) 905 (should (equal (should-error (plist-put '(:foo 1 :bar) :zot 2)
563 :type 'wrong-type-argument) 906 :type 'wrong-type-argument)
564 '(wrong-type-argument plistp (:foo 1 :bar))))) 907 '(wrong-type-argument plistp (:foo 1 :bar)))))
565 908
566(ert-deftest lax-plist-put/odd-number-of-elements ()
567 "Check for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=27726."
568 (should (equal (should-error (lax-plist-put '(:foo 1 :bar) :zot 2)
569 :type 'wrong-type-argument)
570 '(wrong-type-argument plistp (:foo 1 :bar)))))
571
572(ert-deftest plist-member/improper-list () 909(ert-deftest plist-member/improper-list ()
573 "Check for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=27726." 910 "Check for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=27726."
574 (should (equal (should-error (plist-member '(:foo 1 . :bar) :qux) 911 (should (equal (should-error (plist-member '(:foo 1 . :bar) :qux)
575 :type 'wrong-type-argument) 912 :type 'wrong-type-argument)
576 '(wrong-type-argument plistp (:foo 1 . :bar))))) 913 '(wrong-type-argument plistp (:foo 1 . :bar)))))
577 914
578(provide 'fns-tests) 915(ert-deftest test-string-distance ()
916 "Test `string-distance' behavior."
917 ;; ASCII characters are always fine
918 (should (equal 1 (string-distance "heelo" "hello")))
919 (should (equal 2 (string-distance "aeelo" "hello")))
920 (should (equal 0 (string-distance "ab" "ab" t)))
921 (should (equal 1 (string-distance "ab" "abc" t)))
922
923 ;; string containing hanzi character, compare by byte
924 (should (equal 6 (string-distance "ab" "ab我她" t)))
925 (should (equal 3 (string-distance "ab" "a我b" t)))
926 (should (equal 3 (string-distance "我" "她" t)))
927
928 ;; string containing hanzi character, compare by character
929 (should (equal 2 (string-distance "ab" "ab我她")))
930 (should (equal 1 (string-distance "ab" "a我b")))
931 (should (equal 1 (string-distance "我" "她")))
932
933 ;; correct behavior with empty strings
934 (should (equal 0 (string-distance "" "")))
935 (should (equal 0 (string-distance "" "" t)))
936 (should (equal 1 (string-distance "x" "")))
937 (should (equal 1 (string-distance "x" "" t)))
938 (should (equal 1 (string-distance "" "x")))
939 (should (equal 1 (string-distance "" "x" t))))
940
941(ert-deftest test-bignum-eql ()
942 "Test that `eql' works for bignums."
943 (let ((x (+ most-positive-fixnum 1))
944 (y (+ most-positive-fixnum 1)))
945 (should (eq x x))
946 (should (eql x y))
947 (should (equal x y))
948 (should-not (eql x 0.0e+NaN))
949 (should (memql x (list y)))))
950
951(ert-deftest test-bignum-hash ()
952 "Test that hash tables work for bignums."
953 ;; Make two bignums that are eql but not eq.
954 (let ((b1 (1+ most-positive-fixnum))
955 (b2 (1+ most-positive-fixnum)))
956 (dolist (test '(eq eql equal))
957 (let ((hash (make-hash-table :test test)))
958 (puthash b1 t hash)
959 (should (eq (gethash b2 hash)
960 (funcall test b1 b2)))))))
961
962(ert-deftest test-nthcdr-simple ()
963 (should (eq (nthcdr 0 'x) 'x))
964 (should (eq (nthcdr 1 '(x . y)) 'y))
965 (should (eq (nthcdr 2 '(x y . z)) 'z)))
966
967(ert-deftest test-nthcdr-circular ()
968 (dolist (len '(1 2 5 37 120 997 1024))
969 (let ((cycle (make-list len nil)))
970 (setcdr (last cycle) cycle)
971 (dolist (n (list (1- most-negative-fixnum) most-negative-fixnum
972 -1 0 1
973 (1- len) len (1+ len)
974 most-positive-fixnum (1+ most-positive-fixnum)
975 (* 2 most-positive-fixnum)
976 (* most-positive-fixnum most-positive-fixnum)
977 (ash 1 12345)))
978 (let ((a (nthcdr n cycle))
979 (b (if (<= n 0) cycle (nthcdr (mod n len) cycle))))
980 (should (equal (list (eq a b) n len)
981 (list t n len))))))))
982
983(ert-deftest test-proper-list-p ()
984 "Test `proper-list-p' behavior."
985 (dotimes (length 4)
986 ;; Proper and dotted lists.
987 (let ((list (make-list length 0)))
988 (should (= (proper-list-p list) length))
989 (should (not (proper-list-p (nconc list 0)))))
990 ;; Circular lists.
991 (dotimes (n (1+ length))
992 (let ((circle (make-list (1+ length) 0)))
993 (should (not (proper-list-p (nconc circle (nthcdr n circle))))))))
994 ;; Atoms.
995 (should (not (proper-list-p 0)))
996 (should (not (proper-list-p "")))
997 (should (not (proper-list-p [])))
998 (should (not (proper-list-p (make-bool-vector 0 nil))))
999 (should (not (proper-list-p (make-symbol "a")))))
1000
1001(ert-deftest test-hash-function-that-mutates-hash-table ()
1002 (define-hash-table-test 'badeq 'eq 'bad-hash)
1003 (let ((h (make-hash-table :test 'badeq :size 1 :rehash-size 1)))
1004 (defun bad-hash (k)
1005 (if (eq k 100)
1006 (clrhash h))
1007 (sxhash-eq k))
1008 (should-error
1009 (dotimes (k 200)
1010 (puthash k k h)))
1011 (should (= 100 (hash-table-count h)))))
1012
1013(ert-deftest test-sxhash-equal ()
1014 (should (= (sxhash-equal (* most-positive-fixnum most-negative-fixnum))
1015 (sxhash-equal (* most-positive-fixnum most-negative-fixnum))))
1016 (should (= (sxhash-equal (make-string 1000 ?a))
1017 (sxhash-equal (make-string 1000 ?a))))
1018 (should (= (sxhash-equal (point-marker))
1019 (sxhash-equal (point-marker))))
1020 (should (= (sxhash-equal (make-vector 1000 (make-string 10 ?a)))
1021 (sxhash-equal (make-vector 1000 (make-string 10 ?a)))))
1022 (should (= (sxhash-equal (make-bool-vector 1000 t))
1023 (sxhash-equal (make-bool-vector 1000 t))))
1024 (should (= (sxhash-equal (make-char-table nil (make-string 10 ?a)))
1025 (sxhash-equal (make-char-table nil (make-string 10 ?a)))))
1026 (should (= (sxhash-equal (record 'a (make-string 10 ?a)))
1027 (sxhash-equal (record 'a (make-string 10 ?a))))))
1028
1029(ert-deftest test-secure-hash ()
1030 (should (equal (secure-hash 'md5 "foobar")
1031 "3858f62230ac3c915f300c664312c63f"))
1032 (should (equal (secure-hash 'sha1 "foobar")
1033 "8843d7f92416211de9ebb963ff4ce28125932878"))
1034 (should (equal (secure-hash 'sha224 "foobar")
1035 "de76c3e567fca9d246f5f8d3b2e704a38c3c5e258988ab525f941db8"))
1036 (should (equal (secure-hash 'sha256 "foobar")
1037 (concat "c3ab8ff13720e8ad9047dd39466b3c89"
1038 "74e592c2fa383d4a3960714caef0c4f2")))
1039 (should (equal (secure-hash 'sha384 "foobar")
1040 (concat "3c9c30d9f665e74d515c842960d4a451c83a0125fd3de739"
1041 "2d7b37231af10c72ea58aedfcdf89a5765bf902af93ecf06")))
1042 (should (equal (secure-hash 'sha512 "foobar")
1043 (concat "0a50261ebd1a390fed2bf326f2673c145582a6342d5"
1044 "23204973d0219337f81616a8069b012587cf5635f69"
1045 "25f1b56c360230c19b273500ee013e030601bf2425")))
1046 ;; Test that a call to getrandom returns the right format.
1047 ;; This does not test randomness; it's merely a format check.
1048 (should (string-match "\\`[0-9a-f]\\{128\\}\\'"
1049 (secure-hash 'sha512 'iv-auto 100))))
1050
1051(ert-deftest test-vector-delete ()
1052 (let ((v1 (make-vector 1000 1)))
1053 (should (equal (delete t [nil t]) [nil]))
1054 (should (equal (delete 1 v1) (vector)))
1055 (should (equal (delete 2 v1) v1))))
1056
1057(ert-deftest string-search ()
1058 (should (equal (string-search "zot" "foobarzot") 6))
1059 (should (equal (string-search "foo" "foobarzot") 0))
1060 (should (not (string-search "fooz" "foobarzot")))
1061 (should (not (string-search "zot" "foobarzo")))
1062 (should (equal (string-search "ab" "ab") 0))
1063 (should (equal (string-search "ab\0" "ab") nil))
1064 (should (equal (string-search "ab" "abababab" 3) 4))
1065 (should (equal (string-search "ab" "ababac" 3) nil))
1066 (should (equal (string-search "aaa" "aa") nil))
1067 (let ((case-fold-search t))
1068 (should (equal (string-search "ab" "AB") nil)))
1069
1070 (should (equal
1071 (string-search (make-string 2 130)
1072 (concat "helló" (make-string 5 130 t) "bár"))
1073 5))
1074 (should (equal
1075 (string-search (make-string 2 127)
1076 (concat "helló" (make-string 5 127 t) "bár"))
1077 5))
1078
1079 (should (equal (string-search "\377" "a\377ø") 1))
1080 (should (equal (string-search "\377" "a\377a") 1))
1081
1082 (should (not (string-search (make-string 1 255) "a\377ø")))
1083 (should (not (string-search (make-string 1 255) "a\377a")))
1084
1085 (should (equal (string-search "fóo" "zotfóo") 3))
1086
1087 (should (equal (string-search (string-to-multibyte "\377") "ab\377c") 2))
1088 (should (equal (string-search "\303" "aøb") nil))
1089 (should (equal (string-search "\270" "aøb") nil))
1090 (should (equal (string-search "ø" "\303\270") nil))
1091 (should (equal (string-search "ø" (make-string 32 ?a)) nil))
1092 (should (equal (string-search "ø" (string-to-multibyte (make-string 32 ?a)))
1093 nil))
1094 (should (equal (string-search "o" (string-to-multibyte
1095 (apply #'string
1096 (number-sequence ?a ?z))))
1097 14))
1098
1099 (should (equal (string-search "a\U00010f98z" "a\U00010f98a\U00010f98z") 2))
1100
1101 (should-error (string-search "a" "abc" -1))
1102 (should-error (string-search "a" "abc" 4))
1103 (should-error (string-search "a" "abc" 100000000000))
1104
1105 (should (equal (string-search "a" "aaa" 3) nil))
1106 (should (equal (string-search "aa" "aa" 1) nil))
1107 (should (equal (string-search "\0" "") nil))
1108
1109 (should (equal (string-search "" "") 0))
1110 (should-error (string-search "" "" 1))
1111 (should (equal (string-search "" "abc") 0))
1112 (should (equal (string-search "" "abc" 2) 2))
1113 (should (equal (string-search "" "abc" 3) 3))
1114 (should-error (string-search "" "abc" 4))
1115 (should-error (string-search "" "abc" -1))
1116
1117 (should-not (string-search "ø" "foo\303\270"))
1118 (should-not (string-search "\303\270" "ø"))
1119 (should-not (string-search "\370" "ø"))
1120 (should-not (string-search (string-to-multibyte "\370") "ø"))
1121 (should-not (string-search "ø" "\370"))
1122 (should-not (string-search "ø" (string-to-multibyte "\370")))
1123 (should-not (string-search "\303\270" "\370"))
1124 (should-not (string-search (string-to-multibyte "\303\270") "\370"))
1125 (should-not (string-search "\303\270" (string-to-multibyte "\370")))
1126 (should-not (string-search (string-to-multibyte "\303\270")
1127 (string-to-multibyte "\370")))
1128 (should-not (string-search "\370" "\303\270"))
1129 (should-not (string-search (string-to-multibyte "\370") "\303\270"))
1130 (should-not (string-search "\370" (string-to-multibyte "\303\270")))
1131 (should-not (string-search (string-to-multibyte "\370")
1132 (string-to-multibyte "\303\270")))
1133 (should (equal (string-search (string-to-multibyte "o\303\270") "foo\303\270")
1134 2))
1135 (should (equal (string-search "\303\270" "foo\303\270") 3)))
1136
1137(ert-deftest object-intervals ()
1138 (should (equal (object-intervals (propertize "foo" 'bar 'zot))
1139 '((0 3 (bar zot)))))
1140 (should (equal (object-intervals (concat (propertize "foo" 'bar 'zot)
1141 (propertize "foo" 'gazonk "gazonk")))
1142 '((0 3 (bar zot)) (3 6 (gazonk "gazonk")))))
1143 (should (equal
1144 (with-temp-buffer
1145 (insert "foobar")
1146 (put-text-property 1 3 'foo 1)
1147 (put-text-property 3 6 'bar 2)
1148 (put-text-property 2 5 'zot 3)
1149 (object-intervals (current-buffer)))
1150 '((0 1 (foo 1)) (1 2 (zot 3 foo 1)) (2 4 (zot 3 bar 2))
1151 (4 5 (bar 2)) (5 6 nil)))))
1152
1153(ert-deftest length-equals-tests ()
1154 (should-not (length< (list 1 2 3) 2))
1155 (should-not (length< (list 1 2 3) 3))
1156 (should (length< (list 1 2 3) 4))
1157
1158 (should-not (length< "abc" 2))
1159 (should-not (length< "abc" 3))
1160 (should (length< "abc" 4))
1161
1162 (should (length> (list 1 2 3) 2))
1163 (should-not (length> (list 1 2 3) 3))
1164 (should-not (length> (list 1 2 3) 4))
1165
1166 (should (length> "abc" 2))
1167 (should-not (length> "abc" 3))
1168 (should-not (length> "abc" 4))
1169
1170 (should-not (length= (list 1 2 3) 2))
1171 (should (length= (list 1 2 3) 3))
1172 (should-not (length= (list 1 2 3) 4))
1173
1174 (should-not (length= "abc" 2))
1175 (should (length= "abc" 3))
1176 (should-not (length= "abc" 4))
1177
1178 (should-not (length< (list 1 2 3) -1))
1179 (should-not (length< (list 1 2 3) 0))
1180 (should-not (length< (list 1 2 3) -10))
1181
1182 (should (length> (list 1 2 3) -1))
1183 (should (length> (list 1 2 3) 0))
1184
1185 (should-not (length= (list 1 2 3) -1))
1186 (should-not (length= (list 1 2 3) 0))
1187 (should-not (length= (list 1 2 3) 1))
1188
1189 (should-error
1190 (let ((list (list 1)))
1191 (setcdr list list)
1192 (length< list #x1fffe))))
1193
1194(defun approx-equal (list1 list2)
1195 (and (equal (length list1) (length list2))
1196 (cl-loop for v1 in list1
1197 for v2 in list2
1198 when (not (or (= v1 v2)
1199 (< (abs (- v1 v2)) 0.1)))
1200 return nil
1201 finally return t)))
1202
1203(ert-deftest test-buffer-line-stats-nogap ()
1204 (with-temp-buffer
1205 (insert "")
1206 (should (approx-equal (buffer-line-statistics) '(0 0 0))))
1207 (with-temp-buffer
1208 (insert "123\n")
1209 (should (approx-equal (buffer-line-statistics) '(1 3 3))))
1210 (with-temp-buffer
1211 (insert "123\n12345\n123\n")
1212 (should (approx-equal (buffer-line-statistics) '(3 5 3.66))))
1213 (with-temp-buffer
1214 (insert "123\n12345\n123")
1215 (should (approx-equal (buffer-line-statistics) '(3 5 3.66))))
1216 (with-temp-buffer
1217 (insert "123\n12345")
1218 (should (approx-equal (buffer-line-statistics) '(2 5 4))))
1219
1220 (with-temp-buffer
1221 (insert "123\n12é45\n123\n")
1222 (should (approx-equal (buffer-line-statistics) '(3 6 4))))
1223
1224 (with-temp-buffer
1225 (insert "\n\n\n")
1226 (should (approx-equal (buffer-line-statistics) '(3 0 0)))))
1227
1228(ert-deftest test-buffer-line-stats-gap ()
1229 (with-temp-buffer
1230 (dotimes (_ 1000)
1231 (insert "12345678901234567890123456789012345678901234567890\n"))
1232 (goto-char (point-min))
1233 ;; This should make a gap appear.
1234 (insert "123\n")
1235 (delete-region (point-min) (point))
1236 (should (approx-equal (buffer-line-statistics) '(1000 50 50.0))))
1237 (with-temp-buffer
1238 (dotimes (_ 1000)
1239 (insert "12345678901234567890123456789012345678901234567890\n"))
1240 (goto-char (point-min))
1241 (insert "123\n")
1242 (should (approx-equal (buffer-line-statistics) '(1001 50 49.9))))
1243 (with-temp-buffer
1244 (dotimes (_ 1000)
1245 (insert "12345678901234567890123456789012345678901234567890\n"))
1246 (goto-char (point-min))
1247 (insert "123\n")
1248 (goto-char (point-max))
1249 (insert "fóo")
1250 (should (approx-equal (buffer-line-statistics) '(1002 50 49.9)))))
1251
1252(ert-deftest test-line-number-at-position ()
1253 (with-temp-buffer
1254 (insert (make-string 10 ?\n))
1255 (should (= (line-number-at-pos (point)) 11))
1256 (should (= (line-number-at-pos nil) 11))
1257 (should-error (line-number-at-pos -1))
1258 (should-error (line-number-at-pos 100))))
1259
1260(defun fns-tests-concat (&rest args)
1261 ;; Dodge the byte-compiler's partial evaluation of `concat' with
1262 ;; constant arguments.
1263 (apply #'concat args))
1264
1265(ert-deftest fns-concat ()
1266 (should (equal (fns-tests-concat) ""))
1267 (should (equal (fns-tests-concat "") ""))
1268 (should (equal (fns-tests-concat nil) ""))
1269 (should (equal (fns-tests-concat []) ""))
1270 (should (equal (fns-tests-concat [97 98]) "ab"))
1271 (should (equal (fns-tests-concat '(97 98)) "ab"))
1272 (should (equal (fns-tests-concat "ab" '(99 100) nil [101 102] "gh")
1273 "abcdefgh"))
1274 (should (equal (fns-tests-concat "Ab" "\200" "cd") "Ab\200cd"))
1275 (should (equal (fns-tests-concat "aB" "\200" "çd") "aB\200çd"))
1276 (should (equal (fns-tests-concat "AB" (string-to-multibyte "\200") "cd")
1277 (string-to-multibyte "AB\200cd")))
1278 (should (equal (fns-tests-concat "ab" '(#xe5) [255] "cd") "abåÿcd"))
1279 (should (equal (fns-tests-concat '(#x3fffff) [#x3fff80] "xy") "\377\200xy"))
1280 (should (equal (fns-tests-concat '(#x3fffff) [#x3fff80] "xy§") "\377\200xy§"))
1281 (should (equal-including-properties
1282 (fns-tests-concat #("abc" 0 3 (a 1)) #("de" 0 2 (a 1)))
1283 #("abcde" 0 5 (a 1))))
1284 (should (equal-including-properties
1285 (fns-tests-concat #("abc" 0 3 (a 1)) "§ü" #("çå" 0 2 (b 2)))
1286 #("abc§üçå" 0 3 (a 1) 5 7 (b 2))))
1287 (should-error (fns-tests-concat "a" '(98 . 99))
1288 :type 'wrong-type-argument)
1289 (let ((loop (list 66 67)))
1290 (setcdr (cdr loop) loop)
1291 (should-error (fns-tests-concat "A" loop)
1292 :type 'circular-list)))
1293
1294(ert-deftest fns-vconcat ()
1295 (should (equal (vconcat) []))
1296 (should (equal (vconcat nil) []))
1297 (should (equal (vconcat "") []))
1298 (should (equal (vconcat [1 2 3]) [1 2 3]))
1299 (should (equal (vconcat '(1 2 3)) [1 2 3]))
1300 (should (equal (vconcat "ABC") [65 66 67]))
1301 (should (equal (vconcat "ü§") [252 167]))
1302 (should (equal (vconcat [1 2 3] nil '(4 5) "AB" "å"
1303 "\377" (string-to-multibyte "\377")
1304 (bool-vector t nil nil t nil))
1305 [1 2 3 4 5 65 66 #xe5 255 #x3fffff t nil nil t nil]))
1306 (should-error (vconcat [1] '(2 . 3))
1307 :type 'wrong-type-argument)
1308 (let ((loop (list 1 2)))
1309 (setcdr (cdr loop) loop)
1310 (should-error (vconcat [1] loop)
1311 :type 'circular-list)))
1312
1313(ert-deftest fns-append ()
1314 (should (equal (append) nil))
1315 (should (equal (append 'tail) 'tail))
1316 (should (equal (append [1 2 3] nil '(4 5) "AB" "å"
1317 "\377" (string-to-multibyte "\377")
1318 (bool-vector t nil nil t nil)
1319 '(9 10))
1320 '(1 2 3 4 5 65 66 #xe5 255 #x3fffff t nil nil t nil 9 10)))
1321 (should (equal (append '(1 2) '(3 4) 'tail)
1322 '(1 2 3 4 . tail)))
1323 (should-error (append '(1 . 2) '(3))
1324 :type 'wrong-type-argument)
1325 (let ((loop (list 1 2)))
1326 (setcdr (cdr loop) loop)
1327 (should-error (append loop '(end))
1328 :type 'circular-list)))
1329
1330(ert-deftest test-plist ()
1331 (let ((plist '(:a "b")))
1332 (setq plist (plist-put plist :b "c"))
1333 (should (equal (plist-get plist :b) "c"))
1334 (should (equal (plist-member plist :b) '(:b "c"))))
1335
1336 (let ((plist '("1" "2" "a" "b")))
1337 (setq plist (plist-put plist (copy-sequence "a") "c"))
1338 (should-not (equal (plist-get plist (copy-sequence "a")) "c"))
1339 (should-not (equal (plist-member plist (copy-sequence "a")) '("a" "c"))))
1340
1341 (let ((plist '("1" "2" "a" "b")))
1342 (setq plist (plist-put plist (copy-sequence "a") "c" #'equal))
1343 (should (equal (plist-get plist (copy-sequence "a") #'equal) "c"))
1344 (should (equal (plist-member plist (copy-sequence "a") #'equal)
1345 '("a" "c")))))
1346
1347(ert-deftest fns--string-to-unibyte-multibyte ()
1348 (dolist (str (list "" "a" "abc" "a\x00\x7fz" "a\xaa\xbbz" "\x80\xdd\xff"
1349 (apply #'unibyte-string (number-sequence 0 255))))
1350 (ert-info ((prin1-to-string str) :prefix "str: ")
1351 (should-not (multibyte-string-p str))
1352 (let* ((u (string-to-unibyte str)) ; should be identity
1353 (m (string-to-multibyte u)) ; lossless conversion
1354 (mm (string-to-multibyte m)) ; should be identity
1355 (uu (string-to-unibyte m)) ; also lossless
1356 (ml (mapcar (lambda (c) (if (<= c #x7f) c (+ c #x3fff00))) u)))
1357 (should-not (multibyte-string-p u))
1358 (should (multibyte-string-p m))
1359 (should (multibyte-string-p mm))
1360 (should-not (multibyte-string-p uu))
1361 (should (equal str u))
1362 (should (equal m mm))
1363 (should (equal str uu))
1364 (should (equal (append m nil) ml)))))
1365 (should-error (string-to-unibyte "å"))
1366 (should-error (string-to-unibyte "ABC∀BC")))
1367
1368(defun fns-tests--take-ref (n list)
1369 "Reference implementation of `take'."
1370 (named-let loop ((m n) (tail list) (ac nil))
1371 (if (and (> m 0) tail)
1372 (loop (1- m) (cdr tail) (cons (car tail) ac))
1373 (nreverse ac))))
1374
1375(ert-deftest fns--take-ntake ()
1376 "Test `take' and `ntake'."
1377 ;; Check errors and edge cases.
1378 (should-error (take 'x '(a)))
1379 (should-error (ntake 'x '(a)))
1380 (should-error (take 1 'a))
1381 (should-error (ntake 1 'a))
1382 (should-error (take 2 '(a . b)))
1383 (should-error (ntake 2 '(a . b)))
1384 ;; Tolerate non-lists for a count of zero.
1385 (should (equal (take 0 'a) nil))
1386 (should (equal (ntake 0 'a) nil))
1387 ;; But not non-numbers for empty lists.
1388 (should-error (take 'x nil))
1389 (should-error (ntake 'x nil))
1390
1391 (dolist (list '(nil (a) (a b) (a b c) (a b c d) (a . b) (a b . c)))
1392 (ert-info ((prin1-to-string list) :prefix "list: ")
1393 (let ((max (if (proper-list-p list)
1394 (+ 2 (length list))
1395 (safe-length list))))
1396 (dolist (n (number-sequence -1 max))
1397 (ert-info ((prin1-to-string n) :prefix "n: ")
1398 (let* ((l (copy-tree list))
1399 (ref (fns-tests--take-ref n l)))
1400 (should (equal (take n l) ref))
1401 (should (equal l list))
1402 (should (equal (ntake n l) ref))))))))
1403
1404 ;; Circular list.
1405 (let ((list (list 'a 'b 'c)))
1406 (setcdr (nthcdr 2 list) (cdr list)) ; list now (a b c b c b c ...)
1407 (should (equal (take 0 list) nil))
1408 (should (equal (take 1 list) '(a)))
1409 (should (equal (take 2 list) '(a b)))
1410 (should (equal (take 3 list) '(a b c)))
1411 (should (equal (take 4 list) '(a b c b)))
1412 (should (equal (take 5 list) '(a b c b c)))
1413 (should (equal (take 10 list) '(a b c b c b c b c b)))
1414
1415 (should (equal (ntake 10 list) '(a b))))
1416
1417 ;; Bignum N argument.
1418 (let ((list (list 'a 'b 'c)))
1419 (should (equal (take (+ most-positive-fixnum 1) list) '(a b c)))
1420 (should (equal (take (- most-negative-fixnum 1) list) nil))
1421 (should (equal (ntake (+ most-positive-fixnum 1) list) '(a b c)))
1422 (should (equal (ntake (- most-negative-fixnum 1) list) nil))
1423 (should (equal list '(a b c)))))
1424
1425;;; fns-tests.el ends here
diff --git a/test/src/font-tests.el b/test/src/font-tests.el
index d86139b0f19..7e9669c6513 100644
--- a/test/src/font-tests.el
+++ b/test/src/font-tests.el
@@ -1,6 +1,6 @@
1;;; font-tests.el --- Test suite for font-related functions. 1;;; font-tests.el --- Test suite for font-related functions. -*- lexical-binding: t -*-
2 2
3;; Copyright (C) 2011-2017 Free Software Foundation, Inc. 3;; Copyright (C) 2011-2022 Free Software Foundation, Inc.
4 4
5;; Author: Chong Yidong <cyd@stupidchicken.com> 5;; Author: Chong Yidong <cyd@stupidchicken.com>
6;; Keywords: internal 6;; Keywords: internal
@@ -96,8 +96,7 @@ expected font properties from parsing NAME.")
96(put 'font-parse-check 'ert-explainer 'font-parse-explain) 96(put 'font-parse-check 'ert-explainer 'font-parse-explain)
97 97
98(defun font-parse-explain (name prop expected) 98(defun font-parse-explain (name prop expected)
99 (let ((result (font-get (font-spec :name name) prop)) 99 (let ((propname (symbol-name prop)))
100 (propname (symbol-name prop)))
101 (format "Parsing `%s': expected %s `%s', got `%s'." 100 (format "Parsing `%s': expected %s `%s', got `%s'."
102 name (substring propname 1) expected 101 name (substring propname 1) expected
103 (font-get (font-spec :name name) prop)))) 102 (font-get (font-spec :name name) prop))))
@@ -159,9 +158,30 @@ expected font properties from parsing NAME.")
159 (insert "\n")))) 158 (insert "\n"))))
160 (goto-char (point-min))) 159 (goto-char (point-min)))
161 160
162;; Local Variables: 161(ert-deftest font-parse-xlfd-test ()
163;; no-byte-compile: t 162 ;; Normal number of segments.
164;; End: 163 (should (equal (font-get
164 (font-spec :name "-GNU -FreeSans-semibold-italic-normal-*-*-*-*-*-*-0-iso10646-1")
165 :family)
166 'FreeSans))
167 (should (equal (font-get
168 (font-spec :name "-GNU -FreeSans-semibold-italic-normal-*-*-*-*-*-*-0-iso10646-1")
169 :foundry)
170 'GNU\ ))
171 ;; Dash in the family name.
172 (should (equal (font-get
173 (font-spec :name "-Take-mikachan-PS-normal-normal-normal-*-*-*-*-*-*-0-iso10646-1")
174 :family)
175 'mikachan-PS))
176 (should (equal (font-get
177 (font-spec :name "-Take-mikachan-PS-normal-normal-normal-*-*-*-*-*-*-0-iso10646-1")
178 :weight)
179 'normal))
180 ;; Synthetic test.
181 (should (equal (font-get
182 (font-spec :name "-foundry-name-with-lots-of-dashes-normal-normal-normal-*-*-*-*-*-*-0-iso10646-1")
183 :family)
184 'name-with-lots-of-dashes)))
165 185
166(provide 'font-tests) 186(provide 'font-tests)
167;;; font-tests.el ends here. 187;;; font-tests.el ends here.
diff --git a/test/src/image-tests.el b/test/src/image-tests.el
new file mode 100644
index 00000000000..d1a4dad37b9
--- /dev/null
+++ b/test/src/image-tests.el
@@ -0,0 +1,69 @@
1;;; image-tests.el --- Tests for image.c -*- lexical-binding: t -*-
2
3;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
4
5;; Author: Stefan Kangas <stefankangas@gmail.com>
6
7;; This file is part of GNU Emacs.
8
9;; GNU Emacs is free software: you can redistribute it and/or modify
10;; it under the terms of the GNU General Public License as published by
11;; the Free Software Foundation, either version 3 of the License, or
12;; (at your option) any later version.
13
14;; GNU Emacs is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;; GNU General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
20;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
21
22;;; Code:
23
24(require 'ert)
25
26(declare-function image-size "image.c" (spec &optional pixels frame))
27(declare-function image-mask-p "image.c" (spec &optional frame))
28(declare-function image-metadata "image.c" (spec &optional frame))
29
30(defconst image-tests--images
31 `((gif . ,(expand-file-name "test/data/image/black.gif"
32 source-directory))
33 (jpeg . ,(expand-file-name "test/data/image/black.jpg"
34 source-directory))
35 (pbm . ,(find-image '((:file "splash.svg" :type svg))))
36 (png . ,(find-image '((:file "splash.png" :type png))))
37 (svg . ,(find-image '((:file "splash.pbm" :type pbm))))
38 (tiff . ,(expand-file-name
39 "nextstep/GNUstep/Emacs.base/Resources/emacs.tiff"
40 source-directory))
41 (webp . ,(expand-file-name "test/data/image/black.webp"
42 source-directory))
43 (xbm . ,(find-image '((:file "gnus/gnus.xbm" :type xbm))))
44 (xpm . ,(find-image '((:file "splash.xpm" :type xpm))))))
45
46(ert-deftest image-tests-image-size/error-on-nongraphical-display ()
47 (skip-unless (not (display-images-p)))
48 (should-error (image-size 'invalid-spec)))
49
50(ert-deftest image-tests-image-mask-p/error-on-nongraphical-display ()
51 (skip-unless (not (display-images-p)))
52 (should-error (image-mask-p (cdr (assq 'xpm image-tests--images)))))
53
54(ert-deftest image-tests-image-metadata/error-on-nongraphical-display ()
55 (skip-unless (not (display-images-p)))
56 (should-error (image-metadata (cdr (assq 'xpm image-tests--images)))))
57
58(ert-deftest image-tests-imagemagick-types ()
59 (skip-unless (fboundp 'imagemagick-types))
60 (when (fboundp 'imagemagick-types)
61 (should (listp (imagemagick-types)))))
62
63(ert-deftest image-tests-init-image-library ()
64 (skip-unless (fboundp 'init-image-library))
65 (declare-function init-image-library "image.c" (type))
66 (should (init-image-library 'pbm)) ; built-in
67 (should-not (init-image-library 'invalid-image-type)))
68
69;;; image-tests.el ends here
diff --git a/test/src/indent-tests.el b/test/src/indent-tests.el
new file mode 100644
index 00000000000..e6b1fde6e18
--- /dev/null
+++ b/test/src/indent-tests.el
@@ -0,0 +1,61 @@
1;;; indent-tests.el --- tests for src/indent.c -*- lexical-binding:t -*-
2
3;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
4
5;; This file is part of GNU Emacs.
6
7;; GNU Emacs is free software: you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation, either version 3 of the License, or
10;; (at your option) any later version.
11
12;; GNU Emacs is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; GNU General Public License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
19
20;;; Commentary:
21
22;;; Code:
23
24(ert-deftest indent-tests-move-to-column-invis-1tab ()
25 "Test `move-to-column' when a TAB is followed by invisible text."
26 (should
27 (string=
28 (with-temp-buffer
29 (insert "\tLine starting with INVISIBLE text after TAB\n")
30 (add-text-properties 2 21 '(invisible t))
31 (goto-char (point-min))
32 (move-to-column 7 t)
33 (buffer-substring-no-properties 1 8))
34 " ")))
35
36(ert-deftest indent-tests-move-to-column-invis-2tabs ()
37 "Test `move-to-column' when 2 TABs are followed by invisible text."
38 (should
39 (string=
40 (with-temp-buffer
41 (insert "\t\tLine starting with INVISIBLE text after TAB\n")
42 (add-text-properties 3 22 '(invisible t))
43 (goto-char (point-min))
44 (move-to-column 12 t)
45 (buffer-substring-no-properties 1 11))
46 "\t \tLine")))
47
48(ert-deftest indent-tests-move-to-column-invis-between-tabs ()
49 "Test `move-to-column' when 2 TABs are mixed with invisible text."
50 (should
51 (string=
52 (with-temp-buffer
53 (insert "\txxx\tLine starting with INVISIBLE text after TAB\n")
54 (add-text-properties 6 25 '(invisible t))
55 (add-text-properties 2 5 '(invisible t))
56 (goto-char (point-min))
57 (move-to-column 12 t)
58 (buffer-substring-no-properties 1 14))
59 "\txxx \tLine")))
60
61;;; indent-tests.el ends here
diff --git a/test/src/inotify-tests.el b/test/src/inotify-tests.el
index 9f8abb0ffdb..295b184be0e 100644
--- a/test/src/inotify-tests.el
+++ b/test/src/inotify-tests.el
@@ -1,6 +1,6 @@
1;;; inotify-tests.el --- Test suite for inotify. -*- lexical-binding: t -*- 1;;; inotify-tests.el --- Test suite for inotify. -*- lexical-binding: t -*-
2 2
3;; Copyright (C) 2012-2017 Free Software Foundation, Inc. 3;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
4 4
5;; Author: Rüdiger Sonderfeld <ruediger@c-plusplus.de> 5;; Author: Rüdiger Sonderfeld <ruediger@c-plusplus.de>
6;; Keywords: internal 6;; Keywords: internal
@@ -24,9 +24,11 @@
24;;; Code: 24;;; Code:
25 25
26(require 'ert) 26(require 'ert)
27(require 'ert-x)
27 28
28(declare-function inotify-add-watch "inotify.c" (file-name aspect callback)) 29(declare-function inotify-add-watch "inotify.c" (file-name aspect callback))
29(declare-function inotify-rm-watch "inotify.c" (watch-descriptor)) 30(declare-function inotify-rm-watch "inotify.c" (watch-descriptor))
31(declare-function inotify-valid-p "inotify.c" (watch-descriptor))
30 32
31(ert-deftest inotify-valid-p-simple () 33(ert-deftest inotify-valid-p-simple ()
32 "Simple tests for `inotify-valid-p'." 34 "Simple tests for `inotify-valid-p'."
@@ -37,8 +39,7 @@
37 39
38;; (ert-deftest filewatch-file-watch-aspects-check () 40;; (ert-deftest filewatch-file-watch-aspects-check ()
39;; "Test whether `file-watch' properly checks the aspects." 41;; "Test whether `file-watch' properly checks the aspects."
40;; (let ((temp-file (make-temp-file "filewatch-aspects"))) 42;; (ert-with-temp-file temp-file
41;; (should (stringp temp-file))
42;; (should-error (file-watch temp-file 'wrong nil) 43;; (should-error (file-watch temp-file 'wrong nil)
43;; :type 'error) 44;; :type 'error)
44;; (should-error (file-watch temp-file '(modify t) nil) 45;; (should-error (file-watch temp-file '(modify t) nil)
@@ -50,24 +51,22 @@
50 51
51(ert-deftest inotify-file-watch-simple () 52(ert-deftest inotify-file-watch-simple ()
52 "Test if watching a normal file works." 53 "Test if watching a normal file works."
53
54 (skip-unless (featurep 'inotify)) 54 (skip-unless (featurep 'inotify))
55 (let ((temp-file (make-temp-file "inotify-simple")) 55 (ert-with-temp-file temp-file
56 (events 0)) 56 (let ((events 0))
57 (let ((wd 57 (let ((wd
58 (inotify-add-watch temp-file t (lambda (_ev) 58 (inotify-add-watch temp-file t (lambda (_ev)
59 (setq events (1+ events)))))) 59 (setq events (1+ events))))))
60 (unwind-protect 60 (unwind-protect
61 (progn 61 (progn
62 (with-temp-file temp-file 62 (with-temp-file temp-file
63 (insert "Foo\n")) 63 (insert "Foo\n"))
64 (read-event nil nil 5) 64 (read-event nil nil 5)
65 (should (> events 0))) 65 (should (> events 0)))
66 (should (inotify-valid-p wd)) 66 (should (inotify-valid-p wd))
67 (inotify-rm-watch wd) 67 (inotify-rm-watch wd)
68 (should-not (inotify-valid-p wd)) 68 (should-not (inotify-valid-p wd)))))))
69 (delete-file temp-file)))))
70 69
71(provide 'inotify-tests) 70(provide 'inotify-tests)
72 71
73;;; inotify-tests.el ends here. 72;;; inotify-tests.el ends here
diff --git a/test/src/json-tests.el b/test/src/json-tests.el
new file mode 100644
index 00000000000..3560e1abc96
--- /dev/null
+++ b/test/src/json-tests.el
@@ -0,0 +1,343 @@
1;;; json-tests.el --- unit tests for json.c -*- lexical-binding: t; -*-
2
3;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
4
5;; This file is part of GNU Emacs.
6
7;; GNU Emacs is free software: you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation, either version 3 of the License, or
10;; (at your option) any later version.
11
12;; GNU Emacs is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; GNU General Public License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
19
20;;; Commentary:
21
22;; Unit tests for src/json.c.
23
24;;; Code:
25
26(require 'cl-lib)
27(require 'map)
28
29(declare-function json-serialize "json.c" (object &rest args))
30(declare-function json-insert "json.c" (object &rest args))
31(declare-function json-parse-string "json.c" (string &rest args))
32(declare-function json-parse-buffer "json.c" (&rest args))
33
34(define-error 'json-tests--error "JSON test error")
35
36(ert-deftest json-serialize/roundtrip ()
37 (skip-unless (fboundp 'json-serialize))
38 ;; The noncharacter U+FFFF should be passed through,
39 ;; cf. https://www.unicode.org/faq/private_use.html#noncharacters.
40 (let ((lisp [:null :false t 0 123 -456 3.75 "abc\uFFFFαβγ𝔸𝐁𝖢\"\\"])
41 (json "[null,false,true,0,123,-456,3.75,\"abc\uFFFFαβγ𝔸𝐁𝖢\\\"\\\\\"]"))
42 (should (equal (json-serialize lisp) json))
43 (with-temp-buffer
44 (json-insert lisp)
45 (should (equal (buffer-string) json))
46 (should (eobp)))
47 (should (equal (json-parse-string json) lisp))
48 (with-temp-buffer
49 (insert json)
50 (goto-char 1)
51 (should (equal (json-parse-buffer) lisp))
52 (should (eobp)))))
53
54(ert-deftest json-serialize/roundtrip-scalars ()
55 "Check that Bug#42994 is fixed."
56 (skip-unless (fboundp 'json-serialize))
57 (dolist (case '((:null "null")
58 (:false "false")
59 (t "true")
60 (0 "0")
61 (123 "123")
62 (-456 "-456")
63 (3.75 "3.75")
64 ;; The noncharacter U+FFFF should be passed through,
65 ;; cf. https://www.unicode.org/faq/private_use.html#noncharacters.
66 ("abc\uFFFFαβγ𝔸𝐁𝖢\"\\"
67 "\"abc\uFFFFαβγ𝔸𝐁𝖢\\\"\\\\\"")))
68 (cl-destructuring-bind (lisp json) case
69 (ert-info ((format "%S ↔ %S" lisp json))
70 (should (equal (json-serialize lisp) json))
71 (with-temp-buffer
72 (json-insert lisp)
73 (should (equal (buffer-string) json))
74 (should (eobp)))
75 (should (equal (json-parse-string json) lisp))
76 (with-temp-buffer
77 (insert json)
78 (goto-char 1)
79 (should (equal (json-parse-buffer) lisp))
80 (should (eobp)))))))
81
82(ert-deftest json-serialize/object ()
83 (skip-unless (fboundp 'json-serialize))
84 (let ((table (make-hash-table :test #'equal)))
85 (puthash "abc" [1 2 t] table)
86 (puthash "def" :null table)
87 (should (equal (json-serialize table)
88 "{\"abc\":[1,2,true],\"def\":null}")))
89 (should (equal (json-serialize '((abc . [1 2 t]) (def . :null)))
90 "{\"abc\":[1,2,true],\"def\":null}"))
91 (should (equal (json-serialize nil) "{}"))
92 (should (equal (json-serialize '((abc))) "{\"abc\":{}}"))
93 (should (equal (json-serialize '((a . 1) (b . 2) (a . 3)))
94 "{\"a\":1,\"b\":2}"))
95 (should-error (json-serialize '(abc)) :type 'wrong-type-argument)
96 (should-error (json-serialize '((a 1))) :type 'wrong-type-argument)
97 (should-error (json-serialize '((1 . 2))) :type 'wrong-type-argument)
98 (should-error (json-serialize '((a . 1) . b)) :type 'wrong-type-argument)
99 (should-error (json-serialize '#1=((a . 1) . #1#)) :type 'circular-list)
100 (should-error (json-serialize '(#1=(a #1#))))
101
102 (should (equal (json-serialize '(:abc [1 2 t] :def :null))
103 "{\"abc\":[1,2,true],\"def\":null}"))
104 (should (equal (json-serialize '(abc [1 2 t] :def :null))
105 "{\"abc\":[1,2,true],\"def\":null}"))
106 (should-error (json-serialize '#1=(:a 1 . #1#)) :type 'circular-list)
107 (should-error (json-serialize '#1=(:a 1 :b . #1#))
108 :type '(circular-list wrong-type-argument))
109 (should-error (json-serialize '(:foo "bar" (unexpected-alist-key . 1)))
110 :type 'wrong-type-argument)
111 (should-error (json-serialize '((abc . "abc") :unexpected-plist-key "key"))
112 :type 'wrong-type-argument)
113 (should-error (json-serialize '(:foo bar :odd-numbered))
114 :type 'wrong-type-argument)
115 (should (equal
116 (json-serialize
117 (list :detect-hash-table #s(hash-table test equal data ("bla" "ble"))
118 :detect-alist '((bla . "ble"))
119 :detect-plist '(:bla "ble")))
120 "\
121{\
122\"detect-hash-table\":{\"bla\":\"ble\"},\
123\"detect-alist\":{\"bla\":\"ble\"},\
124\"detect-plist\":{\"bla\":\"ble\"}\
125}")))
126
127(ert-deftest json-serialize/object-with-duplicate-keys ()
128 (skip-unless (fboundp 'json-serialize))
129 (let ((table (make-hash-table :test #'eq)))
130 (puthash (copy-sequence "abc") [1 2 t] table)
131 (puthash (copy-sequence "abc") :null table)
132 (should (equal (hash-table-count table) 2))
133 (should-error (json-serialize table) :type 'wrong-type-argument)))
134
135(ert-deftest json-parse-string/object ()
136 (skip-unless (fboundp 'json-parse-string))
137 (let ((input
138 "{ \"abc\" : [1, 2, true], \"def\" : null, \"abc\" : [9, false] }\n"))
139 (let ((actual (json-parse-string input)))
140 (should (hash-table-p actual))
141 (should (equal (hash-table-count actual) 2))
142 (should (equal (cl-sort (map-pairs actual) #'string< :key #'car)
143 '(("abc" . [9 :false]) ("def" . :null)))))
144 (should (equal (json-parse-string input :object-type 'alist)
145 '((abc . [9 :false]) (def . :null))))
146 (should (equal (json-parse-string input :object-type 'plist)
147 '(:abc [9 :false] :def :null)))))
148
149(ert-deftest json-parse-string/array ()
150 (skip-unless (fboundp 'json-parse-string))
151 (let ((input "[\"a\", 1, [\"b\", 2]]"))
152 (should (equal (json-parse-string input)
153 ["a" 1 ["b" 2]]))
154 (should (equal (json-parse-string input :array-type 'list)
155 '("a" 1 ("b" 2))))))
156
157(ert-deftest json-parse-string/string ()
158 (skip-unless (fboundp 'json-parse-string))
159 (should-error (json-parse-string "[\"formfeed\f\"]") :type 'json-parse-error)
160 (should (equal (json-parse-string "[\"foo \\\"bar\\\"\"]") ["foo \"bar\""]))
161 (should (equal (json-parse-string "[\"abcαβγ\"]") ["abcαβγ"]))
162 (should (equal (json-parse-string "[\"\\nasd\\u0444\\u044b\\u0432fgh\\t\"]")
163 ["\nasdфывfgh\t"]))
164 (should (equal (json-parse-string "[\"\\uD834\\uDD1E\"]") ["\U0001D11E"]))
165 (should-error (json-parse-string "foo") :type 'json-parse-error)
166 ;; FIXME: Is this the right behavior?
167 (should (equal (json-parse-string "[\"\u00C4\xC3\x84\"]") ["\u00C4\u00C4"])))
168
169(ert-deftest json-serialize/string ()
170 (skip-unless (fboundp 'json-serialize))
171 (should (equal (json-serialize ["foo"]) "[\"foo\"]"))
172 (should (equal (json-serialize ["a\n\fb"]) "[\"a\\n\\fb\"]"))
173 (should (equal (json-serialize ["\nasdфыв\u001f\u007ffgh\t"])
174 "[\"\\nasdфыв\\u001F\u007ffgh\\t\"]"))
175 (should (equal (json-serialize ["a\0b"]) "[\"a\\u0000b\"]"))
176 ;; FIXME: Is this the right behavior?
177 (should (equal (json-serialize ["\u00C4\xC3\x84"]) "[\"\u00C4\u00C4\"]")))
178
179(ert-deftest json-serialize/invalid-unicode ()
180 (skip-unless (fboundp 'json-serialize))
181 (should-error (json-serialize ["a\uDBBBb"]) :type 'wrong-type-argument)
182 (should-error (json-serialize ["u\x110000v"]) :type 'wrong-type-argument)
183 (should-error (json-serialize ["u\x3FFFFFv"]) :type 'wrong-type-argument)
184 (should-error (json-serialize ["u\xCCv"]) :type 'wrong-type-argument)
185 (should-error (json-serialize ["u\u00C4\xCCv"]) :type 'wrong-type-argument))
186
187(ert-deftest json-parse-string/null ()
188 (skip-unless (fboundp 'json-parse-string))
189 (should-error (json-parse-string "\x00") :type 'wrong-type-argument)
190 (should (json-parse-string "[\"a\\u0000b\"]"))
191 (let* ((string "{\"foo\":\"this is a string including a literal \\u0000\"}")
192 (data (json-parse-string string)))
193 (should (hash-table-p data))
194 (should (equal string (json-serialize data)))))
195
196(ert-deftest json-parse-string/invalid-unicode ()
197 "Some examples from
198https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt.
199Test with both unibyte and multibyte strings."
200 (skip-unless (fboundp 'json-parse-string))
201 ;; Invalid UTF-8 code unit sequences.
202 (should-error (json-parse-string "[\"\x80\"]") :type 'json-parse-error)
203 (should-error (json-parse-string "[\"\u00C4\x80\"]") :type 'json-parse-error)
204 (should-error (json-parse-string "[\"\xBF\"]") :type 'json-parse-error)
205 (should-error (json-parse-string "[\"\u00C4\xBF\"]") :type 'json-parse-error)
206 (should-error (json-parse-string "[\"\xFE\"]") :type 'json-parse-error)
207 (should-error (json-parse-string "[\"\u00C4\xFE\"]") :type 'json-parse-error)
208 (should-error (json-parse-string "[\"\xC0\xAF\"]") :type 'json-parse-error)
209 (should-error (json-parse-string "[\"\u00C4\xC0\xAF\"]")
210 :type 'json-parse-error)
211 (should-error (json-parse-string "[\"\u00C4\xC0\x80\"]")
212 :type 'json-parse-error)
213 ;; Surrogates.
214 (should-error (json-parse-string "[\"\uDB7F\"]")
215 :type 'json-parse-error)
216 (should-error (json-parse-string "[\"\xED\xAD\xBF\"]")
217 :type 'json-parse-error)
218 (should-error (json-parse-string "[\"\u00C4\xED\xAD\xBF\"]")
219 :type 'json-parse-error)
220 (should-error (json-parse-string "[\"\uDB7F\uDFFF\"]")
221 :type 'json-parse-error)
222 (should-error (json-parse-string "[\"\xED\xAD\xBF\xED\xBF\xBF\"]")
223 :type 'json-parse-error)
224 (should-error (json-parse-string "[\"\u00C4\xED\xAD\xBF\xED\xBF\xBF\"]")
225 :type 'json-parse-error))
226
227(ert-deftest json-parse-string/incomplete ()
228 (skip-unless (fboundp 'json-parse-string))
229 (should-error (json-parse-string "[123") :type 'json-end-of-file))
230
231(ert-deftest json-parse-string/trailing ()
232 (skip-unless (fboundp 'json-parse-string))
233 (should-error (json-parse-string "[123] [456]") :type 'json-trailing-content))
234
235(ert-deftest json-parse-buffer/incomplete ()
236 (skip-unless (fboundp 'json-parse-buffer))
237 (with-temp-buffer
238 (insert "[123")
239 (goto-char 1)
240 (should-error (json-parse-buffer) :type 'json-end-of-file)
241 (should (bobp))))
242
243(ert-deftest json-parse-buffer/trailing ()
244 (skip-unless (fboundp 'json-parse-buffer))
245 (with-temp-buffer
246 (insert "[123] [456]")
247 (goto-char 1)
248 (should (equal (json-parse-buffer) [123]))
249 (should-not (bobp))
250 (should (looking-at-p (rx " [456]" eos)))))
251
252(ert-deftest json-parse-with-custom-null-and-false-objects ()
253 (skip-unless (and (fboundp 'json-serialize)
254 (fboundp 'json-parse-string)))
255 (let* ((input
256 "{ \"abc\" : [9, false] , \"def\" : null }")
257 (output
258 (string-replace " " "" input)))
259 (should (equal (json-parse-string input
260 :object-type 'plist
261 :null-object :json-null
262 :false-object :json-false)
263 '(:abc [9 :json-false] :def :json-null)))
264 (should (equal (json-parse-string input
265 :object-type 'plist
266 :false-object :json-false)
267 '(:abc [9 :json-false] :def :null)))
268 (should (equal (json-parse-string input
269 :object-type 'alist
270 :null-object :zilch)
271 '((abc . [9 :false]) (def . :zilch))))
272 (should (equal (json-parse-string input
273 :object-type 'alist
274 :false-object nil
275 :null-object nil)
276 '((abc . [9 nil]) (def))))
277 (let* ((thingy '(1 2 3))
278 (retval (json-parse-string input
279 :object-type 'alist
280 :false-object thingy
281 :null-object nil)))
282 (should (equal retval `((abc . [9 ,thingy]) (def))))
283 (should (eq (elt (cdr (car retval)) 1) thingy)))
284 (should (equal output
285 (json-serialize '((abc . [9 :myfalse]) (def . :mynull))
286 :false-object :myfalse
287 :null-object :mynull)))
288 ;; :object-type is not allowed in json-serialize
289 (should-error (json-serialize '() :object-type 'alist))))
290
291(ert-deftest json-insert/signal ()
292 (skip-unless (fboundp 'json-insert))
293 (with-temp-buffer
294 (let ((calls 0))
295 (add-hook 'after-change-functions
296 (lambda (_begin _end _length)
297 (cl-incf calls)
298 (signal 'json-tests--error
299 '("Error in `after-change-functions'")))
300 :local)
301 (should-error
302 (json-insert '((a . "b") (c . 123) (d . [1 2 t :false])))
303 :type 'json-tests--error)
304 (should (equal calls 1)))))
305
306(ert-deftest json-insert/throw ()
307 (skip-unless (fboundp 'json-insert))
308 (with-temp-buffer
309 (let ((calls 0))
310 (add-hook 'after-change-functions
311 (lambda (_begin _end _length)
312 (cl-incf calls)
313 (throw 'test-tag 'throw-value))
314 :local)
315 (should
316 (equal
317 (catch 'test-tag
318 (json-insert '((a . "b") (c . 123) (d . [1 2 t :false]))))
319 'throw-value))
320 (should (equal calls 1)))))
321
322(ert-deftest json-serialize/bignum ()
323 (skip-unless (fboundp 'json-serialize))
324 (should (equal (json-serialize (vector (1+ most-positive-fixnum)
325 (1- most-negative-fixnum)))
326 (format "[%d,%d]"
327 (1+ most-positive-fixnum)
328 (1- most-negative-fixnum)))))
329
330(ert-deftest json-parse-string/wrong-type ()
331 "Check that Bug#42113 is fixed."
332 (skip-unless (fboundp 'json-parse-string))
333 (should-error (json-parse-string 1) :type 'wrong-type-argument))
334
335(ert-deftest json-serialize/wrong-hash-key-type ()
336 "Check that Bug#42113 is fixed."
337 (skip-unless (fboundp 'json-serialize))
338 (let ((table (make-hash-table :test #'eq)))
339 (puthash 1 2 table)
340 (should-error (json-serialize table) :type 'wrong-type-argument)))
341
342(provide 'json-tests)
343;;; json-tests.el ends here
diff --git a/test/src/keyboard-tests.el b/test/src/keyboard-tests.el
new file mode 100644
index 00000000000..d17c9d96a63
--- /dev/null
+++ b/test/src/keyboard-tests.el
@@ -0,0 +1,74 @@
1;;; keyboard-tests.el --- Tests for keyboard.c -*- lexical-binding: t -*-
2
3;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
4
5;; This file is part of GNU Emacs.
6
7;; GNU Emacs is free software: you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation, either version 3 of the License, or
10;; (at your option) any later version.
11
12;; GNU Emacs is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; GNU General Public License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
19
20;;; Code:
21
22(require 'ert)
23
24(ert-deftest keyboard-unread-command-events ()
25 "Test `unread-command-events'."
26 (let ((unread-command-events nil))
27 (should (equal (progn (push ?\C-a unread-command-events)
28 (read-event nil nil 1))
29 ?\C-a))
30 (should (equal (progn (run-with-timer
31 1 nil
32 (lambda () (push '(t . ?\C-b) unread-command-events)))
33 (read-event nil nil 2))
34 ?\C-b))))
35
36(ert-deftest keyboard-lossage-size ()
37 "Test `lossage-size'."
38 (let ((min-value 100)
39 (lossage-orig (lossage-size)))
40 (dolist (factor (list 1 3 4 5 10 7 3))
41 (let ((new-lossage (* factor min-value)))
42 (should (= new-lossage (lossage-size new-lossage)))))
43 ;; Wrong type
44 (should-error (lossage-size -5))
45 (should-error (lossage-size "200"))
46 ;; Less that minimum value
47 (should-error (lossage-size (1- min-value)))
48 (should (= lossage-orig (lossage-size lossage-orig)))))
49
50;; FIXME: This test doesn't currently work :-(
51;; (ert-deftest keyboard-tests--echo-keystrokes-bug15332 ()
52;; (let ((msgs '())
53;; (unread-command-events nil)
54;; (redisplay--interactive t)
55;; (echo-keystrokes 2))
56;; (setq unread-command-events '(?\C-u))
57;; (let* ((timer1
58;; (run-with-timer 3 1
59;; (lambda ()
60;; (setq unread-command-events '(?5)))))
61;; (timer2
62;; (run-with-timer 2.5 1
63;; (lambda ()
64;; (push (current-message) msgs)))))
65;; (run-with-timer 5 nil
66;; (lambda ()
67;; (cancel-timer timer1)
68;; (cancel-timer timer2)
69;; (throw 'exit msgs)))
70;; (recursive-edit)
71;; (should (equal msgs '("C-u 55-" "C-u 5-" "C-u-"))))))
72
73(provide 'keyboard-tests)
74;;; keyboard-tests.el ends here
diff --git a/test/src/keymap-tests.el b/test/src/keymap-tests.el
index bc2b424a639..ce96be6869e 100644
--- a/test/src/keymap-tests.el
+++ b/test/src/keymap-tests.el
@@ -1,8 +1,9 @@
1;;; keymap-tests.el --- Test suite for src/keymap.c 1;;; keymap-tests.el --- Test suite for src/keymap.c -*- lexical-binding: t -*-
2 2
3;; Copyright (C) 2015-2017 Free Software Foundation, Inc. 3;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
4 4
5;; Author: Juanma Barranquero <lekktu@gmail.com> 5;; Author: Juanma Barranquero <lekktu@gmail.com>
6;; Stefan Kangas <stefankangas@gmail.com>
6 7
7;; This file is part of GNU Emacs. 8;; This file is part of GNU Emacs.
8 9
@@ -23,6 +24,188 @@
23 24
24(require 'ert) 25(require 'ert)
25 26
27(defun keymap-tests--make-keymap-test (fun)
28 (should (eq (car (funcall fun)) 'keymap))
29 (should (proper-list-p (funcall fun)))
30 (should (equal (car (last (funcall fun "foo"))) "foo")))
31
32(ert-deftest keymap-make-keymap ()
33 (keymap-tests--make-keymap-test #'make-keymap)
34 (should (char-table-p (cadr (make-keymap)))))
35
36(ert-deftest keymap-make-sparse-keymap ()
37 (keymap-tests--make-keymap-test #'make-sparse-keymap))
38
39(ert-deftest keymap-keymapp ()
40 (should (keymapp (make-keymap)))
41 (should (keymapp (make-sparse-keymap)))
42 (should-not (keymapp '(foo bar))))
43
44(ert-deftest keymap-keymap-parent ()
45 (should-not (keymap-parent (make-keymap)))
46 (should-not (keymap-parent (make-sparse-keymap)))
47 (let ((map (make-keymap)))
48 (set-keymap-parent map help-mode-map)
49 (should (equal (keymap-parent map) help-mode-map))))
50
51(ert-deftest keymap-copy-keymap/is-equal ()
52 (should (equal (copy-keymap help-mode-map) help-mode-map)))
53
54(ert-deftest keymap-copy-keymap/is-not-eq ()
55 (should-not (eq (copy-keymap help-mode-map) help-mode-map)))
56
57(ert-deftest keymap---get-keyelt/runs-menu-item-filter ()
58 (let* (menu-item-filter-ran
59 (object `(menu-item "2" identity
60 :filter ,(lambda (cmd)
61 (setq menu-item-filter-ran t)
62 cmd))))
63 (keymap--get-keyelt object t)
64 (should menu-item-filter-ran)))
65
66(ert-deftest keymap-define-key/undefined ()
67 ;; nil (means key is undefined in this keymap),
68 (let ((map (make-keymap)))
69 (define-key map [?a] nil)
70 (should-not (lookup-key map [?a]))))
71
72(ert-deftest keymap-define-key/keyboard-macro ()
73 ;; a string (treated as a keyboard macro),
74 (let ((map (make-keymap)))
75 (define-key map [?a] "abc")
76 (should (equal (lookup-key map [?a]) "abc"))))
77
78(ert-deftest keymap-define-key/lambda ()
79 (let ((map (make-keymap)))
80 (define-key map [?a] (lambda () (interactive) nil))
81 (should (functionp (lookup-key map [?a])))))
82
83(ert-deftest keymap-define-key/keymap ()
84 ;; a keymap (to define a prefix key),
85 (let ((map (make-keymap))
86 (map2 (make-keymap)))
87 (define-key map [?a] map2)
88 (define-key map2 [?b] 'foo)
89 (should (eq (lookup-key map [?a ?b]) 'foo))))
90
91(ert-deftest keymap-define-key/menu-item ()
92 ;; or an extended menu item definition.
93 ;; (See info node ‘(elisp)Extended Menu Items’.)
94 (let ((map (make-sparse-keymap))
95 (menu (make-sparse-keymap)))
96 (define-key menu [new-file]
97 '(menu-item "Visit New File..." find-file
98 :enable (menu-bar-non-minibuffer-window-p)
99 :help "Specify a new file's name, to edit the file"))
100 (define-key map [menu-bar file] (cons "File" menu))
101 (should (eq (lookup-key map [menu-bar file new-file]) 'find-file))))
102
103(ert-deftest keymap-lookup-key ()
104 (let ((map (make-keymap)))
105 (define-key map [?a] 'foo)
106 (should (eq (lookup-key map [?a]) 'foo))
107 (should-not (lookup-key map [?b]))))
108
109(ert-deftest keymap-lookup-key/list-of-keymaps ()
110 (let ((map1 (make-keymap))
111 (map2 (make-keymap)))
112 (define-key map1 [?a] 'foo)
113 (define-key map2 [?b] 'bar)
114 (should (eq (lookup-key (list map1 map2) [?a]) 'foo))
115 (should (eq (lookup-key (list map1 map2) [?b]) 'bar))
116 (should-not (lookup-key (list map1 map2) [?c]))))
117
118(ert-deftest keymap-lookup-key/too-long ()
119 (let ((map (make-keymap)))
120 (define-key map (kbd "C-c f") 'foo)
121 (should (= (lookup-key map (kbd "C-c f x")) 2))))
122
123;; TODO: Write test for the ACCEPT-DEFAULT argument.
124;; (ert-deftest keymap-lookup-key/accept-default ()
125;; ...)
126
127(ert-deftest keymap-lookup-key/mixed-case ()
128 "Backwards compatibility behavior (Bug#50752)."
129 (let ((map (make-keymap)))
130 (define-key map [menu-bar foo bar] 'foo)
131 (should (eq (lookup-key map [menu-bar foo bar]) 'foo))
132 (should (eq (lookup-key map [menu-bar Foo Bar]) 'foo)))
133 (let ((map (make-keymap)))
134 (define-key map [menu-bar i-bar] 'foo)
135 (should (eq (lookup-key map [menu-bar I-bar]) 'foo))))
136
137(ert-deftest keymap-lookup-key/mixed-case-multibyte ()
138 "Backwards compatibility behavior (Bug#50752)."
139 (let ((map (make-keymap)))
140 ;; (downcase "Åäö") => "åäö"
141 (define-key map [menu-bar åäö bar] 'foo)
142 (should (eq (lookup-key map [menu-bar åäö bar]) 'foo))
143 (should (eq (lookup-key map [menu-bar Åäö Bar]) 'foo))
144 ;; (downcase "Γ") => "γ"
145 (define-key map [menu-bar γ bar] 'baz)
146 (should (eq (lookup-key map [menu-bar γ bar]) 'baz))
147 (should (eq (lookup-key map [menu-bar Γ Bar]) 'baz))))
148
149(ert-deftest keymap-lookup-key/menu-non-symbol ()
150 "Test for Bug#51527."
151 (let ((map (make-keymap)))
152 (define-key map [menu-bar buffer 1] 'foo)
153 (should (eq (lookup-key map [menu-bar buffer 1]) 'foo))))
154
155(ert-deftest keymap-lookup-keymap/with-spaces ()
156 "Backwards compatibility behavior (Bug#50752)."
157 (let ((map (make-keymap)))
158 (define-key map [menu-bar foo-bar] 'foo)
159 (should (eq (lookup-key map [menu-bar Foo\ Bar]) 'foo))))
160
161(ert-deftest keymap-lookup-keymap/with-spaces-multibyte ()
162 "Backwards compatibility behavior (Bug#50752)."
163 (let ((map (make-keymap)))
164 (define-key map [menu-bar åäö-bar] 'foo)
165 (should (eq (lookup-key map [menu-bar Åäö\ Bar]) 'foo))))
166
167(ert-deftest keymap-lookup-keymap/with-spaces-multibyte-lang-env ()
168 "Backwards compatibility behavior (Bug#50752)."
169 (let ((lang-env current-language-environment))
170 (set-language-environment "Turkish")
171 (let ((map (make-keymap)))
172 (define-key map [menu-bar i-bar] 'foo)
173 (should (eq (lookup-key map [menu-bar I-bar]) 'foo)))
174 (set-language-environment lang-env)))
175
176(ert-deftest describe-buffer-bindings/header-in-current-buffer ()
177 "Header should be inserted into the current buffer.
178https://debbugs.gnu.org/39149#31"
179 (with-temp-buffer
180 (describe-buffer-bindings (current-buffer))
181 (should (string-match (rx bol "key" (+ space) "binding" eol)
182 (buffer-string)))))
183
184(ert-deftest describe-buffer-bindings/returns-nil ()
185 "Should return nil."
186 (with-temp-buffer
187 (should (eq (describe-buffer-bindings (current-buffer)) nil))))
188
189(defun keymap-tests--test-menu-item-filter (show filter-fun)
190 (unwind-protect
191 (progn
192 (define-key global-map (kbd "C-c C-l r")
193 `(menu-item "2" identity :filter ,filter-fun))
194 (with-temp-buffer
195 (describe-buffer-bindings (current-buffer))
196 (goto-char (point-min))
197 (if (eq show 'show)
198 (should (search-forward "C-c C-l r" nil t))
199 (should-not (search-forward "C-c C-l r" nil t)))))
200 (define-key global-map (kbd "C-c C-l r") nil)
201 (define-key global-map (kbd "C-c C-l") nil)))
202
203(ert-deftest describe-buffer-bindings/menu-item-filter-show-binding ()
204 (keymap-tests--test-menu-item-filter 'show (lambda (cmd) cmd)))
205
206(ert-deftest describe-buffer-bindings/menu-item-filter-hide-binding ()
207 (keymap-tests--test-menu-item-filter 'hide (lambda (_) nil)))
208
26(ert-deftest keymap-store_in_keymap-XFASTINT-on-non-characters () 209(ert-deftest keymap-store_in_keymap-XFASTINT-on-non-characters ()
27 "Check for bug fixed in \"Fix assertion violation in define-key\", 210 "Check for bug fixed in \"Fix assertion violation in define-key\",
28commit 86c19714b097aa477d339ed99ffb5136c755a046." 211commit 86c19714b097aa477d339ed99ffb5136c755a046."
@@ -38,13 +221,227 @@ commit 86c19714b097aa477d339ed99ffb5136c755a046."
38 (should (eq (lookup-key Buffer-menu-mode-map [32]) 'undefined))) 221 (should (eq (lookup-key Buffer-menu-mode-map [32]) 'undefined)))
39 (define-key Buffer-menu-mode-map [32] def)))) 222 (define-key Buffer-menu-mode-map [32] def))))
40 223
41(ert-deftest keymap-where-is-internal-test () 224
225;;;; where-is-internal
226
227(defun keymap-tests--command-1 () (interactive) nil)
228(defun keymap-tests--command-2 () (interactive) nil)
229(put 'keymap-tests--command-1 :advertised-binding [?y])
230
231(ert-deftest keymap-where-is-internal ()
232 (let ((map (make-sparse-keymap)))
233 (define-key map "x" 'keymap-tests--command-1)
234 (define-key map "y" 'keymap-tests--command-1)
235 (should (equal (where-is-internal 'keymap-tests--command-1 map)
236 '([?y] [?x])))))
237
238(ert-deftest keymap-where-is-internal/firstonly-t ()
239 (let ((map (make-sparse-keymap)))
240 (define-key map "x" 'keymap-tests--command-1)
241 (define-key map "y" 'keymap-tests--command-1)
242 (should (equal (where-is-internal 'keymap-tests--command-1 map t)
243 [?y]))))
244
245(ert-deftest keymap-where-is-internal/menu-item ()
246 (let ((map (make-sparse-keymap)))
247 (define-key map [menu-bar foobar cmd1]
248 '(menu-item "Run Command 1" keymap-tests--command-1
249 :help "Command 1 Help"))
250 (define-key map "x" 'keymap-tests--command-1)
251 (should (equal (where-is-internal 'keymap-tests--command-1 map)
252 '([?x] [menu-bar foobar cmd1])))
253 (should (equal (where-is-internal 'keymap-tests--command-1 map t) [?x]))))
254
255
256(ert-deftest keymap-where-is-internal/advertised-binding ()
257 ;; Make sure order does not matter.
258 (dolist (keys '(("x" . "y") ("y" . "x")))
259 (let ((map (make-sparse-keymap)))
260 (define-key map (car keys) 'keymap-tests--command-1)
261 (define-key map (cdr keys) 'keymap-tests--command-1)
262 (should (equal (where-is-internal 'keymap-tests--command-1 map t) [121])))))
263
264(ert-deftest keymap-where-is-internal/advertised-binding-respect-remap ()
265 (let ((map (make-sparse-keymap)))
266 (define-key map "x" 'next-line)
267 (define-key map [remap keymap-tests--command-1] 'next-line)
268 (define-key map "y" 'keymap-tests--command-1)
269 (should (equal (where-is-internal 'keymap-tests--command-1 map t) [?x]))))
270
271(ert-deftest keymap-where-is-internal/remap ()
272 (let ((map (make-keymap)))
273 (define-key map (kbd "x") 'foo)
274 (define-key map (kbd "y") 'bar)
275 (define-key map [remap foo] 'bar)
276 (should (equal (where-is-internal 'foo map t) [?y]))
277 (should (equal (where-is-internal 'bar map t) [?y]))))
278
279(defvar-keymap keymap-tests-minor-mode-map
280 "x" 'keymap-tests--command-2)
281
282(defvar-keymap keymap-tests-major-mode-map
283 "x" 'keymap-tests--command-1)
284
285(define-minor-mode keymap-tests-minor-mode "Test.")
286
287(define-derived-mode keymap-tests-major-mode nil "Test.")
288
289(ert-deftest keymap-where-is-internal/shadowed ()
290 (with-temp-buffer
291 (keymap-tests-major-mode)
292 (keymap-tests-minor-mode)
293 (should-not (where-is-internal 'keymap-tests--command-1 nil t))
294 (should (equal (where-is-internal 'keymap-tests--command-2 nil t) [120]))))
295
296(ert-deftest keymap-where-is-internal/preferred-modifier-is-a-string ()
42 "Make sure we don't crash when `where-is-preferred-modifier' is not a symbol." 297 "Make sure we don't crash when `where-is-preferred-modifier' is not a symbol."
43 (should 298 (should
44 (equal (let ((where-is-preferred-modifier "alt")) 299 (equal (let ((where-is-preferred-modifier "alt"))
45 (where-is-internal 'execute-extended-command global-map t)) 300 (where-is-internal 'execute-extended-command global-map t))
46 [#x8000078]))) 301 [#x8000078])))
47 302
303
304;;;; describe_vector
305
306(ert-deftest help--describe-vector/bug-9293-one-shadowed-in-range ()
307 "Check that we only show a range if shadowed by the same command."
308 (let ((orig-map (let ((map (make-keymap)))
309 (define-key map "e" 'foo)
310 (define-key map "f" 'foo)
311 (define-key map "g" 'foo)
312 (define-key map "h" 'foo)
313 map))
314 (shadow-map (let ((map (make-keymap)))
315 (define-key map "f" 'bar)
316 map))
317 (text-quoting-style 'grave)
318 (describe-bindings-check-shadowing-in-ranges 'ignore-self-insert))
319 (with-temp-buffer
320 (help--describe-vector (cadr orig-map) nil #'help--describe-command
321 t shadow-map orig-map t)
322 (should (equal (buffer-substring-no-properties (point-min) (point-max))
323 (string-replace "\t" "" "
324e foo
325f foo (currently shadowed by `bar')
326g .. h foo
327"))))))
328
329(ert-deftest help--describe-vector/bug-9293-same-command-does-not-shadow ()
330 "Check that a command can't be shadowed by the same command."
331 (let ((range-map
332 (let ((map (make-keymap)))
333 (define-key map "0" 'foo)
334 (define-key map "1" 'foo)
335 (define-key map "2" 'foo)
336 (define-key map "3" 'foo)
337 map))
338 (shadow-map
339 (let ((map (make-keymap)))
340 (define-key map "0" 'foo)
341 (define-key map "1" 'foo)
342 (define-key map "2" 'foo)
343 (define-key map "3" 'foo)
344 map)))
345 (with-temp-buffer
346 (help--describe-vector (cadr range-map) nil #'help--describe-command
347 t shadow-map range-map t)
348 (should (equal (buffer-substring-no-properties (point-min) (point-max))
349 (string-replace "\t" "" "
3500 .. 3 foo
351"))))))
352
353(ert-deftest keymap--key-description ()
354 (should (equal (key-description [right] [?\C-x])
355 "C-x <right>"))
356 (should (equal (key-description [M-H-right] [?\C-x])
357 "C-x M-H-<right>"))
358 (should (equal (single-key-description 'home)
359 "<home>"))
360 (should (equal (single-key-description 'home t)
361 "home"))
362 (should (equal (single-key-description 'C-s-home)
363 "C-s-<home>")))
364
365(ert-deftest keymap-test-lookups ()
366 (should (eq (lookup-key (current-global-map) "\C-x\C-f") 'find-file))
367 (should (eq (lookup-key (current-global-map) [(control x) (control f)])
368 'find-file))
369 (should (eq (lookup-key (current-global-map) ["C-x C-f"]) 'find-file))
370 (should (eq (lookup-key (current-global-map) [?\C-x ?\C-f]) 'find-file)))
371
372(ert-deftest keymap-removal ()
373 ;; Set to nil.
374 (let ((map (define-keymap "a" 'foo)))
375 (should (equal map '(keymap (97 . foo))))
376 (define-key map "a" nil)
377 (should (equal map '(keymap (97)))))
378 ;; Remove.
379 (let ((map (define-keymap "a" 'foo)))
380 (should (equal map '(keymap (97 . foo))))
381 (define-key map "a" nil t)
382 (should (equal map '(keymap)))))
383
384(ert-deftest keymap-removal-inherit ()
385 ;; Set to nil.
386 (let ((parent (make-sparse-keymap))
387 (child (make-keymap)))
388 (set-keymap-parent child parent)
389 (define-key parent [?a] 'foo)
390 (define-key child [?a] 'bar)
391
392 (should (eq (lookup-key child [?a]) 'bar))
393 (define-key child [?a] nil)
394 (should (eq (lookup-key child [?a]) nil)))
395 ;; Remove.
396 (let ((parent (make-sparse-keymap))
397 (child (make-keymap)))
398 (set-keymap-parent child parent)
399 (define-key parent [?a] 'foo)
400 (define-key child [?a] 'bar)
401
402 (should (eq (lookup-key child [?a]) 'bar))
403 (define-key child [?a] nil t)
404 (should (eq (lookup-key child [?a]) 'foo))))
405
406(ert-deftest keymap-text-char-description ()
407 (should (equal (text-char-description ?a) "a"))
408 (should (equal (text-char-description ?\s) " "))
409 (should (equal (text-char-description ?\t) "^I"))
410 (should (equal (text-char-description ?\^C) "^C"))
411 (should (equal (text-char-description ?\^?) "^?"))
412 (should (equal (text-char-description #x80) "€"))
413 (should (equal (text-char-description ?å) "å"))
414 (should (equal (text-char-description ?Ş) "Ş"))
415 (should (equal (text-char-description ?Ā) "Ā"))
416 (should-error (text-char-description "c"))
417 (should-error (text-char-description [?\C-x ?l]))
418 (should-error (text-char-description ?\M-c))
419 (should-error (text-char-description ?\s-c)))
420
421(ert-deftest test-non-key-events ()
422 ;; Dummy command.
423 (declare-function keymap-tests-command nil)
424 (should (null (where-is-internal 'keymap-tests-command)))
425 (keymap-set global-map "C-c g" #'keymap-tests-command)
426 (should (equal (where-is-internal 'keymap-tests-command) '([3 103])))
427 (keymap-set global-map "<keymap-tests-event>" #'keymap-tests-command)
428 (should (equal (where-is-internal 'keymap-tests-command)
429 '([keymap-tests-event] [3 103])))
430 (make-non-key-event 'keymap-tests-event)
431 (should (equal (where-is-internal 'keymap-tests-command) '([3 103]))))
432
433(ert-deftest keymap-test-duplicate-definitions ()
434 "Check that defvar-keymap rejects duplicate key definitions."
435 (should-error
436 (defvar-keymap
437 ert-keymap-duplicate
438 "a" #'next-line
439 "a" #'previous-line))
440 (should-error
441 (define-keymap
442 "a" #'next-line
443 "a" #'previous-line)))
444
48(provide 'keymap-tests) 445(provide 'keymap-tests)
49 446
50;;; keymap-tests.el ends here 447;;; keymap-tests.el ends here
diff --git a/test/src/lcms-tests.el b/test/src/lcms-tests.el
index cc324af68ba..1829a7ea1f1 100644
--- a/test/src/lcms-tests.el
+++ b/test/src/lcms-tests.el
@@ -1,6 +1,6 @@
1;;; lcms-tests.el --- tests for Little CMS interface -*- lexical-binding: t -*- 1;;; lcms-tests.el --- tests for Little CMS interface -*- lexical-binding: t -*-
2 2
3;; Copyright (C) 2017 Free Software Foundation, Inc. 3;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
4 4
5;; Maintainer: emacs-devel@gnu.org 5;; Maintainer: emacs-devel@gnu.org
6 6
@@ -35,6 +35,13 @@
35(require 'ert) 35(require 'ert)
36(require 'color) 36(require 'color)
37 37
38(declare-function lcms-jab->jch "lcms.c")
39(declare-function lcms-jch->jab "lcms.c")
40(declare-function lcms-xyz->jch "lcms.c")
41(declare-function lcms-jch->xyz "lcms.c")
42(declare-function lcms-temp->white-point "lcms.c")
43(declare-function lcms-cam02-ucs "lcms.c")
44
38(defconst lcms-colorspacious-d65 '(0.95047 1.0 1.08883) 45(defconst lcms-colorspacious-d65 '(0.95047 1.0 1.08883)
39 "D65 white point from colorspacious.") 46 "D65 white point from colorspacious.")
40 47
@@ -95,7 +102,7 @@ B is considered the exact value."
95 '(0.29902 0.31485 1.0)))) 102 '(0.29902 0.31485 1.0))))
96 103
97(ert-deftest lcms-roundtrip () 104(ert-deftest lcms-roundtrip ()
98 "Test accuracy of converting to and from different color spaces" 105 "Test accuracy of converting to and from different color spaces."
99 (skip-unless (featurep 'lcms2)) 106 (skip-unless (featurep 'lcms2))
100 (should 107 (should
101 (let ((color '(.5 .3 .7))) 108 (let ((color '(.5 .3 .7)))
@@ -109,7 +116,7 @@ B is considered the exact value."
109 0.0001)))) 116 0.0001))))
110 117
111(ert-deftest lcms-ciecam02-gold () 118(ert-deftest lcms-ciecam02-gold ()
112 "Test CIE CAM02 JCh gold values" 119 "Test CIE CAM02 JCh gold values."
113 (skip-unless (featurep 'lcms2)) 120 (skip-unless (featurep 'lcms2))
114 (should 121 (should
115 (lcms-triple-approx-p 122 (lcms-triple-approx-p
diff --git a/test/src/lread-resources/lazydoc.el b/test/src/lread-resources/lazydoc.el
new file mode 100644
index 00000000000..cb434c239b5
--- /dev/null
+++ b/test/src/lread-resources/lazydoc.el
Binary files differ
diff --git a/test/src/lread-resources/somelib.el b/test/src/lread-resources/somelib.el
new file mode 100644
index 00000000000..7b8d4037396
--- /dev/null
+++ b/test/src/lread-resources/somelib.el
@@ -0,0 +1,7 @@
1;;; -*- lexical-binding: t; -*-
2
3;; blah
4
5(defun somefunc () t)
6
7(provide 'somelib)
diff --git a/test/src/lread-resources/somelib2.el b/test/src/lread-resources/somelib2.el
new file mode 100644
index 00000000000..05156145a22
--- /dev/null
+++ b/test/src/lread-resources/somelib2.el
@@ -0,0 +1,7 @@
1;;; -*- lexical-binding: t; -*-
2
3;; blah
4
5(defun somefunc2 () t)
6
7(provide 'somelib2)
diff --git a/test/src/lread-tests.el b/test/src/lread-tests.el
index ac730b4f005..57143dd81e5 100644
--- a/test/src/lread-tests.el
+++ b/test/src/lread-tests.el
@@ -1,23 +1,23 @@
1;;; lread-tests.el --- tests for lread.c -*- lexical-binding: t; -*- 1;;; lread-tests.el --- tests for lread.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
7;; This file is part of GNU Emacs. 7;; This file is part of GNU Emacs.
8 8
9;; This program is free software; you can redistribute it and/or modify 9;; GNU Emacs is free software: you can redistribute it and/or modify
10;; it under the terms of the GNU General Public License as published by 10;; it under the terms of the GNU General Public License as published by
11;; the Free Software Foundation, either version 3 of the License, or 11;; the Free Software Foundation, either version 3 of the License, or
12;; (at your option) any later version. 12;; (at your option) any later version.
13 13
14;; This program is distributed in the hope that it will be useful, 14;; GNU Emacs is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;; GNU General Public License for more details. 17;; GNU General Public License for more details.
18 18
19;; You should have received a copy of the GNU General Public License 19;; You should have received a copy of the GNU General Public License
20;; along with this program. If not, see <https://www.gnu.org/licenses/>. 20;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
21 21
22;;; Commentary: 22;;; Commentary:
23 23
@@ -25,6 +25,9 @@
25 25
26;;; Code: 26;;; Code:
27 27
28(require 'ert)
29(require 'ert-x)
30
28(ert-deftest lread-char-number () 31(ert-deftest lread-char-number ()
29 (should (equal (read "?\\N{U+A817}") #xA817))) 32 (should (equal (read "?\\N{U+A817}") #xA817)))
30 33
@@ -112,59 +115,37 @@
112 (should-error (read "#24r") :type 'invalid-read-syntax) 115 (should-error (read "#24r") :type 'invalid-read-syntax)
113 (should-error (read "#") :type 'invalid-read-syntax)) 116 (should-error (read "#") :type 'invalid-read-syntax))
114 117
118(ert-deftest lread-char-modifiers ()
119 (should (eq ?\C-\M-é (+ (- ?\M-a ?a) ?\C-é)))
120 (should (eq (- ?\C-ŗ ?ŗ) (- ?\C-é ?é))))
121
115(ert-deftest lread-record-1 () 122(ert-deftest lread-record-1 ()
116 (should (equal '(#s(foo) #s(foo)) 123 (should (equal '(#s(foo) #s(foo))
117 (read "(#1=#s(foo) #1#)")))) 124 (read "(#1=#s(foo) #1#)"))))
118 125
119(defmacro lread-tests--with-temp-file (file-name-var &rest body)
120 (declare (indent 1))
121 (cl-check-type file-name-var symbol)
122 `(let ((,file-name-var (make-temp-file "emacs")))
123 (unwind-protect
124 (progn ,@body)
125 (delete-file ,file-name-var))))
126
127(defun lread-tests--last-message () 126(defun lread-tests--last-message ()
128 (with-current-buffer "*Messages*" 127 (with-current-buffer "*Messages*"
129 (save-excursion 128 (save-excursion
130 (goto-char (point-max)) 129 (goto-char (point-max))
131 (skip-chars-backward "\n") 130 (skip-chars-backward "\n")
132 (buffer-substring (line-beginning-position) (point))))) 131 (buffer-substring (pos-bol) (point)))))
133 132
134(ert-deftest lread-tests--unescaped-char-literals () 133(ert-deftest lread-tests--unescaped-char-literals ()
135 "Check that loading warns about unescaped character 134 "Check that loading warns about unescaped character
136literals (Bug#20852)." 135literals (Bug#20852)."
137 (lread-tests--with-temp-file file-name 136 (ert-with-temp-file file-name
138 (write-region "?) ?( ?; ?\" ?[ ?]" nil file-name) 137 (write-region "?) ?( ?; ?\" ?[ ?]" nil file-name)
139 (should (equal (load file-name nil :nomessage :nosuffix) t)) 138 (should (equal (load file-name nil :nomessage :nosuffix) t))
140 (should (equal (lread-tests--last-message) 139 (should (equal (lread-tests--last-message)
141 (concat (format-message "Loading `%s': " file-name) 140 (concat (format-message "Loading `%s': " file-name)
142 "unescaped character literals " 141 "unescaped character literals "
143 "`?\"', `?(', `?)', `?;', `?[', `?]' detected!"))))) 142 "`?\"', `?(', `?)', `?;', `?[', `?]' detected, "
144 143 "`?\\\"', `?\\(', `?\\)', `?\\;', `?\\[', `?\\]' "
145(ert-deftest lread-tests--funny-quote-symbols () 144 "expected!")))))
146 "Check that 'smart quotes' or similar trigger errors in symbol names."
147 (dolist (quote-char
148 '(#x2018 ;; LEFT SINGLE QUOTATION MARK
149 #x2019 ;; RIGHT SINGLE QUOTATION MARK
150 #x201B ;; SINGLE HIGH-REVERSED-9 QUOTATION MARK
151 #x201C ;; LEFT DOUBLE QUOTATION MARK
152 #x201D ;; RIGHT DOUBLE QUOTATION MARK
153 #x201F ;; DOUBLE HIGH-REVERSED-9 QUOTATION MARK
154 #x301E ;; DOUBLE PRIME QUOTATION MARK
155 #xFF02 ;; FULLWIDTH QUOTATION MARK
156 #xFF07 ;; FULLWIDTH APOSTROPHE
157 ))
158 (let ((str (format "%cfoo" quote-char)))
159 (should-error (read str) :type 'invalid-read-syntax)
160 (should (eq (read (concat "\\" str)) (intern str))))))
161 145
162(ert-deftest lread-test-bug26837 () 146(ert-deftest lread-test-bug26837 ()
163 "Test for https://debbugs.gnu.org/26837 ." 147 "Test for https://debbugs.gnu.org/26837 ."
164 (let ((load-path (cons 148 (let ((load-path (cons (ert-resource-directory) load-path)))
165 (file-name-as-directory
166 (expand-file-name "data" (getenv "EMACS_TEST_DIRECTORY")))
167 load-path)))
168 (load "somelib" nil t) 149 (load "somelib" nil t)
169 (should (string-suffix-p "/somelib.el" (caar load-history))) 150 (should (string-suffix-p "/somelib.el" (caar load-history)))
170 (load "somelib2" nil t) 151 (load "somelib2" nil t)
@@ -172,19 +153,190 @@ literals (Bug#20852)."
172 (load "somelib" nil t) 153 (load "somelib" nil t)
173 (should (string-suffix-p "/somelib.el" (caar load-history))))) 154 (should (string-suffix-p "/somelib.el" (caar load-history)))))
174 155
175(ert-deftest lread-tests--old-style-backquotes ()
176 "Check that loading warns about old-style backquotes."
177 (lread-tests--with-temp-file file-name
178 (write-region "(` (a b))" nil file-name)
179 (should (equal (load file-name nil :nomessage :nosuffix) t))
180 (should (equal (lread-tests--last-message)
181 (concat (format-message "Loading `%s': " file-name)
182 "old-style backquotes detected!")))))
183
184(ert-deftest lread-lread--substitute-object-in-subtree () 156(ert-deftest lread-lread--substitute-object-in-subtree ()
185 (let ((x (cons 0 1))) 157 (let ((x (cons 0 1)))
186 (setcar x x) 158 (setcar x x)
187 (lread--substitute-object-in-subtree x 1 t) 159 (lread--substitute-object-in-subtree x 1 t)
188 (should (eq x (cdr x))))) 160 (should (eq x (cdr x)))))
189 161
162(ert-deftest lread-long-hex-integer ()
163 (should (bignump (read "#xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))))
164
165(ert-deftest lread-test-bug-31186 ()
166 (with-temp-buffer
167 (insert ";; -*- -:*-")
168 (should-not
169 ;; This used to crash in lisp_file_lexically_bound_p before the
170 ;; bug was fixed.
171 (eval-buffer))))
172
173(ert-deftest lread-invalid-bytecodes ()
174 (should-error
175 (let ((load-force-doc-strings t)) (read "#[0 \"\"]"))))
176
177(ert-deftest lread-string-to-number-trailing-dot ()
178 (dolist (n (list (* most-negative-fixnum most-negative-fixnum)
179 (1- most-negative-fixnum) most-negative-fixnum
180 (1+ most-negative-fixnum) -1 0 1
181 (1- most-positive-fixnum) most-positive-fixnum
182 (1+ most-positive-fixnum)
183 (* most-positive-fixnum most-positive-fixnum)))
184 (should (= n (string-to-number (format "%d." n))))))
185
186(ert-deftest lread-circular-hash ()
187 (should-error (read "#s(hash-table data #0=(#0# . #0#))")))
188
189(ert-deftest test-inhibit-interaction ()
190 (let ((inhibit-interaction t))
191 (should-error (read-char "foo: "))
192 (should-error (read-event "foo: "))
193 (should-error (read-char-exclusive "foo: "))))
194
195(ert-deftest lread-float ()
196 (should (equal (read "13") 13))
197 (should (equal (read "+13") 13))
198 (should (equal (read "-13") -13))
199 (should (equal (read "13.") 13))
200 (should (equal (read "+13.") 13))
201 (should (equal (read "-13.") -13))
202 (should (equal (read "13.25") 13.25))
203 (should (equal (read "+13.25") 13.25))
204 (should (equal (read "-13.25") -13.25))
205 (should (equal (read ".25") 0.25))
206 (should (equal (read "+.25") 0.25))
207 (should (equal (read "-.25") -0.25))
208 (should (equal (read "13e4") 130000.0))
209 (should (equal (read "+13e4") 130000.0))
210 (should (equal (read "-13e4") -130000.0))
211 (should (equal (read "13e+4") 130000.0))
212 (should (equal (read "+13e+4") 130000.0))
213 (should (equal (read "-13e+4") -130000.0))
214 (should (equal (read "625e-4") 0.0625))
215 (should (equal (read "+625e-4") 0.0625))
216 (should (equal (read "-625e-4") -0.0625))
217 (should (equal (read "1.25e2") 125.0))
218 (should (equal (read "+1.25e2") 125.0))
219 (should (equal (read "-1.25e2") -125.0))
220 (should (equal (read "1.25e+2") 125.0))
221 (should (equal (read "+1.25e+2") 125.0))
222 (should (equal (read "-1.25e+2") -125.0))
223 (should (equal (read "1.25e-1") 0.125))
224 (should (equal (read "+1.25e-1") 0.125))
225 (should (equal (read "-1.25e-1") -0.125))
226 (should (equal (read "4.e3") 4000.0))
227 (should (equal (read "+4.e3") 4000.0))
228 (should (equal (read "-4.e3") -4000.0))
229 (should (equal (read "4.e+3") 4000.0))
230 (should (equal (read "+4.e+3") 4000.0))
231 (should (equal (read "-4.e+3") -4000.0))
232 (should (equal (read "5.e-1") 0.5))
233 (should (equal (read "+5.e-1") 0.5))
234 (should (equal (read "-5.e-1") -0.5))
235 (should (equal (read "0") 0))
236 (should (equal (read "+0") 0))
237 (should (equal (read "-0") 0))
238 (should (equal (read "0.") 0))
239 (should (equal (read "+0.") 0))
240 (should (equal (read "-0.") 0))
241 (should (equal (read "0.0") 0.0))
242 (should (equal (read "+0.0") 0.0))
243 (should (equal (read "-0.0") -0.0))
244 (should (equal (read "0e5") 0.0))
245 (should (equal (read "+0e5") 0.0))
246 (should (equal (read "-0e5") -0.0))
247 (should (equal (read "0e-5") 0.0))
248 (should (equal (read "+0e-5") 0.0))
249 (should (equal (read "-0e-5") -0.0))
250 (should (equal (read ".0e-5") 0.0))
251 (should (equal (read "+.0e-5") 0.0))
252 (should (equal (read "-.0e-5") -0.0))
253 (should (equal (read "0.0e-5") 0.0))
254 (should (equal (read "+0.0e-5") 0.0))
255 (should (equal (read "-0.0e-5") -0.0))
256 (should (equal (read "0.e-5") 0.0))
257 (should (equal (read "+0.e-5") 0.0))
258 (should (equal (read "-0.e-5") -0.0))
259 )
260
261(defun lread-test-read-and-print (str)
262 (let* ((read-circle t)
263 (print-circle t)
264 (val (read-from-string str)))
265 (if (consp val)
266 (prin1-to-string (car val))
267 (error "reading %S failed: %S" str val))))
268
269(defconst lread-test-circle-cases
270 '("#1=(#1# . #1#)"
271 "#1=[#1# a #1#]"
272 "#1=(#2=[#1# #2#] . #1#)"
273 "#1=(#2=[#1# #2#] . #2#)"
274 "#1=[#2=(#1# . #2#)]"
275 "#1=(#2=[#3=(#1# . #2#) #4=(#3# . #4#)])"
276 ))
277
278(ert-deftest lread-circle ()
279 (dolist (str lread-test-circle-cases)
280 (ert-info (str :prefix "input: ")
281 (should (equal (lread-test-read-and-print str) str))))
282 (should-error (read-from-string "#1=#1#") :type 'invalid-read-syntax))
283
284(ert-deftest lread-deeply-nested ()
285 ;; Check that we can read a deeply nested data structure correctly.
286 (let ((levels 10000)
287 (prefix nil)
288 (suffix nil))
289 (dotimes (_ levels)
290 (push "([#s(r " prefix)
291 (push ")])" suffix))
292 (let ((str (concat (apply #'concat prefix)
293 "a"
294 (apply #'concat suffix))))
295 (let* ((read-circle t)
296 (result (read-from-string str)))
297 (should (equal (cdr result) (length str)))
298 ;; Check the result. (We can't build a reference value and compare
299 ;; using `equal' because that function is currently depth-limited.)
300 (named-let check ((x (car result)) (level 0))
301 (if (equal level levels)
302 (should (equal x 'a))
303 (should (and (consp x) (null (cdr x))))
304 (let ((x2 (car x)))
305 (should (and (vectorp x2) (equal (length x2) 1)))
306 (let ((x3 (aref x2 0)))
307 (should (and (recordp x3) (equal (length x3) 2)
308 (equal (aref x3 0) 'r)))
309 (check (aref x3 1) (1+ level))))))))))
310
311(ert-deftest lread-misc ()
312 ;; Regression tests for issues found and fixed in bug#55676:
313 ;; Non-breaking space after a dot makes it a dot token.
314 (should (equal (read-from-string "(a .\u00A0b)")
315 '((a . b) . 7)))
316 ;; #_ without symbol following is the interned empty symbol.
317 (should (equal (read-from-string "#_")
318 '(## . 2))))
319
320(ert-deftest lread-escaped-lf ()
321 ;; ?\LF should signal an error; \LF is ignored inside string literals.
322 (should-error (read-from-string "?\\\n x"))
323 (should (equal (read-from-string "\"a\\\nb\"") '("ab" . 6))))
324
325(ert-deftest lread-force-load-doc-strings ()
326 ;; Verify that lazy doc strings are loaded lazily by default,
327 ;; but eagerly with `force-load-doc-strings' set.
328 (let ((file (expand-file-name "lazydoc.el" (ert-resource-directory))))
329 (fmakunbound 'lazydoc-fun)
330 (load file)
331 (let ((f (symbol-function 'lazydoc-fun)))
332 (should (byte-code-function-p f))
333 (should (equal (aref f 4) (cons file 87))))
334
335 (fmakunbound 'lazydoc-fun)
336 (let ((load-force-doc-strings t))
337 (load file)
338 (let ((f (symbol-function 'lazydoc-fun)))
339 (should (byte-code-function-p f))
340 (should (equal (aref f 4) "My little\ndoc string\nhere"))))))
341
190;;; lread-tests.el ends here 342;;; lread-tests.el ends here
diff --git a/test/src/marker-tests.el b/test/src/marker-tests.el
index 2540f157e76..32e4804fe7d 100644
--- a/test/src/marker-tests.el
+++ b/test/src/marker-tests.el
@@ -1,6 +1,6 @@
1;;; marker-tests.el --- tests for marker.c functions -*- lexical-binding: t -*- 1;;; marker-tests.el --- tests for marker.c functions -*- 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;; This file is part of GNU Emacs. 5;; This file is part of GNU Emacs.
6 6
@@ -57,4 +57,4 @@
57 (set-marker marker-2 marker-1) 57 (set-marker marker-2 marker-1)
58 (should (goto-char marker-2)))) 58 (should (goto-char marker-2))))
59 59
60;;; marker-tests.el ends here. 60;;; marker-tests.el ends here
diff --git a/test/src/minibuf-tests.el b/test/src/minibuf-tests.el
index aba5ca51707..68800729502 100644
--- a/test/src/minibuf-tests.el
+++ b/test/src/minibuf-tests.el
@@ -1,6 +1,6 @@
1;;; minibuf-tests.el --- tests for minibuf.c functions -*- lexical-binding: t -*- 1;;; minibuf-tests.el --- tests for minibuf.c functions -*- 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;; This file is part of GNU Emacs. 5;; This file is part of GNU Emacs.
6 6
@@ -399,5 +399,31 @@
399 (minibuf-tests--test-completion-regexp 399 (minibuf-tests--test-completion-regexp
400 #'minibuf-tests--strings-to-symbol-hashtable)) 400 #'minibuf-tests--strings-to-symbol-hashtable))
401 401
402(ert-deftest test-try-completion-ignore-case ()
403 (let ((completion-ignore-case t))
404 (should (equal (try-completion "bar" '("bAr" "barfoo")) "bAr"))
405 (should (equal (try-completion "bar" '("bArfoo" "barbaz")) "bar"))
406 (should (equal (try-completion "bar" '("bArfoo" "barbaz"))
407 (try-completion "bar" '("barbaz" "bArfoo"))))
408 ;; bug#11339
409 (should (equal (try-completion "baz" '("baz" "bAz")) "baz")) ;And not t!
410 (should (equal (try-completion "baz" '("bAz" "baz"))
411 (try-completion "baz" '("baz" "bAz"))))))
412
413(ert-deftest test-inhibit-interaction ()
414 (let ((inhibit-interaction t))
415 (should-error (read-from-minibuffer "foo: ") :type 'inhibited-interaction)
416
417 (should-error (y-or-n-p "Foo?") :type 'inhibited-interaction)
418 (should-error (yes-or-no-p "Foo?") :type 'inhibited-interaction)
419 (should-error (read-no-blanks-input "foo: ") :type 'inhibited-interaction)
420
421 ;; See that we get the expected error.
422 (should (eq (condition-case nil
423 (read-from-minibuffer "foo: ")
424 (inhibited-interaction 'inhibit)
425 (error nil))
426 'inhibit))))
427
402 428
403;;; minibuf-tests.el ends here 429;;; minibuf-tests.el ends here
diff --git a/test/src/print-tests.el b/test/src/print-tests.el
index b8f6c797dab..faab196f22f 100644
--- a/test/src/print-tests.el
+++ b/test/src/print-tests.el
@@ -1,32 +1,112 @@
1;;; print-tests.el --- tests for src/print.c -*- lexical-binding: t; -*- 1;;; print-tests.el --- tests for src/print.c -*- lexical-binding: t; -*-
2 2
3;; Copyright (C) 2014-2017 Free Software Foundation, Inc. 3;; Copyright (C) 2014-2022 Free Software Foundation, Inc.
4 4
5;; This file is part of GNU Emacs. 5;; This file is part of GNU Emacs.
6 6
7;; This program is free software; you can redistribute it and/or modify 7;; GNU Emacs is free software: you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by 8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation, either version 3 of the License, or 9;; the Free Software Foundation, either version 3 of the License, or
10;; (at your option) any later version. 10;; (at your option) any later version.
11 11
12;; This program is distributed in the hope that it will be useful, 12;; GNU Emacs is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of 13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; GNU General Public License for more details. 15;; GNU General Public License for more details.
16 16
17;; You should have received a copy of the GNU General Public License 17;; You should have received a copy of the GNU General Public License
18;; along with this program. If not, see <https://www.gnu.org/licenses/>. 18;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
19 19
20;;; Code: 20;;; Code:
21 21
22(require 'ert) 22(require 'ert)
23 23
24(ert-deftest print-hex-backslash () 24;; Support sharing test code with cl-print-tests.
25
26(defalias 'print-tests--prin1-to-string #'identity
27 "The function to print to a string which is under test.")
28
29(defmacro print-tests--deftest (name arg &rest docstring-keys-and-body)
30 "Test both print.c and cl-print.el at once."
31 (declare (debug ert-deftest)
32 (doc-string 3)
33 (indent 2))
34 (let ((clname (intern (concat (symbol-name name) "-cl-print")))
35 (doc (when (stringp (car-safe docstring-keys-and-body))
36 (list (pop docstring-keys-and-body))))
37 (keys-and-values nil))
38 (while (keywordp (car-safe docstring-keys-and-body))
39 (let ((key (pop docstring-keys-and-body))
40 (val (pop docstring-keys-and-body)))
41 (push val keys-and-values)
42 (push key keys-and-values)))
43 `(progn
44 ;; Set print-tests--prin1-to-string at both declaration and
45 ;; runtime, so that it can be used by the :expected-result
46 ;; keyword.
47 (cl-letf (((symbol-function #'print-tests--prin1-to-string)
48 #'prin1-to-string))
49 (ert-deftest ,name ,arg
50 ,@doc
51 ,@keys-and-values
52 (cl-letf (((symbol-function #'print-tests--prin1-to-string)
53 #'prin1-to-string))
54 ,@docstring-keys-and-body)))
55 (cl-letf (((symbol-function #'print-tests--prin1-to-string)
56 #'cl-prin1-to-string))
57 (ert-deftest ,clname ,arg
58 ,@doc
59 ,@keys-and-values
60 (cl-letf (((symbol-function #'print-tests--prin1-to-string)
61 #'cl-prin1-to-string))
62 ,@docstring-keys-and-body))))))
63
64(print-tests--deftest print-hex-backslash ()
25 (should (string= (let ((print-escape-multibyte t) 65 (should (string= (let ((print-escape-multibyte t)
26 (print-escape-newlines t)) 66 (print-escape-newlines t))
27 (prin1-to-string "\u00A2\ff")) 67 (print-tests--prin1-to-string "\u00A2\ff"))
28 "\"\\x00a2\\ff\""))) 68 "\"\\x00a2\\ff\"")))
29 69
70(defun print-tests--prints-with-charset-p (ch odd-charset)
71 "Return t if print function being tested prints CH with the `charset' property.
72CH is propertized with a `charset' value according to
73ODD-CHARSET: if nil, then use the one returned by `char-charset',
74otherwise, use a different charset."
75 (integerp
76 (string-match
77 "charset"
78 (print-tests--prin1-to-string
79 (propertize (string ch)
80 'charset
81 (if odd-charset
82 (cl-find (char-charset ch) charset-list :test-not #'eq)
83 (char-charset ch)))))))
84
85(print-tests--deftest print-charset-text-property-nil ()
86 :expected-result (if (eq (symbol-function #'print-tests--prin1-to-string)
87 #'cl-prin1-to-string) :failed :passed)
88 (let ((print-charset-text-property nil))
89 (should-not (print-tests--prints-with-charset-p ?\xf6 t)) ; Bug#31376.
90 (should-not (print-tests--prints-with-charset-p ?a t))
91 (should-not (print-tests--prints-with-charset-p ?\xf6 nil))
92 (should-not (print-tests--prints-with-charset-p ?a nil))))
93
94(print-tests--deftest print-charset-text-property-default ()
95 :expected-result (if (eq (symbol-function #'print-tests--prin1-to-string)
96 #'cl-prin1-to-string) :failed :passed)
97 (let ((print-charset-text-property 'default))
98 (should (print-tests--prints-with-charset-p ?\xf6 t))
99 (should-not (print-tests--prints-with-charset-p ?a t))
100 (should-not (print-tests--prints-with-charset-p ?\xf6 nil))
101 (should-not (print-tests--prints-with-charset-p ?a nil))))
102
103(print-tests--deftest print-charset-text-property-t ()
104 (let ((print-charset-text-property t))
105 (should (print-tests--prints-with-charset-p ?\xf6 t))
106 (should (print-tests--prints-with-charset-p ?a t))
107 (should (print-tests--prints-with-charset-p ?\xf6 nil))
108 (should (print-tests--prints-with-charset-p ?a nil))))
109
30(ert-deftest terpri () 110(ert-deftest terpri ()
31 (should (string= (with-output-to-string 111 (should (string= (with-output-to-string
32 (princ 'abc) 112 (princ 'abc)
@@ -58,5 +138,411 @@
58 (buffer-string)) 138 (buffer-string))
59 "--------\n")))) 139 "--------\n"))))
60 140
141(print-tests--deftest print-read-roundtrip ()
142 (let ((syms (list '## '& '* '+ '- '/ '0E '0e '< '= '> 'E 'E0 'NaN '\"
143 '\# '\#x0 '\' '\'\' '\( '\) '\+00 '\, '\-0 '\. '\.0
144 '\0 '\0.0 '\0E0 '\0e0 '\1E+ '\1E+NaN '\1e+ '\1e+NaN
145 '\; '\? '\[ '\\ '\] '\` '_ 'a 'e 'e0 'x
146 '{ '| '} '~ : '\’ '\’bar
147 (intern "\t") (intern "\n") (intern " ")
148 (intern "\N{NO-BREAK SPACE}")
149 (intern "\N{ZERO WIDTH SPACE}")
150 (intern "\0"))))
151 (dolist (sym syms)
152 (should (eq (read (print-tests--prin1-to-string sym)) sym))
153 (dolist (sym1 syms)
154 (let ((sym2 (intern (concat (symbol-name sym) (symbol-name sym1)))))
155 (should (eq (read (print-tests--prin1-to-string sym2)) sym2)))))))
156
157(print-tests--deftest print-bignum ()
158 (let* ((str "999999999999999999999999999999999")
159 (val (read str)))
160 (should (> val most-positive-fixnum))
161 (should (equal (print-tests--prin1-to-string val) str))))
162
163(print-tests--deftest print-tests-print-gensym ()
164 "Printing observes `print-gensym'."
165 (let* ((sym1 (gensym))
166 (syms (list sym1 (gensym "x") (make-symbol "y") sym1)))
167 (let* ((print-circle nil)
168 (printed-with (let ((print-gensym t))
169 (print-tests--prin1-to-string syms)))
170 (printed-without (let ((print-gensym nil))
171 (print-tests--prin1-to-string syms))))
172 (should (string-match
173 "(#:\\(g[[:digit:]]+\\) #:x[[:digit:]]+ #:y #:\\(g[[:digit:]]+\\))$"
174 printed-with))
175 (should (string= (match-string 1 printed-with)
176 (match-string 2 printed-with)))
177 (should (string-match "(g[[:digit:]]+ x[[:digit:]]+ y g[[:digit:]]+)$"
178 printed-without)))
179 (let* ((print-circle t)
180 (printed-with (let ((print-gensym t))
181 (print-tests--prin1-to-string syms)))
182 (printed-without (let ((print-gensym nil))
183 (print-tests--prin1-to-string syms))))
184 (should (string-match "(#1=#:g[[:digit:]]+ #:x[[:digit:]]+ #:y #1#)$"
185 printed-with))
186 (should (string-match "(g[[:digit:]]+ x[[:digit:]]+ y g[[:digit:]]+)$"
187 printed-without)))))
188
189(print-tests--deftest print-tests-continuous-numbering ()
190 "Printing observes `print-continuous-numbering'."
191 ;; cl-print does not support print-continuous-numbering.
192 :expected-result (if (eq (symbol-function #'print-tests--prin1-to-string)
193 #'cl-prin1-to-string)
194 :failed :passed)
195 (let* ((x (list 1))
196 (y "hello")
197 (g (gensym))
198 (g2 (gensym))
199 (print-circle t)
200 (print-gensym t))
201 (let ((print-continuous-numbering t)
202 (print-number-table nil))
203 (should (string-match
204 "(#1=(1) #1# #2=\"hello\" #2#)(#3=#:g[[:digit:]]+ #3#)(#1# #2# #3#)#2#$"
205 (mapconcat #'print-tests--prin1-to-string
206 `((,x ,x ,y ,y) (,g ,g) (,x ,y ,g) ,y)))))
207
208 ;; This is the special case for byte-compile-output-docform
209 ;; mentioned in a comment in print_preprocess. When
210 ;; print-continuous-numbering and print-circle and print-gensym
211 ;; are all non-nil, print all gensyms with numbers even if they
212 ;; only occur once.
213 (let ((print-continuous-numbering t)
214 (print-number-table nil))
215 (should (string-match
216 "(#1=#:g[[:digit:]]+ #2=#:g[[:digit:]]+)$"
217 (print-tests--prin1-to-string (list g g2)))))))
218
219(cl-defstruct print--test a b)
220
221(print-tests--deftest print-tests-1 ()
222 "Test print code."
223 (let ((x (make-print--test :a 1 :b 2))
224 (rec (cond
225 ((eq (symbol-function #'print-tests--prin1-to-string) 'prin1-to-string)
226 "#s(print--test 1 2)")
227 ((eq (symbol-function #'print-tests--prin1-to-string) 'cl-prin1-to-string)
228 "#s(print--test :a 1 :b 2)")
229 (t (cl-assert nil)))))
230
231 (let ((print-circle nil))
232 (should (equal (print-tests--prin1-to-string `((x . ,x) (y . ,x)))
233 (format "((x . %s) (y . %s))" rec rec))))
234 (let ((print-circle t))
235 (should (equal (print-tests--prin1-to-string `((x . ,x) (y . ,x)))
236 (format "((x . #1=%s) (y . #1#))" rec))))))
237
238(print-tests--deftest print-tests-2 ()
239 (let ((x (record 'foo 1 2 3)))
240 (should (equal
241 x
242 (car (read-from-string (with-output-to-string (prin1 x))))))
243 (let ((print-circle t))
244 (should (string-match
245 "\\`(#1=#s(foo 1 2 3) #1#)\\'"
246 (print-tests--prin1-to-string (list x x)))))))
247
248(cl-defstruct (print-tests-struct
249 (:constructor print-tests-con))
250 a b c d e)
251
252(print-tests--deftest print-tests-3 ()
253 "Printing observes `print-length'."
254 (let ((long-list (make-list 5 'a))
255 (long-vec (make-vector 5 'b))
256 ;; (long-struct (print-tests-con))
257 ;; (long-string (make-string 5 ?a))
258 (print-length 4))
259 (should (equal "(a a a a ...)" (print-tests--prin1-to-string long-list)))
260 (should (equal "[b b b b ...]" (print-tests--prin1-to-string long-vec)))
261 ;; This one only prints 3 nils. Should it print 4?
262 ;; (should (equal "#s(print-tests-struct nil nil nil nil ...)"
263 ;; (print-tests--prin1-to-string long-struct)))
264 ;; This one is only supported by cl-print
265 ;; (should (equal "\"aaaa...\"" (cl-print-tests--prin1-to-string long-string)))
266 ))
267
268(print-tests--deftest print-tests-4 ()
269 "Printing observes `print-level'."
270 (let* ((deep-list '(a (b (c (d (e))))))
271 (buried-vector '(a (b (c (d [e])))))
272 (deep-struct (print-tests-con))
273 (buried-struct `(a (b (c (d ,deep-struct)))))
274 (buried-string '(a (b (c (d #("hello" 0 5 (print-test t)))))))
275 (buried-simple-string '(a (b (c (d "hello")))))
276 (print-level 4))
277 (setf (print-tests-struct-a deep-struct) deep-list)
278 (should (equal "(a (b (c (d ...))))" (print-tests--prin1-to-string deep-list)))
279 (should (equal "(a (b (c (d \"hello\"))))"
280 (print-tests--prin1-to-string buried-simple-string)))
281 (cond
282 ((eq (symbol-function #'print-tests--prin1-to-string) #'prin1-to-string)
283 (should (equal "(a (b (c (d [e]))))" (print-tests--prin1-to-string buried-vector)))
284 (should (equal "(a (b (c (d #s(print-tests-struct ... nil nil nil nil)))))"
285 (print-tests--prin1-to-string buried-struct)))
286 (should (equal "(a (b (c (d #(\"hello\" 0 5 ...)))))"
287 (print-tests--prin1-to-string buried-string)))
288 (should (equal "#s(print-tests-struct (a (b (c ...))) nil nil nil nil)"
289 (print-tests--prin1-to-string deep-struct))))
290
291 ((eq (symbol-function #'print-tests--prin1-to-string) #'cl-prin1-to-string)
292 (should (equal "(a (b (c (d ...))))" (print-tests--prin1-to-string buried-vector)))
293 (should (equal "(a (b (c (d ...))))" (print-tests--prin1-to-string buried-struct)))
294 (should (equal "(a (b (c (d ...))))" (print-tests--prin1-to-string buried-string)))
295 (should (equal "#s(print-tests-struct :a (a (b (c ...))) :b nil :c nil :d nil :e nil)"
296 (print-tests--prin1-to-string deep-struct))))
297 (t (cl-assert nil)))))
298
299(print-tests--deftest print-tests-5 ()
300 "Printing observes `print-quoted'."
301 (let ((quoted-stuff '('a #'b `(,c ,@d))))
302 (let ((print-quoted t))
303 (should (equal "('a #'b `(,c ,@d))"
304 (print-tests--prin1-to-string quoted-stuff))))
305 (let ((print-quoted nil))
306 (should (equal "((quote a) (function b) (\\` ((\\, c) (\\,@ d))))"
307 (print-tests--prin1-to-string quoted-stuff))))))
308
309(print-tests--deftest print-tests-strings ()
310 "Can print strings and propertized strings."
311 (let* ((str1 "abcdefghij")
312 (str2 #("abcdefghij" 3 6 (bold t) 7 9 (italic t)))
313 (str3 #("abcdefghij" 0 10 (test t)))
314 (obj '(a b))
315 ;; Since the byte compiler reuses string literals,
316 ;; and the put-text-property call is destructive, use
317 ;; copy-sequence to make a new string.
318 (str4 (copy-sequence "abcdefghij")))
319 (put-text-property 0 5 'test obj str4)
320 (put-text-property 7 10 'test obj str4)
321
322 (should (equal "\"abcdefghij\"" (print-tests--prin1-to-string str1)))
323 (should (equal "#(\"abcdefghij\" 3 6 (bold t) 7 9 (italic t))"
324 (print-tests--prin1-to-string str2)))
325 (should (equal "#(\"abcdefghij\" 0 10 (test t))"
326 (print-tests--prin1-to-string str3)))
327 (let ((print-circle nil))
328 (should
329 (equal
330 "#(\"abcdefghij\" 0 5 (test (a b)) 7 10 (test (a b)))"
331 (print-tests--prin1-to-string str4))))
332 (let ((print-circle t))
333 (should
334 (equal
335 "#(\"abcdefghij\" 0 5 (test #1=(a b)) 7 10 (test #1#))"
336 (print-tests--prin1-to-string str4))))))
337
338(print-tests--deftest print-circle ()
339 (let ((x '(#1=(a . #1#) #1#)))
340 (let ((print-circle nil))
341 (should (string-match "\\`((a . #[0-9]) (a . #[0-9]))\\'"
342 (print-tests--prin1-to-string x))))
343 (let ((print-circle t))
344 (should (equal "(#1=(a . #1#) #1#)" (print-tests--prin1-to-string x))))))
345
346(print-tests--deftest print-circle-2 ()
347 ;; Bug#31146.
348 (let ((x '(0 . #1=(0 . #1#))))
349 (let ((print-circle nil))
350 (should (string-match "\\`(0\\( 0\\)* . #[0-9]+)\\'"
351 (print-tests--prin1-to-string x))))
352 (let ((print-circle t))
353 (should (equal "(0 . #1=(0 . #1#))" (print-tests--prin1-to-string x))))))
354
355(print-tests--deftest error-message-string-circular ()
356 (let ((err (list 'error)))
357 (setcdr err err)
358 (should-error (error-message-string err) :type 'circular-list)))
359
360(print-tests--deftest print-hash-table-test ()
361 (should
362 (string-match
363 "data (2 3)"
364 (let ((h (make-hash-table)))
365 (puthash 1 2 h)
366 (puthash 2 3 h)
367 (remhash 1 h)
368 (format "%S" h))))
369
370 (should
371 (string-match
372 "data ()"
373 (let ((h (make-hash-table)))
374 (let ((print-length 0))
375 (format "%S" h)))))
376
377 (should
378 (string-match
379 "data (99 99)"
380 (let ((h (make-hash-table)))
381 (dotimes (i 100)
382 (puthash i i h))
383 (dotimes (i 99)
384 (remhash i h))
385 (let ((print-length 1))
386 (format "%S" h))))))
387
388(print-tests--deftest print-integers-as-characters ()
389 ;; Bug#44155.
390 (let* ((print-integers-as-characters t)
391 (chars '(?? ?\; ?\( ?\) ?\{ ?\} ?\[ ?\] ?\" ?\' ?\\ ?f ?~ ?Á 32
392 ?\n ?\r ?\t ?\b ?\f ?\a ?\v ?\e ?\d))
393 (nums '(-1 -65 0 1 31 #x80 #x9f #x110000 #x3fff80 #x3fffff))
394 (nonprints '(#xd800 #xdfff #x030a #xffff #x2002 #x200c))
395 (printed-chars (print-tests--prin1-to-string chars))
396 (printed-nums (print-tests--prin1-to-string nums))
397 (printed-nonprints (print-tests--prin1-to-string nonprints)))
398 (should (equal (read printed-chars) chars))
399 (should (equal
400 printed-chars
401 (concat
402 "(?? ?\\; ?\\( ?\\) ?\\{ ?\\} ?\\[ ?\\] ?\\\" ?\\' ?\\\\"
403 " ?f ?~ ?Á ?\\s ?\\n ?\\r ?\\t ?\\b ?\\f 7 11 27 127)")))
404 (should (equal (read printed-nums) nums))
405 (should (equal printed-nums
406 "(-1 -65 0 1 31 128 159 1114112 4194176 4194303)"))
407 (should (equal (read printed-nonprints) nonprints))
408 (should (equal printed-nonprints
409 "(55296 57343 778 65535 8194 8204)"))))
410
411(ert-deftest test-unreadable ()
412 (should (equal (prin1-to-string (make-marker)) "#<marker in no buffer>"))
413 (let ((print-unreadable-function
414 (lambda (_object _escape)
415 "hello")))
416 (should (equal (prin1-to-string (make-marker)) "hello")))
417 (let ((print-unreadable-function
418 (lambda (_object _escape)
419 t)))
420 (should (equal (prin1-to-string (make-marker)) ""))))
421
422(ert-deftest test-dots ()
423 (should (equal (prin1-to-string 'foo.bar) "foo.bar"))
424 (should (equal (prin1-to-string '.foo) "\\.foo"))
425 (should (equal (prin1-to-string '.foo.) "\\.foo."))
426 (should (equal (prin1-to-string 'bar?bar) "bar?bar"))
427 (should (equal (prin1-to-string '\?bar) "\\?bar"))
428 (should (equal (prin1-to-string '\?bar?) "\\?bar?")))
429
430(ert-deftest test-prin1-overrides ()
431 (with-temp-buffer
432 (let ((print-length 10))
433 (prin1 (make-list 20 t) (current-buffer) t)
434 (should (= print-length 10)))
435 (goto-char (point-min))
436 (should (= (length (read (current-buffer))) 20)))
437
438 (with-temp-buffer
439 (let ((print-length 10))
440 (prin1 (make-list 20 t) (current-buffer) '((length . 5)))
441 (should (= print-length 10)))
442 (goto-char (point-min))
443 (should (= (length (read (current-buffer))) 6)))
444
445 (with-temp-buffer
446 (let ((print-length 10))
447 (prin1 (make-list 20 t) (current-buffer) '(t (length . 5)))
448 (should (= print-length 10)))
449 (goto-char (point-min))
450 (should (= (length (read (current-buffer))) 6))))
451
452(ert-deftest test-prin1-to-string-overrides ()
453 (let ((print-length 10))
454 (should
455 (= (length (car (read-from-string
456 (prin1-to-string (make-list 20 t) nil t))))
457 20)))
458
459 (let ((print-length 10))
460 (should
461 (= (length (car (read-from-string
462 (prin1-to-string (make-list 20 t) nil
463 '((length . 5))))))
464 6)))
465
466 (should-error (prin1-to-string 'foo nil 'a))
467 (should-error (prin1-to-string 'foo nil '(a)))
468 (should-error (prin1-to-string 'foo nil '(t . b)))
469 (should-error (prin1-to-string 'foo nil '(t b)))
470 (should-error (prin1-to-string 'foo nil '((a . b) b)))
471 (should-error (prin1-to-string 'foo nil '((length . 10) . b))))
472
473(ert-deftest print-deeply-nested ()
474 ;; Check that we can print a deeply nested data structure correctly.
475 (let ((print-circle t))
476 (let ((levels 10000)
477 (x 'a)
478 (prefix nil)
479 (suffix nil))
480 (dotimes (_ levels)
481 (setq x (list (vector (record 'r x))))
482 (push "([#s(r " prefix)
483 (push ")])" suffix))
484 (let ((expected (concat (apply #'concat prefix)
485 "a"
486 (apply #'concat suffix))))
487 (should (equal (prin1-to-string x) expected))))))
488
489(defun print-test-rho (lead loop)
490 "A circular iota list with LEAD elements followed by LOOP in circle."
491 (let ((l (number-sequence 1 (+ lead loop))))
492 (setcdr (nthcdr (+ lead loop -1) l) (nthcdr lead l))
493 l))
494
495(ert-deftest print-circular ()
496 ;; Check printing of rho-shaped circular lists such as (1 2 3 4 5 4 5 4 . #6)
497 ;; when `print-circle' is nil. The exact output may differ since the number
498 ;; of elements printed of the looping part can vary depending on when the
499 ;; circularity was detected.
500 (dotimes (lead 7)
501 (ert-info ((prin1-to-string lead) :prefix "lead: ")
502 (dolist (loop (number-sequence 1 7))
503 (ert-info ((prin1-to-string loop) :prefix "loop: ")
504 (let* ((rho (print-test-rho lead loop))
505 (print-circle nil)
506 (str (prin1-to-string rho)))
507 (should (string-match (rx "("
508 (group (+ (+ digit) " "))
509 ". #" (group (+ digit)) ")")
510 str))
511 (let* ((g1 (match-string 1 str))
512 (g2 (match-string 2 str))
513 (numbers (mapcar #'string-to-number (split-string g1)))
514 (loopback-index (string-to-number g2)))
515 ;; Split the numbers in the lead and loop part.
516 (should (< lead (length numbers)))
517 (should (<= lead loopback-index))
518 (should (< loopback-index (length numbers)))
519 (let ((lead-part (take lead numbers))
520 (loop-part (nthcdr lead numbers)))
521 ;; The lead part must match exactly.
522 (should (equal lead-part (number-sequence 1 lead)))
523 ;; The loop part is at least LOOP long: make sure it matches.
524 (should (>= (length loop-part) loop))
525 (let ((expected-loop-part
526 (mapcar (lambda (x) (+ lead 1 (% x loop)))
527 (number-sequence 0 (1- (length loop-part))))))
528 (should (equal loop-part expected-loop-part))
529 ;; The loopback index must match the length of the
530 ;; loop part.
531 (should (equal (% (- (length numbers) loopback-index) loop)
532 0)))))))))))
533
534(ert-deftest test-print-unreadable-function-buffer ()
535 (let* ((buffer nil)
536 (callback-buffer nil)
537 (str (with-temp-buffer
538 (setq buffer (current-buffer))
539 (let ((print-unreadable-function
540 (lambda (_object _escape)
541 (setq callback-buffer (current-buffer))
542 "tata")))
543 (prin1-to-string (make-marker))))))
544 (should (eq callback-buffer buffer))
545 (should (equal str "tata"))))
546
61(provide 'print-tests) 547(provide 'print-tests)
62;;; print-tests.el ends here 548;;; print-tests.el ends here
diff --git a/test/src/process-tests.el b/test/src/process-tests.el
index b26f9391909..7d3d9eb72b8 100644
--- a/test/src/process-tests.el
+++ b/test/src/process-tests.el
@@ -1,19 +1,21 @@
1;;; process-tests.el --- Testing the process facilities 1;;; process-tests.el --- Testing the process facilities -*- lexical-binding: t -*-
2 2
3;; Copyright (C) 2013-2017 Free Software Foundation, Inc. 3;; Copyright (C) 2013-2022 Free Software Foundation, Inc.
4 4
5;; This program is free software; you can redistribute it and/or modify 5;; This file is part of GNU Emacs.
6
7;; GNU Emacs is free software: you can redistribute it and/or modify
6;; it under the terms of the GNU General Public License as published by 8;; it under the terms of the GNU General Public License as published by
7;; the Free Software Foundation, either version 3 of the License, or 9;; the Free Software Foundation, either version 3 of the License, or
8;; (at your option) any later version. 10;; (at your option) any later version.
9 11
10;; This program is distributed in the hope that it will be useful, 12;; GNU Emacs is distributed in the hope that it will be useful,
11;; but WITHOUT ANY WARRANTY; without even the implied warranty of 13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
12;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13;; GNU General Public License for more details. 15;; GNU General Public License for more details.
14 16
15;; You should have received a copy of the GNU General Public License 17;; You should have received a copy of the GNU General Public License
16;; along with this program. If not, see <https://www.gnu.org/licenses/>. 18;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
17 19
18;;; Commentary: 20;;; Commentary:
19 21
@@ -21,61 +23,74 @@
21 23
22;;; Code: 24;;; Code:
23 25
26(require 'cl-lib)
24(require 'ert) 27(require 'ert)
28(require 'ert-x) ; ert-with-temp-directory
29(require 'puny)
30(require 'subr-x)
31(require 'dns)
32(require 'url-http)
33
34(declare-function thread-last-error "thread.c")
35(declare-function thread-join "thread.c")
36(declare-function make-thread "thread.c")
25 37
26;; Timeout in seconds; the test fails if the timeout is reached. 38;; Timeout in seconds; the test fails if the timeout is reached.
27(defvar process-test-sentinel-wait-timeout 2.0) 39(defvar process-test-sentinel-wait-timeout 2.0)
28 40
29;; Start a process that exits immediately. Call WAIT-FUNCTION, 41(defun process-test-wait-for-sentinel (proc exit-status &optional wait-function)
30;; possibly multiple times, to wait for the process to complete. 42 "Set a sentinel on PROC and wait for it to be called with EXIT-STATUS.
31(defun process-test-sentinel-wait-function-working-p (wait-function) 43Call WAIT-FUNCTION, possibly multiple times, to wait for the
32 (let ((proc (start-process "test" nil "bash" "-c" "exit 20")) 44process to complete."
45 (let ((wait-function (or wait-function #'accept-process-output))
33 (sentinel-called nil) 46 (sentinel-called nil)
34 (start-time (float-time))) 47 (start-time (float-time)))
35 (set-process-sentinel proc (lambda (proc msg) 48 (set-process-sentinel proc (lambda (_proc _msg)
36 (setq sentinel-called t))) 49 (setq sentinel-called t)))
37 (while (not (or sentinel-called 50 (while (not (or sentinel-called
38 (> (- (float-time) start-time) 51 (> (- (float-time) start-time)
39 process-test-sentinel-wait-timeout))) 52 process-test-sentinel-wait-timeout)))
40 (funcall wait-function)) 53 (funcall wait-function))
41 (cl-assert (eq (process-status proc) 'exit)) 54 (should sentinel-called)
42 (cl-assert (= (process-exit-status proc) 20)) 55 (should (eq (process-status proc) 'exit))
43 sentinel-called)) 56 (should (= (process-exit-status proc) exit-status))))
44 57
45(ert-deftest process-test-sentinel-accept-process-output () 58(ert-deftest process-test-sentinel-accept-process-output ()
46 (skip-unless (executable-find "bash")) 59 (skip-unless (executable-find "bash"))
47 (should (process-test-sentinel-wait-function-working-p 60 (with-timeout (60 (ert-fail "Test timed out"))
48 #'accept-process-output))) 61 (let ((proc (start-process "test" nil "bash" "-c" "exit 20")))
62 (should (process-test-wait-for-sentinel proc 20)))))
49 63
50(ert-deftest process-test-sentinel-sit-for () 64(ert-deftest process-test-sentinel-sit-for ()
51 (skip-unless (executable-find "bash")) 65 (skip-unless (executable-find "bash"))
52 (should 66 (with-timeout (60 (ert-fail "Test timed out"))
53 (process-test-sentinel-wait-function-working-p (lambda () (sit-for 0.01 t))))) 67 (let ((proc (start-process "test" nil "bash" "-c" "exit 20")))
68 (should (process-test-wait-for-sentinel
69 proc 20 (lambda () (sit-for 0.01 t)))))))
54 70
55(when (eq system-type 'windows-nt) 71(when (eq system-type 'windows-nt)
56 (ert-deftest process-test-quoted-batfile () 72 (ert-deftest process-test-quoted-batfile ()
57 "Check that Emacs hides CreateProcess deficiency (bug#18745)." 73 "Check that Emacs hides CreateProcess deficiency (bug#18745)."
58 (let (batfile) 74 (ert-with-temp-file batfile
59 (unwind-protect 75 ;; CreateProcess will fail when both the bat file and 1st
60 (progn 76 ;; argument are quoted, so include spaces in both of those
61 ;; CreateProcess will fail when both the bat file and 1st 77 ;; to force quoting.
62 ;; argument are quoted, so include spaces in both of those 78 :prefix "echo args"
63 ;; to force quoting. 79 :suffix ".bat"
64 (setq batfile (make-temp-file "echo args" nil ".bat")) 80 (with-temp-file batfile
65 (with-temp-file batfile 81 (insert "@echo arg1=%1, arg2=%2\n"))
66 (insert "@echo arg1=%1, arg2=%2\n")) 82 (with-temp-buffer
67 (with-temp-buffer 83 (call-process batfile nil '(t t) t "x &y")
68 (call-process batfile nil '(t t) t "x &y") 84 (should (string= (buffer-string) "arg1=\"x &y\", arg2=\n")))
69 (should (string= (buffer-string) "arg1=\"x &y\", arg2=\n"))) 85 (with-temp-buffer
70 (with-temp-buffer 86 (call-process-shell-command
71 (call-process-shell-command 87 (mapconcat #'shell-quote-argument (list batfile "x &y") " ")
72 (mapconcat #'shell-quote-argument (list batfile "x &y") " ") 88 nil '(t t) t)
73 nil '(t t) t) 89 (should (string= (buffer-string) "arg1=\"x &y\", arg2=\n"))))))
74 (should (string= (buffer-string) "arg1=\"x &y\", arg2=\n"))))
75 (when batfile (delete-file batfile))))))
76 90
77(ert-deftest process-test-stderr-buffer () 91(ert-deftest process-test-stderr-buffer ()
78 (skip-unless (executable-find "bash")) 92 (skip-unless (executable-find "bash"))
93 (with-timeout (60 (ert-fail "Test timed out"))
79 (let* ((stdout-buffer (generate-new-buffer "*stdout*")) 94 (let* ((stdout-buffer (generate-new-buffer "*stdout*"))
80 (stderr-buffer (generate-new-buffer "*stderr*")) 95 (stderr-buffer (generate-new-buffer "*stderr*"))
81 (proc (make-process :name "test" 96 (proc (make-process :name "test"
@@ -84,28 +99,19 @@
84 "echo hello stderr! >&2; " 99 "echo hello stderr! >&2; "
85 "exit 20")) 100 "exit 20"))
86 :buffer stdout-buffer 101 :buffer stdout-buffer
87 :stderr stderr-buffer)) 102 :stderr stderr-buffer)))
88 (sentinel-called nil) 103 (process-test-wait-for-sentinel proc 20)
89 (start-time (float-time)))
90 (set-process-sentinel proc (lambda (proc msg)
91 (setq sentinel-called t)))
92 (while (not (or sentinel-called
93 (> (- (float-time) start-time)
94 process-test-sentinel-wait-timeout)))
95 (accept-process-output))
96 (cl-assert (eq (process-status proc) 'exit))
97 (cl-assert (= (process-exit-status proc) 20))
98 (should (with-current-buffer stdout-buffer 104 (should (with-current-buffer stdout-buffer
99 (goto-char (point-min)) 105 (goto-char (point-min))
100 (looking-at "hello stdout!"))) 106 (looking-at "hello stdout!")))
101 (should (with-current-buffer stderr-buffer 107 (should (with-current-buffer stderr-buffer
102 (goto-char (point-min)) 108 (goto-char (point-min))
103 (looking-at "hello stderr!"))))) 109 (looking-at "hello stderr!"))))))
104 110
105(ert-deftest process-test-stderr-filter () 111(ert-deftest process-test-stderr-filter ()
106 (skip-unless (executable-find "bash")) 112 (skip-unless (executable-find "bash"))
107 (let* ((sentinel-called nil) 113 (with-timeout (60 (ert-fail "Test timed out"))
108 (stderr-sentinel-called nil) 114 (let* ((stderr-sentinel-called nil)
109 (stdout-output nil) 115 (stdout-output nil)
110 (stderr-output nil) 116 (stderr-output nil)
111 (stdout-buffer (generate-new-buffer "*stdout*")) 117 (stdout-buffer (generate-new-buffer "*stdout*"))
@@ -117,36 +123,62 @@
117 (concat "echo hello stdout!; " 123 (concat "echo hello stdout!; "
118 "echo hello stderr! >&2; " 124 "echo hello stderr! >&2; "
119 "exit 20")) 125 "exit 20"))
120 :stderr stderr-proc)) 126 :stderr stderr-proc)))
121 (start-time (float-time))) 127 (set-process-filter proc (lambda (_proc input)
122 (set-process-filter proc (lambda (proc input)
123 (push input stdout-output))) 128 (push input stdout-output)))
124 (set-process-sentinel proc (lambda (proc msg) 129 (set-process-filter stderr-proc (lambda (_proc input)
125 (setq sentinel-called t)))
126 (set-process-filter stderr-proc (lambda (proc input)
127 (push input stderr-output))) 130 (push input stderr-output)))
128 (set-process-sentinel stderr-proc (lambda (proc input) 131 (set-process-sentinel stderr-proc (lambda (_proc _input)
129 (setq stderr-sentinel-called t))) 132 (setq stderr-sentinel-called t)))
130 (while (not (or sentinel-called 133 (process-test-wait-for-sentinel proc 20)
131 (> (- (float-time) start-time)
132 process-test-sentinel-wait-timeout)))
133 (accept-process-output))
134 (cl-assert (eq (process-status proc) 'exit))
135 (cl-assert (= (process-exit-status proc) 20))
136 (should sentinel-called)
137 (should (equal 1 (with-current-buffer stdout-buffer 134 (should (equal 1 (with-current-buffer stdout-buffer
138 (point-max)))) 135 (point-max))))
139 (should (equal "hello stdout!\n" 136 (should (equal "hello stdout!\n"
140 (mapconcat #'identity (nreverse stdout-output) ""))) 137 (mapconcat #'identity (nreverse stdout-output))))
141 (should stderr-sentinel-called) 138 (should stderr-sentinel-called)
142 (should (equal 1 (with-current-buffer stderr-buffer 139 (should (equal 1 (with-current-buffer stderr-buffer
143 (point-max)))) 140 (point-max))))
144 (should (equal "hello stderr!\n" 141 (should (equal "hello stderr!\n"
145 (mapconcat #'identity (nreverse stderr-output) ""))))) 142 (mapconcat #'identity (nreverse stderr-output)))))))
143
144(ert-deftest set-process-filter-t ()
145 "Test setting process filter to t and back." ;; Bug#36591
146 (with-timeout (60 (ert-fail "Test timed out"))
147 (with-temp-buffer
148 (let* ((print-level nil)
149 (print-length nil)
150 (proc (start-process
151 "test proc" (current-buffer)
152 (concat invocation-directory invocation-name)
153 "-Q" "--batch" "--eval"
154 (prin1-to-string
155 '(let ((s nil) (count 0))
156 (while (setq s (read-from-minibuffer
157 (format "%d> " count)))
158 (princ s)
159 (princ "\n")
160 (setq count (1+ count))))))))
161 (set-process-query-on-exit-flag proc nil)
162 (send-string proc "one\n")
163 (while (not (equal (buffer-substring (pos-bol) (point-max))
164 "1> "))
165 (accept-process-output proc)) ; Read "one".
166 (should (equal (buffer-string) "0> one\n1> "))
167 (set-process-filter proc t) ; Stop reading from proc.
168 (send-string proc "two\n")
169 (should-not
170 (accept-process-output proc 1)) ; Can't read "two" yet.
171 (should (equal (buffer-string) "0> one\n1> "))
172 (set-process-filter proc nil) ; Resume reading from proc.
173 (while (not (equal (buffer-substring (pos-bol) (point-max))
174 "2> "))
175 (accept-process-output proc)) ; Read "Two".
176 (should (equal (buffer-string) "0> one\n1> two\n2> "))))))
146 177
147(ert-deftest start-process-should-not-modify-arguments () 178(ert-deftest start-process-should-not-modify-arguments ()
148 "`start-process' must not modify its arguments in-place." 179 "`start-process' must not modify its arguments in-place."
149 ;; See bug#21831. 180 ;; See bug#21831.
181 (with-timeout (60 (ert-fail "Test timed out"))
150 (let* ((path (pcase system-type 182 (let* ((path (pcase system-type
151 ((or 'windows-nt 'ms-dos) 183 ((or 'windows-nt 'ms-dos)
152 ;; Make sure the file name uses forward slashes. 184 ;; Make sure the file name uses forward slashes.
@@ -160,7 +192,832 @@
160 (should (process-live-p (condition-case nil 192 (should (process-live-p (condition-case nil
161 (start-process "" nil path) 193 (start-process "" nil path)
162 (error nil)))) 194 (error nil))))
163 (should (equal path samepath)))) 195 (should (equal path samepath)))))
196
197(ert-deftest make-process/noquery-stderr ()
198 "Checks that Bug#30031 is fixed."
199 (skip-unless (executable-find "sleep"))
200 (with-timeout (60 (ert-fail "Test timed out"))
201 (with-temp-buffer
202 (let* ((previous-processes (process-list))
203 (process (make-process :name "sleep"
204 :command '("sleep" "1h")
205 :noquery t
206 :connection-type 'pipe
207 :stderr (current-buffer))))
208 (unwind-protect
209 (let ((new-processes (cl-set-difference (process-list)
210 previous-processes
211 :test #'eq)))
212 (should new-processes)
213 (dolist (process new-processes)
214 (should-not (process-query-on-exit-flag process))))
215 (kill-process process))))))
216
217;; Return t if OUTPUT could have been generated by merging the INPUTS somehow.
218(defun process-tests--mixable (output &rest inputs)
219 (while (and output (let ((ins inputs))
220 (while (and ins (not (eq (car (car ins)) (car output))))
221 (setq ins (cdr ins)))
222 (if ins
223 (setcar ins (cdr (car ins))))
224 ins))
225 (setq output (cdr output)))
226 (not (apply #'append output inputs)))
227
228(ert-deftest make-process/mix-stderr ()
229 "Check that `make-process' mixes the output streams if STDERR is nil."
230 (skip-unless (executable-find "bash"))
231 (with-timeout (60 (ert-fail "Test timed out"))
232 ;; Frequent random (?) failures on hydra.nixos.org, with no process output.
233 ;; Maybe this test should be tagged unstable? See bug#31214.
234 (skip-unless (not (getenv "EMACS_HYDRA_CI")))
235 (with-temp-buffer
236 (let ((process (make-process
237 :name "mix-stderr"
238 :command (list "bash" "-c"
239 "echo stdout && echo stderr >&2")
240 :buffer (current-buffer)
241 :sentinel #'ignore
242 :noquery t
243 :connection-type 'pipe)))
244 (while (or (accept-process-output process)
245 (process-live-p process)))
246 (should (eq (process-status process) 'exit))
247 (should (eq (process-exit-status process) 0))
248 (should (process-tests--mixable (string-to-list (buffer-string))
249 (string-to-list "stdout\n")
250 (string-to-list "stderr\n")))))))
251
252(ert-deftest make-process-w32-debug-spawn-error ()
253 "Check that debugger runs on `make-process' failure (Bug#33016)."
254 (skip-unless (eq system-type 'windows-nt))
255 (with-timeout (60 (ert-fail "Test timed out"))
256 (let* ((debug-on-error t)
257 (have-called-debugger nil)
258 (debugger (lambda (&rest _)
259 (setq have-called-debugger t)
260 ;; Allow entering the debugger later in the same
261 ;; test run, before going back to the command
262 ;; loop.
263 (setq internal-when-entered-debugger -1))))
264 (should (eq :got-error ;; NOTE: `should-error' would inhibit debugger.
265 (condition-case-unless-debug ()
266 ;; Emacs doesn't search for absolute filenames, so
267 ;; the error will be hit in the w32 process spawn
268 ;; code.
269 (make-process :name "test" :command '("c:/No-Such-Command"))
270 (error :got-error))))
271 (should have-called-debugger))))
272
273(defun make-process/test-connection-type (ttys &rest args)
274 "Make a process and check whether its standard streams match TTYS.
275This calls `make-process', passing ARGS to adjust how the process
276is created. TTYS should be a list of 3 boolean values,
277indicating whether the subprocess's stdin, stdout, and stderr
278should be a TTY, respectively."
279 (declare (indent 1))
280 (let* (;; MS-Windows doesn't support communicating via pty.
281 (ttys (if (eq system-type 'windows-nt) '(nil nil nil) ttys))
282 (expected-output (concat (and (nth 0 ttys) "stdin\n")
283 (and (nth 1 ttys) "stdout\n")
284 (and (nth 2 ttys) "stderr\n")))
285 (stdout-buffer (generate-new-buffer "*stdout*"))
286 (proc (apply
287 #'make-process
288 :name "test"
289 :command (list "sh" "-c"
290 (concat "if [ -t 0 ]; then echo stdin; fi; "
291 "if [ -t 1 ]; then echo stdout; fi; "
292 "if [ -t 2 ]; then echo stderr; fi"))
293 :buffer stdout-buffer
294 args)))
295 (should (eq (and (process-tty-name proc 'stdin) t) (nth 0 ttys)))
296 (should (eq (and (process-tty-name proc 'stdout) t) (nth 1 ttys)))
297 (should (eq (and (process-tty-name proc 'stderr) t) (nth 2 ttys)))
298 (process-test-wait-for-sentinel proc 0)
299 (should (equal (with-current-buffer stdout-buffer (buffer-string))
300 expected-output))))
301
302(ert-deftest make-process/connection-type/pty ()
303 (skip-unless (executable-find "sh"))
304 (make-process/test-connection-type '(t t t)
305 :connection-type 'pty))
306
307(ert-deftest make-process/connection-type/pty-2 ()
308 (skip-unless (executable-find "sh"))
309 (make-process/test-connection-type '(t t t)
310 :connection-type '(pty . pty)))
311
312(ert-deftest make-process/connection-type/pipe ()
313 (skip-unless (executable-find "sh"))
314 (make-process/test-connection-type '(nil nil nil)
315 :connection-type 'pipe))
316
317(ert-deftest make-process/connection-type/pipe-2 ()
318 (skip-unless (executable-find "sh"))
319 (make-process/test-connection-type '(nil nil nil)
320 :connection-type '(pipe . pipe)))
321
322(ert-deftest make-process/connection-type/in-pty ()
323 (skip-unless (executable-find "sh"))
324 (make-process/test-connection-type '(t nil nil)
325 :connection-type '(pty . pipe)))
326
327(ert-deftest make-process/connection-type/out-pty ()
328 (skip-unless (executable-find "sh"))
329 (make-process/test-connection-type '(nil t t)
330 :connection-type '(pipe . pty)))
331
332(ert-deftest make-process/connection-type/pty-with-stderr-buffer ()
333 (skip-unless (executable-find "sh"))
334 (let ((stderr-buffer (generate-new-buffer "*stderr*")))
335 (make-process/test-connection-type '(t t nil)
336 :connection-type 'pty :stderr stderr-buffer)))
337
338(ert-deftest make-process/connection-type/out-pty-with-stderr-buffer ()
339 (skip-unless (executable-find "sh"))
340 (let ((stderr-buffer (generate-new-buffer "*stderr*")))
341 (make-process/test-connection-type '(nil t nil)
342 :connection-type '(pipe . pty) :stderr stderr-buffer)))
343
344(ert-deftest make-process/file-handler/found ()
345 "Check that the `:file-handler’ argument of `make-process’
346works as expected if a file name handler is found."
347 (with-timeout (60 (ert-fail "Test timed out"))
348 (let ((file-handler-calls 0))
349 (cl-flet ((file-handler
350 (&rest args)
351 (should (equal default-directory "test-handler:/dir/"))
352 (should (equal args '(make-process :name "name"
353 :command ("/some/binary")
354 :file-handler t)))
355 (cl-incf file-handler-calls)
356 'fake-process))
357 (let ((file-name-handler-alist (list (cons (rx bos "test-handler:")
358 #'file-handler)))
359 (default-directory "test-handler:/dir/"))
360 (should (eq (make-process :name "name"
361 :command '("/some/binary")
362 :file-handler t)
363 'fake-process))
364 (should (= file-handler-calls 1)))))))
365
366(ert-deftest make-process/file-handler/not-found ()
367 "Check that the `:file-handler’ argument of `make-process’
368works as expected if no file name handler is found."
369 (with-timeout (60 (ert-fail "Test timed out"))
370 (let ((file-name-handler-alist ())
371 (default-directory invocation-directory)
372 (program (expand-file-name invocation-name invocation-directory)))
373 (should (processp (make-process :name "name"
374 :command (list program "--version")
375 :file-handler t))))))
376
377(ert-deftest make-process/file-handler/disable ()
378 "Check `make-process’ works as expected if it shouldn’t use the
379file name handler."
380 (with-timeout (60 (ert-fail "Test timed out"))
381 (let ((file-name-handler-alist (list (cons (rx bos "test-handler:")
382 #'process-tests--file-handler)))
383 (default-directory "test-handler:/dir/")
384 (program (expand-file-name invocation-name invocation-directory)))
385 (should (processp (make-process :name "name"
386 :command (list program "--version")))))))
387
388(defun process-tests--file-handler (operation &rest _args)
389 (cl-ecase operation
390 (unhandled-file-name-directory "/")
391 (make-process (ert-fail "file name handler called unexpectedly"))))
392
393(put #'process-tests--file-handler 'operations
394 '(unhandled-file-name-directory make-process))
395
396(ert-deftest make-process/stop ()
397 "Check that `make-process' doesn't accept a `:stop' key.
398See Bug#30460."
399 (with-timeout (60 (ert-fail "Test timed out"))
400 (should-error
401 (make-process :name "test"
402 :command (list (expand-file-name invocation-name
403 invocation-directory))
404 :stop t))))
405
406;; The following tests require working DNS
407
408;; This will need updating when IANA assign more IPv6 global ranges.
409(defun ipv6-is-available ()
410 (and (featurep 'make-network-process '(:family ipv6))
411 (cl-rassoc-if
412 (lambda (elt)
413 (and (eq 9 (length elt))
414 (= (logand (aref elt 0) #xe000) #x2000)))
415 (network-interface-list))))
416
417;; Check if the Internet seems to be working. Mainly to pacify
418;; Debian's CI system.
419(defvar internet-is-working
420 (progn
421 (require 'dns)
422 (dns-query "google.com")))
423
424(ert-deftest lookup-family-specification ()
425 "`network-lookup-address-info' should only accept valid family symbols."
426 (skip-unless internet-is-working)
427 (with-timeout (60 (ert-fail "Test timed out"))
428 (should-error (network-lookup-address-info "localhost" 'both))
429 (should (network-lookup-address-info "localhost" 'ipv4))
430 (when (ipv6-is-available)
431 (should (network-lookup-address-info "localhost" 'ipv6)))))
432
433(ert-deftest lookup-hints-specification ()
434 "`network-lookup-address-info' should only accept valid hints arg."
435 (should-error (network-lookup-address-info "1.1.1.1" nil t))
436 (should-error (network-lookup-address-info "1.1.1.1" 'ipv4 t))
437 (should (network-lookup-address-info "1.1.1.1" nil 'numeric))
438 (should (network-lookup-address-info "1.1.1.1" 'ipv4 'numeric))
439 (when (ipv6-is-available)
440 (should-error (network-lookup-address-info "::1" nil t))
441 (should-error (network-lookup-address-info "::1" 'ipv6 't))
442 (should (network-lookup-address-info "::1" nil 'numeric))
443 (should (network-lookup-address-info "::1" 'ipv6 'numeric))))
444
445(ert-deftest lookup-hints-values ()
446 "`network-lookup-address-info' should succeed/fail in looking up various numeric IP addresses."
447 (let ((ipv4-invalid-addrs
448 '("localhost" "343.1.2.3" "1.2.3.4.5"))
449 ;; These are valid for IPv4 but invalid for IPv6
450 (ipv4-addrs
451 '("127.0.0.1" "127.0.1" "127.1" "127" "1" "0"
452 "0xe3010203" "0xe3.1.2.3" "227.0x1.2.3"
453 "034300201003" "0343.1.2.3" "227.001.2.3"))
454 (ipv6-only-invalid-addrs
455 '("fe80:1" "e301:203:1" "e301::203::1"
456 "1:2:3:4:5:6:7:8:9" "0xe301:203::1"
457 "343:10001:2::3"
458 ;; "00343:1:2::3" is invalid on GNU/Linux and FreeBSD, but
459 ;; valid on macOS. macOS is wrong here, but such is life.
460 ))
461 ;; These are valid for IPv6 but invalid for IPv4
462 (ipv6-addrs
463 '("fe80::1" "e301::203:1" "e301:203::1"
464 "e301:0203::1" "::1" "::0"
465 "0343:1:2::3" "343:001:2::3")))
466 (dolist (a ipv4-invalid-addrs)
467 (should-not (network-lookup-address-info a nil 'numeric))
468 (should-not (network-lookup-address-info a 'ipv4 'numeric)))
469 (dolist (a ipv6-addrs)
470 (should-not (network-lookup-address-info a 'ipv4 'numeric)))
471 (dolist (a ipv4-addrs)
472 (should (network-lookup-address-info a nil 'numeric))
473 (should (network-lookup-address-info a 'ipv4 'numeric)))
474 (when (ipv6-is-available)
475 (dolist (a ipv4-addrs)
476 (should-not (network-lookup-address-info a 'ipv6 'numeric)))
477 (dolist (a ipv6-only-invalid-addrs)
478 (should-not (network-lookup-address-info a 'ipv6 'numeric)))
479 (dolist (a ipv6-addrs)
480 (should (network-lookup-address-info a nil 'numeric))
481 (should (network-lookup-address-info a 'ipv6 'numeric))
482 (should (network-lookup-address-info (upcase a) nil 'numeric))
483 (should (network-lookup-address-info (upcase a) 'ipv6 'numeric))))))
484
485(ert-deftest lookup-unicode-domains ()
486 "Unicode domains should fail."
487 (skip-unless internet-is-working)
488 (with-timeout (60 (ert-fail "Test timed out"))
489 (should-error (network-lookup-address-info "faß.de"))
490 (should (network-lookup-address-info (puny-encode-domain "faß.de")))))
491
492(ert-deftest unibyte-domain-name ()
493 "Unibyte domain names should work."
494 (skip-unless internet-is-working)
495 (with-timeout (60 (ert-fail "Test timed out"))
496 (should (network-lookup-address-info (string-to-unibyte "google.com")))))
497
498(ert-deftest lookup-google ()
499 "Check that we can look up google IP addresses."
500 (skip-unless internet-is-working)
501 (with-timeout (60 (ert-fail "Test timed out"))
502 (let ((addresses-both (network-lookup-address-info "google.com"))
503 (addresses-v4 (network-lookup-address-info "google.com" 'ipv4)))
504 (should addresses-both)
505 (should addresses-v4))
506 (when (and (ipv6-is-available)
507 (dns-query "google.com" 'AAAA))
508 (should (network-lookup-address-info "google.com" 'ipv6)))))
509
510(ert-deftest non-existent-lookup-failure ()
511 "Check that looking up non-existent domain returns nil."
512 (skip-unless internet-is-working)
513 (with-timeout (60 (ert-fail "Test timed out"))
514 (should (eq nil (network-lookup-address-info "emacs.invalid")))))
515
516;; End of tests requiring DNS
517
518(defmacro process-tests--ignore-EMFILE (&rest body)
519 "Evaluate BODY, ignoring EMFILE errors."
520 (declare (indent 0) (debug t))
521 (let ((err (make-symbol "err"))
522 (message (make-symbol "message")))
523 `(let ((,message (process-tests--EMFILE-message)))
524 (condition-case ,err
525 ,(macroexp-progn body)
526 (file-error
527 ;; If we couldn't determine the EMFILE message, just ignore
528 ;; all `file-error' signals.
529 (and ,message
530 (not (string-equal (caddr ,err) ,message))
531 (signal (car ,err) (cdr ,err))))))))
532
533(defmacro process-tests--with-buffers (var &rest body)
534 "Bind VAR to nil and evaluate BODY.
535Afterwards, kill all buffers in the list VAR. BODY should add
536some buffer objects to VAR."
537 (declare (indent 1) (debug (symbolp body)))
538 (cl-check-type var symbol)
539 `(let ((,var nil))
540 (unwind-protect
541 ,(macroexp-progn body)
542 (mapc #'kill-buffer ,var))))
543
544(defmacro process-tests--with-processes (var &rest body)
545 "Bind VAR to nil and evaluate BODY.
546Afterwards, delete all processes in the list VAR. BODY should
547add some process objects to VAR."
548 (declare (indent 1) (debug (symbolp body)))
549 (cl-check-type var symbol)
550 `(let ((,var nil))
551 (unwind-protect
552 ,(macroexp-progn body)
553 (mapc #'delete-process ,var))))
554
555(defmacro process-tests--with-raised-rlimit (&rest body)
556 "Evaluate BODY using a higher limit for the number of open files.
557Attempt to set the resource limit for the number of open files
558temporarily to the highest possible value."
559 (declare (indent 0) (debug t))
560 (let ((prlimit (make-symbol "prlimit"))
561 (soft (make-symbol "soft"))
562 (hard (make-symbol "hard"))
563 (pid-arg (make-symbol "pid-arg")))
564 `(let ((,prlimit (executable-find "prlimit"))
565 (,pid-arg (format "--pid=%d" (emacs-pid)))
566 (,soft nil) (,hard nil))
567 (cl-flet ((set-limit
568 (value)
569 (cl-check-type value natnum)
570 (when ,prlimit
571 (call-process ,prlimit nil nil nil
572 ,pid-arg
573 (format "--nofile=%d:" value)))))
574 (when ,prlimit
575 (with-temp-buffer
576 (when (eql (call-process ,prlimit nil t nil
577 ,pid-arg "--nofile"
578 "--raw" "--noheadings"
579 "--output=SOFT,HARD")
580 0)
581 (goto-char (point-min))
582 (when (looking-at (rx (group (+ digit)) (+ blank)
583 (group (+ digit)) ?\n))
584 (setq ,soft (string-to-number
585 (match-string-no-properties 1))
586 ,hard (string-to-number
587 (match-string-no-properties 2))))))
588 (and ,soft ,hard (< ,soft ,hard)
589 (set-limit ,hard)))
590 (unwind-protect
591 ,(macroexp-progn body)
592 (when ,soft (set-limit ,soft)))))))
593
594(defmacro process-tests--fd-setsize-test (&rest body)
595 "Run BODY as a test for FD_SETSIZE overflow.
596Try to generate pipe processes until we are close to the
597FD_SETSIZE limit. Within BODY, only a small number of file
598descriptors should still be available. Furthermore, raise the
599maximum number of open files in the Emacs process above
600FD_SETSIZE."
601 (declare (indent 0) (debug t))
602 (let ((process (make-symbol "process"))
603 (processes (make-symbol "processes"))
604 (buffer (make-symbol "buffer"))
605 (buffers (make-symbol "buffers"))
606 ;; FD_SETSIZE is typically 1024 on Unix-like systems. On
607 ;; MS-Windows we artificially limit FD_SETSIZE to 64, see the
608 ;; commentary in w32proc.c.
609 (fd-setsize (if (eq system-type 'windows-nt) 64 1024)))
610 `(process-tests--with-raised-rlimit
611 (process-tests--with-buffers ,buffers
612 (process-tests--with-processes ,processes
613 ;; First, allocate enough pipes to definitely exceed the
614 ;; FD_SETSIZE limit.
615 (cl-loop for i from 1 to ,(1+ fd-setsize)
616 for ,buffer = (generate-new-buffer
617 (format " *pipe %d*" i))
618 do (push ,buffer ,buffers)
619 for ,process = (process-tests--ignore-EMFILE
620 (make-pipe-process
621 :name (format "pipe %d" i)
622 ;; Prevent delete-process from
623 ;; trying to read from pipe
624 ;; processes that didn't exit
625 ;; yet, because no one is
626 ;; writing to those pipes, and
627 ;; the read will stall.
628 :stop (eq system-type 'windows-nt)
629 :buffer ,buffer
630 :coding 'no-conversion
631 :noquery t))
632 while ,process
633 do (push ,process ,processes))
634 (unless (cddr ,processes)
635 (ert-fail "Couldn't allocate enough pipes"))
636 ;; Delete two pipes to test more edge cases.
637 (delete-process (pop ,processes))
638 (delete-process (pop ,processes))
639 ,@body)))))
640
641;; Tests for FD_SETSIZE overflow (Bug#24325). The following tests
642;; generate lots of process objects of the various kinds. Running the
643;; tests with assertions enabled should not result in any crashes due
644;; to file descriptor set overflow. These tests first generate lots
645;; of unused pipe processes to fill up the file descriptor space.
646;; Then, they create a few instances of the process type under test.
647
648(ert-deftest process-tests/fd-setsize-no-crash/make-process ()
649 "Check that Emacs doesn't crash when trying to use more than
650FD_SETSIZE file descriptors (Bug#24325)."
651 (with-timeout (60 (ert-fail "Test timed out"))
652 (let ((cat (executable-find "cat")))
653 (skip-unless cat)
654 (dolist (conn-type '(pipe pty))
655 (ert-info ((format "Connection type `%s'" conn-type))
656 (process-tests--fd-setsize-test
657 (process-tests--with-processes processes
658 ;; Start processes until we exhaust the file descriptor
659 ;; set size. We assume that each process requires at
660 ;; least one file descriptor.
661 (dotimes (i 10)
662 (let ((process
663 ;; Failure to allocate more file descriptors
664 ;; should signal `file-error', but not crash.
665 ;; Since we don't know the exact limit, we
666 ;; ignore `file-error'.
667 (process-tests--ignore-EMFILE
668 (make-process :name (format "test %d" i)
669 :command (list cat)
670 :connection-type conn-type
671 :coding 'no-conversion
672 :noquery t))))
673 (when process (push process processes))))
674 ;; We should have managed to start at least one process.
675 (should processes)
676 (dolist (process processes)
677 ;; The process now should either be running, or have
678 ;; already failed before `exec'.
679 (should (memq (process-status process) '(run exit)))
680 (when (process-live-p process)
681 (process-send-eof process))
682 (while (accept-process-output process))
683 (should (eq (process-status process) 'exit))
684 ;; If there's an error between fork and exec, Emacs
685 ;; will use exit statuses between 125 and 127, see
686 ;; process.h. This can happen if the child process
687 ;; tries to set up terminal device but fails due to
688 ;; file number limits. We don't treat this as an
689 ;; error.
690 (should (memql (process-exit-status process)
691 '(0 125 126 127)))))))))))
692
693(ert-deftest process-tests/fd-setsize-no-crash/make-pipe-process ()
694 "Check that Emacs doesn't crash when trying to use more than
695FD_SETSIZE file descriptors (Bug#24325)."
696 (with-timeout (60 (ert-fail "Test timed out"))
697 (process-tests--fd-setsize-test
698 (process-tests--with-buffers buffers
699 (process-tests--with-processes processes
700 ;; Start processes until we exhaust the file descriptor set
701 ;; size. We assume that each process requires at least one
702 ;; file descriptor.
703 (dotimes (i 10)
704 (let ((buffer (generate-new-buffer (format " *%d*" i))))
705 (push buffer buffers)
706 (let ((process
707 ;; Failure to allocate more file descriptors
708 ;; should signal `file-error', but not crash.
709 ;; Since we don't know the exact limit, we ignore
710 ;; `file-error'.
711 (process-tests--ignore-EMFILE
712 (make-pipe-process :name (format "test %d" i)
713 :buffer buffer
714 :coding 'no-conversion
715 :noquery t))))
716 (when process (push process processes)))))
717 ;; We should have managed to start at least one process.
718 (should processes))))))
719
720(ert-deftest process-tests/fd-setsize-no-crash/make-network-process ()
721 "Check that Emacs doesn't crash when trying to use more than
722FD_SETSIZE file descriptors (Bug#24325)."
723 (skip-unless (featurep 'make-network-process '(:server t)))
724 (skip-unless (featurep 'make-network-process '(:family local)))
725 ;; Avoid hang due to connect/accept handshake on Cygwin (bug#49496).
726 (skip-unless (not (eq system-type 'cygwin)))
727 (with-timeout (60 (ert-fail "Test timed out"))
728 (ert-with-temp-directory directory
729 (process-tests--with-processes processes
730 (let* ((num-clients 10)
731 (socket-name (expand-file-name "socket" directory))
732 ;; Run a UNIX server to connect to.
733 (server (make-network-process :name "server"
734 :server num-clients
735 :buffer nil
736 :service socket-name
737 :family 'local
738 :coding 'no-conversion
739 :noquery t)))
740 (push server processes)
741 (process-tests--fd-setsize-test
742 ;; Start processes until we exhaust the file descriptor
743 ;; set size. We assume that each process requires at
744 ;; least one file descriptor.
745 (dotimes (i num-clients)
746 (let ((client
747 ;; Failure to allocate more file descriptors
748 ;; should signal `file-error', but not crash.
749 ;; Since we don't know the exact limit, we ignore
750 ;; `file-error'.
751 (process-tests--ignore-EMFILE
752 (make-network-process
753 :name (format "client %d" i)
754 :service socket-name
755 :family 'local
756 :coding 'no-conversion
757 :noquery t))))
758 (when client (push client processes))))
759 ;; We should have managed to start at least one process.
760 (should processes)))))))
761
762(ert-deftest process-tests/fd-setsize-no-crash/make-serial-process ()
763 "Check that Emacs doesn't crash when trying to use more than
764FD_SETSIZE file descriptors (Bug#24325)."
765 ;; This test cannot be run if PTYs aren't supported.
766 (skip-unless (not (eq system-type 'windows-nt)))
767 (with-timeout (60 (ert-fail "Test timed out"))
768 (process-tests--with-processes processes
769 ;; In order to use `make-serial-process', we need to create some
770 ;; pseudoterminals. The easiest way to do that is to start a
771 ;; normal process using the `pty' connection type. We need to
772 ;; ensure that the terminal stays around while we connect to it.
773 ;; Create the host processes before the dummy pipes so we have a
774 ;; high chance of succeeding here.
775 (let ((sleep (executable-find "sleep"))
776 (tty-names ()))
777 (skip-unless sleep)
778 (dotimes (i 10)
779 (let* ((host (make-process :name (format "tty host %d" i)
780 :command (list sleep "60")
781 :buffer nil
782 :coding 'utf-8-unix
783 :connection-type 'pty
784 :noquery t))
785 (tty-name (process-tty-name host)))
786 (should (processp host))
787 (push host processes)
788 ;; FIXME: The assumption below that using :connection 'pty
789 ;; in make-process necessarily produces a process with PTY
790 ;; connection is unreliable and non-portable.
791 ;; make-process can legitimately and silently fall back on
792 ;; pipes if allocating a PTY fails (and on MS-Windows it
793 ;; always fails). The following code also assumes that
794 ;; process-tty-name produces a file name that can be
795 ;; passed to 'stat' and to make-serial-process, which is
796 ;; also non-portable.
797 (should tty-name)
798 (should (file-exists-p tty-name))
799 (should-not (member tty-name tty-names))
800 (push tty-name tty-names)))
801 (process-tests--fd-setsize-test
802 (process-tests--with-processes processes
803 (process-tests--with-buffers buffers
804 (dolist (tty-name tty-names)
805 (let ((buffer (generate-new-buffer
806 (format " *%s*" tty-name))))
807 (push buffer buffers)
808 ;; Failure to allocate more file descriptors should
809 ;; signal `file-error', but not crash. Since we
810 ;; don't know the exact limit, we ignore
811 ;; `file-error'.
812 (let ((process (process-tests--ignore-EMFILE
813 (make-serial-process
814 :name (format "test %s" tty-name)
815 :port tty-name
816 :speed 9600
817 :buffer buffer
818 :coding 'no-conversion
819 :noquery t))))
820 (when process (push process processes))))))
821 ;; We should have managed to start at least one process.
822 (should processes)))))))
823
824(defvar process-tests--EMFILE-message :unknown
825 "Cached result of the function `process-tests--EMFILE-message'.")
826
827(defun process-tests--EMFILE-message ()
828 "Return the error message for the EMFILE POSIX error.
829Return nil if that can't be determined."
830 (when (eq process-tests--EMFILE-message :unknown)
831 (setq process-tests--EMFILE-message
832 (with-temp-buffer
833 (when (eql (ignore-error 'file-error
834 (call-process "errno" nil t nil "EMFILE"))
835 0)
836 (goto-char (point-min))
837 (when (looking-at (rx "EMFILE" (+ blank) (+ digit)
838 (+ blank) (group (+ nonl))))
839 (match-string-no-properties 1))))))
840 process-tests--EMFILE-message)
841
842(ert-deftest process-tests/sentinel-called ()
843 "Check that sentinels are called after processes finish."
844 (let ((command (process-tests--emacs-command)))
845 (skip-unless command)
846 (dolist (conn-type '(pipe pty))
847 (ert-info ((format "Connection type: %s" conn-type))
848 (process-tests--with-processes processes
849 (let* ((calls ())
850 (process (make-process
851 :name "echo"
852 :command (process-tests--eval
853 command '(print "first"))
854 :noquery t
855 :connection-type conn-type
856 :coding 'utf-8-unix
857 :sentinel (lambda (process message)
858 (push (list process message)
859 calls)))))
860 (push process processes)
861 (while (accept-process-output process))
862 (should (equal calls
863 (list (list process "finished\n"))))))))))
864
865(ert-deftest process-tests/sentinel-with-multiple-processes ()
866 "Check that sentinels are called in time even when other processes
867have written output."
868 (let ((command (process-tests--emacs-command)))
869 (skip-unless command)
870 (dolist (conn-type '(pipe pty))
871 (ert-info ((format "Connection type: %s" conn-type))
872 (process-tests--with-processes processes
873 (let* ((calls ())
874 (process (make-process
875 :name "echo"
876 :command (process-tests--eval
877 command '(print "first"))
878 :noquery t
879 :connection-type conn-type
880 :coding 'utf-8-unix
881 :sentinel (lambda (process message)
882 (push (list process message)
883 calls)))))
884 (push process processes)
885 (push (make-process
886 :name "bash"
887 :command (process-tests--eval
888 command
889 '(progn (sleep-for 10) (print "second")))
890 :noquery t
891 :connection-type conn-type)
892 processes)
893 (while (accept-process-output process))
894 (should (equal calls
895 (list (list process "finished\n"))))))))))
896
897(ert-deftest process-tests/multiple-threads-waiting ()
898 :tags (if (getenv "EMACS_EMBA_CI") '(:unstable))
899 (skip-unless (fboundp 'make-thread))
900 (with-timeout (60 (ert-fail "Test timed out"))
901 (process-tests--with-processes processes
902 (let ((threads ())
903 (cat (executable-find "cat")))
904 (skip-unless cat)
905 (dotimes (i 10)
906 (let* ((name (format "test %d" i))
907 (process (make-process :name name
908 :command (list cat)
909 :coding 'no-conversion
910 :noquery t
911 :connection-type 'pipe)))
912 (push process processes)
913 (set-process-thread process nil)
914 (push (make-thread
915 (lambda ()
916 (while (accept-process-output process)))
917 name)
918 threads)))
919 (mapc #'process-send-eof processes)
920 (cl-loop for process in processes
921 and thread in threads
922 do
923 (should-not (thread-join thread))
924 (should-not (thread-last-error))
925 (should (eq (process-status process) 'exit))
926 (should (eql (process-exit-status process) 0)))))))
927
928(defun process-tests--eval (command form)
929 "Return a command that evaluates FORM in an Emacs subprocess.
930COMMAND must be a list returned by
931`process-tests--emacs-command'."
932 (let ((print-gensym t)
933 (print-circle t)
934 (print-length nil)
935 (print-level nil)
936 (print-escape-control-characters t)
937 (print-escape-newlines t)
938 (print-escape-multibyte t)
939 (print-escape-nonascii t))
940 `(,@command "--quick" "--batch" ,(format "--eval=%S" form))))
941
942(defun process-tests--emacs-command ()
943 "Return a command to reinvoke the current Emacs instance.
944Return nil if that doesn't appear to be possible."
945 (when-let ((binary (process-tests--emacs-binary))
946 (dump (process-tests--dump-file)))
947 (cons binary
948 (unless (eq dump :not-needed)
949 (list (concat "--dump-file="
950 (file-name-unquote dump)))))))
951
952(defun process-tests--emacs-binary ()
953 "Return the filename of the currently running Emacs binary.
954Return nil if that can't be determined."
955 (and (stringp invocation-name)
956 (not (file-remote-p invocation-name))
957 (not (file-name-absolute-p invocation-name))
958 (stringp invocation-directory)
959 (not (file-remote-p invocation-directory))
960 (file-name-absolute-p invocation-directory)
961 (when-let ((file (process-tests--usable-file-for-reinvoke
962 (expand-file-name invocation-name
963 invocation-directory))))
964 (and (file-executable-p file) file))))
965
966(defun process-tests--dump-file ()
967 "Return the filename of the dump file used to start Emacs.
968Return nil if that can't be determined. Return `:not-needed' if
969Emacs wasn't started with a dump file."
970 (if-let ((stats (and (fboundp 'pdumper-stats) (pdumper-stats))))
971 (when-let ((file (process-tests--usable-file-for-reinvoke
972 (cdr (assq 'dump-file-name stats)))))
973 (and (file-readable-p file) file))
974 :not-needed))
975
976(defun process-tests--usable-file-for-reinvoke (filename)
977 "Return a version of FILENAME that can be used to reinvoke Emacs.
978Return nil if FILENAME doesn't exist."
979 (when (and (stringp filename)
980 (not (file-remote-p filename)))
981 (cl-callf file-truename filename)
982 (and (stringp filename)
983 (not (file-remote-p filename))
984 (file-name-absolute-p filename)
985 (file-regular-p filename)
986 filename)))
987
988;; Bug#46284
989(ert-deftest process-sentinel-interrupt-event ()
990 "Test that interrupting a process on Windows sends \"interrupt\" to sentinel."
991 (skip-unless (eq system-type 'windows-nt))
992 (with-temp-buffer
993 (let* ((proc-buf (current-buffer))
994 ;; Start a new emacs process to wait idly until interrupted.
995 (cmd "emacs -batch --eval=\"(sit-for 50000)\"")
996 (proc (start-file-process-shell-command
997 "test/process-sentinel-signal-event" proc-buf cmd))
998 (events '()))
999
1000 ;; Capture any incoming events.
1001 (set-process-sentinel proc
1002 (lambda (_prc event)
1003 (push event events)))
1004 ;; Wait for the process to start.
1005 (sleep-for 2)
1006 (should (equal 'run (process-status proc)))
1007 ;; Interrupt the sub-process and wait for it to die.
1008 (interrupt-process proc)
1009 (sleep-for 2)
1010 ;; Should have received SIGINT...
1011 (should (equal 'signal (process-status proc)))
1012 (should (equal 2 (process-exit-status proc)))
1013 ;; ...and the change description should be "interrupt".
1014 (should (equal '("interrupt\n") events)))))
1015
1016(ert-deftest process-num-processors ()
1017 "Sanity checks for num-processors."
1018 (should (equal (num-processors) (num-processors)))
1019 (should (integerp (num-processors)))
1020 (should (< 0 (num-processors))))
164 1021
165(provide 'process-tests) 1022(provide 'process-tests)
166;; process-tests.el ends here. 1023;;; process-tests.el ends here
diff --git a/test/src/regex-tests.el b/test/src/regex-emacs-tests.el
index b1f1ea71cef..ff0d6be3f5d 100644
--- a/test/src/regex-tests.el
+++ b/test/src/regex-emacs-tests.el
@@ -1,6 +1,6 @@
1;;; regex-tests.el --- tests for regex.c functions -*- lexical-binding: t -*- 1;;; regex-emacs-tests.el --- tests for regex-emacs.c -*- lexical-binding: t -*-
2 2
3;; Copyright (C) 2015-2017 Free Software Foundation, Inc. 3;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
4 4
5;; This file is part of GNU Emacs. 5;; This file is part of GNU Emacs.
6 6
@@ -24,16 +24,16 @@
24(defvar regex-tests--resources-dir 24(defvar regex-tests--resources-dir
25 (concat (concat (file-name-directory (or load-file-name buffer-file-name)) 25 (concat (concat (file-name-directory (or load-file-name buffer-file-name))
26 "/regex-resources/")) 26 "/regex-resources/"))
27 "Path to regex-resources directory next to the \"regex-tests.el\" file.") 27 "Path to regex-resources directory next to the \"regex-emacs-tests.el\" file.")
28 28
29(ert-deftest regex-word-cc-fallback-test () 29(ert-deftest regex-word-cc-fallback-test ()
30 "Test that [[:cc:]]*x matches x (bug#24020). 30 "Test that \"[[:cc:]]*x\" matches \"x\" (bug#24020).
31 31
32Test that a regex of the form \"[[:cc:]]*x\" where CC is 32Test that a regex of the form \"[[:cc:]]*x\" where CC is
33a character class which matches a multibyte character X, matches 33a character class which matches a multibyte character X, matches
34string \"x\". 34string \"x\".
35 35
36For example, [[:word:]]*\u2620 regex (note: \u2620 is a word 36For example, \"[[:word:]]*\u2620\" regex (note: \u2620 is a word
37character) must match a string \"\u2420\"." 37character) must match a string \"\u2420\"."
38 (dolist (class '("[[:word:]]" "\\sw")) 38 (dolist (class '("[[:word:]]" "\\sw"))
39 (dolist (repeat '("*" "+")) 39 (dolist (repeat '("*" "+"))
@@ -157,18 +157,18 @@ are known failures, and are skipped."
157 157
158(defun regex-tests-compare (string what-failed bounds-ref &optional substring-ref) 158(defun regex-tests-compare (string what-failed bounds-ref &optional substring-ref)
159 "I just ran a search, looking at STRING. WHAT-FAILED describes 159 "I just ran a search, looking at STRING. WHAT-FAILED describes
160what failed, if anything; valid values are 'search-failed, 160what failed, if anything; valid values are `search-failed',
161'compilation-failed and nil. I compare the beginning/end of each 161`compilation-failed' and nil. I compare the beginning/end of each
162group with their expected values. This is done with either 162group with their expected values. This is done with either
163BOUNDS-REF or SUBSTRING-REF; one of those should be non-nil. 163BOUNDS-REF or SUBSTRING-REF; one of those should be non-nil.
164BOUNDS-REF is a sequence \[start-ref0 end-ref0 start-ref1 164BOUNDS-REF is a sequence [start-ref0 end-ref0 start-ref1
165end-ref1 ....] while SUBSTRING-REF is the expected substring 165end-ref1 ....] while SUBSTRING-REF is the expected substring
166obtained by indexing the input string by start/end-ref. 166obtained by indexing the input string by start/end-ref.
167 167
168If the search was supposed to fail then start-ref0/substring-ref0 168If the search was supposed to fail then start-ref0/substring-ref0
169is 'search-failed. If the search wasn't even supposed to compile 169is `search-failed'. If the search wasn't even supposed to compile
170successfully, then start-ref0/substring-ref0 is 170successfully, then start-ref0/substring-ref0 is
171'compilation-failed. If I only care about a match succeeding, 171`compilation-failed'. If I only care about a match succeeding,
172this can be set to t. 172this can be set to t.
173 173
174This function returns a string that describes the failure, or nil 174This function returns a string that describes the failure, or nil
@@ -259,8 +259,8 @@ BOUNDS-REF is a sequence [start-ref0 end-ref0 start-ref1 end-ref1
259....]. 259....].
260 260
261If the search was supposed to fail then start-ref0 is 261If the search was supposed to fail then start-ref0 is
262'search-failed. If the search wasn't even supposed to compile 262`search-failed'. If the search wasn't even supposed to compile
263successfully, then start-ref0 is 'compilation-failed. 263successfully, then start-ref0 is `compilation-failed'.
264 264
265This function returns a string that describes the failure, or nil 265This function returns a string that describes the failure, or nil
266on success" 266on success"
@@ -278,12 +278,12 @@ on success"
278 278
279 279
280(defconst regex-tests-re-even-escapes 280(defconst regex-tests-re-even-escapes
281 "\\(?:^\\|[^\\\\]\\)\\(?:\\\\\\\\\\)*" 281 "\\(?:^\\|[^\\]\\)\\(?:\\\\\\\\\\)*"
282 "Regex that matches an even number of \\ characters") 282 "Regex that matches an even number of \\ characters.")
283 283
284(defconst regex-tests-re-odd-escapes 284(defconst regex-tests-re-odd-escapes
285 (concat regex-tests-re-even-escapes "\\\\") 285 (concat regex-tests-re-even-escapes "\\\\")
286 "Regex that matches an odd number of \\ characters") 286 "Regex that matches an odd number of \\ characters.")
287 287
288 288
289(defun regex-tests-unextend (pattern) 289(defun regex-tests-unextend (pattern)
@@ -327,7 +327,7 @@ emacs requires an extra symbol character"
327(defun regex-tests-BOOST-frob-escapes (s ispattern) 327(defun regex-tests-BOOST-frob-escapes (s ispattern)
328 "Mangle \\ the way it is done in frob_escapes() in 328 "Mangle \\ the way it is done in frob_escapes() in
329regex-tests-BOOST.c in glibc: \\t, \\n, \\r are interpreted; 329regex-tests-BOOST.c in glibc: \\t, \\n, \\r are interpreted;
330\\\\, \\^, \{, \\|, \} are unescaped for the string (not 330\\\\, \\^, \\{, \\|, \\} are unescaped for the string (not
331pattern)" 331pattern)"
332 332
333 ;; this is all similar to (regex-tests-unextend) 333 ;; this is all similar to (regex-tests-unextend)
@@ -396,9 +396,9 @@ pattern)"
396 ;; emacs matches non-greedy regex ab.*? non-greedily 396 ;; emacs matches non-greedy regex ab.*? non-greedily
397 639 677 712 397 639 677 712
398 ] 398 ]
399 "Line numbers in the boost test that should be skipped. These 399 "Line numbers in the boost test that should be skipped.
400are false-positive test failures that represent known/benign 400These are false-positive test failures that represent
401differences in behavior.") 401known/benign differences in behavior.")
402 402
403;; - Format 403;; - Format
404;; - Comments are lines starting with ; 404;; - Comments are lines starting with ;
@@ -480,9 +480,9 @@ differences in behavior.")
480 ;; ambiguous groupings are ambiguous 480 ;; ambiguous groupings are ambiguous
481 610 611 1154 1157 1160 1168 1171 1176 1179 1182 1185 1188 1193 1196 1203 481 610 611 1154 1157 1160 1168 1171 1176 1179 1182 1185 1188 1193 1196 1203
482 ] 482 ]
483 "Line numbers in the PCRE test that should be skipped. These 483 "Line numbers in the PCRE test that should be skipped.
484are false-positive test failures that represent known/benign 484These are false-positive test failures that represent
485differences in behavior.") 485known/benign differences in behavior.")
486 486
487;; - Format 487;; - Format
488;; 488;;
@@ -505,7 +505,7 @@ differences in behavior.")
505 (cond 505 (cond
506 506
507 ;; pattern 507 ;; pattern
508 ((save-excursion (re-search-forward "^/\\(.*\\)/\\(.*i?\\)$" nil t)) 508 ((save-excursion (re-search-forward "^/\\(.*\\)/\\(.*\\)$" nil t))
509 (setq icase (string= "i" (match-string 2)) 509 (setq icase (string= "i" (match-string 2))
510 pattern (regex-tests-unextend (match-string 1)))) 510 pattern (regex-tests-unextend (match-string 1))))
511 511
@@ -555,16 +555,16 @@ differences in behavior.")
555 555
556(defconst regex-tests-PTESTS-whitelist 556(defconst regex-tests-PTESTS-whitelist
557 [ 557 [
558 ;; emacs doesn't barf on weird ranges such as [b-a], but simply 558 ;; emacs doesn't see DEL (0x7f) as a [:cntrl:] character
559 ;; fails to match
560 138 559 138
561 560
562 ;; emacs doesn't see DEL (0x78) as a [:cntrl:] character 561 ;; emacs doesn't barf on weird ranges such as [b-a], but simply
562 ;; fails to match
563 168 563 168
564 ] 564 ]
565 "Line numbers in the PTESTS test that should be skipped. These 565 "Line numbers in the PTESTS test that should be skipped.
566are false-positive test failures that represent known/benign 566These are false-positive test failures that represent
567differences in behavior.") 567known/benign differences in behavior.")
568 568
569;; - Format 569;; - Format
570;; - fields separated by ¦ (note: this is not a |) 570;; - fields separated by ¦ (note: this is not a |)
@@ -621,9 +621,9 @@ differences in behavior.")
621 ;; emacs is more stringent with regexes involving unbalanced ) 621 ;; emacs is more stringent with regexes involving unbalanced )
622 67 622 67
623 ] 623 ]
624 "Line numbers in the TESTS test that should be skipped. These 624 "Line numbers in the TESTS test that should be skipped.
625are false-positive test failures that represent known/benign 625These are false-positive test failures that represent
626differences in behavior.") 626known/benign differences in behavior.")
627 627
628;; - Format 628;; - Format
629;; - fields separated by :. Watch for [\[:xxx:]] 629;; - fields separated by :. Watch for [\[:xxx:]]
@@ -677,4 +677,194 @@ This evaluates the PTESTS test cases from glibc."
677This evaluates the TESTS test cases from glibc." 677This evaluates the TESTS test cases from glibc."
678 (should-not (regex-tests-TESTS))) 678 (should-not (regex-tests-TESTS)))
679 679
680;;; regex-tests.el ends here 680(ert-deftest regex-repeat-limit ()
681 "Test the #xFFFF repeat limit."
682 (should (string-match "\\`x\\{65535\\}" (make-string 65535 ?x)))
683 (should-not (string-match "\\`x\\{65535\\}" (make-string 65534 ?x)))
684 (should-error (string-match "\\`x\\{65536\\}" "X") :type 'invalid-regexp))
685
686(ert-deftest regexp-unibyte-unibyte ()
687 "Test matching a unibyte regexp against a unibyte string."
688 ;; Sanity check
689 (should-not (multibyte-string-p "ab"))
690 (should-not (multibyte-string-p "\xff"))
691 ;; ASCII
692 (should (string-match "a[b]" "ab"))
693 ;; Raw
694 (should (string-match "\xf1" "\xf1"))
695 (should-not (string-match "\xf1" "\xc1\xb1"))
696 ;; Raw, char alt
697 (should (string-match "[\xf1]" "\xf1"))
698 (should-not (string-match "[\xf1]" "\xc1\xb1"))
699 ;; Raw range
700 (should (string-match "[\x82-\xd3]" "\xbb"))
701 (should-not (string-match "[\x82-\xd3]" "a"))
702 (should-not (string-match "[\x82-\xd3]" "\x81"))
703 (should-not (string-match "[\x82-\xd3]" "\xd4"))
704 ;; ASCII-raw range
705 (should (string-match "[f-\xd3]" "q"))
706 (should (string-match "[f-\xd3]" "\xbb"))
707 (should-not (string-match "[f-\xd3]" "e"))
708 (should-not (string-match "[f-\xd3]" "\xd4")))
709
710(ert-deftest regexp-multibyte-multibyte ()
711 "Test matching a multibyte regexp against a multibyte string."
712 ;; Sanity check
713 (should (multibyte-string-p "åü"))
714 ;; ASCII
715 (should (string-match (string-to-multibyte "a[b]")
716 (string-to-multibyte "ab")))
717 ;; Unicode
718 (should (string-match "å[ü]z" "åüz"))
719 (should-not (string-match "ü" (string-to-multibyte "\xc3\xbc")))
720 ;; Raw
721 (should (string-match (string-to-multibyte "\xf1")
722 (string-to-multibyte "\xf1")))
723 (should-not (string-match (string-to-multibyte "\xf1")
724 (string-to-multibyte "\xc1\xb1")))
725 (should-not (string-match (string-to-multibyte "\xc1\xb1")
726 (string-to-multibyte "\xf1")))
727 ;; Raw, char alt
728 (should (string-match (string-to-multibyte "[\xf1]")
729 (string-to-multibyte "\xf1")))
730 ;; Raw range
731 (should (string-match (string-to-multibyte "[\x82-\xd3]")
732 (string-to-multibyte "\xbb")))
733 (should-not (string-match (string-to-multibyte "[\x82-\xd3]") "a"))
734 (should-not (string-match (string-to-multibyte "[\x82-\xd3]") "Å"))
735 (should-not (string-match (string-to-multibyte "[\x82-\xd3]") "ü"))
736 (should-not (string-match (string-to-multibyte "[\x82-\xd3]") "\x81"))
737 (should-not (string-match (string-to-multibyte "[\x82-\xd3]") "\xd4"))
738 ;; ASCII-raw range: should exclude U+0100..U+10FFFF
739 (should (string-match (string-to-multibyte "[f-\xd3]")
740 (string-to-multibyte "q")))
741 (should (string-match (string-to-multibyte "[f-\xd3]")
742 (string-to-multibyte "\xbb")))
743 (should-not (string-match (string-to-multibyte "[f-\xd3]") "e"))
744 (should-not (string-match (string-to-multibyte "[f-\xd3]") "Å"))
745 (should-not (string-match (string-to-multibyte "[f-\xd3]") "ü"))
746 (should-not (string-match (string-to-multibyte "[f-\xd3]") "\xd4"))
747 ;; Unicode-raw range: should be empty
748 (should-not (string-match "[å-\xd3]" "å"))
749 (should-not (string-match "[å-\xd3]" (string-to-multibyte "\xd3")))
750 (should-not (string-match "[å-\xd3]" (string-to-multibyte "\xbb")))
751 (should-not (string-match "[å-\xd3]" "ü"))
752 ;; No equivalence between raw bytes and latin-1
753 (should-not (string-match "å" (string-to-multibyte "\xe5")))
754 (should-not (string-match "[å]" (string-to-multibyte "\xe5")))
755 (should-not (string-match "\xe5" "å"))
756 (should-not (string-match "[\xe5]" "å")))
757
758(ert-deftest regexp-unibyte-multibyte ()
759 "Test matching a unibyte regexp against a multibyte string."
760 ;; ASCII
761 (should (string-match "a[b]" (string-to-multibyte "ab")))
762 ;; Unicode
763 (should (string-match "a.[^b]c" (string-to-multibyte "aåüc")))
764 ;; Raw
765 (should (string-match "\xf1" (string-to-multibyte "\xf1")))
766 (should-not (string-match "\xc1\xb1" (string-to-multibyte "\xf1")))
767 ;; Raw, char alt
768 (should (string-match "[\xf1]" (string-to-multibyte "\xf1")))
769 (should-not (string-match "[\xc1][\xb1]" (string-to-multibyte "\xf1")))
770 ;; ASCII-raw range: should exclude U+0100..U+10FFFF
771 (should (string-match "[f-\xd3]" (string-to-multibyte "q")))
772 (should (string-match "[f-\xd3]" (string-to-multibyte "\xbb")))
773 (should-not (string-match "[f-\xd3]" "e"))
774 (should-not (string-match "[f-\xd3]" "Å"))
775 (should-not (string-match "[f-\xd3]" "ü"))
776 (should-not (string-match "[f-\xd3]" "\xd4"))
777 ;; No equivalence between raw bytes and latin-1
778 (should-not (string-match "\xe5" "å"))
779 (should-not (string-match "[\xe5]" "å")))
780
781(ert-deftest regexp-multibyte-unibyte ()
782 "Test matching a multibyte regexp against a unibyte string."
783 ;; ASCII
784 (should (string-match (string-to-multibyte "a[b]") "ab"))
785 ;; Unicode
786 (should (string-match "a[^ü]c" "abc"))
787 (should-not (string-match "ü" "\xc3\xbc"))
788 ;; Raw
789 (should (string-match (string-to-multibyte "\xf1") "\xf1"))
790 (should-not (string-match (string-to-multibyte "\xf1") "\xc1\xb1"))
791 ;; Raw, char alt
792 (should (string-match (string-to-multibyte "[\xf1]") "\xf1"))
793 (should-not (string-match (string-to-multibyte "[\xf1]") "\xc1\xb1"))
794 ;; ASCII-raw range: should exclude U+0100..U+10FFFF
795 (should (string-match (string-to-multibyte "[f-\xd3]") "q"))
796 (should (string-match (string-to-multibyte "[f-\xd3]") "\xbb"))
797 (should-not (string-match (string-to-multibyte "[f-\xd3]") "e"))
798 (should-not (string-match (string-to-multibyte "[f-\xd3]") "\xd4"))
799 ;; Unicode-raw range: should be empty
800 (should-not (string-match "[å-\xd3]" "\xd3"))
801 (should-not (string-match "[å-\xd3]" "\xbb"))
802 ;; No equivalence between raw bytes and latin-1
803 (should-not (string-match "å" "\xe5"))
804 (should-not (string-match "[å]" "\xe5")))
805
806(ert-deftest regexp-case-fold ()
807 "Test case-sensitive and case-insensitive matching."
808 (let ((case-fold-search nil))
809 (should (equal (string-match "aB" "ABaB") 2))
810 (should (equal (string-match "åÄ" "ÅäåäÅÄåÄ") 6))
811 (should (equal (string-match "λΛ" "lΛλλΛ") 3))
812 (should (equal (string-match "шШ" "zШшшШ") 3))
813 (should (equal (string-match "[[:alpha:]]+" ".3aBåÄßλΛшШ中﷽") 2))
814 (should (equal (match-end 0) 12))
815 (should (equal (string-match "[[:alnum:]]+" ".3aBåÄßλΛшШ中﷽") 1))
816 (should (equal (match-end 0) 12))
817 (should (equal (string-match "[[:upper:]]+" ".3aåλшBÄΛШ中﷽") 6))
818 (should (equal (match-end 0) 10))
819 (should (equal (string-match "[[:lower:]]+" ".3BÄΛШaåλш中﷽") 6))
820 (should (equal (match-end 0) 10)))
821 (let ((case-fold-search t))
822 (should (equal (string-match "aB" "ABaB") 0))
823 (should (equal (string-match "åÄ" "ÅäåäÅÄåÄ") 0))
824 (should (equal (string-match "λΛ" "lΛλλΛ") 1))
825 (should (equal (string-match "шШ" "zШшшШ") 1))
826 (should (equal (string-match "[[:alpha:]]+" ".3aBåÄßλΛшШ中﷽") 2))
827 (should (equal (match-end 0) 12))
828 (should (equal (string-match "[[:alnum:]]+" ".3aBåÄßλΛшШ中﷽") 1))
829 (should (equal (match-end 0) 12))
830 (should (equal (string-match "[[:upper:]]+" ".3aåλшBÄΛШ中﷽") 2))
831 (should (equal (match-end 0) 10))
832 (should (equal (string-match "[[:lower:]]+" ".3BÄΛШaåλш中﷽") 2))
833 (should (equal (match-end 0) 10))))
834
835(ert-deftest regexp-eszett ()
836 "Test matching of ß and ẞ."
837 ;; Sanity checks.
838 (should (equal (upcase "ß") "SS"))
839 (should (equal (downcase "ß") "ß"))
840 (should (equal (capitalize "ß") "Ss")) ; undeutsch...
841 (should (equal (upcase "ẞ") "ẞ"))
842 (should (equal (downcase "ẞ") "ß"))
843 (should (equal (capitalize "ẞ") "ẞ"))
844 ;; ß is a lower-case letter (Ll); ẞ is an upper-case letter (Lu).
845 (let ((case-fold-search nil))
846 (should (equal (string-match "ß" "ß") 0))
847 (should (equal (string-match "ß" "ẞ") nil))
848 (should (equal (string-match "ẞ" "ß") nil))
849 (should (equal (string-match "ẞ" "ẞ") 0))
850 (should (equal (string-match "[[:alpha:]]" "ß") 0))
851 ;; bug#11309
852 (should (equal (string-match "[[:lower:]]" "ß") 0))
853 (should (equal (string-match "[[:upper:]]" "ß") nil))
854 (should (equal (string-match "[[:alpha:]]" "ẞ") 0))
855 (should (equal (string-match "[[:lower:]]" "ẞ") nil))
856 (should (equal (string-match "[[:upper:]]" "ẞ") 0)))
857 (let ((case-fold-search t))
858 (should (equal (string-match "ß" "ß") 0))
859 (should (equal (string-match "ß" "ẞ") 0))
860 (should (equal (string-match "ẞ" "ß") 0))
861 (should (equal (string-match "ẞ" "ẞ") 0))
862 (should (equal (string-match "[[:alpha:]]" "ß") 0))
863 ;; bug#11309
864 (should (equal (string-match "[[:lower:]]" "ß") 0))
865 (should (equal (string-match "[[:upper:]]" "ß") 0))
866 (should (equal (string-match "[[:alpha:]]" "ẞ") 0))
867 (should (equal (string-match "[[:lower:]]" "ẞ") 0))
868 (should (equal (string-match "[[:upper:]]" "ẞ") 0))))
869
870;;; regex-emacs-tests.el ends here
diff --git a/test/src/regex-resources/BOOST.tests b/test/src/regex-resources/BOOST.tests
index 98fd3b6abf3..756fa00486b 100644
--- a/test/src/regex-resources/BOOST.tests
+++ b/test/src/regex-resources/BOOST.tests
@@ -93,7 +93,7 @@ aa\) !
93. \0 0 1 93. \0 0 1
94 94
95; 95;
96; now move on to the repetion ops, 96; now move on to the repetition ops,
97; starting with operator * 97; starting with operator *
98- match_default normal REG_EXTENDED 98- match_default normal REG_EXTENDED
99a* b 0 0 99a* b 0 0
@@ -275,7 +275,7 @@ a(b*)c\1d abbcbbbd -1 -1
275^(.)\1 abc -1 -1 275^(.)\1 abc -1 -1
276a([bc])\1d abcdabbd 4 8 5 6 276a([bc])\1d abcdabbd 4 8 5 6
277; strictly speaking this is at best ambiguous, at worst wrong, this is what most 277; strictly speaking this is at best ambiguous, at worst wrong, this is what most
278; re implimentations will match though. 278; re implementations will match though.
279a(([bc])\2)*d abbccd 0 6 3 5 3 4 279a(([bc])\2)*d abbccd 0 6 3 5 3 4
280 280
281a(([bc])\2)*d abbcbd -1 -1 281a(([bc])\2)*d abbcbd -1 -1
diff --git a/test/src/search-tests.el b/test/src/search-tests.el
new file mode 100644
index 00000000000..2fa23842841
--- /dev/null
+++ b/test/src/search-tests.el
@@ -0,0 +1,42 @@
1;;; search-tests.el --- tests for search.c functions -*- lexical-binding: t -*-
2
3;; Copyright (C) 2015-2016, 2018-2022 Free Software Foundation, Inc.
4
5;; This file is part of GNU Emacs.
6
7;; GNU Emacs is free software: you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation, either version 3 of the License, or
10;; (at your option) any later version.
11
12;; GNU Emacs is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; GNU General Public License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
19
20;;; Code:
21
22(require 'ert)
23
24(ert-deftest test-replace-match-modification-hooks ()
25 (let ((ov-set nil))
26 (with-temp-buffer
27 (insert "1 abc")
28 (setq ov-set (make-overlay 3 5))
29 (overlay-put
30 ov-set 'modification-hooks
31 (list (lambda (_o after &rest _args)
32 (when after
33 (let ((inhibit-modification-hooks t))
34 (save-excursion
35 (goto-char 2)
36 (insert "234")))))))
37 (goto-char 3)
38 (if (search-forward "bc")
39 (replace-match "bcd"))
40 (should (= (point) 10)))))
41
42;;; search-tests.el ends here
diff --git a/test/src/sqlite-tests.el b/test/src/sqlite-tests.el
new file mode 100644
index 00000000000..5af43923012
--- /dev/null
+++ b/test/src/sqlite-tests.el
@@ -0,0 +1,244 @@
1;;; sqlite-tests.el --- Tests for sqlite.el -*- lexical-binding: t; -*-
2
3;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
4
5;; This file is part of GNU Emacs.
6
7;; GNU Emacs is free software: you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation, either version 3 of the License, or
10;; (at your option) any later version.
11
12;; GNU Emacs is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; GNU General Public License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
19
20;;; Commentary:
21
22;;
23
24;;; Code:
25
26(require 'ert)
27(require 'ert-x)
28
29(declare-function sqlite-execute "sqlite.c")
30(declare-function sqlite-close "sqlite.c")
31(declare-function sqlitep "sqlite.c")
32(declare-function sqlite-available-p "sqlite.c")
33(declare-function sqlite-finalize "sqlite.c")
34(declare-function sqlite-next "sqlite.c")
35(declare-function sqlite-more-p "sqlite.c")
36(declare-function sqlite-select "sqlite.c")
37(declare-function sqlite-open "sqlite.c")
38(declare-function sqlite-load-extension "sqlite.c")
39
40(ert-deftest sqlite-select ()
41 (skip-unless (sqlite-available-p))
42 (let ((db (sqlite-open)))
43 (should (eq (type-of db) 'sqlite))
44 (should (sqlitep db))
45 (should-not (sqlitep 'foo))
46
47 (should
48 (zerop
49 (sqlite-execute
50 db "create table if not exists test1 (col1 text, col2 integer, col3 float, col4 blob)")))
51
52 (should-error
53 (sqlite-execute
54 db "insert into test1 (col1, col2, col3, col4) values ('foo', 2, 9.45, 'bar', 'zot')"))
55
56 (should
57 (=
58 (sqlite-execute
59 db "insert into test1 (col1, col2, col3, col4) values ('foo', 2, 9.45, 'bar')")
60 1))
61
62 (should
63 (equal
64 (sqlite-select db "select * from test1" nil 'full)
65 '(("col1" "col2" "col3" "col4") ("foo" 2 9.45 "bar"))))))
66
67(ert-deftest sqlite-set ()
68 (skip-unless (sqlite-available-p))
69 (let ((db (sqlite-open))
70 set)
71 (should
72 (zerop
73 (sqlite-execute
74 db "create table if not exists test1 (col1 text, col2 integer)")))
75
76 (should
77 (=
78 (sqlite-execute db "insert into test1 (col1, col2) values ('foo', 1)")
79 1))
80 (should
81 (=
82 (sqlite-execute db "insert into test1 (col1, col2) values ('bar', 2)")
83 1))
84
85 (setq set (sqlite-select db "select * from test1" nil 'set))
86 (should (sqlitep set))
87 (should (sqlite-more-p set))
88 (should (equal (sqlite-next set)
89 '("foo" 1)))
90 (should (equal (sqlite-next set)
91 '("bar" 2)))
92 (should-not (sqlite-next set))
93 (should-not (sqlite-more-p set))
94 (sqlite-finalize set)
95 (should-error (sqlite-next set))))
96
97(ert-deftest sqlite-chars ()
98 (skip-unless (sqlite-available-p))
99 (let (db)
100 (setq db (sqlite-open))
101 (sqlite-execute
102 db "create table if not exists test2 (col1 text, col2 integer)")
103 (sqlite-execute
104 db "insert into test2 (col1, col2) values ('fóo', 3)")
105 (sqlite-execute
106 db "insert into test2 (col1, col2) values ('fó‚o', 3)")
107 (sqlite-execute
108 db "insert into test2 (col1, col2) values ('f‚o', 4)")
109 (should
110 (equal (sqlite-select db "select * from test2" nil 'full)
111 '(("col1" "col2") ("fóo" 3) ("fó‚o" 3) ("f‚o" 4))))))
112
113(ert-deftest sqlite-numbers ()
114 (skip-unless (sqlite-available-p))
115 (let (db)
116 (setq db (sqlite-open))
117 (sqlite-execute
118 db "create table if not exists test3 (col1 integer)")
119 (let ((big (expt 2 50))
120 (small (expt 2 10)))
121 (sqlite-execute db (format "insert into test3 values (%d)" small))
122 (sqlite-execute db (format "insert into test3 values (%d)" big))
123 (should
124 (equal
125 (sqlite-select db "select * from test3")
126 (list (list small) (list big)))))))
127
128(ert-deftest sqlite-param ()
129 (skip-unless (sqlite-available-p))
130 (let (db)
131 (setq db (sqlite-open))
132 (sqlite-execute
133 db "create table if not exists test4 (col1 text, col2 number)")
134 (sqlite-execute db "insert into test4 values (?, ?)" (list "foo" 1))
135 (should
136 (equal
137 (sqlite-select db "select * from test4 where col2 = ?" '(1))
138 '(("foo" 1))))
139 (should
140 (equal
141 (sqlite-select db "select * from test4 where col2 = ?" [1])
142 '(("foo" 1))))))
143
144(ert-deftest sqlite-binary ()
145 (skip-unless (sqlite-available-p))
146 (let (db)
147 (setq db (sqlite-open))
148 (sqlite-execute
149 db "create table if not exists test5 (col1 text, col2 number)")
150 (let ((string (with-temp-buffer
151 (set-buffer-multibyte nil)
152 (insert 0 1 2)
153 (buffer-string))))
154 (should-not (multibyte-string-p string))
155 (sqlite-execute
156 db "insert into test5 values (?, ?)" (list string 2))
157 (let ((out (caar
158 (sqlite-select db "select col1 from test5 where col2 = 2"))))
159 (should (equal out string))))))
160
161(ert-deftest sqlite-different-dbs ()
162 (skip-unless (sqlite-available-p))
163 (let (db1 db2)
164 (setq db1 (sqlite-open))
165 (setq db2 (sqlite-open))
166 (sqlite-execute
167 db1 "create table if not exists test6 (col1 text, col2 number)")
168 (sqlite-execute
169 db2 "create table if not exists test6 (col1 text, col2 number)")
170 (sqlite-execute
171 db1 "insert into test6 values (?, ?)" '("foo" 2))
172 (should (sqlite-select db1 "select * from test6"))
173 (should-not (sqlite-select db2 "select * from test6"))))
174
175(ert-deftest sqlite-close-dbs ()
176 (skip-unless (sqlite-available-p))
177 (let (db)
178 (setq db (sqlite-open))
179 (sqlite-execute
180 db "create table if not exists test6 (col1 text, col2 number)")
181 (sqlite-execute db "insert into test6 values (?, ?)" '("foo" 2))
182 (should (sqlite-select db "select * from test6"))
183 (sqlite-close db)
184 (should-error (sqlite-select db "select * from test6"))))
185
186(ert-deftest sqlite-load-extension ()
187 (skip-unless (sqlite-available-p))
188 (skip-unless (fboundp 'sqlite-load-extension))
189 (let (db)
190 (setq db (sqlite-open))
191 (should-error
192 (sqlite-load-extension db "/usr/lib/sqlite3/notpcre.so"))
193 (should-error
194 (sqlite-load-extension db "/usr/lib/sqlite3/n"))
195 (should-error
196 (sqlite-load-extension db "/usr/lib/sqlite3/"))
197 (should-error
198 (sqlite-load-extension db "/usr/lib/sqlite3"))
199 (should
200 (memq
201 (sqlite-load-extension db "/usr/lib/sqlite3/pcre.so")
202 '(nil t)))
203
204 (should-error
205 (sqlite-load-extension
206 db "/usr/lib/x86_64-linux-gnu/libsqlite3_mod_notcsvtable.so"))
207 (should-error
208 (sqlite-load-extension
209 db "/usr/lib/x86_64-linux-gnu/libsqlite3_mod_csvtablen.so"))
210 (should-error
211 (sqlite-load-extension
212 db "/usr/lib/x86_64-linux-gnu/libsqlite3_mod_csvtable"))
213 (should
214 (memq
215 (sqlite-load-extension
216 db "/usr/lib/x86_64-linux-gnu/libsqlite3_mod_csvtable.so")
217 '(nil t)))))
218
219(ert-deftest sqlite-blob ()
220 (skip-unless (sqlite-available-p))
221 (let (db)
222 (progn
223 (setq db (sqlite-open))
224 (sqlite-execute
225 db "create table if not exists test10 (col1 text, col2 blob, col3 numbre)")
226 (let ((string (with-temp-buffer
227 (set-buffer-multibyte nil)
228 (insert 0 1 2)
229 (buffer-string))))
230 (should-not (multibyte-string-p string))
231 (sqlite-execute
232 db "insert into test10 values (?, ?, 1)"
233 (list string
234 (propertize string
235 'coding-system 'binary)))
236 (cl-destructuring-bind
237 (c1 c2 _)
238 (car (sqlite-select db "select * from test10 where col3 = 1"))
239 (should (equal c1 string))
240 (should (equal c2 string))
241 (should (multibyte-string-p c1))
242 (should-not (multibyte-string-p c2)))))))
243
244;;; sqlite-tests.el ends here
diff --git a/test/src/syntax-resources/syntax-comments.txt b/test/src/syntax-resources/syntax-comments.txt
new file mode 100644
index 00000000000..a292d816b9d
--- /dev/null
+++ b/test/src/syntax-resources/syntax-comments.txt
@@ -0,0 +1,94 @@
1/* This file is a test file for tests of the comment handling in src/syntax.c.
2 This includes the testing of comments which figure in parse-partial-sexp
3 and scan-lists. */
4
5/* Straight C comments */
61/* comment */1
72/**/2
83// comment
93
104//
114
125/*/5
136*/6
147/* \*/7
158*/8
169/* \\*/9
1710*/10
1811// \
1912
2011
2113// \\
2214
2313
2415/* /*/15
25
26/* C Comments within lists */
2759}59
2850{ /*70 comment */71 }50
2951{ /**/ }51
3052{ //72 comment
3173}52
3253{ //
33}53
3454{ //74 \
35}54
3655{/* */}55
3756{ /*76 \*/ }56
3857*/77
3958}58
4060{ /*78 \\*/79}60
41
42
43/* Straight Pascal comments (not nested) */
4420}20
4521{ Comment }21
4622{}22
4723{
48}23
4924{
5025{25
51}24
5226{ \}26
53
54
55/* Straight Lisp comments (not nested) */
5630
5730
5831; Comment
5931
6032;;;;;;;;;
6132
6233; \
6333
64
65/* Lisp comments within lists */
6640)40
6741(;90 comment
6891)41
6942(;92\
7093)42
7143( ;94
7295
73
74/* Nested Lisp comments */
75100|#100
76101#|#
77102#||#102
78103#| Comment |#103
79104#| Comment
80|#104
81105#|#|#105
82106#| #| Comment |# |#106
83107#|#|#|#|#|#|#|#|#| Comment |#|#|#|#|#|#|#|#|#107
84
85/* Mixed Lisp comments */
86110; #|
87110
88111#| ; |#111
89
90Local Variables:
91mode: fundamental
92eval: (set-syntax-table (make-syntax-table))
93End:
94999 \ No newline at end of file
diff --git a/test/src/syntax-tests.el b/test/src/syntax-tests.el
index 67e7ec32517..751a900a23e 100644
--- a/test/src/syntax-tests.el
+++ b/test/src/syntax-tests.el
@@ -1,6 +1,6 @@
1;;; syntax-tests.el --- tests for syntax.c functions -*- lexical-binding: t -*- 1;;; syntax-tests.el --- tests for syntax.c functions -*- lexical-binding: t -*-
2 2
3;; Copyright (C) 2017 Free Software Foundation, Inc. 3;; Copyright (C) 2017-2022 Free Software Foundation, Inc.
4 4
5;; This file is part of GNU Emacs. 5;; This file is part of GNU Emacs.
6 6
@@ -20,6 +20,8 @@
20;;; Code: 20;;; Code:
21 21
22(require 'ert) 22(require 'ert)
23(require 'ert-x)
24(require 'cl-lib)
23 25
24(ert-deftest parse-partial-sexp-continue-over-comment-marker () 26(ert-deftest parse-partial-sexp-continue-over-comment-marker ()
25 "Continue a parse that stopped in the middle of a comment marker." 27 "Continue a parse that stopped in the middle of a comment marker."
@@ -55,6 +57,16 @@
55 (should (equal (parse-partial-sexp aftC pointX nil nil pps-aftC) 57 (should (equal (parse-partial-sexp aftC pointX nil nil pps-aftC)
56 ppsX))))) 58 ppsX)))))
57 59
60(ert-deftest syntax-class-character-test ()
61 (cl-loop for char across " .w_()'\"$\\/<>@!|"
62 for i from 0
63 do (should (= char (syntax-class-to-char i)))
64 when (string-to-syntax (string char))
65 do (should (= char (syntax-class-to-char
66 (car (string-to-syntax (string char)))))))
67 (should-error (syntax-class-to-char -1))
68 (should-error (syntax-class-to-char 200)))
69
58(ert-deftest parse-partial-sexp-paren-comments () 70(ert-deftest parse-partial-sexp-paren-comments ()
59 "Test syntax parsing with paren comment markers. 71 "Test syntax parsing with paren comment markers.
60Specifically, where the first character of the comment marker is 72Specifically, where the first character of the comment marker is
@@ -82,4 +94,431 @@ also has open paren syntax (see Bug#24870)."
82 (should (equal (parse-partial-sexp pointC pointX nil nil ppsC) 94 (should (equal (parse-partial-sexp pointC pointX nil nil ppsC)
83 ppsX))))) 95 ppsX)))))
84 96
97
98;;; Commentary:
99;; The next bit tests the handling of comments in syntax.c, in
100;; particular the functions `forward-comment' and `scan-lists' and
101;; `parse-partial-sexp' (in so far as they relate to comments).
102
103;; It is intended to enhance this bit to test nested comments
104;; (2020-10-01).
105
106;; This bit uses the data file syntax-resources/syntax-comments.txt.
107
108(defun syntax-comments-point (n forw)
109 "Return the buffer offset corresponding to the \"label\" N.
110N is a decimal number which appears in the data file, usually
111twice, as \"labels\". It can also be a negative number or zero.
112FORW is t when we're using the label at BOL, nil for the one at EOL.
113
114If the label N doesn't exist in the current buffer, an exception
115is thrown.
116
117When FORW is t and N positive, we return the position after the
118first occurrence of label N at BOL in the data file. With FORW
119nil, we return the position before the last occurrence of the
120label at EOL in the data file.
121
122When N is negative, we return instead the position of the end of
123line that the -N label is on. When it is zero, we return POINT."
124 (if (zerop n)
125 (point)
126 (let ((str (format "%d" (abs n))))
127 (save-excursion
128 (if forw
129 (progn
130 (goto-char (point-min))
131 (re-search-forward
132 (concat "^\\(" str "\\)\\([^0-9\n]\\|$\\)"))
133 (if (< n 0)
134 (progn (end-of-line) (point))
135 (match-end 1)))
136 (goto-char (point-max))
137 (re-search-backward
138 (concat "\\(^\\|[^0-9]\\)\\(" str "\\)$"))
139 (if (< n 0)
140 (progn (end-of-line) (point))
141 (match-beginning 2)))))))
142
143(defun syntax-comments-midpoint (n)
144 "Return the buffer offset corresponding to the \"label\" N.
145N is a positive decimal number which should appear in the buffer
146exactly once. The label need not be at the beginning or end of a
147line.
148
149The return value is the position just before the label.
150
151If the label N doesn't exist in the current buffer, an exception
152is thrown."
153 (let ((str (format "%d" n)))
154 (save-excursion
155 (goto-char (point-min))
156 (re-search-forward
157 (concat "\\(^\\|[^0-9]\\)\\(" str "\\)\\([^0-9\n]\\|$\\)"))
158 (match-beginning 2))))
159
160(eval-and-compile
161 (defvar syntax-comments-section))
162
163(defmacro syntax-comments (-type- -dir- res start &optional stop)
164 "Create an ERT test to test (forward-comment 1/-1).
165The test uses a fixed name data file, which it visits. It calls
166entry and exit functions to set up and tear down syntax entries
167for comment characters. The test is given a name based on the
168global variable `syntax-comments-section', the direction of
169movement and the value of START.
170
171-TYPE- (unquoted) is a symbol from whose name the entry and exit
172function names are derived by appending \"-in\" and \"-out\".
173
174-DIR- (unquoted) is `forward' or `backward', the direction
175`forward-comment' is attempted.
176
177RES, t or nil, is the expected result from `forward-comment'.
178
179START and STOP are decimal numbers corresponding to labels in the
180data file marking the start and expected stop positions. See
181`syntax-comments-point' for a precise specification. If STOP is
182missing or nil, the value of START is assumed for it."
183 (declare (debug t))
184 (let ((forw
185 (cond
186 ((eq -dir- 'forward) t)
187 ((eq -dir- 'backward) nil)
188 (t (error "Invalid -dir- argument \"%s\" to `syntax-comments'" -dir-))))
189 (start-str (format "%d" (abs start)))
190 (type -type-))
191 `(ert-deftest ,(intern (concat "syntax-comments-"
192 syntax-comments-section
193 (if forw "-f" "-b") start-str))
194 ()
195 (with-current-buffer
196 (find-file
197 ,(ert-resource-file "syntax-comments.txt"))
198 (,(intern (concat (symbol-name type) "-in")))
199 (goto-char (syntax-comments-point ,start ,forw))
200 (let ((stop (syntax-comments-point ,(or stop start) ,(not forw))))
201 (should (eq (forward-comment ,(if forw 1 -1)) ,res))
202 (should (eq (point) stop)))
203 (,(intern (concat (symbol-name type) "-out")))))))
204
205(defmacro syntax-br-comments (-type- -dir- res -start- &optional stop)
206 "Create an ERT test to test (scan-lists <position> 1/-1 0).
207This is to test the interface between scan-lists and the internal
208comment routines in syntax.c.
209
210The test uses a fixed name data file, which it visits. It calls
211entry and exit functions to set up and tear down syntax entries
212for comment and paren characters. The test is given a name based
213on the global variable `syntax-comments-section', the direction
214of movement and the value of -START-.
215
216-TYPE- (unquoted) is a symbol from whose name the entry and exit
217function names are derived by appending \"-in\" and \"-out\".
218
219-DIR- (unquoted) is `forward' or `backward', the direction
220`scan-lists' is attempted.
221
222RES is t if `scan-lists' is expected to return, nil if it is
223expected to raise a `scan-error' exception.
224
225-START- and STOP are decimal numbers corresponding to labels in the
226data file marking the start and expected stop positions. See
227`syntax-comments-point' for a precise specification. If STOP is
228missing or nil, the value of -START- is assumed for it."
229 (declare (debug t))
230 (let* ((forw
231 (cond
232 ((eq -dir- 'forward) t)
233 ((eq -dir- 'backward) nil)
234 (t (error "Invalid -dir- argument \"%s\" to `syntax-br-comments'" -dir-))))
235 (start -start-)
236 (start-str (format "%d" (abs start)))
237 (type -type-))
238 `(ert-deftest ,(intern (concat "syntax-br-comments-"
239 syntax-comments-section
240 (if forw "-f" "-b") start-str))
241 ()
242 (with-current-buffer
243 (find-file
244 ,(ert-resource-file "syntax-comments.txt"))
245 (,(intern (concat (symbol-name type) "-in")))
246 (let ((start-pos (syntax-comments-point ,start ,forw))
247 ,@(if res
248 `((stop-pos (syntax-comments-point
249 ,(or stop start) ,(not forw))))))
250 ,(if res
251 `(should
252 (eq (scan-lists start-pos ,(if forw 1 -1) 0)
253 stop-pos))
254 `(should-error (scan-lists start-pos ,(if forw 1 -1) 0)
255 :type 'scan-error)))
256 (,(intern (concat (symbol-name type) "-out")))))))
257
258(defmacro syntax-pps-comments (-type- -start- open close &optional -stop-)
259 "Create an ERT test to test `parse-partial-sexp' with comments.
260This is to test the interface between `parse-partial-sexp' and
261the internal comment routines in syntax.c.
262
263The test uses a fixed name data file, which it visits. It calls
264entry and exit functions to set up and tear down syntax entries
265for comment and paren characters. The test is given a name based
266on the global variable `syntax-comments-section', and the value
267of -START-.
268
269The generated test calls `parse-partial-sexp' three times, the
270first two with COMMENTSTOP set to `syntax-table' so as to stop
271after the start and end of the comment. The third call is
272expected to stop at the brace/paren matching the one where the
273test started.
274
275-TYPE- (unquoted) is a symbol from whose name the entry and exit
276function names are derived by appending \"-in\" and \"-out\".
277
278-START- and -STOP- are decimal numbers corresponding to labels in
279the data file marking the start and expected stop positions. See
280`syntax-comments-point' for a precise specification. If -STOP-
281is missing or nil, the value of -START- is assumed for it.
282
283OPEN and CLOSE are decimal numbers corresponding to labels in the
284data file marking just after the comment opener and closer where
285the `parse-partial-sexp's are expected to stop. See
286`syntax-comments-midpoint' for a precise specification."
287 (declare (debug t))
288 (let* ((type -type-)
289 (start -start-)
290 (start-str (format "%d" start))
291 (stop (or -stop- start)))
292 `(ert-deftest ,(intern (concat "syntax-pps-comments-"
293 syntax-comments-section
294 "-" start-str))
295 ()
296 (with-current-buffer
297 (find-file
298 ,(ert-resource-file "syntax-comments.txt"))
299 (,(intern (concat (symbol-name type) "-in")))
300 (let ((start-pos (syntax-comments-point ,start t))
301 (open-pos (syntax-comments-midpoint ,open))
302 (close-pos (syntax-comments-midpoint ,close))
303 (stop-pos (syntax-comments-point ,stop nil))
304 s)
305 (setq s (parse-partial-sexp
306 start-pos (point-max) 0 nil nil 'syntax-table))
307 (should (eq (point) open-pos))
308 (setq s (parse-partial-sexp
309 (point) (point-max) 0 nil s 'syntax-table))
310 (should (eq (point) close-pos))
311 (setq s (parse-partial-sexp (point) (point-max) 0 nil s))
312 (should (eq (point) stop-pos)))
313 (,(intern (concat (symbol-name type) "-out")))))))
314
315;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
316;; "Pascal" style comments - single character delimiters, the closing
317;; delimiter not being newline.
318;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
319(defun {-in ()
320 (setq parse-sexp-ignore-comments t)
321 (setq comment-end-can-be-escaped nil)
322 (modify-syntax-entry ?{ "<")
323 (modify-syntax-entry ?} ">"))
324(defun {-out ()
325 (modify-syntax-entry ?{ "(}")
326 (modify-syntax-entry ?} "){"))
327(eval-and-compile
328 (setq syntax-comments-section "pascal"))
329
330(syntax-comments { forward nil 20 0)
331(syntax-comments { backward nil 20 0)
332(syntax-comments { forward t 21)
333(syntax-comments { backward t 21)
334(syntax-comments { forward t 22)
335(syntax-comments { backward t 22)
336
337(syntax-comments { forward t 23)
338(syntax-comments { backward t 23)
339(syntax-comments { forward t 24)
340(syntax-comments { backward t 24)
341(syntax-comments { forward t 26)
342(syntax-comments { backward t 26)
343
344;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
345;; "Lisp" style comments - single character opening delimiters on line
346;; comments.
347;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
348(defun \;-in ()
349 (setq parse-sexp-ignore-comments t)
350 (setq comment-end-can-be-escaped nil)
351 (modify-syntax-entry ?\n ">")
352 (modify-syntax-entry ?\; "<")
353 (modify-syntax-entry ?{ ".")
354 (modify-syntax-entry ?} "."))
355(defun \;-out ()
356 (modify-syntax-entry ?\n " ")
357 (modify-syntax-entry ?\; ".")
358 (modify-syntax-entry ?{ "(}")
359 (modify-syntax-entry ?} "){"))
360(eval-and-compile
361 (setq syntax-comments-section "lisp"))
362
363(syntax-comments \; backward nil 30 30)
364(syntax-comments \; forward t 31)
365(syntax-comments \; backward t 31)
366(syntax-comments \; forward t 32)
367(syntax-comments \; backward t 32)
368(syntax-comments \; forward t 33)
369(syntax-comments \; backward t 33)
370
371;; "Lisp" style comments inside lists.
372(syntax-br-comments \; backward nil 40)
373(syntax-br-comments \; forward t 41)
374(syntax-br-comments \; backward t 41)
375(syntax-br-comments \; forward t 42)
376(syntax-br-comments \; backward t 42)
377(syntax-br-comments \; forward nil 43)
378
379;; "Lisp" style comments parsed by `parse-partial-sexp'.
380(syntax-pps-comments \; 41 90 91)
381(syntax-pps-comments \; 42 92 93)
382(syntax-pps-comments \; 43 94 95 -999)
383
384;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
385;; "Lisp" style nested comments: between delimiters #| |#.
386;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
387(defun \#|-in ()
388 (setq parse-sexp-ignore-comments t)
389 (modify-syntax-entry ?# ". 14")
390 (modify-syntax-entry ?| ". 23n")
391 (modify-syntax-entry ?\; "< b")
392 (modify-syntax-entry ?\n "> b"))
393(defun \#|-out ()
394 (modify-syntax-entry ?# ".")
395 (modify-syntax-entry ?| ".")
396 (modify-syntax-entry ?\; ".")
397 (modify-syntax-entry ?\n " "))
398(eval-and-compile
399 (setq syntax-comments-section "lisp-n"))
400
401(syntax-comments \#| forward nil 100 0)
402(syntax-comments \#| backward nil 100 0)
403(syntax-comments \#| forward nil 101 -999)
404(syntax-comments \#| forward t 102)
405(syntax-comments \#| backward t 102)
406
407(syntax-comments \#| forward t 103)
408(syntax-comments \#| backward t 103)
409(syntax-comments \#| forward t 104)
410(syntax-comments \#| backward t 104)
411
412(syntax-comments \#| forward nil 105 -999)
413(syntax-comments \#| backward t 105)
414(syntax-comments \#| forward t 106)
415(syntax-comments \#| backward t 106)
416(syntax-comments \#| forward t 107)
417(syntax-comments \#| backward t 107)
418
419;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
420;; Mixed "Lisp" style (nested and unnested) comments.
421;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
422(syntax-comments \#| forward t 110)
423(syntax-comments \#| backward t 110)
424(syntax-comments \#| forward t 111)
425(syntax-comments \#| backward t 111)
426
427;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
428;; Emacs 27 "C" style comments - `comment-end-can-be-escaped' is non-nil.
429;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
430(defun /*-in ()
431 (setq parse-sexp-ignore-comments t)
432 (setq comment-end-can-be-escaped t)
433 (modify-syntax-entry ?/ ". 124b")
434 (modify-syntax-entry ?* ". 23")
435 (modify-syntax-entry ?\n "> b"))
436(defun /*-out ()
437 (setq comment-end-can-be-escaped nil)
438 (modify-syntax-entry ?/ ".")
439 (modify-syntax-entry ?* ".")
440 (modify-syntax-entry ?\n " "))
441(eval-and-compile
442 (setq syntax-comments-section "c"))
443
444(syntax-comments /* forward t 1)
445(syntax-comments /* backward t 1)
446(syntax-comments /* forward t 2)
447(syntax-comments /* backward t 2)
448(syntax-comments /* forward t 3)
449(syntax-comments /* backward t 3)
450
451(syntax-comments /* forward t 4)
452(syntax-comments /* backward t 4)
453(syntax-comments /* forward t 5 6)
454(syntax-comments /* backward nil 5 0)
455(syntax-comments /* forward nil 6 0)
456(syntax-comments /* backward t 6 5)
457
458(syntax-comments /* forward t 7 8)
459(syntax-comments /* backward nil 7 0)
460(syntax-comments /* forward nil 8 0)
461(syntax-comments /* backward t 8 7)
462(syntax-comments /* forward t 9)
463(syntax-comments /* backward t 9)
464
465(syntax-comments /* forward nil 10 0)
466(syntax-comments /* backward nil 10 0)
467(syntax-comments /* forward t 11)
468(syntax-comments /* backward t 11)
469
470(syntax-comments /* forward t 13 14)
471(syntax-comments /* backward nil 13 -14)
472(syntax-comments /* forward t 15)
473(syntax-comments /* backward t 15)
474
475;; Emacs 27 "C" style comments inside brace lists.
476(syntax-br-comments /* forward t 50)
477(syntax-br-comments /* backward t 50)
478(syntax-br-comments /* forward t 51)
479(syntax-br-comments /* backward t 51)
480(syntax-br-comments /* forward t 52)
481(syntax-br-comments /* backward t 52)
482
483(syntax-br-comments /* forward t 53)
484(syntax-br-comments /* backward t 53)
485(syntax-br-comments /* forward t 54 20)
486(syntax-br-comments /* backward t 54)
487(syntax-br-comments /* forward t 55)
488(syntax-br-comments /* backward t 55)
489
490(syntax-br-comments /* forward t 56 58)
491(syntax-br-comments /* backward t 58 56)
492(syntax-br-comments /* backward nil 59)
493(syntax-br-comments /* forward t 60)
494(syntax-br-comments /* backward t 60)
495
496;; Emacs 27 "C" style comments parsed by `parse-partial-sexp'.
497(syntax-pps-comments /* 50 70 71)
498(syntax-pps-comments /* 52 72 73)
499(syntax-pps-comments /* 54 74 55 20)
500(syntax-pps-comments /* 56 76 77 58)
501(syntax-pps-comments /* 60 78 79)
502
503(ert-deftest test-from-to-parse-partial-sexp ()
504 (with-temp-buffer
505 (insert "foo")
506 (should (parse-partial-sexp 1 1))
507 (should-error (parse-partial-sexp 2 1))))
508
509(ert-deftest syntax-char-syntax ()
510 ;; Verify that char-syntax behaves identically in interpreted and
511 ;; byte-compiled code (bug#53260).
512 (let ((cs (byte-compile (lambda (x) (char-syntax x)))))
513 ;; Use a unibyte buffer with a syntax table using symbol syntax
514 ;; for raw byte 128.
515 (with-temp-buffer
516 (set-buffer-multibyte nil)
517 (let ((st (make-syntax-table)))
518 (modify-syntax-entry (unibyte-char-to-multibyte 128) "_" st)
519 (set-syntax-table st)
520 (should (equal (eval '(char-syntax 128) t) ?_))
521 (should (equal (funcall cs 128) ?_))))
522 (list (char-syntax 128) (funcall cs 128))))
523
85;;; syntax-tests.el ends here 524;;; syntax-tests.el ends here
diff --git a/test/src/textprop-tests.el b/test/src/textprop-tests.el
index 1dcfa8ea29d..d6cee6b6cbe 100644
--- a/test/src/textprop-tests.el
+++ b/test/src/textprop-tests.el
@@ -1,6 +1,6 @@
1;;; textprop-tests.el --- Test suite for text properties. 1;;; textprop-tests.el --- Test suite for text properties. -*- lexical-binding: t -*-
2 2
3;; Copyright (C) 2015-2017 Free Software Foundation, Inc. 3;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
4 4
5;; Author: Wolfgang Jenkner <wjenkner@inode.at> 5;; Author: Wolfgang Jenkner <wjenkner@inode.at>
6;; Keywords: internal 6;; Keywords: internal
@@ -69,4 +69,4 @@
69 (null stack))))) 69 (null stack)))))
70 70
71(provide 'textprop-tests) 71(provide 'textprop-tests)
72;; textprop-tests.el ends here. 72;;; textprop-tests.el ends here
diff --git a/test/src/thread-tests.el b/test/src/thread-tests.el
index 10b2f0761df..75d67140a90 100644
--- a/test/src/thread-tests.el
+++ b/test/src/thread-tests.el
@@ -1,6 +1,6 @@
1;;; threads.el --- tests for threads. 1;;; thread-tests.el --- tests for threads. -*- lexical-binding: t -*-
2 2
3;; Copyright (C) 2012-2017 Free Software Foundation, Inc. 3;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
4 4
5;; This file is part of GNU Emacs. 5;; This file is part of GNU Emacs.
6 6
@@ -19,39 +19,74 @@
19 19
20;;; Code: 20;;; Code:
21 21
22(require 'thread)
23
24;; Declare the functions in case Emacs has been configured --without-threads.
25(declare-function all-threads "thread.c" ())
26(declare-function condition-mutex "thread.c" (cond))
27(declare-function condition-name "thread.c" (cond))
28(declare-function condition-notify "thread.c" (cond &optional all))
29(declare-function condition-wait "thread.c" (cond))
30(declare-function current-thread "thread.c" ())
31(declare-function make-condition-variable "thread.c" (mutex &optional name))
32(declare-function make-mutex "thread.c" (&optional name))
33(declare-function make-thread "thread.c" (function &optional name))
34(declare-function mutex-lock "thread.c" (mutex))
35(declare-function mutex-unlock "thread.c" (mutex))
36(declare-function thread--blocker "thread.c" (thread))
37(declare-function thread-live-p "thread.c" (thread))
38(declare-function thread-join "thread.c" (thread))
39(declare-function thread-last-error "thread.c" (&optional cleanup))
40(declare-function thread-name "thread.c" (thread))
41(declare-function thread-signal "thread.c" (thread error-symbol data))
42(declare-function thread-yield "thread.c" ())
43(defvar main-thread)
44
22(ert-deftest threads-is-one () 45(ert-deftest threads-is-one ()
23 "test for existence of a thread" 46 "Test for existence of a thread."
47 (skip-unless (featurep 'threads))
24 (should (current-thread))) 48 (should (current-thread)))
25 49
26(ert-deftest threads-threadp () 50(ert-deftest threads-threadp ()
27 "test of threadp" 51 "Test of threadp."
52 (skip-unless (featurep 'threads))
28 (should (threadp (current-thread)))) 53 (should (threadp (current-thread))))
29 54
30(ert-deftest threads-type () 55(ert-deftest threads-type ()
31 "test of thread type" 56 "Test of thread type."
57 (skip-unless (featurep 'threads))
32 (should (eq (type-of (current-thread)) 'thread))) 58 (should (eq (type-of (current-thread)) 'thread)))
33 59
34(ert-deftest threads-name () 60(ert-deftest threads-name ()
35 "test for name of a thread" 61 "Test for name of a thread."
62 (skip-unless (featurep 'threads))
36 (should 63 (should
37 (string= "hi bob" (thread-name (make-thread #'ignore "hi bob"))))) 64 (string= "hi bob" (thread-name (make-thread #'ignore "hi bob")))))
38 65
39(ert-deftest threads-alive () 66(ert-deftest threads-live ()
40 "test for thread liveness" 67 "Test for thread liveness."
68 (skip-unless (featurep 'threads))
41 (should 69 (should
42 (thread-alive-p (make-thread #'ignore)))) 70 (thread-live-p (make-thread #'ignore))))
43 71
44(ert-deftest threads-all-threads () 72(ert-deftest threads-all-threads ()
45 "simple test for all-threads" 73 "Simple test for `all-threads'."
74 (skip-unless (featurep 'threads))
46 (should (listp (all-threads)))) 75 (should (listp (all-threads))))
47 76
77(ert-deftest threads-main-thread ()
78 "Simple test for `all-threads'."
79 (skip-unless (featurep 'threads))
80 (should (eq main-thread (car (all-threads)))))
81
48(defvar threads-test-global nil) 82(defvar threads-test-global nil)
49 83
50(defun threads-test-thread1 () 84(defun threads-test-thread1 ()
51 (setq threads-test-global 23)) 85 (setq threads-test-global 23))
52 86
53(ert-deftest threads-basic () 87(ert-deftest threads-basic ()
54 "basic thread test" 88 "Basic thread test."
89 (skip-unless (featurep 'threads))
55 (should 90 (should
56 (progn 91 (progn
57 (setq threads-test-global nil) 92 (setq threads-test-global nil)
@@ -61,19 +96,30 @@
61 threads-test-global))) 96 threads-test-global)))
62 97
63(ert-deftest threads-join () 98(ert-deftest threads-join ()
64 "test of thread-join" 99 "Test of `thread-join'."
100 (skip-unless (featurep 'threads))
65 (should 101 (should
66 (progn 102 (progn
67 (setq threads-test-global nil) 103 (setq threads-test-global nil)
68 (let ((thread (make-thread #'threads-test-thread1))) 104 (let ((thread (make-thread #'threads-test-thread1)))
69 (thread-join thread) 105 (and (= (thread-join thread) 23)
70 (and threads-test-global 106 (= threads-test-global 23)
71 (not (thread-alive-p thread))))))) 107 (not (thread-live-p thread)))))))
72 108
73(ert-deftest threads-join-self () 109(ert-deftest threads-join-self ()
74 "cannot thread-join the current thread" 110 "Cannot `thread-join' the current thread."
111 (skip-unless (featurep 'threads))
75 (should-error (thread-join (current-thread)))) 112 (should-error (thread-join (current-thread))))
76 113
114(ert-deftest threads-join-error ()
115 "Test of error signaling from `thread-join'."
116 :tags '(:unstable)
117 (skip-unless (featurep 'threads))
118 (let ((thread (make-thread #'threads-call-error)))
119 (while (thread-live-p thread)
120 (thread-yield))
121 (should-error (thread-join thread))))
122
77(defvar threads-test-binding nil) 123(defvar threads-test-binding nil)
78 124
79(defun threads-test-thread2 () 125(defun threads-test-thread2 ()
@@ -82,7 +128,8 @@
82 (setq threads-test-global 23)) 128 (setq threads-test-global 23))
83 129
84(ert-deftest threads-let-binding () 130(ert-deftest threads-let-binding ()
85 "simple test of threads and let bindings" 131 "Simple test of threads and let bindings."
132 (skip-unless (featurep 'threads))
86 (should 133 (should
87 (progn 134 (progn
88 (setq threads-test-global nil) 135 (setq threads-test-global nil)
@@ -93,19 +140,23 @@
93 threads-test-global)))) 140 threads-test-global))))
94 141
95(ert-deftest threads-mutexp () 142(ert-deftest threads-mutexp ()
96 "simple test of mutexp" 143 "Simple test of `mutexp'."
144 (skip-unless (featurep 'threads))
97 (should-not (mutexp 'hi))) 145 (should-not (mutexp 'hi)))
98 146
99(ert-deftest threads-mutexp-2 () 147(ert-deftest threads-mutexp-2 ()
100 "another simple test of mutexp" 148 "Another simple test of `mutexp'."
149 (skip-unless (featurep 'threads))
101 (should (mutexp (make-mutex)))) 150 (should (mutexp (make-mutex))))
102 151
103(ert-deftest threads-mutex-type () 152(ert-deftest threads-mutex-type ()
104 "type-of mutex" 153 "type-of mutex."
154 (skip-unless (featurep 'threads))
105 (should (eq (type-of (make-mutex)) 'mutex))) 155 (should (eq (type-of (make-mutex)) 'mutex)))
106 156
107(ert-deftest threads-mutex-lock-unlock () 157(ert-deftest threads-mutex-lock-unlock ()
108 "test mutex-lock and unlock" 158 "Test `mutex-lock' and unlock."
159 (skip-unless (featurep 'threads))
109 (should 160 (should
110 (let ((mx (make-mutex))) 161 (let ((mx (make-mutex)))
111 (mutex-lock mx) 162 (mutex-lock mx)
@@ -113,7 +164,8 @@
113 t))) 164 t)))
114 165
115(ert-deftest threads-mutex-recursive () 166(ert-deftest threads-mutex-recursive ()
116 "test mutex-lock and unlock" 167 "Test mutex recursion."
168 (skip-unless (featurep 'threads))
117 (should 169 (should
118 (let ((mx (make-mutex))) 170 (let ((mx (make-mutex)))
119 (mutex-lock mx) 171 (mutex-lock mx)
@@ -133,7 +185,8 @@
133 (mutex-unlock threads-mutex)) 185 (mutex-unlock threads-mutex))
134 186
135(ert-deftest threads-mutex-contention () 187(ert-deftest threads-mutex-contention ()
136 "test of mutex contention" 188 "Test of mutex contention."
189 (skip-unless (featurep 'threads))
137 (should 190 (should
138 (progn 191 (progn
139 (setq threads-mutex (make-mutex)) 192 (setq threads-mutex (make-mutex))
@@ -153,8 +206,9 @@
153 (mutex-lock threads-mutex)) 206 (mutex-lock threads-mutex))
154 207
155(ert-deftest threads-mutex-signal () 208(ert-deftest threads-mutex-signal ()
156 "test signaling a blocked thread" 209 "Test signaling a blocked thread."
157 (should 210 (skip-unless (featurep 'threads))
211 (should-error
158 (progn 212 (progn
159 (setq threads-mutex (make-mutex)) 213 (setq threads-mutex (make-mutex))
160 (setq threads-mutex-key nil) 214 (setq threads-mutex-key nil)
@@ -163,14 +217,17 @@
163 (while (not threads-mutex-key) 217 (while (not threads-mutex-key)
164 (thread-yield)) 218 (thread-yield))
165 (thread-signal thr 'quit nil) 219 (thread-signal thr 'quit nil)
166 (thread-join thr)) 220 ;; `quit' is not catched by `should-error'. We must indicate it.
167 t))) 221 (condition-case nil
222 (thread-join thr)
223 (quit (signal 'error nil)))))))
168 224
169(defun threads-test-io-switch () 225(defun threads-test-io-switch ()
170 (setq threads-test-global 23)) 226 (setq threads-test-global 23))
171 227
172(ert-deftest threads-io-switch () 228(ert-deftest threads-io-switch ()
173 "test that accept-process-output causes thread switch" 229 "Test that `accept-process-output' causes thread switch."
230 (skip-unless (featurep 'threads))
174 (should 231 (should
175 (progn 232 (progn
176 (setq threads-test-global nil) 233 (setq threads-test-global nil)
@@ -180,60 +237,72 @@
180 threads-test-global))) 237 threads-test-global)))
181 238
182(ert-deftest threads-condvarp () 239(ert-deftest threads-condvarp ()
183 "simple test of condition-variable-p" 240 "Simple test of `condition-variable-p'."
241 (skip-unless (featurep 'threads))
184 (should-not (condition-variable-p 'hi))) 242 (should-not (condition-variable-p 'hi)))
185 243
186(ert-deftest threads-condvarp-2 () 244(ert-deftest threads-condvarp-2 ()
187 "another simple test of condition-variable-p" 245 "Another simple test of `condition-variable-p'."
246 (skip-unless (featurep 'threads))
188 (should (condition-variable-p (make-condition-variable (make-mutex))))) 247 (should (condition-variable-p (make-condition-variable (make-mutex)))))
189 248
190(ert-deftest threads-condvar-type () 249(ert-deftest threads-condvar-type ()
191 "type-of condvar" 250 "type-of condvar"
251 (skip-unless (featurep 'threads))
192 (should (eq (type-of (make-condition-variable (make-mutex))) 252 (should (eq (type-of (make-condition-variable (make-mutex)))
193 'condition-variable))) 253 'condition-variable)))
194 254
195(ert-deftest threads-condvar-mutex () 255(ert-deftest threads-condvar-mutex ()
196 "simple test of condition-mutex" 256 "Simple test of `condition-mutex'."
257 (skip-unless (featurep 'threads))
197 (should 258 (should
198 (let ((m (make-mutex))) 259 (let ((m (make-mutex)))
199 (eq m (condition-mutex (make-condition-variable m)))))) 260 (eq m (condition-mutex (make-condition-variable m))))))
200 261
201(ert-deftest threads-condvar-name () 262(ert-deftest threads-condvar-name ()
202 "simple test of condition-name" 263 "Simple test of `condition-name'."
264 (skip-unless (featurep 'threads))
203 (should 265 (should
204 (eq nil (condition-name (make-condition-variable (make-mutex)))))) 266 (eq nil (condition-name (make-condition-variable (make-mutex))))))
205 267
206(ert-deftest threads-condvar-name-2 () 268(ert-deftest threads-condvar-name-2 ()
207 "another simple test of condition-name" 269 "Another simple test of `condition-name'."
270 (skip-unless (featurep 'threads))
208 (should 271 (should
209 (string= "hi bob" 272 (string= "hi bob"
210 (condition-name (make-condition-variable (make-mutex) 273 (condition-name (make-condition-variable (make-mutex)
211 "hi bob"))))) 274 "hi bob")))))
212(defun call-error () 275
276(defun threads-call-error ()
213 "Call `error'." 277 "Call `error'."
214 (error "Error is called")) 278 (error "Error is called"))
215 279
216;; This signals an error internally; the error should be caught. 280;; This signals an error internally; the error should be caught.
217(defun thread-custom () 281(defun threads-custom ()
218 (defcustom thread-custom-face 'highlight 282 (defcustom threads-custom-face 'highlight
219 "Face used for thread customizations." 283 "Face used for thread customizations."
220 :type 'face 284 :type 'face
221 :group 'widget-faces)) 285 :group 'widget-faces))
222 286
223(ert-deftest thread-errors () 287(ert-deftest threads-errors ()
224 "Test what happens when a thread signals an error." 288 "Test what happens when a thread signals an error."
289 (skip-unless (featurep 'threads))
225 (let (th1 th2) 290 (let (th1 th2)
226 (setq th1 (make-thread #'call-error "call-error")) 291 (setq th1 (make-thread #'threads-call-error "call-error"))
227 (should (threadp th1)) 292 (should (threadp th1))
228 (while (thread-alive-p th1) 293 (while (thread-live-p th1)
229 (thread-yield)) 294 (thread-yield))
230 (should (equal (thread-last-error) 295 (should (equal (thread-last-error)
231 '(error "Error is called"))) 296 '(error "Error is called")))
232 (setq th2 (make-thread #'thread-custom "thread-custom")) 297 (should (equal (thread-last-error 'cleanup)
298 '(error "Error is called")))
299 (should-not (thread-last-error))
300 (setq th2 (make-thread #'threads-custom "threads-custom"))
233 (should (threadp th2)))) 301 (should (threadp th2))))
234 302
235(ert-deftest thread-sticky-point () 303(ert-deftest threads-sticky-point ()
236 "Test bug #25165 with point movement in cloned buffer." 304 "Test bug #25165 with point movement in cloned buffer."
305 (skip-unless (featurep 'threads))
237 (with-temp-buffer 306 (with-temp-buffer
238 (insert "Lorem ipsum dolor sit amet, consectetur adipiscing elit.") 307 (insert "Lorem ipsum dolor sit amet, consectetur adipiscing elit.")
239 (goto-char (point-min)) 308 (goto-char (point-min))
@@ -242,16 +311,36 @@
242 (sit-for 1) 311 (sit-for 1)
243 (should (= (point) 21)))) 312 (should (= (point) 21))))
244 313
245(ert-deftest thread-signal-early () 314(ert-deftest threads-signal-early ()
246 "Test signaling a thread as soon as it is started by the OS." 315 "Test signaling a thread as soon as it is started by the OS."
316 (skip-unless (featurep 'threads))
247 (let ((thread 317 (let ((thread
248 (make-thread #'(lambda () 318 (make-thread (lambda ()
249 (while t (thread-yield)))))) 319 (while t (thread-yield))))))
250 (thread-signal thread 'error nil) 320 (thread-signal thread 'error nil)
251 (sit-for 1) 321 (sit-for 1)
252 (should-not (thread-alive-p thread)) 322 (should-not (thread-live-p thread))
253 (should (equal (thread-last-error) '(error))))) 323 (should (equal (thread-last-error) '(error)))))
254 324
325(ert-deftest threads-signal-main-thread ()
326 "Test signaling the main thread."
327 (skip-unless (featurep 'threads))
328 ;; We cannot use `ert-with-message-capture', because threads do not
329 ;; know let-bound variables.
330 (with-current-buffer "*Messages*"
331 (let (buffer-read-only)
332 (erase-buffer))
333 (let ((thread
334 (make-thread (lambda () (thread-signal main-thread 'error nil)))))
335 (while (thread-live-p thread)
336 (thread-yield))
337 (read-event nil nil 0.1)
338 ;; No error has been raised, which is part of the test.
339 (should
340 (string-match
341 (format-message "Error %s: (error nil)" thread)
342 (buffer-string ))))))
343
255(defvar threads-condvar nil) 344(defvar threads-condvar nil)
256 345
257(defun threads-test-condvar-wait () 346(defun threads-test-condvar-wait ()
@@ -263,7 +352,8 @@
263 (condition-wait threads-condvar))) 352 (condition-wait threads-condvar)))
264 353
265(ert-deftest threads-condvar-wait () 354(ert-deftest threads-condvar-wait ()
266 "test waiting on conditional variable" 355 "Test waiting on conditional variable."
356 (skip-unless (featurep 'threads))
267 (let ((cv-mutex (make-mutex)) 357 (let ((cv-mutex (make-mutex))
268 new-thread) 358 new-thread)
269 ;; We could have spurious threads from the previous tests still 359 ;; We could have spurious threads from the previous tests still
@@ -274,7 +364,7 @@
274 (setq new-thread (make-thread #'threads-test-condvar-wait)) 364 (setq new-thread (make-thread #'threads-test-condvar-wait))
275 365
276 ;; Make sure new-thread is alive. 366 ;; Make sure new-thread is alive.
277 (should (thread-alive-p new-thread)) 367 (should (thread-live-p new-thread))
278 (should (= (length (all-threads)) 2)) 368 (should (= (length (all-threads)) 2))
279 ;; Wait for new-thread to become blocked on the condvar. 369 ;; Wait for new-thread to become blocked on the condvar.
280 (while (not (eq (thread--blocker new-thread) threads-condvar)) 370 (while (not (eq (thread--blocker new-thread) threads-condvar))
@@ -287,7 +377,7 @@
287 (sleep-for 0.1) 377 (sleep-for 0.1)
288 ;; Make sure the thread is still there. This used to fail due to 378 ;; Make sure the thread is still there. This used to fail due to
289 ;; a bug in thread.c:condition_wait_callback. 379 ;; a bug in thread.c:condition_wait_callback.
290 (should (thread-alive-p new-thread)) 380 (should (thread-live-p new-thread))
291 (should (= (length (all-threads)) 2)) 381 (should (= (length (all-threads)) 2))
292 (should (eq (thread--blocker new-thread) threads-condvar)) 382 (should (eq (thread--blocker new-thread) threads-condvar))
293 383
@@ -298,4 +388,34 @@
298 (should (= (length (all-threads)) 1)) 388 (should (= (length (all-threads)) 1))
299 (should (equal (thread-last-error) '(error "Die, die, die!"))))) 389 (should (equal (thread-last-error) '(error "Die, die, die!")))))
300 390
301;;; threads.el ends here 391(ert-deftest threads-test-bug33073 ()
392 (skip-unless (fboundp 'make-thread))
393 (let ((th (make-thread 'ignore)))
394 (should-not (equal th main-thread))))
395
396(defvar threads-test--var 'global)
397
398(ert-deftest threads-test-bug48990 ()
399 (skip-unless (fboundp 'make-thread))
400 (let ((buf1 (generate-new-buffer " thread-test"))
401 (buf2 (generate-new-buffer " thread-test")))
402 (with-current-buffer buf1
403 (setq-local threads-test--var 'local1))
404 (with-current-buffer buf2
405 (setq-local threads-test--var 'local2))
406 (let ((seen nil))
407 (with-current-buffer buf1
408 (should (eq threads-test--var 'local1))
409 (make-thread (lambda () (setq seen threads-test--var))))
410 (with-current-buffer buf2
411 (should (eq threads-test--var 'local2))
412 (let ((threads-test--var 'let2))
413 (should (eq threads-test--var 'let2))
414 (while (not seen)
415 (thread-yield))
416 (should (eq threads-test--var 'let2))
417 (should (eq seen 'local1)))
418 (should (eq threads-test--var 'local2)))
419 (should (eq threads-test--var 'global)))))
420
421;;; thread-tests.el ends here
diff --git a/test/src/timefns-tests.el b/test/src/timefns-tests.el
new file mode 100644
index 00000000000..24f9000ffbd
--- /dev/null
+++ b/test/src/timefns-tests.el
@@ -0,0 +1,264 @@
1;;; timefns-tests.el --- tests for timefns.c -*- lexical-binding: t -*-
2
3;; Copyright (C) 2016-2022 Free Software Foundation, Inc.
4
5;; This file is part of GNU Emacs.
6
7;; GNU Emacs is free software: you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation, either version 3 of the License, or
10;; (at your option) any later version.
11
12;; GNU Emacs is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; GNU General Public License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
19
20;;; Code:
21
22(require 'ert)
23
24(defun timefns-tests--decode-time (look zone decoded-time)
25 (should (equal (decode-time look zone t) decoded-time))
26 (should (equal (decode-time look zone 'integer)
27 (cons (time-convert (car decoded-time) 'integer)
28 (cdr decoded-time)))))
29
30;;; Check format-time-string and decode-time with various TZ settings.
31;;; Use only POSIX-compatible TZ values, since the tests should work
32;;; even if tzdb is not in use.
33(ert-deftest format-time-string-with-zone ()
34 ;; Don’t use (0 0 0 0) as the test case, as there are too many bugs
35 ;; in MS-Windows (and presumably other) C libraries when formatting
36 ;; time stamps near the Epoch of 1970-01-01 00:00:00 UTC, and this
37 ;; test is for GNU Emacs, not for C runtimes. Instead, look before
38 ;; you leap: "look" is the timestamp just before the first leap
39 ;; second on 1972-06-30 23:59:60 UTC, so it should format to the
40 ;; same string regardless of whether the underlying C library
41 ;; ignores leap seconds, while avoiding circa-1970 glitches.
42 ;;
43 ;; Similarly, stick to the limited set of time zones that are
44 ;; supported by both POSIX and MS-Windows: exactly 3 ASCII letters
45 ;; in the abbreviation, and no DST.
46 (let ((format "%Y-%m-%d %H:%M:%S.%3N %z (%Z)"))
47 (dolist (look '((1202 22527 999999 999999)
48 (7879679999900 . 100000)
49 (78796799999999999999 . 1000000000000)))
50 ;; UTC.
51 (let* ((look-ticks-hz (time-convert look t))
52 (hz (cdr look-ticks-hz))
53 (look-integer (time-convert look 'integer))
54 (sec (time-add (time-convert 59 hz)
55 (time-subtract look-ticks-hz
56 (time-convert look-integer hz)))))
57 (should (string-equal
58 (format-time-string "%Y-%m-%d %H:%M:%S.%3N %z" look t)
59 "1972-06-30 23:59:59.999 +0000"))
60 (timefns-tests--decode-time look t
61 (list sec 59 23 30 6 1972 5 nil 0))
62 ;; "UTC0".
63 (should (string-equal
64 (format-time-string format look "UTC0")
65 "1972-06-30 23:59:59.999 +0000 (UTC)"))
66 (timefns-tests--decode-time look "UTC0"
67 (list sec 59 23 30 6 1972 5 nil 0))
68 ;; Negative UTC offset, as a Lisp list.
69 (should (string-equal
70 (format-time-string format look '(-28800 "PST"))
71 "1972-06-30 15:59:59.999 -0800 (PST)"))
72 (timefns-tests--decode-time look '(-28800 "PST")
73 (list sec 59 15 30 6 1972 5 nil -28800))
74 ;; Negative UTC offset, as a Lisp integer.
75 (should (string-equal
76 (format-time-string format look -28800)
77 ;; MS-Windows build replaces unrecognizable TZ values,
78 ;; such as "-08", with "ZZZ".
79 (if (eq system-type 'windows-nt)
80 "1972-06-30 15:59:59.999 -0800 (ZZZ)"
81 "1972-06-30 15:59:59.999 -0800 (-08)")))
82 (timefns-tests--decode-time look -28800
83 (list sec 59 15 30 6 1972 5 nil -28800))
84 ;; Positive UTC offset that is not an hour multiple, as a string.
85 (should (string-equal
86 (format-time-string format look "IST-5:30")
87 "1972-07-01 05:29:59.999 +0530 (IST)"))
88 (timefns-tests--decode-time look "IST-5:30"
89 (list sec 29 5 1 7 1972 6 nil 19800))))))
90
91(ert-deftest decode-then-encode-time ()
92 (let ((time-values (list 0 -2 1 0.0 -0.0 -2.0 1.0
93 most-negative-fixnum most-positive-fixnum
94 (1- most-negative-fixnum)
95 (1+ most-positive-fixnum)
96 '(0 1 0 0) '(1 0 0 0) '(-1 0 0 0)
97 '(123456789000000 . 1000000)
98 (cons (1+ most-positive-fixnum) 1000000000000)
99 (cons 1000000000000 (1+ most-positive-fixnum)))))
100 (dolist (a time-values)
101 (let* ((d (ignore-errors (decode-time a t t)))
102 (d-integer (ignore-errors (decode-time a t 'integer)))
103 (e (if d (encode-time d)))
104 (e-integer (if d-integer (encode-time d-integer))))
105 (should (or (not d) (time-equal-p a e)))
106 (should (or (not d-integer) (time-equal-p (time-convert a 'integer)
107 e-integer)))))))
108
109;;; This should not dump core.
110(ert-deftest format-time-string-with-outlandish-zone ()
111 (should (stringp
112 (format-time-string "%Y-%m-%d %H:%M:%S.%3N %z" nil
113 (concat (make-string 2048 ?X) "0")))))
114
115(defun timefns-tests--have-leap-seconds ()
116 (string-equal (format-time-string "%Y-%m-%d %H:%M:%S" 78796800 t)
117 "1972-06-30 23:59:60"))
118
119(ert-deftest format-time-string-with-bignum-on-32-bit ()
120 (should (or (string-equal
121 (format-time-string "%Y-%m-%d %H:%M:%S" (- (ash 1 31) 3600) t)
122 "2038-01-19 02:14:08")
123 (timefns-tests--have-leap-seconds))))
124
125;;; Tests of format-time-string padding
126
127(ert-deftest format-time-string-padding-minimal-deletes-unneeded-zeros ()
128 (let ((ref-time (encode-time '((123450 . 1000000) 0 0 15 2 2000 - - t))))
129 (should (equal (format-time-string "%-:::z" ref-time "FJT-12") "+12"))
130 (should (equal (format-time-string "%-N" ref-time t) "12345"))
131 (should (equal (format-time-string "%-6N" ref-time t) "12345"))
132 (should (equal (format-time-string "%-m" ref-time t) "2")))) ;not "02"
133
134(ert-deftest format-time-string-padding-minimal-retains-needed-zeros ()
135 (let ((ref-time (encode-time '((3450 . 1000000) 0 0 20 10 2000 - - t))))
136 (should (equal (format-time-string "%-z" ref-time "IST-5:30") "+530"))
137 (should (equal (format-time-string "%-4z" ref-time "IST-5:30") "+530"))
138 (should (equal (format-time-string "%4z" ref-time "IST-5:30") "+530"))
139 (should (equal (format-time-string "%-N" ref-time t) "00345"))
140 (should (equal (format-time-string "%-3N" ref-time t) "003"))
141 (should (equal (format-time-string "%3N" ref-time t) "003"))
142 (should (equal (format-time-string "%-m" ref-time t) "10")) ;not "1"
143 (should (equal (format-time-string "%-1m" ref-time t) "10")) ;not "1"
144 (should (equal (format-time-string "%1m" ref-time t) "10")))) ;not "1"
145
146(ert-deftest format-time-string-padding-spaces ()
147 (let ((ref-time (encode-time '((123000 . 1000000) 0 0 10 12 2000 - - t))))
148 (should (equal (format-time-string "%_7z" ref-time "CHA-12:45") " +1245"))
149 (should (equal (format-time-string "%_6N" ref-time t) "123 "))
150 (should (equal (format-time-string "%_9N" ref-time t) "123 "))
151 (should (equal (format-time-string "%_12N" ref-time t) "123 "))
152 (should (equal (format-time-string "%_m" ref-time t) "12"))
153 (should (equal (format-time-string "%_2m" ref-time t) "12"))
154 (should (equal (format-time-string "%_3m" ref-time t) " 12"))))
155
156(ert-deftest format-time-string-padding-zeros-adds-on-insignificant-side ()
157 "Fractional seconds have a fixed place on the left,
158and any padding must happen on the right. All other numbers have
159a fixed place on the right and are padded on the left."
160 (let ((ref-time (encode-time '((123000 . 1000000) 0 0 10 12 2000 - - t))))
161 (should (equal (format-time-string "%3m" ref-time t) "012"))
162 (should (equal (format-time-string "%7z" ref-time "CHA-12:45") "+001245"))
163 (should (equal (format-time-string "%12N" ref-time t) "123000000000"))
164 (should (equal (format-time-string "%9N" ref-time t) "123000000"))
165 (should (equal (format-time-string "%6N" ref-time t) "123000"))))
166
167
168(ert-deftest time-equal-p-nil-nil ()
169 (should (time-equal-p nil nil)))
170
171(ert-deftest time-arith-tests ()
172 (let ((time-values (list 0 -1 1 0.0 -0.0 -1.0 1.0
173 most-negative-fixnum most-positive-fixnum
174 (1- most-negative-fixnum)
175 (1+ most-positive-fixnum)
176 1e1 -1e1 1e-1 -1e-1
177 1e8 -1e8 1e-8 -1e-8
178 1e9 -1e9 1e-9 -1e-9
179 1e10 -1e10 1e-10 -1e-10
180 1e16 -1e16 1e-16 -1e-16
181 1e37 -1e37 1e-37 -1e-37
182 '(0 0 0 1) '(0 0 1 0) '(0 1 0 0) '(1 0 0 0)
183 '(-1 0 0 0) '(1 2 3 4) '(-1 2 3 4)
184 '(-123456789 . 100000) '(123456789 . 1000000)
185 (cons (1+ most-positive-fixnum) 1000000000000)
186 (cons 1000000000000 (1+ most-positive-fixnum)))))
187 (dolist (a time-values)
188 (should-error (time-add a 'ouch))
189 (should-error (time-add 'ouch a))
190 (should-error (time-subtract a 'ouch))
191 (should-error (time-subtract 'ouch a))
192 (dolist (b time-values)
193 (let ((aa (time-subtract (time-add a b) b)))
194 (should (or (time-equal-p a aa) (and (floatp aa) (isnan aa)))))
195 (should (= 1 (+ (if (time-less-p a b) 1 0)
196 (if (time-equal-p a b) 1 0)
197 (if (time-less-p b a) 1 0)
198 (if (or (and (floatp a) (isnan a))
199 (and (floatp b) (isnan b)))
200 1 0))))
201 (should (or (not (time-less-p 0 b))
202 (time-less-p a (time-add a b))
203 (time-equal-p a (time-add a b))
204 (and (floatp (time-add a b)) (isnan (time-add a b)))))
205 (let ((x (float-time (time-add a b)))
206 (y (+ (float-time a) (float-time b))))
207 (should (or (and (isnan x) (isnan y))
208 (= x y)
209 (< 0.99 (/ x y) 1.01)
210 (< 0.99 (/ (- (float-time a)) (float-time b))
211 1.01))))))))
212
213(ert-deftest time-rounding-tests ()
214 (should (time-equal-p 1e-13 (time-add 0 1e-13))))
215
216(ert-deftest encode-time-dst-numeric-zone ()
217 "Check for Bug#35502."
218 (should (time-equal-p
219 (encode-time '(29 31 17 30 4 2019 2 t 7200))
220 '(23752 27217))))
221
222(ert-deftest encode-time-alternate-apis ()
223 (let* ((time '(30 30 12 15 6 1970))
224 (time-1 (append time '(nil -1 nil)))
225 (etime (encode-time time)))
226 (should (time-equal-p etime (encode-time time-1)))
227 (should (time-equal-p etime (apply #'encode-time time)))
228 (should (time-equal-p etime (apply #'encode-time time-1)))
229 (should (time-equal-p etime (apply #'encode-time (append time '(nil)))))))
230
231(ert-deftest float-time-precision ()
232 (should (= (float-time '(0 1 0 4025)) 1.000000004025))
233 (should (= (float-time '(1000000004025 . 1000000000000)) 1.000000004025))
234
235 (should (< 0 (float-time '(1 . 10000000000))))
236 (should (< (float-time '(-1 . 10000000000)) 0))
237
238 (let ((x 1.0))
239 (while (not (zerop x))
240 (dolist (multiplier '(-1.9 -1.5 -1.1 -1 1 1.1 1.5 1.9))
241 (let ((xmult (* x multiplier)))
242 (should (= xmult (float-time (time-convert xmult t))))))
243 (setq x (/ x 2))))
244
245 (let ((x 1.0))
246 (while (ignore-errors (time-convert x t))
247 (dolist (divisor '(-1.9 -1.5 -1.1 -1 1 1.1 1.5 1.9))
248 (let ((xdiv (/ x divisor)))
249 (should (= xdiv (float-time (time-convert xdiv t))))))
250 (setq x (* x 2)))))
251
252(ert-deftest time-convert-forms ()
253 ;; These computations involve numbers that should have exact
254 ;; representations on any Emacs platform.
255 (dolist (time '(-86400 -1 0 1 86400))
256 (dolist (delta '(0 0.0 0.25 3.25 1000 1000.25))
257 (let ((time+ (+ time delta))
258 (time- (- time delta)))
259 (dolist (form '(nil t list 4 1000 1000000 1000000000))
260 (should (time-equal-p time (time-convert time form)))
261 (should (time-equal-p time- (time-convert time- form)))
262 (should (time-equal-p time+ (time-convert time+ form))))))))
263
264;;; timefns-tests.el ends here
diff --git a/test/src/undo-tests.el b/test/src/undo-tests.el
index 3ff75ae68d5..cb0822fb1b9 100644
--- a/test/src/undo-tests.el
+++ b/test/src/undo-tests.el
@@ -1,21 +1,23 @@
1;;; undo-tests.el --- Tests of primitive-undo 1;;; undo-tests.el --- Tests of primitive-undo -*- lexical-binding: t -*-
2 2
3;; Copyright (C) 2012-2017 Free Software Foundation, Inc. 3;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
4 4
5;; Author: Aaron S. Hawley <aaron.s.hawley@gmail.com> 5;; Author: Aaron S. Hawley <aaron.s.hawley@gmail.com>
6 6
7;; This program is free software: you can redistribute it and/or 7;; This file is part of GNU Emacs.
8;;
9;; GNU Emacs is free software: you can redistribute it and/or
8;; modify it under the terms of the GNU General Public License as 10;; modify it under the terms of the GNU General Public License as
9;; published by the Free Software Foundation, either version 3 of the 11;; published by the Free Software Foundation, either version 3 of the
10;; License, or (at your option) any later version. 12;; License, or (at your option) any later version.
11;; 13;;
12;; This program is distributed in the hope that it will be useful, but 14;; GNU Emacs is distributed in the hope that it will be useful, but
13;; WITHOUT ANY WARRANTY; without even the implied warranty of 15;; WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15;; General Public License for more details. 17;; General Public License for more details.
16;; 18;;
17;; You should have received a copy of the GNU General Public License 19;; You should have received a copy of the GNU General Public License
18;; along with this program. If not, see `https://www.gnu.org/licenses/'. 20;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
19 21
20;;; Commentary: 22;;; Commentary:
21 23
@@ -44,6 +46,8 @@
44;;; Code: 46;;; Code:
45 47
46(require 'ert) 48(require 'ert)
49(require 'ert-x)
50(require 'facemenu)
47 51
48(ert-deftest undo-test0 () 52(ert-deftest undo-test0 ()
49 "Test basics of \\[undo]." 53 "Test basics of \\[undo]."
@@ -72,7 +76,7 @@
72 (undo-boundary) 76 (undo-boundary)
73 (put-text-property (point-min) (point-max) 'face 'bold) 77 (put-text-property (point-min) (point-max) 'face 'bold)
74 (undo-boundary) 78 (undo-boundary)
75 (remove-text-properties (point-min) (point-max) '(face default)) 79 (remove-list-of-text-properties (point-min) (point-max) '(face))
76 (undo-boundary) 80 (undo-boundary)
77 (set-buffer-multibyte (not enable-multibyte-characters)) 81 (set-buffer-multibyte (not enable-multibyte-characters))
78 (undo-boundary) 82 (undo-boundary)
@@ -85,6 +89,7 @@
85 89
86(ert-deftest undo-test1 () 90(ert-deftest undo-test1 ()
87 "Test undo of \\[undo] command (redo)." 91 "Test undo of \\[undo] command (redo)."
92 (require 'facemenu)
88 (with-temp-buffer 93 (with-temp-buffer
89 (buffer-enable-undo) 94 (buffer-enable-undo)
90 (undo-boundary) 95 (undo-boundary)
@@ -214,17 +219,14 @@
214 219
215(ert-deftest undo-test-file-modified () 220(ert-deftest undo-test-file-modified ()
216 "Test undoing marks buffer visiting file unmodified." 221 "Test undoing marks buffer visiting file unmodified."
217 (let ((tempfile (make-temp-file "undo-test"))) 222 (ert-with-temp-file tempfile
218 (unwind-protect 223 (with-current-buffer (find-file-noselect tempfile)
219 (progn 224 (insert "1")
220 (with-current-buffer (find-file-noselect tempfile) 225 (undo-boundary)
221 (insert "1") 226 (set-buffer-modified-p nil)
222 (undo-boundary) 227 (insert "2")
223 (set-buffer-modified-p nil) 228 (undo)
224 (insert "2") 229 (should-not (buffer-modified-p)))))
225 (undo)
226 (should-not (buffer-modified-p))))
227 (delete-file tempfile))))
228 230
229(ert-deftest undo-test-region-not-most-recent () 231(ert-deftest undo-test-region-not-most-recent ()
230 "Test undo in region of an edit not the most recent." 232 "Test undo in region of an edit not the most recent."
@@ -255,7 +257,7 @@
255 (insert "12345") 257 (insert "12345")
256 (search-backward "4") 258 (search-backward "4")
257 (undo-boundary) 259 (undo-boundary)
258 (delete-forward-char 1) 260 (funcall-interactively 'delete-forward-char 1)
259 (search-backward "1") 261 (search-backward "1")
260 (undo-boundary) 262 (undo-boundary)
261 (insert "xxxx") 263 (insert "xxxx")
@@ -299,7 +301,7 @@ undo-make-selective-list."
299 (insert "ddd") 301 (insert "ddd")
300 (search-backward "ad") 302 (search-backward "ad")
301 (undo-boundary) 303 (undo-boundary)
302 (delete-forward-char 2) 304 (funcall-interactively 'delete-forward-char 2)
303 (undo-boundary) 305 (undo-boundary)
304 ;; Select "dd" 306 ;; Select "dd"
305 (push-mark (point) t t) 307 (push-mark (point) t t)
@@ -348,7 +350,7 @@ undo-make-selective-list."
348 (let ((m (make-marker))) 350 (let ((m (make-marker)))
349 (set-marker m 2 (current-buffer)) 351 (set-marker m 2 (current-buffer))
350 (goto-char (point-min)) 352 (goto-char (point-min))
351 (delete-forward-char 3) 353 (funcall-interactively 'delete-forward-char 3)
352 (undo-boundary) 354 (undo-boundary)
353 (should (= (point-min) (marker-position m))) 355 (should (= (point-min) (marker-position m)))
354 (undo) 356 (undo)
@@ -369,7 +371,7 @@ undo-make-selective-list."
369 (push-mark (point) t t) 371 (push-mark (point) t t)
370 (setq mark-active t) 372 (setq mark-active t)
371 (goto-char (point-min)) 373 (goto-char (point-min))
372 (delete-forward-char 1) ;; delete region covering "ab" 374 (funcall-interactively 'delete-forward-char 1) ; delete region covering "ab"
373 (undo-boundary) 375 (undo-boundary)
374 (should (= (point-min) (marker-position m))) 376 (should (= (point-min) (marker-position m)))
375 ;; Resurrect "ab". m's insertion type means the reinsertion 377 ;; Resurrect "ab". m's insertion type means the reinsertion
@@ -389,7 +391,7 @@ Demonstrates bug 16818."
389 (let ((m (make-marker))) 391 (let ((m (make-marker)))
390 (set-marker m 2 (current-buffer)) ; m at b 392 (set-marker m 2 (current-buffer)) ; m at b
391 (goto-char (point-min)) 393 (goto-char (point-min))
392 (delete-forward-char 3) ; m at d 394 (funcall-interactively 'delete-forward-char 3) ; m at d
393 (undo-boundary) 395 (undo-boundary)
394 (set-marker m 4) ; m at g 396 (set-marker m 4) ; m at g
395 (undo) 397 (undo)
@@ -422,7 +424,7 @@ Demonstrates bug 16818."
422 (push-mark (point) t t) 424 (push-mark (point) t t)
423 (setq mark-active t) 425 (setq mark-active t)
424 (goto-char (- (point) 3)) 426 (goto-char (- (point) 3))
425 (delete-forward-char 1) 427 (funcall-interactively 'delete-forward-char 1)
426 (undo-boundary) 428 (undo-boundary)
427 429
428 (insert "bbb") 430 (insert "bbb")
@@ -452,17 +454,16 @@ Demonstrates bug 25599."
452 (insert ";; aaaaaaaaa 454 (insert ";; aaaaaaaaa
453;; bbbbbbbb") 455;; bbbbbbbb")
454 (let ((overlay-modified 456 (let ((overlay-modified
455 (lambda (ov after-p _beg _end &optional length) 457 (lambda (ov after-p _beg _end &optional _length)
456 (unless after-p 458 (unless after-p
457 (when (overlay-buffer ov) 459 (when (overlay-buffer ov)
458 (delete-overlay ov)))))) 460 (delete-overlay ov))))))
459 (save-excursion 461 (save-excursion
460 (goto-char (point-min)) 462 (goto-char (point-min))
461 (let ((ov (make-overlay (line-beginning-position 2) 463 (let ((ov (make-overlay (pos-bol 2) (pos-eol 2))))
462 (line-end-position 2))))
463 (overlay-put ov 'insert-in-front-hooks 464 (overlay-put ov 'insert-in-front-hooks
464 (list overlay-modified))))) 465 (list overlay-modified)))))
465 (kill-region (point-min) (line-beginning-position 2)) 466 (kill-region (point-min) (pos-bol 2))
466 (undo-boundary) 467 (undo-boundary)
467 (undo))) 468 (undo)))
468 469
diff --git a/test/src/xdisp-tests.el b/test/src/xdisp-tests.el
new file mode 100644
index 00000000000..6ff64d0431a
--- /dev/null
+++ b/test/src/xdisp-tests.el
@@ -0,0 +1,182 @@
1;;; xdisp-tests.el --- tests for xdisp.c functions -*- lexical-binding: t -*-
2
3;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
4
5;; This file is part of GNU Emacs.
6
7;; GNU Emacs is free software: you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation, either version 3 of the License, or
10;; (at your option) any later version.
11
12;; GNU Emacs is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; GNU General Public License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
19
20;;; Code:
21
22(require 'ert)
23
24(defmacro xdisp-tests--in-minibuffer (&rest body)
25 (declare (debug t) (indent 0))
26 `(catch 'result
27 (minibuffer-with-setup-hook
28 (lambda ()
29 (let ((redisplay-skip-initial-frame nil)
30 (executing-kbd-macro nil)) ;Don't skip redisplay
31 (throw 'result (progn . ,body))))
32 (let ((executing-kbd-macro t)) ;Force real minibuffer in `read-string'.
33 (read-string "toto: ")))))
34
35(ert-deftest xdisp-tests--minibuffer-resizing () ;; bug#43519
36 (should
37 (equal
38 t
39 (xdisp-tests--in-minibuffer
40 (insert "hello")
41 (let ((ol (make-overlay (point) (point)))
42 (max-mini-window-height 1)
43 (text "askdjfhaklsjdfhlkasjdfhklasdhflkasdhflkajsdhflkashdfkljahsdlfkjahsdlfkjhasldkfhalskdjfhalskdfhlaksdhfklasdhflkasdhflkasdhflkajsdhklajsdgh"))
44 ;; (save-excursion (insert text))
45 ;; (sit-for 2)
46 ;; (delete-region (point) (point-max))
47 (put-text-property 0 1 'cursor t text)
48 (overlay-put ol 'after-string text)
49 (redisplay 'force)
50 ;; Make sure we do the see "hello" text.
51 (prog1 (equal (window-start) (point-min))
52 ;; (list (window-start) (window-end) (window-width))
53 (delete-overlay ol)))))))
54
55(ert-deftest xdisp-tests--minibuffer-scroll () ;; bug#44070
56 (let ((posns
57 (xdisp-tests--in-minibuffer
58 (let ((max-mini-window-height 4))
59 (dotimes (_ 80) (insert "\nhello"))
60 (goto-char (point-min))
61 (redisplay 'force)
62 (goto-char (point-max))
63 ;; A simple edit like removing the last `o' shouldn't cause
64 ;; the rest of the minibuffer's text to move.
65 (list
66 (progn (redisplay 'force) (window-start))
67 (progn (delete-char -1)
68 (redisplay 'force) (window-start))
69 (progn (goto-char (point-min)) (redisplay 'force)
70 (goto-char (point-max)) (redisplay 'force)
71 (window-start)))))))
72 (should (equal (nth 0 posns) (nth 1 posns)))
73 (should (equal (nth 1 posns) (nth 2 posns)))))
74
75(ert-deftest xdisp-tests--window-text-pixel-size () ;; bug#45748
76 (with-temp-buffer
77 (insert "xxx")
78 (switch-to-buffer (current-buffer))
79 (let* ((char-width (frame-char-width))
80 (size (window-text-pixel-size nil t t))
81 (width-in-chars (/ (car size) char-width)))
82 (should (equal width-in-chars 3)))))
83
84(ert-deftest xdisp-tests--window-text-pixel-size-leading-space () ;; bug#45748
85 (with-temp-buffer
86 (insert " xx")
87 (switch-to-buffer (current-buffer))
88 (let* ((char-width (frame-char-width))
89 (size (window-text-pixel-size nil t t))
90 (width-in-chars (/ (car size) char-width)))
91 (should (equal width-in-chars 3)))))
92
93(ert-deftest xdisp-tests--window-text-pixel-size-trailing-space () ;; bug#45748
94 (with-temp-buffer
95 (insert "xx ")
96 (switch-to-buffer (current-buffer))
97 (let* ((char-width (frame-char-width))
98 (size (window-text-pixel-size nil t t))
99 (width-in-chars (/ (car size) char-width)))
100 (should (equal width-in-chars 3)))))
101
102(ert-deftest xdisp-tests--find-directional-overrides-case-1 ()
103 (with-temp-buffer
104 (insert "\
105int main() {
106 bool isAdmin = false;
107 /*‮ }⁦if (isAdmin)⁩ ⁦ begin admins only */
108 printf(\"You are an admin.\\n\");
109 /* end admins only ‮ { ⁦*/
110 return 0;
111}")
112 (goto-char (point-min))
113 (should (eq (bidi-find-overridden-directionality (point-min) (point-max)
114 nil)
115 46))))
116
117(ert-deftest xdisp-tests--find-directional-overrides-case-2 ()
118 (with-temp-buffer
119 (insert "\
120#define is_restricted_user(user) \\
121 !strcmp (user, \"root\") ? 0 : \\
122 !strcmp (user, \"admin\") ? 0 : \\
123 !strcmp (user, \"superuser‮⁦? 0 : 1⁩ ⁦\")⁩‬
124
125int main () {
126 printf (\"root: %d\\n\", is_restricted_user (\"root\"));
127 printf (\"admin: %d\\n\", is_restricted_user (\"admin\"));
128 printf (\"superuser: %d\\n\", is_restricted_user (\"superuser\"));
129 printf (\"luser: %d\\n\", is_restricted_user (\"luser\"));
130 printf (\"nobody: %d\\n\", is_restricted_user (\"nobody\"));
131}")
132 (goto-char (point-min))
133 (should (eq (bidi-find-overridden-directionality (point-min) (point-max)
134 nil)
135 138))))
136
137(ert-deftest xdisp-tests--find-directional-overrides-case-3 ()
138 (with-temp-buffer
139 (insert "\
140#define is_restricted_user(user) \\
141 !strcmp (user, \"root\") ? 0 : \\
142 !strcmp (user, \"admin\") ? 0 : \\
143 !strcmp (user, \"superuser‮⁦? '#' : '!'⁩ ⁦\")⁩‬
144
145int main () {
146 printf (\"root: %d\\n\", is_restricted_user (\"root\"));
147 printf (\"admin: %d\\n\", is_restricted_user (\"admin\"));
148 printf (\"superuser: %d\\n\", is_restricted_user (\"superuser\"));
149 printf (\"luser: %d\\n\", is_restricted_user (\"luser\"));
150 printf (\"nobody: %d\\n\", is_restricted_user (\"nobody\"));
151}")
152 (goto-char (point-min))
153 (should (eq (bidi-find-overridden-directionality (point-min) (point-max)
154 nil)
155 138))))
156
157(ert-deftest test-get-display-property ()
158 (with-temp-buffer
159 (insert (propertize "foo" 'face 'bold 'display '(height 2.0)))
160 (should (equal (get-display-property 2 'height) 2.0)))
161 (with-temp-buffer
162 (insert (propertize "foo" 'face 'bold 'display '((height 2.0)
163 (space-width 2.0))))
164 (should (equal (get-display-property 2 'height) 2.0))
165 (should (equal (get-display-property 2 'space-width) 2.0)))
166 (with-temp-buffer
167 (insert (propertize "foo bar" 'face 'bold
168 'display '[(height 2.0)
169 (space-width 20)]))
170 (should (equal (get-display-property 2 'height) 2.0))
171 (should (equal (get-display-property 2 'space-width) 20))))
172
173(ert-deftest test-messages-buffer-name ()
174 (should
175 (equal
176 (let ((messages-buffer-name "test-message"))
177 (message "foo")
178 (with-current-buffer messages-buffer-name
179 (buffer-string)))
180 "foo\n")))
181
182;;; xdisp-tests.el ends here
diff --git a/test/src/xfaces-tests.el b/test/src/xfaces-tests.el
new file mode 100644
index 00000000000..16f16537918
--- /dev/null
+++ b/test/src/xfaces-tests.el
@@ -0,0 +1,57 @@
1;;; xfaces-tests.el --- tests for xfaces.c -*- lexical-binding: t -*-
2
3;; Copyright (C) 2020-2022 Free Software Foundation, Inc.
4
5;; This file is part of GNU Emacs.
6
7;; GNU Emacs is free software: you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation, either version 3 of the License, or
10;; (at your option) any later version.
11
12;; GNU Emacs is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; GNU General Public License for more details.
16
17;; You should have received a copy of the GNU General Public License
18;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
19
20;;; Code:
21
22(require 'ert)
23
24(ert-deftest xfaces-color-distance ()
25 ;; Check symmetry (bug#41544).
26 (should (equal (color-distance "#222222" "#ffffff")
27 (color-distance "#ffffff" "#222222"))))
28
29(ert-deftest xfaces-internal-color-values-from-color-spec ()
30 (should (equal (color-values-from-color-spec "#f05")
31 '(#xffff #x0000 #x5555)))
32 (should (equal (color-values-from-color-spec "#1fb0C5")
33 '(#x1f1f #xb0b0 #xc5c5)))
34 (should (equal (color-values-from-color-spec "#1f8b0AC5e")
35 '(#x1f81 #xb0aa #xc5eb)))
36 (should (equal (color-values-from-color-spec "#1f83b0ADC5e2")
37 '(#x1f83 #xb0ad #xc5e2)))
38 (should (equal (color-values-from-color-spec "#1f83b0ADC5e2g") nil))
39 (should (equal (color-values-from-color-spec "#1f83b0ADC5e20") nil))
40 (should (equal (color-values-from-color-spec "#12345") nil))
41 (should (equal (color-values-from-color-spec "rgb:f/23/28a")
42 '(#xffff #x2323 #x28a2)))
43 (should (equal (color-values-from-color-spec "rgb:1234/5678/09ab")
44 '(#x1234 #x5678 #x09ab)))
45 (should (equal (color-values-from-color-spec "rgb:0//0") nil))
46 (should (equal (color-values-from-color-spec "rgbi:0/0.5/0.1")
47 '(0 32768 6554)))
48 (should (equal (color-values-from-color-spec "rgbi:1e-3/1.0e-2/1e0")
49 '(66 655 65535)))
50 (should (equal (color-values-from-color-spec "rgbi:0/0.5/10") nil))
51 (should (equal (color-values-from-color-spec "rgbi:0/0/ 0") nil))
52 (should (equal (color-values-from-color-spec "rgbi:0/0x0/0") nil))
53 (should (equal (color-values-from-color-spec "rgbi:0/+0x1/0") nil)))
54
55(provide 'xfaces-tests)
56
57;;; xfaces-tests.el ends here
diff --git a/test/src/xml-tests.el b/test/src/xml-tests.el
index 557e6da4524..6a8290bd0c8 100644
--- a/test/src/xml-tests.el
+++ b/test/src/xml-tests.el
@@ -1,6 +1,6 @@
1;;; libxml-parse-tests.el --- Test suite for libxml parsing. 1;;; xml-tests.el --- Test suite for libxml parsing. -*- lexical-binding: t -*-
2 2
3;; Copyright (C) 2014-2017 Free Software Foundation, Inc. 3;; Copyright (C) 2014-2022 Free Software Foundation, Inc.
4 4
5;; Author: Ulf Jasper <ulf.jasper@web.de> 5;; Author: Ulf Jasper <ulf.jasper@web.de>
6;; Keywords: internal 6;; Keywords: internal
@@ -27,6 +27,8 @@
27 27
28(require 'ert) 28(require 'ert)
29 29
30(declare-function libxml-parse-xml-region "xml.c")
31
30(defvar libxml-tests--data-comments-preserved 32(defvar libxml-tests--data-comments-preserved
31 `(;; simple case 33 `(;; simple case
32 ("<?xml version=\"1.0\"?><foo baz=\"true\">bar</foo>" 34 ("<?xml version=\"1.0\"?><foo baz=\"true\">bar</foo>"
@@ -42,33 +44,14 @@
42 (comment nil "comment-b") (comment nil "comment-c")))) 44 (comment nil "comment-b") (comment nil "comment-c"))))
43 "Alist of XML strings and their expected parse trees for preserved comments.") 45 "Alist of XML strings and their expected parse trees for preserved comments.")
44 46
45(defvar libxml-tests--data-comments-discarded
46 `(;; simple case
47 ("<?xml version=\"1.0\"?><foo baz=\"true\">bar</foo>"
48 . (foo ((baz . "true")) "bar"))
49 ;; toplevel comments -- first document child must not get lost
50 (,(concat "<?xml version=\"1.0\"?><foo>bar</foo><!--comment-1-->"
51 "<!--comment-2-->")
52 . (foo nil "bar"))
53 (,(concat "<?xml version=\"1.0\"?><!--comment-a--><foo a=\"b\">"
54 "<bar>blub</bar></foo><!--comment-b--><!--comment-c-->")
55 . (foo ((a . "b")) (bar nil "blub"))))
56 "Alist of XML strings and their expected parse trees for discarded comments.")
57
58
59(ert-deftest libxml-tests () 47(ert-deftest libxml-tests ()
60 "Test libxml." 48 "Test libxml."
61 (when (fboundp 'libxml-parse-xml-region) 49 (skip-unless (fboundp 'libxml-parse-xml-region))
62 (with-temp-buffer 50 (with-temp-buffer
63 (dolist (test libxml-tests--data-comments-preserved) 51 (dolist (test libxml-tests--data-comments-preserved)
64 (erase-buffer) 52 (erase-buffer)
65 (insert (car test)) 53 (insert (car test))
66 (should (equal (cdr test) 54 (should (equal (cdr test)
67 (libxml-parse-xml-region (point-min) (point-max))))) 55 (libxml-parse-xml-region (point-min) (point-max)))))))
68 (dolist (test libxml-tests--data-comments-discarded) 56
69 (erase-buffer) 57;;; xml-tests.el ends here
70 (insert (car test))
71 (should (equal (cdr test)
72 (libxml-parse-xml-region (point-min) (point-max) nil t)))))))
73
74;;; libxml-tests.el ends here