diff options
| author | Stefan Monnier | 2022-09-25 16:15:16 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2022-09-25 16:15:16 -0400 |
| commit | 650c20f1ca4e07591a727e1cfcc74b3363d15985 (patch) | |
| tree | 85d11f6437cde22f410c25e0e5f71a3131ebd07d /test/src | |
| parent | 8869332684c2302b5ba1ead4568bbc7ba1c0183e (diff) | |
| parent | 4b85ae6a24380fb67a3315eaec9233f17a872473 (diff) | |
| download | emacs-650c20f1ca4e07591a727e1cfcc74b3363d15985.tar.gz emacs-650c20f1ca4e07591a727e1cfcc74b3363d15985.zip | |
Merge 'master' into noverlay
Diffstat (limited to 'test/src')
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 | |||
| 31 | Always overwrites the `insert-in-front-hooks', | ||
| 32 | `modification-hooks' and `insert-behind-hooks' properties. Any | ||
| 33 | recorded history from a previous call is erased. | ||
| 34 | |||
| 35 | The history is stored in a property on the overlay itself. Call | ||
| 36 | `overlay-tests-get-recorded-modification-hooks' to retrieve the | ||
| 37 | recorded 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 | |||
| 56 | Must be preceded by a call to | ||
| 57 | `overlay-tests-start-recording-modification-hooks' on OVERLAY. | ||
| 58 | |||
| 59 | Returns a list. Each element of the list represents a recorded | ||
| 60 | call to a particular modification hook. | ||
| 61 | |||
| 62 | Each call is itself a sub-list where the first element is a | ||
| 63 | symbol 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 | ||
| 66 | arguments passed to the hook. The first hook argument, the | ||
| 67 | overlay itself, is omitted to make test result verification | ||
| 68 | easier." | ||
| 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 | |||
| 75 | This exercises hooks registered on the `insert-in-front-hooks', | ||
| 76 | `modification-hooks' and `insert-behind-hooks' overlay | ||
| 77 | properties." | ||
| 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. | ||
| 67 | Check 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. | ||
| 397 | https://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. | ||
| 784 | Return 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 | ||
| 1411 | folded." | ||
| 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. | ||
| 28 | It is also as small as conveniently possible, to make the tests sharper. | ||
| 29 | Adding 1.0 to `most-positive-fixnum' should suffice on all | ||
| 30 | practical Emacs platforms, since the result is a power of 2 and | ||
| 31 | this 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'. |
| 198 | DESC is a string describing the test. It is a sequence of | 207 | DESC is a string describing the test. It is a sequence of |
| 199 | hexadecimal digits describing the bool vector. We exhaustively | 208 | hexadecimal digits describing the bool vector. We exhaustively |
| 200 | test all counts at all possible positions in the vector by | 209 | test all counts at all possible positions in the vector by |
| 201 | comparing the subr with a much slower lisp implementation." | 210 | comparing 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 | "\ | ||
| 41 | key binding | ||
| 42 | --- ------- | ||
| 43 | 26 | ||
| 44 | C-g abort-recursive-edit | 27 | (ert-deftest doc-tests-documentation/preloaded () |
| 45 | TAB minibuffer-complete | 28 | (should (stringp (documentation 'defun)))) |
| 46 | C-j minibuffer-complete-and-exit | ||
| 47 | RET minibuffer-complete-and-exit | ||
| 48 | ESC Prefix Command | ||
| 49 | SPC 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 | ||
| 59 | M-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 | ||
| 61 | M-n next-history-element | 35 | (ert-deftest doc-tests-documentation/autoloaded-defun () |
| 62 | M-p previous-history-element | 36 | (skip-unless noninteractive) |
| 63 | M-r previous-matching-history-element | 37 | (should (autoloadp (symbol-function 'tetris))) |
| 64 | M-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 | |||
| 3 | Copyright 2015-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 (at | ||
| 10 | 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 | #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. */ | ||
| 37 | uintptr_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 | |||
| 50 | int 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'. */ | ||
| 76 | static emacs_value | ||
| 77 | Fmod_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. */ | ||
| 84 | static intmax_t | ||
| 85 | sum (intmax_t a, intmax_t b) | ||
| 86 | { | ||
| 87 | return a + b; | ||
| 88 | } | ||
| 89 | |||
| 90 | static emacs_value | ||
| 91 | Fmod_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). */ | ||
| 106 | static emacs_value | ||
| 107 | Fmod_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). */ | ||
| 118 | static emacs_value | ||
| 119 | Fmod_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. */ | ||
| 131 | static emacs_value | ||
| 132 | Fmod_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. */ | ||
| 169 | static emacs_value | ||
| 170 | Fmod_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. */ | ||
| 184 | static emacs_value | ||
| 185 | Fmod_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 | |||
| 204 | static emacs_value | ||
| 205 | Fmod_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 | |||
| 216 | static emacs_value | ||
| 217 | Fmod_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'. */ | ||
| 245 | static emacs_value | ||
| 246 | Fmod_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. */ | ||
| 268 | static emacs_value | ||
| 269 | Fmod_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. */ | ||
| 280 | struct super_struct | ||
| 281 | { | ||
| 282 | int amazing_int; | ||
| 283 | char large_unused_buffer[512]; | ||
| 284 | }; | ||
| 285 | |||
| 286 | static 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. */ | ||
| 290 | static emacs_value | ||
| 291 | Fmod_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'. */ | ||
| 305 | static emacs_value | ||
| 306 | Fmod_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]. */ | ||
| 315 | static emacs_value | ||
| 316 | Fmod_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]. */ | ||
| 330 | static emacs_value | ||
| 331 | Fmod_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 | |||
| 343 | static 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 | |||
| 351 | static emacs_value | ||
| 352 | Fmod_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 | |||
| 358 | static emacs_value | ||
| 359 | Fmod_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 | |||
| 370 | static emacs_value global_copy_of_invalid_stored_value; | ||
| 371 | |||
| 372 | static emacs_value | ||
| 373 | Fmod_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 | |||
| 385 | static emacs_env *current_env; | ||
| 386 | |||
| 387 | static void | ||
| 388 | invalid_finalizer (void *ptr) | ||
| 389 | { | ||
| 390 | current_env->intern (current_env, "nil"); | ||
| 391 | } | ||
| 392 | |||
| 393 | static emacs_value | ||
| 394 | Fmod_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 | |||
| 402 | static void | ||
| 403 | signal_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 | |||
| 414 | static void | ||
| 415 | signal_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. */ | ||
| 423 | static bool | ||
| 424 | timespec_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 | |||
| 433 | static emacs_value | ||
| 434 | Fmod_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 | |||
| 464 | static emacs_value | ||
| 465 | Fmod_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 | |||
| 476 | static void | ||
| 477 | signal_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 | |||
| 485 | static void | ||
| 486 | memory_full (emacs_env *env) | ||
| 487 | { | ||
| 488 | signal_error (env, "Memory exhausted"); | ||
| 489 | } | ||
| 490 | |||
| 491 | enum | ||
| 492 | { | ||
| 493 | max_count = ((SIZE_MAX < PTRDIFF_MAX ? SIZE_MAX : PTRDIFF_MAX) | ||
| 494 | / sizeof (emacs_limb_t)) | ||
| 495 | }; | ||
| 496 | |||
| 497 | static bool | ||
| 498 | extract_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 | |||
| 527 | static emacs_value | ||
| 528 | make_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 | ||
| 565 | static emacs_value | ||
| 566 | Fmod_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 | |||
| 581 | static emacs_value | ||
| 582 | Fmod_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 | |||
| 596 | static int function_data; | ||
| 597 | static int finalizer_calls_with_correct_data; | ||
| 598 | static int finalizer_calls_with_incorrect_data; | ||
| 599 | |||
| 600 | static void | ||
| 601 | finalizer (void *data) | ||
| 602 | { | ||
| 603 | if (data == &function_data) | ||
| 604 | ++finalizer_calls_with_correct_data; | ||
| 605 | else | ||
| 606 | ++finalizer_calls_with_incorrect_data; | ||
| 607 | } | ||
| 608 | |||
| 609 | static emacs_value | ||
| 610 | Fmod_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 | |||
| 621 | static emacs_value | ||
| 622 | Fmod_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 | |||
| 632 | static void | ||
| 633 | sleep_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 | ||
| 646 | static void ALIGN_STACK | ||
| 647 | #else | ||
| 648 | static void * | ||
| 649 | #endif | ||
| 650 | write_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 | |||
| 667 | static emacs_value | ||
| 668 | Fmod_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 | |||
| 699 | static emacs_value | ||
| 700 | Fmod_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 | |||
| 707 | static emacs_value | ||
| 708 | Fmod_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 | |||
| 715 | static emacs_value | ||
| 716 | Fmod_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. */ | ||
| 746 | static void | ||
| 747 | provide (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. */ | ||
| 757 | static void | ||
| 758 | bind_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. */ | ||
| 768 | int | ||
| 769 | emacs_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 | |||
| 73 | changes." | 98 | changes." |
| 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. | ||
| 187 | NAME must be a symbol. Delete the temporary directory after BODY | ||
| 188 | exits normally or non-locally. NAME will be bound to the | ||
| 189 | directory name (not the directory file name) of the temporary | ||
| 190 | directory." | ||
| 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. |
| 201 | Run Emacs as a subprocess, load the test module `mod-test-file', | 216 | Run Emacs as a subprocess, load the test module `mod-test-file', |
| @@ -204,7 +219,7 @@ assertion message that matches PATTERN. PATTERN is evaluated and | |||
| 204 | must evaluate to a regular expression string." | 219 | must 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." |
| 235 | aren’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. | ||
| 266 | This differs from `module--test-assertions-load-non-live-object' | ||
| 267 | in that it stows away a global reference. The module assertions | ||
| 268 | should 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 |
| 249 | during garbage collection." | 285 | during 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 | ||
| 297 | local 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 | |||
| 323 | Return 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. | ||
| 338 | Interactively, 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. | ||
| 422 | See 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. | ||
| 213 | Assume that the current buffer contains subprocess output for the | ||
| 214 | failing process. START-TIME and END-TIME are time values between | ||
| 215 | which 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 doesn’t accept weird argument lists. | 40 | "Check that Emacs doesn't accept weird argument lists. |
| 39 | Bug#24912 and Bug#24913." | 41 | Bug#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. | ||
| 62 | Bug#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. | ||
| 138 | Check that byte-compiled objects being executed by exec-byte-code | ||
| 139 | are 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. | ||
| 168 | Don't handle destructive splicing in backquote expressions (like | ||
| 169 | in Common Lisp). Instead, make sure substitution in backquote | ||
| 170 | expressions 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. | ||
| 36 | Create a test directory and a buffer whose `buffer-file-name' and | ||
| 37 | `buffer-file-truename' are a file within it, then call BODY. | ||
| 38 | Finally, 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. | ||
| 57 | Equivalent logic in Emacs proper is implemented in C and | ||
| 58 | unavailable 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. | ||
| 65 | Cause Emacs to report errors for various file locking operations | ||
| 66 | on FILE-NAME going forward. Create a file that is incompatible | ||
| 67 | with Emacs' file locking protocol, but uses the same name as | ||
| 68 | FILE-NAME's lock file. A directory file is used, which is | ||
| 69 | portable 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. | ||
| 74 | See `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. | ||
| 79 | Exception: on systems without lock file support, aborts the | ||
| 80 | current test if the current file is locked (which should never | ||
| 81 | the 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’ doesn’t 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 | ||
| 198 | https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt. | ||
| 199 | Test 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. | ||
| 178 | https://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\", |
| 28 | commit 86c19714b097aa477d339ed99ffb5136c755a046." | 211 | commit 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" "" " | ||
| 324 | e foo | ||
| 325 | f foo (currently shadowed by `bar') | ||
| 326 | g .. 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" "" " | ||
| 350 | 0 .. 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 |
| 136 | literals (Bug#20852)." | 135 | literals (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. | ||
| 72 | CH is propertized with a `charset' value according to | ||
| 73 | ODD-CHARSET: if nil, then use the one returned by `char-charset', | ||
| 74 | otherwise, 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) | 43 | Call WAIT-FUNCTION, possibly multiple times, to wait for the |
| 32 | (let ((proc (start-process "test" nil "bash" "-c" "exit 20")) | 44 | process 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. | ||
| 275 | This calls `make-process', passing ARGS to adjust how the process | ||
| 276 | is created. TTYS should be a list of 3 boolean values, | ||
| 277 | indicating whether the subprocess's stdin, stdout, and stderr | ||
| 278 | should 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’ | ||
| 346 | works 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’ | ||
| 368 | works 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 | ||
| 379 | file 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. | ||
| 398 | See 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. | ||
| 535 | Afterwards, kill all buffers in the list VAR. BODY should add | ||
| 536 | some 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. | ||
| 546 | Afterwards, delete all processes in the list VAR. BODY should | ||
| 547 | add 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. | ||
| 557 | Attempt to set the resource limit for the number of open files | ||
| 558 | temporarily 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. | ||
| 596 | Try to generate pipe processes until we are close to the | ||
| 597 | FD_SETSIZE limit. Within BODY, only a small number of file | ||
| 598 | descriptors should still be available. Furthermore, raise the | ||
| 599 | maximum number of open files in the Emacs process above | ||
| 600 | FD_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 | ||
| 650 | FD_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 | ||
| 695 | FD_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 | ||
| 722 | FD_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 | ||
| 764 | FD_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. | ||
| 829 | Return 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 | ||
| 867 | have 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. | ||
| 930 | COMMAND 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. | ||
| 944 | Return 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. | ||
| 954 | Return 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. | ||
| 968 | Return nil if that can't be determined. Return `:not-needed' if | ||
| 969 | Emacs 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. | ||
| 978 | Return 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 | ||
| 32 | Test that a regex of the form \"[[:cc:]]*x\" where CC is | 32 | Test that a regex of the form \"[[:cc:]]*x\" where CC is |
| 33 | a character class which matches a multibyte character X, matches | 33 | a character class which matches a multibyte character X, matches |
| 34 | string \"x\". | 34 | string \"x\". |
| 35 | 35 | ||
| 36 | For example, ‘[[:word:]]*\u2620’ regex (note: \u2620 is a word | 36 | For example, \"[[:word:]]*\u2620\" regex (note: \u2620 is a word |
| 37 | character) must match a string \"\u2420\"." | 37 | character) 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 |
| 160 | what failed, if anything; valid values are 'search-failed, | 160 | what 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 |
| 162 | group with their expected values. This is done with either | 162 | group with their expected values. This is done with either |
| 163 | BOUNDS-REF or SUBSTRING-REF; one of those should be non-nil. | 163 | BOUNDS-REF or SUBSTRING-REF; one of those should be non-nil. |
| 164 | BOUNDS-REF is a sequence \[start-ref0 end-ref0 start-ref1 | 164 | BOUNDS-REF is a sequence [start-ref0 end-ref0 start-ref1 |
| 165 | end-ref1 ....] while SUBSTRING-REF is the expected substring | 165 | end-ref1 ....] while SUBSTRING-REF is the expected substring |
| 166 | obtained by indexing the input string by start/end-ref. | 166 | obtained by indexing the input string by start/end-ref. |
| 167 | 167 | ||
| 168 | If the search was supposed to fail then start-ref0/substring-ref0 | 168 | If the search was supposed to fail then start-ref0/substring-ref0 |
| 169 | is 'search-failed. If the search wasn't even supposed to compile | 169 | is `search-failed'. If the search wasn't even supposed to compile |
| 170 | successfully, then start-ref0/substring-ref0 is | 170 | successfully, 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, |
| 172 | this can be set to t. | 172 | this can be set to t. |
| 173 | 173 | ||
| 174 | This function returns a string that describes the failure, or nil | 174 | This 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 | ||
| 261 | If the search was supposed to fail then start-ref0 is | 261 | If 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 |
| 263 | successfully, then start-ref0 is 'compilation-failed. | 263 | successfully, then start-ref0 is `compilation-failed'. |
| 264 | 264 | ||
| 265 | This function returns a string that describes the failure, or nil | 265 | This function returns a string that describes the failure, or nil |
| 266 | on success" | 266 | on 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 |
| 329 | regex-tests-BOOST.c in glibc: \\t, \\n, \\r are interpreted; | 329 | regex-tests-BOOST.c in glibc: \\t, \\n, \\r are interpreted; |
| 330 | \\\\, \\^, \{, \\|, \} are unescaped for the string (not | 330 | \\\\, \\^, \\{, \\|, \\} are unescaped for the string (not |
| 331 | pattern)" | 331 | pattern)" |
| 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. |
| 400 | are false-positive test failures that represent known/benign | 400 | These are false-positive test failures that represent |
| 401 | differences in behavior.") | 401 | known/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. |
| 484 | are false-positive test failures that represent known/benign | 484 | These are false-positive test failures that represent |
| 485 | differences in behavior.") | 485 | known/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. |
| 566 | are false-positive test failures that represent known/benign | 566 | These are false-positive test failures that represent |
| 567 | differences in behavior.") | 567 | known/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. |
| 625 | are false-positive test failures that represent known/benign | 625 | These are false-positive test failures that represent |
| 626 | differences in behavior.") | 626 | known/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." | |||
| 677 | This evaluates the TESTS test cases from glibc." | 677 | This 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 |
| 99 | a* b 0 0 | 99 | a* b 0 0 |
| @@ -275,7 +275,7 @@ a(b*)c\1d abbcbbbd -1 -1 | |||
| 275 | ^(.)\1 abc -1 -1 | 275 | ^(.)\1 abc -1 -1 |
| 276 | a([bc])\1d abcdabbd 4 8 5 6 | 276 | a([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. |
| 279 | a(([bc])\2)*d abbccd 0 6 3 5 3 4 | 279 | a(([bc])\2)*d abbccd 0 6 3 5 3 4 |
| 280 | 280 | ||
| 281 | a(([bc])\2)*d abbcbd -1 -1 | 281 | a(([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 ('fo', 4)") | ||
| 109 | (should | ||
| 110 | (equal (sqlite-select db "select * from test2" nil 'full) | ||
| 111 | '(("col1" "col2") ("fóo" 3) ("fóo" 3) ("fo" 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 */ | ||
| 6 | 1/* comment */1 | ||
| 7 | 2/**/2 | ||
| 8 | 3// comment | ||
| 9 | 3 | ||
| 10 | 4// | ||
| 11 | 4 | ||
| 12 | 5/*/5 | ||
| 13 | 6*/6 | ||
| 14 | 7/* \*/7 | ||
| 15 | 8*/8 | ||
| 16 | 9/* \\*/9 | ||
| 17 | 10*/10 | ||
| 18 | 11// \ | ||
| 19 | 12 | ||
| 20 | 11 | ||
| 21 | 13// \\ | ||
| 22 | 14 | ||
| 23 | 13 | ||
| 24 | 15/* /*/15 | ||
| 25 | |||
| 26 | /* C Comments within lists */ | ||
| 27 | 59}59 | ||
| 28 | 50{ /*70 comment */71 }50 | ||
| 29 | 51{ /**/ }51 | ||
| 30 | 52{ //72 comment | ||
| 31 | 73}52 | ||
| 32 | 53{ // | ||
| 33 | }53 | ||
| 34 | 54{ //74 \ | ||
| 35 | }54 | ||
| 36 | 55{/* */}55 | ||
| 37 | 56{ /*76 \*/ }56 | ||
| 38 | 57*/77 | ||
| 39 | 58}58 | ||
| 40 | 60{ /*78 \\*/79}60 | ||
| 41 | |||
| 42 | |||
| 43 | /* Straight Pascal comments (not nested) */ | ||
| 44 | 20}20 | ||
| 45 | 21{ Comment }21 | ||
| 46 | 22{}22 | ||
| 47 | 23{ | ||
| 48 | }23 | ||
| 49 | 24{ | ||
| 50 | 25{25 | ||
| 51 | }24 | ||
| 52 | 26{ \}26 | ||
| 53 | |||
| 54 | |||
| 55 | /* Straight Lisp comments (not nested) */ | ||
| 56 | 30 | ||
| 57 | 30 | ||
| 58 | 31; Comment | ||
| 59 | 31 | ||
| 60 | 32;;;;;;;;; | ||
| 61 | 32 | ||
| 62 | 33; \ | ||
| 63 | 33 | ||
| 64 | |||
| 65 | /* Lisp comments within lists */ | ||
| 66 | 40)40 | ||
| 67 | 41(;90 comment | ||
| 68 | 91)41 | ||
| 69 | 42(;92\ | ||
| 70 | 93)42 | ||
| 71 | 43( ;94 | ||
| 72 | 95 | ||
| 73 | |||
| 74 | /* Nested Lisp comments */ | ||
| 75 | 100|#100 | ||
| 76 | 101#|# | ||
| 77 | 102#||#102 | ||
| 78 | 103#| Comment |#103 | ||
| 79 | 104#| Comment | ||
| 80 | |#104 | ||
| 81 | 105#|#|#105 | ||
| 82 | 106#| #| Comment |# |#106 | ||
| 83 | 107#|#|#|#|#|#|#|#|#| Comment |#|#|#|#|#|#|#|#|#107 | ||
| 84 | |||
| 85 | /* Mixed Lisp comments */ | ||
| 86 | 110; #| | ||
| 87 | 110 | ||
| 88 | 111#| ; |#111 | ||
| 89 | |||
| 90 | Local Variables: | ||
| 91 | mode: fundamental | ||
| 92 | eval: (set-syntax-table (make-syntax-table)) | ||
| 93 | End: | ||
| 94 | 999 \ 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. |
| 60 | Specifically, where the first character of the comment marker is | 72 | Specifically, 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. | ||
| 110 | N is a decimal number which appears in the data file, usually | ||
| 111 | twice, as \"labels\". It can also be a negative number or zero. | ||
| 112 | FORW is t when we're using the label at BOL, nil for the one at EOL. | ||
| 113 | |||
| 114 | If the label N doesn't exist in the current buffer, an exception | ||
| 115 | is thrown. | ||
| 116 | |||
| 117 | When FORW is t and N positive, we return the position after the | ||
| 118 | first occurrence of label N at BOL in the data file. With FORW | ||
| 119 | nil, we return the position before the last occurrence of the | ||
| 120 | label at EOL in the data file. | ||
| 121 | |||
| 122 | When N is negative, we return instead the position of the end of | ||
| 123 | line 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. | ||
| 145 | N is a positive decimal number which should appear in the buffer | ||
| 146 | exactly once. The label need not be at the beginning or end of a | ||
| 147 | line. | ||
| 148 | |||
| 149 | The return value is the position just before the label. | ||
| 150 | |||
| 151 | If the label N doesn't exist in the current buffer, an exception | ||
| 152 | is 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). | ||
| 165 | The test uses a fixed name data file, which it visits. It calls | ||
| 166 | entry and exit functions to set up and tear down syntax entries | ||
| 167 | for comment characters. The test is given a name based on the | ||
| 168 | global variable `syntax-comments-section', the direction of | ||
| 169 | movement and the value of START. | ||
| 170 | |||
| 171 | -TYPE- (unquoted) is a symbol from whose name the entry and exit | ||
| 172 | function names are derived by appending \"-in\" and \"-out\". | ||
| 173 | |||
| 174 | -DIR- (unquoted) is `forward' or `backward', the direction | ||
| 175 | `forward-comment' is attempted. | ||
| 176 | |||
| 177 | RES, t or nil, is the expected result from `forward-comment'. | ||
| 178 | |||
| 179 | START and STOP are decimal numbers corresponding to labels in the | ||
| 180 | data file marking the start and expected stop positions. See | ||
| 181 | `syntax-comments-point' for a precise specification. If STOP is | ||
| 182 | missing 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). | ||
| 207 | This is to test the interface between scan-lists and the internal | ||
| 208 | comment routines in syntax.c. | ||
| 209 | |||
| 210 | The test uses a fixed name data file, which it visits. It calls | ||
| 211 | entry and exit functions to set up and tear down syntax entries | ||
| 212 | for comment and paren characters. The test is given a name based | ||
| 213 | on the global variable `syntax-comments-section', the direction | ||
| 214 | of movement and the value of -START-. | ||
| 215 | |||
| 216 | -TYPE- (unquoted) is a symbol from whose name the entry and exit | ||
| 217 | function names are derived by appending \"-in\" and \"-out\". | ||
| 218 | |||
| 219 | -DIR- (unquoted) is `forward' or `backward', the direction | ||
| 220 | `scan-lists' is attempted. | ||
| 221 | |||
| 222 | RES is t if `scan-lists' is expected to return, nil if it is | ||
| 223 | expected to raise a `scan-error' exception. | ||
| 224 | |||
| 225 | -START- and STOP are decimal numbers corresponding to labels in the | ||
| 226 | data file marking the start and expected stop positions. See | ||
| 227 | `syntax-comments-point' for a precise specification. If STOP is | ||
| 228 | missing 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. | ||
| 260 | This is to test the interface between `parse-partial-sexp' and | ||
| 261 | the internal comment routines in syntax.c. | ||
| 262 | |||
| 263 | The test uses a fixed name data file, which it visits. It calls | ||
| 264 | entry and exit functions to set up and tear down syntax entries | ||
| 265 | for comment and paren characters. The test is given a name based | ||
| 266 | on the global variable `syntax-comments-section', and the value | ||
| 267 | of -START-. | ||
| 268 | |||
| 269 | The generated test calls `parse-partial-sexp' three times, the | ||
| 270 | first two with COMMENTSTOP set to `syntax-table' so as to stop | ||
| 271 | after the start and end of the comment. The third call is | ||
| 272 | expected to stop at the brace/paren matching the one where the | ||
| 273 | test started. | ||
| 274 | |||
| 275 | -TYPE- (unquoted) is a symbol from whose name the entry and exit | ||
| 276 | function names are derived by appending \"-in\" and \"-out\". | ||
| 277 | |||
| 278 | -START- and -STOP- are decimal numbers corresponding to labels in | ||
| 279 | the data file marking the start and expected stop positions. See | ||
| 280 | `syntax-comments-point' for a precise specification. If -STOP- | ||
| 281 | is missing or nil, the value of -START- is assumed for it. | ||
| 282 | |||
| 283 | OPEN and CLOSE are decimal numbers corresponding to labels in the | ||
| 284 | data file marking just after the comment opener and closer where | ||
| 285 | the `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, | ||
| 158 | and any padding must happen on the right. All other numbers have | ||
| 159 | a 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 "\ | ||
| 105 | int 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 | |||
| 125 | int 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 | |||
| 145 | int 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 | ||