Mercurial > emacs
comparison lisp/emacs-lisp/testcover.el @ 53196:b3327f1ed9e1
Ensure that forms marked with `1value' actually always return the same value.
author | Jonathan Yavner <jyavner@member.fsf.org> |
---|---|
date | Sun, 30 Nov 2003 06:56:28 +0000 |
parents | 695cf19ef79e |
children | 71315b2afe5b |
comparison
equal
deleted
inserted
replaced
53195:49d5fa0b5a1c | 53196:b3327f1ed9e1 |
---|---|
169 | 169 |
170 ;;;========================================================================= | 170 ;;;========================================================================= |
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 |
185 testcover-module-constants nil | 184 testcover-module-constants nil |
186 testcover-module-1value-functions nil) | 185 testcover-module-1value-functions nil) |
208 | 207 |
209 (defun testcover-reinstrument (form) | 208 (defun testcover-reinstrument (form) |
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)) |
217 (memq form testcover-constants) | 217 (memq form testcover-constants) |
218 (memq form testcover-module-constants))) | 218 (memq form testcover-module-constants))) |
232 ;;1-valued if first argument is | 232 ;;1-valued if first argument is |
233 (testcover-reinstrument-list (cddr form)) | 233 (testcover-reinstrument-list (cddr form)) |
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)) |
244 (setcar form 'testcover-enter) | 244 (setcar form 'testcover-enter) |
245 (setcdr (nthcdr 1 form) (nthcdr 3 form)) | 245 (setcdr (nthcdr 1 form) (nthcdr 3 form)) |
248 ((eq fun 'edebug-after) | 248 ((eq fun 'edebug-after) |
249 ;;(edebug-after (edebug-before XXX) YYY FORM) | 249 ;;(edebug-after (edebug-before XXX) YYY FORM) |
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))) |
267 ((eq fun 'defconst) | 272 ((eq fun 'defconst) |
268 ;;Define this symbol as 1-valued | 273 ;;Define this symbol as 1-valued |
314 (testcover-reinstrument (cadr form)))) | 319 (testcover-reinstrument (cadr form)))) |
315 ((memq fun '(1value noreturn)) | 320 ((memq fun '(1value noreturn)) |
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)) |
324 nil)))) | 332 nil)))) |
325 | 333 |
346 "Turn off instrumentation of all macros and functions in FILENAME." | 354 "Turn off instrumentation of all macros and functions in FILENAME." |
347 (interactive "b") | 355 (interactive "b") |
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 |
363 ;;;========================================================================= | 362 ;;;========================================================================= |
364 | 363 |
376 ((eq (aref testcover-vector idx) 'unknown) | 375 ((eq (aref testcover-vector idx) 'unknown) |
377 (aset testcover-vector idx val)) | 376 (aset testcover-vector idx val)) |
378 ((not (equal (aref testcover-vector idx) val)) | 377 ((not (equal (aref testcover-vector idx) val)) |
379 (aset testcover-vector idx 'ok-coverage))) | 378 (aset testcover-vector idx 'ok-coverage))) |
380 val) | 379 val) |
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 | |
381 | 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. |
385 ;;;========================================================================= | 397 ;;;========================================================================= |
409 (overlays-in def-mark (+ def-mark (aref points (1- len)) 1))) | 421 (overlays-in def-mark (+ def-mark (aref points (1- len)) 1))) |
410 (while (> len 0) | 422 (while (> len 0) |
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 |
417 (if (memq data '(unknown 1value)) | 430 (if (memq data '(unknown 1value)) |
418 'testcover-nohits-face | 431 'testcover-nohits-face |