diff options
| author | Jonathan Yavner | 2003-11-30 06:56:28 +0000 |
|---|---|---|
| committer | Jonathan Yavner | 2003-11-30 06:56:28 +0000 |
| commit | bbaa142972a148a3a6cc68c2a8aaf973aaf2135f (patch) | |
| tree | 35d56c0decf3f74553e0f0ed3ce0e9ac3047d73e | |
| parent | 190177521fe7c6f0d895606b585852f1e3635de4 (diff) | |
| download | emacs-bbaa142972a148a3a6cc68c2a8aaf973aaf2135f.tar.gz emacs-bbaa142972a148a3a6cc68c2a8aaf973aaf2135f.zip | |
Ensure that forms marked with `1value' actually always return the same value.
| -rw-r--r-- | lisp/emacs-lisp/testcover.el | 55 |
1 files changed, 34 insertions, 21 deletions
diff --git a/lisp/emacs-lisp/testcover.el b/lisp/emacs-lisp/testcover.el index 4d668a78678..547e2cbd32d 100644 --- a/lisp/emacs-lisp/testcover.el +++ b/lisp/emacs-lisp/testcover.el | |||
| @@ -171,14 +171,13 @@ call to one of the `testcover-1value-functions'." | |||
| 171 | ;;; Add instrumentation to your module | 171 | ;;; Add instrumentation to your module |
| 172 | ;;;========================================================================= | 172 | ;;;========================================================================= |
| 173 | 173 | ||
| 174 | ;;;###autoload | ||
| 175 | (defun testcover-start (filename &optional byte-compile) | 174 | (defun testcover-start (filename &optional byte-compile) |
| 176 | "Uses edebug to instrument all macros and functions in FILENAME, then | 175 | "Uses edebug to instrument all macros and functions in FILENAME, then |
| 177 | changes the instrumentation from edebug to testcover--much faster, no | 176 | changes the instrumentation from edebug to testcover--much faster, no |
| 178 | problems with type-ahead or post-command-hook, etc. If BYTE-COMPILE is | 177 | problems with type-ahead or post-command-hook, etc. If BYTE-COMPILE is |
| 179 | non-nil, byte-compiles each function after instrumenting." | 178 | non-nil, byte-compiles each function after instrumenting." |
| 180 | (interactive "f") | 179 | (interactive "f") |
| 181 | (let ((buf (find-file filename)) | 180 | (let ((buf (find-file filename)) |
| 182 | (load-read-function 'testcover-read) | 181 | (load-read-function 'testcover-read) |
| 183 | (edebug-all-defs t)) | 182 | (edebug-all-defs t)) |
| 184 | (setq edebug-form-data nil | 183 | (setq edebug-form-data nil |
| @@ -210,7 +209,8 @@ non-nil, byte-compiles each function after instrumenting." | |||
| 210 | "Reinstruments FORM to use testcover instead of edebug. This function | 209 | "Reinstruments FORM to use testcover instead of edebug. This function |
| 211 | modifies the list that FORM points to. Result is non-nil if FORM will | 210 | modifies the list that FORM points to. Result is non-nil if FORM will |
| 212 | always return the same value." | 211 | always return the same value." |
| 213 | (let ((fun (car-safe form))) | 212 | (let ((fun (car-safe form)) |
| 213 | id) | ||
| 214 | (cond | 214 | (cond |
| 215 | ((not fun) ;Atom | 215 | ((not fun) ;Atom |
| 216 | (or (not (symbolp form)) | 216 | (or (not (symbolp form)) |
| @@ -234,10 +234,10 @@ always return the same value." | |||
| 234 | (testcover-reinstrument (cadr form))) | 234 | (testcover-reinstrument (cadr form))) |
| 235 | ((memq fun testcover-compose-functions) | 235 | ((memq fun testcover-compose-functions) |
| 236 | ;;1-valued if all arguments are | 236 | ;;1-valued if all arguments are |
| 237 | (setq fun t) | 237 | (setq id t) |
| 238 | (mapc #'(lambda (x) (setq fun (or (testcover-reinstrument x) fun))) | 238 | (mapc #'(lambda (x) (setq id (or (testcover-reinstrument x) id))) |
| 239 | (cdr form)) | 239 | (cdr form)) |
| 240 | fun) | 240 | id) |
| 241 | ((eq fun 'edebug-enter) | 241 | ((eq fun 'edebug-enter) |
| 242 | ;;(edebug-enter 'SYM ARGS #'(lambda nil FORMS)) | 242 | ;;(edebug-enter 'SYM ARGS #'(lambda nil FORMS)) |
| 243 | ;; => (testcover-enter 'SYM #'(lambda nil FORMS)) | 243 | ;; => (testcover-enter 'SYM #'(lambda nil FORMS)) |
| @@ -250,17 +250,22 @@ always return the same value." | |||
| 250 | ;; => (testcover-after YYY FORM), mark XXX as ok-coverage | 250 | ;; => (testcover-after YYY FORM), mark XXX as ok-coverage |
| 251 | (unless (eq (cadr form) 0) | 251 | (unless (eq (cadr form) 0) |
| 252 | (aset testcover-vector (cadr (cadr form)) 'ok-coverage)) | 252 | (aset testcover-vector (cadr (cadr form)) 'ok-coverage)) |
| 253 | (setq fun (nth 2 form)) | 253 | (setq id (nth 2 form)) |
| 254 | (setcdr form (nthcdr 2 form)) | 254 | (setcdr form (nthcdr 2 form)) |
| 255 | (if (not (memq (car-safe (nth 2 form)) testcover-noreturn-functions)) | 255 | (cond |
| 256 | (setcar form 'testcover-after) | 256 | ((memq (car-safe (nth 2 form)) testcover-noreturn-functions) |
| 257 | ;;This function won't return, so set the value in advance | 257 | ;;This function won't return, so set the value in advance |
| 258 | ;;(edebug-after (edebug-before XXX) YYY FORM) | 258 | ;;(edebug-after (edebug-before XXX) YYY FORM) |
| 259 | ;; => (progn (edebug-after YYY nil) FORM) | 259 | ;; => (progn (edebug-after YYY nil) FORM) |
| 260 | (setcar form 'progn) | 260 | (setcar form 'progn) |
| 261 | (setcar (cdr form) `(testcover-after ,fun nil))) | 261 | (setcar (cdr form) `(testcover-after ,id nil))) |
| 262 | ((eq (car-safe (nth 2 form)) '1value) | ||
| 263 | ;;This function is always supposed to return the same value | ||
| 264 | (setcar form 'testcover-1value)) | ||
| 265 | (t | ||
| 266 | (setcar form 'testcover-after))) | ||
| 262 | (when (testcover-reinstrument (nth 2 form)) | 267 | (when (testcover-reinstrument (nth 2 form)) |
| 263 | (aset testcover-vector fun '1value))) | 268 | (aset testcover-vector id '1value))) |
| 264 | ((eq fun 'defun) | 269 | ((eq fun 'defun) |
| 265 | (if (testcover-reinstrument-list (nthcdr 3 form)) | 270 | (if (testcover-reinstrument-list (nthcdr 3 form)) |
| 266 | (push (cadr form) testcover-module-1value-functions))) | 271 | (push (cadr form) testcover-module-1value-functions))) |
| @@ -316,8 +321,11 @@ always return the same value." | |||
| 316 | ;;Hack - pretend the arg is 1-valued here | 321 | ;;Hack - pretend the arg is 1-valued here |
| 317 | (if (symbolp (cadr form)) ;A pseudoconstant variable | 322 | (if (symbolp (cadr form)) ;A pseudoconstant variable |
| 318 | t | 323 | t |
| 324 | (if (eq (car (cadr form)) 'edebug-after) | ||
| 325 | (setq id (car (nth 3 (cadr form)))) | ||
| 326 | (setq id (car (cadr form)))) | ||
| 319 | (let ((testcover-1value-functions | 327 | (let ((testcover-1value-functions |
| 320 | (cons (car (cadr form)) testcover-1value-functions))) | 328 | (cons id testcover-1value-functions))) |
| 321 | (testcover-reinstrument (cadr form))))) | 329 | (testcover-reinstrument (cadr form))))) |
| 322 | (t ;Some other function or weird thing | 330 | (t ;Some other function or weird thing |
| 323 | (testcover-reinstrument-list (cdr form)) | 331 | (testcover-reinstrument-list (cdr form)) |
| @@ -348,15 +356,6 @@ Result is t if every clause is 1-valued." | |||
| 348 | (let ((buf (find-file-noselect buffer))) | 356 | (let ((buf (find-file-noselect buffer))) |
| 349 | (eval-buffer buf t))) | 357 | (eval-buffer buf t))) |
| 350 | 358 | ||
| 351 | (defmacro 1value (form) | ||
| 352 | "For coverage testing, indicate FORM should always have the same value." | ||
| 353 | form) | ||
| 354 | |||
| 355 | (defmacro noreturn (form) | ||
| 356 | "For coverage testing, indicate that FORM will never return." | ||
| 357 | `(prog1 ,form | ||
| 358 | (error "Form marked with `noreturn' did return"))) | ||
| 359 | |||
| 360 | 359 | ||
| 361 | ;;;========================================================================= | 360 | ;;;========================================================================= |
| 362 | ;;; Accumulate coverage data | 361 | ;;; Accumulate coverage data |
| @@ -379,6 +378,19 @@ binding `testcover-vector' to the code-coverage vector for TESTCOVER-SYM | |||
| 379 | (aset testcover-vector idx 'ok-coverage))) | 378 | (aset testcover-vector idx 'ok-coverage))) |
| 380 | val) | 379 | val) |
| 381 | 380 | ||
| 381 | (defun testcover-1value (idx val) | ||
| 382 | "Internal function for coverage testing. Returns VAL after installing it in | ||
| 383 | `testcover-vector' at offset IDX. Error if FORM does not always return the | ||
| 384 | same value during coverage testing." | ||
| 385 | (cond | ||
| 386 | ((eq (aref testcover-vector idx) '1value) | ||
| 387 | (aset testcover-vector idx (cons '1value val))) | ||
| 388 | ((not (and (eq (car-safe (aref testcover-vector idx)) '1value) | ||
| 389 | (equal (cdr (aref testcover-vector idx)) val))) | ||
| 390 | (error "Value of form marked with `1value' does vary."))) | ||
| 391 | val) | ||
| 392 | |||
| 393 | |||
| 382 | 394 | ||
| 383 | ;;;========================================================================= | 395 | ;;;========================================================================= |
| 384 | ;;; Display the coverage data as color splotches on your code. | 396 | ;;; Display the coverage data as color splotches on your code. |
| @@ -411,6 +423,7 @@ eliminated by adding more test cases." | |||
| 411 | (setq len (1- len) | 423 | (setq len (1- len) |
| 412 | data (aref coverage len)) | 424 | data (aref coverage len)) |
| 413 | (when (and (not (eq data 'ok-coverage)) | 425 | (when (and (not (eq data 'ok-coverage)) |
| 426 | (not (eq (car-safe data) '1value)) | ||
| 414 | (setq j (+ def-mark (aref points len)))) | 427 | (setq j (+ def-mark (aref points len)))) |
| 415 | (setq ov (make-overlay (1- j) j)) | 428 | (setq ov (make-overlay (1- j) j)) |
| 416 | (overlay-put ov 'face | 429 | (overlay-put ov 'face |