Mercurial > hg > xemacs-beta
annotate tests/automated/test-harness.el @ 4605:c786c3fd0740
Listen to the byte-compiler, core Lisp.
lisp/ChangeLog addition:
2009-02-07 Aidan Kehoe <kehoea@parhasard.net>
* descr-text.el (describe-text-sexp):
pp is in packages, use cl-prettyprint instead.
* mule/mule-coding.el (make-8-bit-generate-helper):
Don't uselessly bind args-out-of-range, thank you the byte
compiler.
* mule/mule-coding.el (8-bit-fixed-query-coding-region):
Don't uselessly bind previous-fail, thank you the byte compiler.
* tty-init.el (make-device-early-tty-entry-point):
Set make-device-early-tty-entry-point-called-p, not
pre-tty-win-initted, thank you the byte compiler.
* unicode.el (unicode-query-coding-region):
Don't uselessly bind invalid-sequence-p, thank you the
byte-compiler.
| author | Aidan Kehoe <kehoea@parhasard.net> |
|---|---|
| date | Sat, 07 Feb 2009 18:31:21 +0000 |
| parents | bceb3e285ae7 |
| children | 294a86d29f99 |
| 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 |
| 2056 | 270 (defmacro Assert (assertion &optional failing-case) |
| 428 | 271 `(condition-case error-info |
| 2056 | 272 (progn |
| 273 (assert ,assertion) | |
| 274 (Print-Pass "%S" (quote ,assertion)) | |
| 275 (incf passes)) | |
| 276 (cl-assertion-failed | |
| 277 (Print-Failure (if ,failing-case | |
| 278 "Assertion failed: %S; failing case = %S" | |
| 279 "Assertion failed: %S") | |
| 280 (quote ,assertion) ,failing-case) | |
| 281 (incf assertion-failures)) | |
| 282 (t (Print-Failure (if ,failing-case | |
| 283 "%S ==> error: %S; failing case = %S" | |
| 284 "%S ==> error: %S") | |
| 285 (quote ,assertion) error-info ,failing-case) | |
| 286 (incf other-failures) | |
| 287 ))) | |
| 288 | |
| 428 | 289 |
| 290 (defmacro Check-Error (expected-error &rest body) | |
| 291 (let ((quoted-body (if (= 1 (length body)) | |
| 292 `(quote ,(car body)) `(quote (progn ,@body))))) | |
| 293 `(condition-case error-info | |
| 294 (progn | |
| 295 (setq trick-optimizer (progn ,@body)) | |
| 826 | 296 (Print-Failure "%S executed successfully, but expected error %S" |
| 428 | 297 ,quoted-body |
| 826 | 298 ',expected-error) |
| 428 | 299 (incf no-error-failures)) |
| 300 (,expected-error | |
| 826 | 301 (Print-Pass "%S ==> error %S, as expected" |
| 302 ,quoted-body ',expected-error) | |
| 428 | 303 (incf passes)) |
| 304 (error | |
| 826 | 305 (Print-Failure "%S ==> expected error %S, got error %S instead" |
| 306 ,quoted-body ',expected-error error-info) | |
| 428 | 307 (incf wrong-error-failures))))) |
| 308 | |
| 826 | 309 (defmacro Check-Error-Message (expected-error expected-error-regexp |
| 310 &rest body) | |
| 428 | 311 (let ((quoted-body (if (= 1 (length body)) |
| 312 `(quote ,(car body)) `(quote (progn ,@body))))) | |
| 313 `(condition-case error-info | |
| 314 (progn | |
| 315 (setq trick-optimizer (progn ,@body)) | |
| 826 | 316 (Print-Failure "%S executed successfully, but expected error %S" |
| 317 ,quoted-body ',expected-error) | |
| 428 | 318 (incf no-error-failures)) |
| 319 (,expected-error | |
| 4199 | 320 ;; #### Damn, this binding doesn't capture frobs, eg, for |
| 321 ;; invalid_argument() ... you only get the REASON. And for | |
| 322 ;; wrong_type_argument(), there's no reason only FROBs. | |
| 323 ;; If this gets fixed, fix tests in regexp-tests.el. | |
| 428 | 324 (let ((error-message (second error-info))) |
| 325 (if (string-match ,expected-error-regexp error-message) | |
| 326 (progn | |
| 826 | 327 (Print-Pass "%S ==> error %S %S, as expected" |
| 328 ,quoted-body error-message ',expected-error) | |
| 428 | 329 (incf passes)) |
| 826 | 330 (Print-Failure "%S ==> got error %S as expected, but error message %S did not match regexp %S" |
| 331 ,quoted-body ',expected-error error-message ,expected-error-regexp) | |
| 428 | 332 (incf wrong-error-failures)))) |
| 333 (error | |
| 826 | 334 (Print-Failure "%S ==> expected error %S, got error %S instead" |
| 335 ,quoted-body ',expected-error error-info) | |
| 428 | 336 (incf wrong-error-failures))))) |
| 337 | |
| 3472 | 338 ;; Do not use this with Silence-Message. |
| 428 | 339 (defmacro Check-Message (expected-message-regexp &rest body) |
| 1095 | 340 (Skip-Test-Unless (fboundp 'defadvice) |
| 341 "can't defadvice" | |
| 342 expected-message-regexp | |
| 973 | 343 (let ((quoted-body (if (= 1 (length body)) |
| 344 `(quote ,(car body)) | |
| 345 `(quote (progn ,@body))))) | |
| 346 `(let ((messages "")) | |
| 347 (defadvice message (around collect activate) | |
| 348 (defvar messages) | |
| 349 (let ((msg-string (apply 'format (ad-get-args 0)))) | |
| 350 (setq messages (concat messages msg-string)) | |
| 351 msg-string)) | |
| 352 (condition-case error-info | |
| 353 (progn | |
| 354 (setq trick-optimizer (progn ,@body)) | |
| 355 (if (string-match ,expected-message-regexp messages) | |
| 356 (progn | |
| 357 (Print-Pass "%S ==> value %S, message %S, matching %S, as expected" | |
| 358 ,quoted-body trick-optimizer messages ',expected-message-regexp) | |
| 359 (incf passes)) | |
| 360 (Print-Failure "%S ==> value %S, message %S, NOT matching expected %S" | |
| 361 ,quoted-body trick-optimizer messages | |
| 362 ',expected-message-regexp) | |
| 363 (incf missing-message-failures))) | |
| 364 (error | |
| 365 (Print-Failure "%S ==> unexpected error %S" | |
| 366 ,quoted-body error-info) | |
| 367 (incf other-failures))) | |
| 368 (ad-unadvise 'message))))) | |
| 428 | 369 |
| 3472 | 370 ;; #### Perhaps this should override `message' itself, too? |
| 371 (defmacro Silence-Message (&rest body) | |
|
4323
94509abd0ef0
Commit a forgotten chunk of 4d0f773d5e21.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4199
diff
changeset
|
372 `(flet ((append-message (&rest args) ()) |
|
94509abd0ef0
Commit a forgotten chunk of 4d0f773d5e21.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4199
diff
changeset
|
373 (clear-message (&rest args) ())) |
|
94509abd0ef0
Commit a forgotten chunk of 4d0f773d5e21.
Aidan Kehoe <kehoea@parhasard.net>
parents:
4199
diff
changeset
|
374 ,@body)) |
| 3472 | 375 |
| 428 | 376 (defmacro Ignore-Ebola (&rest body) |
| 377 `(let ((debug-issue-ebola-notices -42)) ,@body)) | |
| 378 | |
| 379 (defun Int-to-Marker (pos) | |
| 380 (save-excursion | |
| 381 (set-buffer standard-output) | |
| 382 (save-excursion | |
| 383 (goto-char pos) | |
| 384 (point-marker)))) | |
| 385 | |
| 386 (princ "Testing Interpreted Lisp\n\n") | |
| 387 (condition-case error-info | |
| 388 (funcall (test-harness-read-from-buffer inbuffer)) | |
| 389 (error | |
| 3471 | 390 (incf unexpected-test-file-failures) |
| 428 | 391 (princ (format "Unexpected error %S while executing interpreted code\n" |
| 392 error-info)) | |
| 393 (message "Unexpected error %S while executing interpreted code." error-info) | |
| 394 (message "Test suite execution aborted." error-info) | |
| 395 )) | |
| 396 (princ "\nTesting Compiled Lisp\n\n") | |
| 1758 | 397 (let (code |
| 398 (test-harness-test-compiled t)) | |
| 428 | 399 (condition-case error-info |
| 446 | 400 (setq code |
| 401 ;; our lisp code is often intentionally dubious, | |
| 402 ;; so throw away _all_ the byte compiler warnings. | |
| 403 (letf (((symbol-function 'byte-compile-warn) 'ignore)) | |
| 404 (byte-compile (test-harness-read-from-buffer inbuffer)))) | |
| 428 | 405 (error |
| 406 (princ (format "Unexpected error %S while byte-compiling code\n" | |
| 407 error-info)))) | |
| 408 (condition-case error-info | |
| 409 (if code (funcall code)) | |
| 410 (error | |
| 3471 | 411 (incf unexpected-test-file-failures) |
| 428 | 412 (princ (format "Unexpected error %S while executing byte-compiled code\n" |
| 413 error-info)) | |
| 414 (message "Unexpected error %S while executing byte-compiled code." error-info) | |
| 415 (message "Test suite execution aborted." error-info) | |
| 416 ))) | |
| 826 | 417 (princ (format "\nSUMMARY for %s:\n" filename)) |
| 428 | 418 (princ (format "\t%5d passes\n" passes)) |
| 419 (princ (format "\t%5d assertion failures\n" assertion-failures)) | |
| 420 (princ (format "\t%5d errors that should have been generated, but weren't\n" no-error-failures)) | |
| 421 (princ (format "\t%5d wrong-error failures\n" wrong-error-failures)) | |
| 422 (princ (format "\t%5d missing-message failures\n" missing-message-failures)) | |
| 423 (princ (format "\t%5d other failures\n" other-failures)) | |
| 424 (let* ((total (+ passes | |
| 425 assertion-failures | |
| 426 no-error-failures | |
| 427 wrong-error-failures | |
| 428 missing-message-failures | |
| 429 other-failures)) | |
| 430 (basename (file-name-nondirectory filename)) | |
| 431 (summary-msg | |
| 432 (if (> total 0) | |
| 1751 | 433 (format test-harness-file-summary-template |
| 434 (concat basename ":") | |
| 435 passes total (/ (* 100 passes) total)) | |
| 436 (format test-harness-null-summary-template | |
| 437 (concat basename ":")))) | |
| 973 | 438 (reasons "")) |
| 439 (maphash (lambda (key value) | |
| 440 (setq reasons | |
| 441 (concat reasons | |
| 1095 | 442 (format "\n %d tests skipped because %s." |
| 973 | 443 value key)))) |
| 444 skipped-test-reasons) | |
| 445 (when (> (length reasons) 1) | |
| 446 (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
|
447 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
|
448 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
|
449 --package-path to enable the skipped tests."))) |
| 1719 | 450 (setq test-harness-file-results-alist |
| 451 (cons (list filename passes total) | |
| 452 test-harness-file-results-alist)) | |
| 428 | 453 (message "%s" summary-msg)) |
| 3471 | 454 (when (> unexpected-test-file-failures 0) |
| 455 (setq unexpected-test-suite-failure-files | |
| 456 (cons filename unexpected-test-suite-failure-files)) | |
| 457 (setq unexpected-test-suite-failures | |
| 458 (+ unexpected-test-suite-failures unexpected-test-file-failures)) | |
| 428 | 459 (message "Test suite execution failed unexpectedly.")) |
| 460 (fmakunbound 'Assert) | |
| 461 (fmakunbound 'Check-Error) | |
| 863 | 462 (fmakunbound 'Check-Message) |
| 463 (fmakunbound 'Check-Error-Message) | |
| 428 | 464 (fmakunbound 'Ignore-Ebola) |
| 465 (fmakunbound 'Int-to-Marker) | |
| 1719 | 466 (and noninteractive |
| 467 (message "%s" (buffer-substring-no-properties | |
| 1751 | 468 nil nil "*Test-Log*"))) |
| 469 ))) | |
| 428 | 470 |
| 471 (defvar test-harness-results-point-max nil) | |
| 472 (defmacro displaying-emacs-test-results (&rest body) | |
| 473 `(let ((test-harness-results-point-max test-harness-results-point-max)) | |
| 474 ;; Log the file name. | |
| 475 (test-harness-log-file) | |
| 476 ;; Record how much is logged now. | |
| 477 ;; We will display the log buffer if anything more is logged | |
| 478 ;; before the end of BODY. | |
| 479 (or test-harness-results-point-max | |
| 480 (save-excursion | |
| 481 (set-buffer (get-buffer-create "*Test-Log*")) | |
| 482 (setq test-harness-results-point-max (point-max)))) | |
| 483 (unwind-protect | |
| 484 (condition-case error-info | |
| 485 (progn ,@body) | |
| 486 (error | |
| 487 (test-harness-report-error error-info))) | |
| 488 (save-excursion | |
| 489 ;; If there were compilation warnings, display them. | |
| 490 (set-buffer "*Test-Log*") | |
| 491 (if (= test-harness-results-point-max (point-max)) | |
| 492 nil | |
| 493 (if temp-buffer-show-function | |
| 494 (let ((show-buffer (get-buffer-create "*Test-Log-Show*"))) | |
| 495 (save-excursion | |
| 496 (set-buffer show-buffer) | |
| 497 (setq buffer-read-only nil) | |
| 498 (erase-buffer)) | |
| 499 (copy-to-buffer show-buffer | |
| 500 (save-excursion | |
| 501 (goto-char test-harness-results-point-max) | |
| 502 (forward-line -1) | |
| 503 (point)) | |
| 504 (point-max)) | |
| 505 (funcall temp-buffer-show-function show-buffer)) | |
| 506 (select-window | |
| 507 (prog1 (selected-window) | |
| 508 (select-window (display-buffer (current-buffer))) | |
| 509 (goto-char test-harness-results-point-max) | |
| 510 (recenter 1))))))))) | |
| 511 | |
| 512 (defun batch-test-emacs-1 (file) | |
| 513 (condition-case error-info | |
| 514 (progn (test-emacs-test-file file) t) | |
| 515 (error | |
| 516 (princ ">>Error occurred processing ") | |
| 517 (princ file) | |
| 518 (princ ": ") | |
| 519 (display-error error-info nil) | |
| 520 (terpri) | |
| 521 nil))) | |
| 522 | |
| 523 (defun batch-test-emacs () | |
| 524 "Run `test-harness' on the files remaining on the command line. | |
| 525 Use this from the command line, with `-batch'; | |
| 526 it won't work in an interactive Emacs. | |
| 527 Each file is processed even if an error occurred previously. | |
| 528 For example, invoke \"xemacs -batch -f batch-test-emacs tests/*.el\"" | |
| 529 ;; command-line-args-left is what is left of the command line (from | |
| 530 ;; startup.el) | |
| 531 (defvar command-line-args-left) ;Avoid 'free variable' warning | |
| 532 (defvar debug-issue-ebola-notices) | |
| 533 (if (not noninteractive) | |
| 534 (error "`batch-test-emacs' is to be used only with -batch")) | |
| 535 (let ((error nil)) | |
| 536 (dolist (file command-line-args-left) | |
| 537 (if (file-directory-p file) | |
| 538 (dolist (file-in-dir (directory-files file t)) | |
| 539 (when (and (string-match emacs-lisp-file-regexp file-in-dir) | |
| 540 (not (or (auto-save-file-name-p file-in-dir) | |
| 541 (backup-file-name-p file-in-dir) | |
| 542 (equal (file-name-nondirectory file-in-dir) | |
| 543 "test-harness.el")))) | |
| 544 (or (batch-test-emacs-1 file-in-dir) | |
| 545 (setq error t)))) | |
| 546 (or (batch-test-emacs-1 file) | |
| 547 (setq error t)))) | |
| 1719 | 548 (let ((namelen 0) |
| 549 (succlen 0) | |
| 550 (testlen 0) | |
| 551 (results test-harness-file-results-alist)) | |
| 552 ;; compute maximum lengths of variable components of report | |
| 553 ;; probably should just use (length "byte-compiler-tests.el") | |
| 554 ;; and 5-place sizes -- this will also work for the file-by-file | |
| 555 ;; printing when Adrian's kludge gets reverted | |
| 556 (flet ((print-width (i) | |
| 557 (let ((x 10) (y 1)) | |
| 558 (while (>= i x) | |
| 559 (setq x (* 10 x) y (1+ y))) | |
| 560 y))) | |
| 561 (while results | |
| 562 (let* ((head (car results)) | |
| 563 (nn (length (file-name-nondirectory (first head)))) | |
| 564 (ss (print-width (second head))) | |
| 565 (tt (print-width (third head)))) | |
| 566 (when (> nn namelen) (setq namelen nn)) | |
| 567 (when (> ss succlen) (setq succlen ss)) | |
| 568 (when (> tt testlen) (setq testlen tt))) | |
| 569 (setq results (cdr results)))) | |
| 570 ;; create format and print | |
| 1751 | 571 (let ((results (reverse test-harness-file-results-alist))) |
| 1719 | 572 (while results |
| 573 (let* ((head (car results)) | |
| 1751 | 574 (basename (file-name-nondirectory (first head))) |
| 1719 | 575 (nsucc (second head)) |
| 576 (ntest (third head))) | |
| 1722 | 577 (if (> ntest 0) |
| 1751 | 578 (message test-harness-file-summary-template |
| 579 (concat basename ":") | |
| 1722 | 580 nsucc |
| 581 ntest | |
| 582 (/ (* 100 nsucc) ntest)) | |
| 1751 | 583 (message test-harness-null-summary-template |
| 584 (concat basename ":"))) | |
| 3471 | 585 (setq results (cdr results))))) |
| 586 (when (> unexpected-test-suite-failures 0) | |
| 587 (message "\n***** There %s %d unexpected test suite %s in %s:" | |
| 588 (if (= unexpected-test-suite-failures 1) "was" "were") | |
| 589 unexpected-test-suite-failures | |
| 590 (if (= unexpected-test-suite-failures 1) "failure" "failures") | |
| 591 (if (= (length unexpected-test-suite-failure-files) 1) | |
| 592 "file" | |
| 593 "files")) | |
| 594 (while unexpected-test-suite-failure-files | |
| 595 (let ((line (pop unexpected-test-suite-failure-files))) | |
| 596 (while (and (< (length line) 61) | |
| 597 unexpected-test-suite-failure-files) | |
| 598 (setq line | |
| 599 (concat line " " | |
| 600 (pop unexpected-test-suite-failure-files)))) | |
| 601 (message line))))) | |
| 1719 | 602 (message "\nDone") |
| 428 | 603 (kill-emacs (if error 1 0)))) |
| 604 | |
| 605 (provide 'test-harness) | |
| 606 | |
| 607 ;;; test-harness.el ends here |
