Mercurial > hg > xemacs-beta
annotate tests/automated/test-harness.el @ 4792:95b04754ea8c
Make #'equalp more compatible with CL; add a compiler macro, test & doc it.
lisp/ChangeLog addition:
2009-11-08 Aidan Kehoe <kehoea@parhasard.net>
* cl-extra.el (cl-string-vector-equalp)
(cl-bit-vector-vector-equalp, cl-vector-array-equalp)
(cl-hash-table-contents-equalp): New functions, to implement
equalp treating arrays with identical contents as equivalent, as
specified by Common Lisp.
(equalp): Revise this function to implement array equivalence,
and the hash-table equalp behaviour specified by CL.
* cl-macs.el (equalp): Add a compiler macro for this function,
used when one of the arguments is constant, and as such, its type
is known at compile time.
man/ChangeLog addition:
2009-11-08 Aidan Kehoe <kehoea@parhasard.net>
* lispref/objects.texi (Equality Predicates):
Document #'equalp here, as well as #'equal and #'eq.
tests/ChangeLog addition:
2009-12-31 Aidan Kehoe <kehoea@parhasard.net>
* automated/lisp-tests.el:
Test much of the functionality of equalp; add a pointer to Paul
Dietz' ANSI test suite for this function, converted to Emacs
Lisp. Not including the tests themselves in XEmacs because who
owns the copyright on the files is unclear and the GCL people
didn't respond to my queries.
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Thu, 31 Dec 2009 15:09:41 +0000 |
parents | 294a86d29f99 |
children | a3c673c0720b |
rev | line source |
---|---|
428 | 1 ;; test-harness.el --- Run Emacs Lisp test suites. |
2 | |
1751 | 3 ;;; Copyright (C) 1998, 2002, 2003 Free Software Foundation, Inc. |
826 | 4 ;;; Copyright (C) 2002 Ben Wing. |
428 | 5 |
6 ;; Author: Martin Buchholz | |
1761 | 7 ;; Maintainer: Stephen J. Turnbull <stephen@xemacs.org> |
428 | 8 ;; Keywords: testing |
9 | |
10 ;; This file is part of XEmacs. | |
11 | |
12 ;; XEmacs is free software; you can redistribute it and/or modify it | |
13 ;; under the terms of the GNU General Public License as published by | |
14 ;; the Free Software Foundation; either version 2, or (at your option) | |
15 ;; any later version. | |
16 | |
17 ;; XEmacs is distributed in the hope that it will be useful, but | |
18 ;; WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
20 ;; General Public License for more details. | |
21 | |
22 ;; You should have received a copy of the GNU General Public License | |
23 ;; along with XEmacs; see the file COPYING. If not, write to the | |
24 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
25 ;; Boston, MA 02111-1307, USA. | |
26 | |
27 ;;; Synched up with: Not in FSF. | |
28 | |
29 ;;; Commentary: | |
30 | |
31 ;;; A test suite harness for testing XEmacs. | |
32 ;;; The actual tests are in other files in this directory. | |
33 ;;; Basically you just create files of emacs-lisp, and use the | |
1095 | 34 ;;; Assert, Check-Error, Check-Message, and Check-Error-Message functions |
35 ;;; to create tests. See `test-harness-from-buffer' below. | |
36 ;;; Don't suppress tests just because they're due to known bugs not yet | |
1413 | 37 ;;; fixed -- use the Known-Bug-Expect-Failure and |
38 ;;; Implementation-Incomplete-Expect-Failure wrapper macros to mark them. | |
1095 | 39 ;;; A lot of the tests we run push limits; suppress Ebola message with the |
40 ;;; Ignore-Ebola wrapper macro. | |
3472 | 41 ;;; Some noisy code will call `message'. Output from `message' can be |
42 ;;; suppressed with the Silence-Message macro. Functions that are known to | |
43 ;;; issue messages include `write-region', `find-tag', `tag-loop-continue', | |
44 ;;; `insert', and `mark-whole-buffer'. N.B. The Silence-Message macro | |
45 ;;; currently does not suppress the newlines printed by `message'. | |
46 ;;; Definitely do not use Silence-Message with Check-Message. | |
47 ;;; In general it should probably only be used on code that prepares for a | |
48 ;;; test, not on tests. | |
1095 | 49 ;;; |
428 | 50 ;;; You run the tests using M-x test-emacs-test-file, |
51 ;;; or $(EMACS) -batch -l .../test-harness.el -f batch-test-emacs file ... | |
52 ;;; which is run for you by the `make check' target in the top-level Makefile. | |
53 | |
54 (require 'bytecomp) | |
55 | |
3471 | 56 (defvar unexpected-test-suite-failures 0 |
57 "Cumulative number of unexpected failures since test-harness was loaded. | |
58 | |
59 \"Unexpected failures\" are those caught by a generic handler established | |
60 outside of the test context. As such they involve an abort of the test | |
61 suite for the file being tested. | |
62 | |
63 They often occur during preparation of a test or recording of the results. | |
64 For example, an executable used to generate test data might not be present | |
65 on the system, or a system error might occur while reading a data file.") | |
66 | |
67 (defvar unexpected-test-suite-failure-files nil | |
68 "List of test files causing unexpected failures.") | |
69 | |
70 ;; Declared for dynamic scope; _do not_ initialize here. | |
71 (defvar unexpected-test-file-failures) | |
72 | |
1758 | 73 (defvar test-harness-test-compiled nil |
4366
7b628daa39d4
Move debugging code to usage example.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4323
diff
changeset
|
74 "Non-nil means the test code was compiled before execution. |
7b628daa39d4
Move debugging code to usage example.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4323
diff
changeset
|
75 |
7b628daa39d4
Move debugging code to usage example.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4323
diff
changeset
|
76 You probably should not make tests depend on compilation. |
7b628daa39d4
Move debugging code to usage example.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4323
diff
changeset
|
77 However, it can be useful to conditionally change messages based on whether |
7b628daa39d4
Move debugging code to usage example.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4323
diff
changeset
|
78 the code was compiled or not. For example, the case that motivated the |
7b628daa39d4
Move debugging code to usage example.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4323
diff
changeset
|
79 implementation of this variable: |
7b628daa39d4
Move debugging code to usage example.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4323
diff
changeset
|
80 |
7b628daa39d4
Move debugging code to usage example.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4323
diff
changeset
|
81 \(when test-harness-test-compiled |
7b628daa39d4
Move debugging code to usage example.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4323
diff
changeset
|
82 ;; this ha-a-ack depends on the failing compiled test coming last |
7b628daa39d4
Move debugging code to usage example.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4323
diff
changeset
|
83 \(setq test-harness-failure-tag |
7b628daa39d4
Move debugging code to usage example.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4323
diff
changeset
|
84 \"KNOWN BUG - fix reverted; after 2003-10-31 notify stephen\n\"))") |
1758 | 85 |
428 | 86 (defvar test-harness-verbose |
87 (and (not noninteractive) (> (device-baud-rate) search-slow-speed)) | |
88 "*Non-nil means print messages describing progress of emacs-tester.") | |
89 | |
1719 | 90 (defvar test-harness-file-results-alist nil |
91 "Each element is a list (FILE SUCCESSES TESTS). | |
92 The order is the reverse of the order in which tests are run. | |
93 | |
94 FILE is a string naming the test file. | |
95 SUCCESSES is a non-negative integer, the number of successes. | |
96 TESTS is a non-negative integer, the number of tests run.") | |
97 | |
1425 | 98 (defvar test-harness-risk-infloops nil |
99 "*Non-nil to run tests that may loop infinitely in buggy implementations.") | |
100 | |
428 | 101 (defvar test-harness-current-file nil) |
102 | |
103 (defvar emacs-lisp-file-regexp (purecopy "\\.el\\'") | |
104 "*Regexp which matches Emacs Lisp source files.") | |
105 | |
1751 | 106 (defconst test-harness-file-summary-template |
107 (format "%%-%ds %%%dd of %%%dd tests successful (%%3d%%%%)." | |
108 (length "byte-compiler-tests.el:") ; use the longest file name | |
109 5 | |
110 5) | |
111 "Format for summary lines printed after each file is run.") | |
112 | |
113 (defconst test-harness-null-summary-template | |
114 (format "%%-%ds No tests run." | |
115 (length "byte-compiler-tests.el:")) ; use the longest file name | |
116 "Format for \"No tests\" lines printed after a file is run.") | |
117 | |
428 | 118 ;;;###autoload |
119 (defun test-emacs-test-file (filename) | |
120 "Test a file of Lisp code named FILENAME. | |
121 The output file's name is made by appending `c' to the end of FILENAME." | |
122 (interactive | |
123 (let ((file buffer-file-name) | |
124 (file-name nil) | |
125 (file-dir nil)) | |
126 (and file | |
127 (eq (cdr (assq 'major-mode (buffer-local-variables))) | |
128 'emacs-lisp-mode) | |
129 (setq file-name (file-name-nondirectory file) | |
130 file-dir (file-name-directory file))) | |
131 (list (read-file-name "Test file: " file-dir nil nil file-name)))) | |
132 ;; Expand now so we get the current buffer's defaults | |
133 (setq filename (expand-file-name filename)) | |
134 | |
135 ;; If we're testing a file that's in a buffer and is modified, offer | |
136 ;; to save it first. | |
137 (or noninteractive | |
138 (let ((b (get-file-buffer (expand-file-name filename)))) | |
139 (if (and b (buffer-modified-p b) | |
140 (y-or-n-p (format "save buffer %s first? " (buffer-name b)))) | |
141 (save-excursion (set-buffer b) (save-buffer))))) | |
142 | |
143 (if (or noninteractive test-harness-verbose) | |
144 (message "Testing %s..." filename)) | |
145 (let ((test-harness-current-file filename) | |
146 input-buffer) | |
147 (save-excursion | |
148 (setq input-buffer (get-buffer-create " *Test Input*")) | |
149 (set-buffer input-buffer) | |
150 (erase-buffer) | |
151 (insert-file-contents filename) | |
152 ;; Run hooks including the uncompression hook. | |
153 ;; If they change the file name, then change it for the output also. | |
154 (let ((buffer-file-name filename) | |
155 (default-major-mode 'emacs-lisp-mode) | |
156 (enable-local-eval nil)) | |
157 (normal-mode) | |
158 (setq filename buffer-file-name))) | |
159 (test-harness-from-buffer input-buffer filename) | |
160 (kill-buffer input-buffer) | |
161 )) | |
162 | |
163 (defun test-harness-read-from-buffer (buffer) | |
164 "Read forms from BUFFER, and turn it into a lambda test form." | |
165 (let ((body nil)) | |
166 (goto-char (point-min) buffer) | |
167 (condition-case error-info | |
168 (while t | |
169 (setq body (cons (read buffer) body))) | |
170 (end-of-file nil) | |
171 (error | |
3471 | 172 (incf unexpected-test-file-failures) |
1751 | 173 (princ (format "Unexpected error %S reading forms from buffer\n" |
174 error-info)))) | |
428 | 175 `(lambda () |
176 (defvar passes) | |
177 (defvar assertion-failures) | |
178 (defvar no-error-failures) | |
179 (defvar wrong-error-failures) | |
180 (defvar missing-message-failures) | |
181 (defvar other-failures) | |
182 | |
183 (defvar trick-optimizer) | |
184 | |
185 ,@(nreverse body)))) | |
186 | |
187 (defun test-harness-from-buffer (inbuffer filename) | |
188 "Run tests in buffer INBUFFER, visiting FILENAME." | |
189 (defvar trick-optimizer) | |
190 (let ((passes 0) | |
191 (assertion-failures 0) | |
192 (no-error-failures 0) | |
193 (wrong-error-failures 0) | |
194 (missing-message-failures 0) | |
195 (other-failures 0) | |
3471 | 196 (unexpected-test-file-failures 0) |
428 | 197 |
973 | 198 ;; #### perhaps this should be a defvar, and output at the very end |
199 ;; OTOH, this way AC types can use a null EMACSPACKAGEPATH to find | |
200 ;; what stuff is needed, and ways to avoid using them | |
201 (skipped-test-reasons (make-hash-table :test 'equal)) | |
202 | |
428 | 203 (trick-optimizer nil) |
826 | 204 (debug-on-error t) |
205 (pass-stream nil)) | |
428 | 206 (with-output-to-temp-buffer "*Test-Log*" |
826 | 207 (princ (format "Testing %s...\n\n" filename)) |
1095 | 208 |
1413 | 209 (defconst test-harness-failure-tag "FAIL") |
210 (defconst test-harness-success-tag "PASS") | |
1095 | 211 |
212 (defmacro Known-Bug-Expect-Failure (&rest body) | |
1413 | 213 `(let ((test-harness-failure-tag "KNOWN BUG") |
214 (test-harness-success-tag "PASS (FAILURE EXPECTED)")) | |
215 ,@body)) | |
4323
94509abd0ef0
Commit a forgotten chunk of 4d0f773d5e21.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4199
diff
changeset
|
216 |
94509abd0ef0
Commit a forgotten chunk of 4d0f773d5e21.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4199
diff
changeset
|
217 (defmacro Known-Bug-Expect-Error (expected-error &rest body) |
94509abd0ef0
Commit a forgotten chunk of 4d0f773d5e21.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4199
diff
changeset
|
218 (let ((quoted-body (if (= 1 (length body)) |
94509abd0ef0
Commit a forgotten chunk of 4d0f773d5e21.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4199
diff
changeset
|
219 `(quote ,(car body)) `(quote (progn ,@body))))) |
94509abd0ef0
Commit a forgotten chunk of 4d0f773d5e21.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4199
diff
changeset
|
220 `(let ((test-harness-failure-tag "KNOWN BUG") |
94509abd0ef0
Commit a forgotten chunk of 4d0f773d5e21.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4199
diff
changeset
|
221 (test-harness-success-tag "PASS (FAILURE EXPECTED)")) |
94509abd0ef0
Commit a forgotten chunk of 4d0f773d5e21.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4199
diff
changeset
|
222 (condition-case error-info |
94509abd0ef0
Commit a forgotten chunk of 4d0f773d5e21.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4199
diff
changeset
|
223 (progn |
94509abd0ef0
Commit a forgotten chunk of 4d0f773d5e21.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4199
diff
changeset
|
224 (setq trick-optimizer (progn ,@body)) |
94509abd0ef0
Commit a forgotten chunk of 4d0f773d5e21.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4199
diff
changeset
|
225 (Print-Pass |
94509abd0ef0
Commit a forgotten chunk of 4d0f773d5e21.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4199
diff
changeset
|
226 "%S executed successfully, but expected error %S" |
94509abd0ef0
Commit a forgotten chunk of 4d0f773d5e21.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4199
diff
changeset
|
227 ,quoted-body |
94509abd0ef0
Commit a forgotten chunk of 4d0f773d5e21.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4199
diff
changeset
|
228 ',expected-error) |
94509abd0ef0
Commit a forgotten chunk of 4d0f773d5e21.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4199
diff
changeset
|
229 (incf passes)) |
94509abd0ef0
Commit a forgotten chunk of 4d0f773d5e21.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4199
diff
changeset
|
230 (,expected-error |
94509abd0ef0
Commit a forgotten chunk of 4d0f773d5e21.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4199
diff
changeset
|
231 (Print-Failure "%S ==> error %S, as expected" |
94509abd0ef0
Commit a forgotten chunk of 4d0f773d5e21.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4199
diff
changeset
|
232 ,quoted-body ',expected-error) |
94509abd0ef0
Commit a forgotten chunk of 4d0f773d5e21.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4199
diff
changeset
|
233 (incf no-error-failures)) |
94509abd0ef0
Commit a forgotten chunk of 4d0f773d5e21.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4199
diff
changeset
|
234 (error |
94509abd0ef0
Commit a forgotten chunk of 4d0f773d5e21.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4199
diff
changeset
|
235 (Print-Failure "%S ==> expected error %S, got error %S instead" |
94509abd0ef0
Commit a forgotten chunk of 4d0f773d5e21.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4199
diff
changeset
|
236 ,quoted-body ',expected-error error-info) |
94509abd0ef0
Commit a forgotten chunk of 4d0f773d5e21.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4199
diff
changeset
|
237 (incf wrong-error-failures)))))) |
94509abd0ef0
Commit a forgotten chunk of 4d0f773d5e21.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4199
diff
changeset
|
238 |
1413 | 239 (defmacro Implementation-Incomplete-Expect-Failure (&rest body) |
240 `(let ((test-harness-failure-tag "IMPLEMENTATION INCOMPLETE") | |
241 (test-harness-success-tag "PASS (FAILURE EXPECTED)")) | |
242 ,@body)) | |
826 | 243 |
244 (defun Print-Failure (fmt &rest args) | |
1413 | 245 (setq fmt (format "%s: %s" test-harness-failure-tag fmt)) |
826 | 246 (if (noninteractive) (apply #'message fmt args)) |
247 (princ (concat (apply #'format fmt args) "\n"))) | |
248 | |
249 (defun Print-Pass (fmt &rest args) | |
1413 | 250 (setq fmt (format "%s: %s" test-harness-success-tag fmt)) |
826 | 251 (and test-harness-verbose |
252 (princ (concat (apply #'format fmt args) "\n")))) | |
253 | |
973 | 254 (defun Print-Skip (test reason &optional fmt &rest args) |
1095 | 255 (setq fmt (concat "SKIP: %S BECAUSE %S" fmt)) |
973 | 256 (princ (concat (apply #'format fmt test reason args) "\n"))) |
257 | |
1095 | 258 (defmacro Skip-Test-Unless (condition reason description &rest body) |
259 "Unless CONDITION is satisfied, skip test BODY. | |
260 REASON is a description of the condition failure, and must be unique (it | |
261 is used as a hash key). DESCRIPTION describes the tests that were skipped. | |
262 BODY is a sequence of expressions and may contain several tests." | |
263 `(if (not ,condition) | |
264 (let ((count (gethash ,reason skipped-test-reasons))) | |
265 (puthash ,reason (if (null count) 1 (1+ count)) | |
266 skipped-test-reasons) | |
267 (Print-Skip ,description ,reason)) | |
268 ,@body)) | |
428 | 269 |
4747
294a86d29f99
Eliminate C asserts from c-tests.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4415
diff
changeset
|
270 (defmacro Assert (assertion &optional failing-case description) |
294a86d29f99
Eliminate C asserts from c-tests.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4415
diff
changeset
|
271 "Test passes if ASSERTION is true. |
294a86d29f99
Eliminate C asserts from c-tests.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4415
diff
changeset
|
272 Optional FAILING-CASE describes the particular failure. |
294a86d29f99
Eliminate C asserts from c-tests.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4415
diff
changeset
|
273 Optional DESCRIPTION describes the assertion. |
294a86d29f99
Eliminate C asserts from c-tests.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4415
diff
changeset
|
274 FAILING-CASE and DESCRIPTION are useful when Assert is used in a loop." |
428 | 275 `(condition-case error-info |
2056 | 276 (progn |
277 (assert ,assertion) | |
4747
294a86d29f99
Eliminate C asserts from c-tests.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4415
diff
changeset
|
278 (Print-Pass "%S" (quote ,(or description assertion))) |
2056 | 279 (incf passes)) |
280 (cl-assertion-failed | |
281 (Print-Failure (if ,failing-case | |
282 "Assertion failed: %S; failing case = %S" | |
283 "Assertion failed: %S") | |
4747
294a86d29f99
Eliminate C asserts from c-tests.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4415
diff
changeset
|
284 (quote ,(or description assertion)) ,failing-case) |
2056 | 285 (incf assertion-failures)) |
286 (t (Print-Failure (if ,failing-case | |
287 "%S ==> error: %S; failing case = %S" | |
288 "%S ==> error: %S") | |
4747
294a86d29f99
Eliminate C asserts from c-tests.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4415
diff
changeset
|
289 (quote ,(or description assertion)) |
294a86d29f99
Eliminate C asserts from c-tests.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4415
diff
changeset
|
290 error-info ,failing-case) |
2056 | 291 (incf other-failures) |
292 ))) | |
293 | |
428 | 294 |
295 (defmacro Check-Error (expected-error &rest body) | |
296 (let ((quoted-body (if (= 1 (length body)) | |
297 `(quote ,(car body)) `(quote (progn ,@body))))) | |
298 `(condition-case error-info | |
299 (progn | |
300 (setq trick-optimizer (progn ,@body)) | |
826 | 301 (Print-Failure "%S executed successfully, but expected error %S" |
428 | 302 ,quoted-body |
826 | 303 ',expected-error) |
428 | 304 (incf no-error-failures)) |
305 (,expected-error | |
826 | 306 (Print-Pass "%S ==> error %S, as expected" |
307 ,quoted-body ',expected-error) | |
428 | 308 (incf passes)) |
309 (error | |
826 | 310 (Print-Failure "%S ==> expected error %S, got error %S instead" |
311 ,quoted-body ',expected-error error-info) | |
428 | 312 (incf wrong-error-failures))))) |
313 | |
826 | 314 (defmacro Check-Error-Message (expected-error expected-error-regexp |
315 &rest body) | |
428 | 316 (let ((quoted-body (if (= 1 (length body)) |
317 `(quote ,(car body)) `(quote (progn ,@body))))) | |
318 `(condition-case error-info | |
319 (progn | |
320 (setq trick-optimizer (progn ,@body)) | |
826 | 321 (Print-Failure "%S executed successfully, but expected error %S" |
322 ,quoted-body ',expected-error) | |
428 | 323 (incf no-error-failures)) |
324 (,expected-error | |
4199 | 325 ;; #### Damn, this binding doesn't capture frobs, eg, for |
326 ;; invalid_argument() ... you only get the REASON. And for | |
327 ;; wrong_type_argument(), there's no reason only FROBs. | |
328 ;; If this gets fixed, fix tests in regexp-tests.el. | |
428 | 329 (let ((error-message (second error-info))) |
330 (if (string-match ,expected-error-regexp error-message) | |
331 (progn | |
826 | 332 (Print-Pass "%S ==> error %S %S, as expected" |
333 ,quoted-body error-message ',expected-error) | |
428 | 334 (incf passes)) |
826 | 335 (Print-Failure "%S ==> got error %S as expected, but error message %S did not match regexp %S" |
336 ,quoted-body ',expected-error error-message ,expected-error-regexp) | |
428 | 337 (incf wrong-error-failures)))) |
338 (error | |
826 | 339 (Print-Failure "%S ==> expected error %S, got error %S instead" |
340 ,quoted-body ',expected-error error-info) | |
428 | 341 (incf wrong-error-failures))))) |
342 | |
3472 | 343 ;; Do not use this with Silence-Message. |
428 | 344 (defmacro Check-Message (expected-message-regexp &rest body) |
1095 | 345 (Skip-Test-Unless (fboundp 'defadvice) |
346 "can't defadvice" | |
347 expected-message-regexp | |
973 | 348 (let ((quoted-body (if (= 1 (length body)) |
349 `(quote ,(car body)) | |
350 `(quote (progn ,@body))))) | |
351 `(let ((messages "")) | |
352 (defadvice message (around collect activate) | |
353 (defvar messages) | |
354 (let ((msg-string (apply 'format (ad-get-args 0)))) | |
355 (setq messages (concat messages msg-string)) | |
356 msg-string)) | |
357 (condition-case error-info | |
358 (progn | |
359 (setq trick-optimizer (progn ,@body)) | |
360 (if (string-match ,expected-message-regexp messages) | |
361 (progn | |
362 (Print-Pass "%S ==> value %S, message %S, matching %S, as expected" | |
363 ,quoted-body trick-optimizer messages ',expected-message-regexp) | |
364 (incf passes)) | |
365 (Print-Failure "%S ==> value %S, message %S, NOT matching expected %S" | |
366 ,quoted-body trick-optimizer messages | |
367 ',expected-message-regexp) | |
368 (incf missing-message-failures))) | |
369 (error | |
370 (Print-Failure "%S ==> unexpected error %S" | |
371 ,quoted-body error-info) | |
372 (incf other-failures))) | |
373 (ad-unadvise 'message))))) | |
428 | 374 |
3472 | 375 ;; #### Perhaps this should override `message' itself, too? |
376 (defmacro Silence-Message (&rest body) | |
4323
94509abd0ef0
Commit a forgotten chunk of 4d0f773d5e21.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4199
diff
changeset
|
377 `(flet ((append-message (&rest args) ()) |
94509abd0ef0
Commit a forgotten chunk of 4d0f773d5e21.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4199
diff
changeset
|
378 (clear-message (&rest args) ())) |
94509abd0ef0
Commit a forgotten chunk of 4d0f773d5e21.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4199
diff
changeset
|
379 ,@body)) |
3472 | 380 |
428 | 381 (defmacro Ignore-Ebola (&rest body) |
382 `(let ((debug-issue-ebola-notices -42)) ,@body)) | |
383 | |
384 (defun Int-to-Marker (pos) | |
385 (save-excursion | |
386 (set-buffer standard-output) | |
387 (save-excursion | |
388 (goto-char pos) | |
389 (point-marker)))) | |
390 | |
391 (princ "Testing Interpreted Lisp\n\n") | |
392 (condition-case error-info | |
393 (funcall (test-harness-read-from-buffer inbuffer)) | |
394 (error | |
3471 | 395 (incf unexpected-test-file-failures) |
428 | 396 (princ (format "Unexpected error %S while executing interpreted code\n" |
397 error-info)) | |
398 (message "Unexpected error %S while executing interpreted code." error-info) | |
399 (message "Test suite execution aborted." error-info) | |
400 )) | |
401 (princ "\nTesting Compiled Lisp\n\n") | |
1758 | 402 (let (code |
403 (test-harness-test-compiled t)) | |
428 | 404 (condition-case error-info |
446 | 405 (setq code |
406 ;; our lisp code is often intentionally dubious, | |
407 ;; so throw away _all_ the byte compiler warnings. | |
408 (letf (((symbol-function 'byte-compile-warn) 'ignore)) | |
409 (byte-compile (test-harness-read-from-buffer inbuffer)))) | |
428 | 410 (error |
411 (princ (format "Unexpected error %S while byte-compiling code\n" | |
412 error-info)))) | |
413 (condition-case error-info | |
414 (if code (funcall code)) | |
415 (error | |
3471 | 416 (incf unexpected-test-file-failures) |
428 | 417 (princ (format "Unexpected error %S while executing byte-compiled code\n" |
418 error-info)) | |
419 (message "Unexpected error %S while executing byte-compiled code." error-info) | |
420 (message "Test suite execution aborted." error-info) | |
421 ))) | |
826 | 422 (princ (format "\nSUMMARY for %s:\n" filename)) |
428 | 423 (princ (format "\t%5d passes\n" passes)) |
424 (princ (format "\t%5d assertion failures\n" assertion-failures)) | |
425 (princ (format "\t%5d errors that should have been generated, but weren't\n" no-error-failures)) | |
426 (princ (format "\t%5d wrong-error failures\n" wrong-error-failures)) | |
427 (princ (format "\t%5d missing-message failures\n" missing-message-failures)) | |
428 (princ (format "\t%5d other failures\n" other-failures)) | |
429 (let* ((total (+ passes | |
430 assertion-failures | |
431 no-error-failures | |
432 wrong-error-failures | |
433 missing-message-failures | |
434 other-failures)) | |
435 (basename (file-name-nondirectory filename)) | |
436 (summary-msg | |
437 (if (> total 0) | |
1751 | 438 (format test-harness-file-summary-template |
439 (concat basename ":") | |
440 passes total (/ (* 100 passes) total)) | |
441 (format test-harness-null-summary-template | |
442 (concat basename ":")))) | |
973 | 443 (reasons "")) |
444 (maphash (lambda (key value) | |
445 (setq reasons | |
446 (concat reasons | |
1095 | 447 (format "\n %d tests skipped because %s." |
973 | 448 value key)))) |
449 skipped-test-reasons) | |
450 (when (> (length reasons) 1) | |
451 (setq summary-msg (concat summary-msg reasons " | |
4415
bceb3e285ae7
case-tests.el: fix it on non-DEBUG_XEMACS; save standard-case-table, use it
Aidan Kehoe <kehoea@parhasard.net>
parents:
4366
diff
changeset
|
452 It may be that XEmacs cannot find your installed packages. Set |
bceb3e285ae7
case-tests.el: fix it on non-DEBUG_XEMACS; save standard-case-table, use it
Aidan Kehoe <kehoea@parhasard.net>
parents:
4366
diff
changeset
|
453 EMACSPACKAGEPATH to the package hierarchy root or configure with |
bceb3e285ae7
case-tests.el: fix it on non-DEBUG_XEMACS; save standard-case-table, use it
Aidan Kehoe <kehoea@parhasard.net>
parents:
4366
diff
changeset
|
454 --package-path to enable the skipped tests."))) |
1719 | 455 (setq test-harness-file-results-alist |
456 (cons (list filename passes total) | |
457 test-harness-file-results-alist)) | |
428 | 458 (message "%s" summary-msg)) |
3471 | 459 (when (> unexpected-test-file-failures 0) |
460 (setq unexpected-test-suite-failure-files | |
461 (cons filename unexpected-test-suite-failure-files)) | |
462 (setq unexpected-test-suite-failures | |
463 (+ unexpected-test-suite-failures unexpected-test-file-failures)) | |
428 | 464 (message "Test suite execution failed unexpectedly.")) |
465 (fmakunbound 'Assert) | |
466 (fmakunbound 'Check-Error) | |
863 | 467 (fmakunbound 'Check-Message) |
468 (fmakunbound 'Check-Error-Message) | |
428 | 469 (fmakunbound 'Ignore-Ebola) |
470 (fmakunbound 'Int-to-Marker) | |
1719 | 471 (and noninteractive |
472 (message "%s" (buffer-substring-no-properties | |
1751 | 473 nil nil "*Test-Log*"))) |
474 ))) | |
428 | 475 |
476 (defvar test-harness-results-point-max nil) | |
477 (defmacro displaying-emacs-test-results (&rest body) | |
478 `(let ((test-harness-results-point-max test-harness-results-point-max)) | |
479 ;; Log the file name. | |
480 (test-harness-log-file) | |
481 ;; Record how much is logged now. | |
482 ;; We will display the log buffer if anything more is logged | |
483 ;; before the end of BODY. | |
484 (or test-harness-results-point-max | |
485 (save-excursion | |
486 (set-buffer (get-buffer-create "*Test-Log*")) | |
487 (setq test-harness-results-point-max (point-max)))) | |
488 (unwind-protect | |
489 (condition-case error-info | |
490 (progn ,@body) | |
491 (error | |
492 (test-harness-report-error error-info))) | |
493 (save-excursion | |
494 ;; If there were compilation warnings, display them. | |
495 (set-buffer "*Test-Log*") | |
496 (if (= test-harness-results-point-max (point-max)) | |
497 nil | |
498 (if temp-buffer-show-function | |
499 (let ((show-buffer (get-buffer-create "*Test-Log-Show*"))) | |
500 (save-excursion | |
501 (set-buffer show-buffer) | |
502 (setq buffer-read-only nil) | |
503 (erase-buffer)) | |
504 (copy-to-buffer show-buffer | |
505 (save-excursion | |
506 (goto-char test-harness-results-point-max) | |
507 (forward-line -1) | |
508 (point)) | |
509 (point-max)) | |
510 (funcall temp-buffer-show-function show-buffer)) | |
511 (select-window | |
512 (prog1 (selected-window) | |
513 (select-window (display-buffer (current-buffer))) | |
514 (goto-char test-harness-results-point-max) | |
515 (recenter 1))))))))) | |
516 | |
517 (defun batch-test-emacs-1 (file) | |
518 (condition-case error-info | |
519 (progn (test-emacs-test-file file) t) | |
520 (error | |
521 (princ ">>Error occurred processing ") | |
522 (princ file) | |
523 (princ ": ") | |
524 (display-error error-info nil) | |
525 (terpri) | |
526 nil))) | |
527 | |
528 (defun batch-test-emacs () | |
529 "Run `test-harness' on the files remaining on the command line. | |
530 Use this from the command line, with `-batch'; | |
531 it won't work in an interactive Emacs. | |
532 Each file is processed even if an error occurred previously. | |
533 For example, invoke \"xemacs -batch -f batch-test-emacs tests/*.el\"" | |
534 ;; command-line-args-left is what is left of the command line (from | |
535 ;; startup.el) | |
536 (defvar command-line-args-left) ;Avoid 'free variable' warning | |
537 (defvar debug-issue-ebola-notices) | |
538 (if (not noninteractive) | |
539 (error "`batch-test-emacs' is to be used only with -batch")) | |
540 (let ((error nil)) | |
541 (dolist (file command-line-args-left) | |
542 (if (file-directory-p file) | |
543 (dolist (file-in-dir (directory-files file t)) | |
544 (when (and (string-match emacs-lisp-file-regexp file-in-dir) | |
545 (not (or (auto-save-file-name-p file-in-dir) | |
546 (backup-file-name-p file-in-dir) | |
547 (equal (file-name-nondirectory file-in-dir) | |
548 "test-harness.el")))) | |
549 (or (batch-test-emacs-1 file-in-dir) | |
550 (setq error t)))) | |
551 (or (batch-test-emacs-1 file) | |
552 (setq error t)))) | |
1719 | 553 (let ((namelen 0) |
554 (succlen 0) | |
555 (testlen 0) | |
556 (results test-harness-file-results-alist)) | |
557 ;; compute maximum lengths of variable components of report | |
558 ;; probably should just use (length "byte-compiler-tests.el") | |
559 ;; and 5-place sizes -- this will also work for the file-by-file | |
560 ;; printing when Adrian's kludge gets reverted | |
561 (flet ((print-width (i) | |
562 (let ((x 10) (y 1)) | |
563 (while (>= i x) | |
564 (setq x (* 10 x) y (1+ y))) | |
565 y))) | |
566 (while results | |
567 (let* ((head (car results)) | |
568 (nn (length (file-name-nondirectory (first head)))) | |
569 (ss (print-width (second head))) | |
570 (tt (print-width (third head)))) | |
571 (when (> nn namelen) (setq namelen nn)) | |
572 (when (> ss succlen) (setq succlen ss)) | |
573 (when (> tt testlen) (setq testlen tt))) | |
574 (setq results (cdr results)))) | |
575 ;; create format and print | |
1751 | 576 (let ((results (reverse test-harness-file-results-alist))) |
1719 | 577 (while results |
578 (let* ((head (car results)) | |
1751 | 579 (basename (file-name-nondirectory (first head))) |
1719 | 580 (nsucc (second head)) |
581 (ntest (third head))) | |
1722 | 582 (if (> ntest 0) |
1751 | 583 (message test-harness-file-summary-template |
584 (concat basename ":") | |
1722 | 585 nsucc |
586 ntest | |
587 (/ (* 100 nsucc) ntest)) | |
1751 | 588 (message test-harness-null-summary-template |
589 (concat basename ":"))) | |
3471 | 590 (setq results (cdr results))))) |
591 (when (> unexpected-test-suite-failures 0) | |
592 (message "\n***** There %s %d unexpected test suite %s in %s:" | |
593 (if (= unexpected-test-suite-failures 1) "was" "were") | |
594 unexpected-test-suite-failures | |
595 (if (= unexpected-test-suite-failures 1) "failure" "failures") | |
596 (if (= (length unexpected-test-suite-failure-files) 1) | |
597 "file" | |
598 "files")) | |
599 (while unexpected-test-suite-failure-files | |
600 (let ((line (pop unexpected-test-suite-failure-files))) | |
601 (while (and (< (length line) 61) | |
602 unexpected-test-suite-failure-files) | |
603 (setq line | |
604 (concat line " " | |
605 (pop unexpected-test-suite-failure-files)))) | |
606 (message line))))) | |
1719 | 607 (message "\nDone") |
428 | 608 (kill-emacs (if error 1 0)))) |
609 | |
610 (provide 'test-harness) | |
611 | |
612 ;;; test-harness.el ends here |