unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#24402: 25.1.50; testcover-start breaks should-error
@ 2016-09-10  1:26 Gemini Lasswell
       [not found] ` <handler.24402.B.14734739098199.ack@debbugs.gnu.org>
  0 siblings, 1 reply; 28+ messages in thread
From: Gemini Lasswell @ 2016-09-10  1:26 UTC (permalink / raw)
  To: 24402

[-- Attachment #1: Type: text/plain, Size: 613 bytes --]

Enabling code coverage on a file containing an ert test that uses should-error causes the test to fail.

Steps to reproduce:
1. Start emacs (I used: open nextstep/Emacs.app —args -Q)

2. Create a buffer containing the following code and save it as bug.el:
(require 'ert)
(require 'testcover)

(ert-deftest should-error-bug ()
  (should-error (my-error)))

(defun my-error ()
  (/ 1 0))

3. M-x eval-buffer RET

4. M-x ert RET t RET

5. The test passes.

6. M-x testcover-start RET bug.el RET

7. M-x ert RET t RET

8. The test fails. TAB TAB d produced the attached debugger output.


[-- Attachment #2: bug.txt --]
[-- Type: text/plain, Size: 17362 bytes --]

Debugger entered--Lisp error: (arith-error)
  apply(debug (error (arith-error)))
  ert--run-test-debugger([cl-struct-ert--test-execution-info [cl-struct-ert-test should-error-bug nil (lambda nil (testcover-enter (quote test@should-error-bug) (function (lambda nil (testcover-after 3 (let ... ...)))))) nil :passed nil] [cl-struct-ert-test-failed nil nil (arith-error) ((t (lambda nil (testcover-1value 1 (/ 1 0)))) (t testcover-enter my-error (lambda nil (testcover-1value 1 (/ 1 0)))) (t my-error) (nil list 2 (my-error)) (nil let ((fn-7 (function testcover-after)) (args-8 (list 2 (my-error)))) (let ((value-9 (quote ert-form-evaluation-aborted-10))) (let (form-description-11) (let (... ...) (condition-case -condition- ... ...) (if errorp12 nil ...))) value-9)) (nil testcover-after 3 (let ((fn-7 (function testcover-after)) (args-8 (list 2 ...))) (let ((value-9 ...)) (let (form-description-11) (let ... ... ...)) value-9))) (t (lambda nil (testcover-after 3 (let (... ...) (let ... ... value-9))))) (t testcover-enter test@should-error-bug (lambda nil (testcover-after 3 (let (... ...) (let ... ... value-9))))) (t (lambda nil (testcover-enter (quote test@should-error-bug) (function (lambda nil ...))))) (t ert--run-test-internal #0) (t ert-run-test [cl-struct-ert-test should-error-bug nil (lambda nil (testcover-enter (quote test@should-error-bug) (function ...))) nil :passed nil]) (t ert-run-or-rerun-test [cl-struct-ert--stats t [[cl-struct-ert-test should-error-bug nil (lambda nil ...) nil :passed nil]] #s(hash-table size 1 test eql rehash-size 1.5 rehash-threshold 0.8 data (should-error-bug 0)) [nil] [(22483 23504 1016 0)] [(22483 22641 595275 0)] 0 0 0 0 0 (22483 22641 578681 0) (22483 22641 595513 0) nil [cl-struct-ert-test should-error-bug nil (lambda nil (testcover-enter ... ...)) nil :passed nil] 1473469392.100925] [cl-struct-ert-test should-error-bug nil (lambda nil (testcover-enter (quote test@should-error-bug) (function ...))) nil :passed nil] #[385 "\306\x02\307\"\203)\0\211\211G\310U\203\x14\0\211@\202^[\0\311\312\313\x03GD\"\301\314\x02\302\242\300#\240\210\315\301\242!\207\306\x02\316\"\203\222\0\211\211G\317U\203A\0\211\x01A\262\x02\242\202H\0\311\312\313\x03GD\"\x01@\303\320\x02\204T\0\321\202U\0\322\323\x05!\324\x06\x06!\325\x06\a!\211\326U\203j\0\321\202n\0\327\330\x02\"\262\x01\331\x06\b!\211\326U\203~\0\321\202\202\0\327\332\x02\"\262\x01&\x06\210\333r\301\242q\210\f)\x03\"\207\306\x02\334\"\203\372\0\211\211G\317U\203\252\0\211\x01A\262\x02\242\202\261\0\311\312\313\x03GD\"\x01@r\301\242q\210\f\335\x03\x03\"\336\x02\x02\"\211\204\311\0\337\340!\210\211\317H\211\326H\r>\204\333\0\311\341\342\x03D\"\210\211\211\310\x06\aI\266\x03\x0e-\x02\343\313\344\"I\210\345\x03\x06\x06\"\210\346\x03\x02\"\266\203)\207\306\x02\347\"\203\204\x01\211\211G\350U\203\x12\x01\211\x01A\262\x02\242\202\x19\x01\311\312\313\x03GD\"\x01\211A\262\x03\242\x02@r\301\242q\210\f\335\x04\x04\"\336\x02\x02\"\211\317H\211\326H\r>\204A\x01\311\341\342\x03D\"\210\211\317H\262\x01\203g\x01\211\317H\211\326H\r>\204[\x01\311\341\342\x03D\"\210\211\211\317\351\x06	\x06	\"I\266\x03\x0e-\x02\343\x06\x06\351\x06	\x06	\"\"I\210\345\x03\x06\a\"\210\346\x03\x02\"\266\203)\207\352\353\x03\354#\205\215\x01\313\207" [nil (#<buffer *ert*>) (#4) message ert--results-ewoc cl-struct-ert--ewoc-entry-tags eql run-started 1 signal wrong-number-of-arguments nil ert--setup-results-buffer pop-to-buffer run-ended 2 "%sRan %s tests, %s results were as expected%s%s" "" "Aborted: " ert-stats-total ert-stats-completed-expected ert-stats-completed-unexpected 0 format ", %s unexpected" ert-stats-skipped ", %s skipped" ert--results-update-stats-display test-started ert--stats-test-pos ewoc-nth cl--assertion-failed node wrong-type-argument ert--ewoc-entry ert-char-for-test-result t ert--results-update-stats-display-maybe ewoc-invalidate test-ended 3 ert-test-result-expected-p error "cl-ecase failed: %s, %s" (run-started run-ended test-started test-ended) ert--results-progress-bar-string] 16 "\n\n(fn EVENT-TYPE &rest EVENT-ARGS)"]) (t ert-results-rerun-test-at-point) (t ert-results-rerun-test-at-point-debugging-errors) (t funcall-interactively ert-results-rerun-test-at-point-debugging-errors) (t call-interactively ert-results-rerun-test-at-point-debugging-errors nil nil) (t command-execute ert-results-rerun-test-at-point-debugging-errors)) nil] #[0 "\300\301\302\"\207" [throw --cl-block-error-- nil] 3] debug t] (error (arith-error)))
  #[128 "\301\300\x02\"\207" [[cl-struct-ert--test-execution-info [cl-struct-ert-test should-error-bug nil (lambda nil (testcover-enter (quote test@should-error-bug) (function (lambda nil ...)))) nil :passed nil] [cl-struct-ert-test-failed nil nil (arith-error) ((t (lambda nil (testcover-1value 1 ...))) (t testcover-enter my-error (lambda nil (testcover-1value 1 ...))) (t my-error) (nil list 2 (my-error)) (nil let ((fn-7 ...) (args-8 ...)) (let (...) (let ... ...) value-9)) (nil testcover-after 3 (let (... ...) (let ... ... value-9))) (t (lambda nil (testcover-after 3 ...))) (t testcover-enter test@should-error-bug (lambda nil (testcover-after 3 ...))) (t (lambda nil (testcover-enter ... ...))) (t ert--run-test-internal #2) (t ert-run-test [cl-struct-ert-test should-error-bug nil (lambda nil ...) nil :passed nil]) (t ert-run-or-rerun-test [cl-struct-ert--stats t [[cl-struct-ert-test should-error-bug nil ... nil :passed nil]] #s(hash-table size 1 test eql rehash-size 1.5 rehash-threshold 0.8 data (should-error-bug 0)) [nil] [...] [...] 0 0 0 0 0 (22483 22641 578681 0) (22483 22641 595513 0) nil [cl-struct-ert-test should-error-bug nil ... nil :passed nil] 1473469392.100925] [cl-struct-ert-test should-error-bug nil (lambda nil ...) nil :passed nil] #[385 "\306\x02\307\"\203)\0\211\211G\310U\203\x14\0\211@\202^[\0\311\312\313\x03GD\"\301\314\x02\302\242\300#\240\210\315\301\242!\207\306\x02\316\"\203\222\0\211\211G\317U\203A\0\211\x01A\262\x02\242\202H\0\311\312\313\x03GD\"\x01@\303\320\x02\204T\0\321\202U\0\322\323\x05!\324\x06\x06!\325\x06\a!\211\326U\203j\0\321\202n\0\327\330\x02\"\262\x01\331\x06\b!\211\326U\203~\0\321\202\202\0\327\332\x02\"\262\x01&\x06\210\333r\301\242q\210\f)\x03\"\207\306\x02\334\"\203\372\0\211\211G\317U\203\252\0\211\x01A\262\x02\242\202\261\0\311\312\313\x03GD\"\x01@r\301\242q\210\f\335\x03\x03\"\336\x02\x02\"\211\204\311\0\337\340!\210\211\317H\211\326H\r>\204\333\0\311\341\342\x03D\"\210\211\211\310\x06\aI\266\x03\x0e-\x02\343\313\344\"I\210\345\x03\x06\x06\"\210\346\x03\x02\"\266\203)\207\306\x02\347\"\203\204\x01\211\211G\350U\203\x12\x01\211\x01A\262\x02\242\202\x19\x01\311\312\313\x03GD\"\x01\211A\262\x03\242\x02@r\301\242q\210\f\335\x04\x04\"\336\x02\x02\"\211\317H\211\326H\r>\204A\x01\311\341\342\x03D\"\210\211\317H\262\x01\203g\x01\211\317H\211\326H\r>\204[\x01\311\341\342\x03D\"\210\211\211\317\351\x06	\x06	\"I\266\x03\x0e-\x02\343\x06\x06\351\x06	\x06	\"\"I\210\345\x03\x06\a\"\210\346\x03\x02\"\266\203)\207\352\353\x03\354#\205\215\x01\313\207" [nil ... ... message ert--results-ewoc cl-struct-ert--ewoc-entry-tags eql run-started 1 signal wrong-number-of-arguments nil ert--setup-results-buffer pop-to-buffer run-ended 2 "%sRan %s tests, %s results were as expected%s%s" "" "Aborted: " ert-stats-total ert-stats-completed-expected ert-stats-completed-unexpected 0 format ", %s unexpected" ert-stats-skipped ", %s skipped" ert--results-update-stats-display test-started ert--stats-test-pos ewoc-nth cl--assertion-failed node wrong-type-argument ert--ewoc-entry ert-char-for-test-result t ert--results-update-stats-display-maybe ewoc-invalidate test-ended 3 ert-test-result-expected-p error "cl-ecase failed: %s, %s" ... ert--results-progress-bar-string] 16 "\n\n(fn EVENT-TYPE &rest EVENT-ARGS)"]) (t ert-results-rerun-test-at-point) (t ert-results-rerun-test-at-point-debugging-errors) (t funcall-interactively ert-results-rerun-test-at-point-debugging-errors) (t call-interactively ert-results-rerun-test-at-point-debugging-errors nil nil) (t command-execute ert-results-rerun-test-at-point-debugging-errors)) nil] #[0 "\300\301\302\"\207" [throw --cl-block-error-- nil] 3] debug t] ert--run-test-debugger] 4 "\n\n(fn &rest ARGS)"](error (arith-error))
  /(1 0)
  (testcover-1value 1 (/ 1 0))
  (lambda nil (testcover-1value 1 (/ 1 0)))()
  testcover-enter(my-error (lambda nil (testcover-1value 1 (/ 1 0))))
  my-error()
  (list 2 (my-error))
  (let ((fn-7 (function testcover-after)) (args-8 (list 2 (my-error)))) (let ((value-9 (quote ert-form-evaluation-aborted-10))) (let (form-description-11) (let ((errorp12 nil) (form-description-fn-13 (function (lambda nil form-description-11)))) (condition-case -condition- (unwind-protect (setq value-9 (apply fn-7 args-8)) (setq form-description-11 (nconc ... ... ... ...)) (ert--signal-should-execution form-description-11)) (error (setq errorp12 t) (ert--should-error-handle-error form-description-fn-13 -condition- (quote error) nil) (setq value-9 -condition-))) (if errorp12 nil (ert-fail (append (funcall form-description-fn-13) (list :fail-reason "did not signal an error")))))) value-9))
  (testcover-after 3 (let ((fn-7 (function testcover-after)) (args-8 (list 2 (my-error)))) (let ((value-9 (quote ert-form-evaluation-aborted-10))) (let (form-description-11) (let ((errorp12 nil) (form-description-fn-13 (function ...))) (condition-case -condition- (unwind-protect (setq value-9 ...) (setq form-description-11 ...) (ert--signal-should-execution form-description-11)) (error (setq errorp12 t) (ert--should-error-handle-error form-description-fn-13 -condition- ... nil) (setq value-9 -condition-))) (if errorp12 nil (ert-fail (append ... ...))))) value-9)))
  (lambda nil (testcover-after 3 (let ((fn-7 (function testcover-after)) (args-8 (list 2 (my-error)))) (let ((value-9 (quote ert-form-evaluation-aborted-10))) (let (form-description-11) (let ((errorp12 nil) (form-description-fn-13 ...)) (condition-case -condition- (unwind-protect ... ... ...) (error ... ... ...)) (if errorp12 nil (ert-fail ...)))) value-9))))()
  testcover-enter(test@should-error-bug (lambda nil (testcover-after 3 (let ((fn-7 (function testcover-after)) (args-8 (list 2 (my-error)))) (let ((value-9 (quote ert-form-evaluation-aborted-10))) (let (form-description-11) (let ((errorp12 nil) (form-description-fn-13 ...)) (condition-case -condition- (unwind-protect ... ... ...) (error ... ... ...)) (if errorp12 nil (ert-fail ...)))) value-9)))))
  (lambda nil (testcover-enter (quote test@should-error-bug) (function (lambda nil (testcover-after 3 (let ((fn-7 ...) (args-8 ...)) (let (...) (let ... ...) value-9)))))))()
  ert--run-test-internal([cl-struct-ert--test-execution-info [cl-struct-ert-test should-error-bug nil (lambda nil (testcover-enter (quote test@should-error-bug) (function (lambda nil (testcover-after 3 (let ... ...)))))) nil :passed nil] [cl-struct-ert-test-failed nil nil (arith-error) ((t (lambda nil (testcover-1value 1 (/ 1 0)))) (t testcover-enter my-error (lambda nil (testcover-1value 1 (/ 1 0)))) (t my-error) (nil list 2 (my-error)) (nil let ((fn-7 (function testcover-after)) (args-8 (list 2 (my-error)))) (let ((value-9 (quote ert-form-evaluation-aborted-10))) (let (form-description-11) (let (... ...) (condition-case -condition- ... ...) (if errorp12 nil ...))) value-9)) (nil testcover-after 3 (let ((fn-7 (function testcover-after)) (args-8 (list 2 ...))) (let ((value-9 ...)) (let (form-description-11) (let ... ... ...)) value-9))) (t (lambda nil (testcover-after 3 (let (... ...) (let ... ... value-9))))) (t testcover-enter test@should-error-bug (lambda nil (testcover-after 3 (let (... ...) (let ... ... value-9))))) (t (lambda nil (testcover-enter (quote test@should-error-bug) (function (lambda nil ...))))) (t ert--run-test-internal #0) (t ert-run-test [cl-struct-ert-test should-error-bug nil (lambda nil (testcover-enter (quote test@should-error-bug) (function ...))) nil :passed nil]) (t ert-run-or-rerun-test [cl-struct-ert--stats t [[cl-struct-ert-test should-error-bug nil (lambda nil ...) nil :passed nil]] #s(hash-table size 1 test eql rehash-size 1.5 rehash-threshold 0.8 data (should-error-bug 0)) [nil] [(22483 23504 1016 0)] [(22483 22641 595275 0)] 0 0 0 0 0 (22483 22641 578681 0) (22483 22641 595513 0) nil [cl-struct-ert-test should-error-bug nil (lambda nil (testcover-enter ... ...)) nil :passed nil] 1473469392.100925] [cl-struct-ert-test should-error-bug nil (lambda nil (testcover-enter (quote test@should-error-bug) (function ...))) nil :passed nil] #[385 "\306\x02\307\"\203)\0\211\211G\310U\203\x14\0\211@\202^[\0\311\312\313\x03GD\"\301\314\x02\302\242\300#\240\210\315\301\242!\207\306\x02\316\"\203\222\0\211\211G\317U\203A\0\211\x01A\262\x02\242\202H\0\311\312\313\x03GD\"\x01@\303\320\x02\204T\0\321\202U\0\322\323\x05!\324\x06\x06!\325\x06\a!\211\326U\203j\0\321\202n\0\327\330\x02\"\262\x01\331\x06\b!\211\326U\203~\0\321\202\202\0\327\332\x02\"\262\x01&\x06\210\333r\301\242q\210\f)\x03\"\207\306\x02\334\"\203\372\0\211\211G\317U\203\252\0\211\x01A\262\x02\242\202\261\0\311\312\313\x03GD\"\x01@r\301\242q\210\f\335\x03\x03\"\336\x02\x02\"\211\204\311\0\337\340!\210\211\317H\211\326H\r>\204\333\0\311\341\342\x03D\"\210\211\211\310\x06\aI\266\x03\x0e-\x02\343\313\344\"I\210\345\x03\x06\x06\"\210\346\x03\x02\"\266\203)\207\306\x02\347\"\203\204\x01\211\211G\350U\203\x12\x01\211\x01A\262\x02\242\202\x19\x01\311\312\313\x03GD\"\x01\211A\262\x03\242\x02@r\301\242q\210\f\335\x04\x04\"\336\x02\x02\"\211\317H\211\326H\r>\204A\x01\311\341\342\x03D\"\210\211\317H\262\x01\203g\x01\211\317H\211\326H\r>\204[\x01\311\341\342\x03D\"\210\211\211\317\351\x06	\x06	\"I\266\x03\x0e-\x02\343\x06\x06\351\x06	\x06	\"\"I\210\345\x03\x06\a\"\210\346\x03\x02\"\266\203)\207\352\353\x03\354#\205\215\x01\313\207" [nil (#<buffer *ert*>) (#4) message ert--results-ewoc cl-struct-ert--ewoc-entry-tags eql run-started 1 signal wrong-number-of-arguments nil ert--setup-results-buffer pop-to-buffer run-ended 2 "%sRan %s tests, %s results were as expected%s%s" "" "Aborted: " ert-stats-total ert-stats-completed-expected ert-stats-completed-unexpected 0 format ", %s unexpected" ert-stats-skipped ", %s skipped" ert--results-update-stats-display test-started ert--stats-test-pos ewoc-nth cl--assertion-failed node wrong-type-argument ert--ewoc-entry ert-char-for-test-result t ert--results-update-stats-display-maybe ewoc-invalidate test-ended 3 ert-test-result-expected-p error "cl-ecase failed: %s, %s" (run-started run-ended test-started test-ended) ert--results-progress-bar-string] 16 "\n\n(fn EVENT-TYPE &rest EVENT-ARGS)"]) (t ert-results-rerun-test-at-point) (t ert-results-rerun-test-at-point-debugging-errors) (t funcall-interactively ert-results-rerun-test-at-point-debugging-errors) (t call-interactively ert-results-rerun-test-at-point-debugging-errors nil nil) (t command-execute ert-results-rerun-test-at-point-debugging-errors)) nil] #[0 "\300\301\302\"\207" [throw --cl-block-error-- nil] 3] debug t])
  ert-run-test([cl-struct-ert-test should-error-bug nil (lambda nil (testcover-enter (quote test@should-error-bug) (function (lambda nil (testcover-after 3 (let (... ...) (let ... ... value-9))))))) nil :passed nil])
  ert-run-or-rerun-test([cl-struct-ert--stats t [[cl-struct-ert-test should-error-bug nil (lambda nil (testcover-enter (quote test@should-error-bug) (function (lambda nil (testcover-after 3 ...))))) nil :passed nil]] #s(hash-table size 1 test eql rehash-size 1.5 rehash-threshold 0.8 data (should-error-bug 0)) [nil] [(22483 23504 1016 0)] [(22483 22641 595275 0)] 0 0 0 0 0 (22483 22641 578681 0) (22483 22641 595513 0) nil [cl-struct-ert-test should-error-bug nil (lambda nil (testcover-enter (quote test@should-error-bug) (function (lambda nil (testcover-after 3 (let ... ...)))))) nil :passed nil] 1473469392.100925] [cl-struct-ert-test should-error-bug nil (lambda nil (testcover-enter (quote test@should-error-bug) (function (lambda nil (testcover-after 3 (let (... ...) (let ... ... value-9))))))) nil :passed nil] #[385 "\306\x02\307\"\203)\0\211\211G\310U\203\x14\0\211@\202^[\0\311\312\313\x03GD\"\301\314\x02\302\242\300#\240\210\315\301\242!\207\306\x02\316\"\203\222\0\211\211G\317U\203A\0\211\x01A\262\x02\242\202H\0\311\312\313\x03GD\"\x01@\303\320\x02\204T\0\321\202U\0\322\323\x05!\324\x06\x06!\325\x06\a!\211\326U\203j\0\321\202n\0\327\330\x02\"\262\x01\331\x06\b!\211\326U\203~\0\321\202\202\0\327\332\x02\"\262\x01&\x06\210\333r\301\242q\210\f)\x03\"\207\306\x02\334\"\203\372\0\211\211G\317U\203\252\0\211\x01A\262\x02\242\202\261\0\311\312\313\x03GD\"\x01@r\301\242q\210\f\335\x03\x03\"\336\x02\x02\"\211\204\311\0\337\340!\210\211\317H\211\326H\r>\204\333\0\311\341\342\x03D\"\210\211\211\310\x06\aI\266\x03\x0e-\x02\343\313\344\"I\210\345\x03\x06\x06\"\210\346\x03\x02\"\266\203)\207\306\x02\347\"\203\204\x01\211\211G\350U\203\x12\x01\211\x01A\262\x02\242\202\x19\x01\311\312\313\x03GD\"\x01\211A\262\x03\242\x02@r\301\242q\210\f\335\x04\x04\"\336\x02\x02\"\211\317H\211\326H\r>\204A\x01\311\341\342\x03D\"\210\211\317H\262\x01\203g\x01\211\317H\211\326H\r>\204[\x01\311\341\342\x03D\"\210\211\211\317\351\x06	\x06	\"I\266\x03\x0e-\x02\343\x06\x06\351\x06	\x06	\"\"I\210\345\x03\x06\a\"\210\346\x03\x02\"\266\203)\207\352\353\x03\354#\205\215\x01\313\207" [nil (#<buffer *ert*>) (#0) message ert--results-ewoc cl-struct-ert--ewoc-entry-tags eql run-started 1 signal wrong-number-of-arguments nil ert--setup-results-buffer pop-to-buffer run-ended 2 "%sRan %s tests, %s results were as expected%s%s" "" "Aborted: " ert-stats-total ert-stats-completed-expected ert-stats-completed-unexpected 0 format ", %s unexpected" ert-stats-skipped ", %s skipped" ert--results-update-stats-display test-started ert--stats-test-pos ewoc-nth cl--assertion-failed node wrong-type-argument ert--ewoc-entry ert-char-for-test-result t ert--results-update-stats-display-maybe ewoc-invalidate test-ended 3 ert-test-result-expected-p error "cl-ecase failed: %s, %s" (run-started run-ended test-started test-ended) ert--results-progress-bar-string] 16 "\n\n(fn EVENT-TYPE &rest EVENT-ARGS)"])
  ert-results-rerun-test-at-point()
  ert-results-rerun-test-at-point-debugging-errors()
  funcall-interactively(ert-results-rerun-test-at-point-debugging-errors)
  call-interactively(ert-results-rerun-test-at-point-debugging-errors nil nil)
  command-execute(ert-results-rerun-test-at-point-debugging-errors)

[-- Attachment #3: Type: text/plain, Size: 2705 bytes --]



In GNU Emacs 25.1.50.8 (x86_64-apple-darwin15.6.0, NS appkit-1404.47 Version 10.11.6 (Build 15G1004))
 of 2016-09-09 built on rainbow.local
Windowing system distributor 'Apple', version 10.3.1404
Recent messages:
For information about GNU Emacs and the GNU system, type C-h C-a.
You can run the command ‘eval-buffer’ with M-x ev-b RET
Ran 1 tests, 1 results were as expected
Edebug: test@should-error-bug
Edebug: my-error
You can run the command ‘testcover-start’ with M-x tes-s RET
Edebug: my-error
Ran 1 tests, 0 results were as expected, 1 unexpected

Configured using:
 'configure --with-ns --without-gnutls'

Configured features:
JPEG IMAGEMAGICK NOTIFY ACL LIBXML2 ZLIB TOOLKIT_SCROLL_BARS NS

Important settings:
  value of $LANG: en_US.UTF-8
  locale-coding-system: utf-8-unix

Major mode: ERT-Results

Minor modes in effect:
  tooltip-mode: t
  global-eldoc-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  tool-bar-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  buffer-read-only: t
  line-number-mode: t
  transient-mark-mode: t

Load-path shadows:
None found.

Features:
(shadow sort mail-extr emacsbug message subr-x puny dired dired-loaddefs
format-spec rfc822 mml mml-sec password-cache epa derived epg epg-config
gnus-util rmail rmail-loaddefs mm-decode mm-bodies mm-encode mail-parse
rfc2231 mailabbrev gmm-utils mailheader sendmail rfc2047 rfc2045
ietf-drums mm-util mail-prsvr mail-utils cl-seq cl-macs testcover edebug
ert pp find-func seq byte-opt gv bytecomp byte-compile cl-extra
help-mode cconv ewoc easymenu debug cl-loaddefs pcase cl-lib time-date
mule-util tooltip eldoc electric uniquify ediff-hook vc-hooks
lisp-float-type mwheel term/ns-win ns-win ucs-normalize term/common-win
tool-bar dnd fontset image regexp-opt fringe tabulated-list newcomment
elisp-mode lisp-mode prog-mode register page menu-bar rfn-eshadow timer
select scroll-bar mouse jit-lock font-lock syntax facemenu font-core
term/tty-colors frame cl-generic cham georgian utf-8-lang misc-lang
vietnamese tibetan thai tai-viet lao korean japanese eucjp-ms cp51932
hebrew greek romanian slovak czech european ethiopic indian cyrillic
chinese charscript case-table epa-hook jka-cmpr-hook help simple abbrev
obarray minibuffer cl-preloaded nadvice loaddefs button faces cus-face
macroexp files text-properties overlay sha1 md5 base64 format env
code-pages mule custom widget hashtable-print-readable backquote kqueue
cocoa ns multi-tty make-network-process emacs)



^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#24402: More Information
       [not found] ` <handler.24402.B.14734739098199.ack@debbugs.gnu.org>
@ 2016-09-20  4:27   ` Gemini Lasswell
  2017-07-04  3:28     ` bug#24402: should-error doesn't catch all errors (Was:bug#24402: More Information) Alex
  0 siblings, 1 reply; 28+ messages in thread
From: Gemini Lasswell @ 2016-09-20  4:27 UTC (permalink / raw)
  To: 24402

I’ve done some investigating of why this is happening. testcover-start
transforms:
    (should-error (my-error))
into:
    (should-error (testcover-after 2 (my-error)))

Then the macro expansion of should-error separates the form which it
is passed into a function symbol and list of arguments, and applies
the function to the arguments inside of a condition-case that traps
errors. The problem is that the arguments are evaluated first, outside
of the condition-case, so errors in their evaluation do not get
caught. This problem is not specific to testcover. In this example,
the first test passes and the second fails:

(defun div-by (n)
  (/ 100 n))

(defmacro log-div-by (n)
  `(message "div-by: %d" (div-by ,n)))

(ert-deftest test-div-by ()
  (should-error (div-by 0)))

(ert-deftest test-log-div-by ()
  (should-error (log-div-by 0)))
  








^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#24402: should-error doesn't catch all errors (Was:bug#24402: More Information)
  2016-09-20  4:27   ` bug#24402: More Information Gemini Lasswell
@ 2017-07-04  3:28     ` Alex
  2017-07-05  0:00       ` bug#24402: should-error doesn't catch all errors Alex
  0 siblings, 1 reply; 28+ messages in thread
From: Alex @ 2017-07-04  3:28 UTC (permalink / raw)
  To: Gemini Lasswell; +Cc: 24402

tags + 24402 confirmed
quit

Gemini Lasswell <gazally@runbox.com> writes:

> I’ve done some investigating of why this is happening. testcover-start
> transforms:
>     (should-error (my-error))
> into:
>     (should-error (testcover-after 2 (my-error)))
>
> Then the macro expansion of should-error separates the form which it
> is passed into a function symbol and list of arguments, and applies
> the function to the arguments inside of a condition-case that traps
> errors. The problem is that the arguments are evaluated first, outside
> of the condition-case, so errors in their evaluation do not get
> caught. This problem is not specific to testcover. In this example,
> the first test passes and the second fails:
>
> (defun div-by (n)
>   (/ 100 n))
>
> (defmacro log-div-by (n)
>   `(message "div-by: %d" (div-by ,n)))
>
> (ert-deftest test-div-by ()
>   (should-error (div-by 0)))
>
> (ert-deftest test-log-div-by ()
>   (should-error (log-div-by 0)))
>   

I just ran into this as well. Consider these two forms:

(should-error (cl-fourth "1234") :type 'wrong-type-argument)

(should-error (car (cdr (cdr (cdr "1234")))) :type 'wrong-type-argument)

Only the second raises an error, even though cl-fourth is equivalent to
the car/cdr chain.





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#24402: should-error doesn't catch all errors
  2017-07-04  3:28     ` bug#24402: should-error doesn't catch all errors (Was:bug#24402: More Information) Alex
@ 2017-07-05  0:00       ` Alex
  2017-07-05 13:43         ` Tino Calancha
  0 siblings, 1 reply; 28+ messages in thread
From: Alex @ 2017-07-05  0:00 UTC (permalink / raw)
  To: Gemini Lasswell; +Cc: 24402

[-- Attachment #1: Type: text/plain, Size: 1495 bytes --]

tags 24402 patch
quit

Alex <agrambot@gmail.com> writes:

> Gemini Lasswell <gazally@runbox.com> writes:
>
>> I’ve done some investigating of why this is happening. testcover-start
>> transforms:
>>     (should-error (my-error))
>> into:
>>     (should-error (testcover-after 2 (my-error)))
>>
>> Then the macro expansion of should-error separates the form which it
>> is passed into a function symbol and list of arguments, and applies
>> the function to the arguments inside of a condition-case that traps
>> errors. The problem is that the arguments are evaluated first, outside
>> of the condition-case, so errors in their evaluation do not get
>> caught. This problem is not specific to testcover. In this example,
>> the first test passes and the second fails:
>>
>> (defun div-by (n)
>>   (/ 100 n))
>>
>> (defmacro log-div-by (n)
>>   `(message "div-by: %d" (div-by ,n)))
>>
>> (ert-deftest test-div-by ()
>>   (should-error (div-by 0)))
>>
>> (ert-deftest test-log-div-by ()
>>   (should-error (log-div-by 0)))
>>   
>
> I just ran into this as well. Consider these two forms:
>
> (should-error (cl-fourth "1234") :type 'wrong-type-argument)
>
> (should-error (car (cdr (cdr (cdr "1234")))) :type 'wrong-type-argument)
>
> Only the second raises an error, even though cl-fourth is equivalent to
> the car/cdr chain.

Here's a diff that appears to fix this. It's a bit crude, but I'd rather
not mess around too much with ert's internals.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: first --]
[-- Type: text/x-diff, Size: 918 bytes --]

diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el
index 2c49a634e3..f5f3e30c0d 100644
--- a/lisp/emacs-lisp/ert.el
+++ b/lisp/emacs-lisp/ert.el
@@ -303,8 +303,12 @@ ert--expand-should-1
               (args (cl-gensym "args-"))
               (value (cl-gensym "value-"))
               (default-value (cl-gensym "ert-form-evaluation-aborted-")))
-          `(let ((,fn (function ,fn-name))
-                 (,args (list ,@arg-forms)))
+          `(let* ((,fn (function ,fn-name))
+                  (,args (condition-case err
+                             (list ,@arg-forms)
+                           (error (progn (setq ,fn #'signal)
+                                         (list (car err)
+                                               (cdr err)))))))
              (let ((,value ',default-value))
                ,(funcall inner-expander
                          `(setq ,value (apply ,fn ,args))

[-- Attachment #3: Type: text/plain, Size: 254 bytes --]


There's a similar issue with macro-expansions inside of
should/should-error/should-not that could/should be fixed by wrapping
the macroexpand call at the top of ert--expand-should-1 in a similar
condition-case. Here's another diff that does just that:


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #4: second --]
[-- Type: text/x-diff, Size: 2316 bytes --]

diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el
index eb2b2e3e11..66ae31fd51 100644
--- a/lisp/emacs-lisp/ert.el
+++ b/lisp/emacs-lisp/ert.el
@@ -276,13 +276,15 @@ ert--special-operator-p
 (defun ert--expand-should-1 (whole form inner-expander)
   "Helper function for the `should' macro and its variants."
   (let ((form
-         (macroexpand form (append (bound-and-true-p
-                                    byte-compile-macro-environment)
-                                   (cond
-                                    ((boundp 'macroexpand-all-environment)
-                                     macroexpand-all-environment)
-                                    ((boundp 'cl-macro-environment)
-                                     cl-macro-environment))))))
+         (condition-case err
+             (macroexpand-all form (append (bound-and-true-p
+                                            byte-compile-macro-environment)
+                                           (cond
+                                            ((boundp 'macroexpand-all-environment)
+                                             macroexpand-all-environment)
+                                            ((boundp 'cl-macro-environment)
+                                             cl-macro-environment))))
+           (error `(signal ',(car err) ',(cdr err))))))
     (cond
      ((or (atom form) (ert--special-operator-p (car form)))
       (let ((value (cl-gensym "value-")))
@@ -303,8 +305,13 @@ ert--expand-should-1
               (args (cl-gensym "args-"))
               (value (cl-gensym "value-"))
               (default-value (cl-gensym "ert-form-evaluation-aborted-")))
-          `(let ((,fn (function ,fn-name))
-                 (,args (list ,@arg-forms)))
+          `(let* ((,fn (function ,fn-name))
+                  (,args (condition-case err
+                             (list ,@arg-forms)
+                           ;; (ert-test-failed (signal (car err) (cdr err)))
+                           (error (progn (setq ,fn #'signal)
+                                         (list (car err)
+                                               (cdr err)))))))
              (let ((,value ',default-value))
                ,(funcall inner-expander
                          `(setq ,value (apply ,fn ,args))

[-- Attachment #5: Type: text/plain, Size: 622 bytes --]


I ran "make check" and found only one test that the above diff breaks:
ert-test-test-result-expected-p.

I can't seem to figure out why it doesn't work. The test fails because
of these two:

(let ((test (make-ert-test :body (lambda () (ert-fail "failed")))))
  (should-not (ert-test-result-expected-p test (ert-run-test test))))
(let ((test (make-ert-test :body (lambda () (ert-fail "failed"))
                           :expected-result-type ':failed)))
  (should (ert-test-result-expected-p test (ert-run-test test))))

I tried to re-throw the ert-test-failed signal and still the above two
forms raise error an error.

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* bug#24402: should-error doesn't catch all errors
  2017-07-05  0:00       ` bug#24402: should-error doesn't catch all errors Alex
@ 2017-07-05 13:43         ` Tino Calancha
  2017-07-05 19:56           ` Alex
  0 siblings, 1 reply; 28+ messages in thread
From: Tino Calancha @ 2017-07-05 13:43 UTC (permalink / raw)
  To: Alex; +Cc: Gemini Lasswell, 24402

Alex <agrambot@gmail.com> writes:

> I ran "make check" and found only one test that the above diff breaks:
> ert-test-test-result-expected-p.
>
> I can't seem to figure out why it doesn't work. The test fails because
> of these two:
>
> (let ((test (make-ert-test :body (lambda () (ert-fail "failed")))))
>   (should-not (ert-test-result-expected-p test (ert-run-test test))))
> (let ((test (make-ert-test :body (lambda () (ert-fail "failed"))
>                            :expected-result-type ':failed)))
>   (should (ert-test-result-expected-p test (ert-run-test test))))
>
> I tried to re-throw the ert-test-failed signal and still the above two
> forms raise error an error.

Hi!
I just arrived from teletransportation from Bug#27559.  Very fast! (and
cheap!).

Thank you for looking on this.  I think you go in the right direction to
fix this problem.

* I have updated your patch and all the test suite pass (even your
  proposed tests in Bug#27559 without requiring "(eval '....)").

* Bear in mind that I am far to be an expert on `ert.el', and i am
  already in my second beer, so please double check that
  the patch have sense.
  
--8<-----------------------------cut here---------------start------------->8---
commit a07f99f062f3da3418060ef30e1a00030fa0b947
Author: Tino Calancha <tino.calancha@gmail.com>
Date:   Wed Jul 5 22:11:46 2017 +0900

    Tweak Alex's 2nd patch

diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el
index eb2b2e3e11..2d131cf99e 100644
--- a/lisp/emacs-lisp/ert.el
+++ b/lisp/emacs-lisp/ert.el
@@ -276,13 +276,15 @@ ert--special-operator-p
 (defun ert--expand-should-1 (whole form inner-expander)
   "Helper function for the `should' macro and its variants."
   (let ((form
-         (macroexpand form (append (bound-and-true-p
-                                    byte-compile-macro-environment)
-                                   (cond
-                                    ((boundp 'macroexpand-all-environment)
-                                     macroexpand-all-environment)
-                                    ((boundp 'cl-macro-environment)
-                                     cl-macro-environment))))))
+         (condition-case err
+             (macroexpand-all form (append (bound-and-true-p
+                                            byte-compile-macro-environment)
+                                           (cond
+                                            ((boundp 'macroexpand-all-environment)
+                                             macroexpand-all-environment)
+                                            ((boundp 'cl-macro-environment)
+                                             cl-macro-environment))))
+           (error `(signal ',(car err) ',(cdr err))))))
     (cond
      ((or (atom form) (ert--special-operator-p (car form)))
       (let ((value (cl-gensym "value-")))
@@ -303,8 +305,14 @@ ert--expand-should-1
               (args (cl-gensym "args-"))
               (value (cl-gensym "value-"))
               (default-value (cl-gensym "ert-form-evaluation-aborted-")))
-          `(let ((,fn (function ,fn-name))
-                 (,args (list ,@arg-forms)))
+          `(let* ((,fn (function ,fn-name))
+                  (,args (condition-case err
+                             (list ,@arg-forms)
+                           (error (if (or (eq (car err) 'ert-test-failed)
+                                          (eq (car err) 'ert-test-skipped))
+                                      (list ,@arg-forms)
+                                    (setq ,fn #'signal)
+                                    (list (car err) (cdr err)))))))
              (let ((,value ',default-value))
                ,(funcall inner-expander
                          `(setq ,value (apply ,fn ,args))
--8<-----------------------------cut here---------------end--------------->8---
In GNU Emacs 26.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.22.11)
 of 2017-07-05
Repository revision: 5d62247323f53f3ae9c7d9f51e951635887b2fb6





^ permalink raw reply related	[flat|nested] 28+ messages in thread

* bug#24402: should-error doesn't catch all errors
  2017-07-05 13:43         ` Tino Calancha
@ 2017-07-05 19:56           ` Alex
  2017-07-07 10:15             ` Tino Calancha
  2017-07-11 12:18             ` npostavs
  0 siblings, 2 replies; 28+ messages in thread
From: Alex @ 2017-07-05 19:56 UTC (permalink / raw)
  To: Tino Calancha; +Cc: Gemini Lasswell, 24402

Tino Calancha <tino.calancha@gmail.com> writes:

> Hi!
> I just arrived from teletransportation from Bug#27559.  Very fast! (and
> cheap!).
>
> Thank you for looking on this.  I think you go in the right direction to
> fix this problem.
>
> * I have updated your patch and all the test suite pass (even your
>   proposed tests in Bug#27559 without requiring "(eval '....)").
>
> * Bear in mind that I am far to be an expert on `ert.el', and i am
>   already in my second beer, so please double check that
>   the patch have sense.
>   
>
> commit a07f99f062f3da3418060ef30e1a00030fa0b947
> Author: Tino Calancha <tino.calancha@gmail.com>
> Date:   Wed Jul 5 22:11:46 2017 +0900
>
>     Tweak Alex's 2nd patch
>
> diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el
> index eb2b2e3e11..2d131cf99e 100644
> --- a/lisp/emacs-lisp/ert.el
> +++ b/lisp/emacs-lisp/ert.el
> @@ -276,13 +276,15 @@ ert--special-operator-p
>  (defun ert--expand-should-1 (whole form inner-expander)
>    "Helper function for the `should' macro and its variants."
>    (let ((form
> -         (macroexpand form (append (bound-and-true-p
> -                                    byte-compile-macro-environment)
> -                                   (cond
> -                                    ((boundp 'macroexpand-all-environment)
> -                                     macroexpand-all-environment)
> -                                    ((boundp 'cl-macro-environment)
> -                                     cl-macro-environment))))))
> +         (condition-case err
> +             (macroexpand-all form (append (bound-and-true-p
> +                                            byte-compile-macro-environment)
> +                                           (cond
> +                                            ((boundp 'macroexpand-all-environment)
> +                                             macroexpand-all-environment)
> +                                            ((boundp 'cl-macro-environment)
> +                                             cl-macro-environment))))
> +           (error `(signal ',(car err) ',(cdr err))))))
>      (cond
>       ((or (atom form) (ert--special-operator-p (car form)))
>        (let ((value (cl-gensym "value-")))
> @@ -303,8 +305,14 @@ ert--expand-should-1
>                (args (cl-gensym "args-"))
>                (value (cl-gensym "value-"))
>                (default-value (cl-gensym "ert-form-evaluation-aborted-")))
> -          `(let ((,fn (function ,fn-name))
> -                 (,args (list ,@arg-forms)))
> +          `(let* ((,fn (function ,fn-name))
> +                  (,args (condition-case err
> +                             (list ,@arg-forms)
> +                           (error (if (or (eq (car err) 'ert-test-failed)
> +                                          (eq (car err) 'ert-test-skipped))
> +                                      (list ,@arg-forms)
> +                                    (setq ,fn #'signal)
> +                                    (list (car err) (cdr err)))))))
>               (let ((,value ',default-value))
>                 ,(funcall inner-expander
>                           `(setq ,value (apply ,fn ,args))

Thanks, that helps with my understanding of the issue. Sadly, I don't
think your tweak will work in all cases, namely whenever (list
,@arg-forms) has side-effects. Luckily this doesn't happen in any
current tests, but I think those types of tests should be supported.

I believe the following is why my previous diff doesn't work. Consider:

(let ((test (make-ert-test :body (lambda () (ert-fail "failed")))))
  (ert-run-test test))

The above returns a struct/record and does not error.

(let ((test (make-ert-test :body (lambda () (ert-fail "failed")))))
  (condition-case err
      (ert-run-test test)
    (error "woops")))

Even though ert-run-test by itself does not error, the error handler is
ran. I believe this is because `ert--run-test-internal' binds `debugger'
around the evaluation of the test to somehow suppress this error.

Using condition-case-unless-debug gets around this, but now anytime
debug-on-error is non-nil the condition-case won't catch the error. I'm
not sure how to solve this.





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#24402: should-error doesn't catch all errors
  2017-07-05 19:56           ` Alex
@ 2017-07-07 10:15             ` Tino Calancha
  2017-07-09  7:04               ` Alex
  2017-07-11 12:18             ` npostavs
  1 sibling, 1 reply; 28+ messages in thread
From: Tino Calancha @ 2017-07-07 10:15 UTC (permalink / raw)
  To: Alex; +Cc: Gemini Lasswell, 24402

Alex <agrambot@gmail.com> writes:

> I don't think your tweak will work in all cases, namely whenever
> (list  ,@arg-forms) has side-effects. Luckily this doesn't happen in any
> current tests, but I think those types of tests should be supported.
Good point.

> I believe the following is why my previous diff doesn't work. Consider:
>
> (let ((test (make-ert-test :body (lambda () (ert-fail "failed")))))
>   (ert-run-test test))
>
> The above returns a struct/record and does not error.
>
> (let ((test (make-ert-test :body (lambda () (ert-fail "failed")))))
>   (condition-case err
>       (ert-run-test test)
>     (error "woops")))
>
> Even though ert-run-test by itself does not error, the error handler is
> ran. I believe this is because `ert--run-test-internal' binds `debugger'
> around the evaluation of the test to somehow suppress this error.
>
> Using condition-case-unless-debug gets around this, but now anytime
> debug-on-error is non-nil the condition-case won't catch the error. I'm
> not sure how to solve this.
I've being thinking about this, and i cannot find something better than
your second patch.

My suggestion is:

1. We apply your 2nd patch.
2. We ammend the failing tests wrapping '> I don't think your tweak will work in all cases, namely whenever
> (list  ,@arg-forms) has side-effects. Luckily this doesn't happen in any
> current tests, but I think those types of tests should be supported.
Good point.

> I believe the following is why my previous diff doesn't work. Consider:
>
> (let ((test (make-ert-test :body (lambda () (ert-fail "failed")))))
>   (ert-run-test test))
>
> The above returns a struct/record and does not error.
>
> (let ((test (make-ert-test :body (lambda () (ert-fail "failed")))))
>   (condition-case err
>       (ert-run-test test)
>     (error "woops")))
>
> Even though ert-run-test by itself does not error, the error handler is
> ran. I believe this is because `ert--run-test-internal' binds `debugger'
> around the evaluation of the test to somehow suppress this error.
>
> Using condition-case-unless-debug gets around this, but now anytime
> debug-on-error is non-nil the condition-case won't catch the error. I'm
> not sure how to solve this.
I've being thinking about this, and i cannot find something better than
your second patch.

My suggestion is:

1. We apply your 2nd patch.
2. We handle the failing tests wrapping '(ert-fail "failed")' into
  `ignore-errors' as in below patch.

Then, IMO we are in a better situation than we are know:
That fix this bug, and if i am nt missing something, at a low price: just
tweaking a bit 2 innocents tests.

What do you think?


--8<-----------------------------cut here---------------start------------->8---

diff --git a/test/lisp/emacs-lisp/ert-tests.el b/test/lisp/emacs-lisp/ert-tests.el
index 317838b250..f3e4db192a 100644
--- a/test/lisp/emacs-lisp/ert-tests.el
+++ b/test/lisp/emacs-lisp/ert-tests.el
@@ -413,12 +413,14 @@ ert-test--which-file
   (let ((test (make-ert-test :body (lambda ()))))
     (should (ert-test-result-expected-p test (ert-run-test test))))
   ;; unexpected failure
-  (let ((test (make-ert-test :body (lambda () (ert-fail "failed")))))
-    (should-not (ert-test-result-expected-p test (ert-run-test test))))
-  ;; expected failure
-  (let ((test (make-ert-test :body (lambda () (ert-fail "failed"))
-                             :expected-result-type ':failed)))
+  (let ((test (make-ert-test
+               :body (lambda () (ignore-errors (ert-fail "failed"))))))
     (should (ert-test-result-expected-p test (ert-run-test test))))
+  ;; expected failure
+  (let ((test (make-ert-test
+               :body (lambda () (ignore-errors (ert-fail "failed")))
+               :expected-result-type ':failed)))
+    (should-not (ert-test-result-expected-p test (ert-run-test test))))
   ;; `not' expected type
   (let ((test (make-ert-test :body (lambda ())
                              :expected-result-type '(not :failed))))
--8<-----------------------------cut here---------------end--------------->8---





^ permalink raw reply related	[flat|nested] 28+ messages in thread

* bug#24402: should-error doesn't catch all errors
  2017-07-07 10:15             ` Tino Calancha
@ 2017-07-09  7:04               ` Alex
  0 siblings, 0 replies; 28+ messages in thread
From: Alex @ 2017-07-09  7:04 UTC (permalink / raw)
  To: Tino Calancha; +Cc: Gemini Lasswell, 24402, npostavs

Tino Calancha <tino.calancha@gmail.com> writes:

> I've being thinking about this, and i cannot find something better than
> your second patch.
>
> My suggestion is:
>
> 1. We apply your 2nd patch.
> 2. We handle the failing tests wrapping '(ert-fail "failed")' into
>   `ignore-errors' as in below patch.
>
> Then, IMO we are in a better situation than we are know:
> That fix this bug, and if i am nt missing something, at a low price: just
> tweaking a bit 2 innocents tests.
>
> What do you think?
>
>
> diff --git a/test/lisp/emacs-lisp/ert-tests.el b/test/lisp/emacs-lisp/ert-tests.el
> index 317838b250..f3e4db192a 100644
> --- a/test/lisp/emacs-lisp/ert-tests.el
> +++ b/test/lisp/emacs-lisp/ert-tests.el
> @@ -413,12 +413,14 @@ ert-test--which-file
>    (let ((test (make-ert-test :body (lambda ()))))
>      (should (ert-test-result-expected-p test (ert-run-test test))))
>    ;; unexpected failure
> -  (let ((test (make-ert-test :body (lambda () (ert-fail "failed")))))
> -    (should-not (ert-test-result-expected-p test (ert-run-test test))))
> -  ;; expected failure
> -  (let ((test (make-ert-test :body (lambda () (ert-fail "failed"))
> -                             :expected-result-type ':failed)))
> +  (let ((test (make-ert-test
> +               :body (lambda () (ignore-errors (ert-fail "failed"))))))
>      (should (ert-test-result-expected-p test (ert-run-test test))))
> +  ;; expected failure
> +  (let ((test (make-ert-test
> +               :body (lambda () (ignore-errors (ert-fail "failed")))
> +               :expected-result-type ':failed)))
> +    (should-not (ert-test-result-expected-p test (ert-run-test test))))
>    ;; `not' expected type
>    (let ((test (make-ert-test :body (lambda ())
>                               :expected-result-type '(not :failed))))

I agree that it's a low price, and that it fixes more than it breaks,
but it does involve switching the logic in a simple basic test.

Also note that ignore-errors expands into a condition-case, so instead
of changing the tests, the patch could be tweaked to return nil if the
test signals ert-test-{failed, skipped}. Or the two tests could use
condition-case directly and make sure that ert-test-failed is/isn't
signalled.

I'd like to get some more opinions on this bug, in the hopes that
there's a better solution. Eli/Noam (or anyone happening upon this), do
you have any ideas on how to solve this?





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#24402: should-error doesn't catch all errors
  2017-07-05 19:56           ` Alex
  2017-07-07 10:15             ` Tino Calancha
@ 2017-07-11 12:18             ` npostavs
  2017-07-12  3:47               ` Alex
  1 sibling, 1 reply; 28+ messages in thread
From: npostavs @ 2017-07-11 12:18 UTC (permalink / raw)
  To: Alex; +Cc: Gemini Lasswell, Tino Calancha, 24402

Alex <agrambot@gmail.com> writes:

> I believe the following is why my previous diff doesn't work. Consider:
>
> (let ((test (make-ert-test :body (lambda () (ert-fail "failed")))))
>   (ert-run-test test))
>
> The above returns a struct/record and does not error.
>
> (let ((test (make-ert-test :body (lambda () (ert-fail "failed")))))
>   (condition-case err
>       (ert-run-test test)
>     (error "woops")))
>
> Even though ert-run-test by itself does not error, the error handler is
> ran. I believe this is because `ert--run-test-internal' binds `debugger'
> around the evaluation of the test to somehow suppress this error.

Yes, ert binds `debugger' in order to get full backtrace information
when there is an error.  This means it won't see errors caught by
condition-case.  That's good when it ignores errors caught by test code
using condition-case, but does give rise to problems.  There is some
relevant discussion in Bugs #11218 and #24617.

Espcially the suggestion in #24617 of using `signal-hook-function' to
record error info instead of using `debugger', I think doing this could
simplify things a lot.  It is definitely going to require messing around
with ert's internals though...





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#24402: should-error doesn't catch all errors
  2017-07-11 12:18             ` npostavs
@ 2017-07-12  3:47               ` Alex
  2017-07-12 12:30                 ` npostavs
  0 siblings, 1 reply; 28+ messages in thread
From: Alex @ 2017-07-12  3:47 UTC (permalink / raw)
  To: npostavs; +Cc: Gemini Lasswell, Tino Calancha, 24402

[-- Attachment #1: Type: text/plain, Size: 873 bytes --]

npostavs@users.sourceforge.net writes:

> Yes, ert binds `debugger' in order to get full backtrace information
> when there is an error.  This means it won't see errors caught by
> condition-case.  That's good when it ignores errors caught by test code
> using condition-case, but does give rise to problems.  There is some
> relevant discussion in Bugs #11218 and #24617.
>
> Espcially the suggestion in #24617 of using `signal-hook-function' to
> record error info instead of using `debugger', I think doing this could
> simplify things a lot.  It is definitely going to require messing around
> with ert's internals though...

Thanks for the info. I may have discovered a workaround, but I'm not
sure if there's any negative side-effects. All the tests pass, though.

What do you think of it? It's obviously not ideal, but I think it at
least fixes the issues at hand.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: v3 --]
[-- Type: text/x-diff, Size: 3815 bytes --]

diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el
index eb2b2e3e11..beb32c48ce 100644
--- a/lisp/emacs-lisp/ert.el
+++ b/lisp/emacs-lisp/ert.el
@@ -266,6 +266,14 @@ ert--signal-should-execution
   (when ert--should-execution-observer
     (funcall ert--should-execution-observer form-description)))
 
+;; See Bug#24402 for why this exists
+(defun ert--signal-hook (error-symbol data)
+  "Stupid hack to stop `condition-case' from catching ert signals.
+It should only be stopped when ran from inside ert--run-test-internal."
+  (when (and (not (symbolp debugger))   ; only run on anonymous procedures
+             (memq error-symbol '(ert-test-failed ert-test-skipped)))
+    (funcall debugger 'error data)))
+
 (defun ert--special-operator-p (thing)
   "Return non-nil if THING is a symbol naming a special operator."
   (and (symbolp thing)
@@ -276,13 +284,15 @@ ert--special-operator-p
 (defun ert--expand-should-1 (whole form inner-expander)
   "Helper function for the `should' macro and its variants."
   (let ((form
-         (macroexpand form (append (bound-and-true-p
-                                    byte-compile-macro-environment)
-                                   (cond
-                                    ((boundp 'macroexpand-all-environment)
-                                     macroexpand-all-environment)
-                                    ((boundp 'cl-macro-environment)
-                                     cl-macro-environment))))))
+         (condition-case err
+             (macroexpand-all form (append (bound-and-true-p
+                                            byte-compile-macro-environment)
+                                           (cond
+                                            ((boundp 'macroexpand-all-environment)
+                                             macroexpand-all-environment)
+                                            ((boundp 'cl-macro-environment)
+                                             cl-macro-environment))))
+           (error `(signal ',(car err) ',(cdr err))))))
     (cond
      ((or (atom form) (ert--special-operator-p (car form)))
       (let ((value (cl-gensym "value-")))
@@ -303,8 +313,13 @@ ert--expand-should-1
               (args (cl-gensym "args-"))
               (value (cl-gensym "value-"))
               (default-value (cl-gensym "ert-form-evaluation-aborted-")))
-          `(let ((,fn (function ,fn-name))
-                 (,args (list ,@arg-forms)))
+          `(let* ((,fn (function ,fn-name))
+                  (,args (condition-case err
+                             (let ((signal-hook-function #'ert--signal-hook))
+                               (list ,@arg-forms))
+                           (error (progn (setq ,fn #'signal)
+                                         (list (car err)
+                                               (cdr err)))))))
              (let ((,value ',default-value))
                ,(funcall inner-expander
                          `(setq ,value (apply ,fn ,args))
diff --git a/test/lisp/emacs-lisp/ert-tests.el b/test/lisp/emacs-lisp/ert-tests.el
index 317838b250..b6a7eb68da 100644
--- a/test/lisp/emacs-lisp/ert-tests.el
+++ b/test/lisp/emacs-lisp/ert-tests.el
@@ -294,6 +294,15 @@ ert-self-test-and-exit
                   "the error signaled was a subtype of the expected type")))))
     ))
 
+(ert-deftest ert-test-should-error-argument ()
+  "Errors due to evaluating arguments should not break tests."
+  (should-error (identity (/ 1 0))))
+
+(ert-deftest ert-test-should-error-macroexpansion ()
+  "Errors due to expanding macros should not break tests."
+  (cl-macrolet ((test () (error "Foo")))
+    (should-error (test))))
+
 (ert-deftest ert-test-skip-unless ()
   ;; Don't skip.
   (let ((test (make-ert-test :body (lambda () (skip-unless t)))))

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* bug#24402: should-error doesn't catch all errors
  2017-07-12  3:47               ` Alex
@ 2017-07-12 12:30                 ` npostavs
  2017-07-12 16:45                   ` Alex
  0 siblings, 1 reply; 28+ messages in thread
From: npostavs @ 2017-07-12 12:30 UTC (permalink / raw)
  To: Alex; +Cc: Gemini Lasswell, 24402, Tino Calancha

Alex <agrambot@gmail.com> writes:

> npostavs@users.sourceforge.net writes:
>
>> Yes, ert binds `debugger' in order to get full backtrace information
>> when there is an error.  This means it won't see errors caught by
>> condition-case.  That's good when it ignores errors caught by test code
>> using condition-case, but does give rise to problems.  There is some
>> relevant discussion in Bugs #11218 and #24617.
>>
>> Espcially the suggestion in #24617 of using `signal-hook-function' to
>> record error info instead of using `debugger', I think doing this could
>> simplify things a lot.  It is definitely going to require messing around
>> with ert's internals though...
>
> Thanks for the info. I may have discovered a workaround, but I'm not
> sure if there's any negative side-effects. All the tests pass, though.
>
> What do you think of it? It's obviously not ideal, but I think it at
> least fixes the issues at hand.

Does it also work when loading the elc version of the test file?  (try
'make check TEST_LOAD_EL=no')

What about tests like this?

    (ert-deftest check-error-handling ()
      (should
       (eq 42
           (condition-case ()
               (/ 1 0)
             (arith-error 42)))))





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#24402: should-error doesn't catch all errors
  2017-07-12 12:30                 ` npostavs
@ 2017-07-12 16:45                   ` Alex
  2017-07-13  1:31                     ` npostavs
  0 siblings, 1 reply; 28+ messages in thread
From: Alex @ 2017-07-12 16:45 UTC (permalink / raw)
  To: npostavs; +Cc: Gemini Lasswell, 24402, Tino Calancha

npostavs@users.sourceforge.net writes:

> Alex <agrambot@gmail.com> writes:
>
>> npostavs@users.sourceforge.net writes:
>>
>>> Yes, ert binds `debugger' in order to get full backtrace information
>>> when there is an error.  This means it won't see errors caught by
>>> condition-case.  That's good when it ignores errors caught by test code
>>> using condition-case, but does give rise to problems.  There is some
>>> relevant discussion in Bugs #11218 and #24617.
>>>
>>> Espcially the suggestion in #24617 of using `signal-hook-function' to
>>> record error info instead of using `debugger', I think doing this could
>>> simplify things a lot.  It is definitely going to require messing around
>>> with ert's internals though...
>>
>> Thanks for the info. I may have discovered a workaround, but I'm not
>> sure if there's any negative side-effects. All the tests pass, though.
>>
>> What do you think of it? It's obviously not ideal, but I think it at
>> least fixes the issues at hand.
>
> Does it also work when loading the elc version of the test file?  (try
> 'make check TEST_LOAD_EL=no')

Oh, it doesn't load the elc version by default? That's surprising; I
think that should be documented in the test README.

I get 3 test failures with TEST_LOAD_EL=no, but I don't believe they're
because of me. On a mostly clean master (d014a5e15) those 3 also error.
One of them is simple to fix (the (require 'subr-x) should not be inside
eval-when-compile in dom-tests). The other failing tests are
subr-test-backtrace-integration-test and cl-lib-defstruct-record.

> What about tests like this?
>
>     (ert-deftest check-error-handling ()
>       (should
>        (eq 42
>            (condition-case ()
>                (/ 1 0)
>              (arith-error 42)))))

It works for me, yes. As long as `debugger' is set to a symbol. I can
make it a bit more robust by using an additional defvar in
ert--run-test-internal.

Are you asking because it doesn't work for you?





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#24402: should-error doesn't catch all errors
  2017-07-12 16:45                   ` Alex
@ 2017-07-13  1:31                     ` npostavs
  2017-07-13  3:04                       ` Alex
  0 siblings, 1 reply; 28+ messages in thread
From: npostavs @ 2017-07-13  1:31 UTC (permalink / raw)
  To: Alex; +Cc: Gemini Lasswell, 24402, Tino Calancha

Alex <agrambot@gmail.com> writes:

> npostavs@users.sourceforge.net writes:
>
>> Does it also work when loading the elc version of the test file?  (try
>> 'make check TEST_LOAD_EL=no')
>
> Oh, it doesn't load the elc version by default? That's surprising; I
> think that should be documented in the test README.
>
> I get 3 test failures with TEST_LOAD_EL=no, but I don't believe they're
> because of me. On a mostly clean master (d014a5e15) those 3 also error.
> One of them is simple to fix (the (require 'subr-x) should not be inside
> eval-when-compile in dom-tests).

Ah, the `should' blocks inlining during compilation.  Is that necessary?
Probably yes if we expect to catch errors during macroexpansion I guess.

> The other failing tests are
> subr-test-backtrace-integration-test and cl-lib-defstruct-record.

Hmm, I'll see if I can fix these.

>> What about tests like this?
>>
>>     (ert-deftest check-error-handling ()
>>       (should
>>        (eq 42
>>            (condition-case ()
>>                (/ 1 0)
>>              (arith-error 42)))))
>
> It works for me, yes. As long as `debugger' is set to a symbol. I can
> make it a bit more robust by using an additional defvar in
> ert--run-test-internal.
>
> Are you asking because it doesn't work for you?

No, I'm just trying to explore the edges of this solution.  Isn't
`debugger' bound to a non-symbol while running the the tests?  I'm
confused as to why this solution works.





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#24402: should-error doesn't catch all errors
  2017-07-13  1:31                     ` npostavs
@ 2017-07-13  3:04                       ` Alex
  2017-07-13  3:44                         ` npostavs
  0 siblings, 1 reply; 28+ messages in thread
From: Alex @ 2017-07-13  3:04 UTC (permalink / raw)
  To: npostavs; +Cc: Gemini Lasswell, 24402, Tino Calancha

[-- Attachment #1: Type: text/plain, Size: 1159 bytes --]

npostavs@users.sourceforge.net writes:

> Alex <agrambot@gmail.com> writes:
>
>> npostavs@users.sourceforge.net writes:
>>
>>> Does it also work when loading the elc version of the test file?  (try
>>> 'make check TEST_LOAD_EL=no')
>>
>> Oh, it doesn't load the elc version by default? That's surprising; I
>> think that should be documented in the test README.
>>
>> I get 3 test failures with TEST_LOAD_EL=no, but I don't believe they're
>> because of me. On a mostly clean master (d014a5e15) those 3 also error.
>> One of them is simple to fix (the (require 'subr-x) should not be inside
>> eval-when-compile in dom-tests).
>
> Ah, the `should' blocks inlining during compilation.  Is that necessary?
> Probably yes if we expect to catch errors during macroexpansion I guess.

Can you get errors by expanding inlined functions?

Macros are expanded at compile-time with the current patch. If there are
any macroexpansion errors, then the form is altered to be (error <type>
<data>). Perhaps inline functions could work similarly.

Here's a diff to my patch that uses byte-compile-inline-expand. This
fixes the dom-tests case. Do you think it's worth it?



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: inline --]
[-- Type: text/x-diff, Size: 2280 bytes --]

diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el
index beb32c48ce..f4d2f725ac 100644
--- a/lisp/emacs-lisp/ert.el
+++ b/lisp/emacs-lisp/ert.el
@@ -281,17 +281,19 @@ ert--special-operator-p
          (and (subrp definition)
               (eql (cdr (subr-arity definition)) 'unevalled)))))
 
+(require 'byte-opt)
+
 (defun ert--expand-should-1 (whole form inner-expander)
   "Helper function for the `should' macro and its variants."
   (let ((form
          (condition-case err
-             (macroexpand-all form (append (bound-and-true-p
-                                            byte-compile-macro-environment)
-                                           (cond
-                                            ((boundp 'macroexpand-all-environment)
-                                             macroexpand-all-environment)
-                                            ((boundp 'cl-macro-environment)
-                                             cl-macro-environment))))
+             (byte-compile-inline-expand (macroexpand-all form (append (bound-and-true-p
+                                                                        byte-compile-macro-environment)
+                                                                       (cond
+                                                                        ((boundp 'macroexpand-all-environment)
+                                                                         macroexpand-all-environment)
+                                                                        ((boundp 'cl-macro-environment)
+                                                                         cl-macro-environment)))))
            (error `(signal ',(car err) ',(cdr err))))))
     (cond
      ((or (atom form) (ert--special-operator-p (car form)))
@@ -308,7 +310,8 @@ ert--expand-should-1
         (cl-assert (or (symbolp fn-name)
                        (and (consp fn-name)
                             (eql (car fn-name) 'lambda)
-                            (listp (cdr fn-name)))))
+                            (listp (cdr fn-name)))
+                       (byte-code-function-p fn-name)))
         (let ((fn (cl-gensym "fn-"))
               (args (cl-gensym "args-"))
               (value (cl-gensym "value-"))

[-- Attachment #3: Type: text/plain, Size: 1607 bytes --]


>> The other failing tests are
>> subr-test-backtrace-integration-test and cl-lib-defstruct-record.
>
> Hmm, I'll see if I can fix these.

Thanks. I noticed when byte-compiling cl-lib-tests, I got this warning:
Unused lexical variable ‘cl-struct-foo’.

>>> What about tests like this?
>>>
>>>     (ert-deftest check-error-handling ()
>>>       (should
>>>        (eq 42
>>>            (condition-case ()
>>>                (/ 1 0)
>>>              (arith-error 42)))))
>>
>> It works for me, yes. As long as `debugger' is set to a symbol. I can
>> make it a bit more robust by using an additional defvar in
>> ert--run-test-internal.
>>
>> Are you asking because it doesn't work for you?
>
> No, I'm just trying to explore the edges of this solution.  Isn't
> `debugger' bound to a non-symbol while running the the tests?  I'm
> confused as to why this solution works.

Yes, that's why there's the second test that checks for error-symbol to
be ert-test-{failed, skipped}. Basically what's happening is that
ert--signal-hook forces the debugger to trigger even inside a
condition-case, but only with a non-symbol `debugger' (since
ert--run-test-internal binds it to a closure), and one of the above two
errors.

The only time this approach fails is when you bind `debugger' to a
non-symbol and also signal ert-test-{failed, skipped}.

This is relatively rare compared to the problems at hand (macro and
argument errors), so unless there are unforeseen issues I think it's an
acceptable stop-gap solution. Hopefully Someone™ can properly fix this
eventually.

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* bug#24402: should-error doesn't catch all errors
  2017-07-13  3:04                       ` Alex
@ 2017-07-13  3:44                         ` npostavs
  2017-07-13 22:45                           ` Alex
  0 siblings, 1 reply; 28+ messages in thread
From: npostavs @ 2017-07-13  3:44 UTC (permalink / raw)
  To: Alex; +Cc: Gemini Lasswell, 24402, Tino Calancha

Alex <agrambot@gmail.com> writes:

>>> I get 3 test failures with TEST_LOAD_EL=no, but I don't believe they're
>>> because of me. On a mostly clean master (d014a5e15) those 3 also error.
>>> One of them is simple to fix (the (require 'subr-x) should not be inside
>>> eval-when-compile in dom-tests).
>>
>> Ah, the `should' blocks inlining during compilation.  Is that necessary?
>> Probably yes if we expect to catch errors during macroexpansion I guess.
>
> Can you get errors by expanding inlined functions?

Yes I think so, probably not from defsubst (except for wrong number of
arguments maybe?), but I believe define-inline basically lets you run an
arbitrary macro to produce the inlined call.

> Macros are expanded at compile-time with the current patch. If there are
> any macroexpansion errors, then the form is altered to be (error <type>
> <data>). Perhaps inline functions could work similarly.
>
> Here's a diff to my patch that uses byte-compile-inline-expand. This
> fixes the dom-tests case. Do you think it's worth it?

It would be nice if we can make code inside tests behave the same as
outside.  But we should make it conditional on whether the code is being
compiled, otherwise code inside tests would behave differently when
being interpreted.  Anyway, we can leave this for a separate bug.

> Yes, that's why there's the second test that checks for error-symbol to
> be ert-test-{failed, skipped}. Basically what's happening is that
> ert--signal-hook forces the debugger to trigger even inside a
> condition-case, but only with a non-symbol `debugger' (since
> ert--run-test-internal binds it to a closure), and one of the above two
> errors.
>
> The only time this approach fails is when you bind `debugger' to a
> non-symbol and also signal ert-test-{failed, skipped}.

Okay, it sounds like we would only hit problems when running an ert test
from inside an ert test.  That should be pretty rare outside of ert's
test suite, and we already have workarounds for that case, right?

> This is relatively rare compared to the problems at hand (macro and
> argument errors), so unless there are unforeseen issues I think it's an
> acceptable stop-gap solution. Hopefully Someone™ can properly fix this
> eventually.

Yes, I think this approach is acceptable.






^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#24402: should-error doesn't catch all errors
  2017-07-13  3:44                         ` npostavs
@ 2017-07-13 22:45                           ` Alex
  2017-07-13 23:49                             ` npostavs
  0 siblings, 1 reply; 28+ messages in thread
From: Alex @ 2017-07-13 22:45 UTC (permalink / raw)
  To: npostavs; +Cc: Gemini Lasswell, 24402, Tino Calancha

[-- Attachment #1: Type: text/plain, Size: 2421 bytes --]

npostavs@users.sourceforge.net writes:

> Alex <agrambot@gmail.com> writes:
>
>> Macros are expanded at compile-time with the current patch. If there are
>> any macroexpansion errors, then the form is altered to be (error <type>
>> <data>). Perhaps inline functions could work similarly.
>>
>> Here's a diff to my patch that uses byte-compile-inline-expand. This
>> fixes the dom-tests case. Do you think it's worth it?
>
> It would be nice if we can make code inside tests behave the same as
> outside.  But we should make it conditional on whether the code is being
> compiled, otherwise code inside tests would behave differently when
> being interpreted.  Anyway, we can leave this for a separate bug.

I agree, but that sounds like it'll require a fair bit of refactoring
and knowledge of ert internals.

OOC, is there a robust way to check whether or not you're currently
byte-compiling?

>> Yes, that's why there's the second test that checks for error-symbol to
>> be ert-test-{failed, skipped}. Basically what's happening is that
>> ert--signal-hook forces the debugger to trigger even inside a
>> condition-case, but only with a non-symbol `debugger' (since
>> ert--run-test-internal binds it to a closure), and one of the above two
>> errors.
>>
>> The only time this approach fails is when you bind `debugger' to a
>> non-symbol and also signal ert-test-{failed, skipped}.
>
> Okay, it sounds like we would only hit problems when running an ert test
> from inside an ert test.  That should be pretty rare outside of ert's
> test suite, and we already have workarounds for that case, right?

I tried a nested case using two ert-deftests and it worked, so it looks
okay here too.

>> This is relatively rare compared to the problems at hand (macro and
>> argument errors), so unless there are unforeseen issues I think it's an
>> acceptable stop-gap solution. Hopefully Someone™ can properly fix this
>> eventually.
>
> Yes, I think this approach is acceptable.

I was going to ask if you would merge in a few days, but it appears that
what should have been a simple rebase to master caused unforeseen
consequences. For instance, for some reason I now get a segmentation
fault when executing 'make cl-lib-tests TEST_LOAD_EL=no'. I even reset
to the commit I was at before and it still segfaults. Can you reproduce
this with the following patch on master?


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: ert --]
[-- Type: text/x-diff, Size: 6080 bytes --]

From fdbf66f73672d9b69fc37273223ae90fff951eb2 Mon Sep 17 00:00:00 2001
From: Alexander Gramiak <agrambot@gmail.com>
Date: Thu, 13 Jul 2017 14:54:35 -0600
Subject: [PATCH] Catch argument and expansion errors in ert

This kludge catches errors caused by evaluating arguments in ert's
should, should-not, and should-error macros; it also catches macro and
inline function expansion errors inside of the above
macros (Bug#24402).

* lisp/emacs-lisp/ert.el: (ert--should-signal-hook): New function.
(ert--expand-should-1): Catch expansion errors.
* test/lisp/emacs-lisp/ert-tests.el (ert-test-should-error-argument)
(ert-test-should-error-macroexpansion): Tests for argument and
expansion errors.
---
 lisp/emacs-lisp/ert.el            | 47 ++++++++++++++++++++++++++++++---------
 test/lisp/emacs-lisp/ert-tests.el |  9 ++++++++
 2 files changed, 46 insertions(+), 10 deletions(-)

diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el
index eb2b2e3e11..c6e3ee8503 100644
--- a/lisp/emacs-lisp/ert.el
+++ b/lisp/emacs-lisp/ert.el
@@ -65,6 +65,7 @@
 (require 'find-func)
 (require 'help)
 (require 'pp)
+(require 'byte-opt) ; for ert--expand-should-1 kludge
 
 ;;; UI customization options.
 
@@ -266,6 +267,14 @@ ert--signal-should-execution
   (when ert--should-execution-observer
     (funcall ert--should-execution-observer form-description)))
 
+;; See Bug#24402 for why this exists
+(defun ert--should-signal-hook (error-symbol data)
+  "Stupid hack to stop `condition-case' from catching ert signals.
+It should only be stopped when ran from inside ert--run-test-internal."
+  (when (and (not (symbolp debugger))   ; only run on anonymous debugger
+             (memq error-symbol '(ert-test-failed ert-test-skipped)))
+    (funcall debugger 'error data)))
+
 (defun ert--special-operator-p (thing)
   "Return non-nil if THING is a symbol naming a special operator."
   (and (symbolp thing)
@@ -276,13 +285,20 @@ ert--special-operator-p
 (defun ert--expand-should-1 (whole form inner-expander)
   "Helper function for the `should' macro and its variants."
   (let ((form
-         (macroexpand form (append (bound-and-true-p
-                                    byte-compile-macro-environment)
-                                   (cond
-                                    ((boundp 'macroexpand-all-environment)
-                                     macroexpand-all-environment)
-                                    ((boundp 'cl-macro-environment)
-                                     cl-macro-environment))))))
+         ;; catch all macro and inline function expansion errors
+         ;; FIXME: Code inside of tests should be evaluated like it is
+         ;; outside of tests, with the sole exception of error
+         ;; handling
+         (condition-case err
+             (byte-compile-inline-expand
+              (macroexpand-all form (append (bound-and-true-p
+                                             byte-compile-macro-environment)
+                                            (cond
+                                             ((boundp 'macroexpand-all-environment)
+                                              macroexpand-all-environment)
+                                             ((boundp 'cl-macro-environment)
+                                              cl-macro-environment)))))
+           (error `(signal ',(car err) ',(cdr err))))))
     (cond
      ((or (atom form) (ert--special-operator-p (car form)))
       (let ((value (cl-gensym "value-")))
@@ -298,13 +314,20 @@ ert--expand-should-1
         (cl-assert (or (symbolp fn-name)
                        (and (consp fn-name)
                             (eql (car fn-name) 'lambda)
-                            (listp (cdr fn-name)))))
+                            (listp (cdr fn-name)))
+                       ;; for inline functions
+                       (byte-code-function-p fn-name)))
         (let ((fn (cl-gensym "fn-"))
               (args (cl-gensym "args-"))
               (value (cl-gensym "value-"))
               (default-value (cl-gensym "ert-form-evaluation-aborted-")))
-          `(let ((,fn (function ,fn-name))
-                 (,args (list ,@arg-forms)))
+          `(let* ((,fn (function ,fn-name))
+                  (,args (condition-case err
+                             (let ((signal-hook-function #'ert--should-signal-hook))
+                               (list ,@arg-forms))
+                           (error (progn (setq ,fn #'signal)
+                                         (list (car err)
+                                               (cdr err)))))))
              (let ((,value ',default-value))
                ,(funcall inner-expander
                          `(setq ,value (apply ,fn ,args))
@@ -766,6 +789,10 @@ ert--run-test-internal
     ;; too expensive, we can remove it.
     (with-temp-buffer
       (save-window-excursion
+        ;; FIXME: Use `signal-hook-function' instead of `debugger' to
+        ;; handle ert errors. Once that's done, remove
+        ;; `ert--should-signal-hook'. See Bug#24402 and Bug#11218 for
+        ;; details.
         (let ((debugger (lambda (&rest args)
                           (ert--run-test-debugger test-execution-info
                                                   args)))
diff --git a/test/lisp/emacs-lisp/ert-tests.el b/test/lisp/emacs-lisp/ert-tests.el
index 317838b250..b6a7eb68da 100644
--- a/test/lisp/emacs-lisp/ert-tests.el
+++ b/test/lisp/emacs-lisp/ert-tests.el
@@ -294,6 +294,15 @@ ert-self-test-and-exit
                   "the error signaled was a subtype of the expected type")))))
     ))
 
+(ert-deftest ert-test-should-error-argument ()
+  "Errors due to evaluating arguments should not break tests."
+  (should-error (identity (/ 1 0))))
+
+(ert-deftest ert-test-should-error-macroexpansion ()
+  "Errors due to expanding macros should not break tests."
+  (cl-macrolet ((test () (error "Foo")))
+    (should-error (test))))
+
 (ert-deftest ert-test-skip-unless ()
   ;; Don't skip.
   (let ((test (make-ert-test :body (lambda () (skip-unless t)))))
-- 
2.13.2


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* bug#24402: should-error doesn't catch all errors
  2017-07-13 22:45                           ` Alex
@ 2017-07-13 23:49                             ` npostavs
  2017-07-14  4:42                               ` Alex
  0 siblings, 1 reply; 28+ messages in thread
From: npostavs @ 2017-07-13 23:49 UTC (permalink / raw)
  To: Alex; +Cc: Gemini Lasswell, 24402, Tino Calancha

Alex <agrambot@gmail.com> writes:

> npostavs@users.sourceforge.net writes:
>> It would be nice if we can make code inside tests behave the same as
>> outside.  But we should make it conditional on whether the code is being
>> compiled, otherwise code inside tests would behave differently when
>> being interpreted.  Anyway, we can leave this for a separate bug.
>
> I agree, but that sounds like it'll require a fair bit of refactoring
> and knowledge of ert internals.

I don't think so, just a conditional to decide whether or not to call
the extra expansion.  Do you think there is anything else?

> OOC, is there a robust way to check whether or not you're currently
> byte-compiling?

AFAIK, the usual trick is (bound-and-true-p byte-compile-current-file).
It's probably good enough for most things.

> I was going to ask if you would merge in a few days, but it appears that
> what should have been a simple rebase to master caused unforeseen
> consequences. For instance, for some reason I now get a segmentation
> fault when executing 'make cl-lib-tests TEST_LOAD_EL=no'. I even reset
> to the commit I was at before and it still segfaults. Can you reproduce
> this with the following patch on master?

Nope, I just get the failures on cl-lib-defstruct-record we already
mentioned.





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#24402: should-error doesn't catch all errors
  2017-07-13 23:49                             ` npostavs
@ 2017-07-14  4:42                               ` Alex
  2017-07-14  4:45                                 ` Alex
  2017-07-15 21:57                                 ` npostavs
  0 siblings, 2 replies; 28+ messages in thread
From: Alex @ 2017-07-14  4:42 UTC (permalink / raw)
  To: npostavs; +Cc: Gemini Lasswell, 24402, Tino Calancha

npostavs@users.sourceforge.net writes:

> Alex <agrambot@gmail.com> writes:
>
>> npostavs@users.sourceforge.net writes:
>>> It would be nice if we can make code inside tests behave the same as
>>> outside.  But we should make it conditional on whether the code is being
>>> compiled, otherwise code inside tests would behave differently when
>>> being interpreted.  Anyway, we can leave this for a separate bug.
>>
>> I agree, but that sounds like it'll require a fair bit of refactoring
>> and knowledge of ert internals.
>
> I don't think so, just a conditional to decide whether or not to call
> the extra expansion.  Do you think there is anything else?

I was mostly referring to not binding `debugger', but also evaluating
the code "normally" (i.e., not doing expansions first in one
condition-case, evaluating arguments in another, and then the whole form
in a third one).

>> OOC, is there a robust way to check whether or not you're currently
>> byte-compiling?
>
> AFAIK, the usual trick is (bound-and-true-p byte-compile-current-file).
> It's probably good enough for most things.

I believe the below patch does that, though it has some issues.

>> I was going to ask if you would merge in a few days, but it appears that
>> what should have been a simple rebase to master caused unforeseen
>> consequences. For instance, for some reason I now get a segmentation
>> fault when executing 'make cl-lib-tests TEST_LOAD_EL=no'. I even reset
>> to the commit I was at before and it still segfaults. Can you reproduce
>> this with the following patch on master?
>
> Nope, I just get the failures on cl-lib-defstruct-record we already
> mentioned.

The segfault appears to have been because I didn't wipe out the elc
files when testing different implementations.

I spent a lot longer than I'd like to admit finding this out. Is there a
reason why "make clean" in the test directory doesn't wipe out elc
files? I don't understand why there's a separate bootstrap-clean that
does this. Can this and TEST_LOAD_EL please be documented in the test
README?

Anyway, I got everything back in order. Sadly, there's a couple extra
tests that now fail for me in the patch that *doesn't* expand inline
functions, and these don't fail for me in a clean master. They are in
eieio-tests (23 and 24).

With the inline expansion, I also get some errors in ert-tests. All of
the errors, with the exception of subr-tests error, seem to be from
cl-defstruct and cl-typep (which is defined by define-inline).

Do you have any ideas? There should be 5 unexpected errors without the
inline expansion, and 6 errors with it. Note that all tests pass in both
cases without "TEST_LOAD_EL=no".

If it's easy to fix the eieio tests and not the other ones, then it
might be better to leave the inline-function expansion out for now.





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#24402: should-error doesn't catch all errors
  2017-07-14  4:42                               ` Alex
@ 2017-07-14  4:45                                 ` Alex
  2017-07-15 21:57                                 ` npostavs
  1 sibling, 0 replies; 28+ messages in thread
From: Alex @ 2017-07-14  4:45 UTC (permalink / raw)
  To: npostavs; +Cc: 24402

[-- Attachment #1: Type: text/plain, Size: 128 bytes --]

Alex <agrambot@gmail.com> writes:

> I believe the below patch does that, though it has some issues.

Here's the patch, sorry:


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Catch-argument-and-expansion-errors-in-ert.patch --]
[-- Type: text/x-diff, Size: 6354 bytes --]

From ba2703bce46e7caa6e86d7406a712bd92d06f84d Mon Sep 17 00:00:00 2001
From: Alexander Gramiak <agrambot@gmail.com>
Date: Thu, 13 Jul 2017 14:54:35 -0600
Subject: [PATCH] Catch argument and expansion errors in ert

This kludge catches errors caused by evaluating arguments in ert's
should, should-not, and should-error macros; it also catches macro and
inline function expansion errors inside of the above
macros (Bug#24402).

* lisp/emacs-lisp/ert.el: (ert--should-signal-hook): New function.
(ert--expand-should-1): Catch expansion errors.
* test/lisp/emacs-lisp/ert-tests.el (ert-test-should-error-argument)
(ert-test-should-error-macroexpansion): Tests for argument and
expansion errors.
---
 lisp/emacs-lisp/ert.el            | 53 +++++++++++++++++++++++++++++++--------
 test/lisp/emacs-lisp/ert-tests.el |  9 +++++++
 2 files changed, 52 insertions(+), 10 deletions(-)

diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el
index eb2b2e3e11..353cbb8d57 100644
--- a/lisp/emacs-lisp/ert.el
+++ b/lisp/emacs-lisp/ert.el
@@ -266,6 +266,14 @@ DATA is displayed to the user and should state the reason for skipping."
   (when ert--should-execution-observer
     (funcall ert--should-execution-observer form-description)))
 
+;; See Bug#24402 for why this exists
+(defun ert--should-signal-hook (error-symbol data)
+  "Stupid hack to stop `condition-case' from catching ert signals.
+It should only be stopped when ran from inside ert--run-test-internal."
+  (when (and (not (symbolp debugger))   ; only run on anonymous debugger
+             (memq error-symbol '(ert-test-failed ert-test-skipped)))
+    (funcall debugger 'error data)))
+
 (defun ert--special-operator-p (thing)
   "Return non-nil if THING is a symbol naming a special operator."
   (and (symbolp thing)
@@ -276,13 +284,27 @@ DATA is displayed to the user and should state the reason for skipping."
 (defun ert--expand-should-1 (whole form inner-expander)
   "Helper function for the `should' macro and its variants."
   (let ((form
-         (macroexpand form (append (bound-and-true-p
-                                    byte-compile-macro-environment)
-                                   (cond
-                                    ((boundp 'macroexpand-all-environment)
-                                     macroexpand-all-environment)
-                                    ((boundp 'cl-macro-environment)
-                                     cl-macro-environment))))))
+         ;; catch all macro and inline function expansion errors
+         ;; FIXME: Code inside of tests should be evaluated like it is
+         ;; outside of tests, with the sole exception of error
+         ;; handling
+         (condition-case err
+             (funcall
+              ;; expand only when byte-compiling
+              (lambda (form)
+                (if (and (bound-and-true-p byte-compile-current-file)
+                         (consp form))
+                    (byte-compile-inline-expand form)
+                  form))
+              (macroexpand-all form
+                               (append (bound-and-true-p
+                                        byte-compile-macro-environment)
+                                       (cond
+                                        ((boundp 'macroexpand-all-environment)
+                                         macroexpand-all-environment)
+                                        ((boundp 'cl-macro-environment)
+                                         cl-macro-environment)))))
+           (error `(signal ',(car err) ',(cdr err))))))
     (cond
      ((or (atom form) (ert--special-operator-p (car form)))
       (let ((value (cl-gensym "value-")))
@@ -298,13 +320,20 @@ DATA is displayed to the user and should state the reason for skipping."
         (cl-assert (or (symbolp fn-name)
                        (and (consp fn-name)
                             (eql (car fn-name) 'lambda)
-                            (listp (cdr fn-name)))))
+                            (listp (cdr fn-name)))
+                       ;; for inline functions
+                       (byte-code-function-p fn-name)))
         (let ((fn (cl-gensym "fn-"))
               (args (cl-gensym "args-"))
               (value (cl-gensym "value-"))
               (default-value (cl-gensym "ert-form-evaluation-aborted-")))
-          `(let ((,fn (function ,fn-name))
-                 (,args (list ,@arg-forms)))
+          `(let* ((,fn (function ,fn-name))
+                  (,args (condition-case err
+                             (let ((signal-hook-function #'ert--should-signal-hook))
+                               (list ,@arg-forms))
+                           (error (progn (setq ,fn #'signal)
+                                         (list (car err)
+                                               (cdr err)))))))
              (let ((,value ',default-value))
                ,(funcall inner-expander
                          `(setq ,value (apply ,fn ,args))
@@ -766,6 +795,10 @@ This mainly sets up debugger-related bindings."
     ;; too expensive, we can remove it.
     (with-temp-buffer
       (save-window-excursion
+        ;; FIXME: Use `signal-hook-function' instead of `debugger' to
+        ;; handle ert errors. Once that's done, remove
+        ;; `ert--should-signal-hook'. See Bug#24402 and Bug#11218 for
+        ;; details.
         (let ((debugger (lambda (&rest args)
                           (ert--run-test-debugger test-execution-info
                                                   args)))
diff --git a/test/lisp/emacs-lisp/ert-tests.el b/test/lisp/emacs-lisp/ert-tests.el
index 317838b250..b6a7eb68da 100644
--- a/test/lisp/emacs-lisp/ert-tests.el
+++ b/test/lisp/emacs-lisp/ert-tests.el
@@ -294,6 +294,15 @@ failed or if there was a problem."
                   "the error signaled was a subtype of the expected type")))))
     ))
 
+(ert-deftest ert-test-should-error-argument ()
+  "Errors due to evaluating arguments should not break tests."
+  (should-error (identity (/ 1 0))))
+
+(ert-deftest ert-test-should-error-macroexpansion ()
+  "Errors due to expanding macros should not break tests."
+  (cl-macrolet ((test () (error "Foo")))
+    (should-error (test))))
+
 (ert-deftest ert-test-skip-unless ()
   ;; Don't skip.
   (let ((test (make-ert-test :body (lambda () (skip-unless t)))))
-- 
2.13.2


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* bug#24402: should-error doesn't catch all errors
  2017-07-14  4:42                               ` Alex
  2017-07-14  4:45                                 ` Alex
@ 2017-07-15 21:57                                 ` npostavs
  2017-07-16  3:49                                   ` Alex
  1 sibling, 1 reply; 28+ messages in thread
From: npostavs @ 2017-07-15 21:57 UTC (permalink / raw)
  To: Alex; +Cc: Gemini Lasswell, 24402, Tino Calancha

Alex <agrambot@gmail.com> writes:

> The segfault appears to have been because I didn't wipe out the elc
> files when testing different implementations.

I suspect getting a segfault might indicate an actual bug somewhere.

> I spent a lot longer than I'd like to admit finding this out. Is there a
> reason why "make clean" in the test directory doesn't wipe out elc
> files? I don't understand why there's a separate bootstrap-clean that
> does this. Can this and TEST_LOAD_EL please be documented in the test
> README?

I think it was basically copied from the other Makefiles, where cleaning
all elc files would mean a very long subsequent compilation.  It might
make sense to break the pattern for the test/ subdirectory though.

> Anyway, I got everything back in order. Sadly, there's a couple extra
> tests that now fail for me in the patch that *doesn't* expand inline
> functions, and these don't fail for me in a clean master. They are in
> eieio-tests (23 and 24).

I'm seeing eieio-tests failing also in master.  This seems to be an
actual bug, in the definition of `cl-typep' I think.  I've opened a new
bug for this (Bug#27718).

> With the inline expansion, I also get some errors in ert-tests. All of
> the errors, with the exception of subr-tests error, seem to be from
> cl-defstruct and cl-typep (which is defined by define-inline).
>
> Do you have any ideas? There should be 5 unexpected errors without the
> inline expansion, and 6 errors with it. Note that all tests pass in both
> cases without "TEST_LOAD_EL=no".
>
> If it's easy to fix the eieio tests and not the other ones, then it
> might be better to leave the inline-function expansion out for now.

I have a fix for the subr-tests failed, as for the others, I don't know
enough about the compilation process to untangle it yet.  I think we
should just leave the inline-function expansion part out for now, at
which point I believe your patch won't be making anything worse, so it
should be okay to install.





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#24402: should-error doesn't catch all errors
  2017-07-15 21:57                                 ` npostavs
@ 2017-07-16  3:49                                   ` Alex
  2017-07-17  0:46                                     ` npostavs
  2017-07-19 21:23                                     ` Gemini Lasswell
  0 siblings, 2 replies; 28+ messages in thread
From: Alex @ 2017-07-16  3:49 UTC (permalink / raw)
  To: npostavs; +Cc: Gemini Lasswell, 24402, Tino Calancha

[-- Attachment #1: Type: text/plain, Size: 2908 bytes --]

npostavs@users.sourceforge.net writes:

> Alex <agrambot@gmail.com> writes:
>
>> The segfault appears to have been because I didn't wipe out the elc
>> files when testing different implementations.
>
> I suspect getting a segfault might indicate an actual bug somewhere.

Probably, but I can't reproduce it anymore since I got rid of the
offending .elc files.

>> I spent a lot longer than I'd like to admit finding this out. Is there a
>> reason why "make clean" in the test directory doesn't wipe out elc
>> files? I don't understand why there's a separate bootstrap-clean that
>> does this. Can this and TEST_LOAD_EL please be documented in the test
>> README?
>
> I think it was basically copied from the other Makefiles, where cleaning
> all elc files would mean a very long subsequent compilation.  It might
> make sense to break the pattern for the test/ subdirectory though.

That makes sense to me, but if others disagree then the behaviour being
documented is the next best thing.

>> Anyway, I got everything back in order. Sadly, there's a couple extra
>> tests that now fail for me in the patch that *doesn't* expand inline
>> functions, and these don't fail for me in a clean master. They are in
>> eieio-tests (23 and 24).
>
> I'm seeing eieio-tests failing also in master.  This seems to be an
> actual bug, in the definition of `cl-typep' I think.  I've opened a new
> bug for this (Bug#27718).

Oddly enough, I can't reproduce this on master. I cloned a new copy, ran
"./autogen.sh && ./configure && make -j4", then ran "make eieio-tests
TEST_LOAD_EL=no" with no error. I cloned from 30444c695, then tried
again with 7a0fb008. I also tried "make check-expensive TEST_LOAD_EL=no"
and got only 2 errors (dom-tests and cl-lib-tests).

Perhaps odder is that I can still reproduce your recipe in Bug#27718 in
that same repository.

>> With the inline expansion, I also get some errors in ert-tests. All of
>> the errors, with the exception of subr-tests error, seem to be from
>> cl-defstruct and cl-typep (which is defined by define-inline).
>>
>> Do you have any ideas? There should be 5 unexpected errors without the
>> inline expansion, and 6 errors with it. Note that all tests pass in both
>> cases without "TEST_LOAD_EL=no".
>>
>> If it's easy to fix the eieio tests and not the other ones, then it
>> might be better to leave the inline-function expansion out for now.
>
> I have a fix for the subr-tests failed, as for the others, I don't know
> enough about the compilation process to untangle it yet.  I think we
> should just leave the inline-function expansion part out for now, at
> which point I believe your patch won't be making anything worse, so it
> should be okay to install.

Sounds good. It would be lucky if a fix to Bug#27718 also resolves the
other inline function errors so that we could use the previous patch.
Here's an updated patch with inline function excluded:


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Catch-argument-and-macroexpansion-errors-in-ert.patch --]
[-- Type: text/x-diff, Size: 5700 bytes --]

From 05f0734dd0b066058d263756a2e98cafc4ef8515 Mon Sep 17 00:00:00 2001
From: Alexander Gramiak <agrambot@gmail.com>
Date: Thu, 13 Jul 2017 14:54:35 -0600
Subject: [PATCH] Catch argument and macroexpansion errors in ert

This kludge catches errors caused by evaluating arguments in ert's
should, should-not, and should-error macros; it also catches
macroexpansion errors inside of the above macros (Bug#24402).

* lisp/emacs-lisp/ert.el: (ert--should-signal-hook): New function.
(ert--expand-should-1): Catch macroexpansion errors.
* test/lisp/emacs-lisp/ert-tests.el (ert-test-should-error-argument)
(ert-test-should-error-macroexpansion): Tests for argument and
expansion errors.
---
 lisp/emacs-lisp/ert.el            | 41 ++++++++++++++++++++++++++++++---------
 test/lisp/emacs-lisp/ert-tests.el |  9 +++++++++
 2 files changed, 41 insertions(+), 9 deletions(-)

diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el
index eb2b2e3e11..caa4a9f389 100644
--- a/lisp/emacs-lisp/ert.el
+++ b/lisp/emacs-lisp/ert.el
@@ -266,6 +266,14 @@ DATA is displayed to the user and should state the reason for skipping."
   (when ert--should-execution-observer
     (funcall ert--should-execution-observer form-description)))
 
+;; See Bug#24402 for why this exists
+(defun ert--should-signal-hook (error-symbol data)
+  "Stupid hack to stop `condition-case' from catching ert signals.
+It should only be stopped when ran from inside ert--run-test-internal."
+  (when (and (not (symbolp debugger))   ; only run on anonymous debugger
+             (memq error-symbol '(ert-test-failed ert-test-skipped)))
+    (funcall debugger 'error data)))
+
 (defun ert--special-operator-p (thing)
   "Return non-nil if THING is a symbol naming a special operator."
   (and (symbolp thing)
@@ -273,16 +281,22 @@ DATA is displayed to the user and should state the reason for skipping."
          (and (subrp definition)
               (eql (cdr (subr-arity definition)) 'unevalled)))))
 
+;; FIXME: Code inside of here should probably be evaluated like it is
+;; outside of tests, with the sole exception of error handling
 (defun ert--expand-should-1 (whole form inner-expander)
   "Helper function for the `should' macro and its variants."
   (let ((form
-         (macroexpand form (append (bound-and-true-p
-                                    byte-compile-macro-environment)
-                                   (cond
-                                    ((boundp 'macroexpand-all-environment)
-                                     macroexpand-all-environment)
-                                    ((boundp 'cl-macro-environment)
-                                     cl-macro-environment))))))
+         ;; catch macroexpansion errors
+         (condition-case err
+             (macroexpand-all form
+                              (append (bound-and-true-p
+                                       byte-compile-macro-environment)
+                                      (cond
+                                       ((boundp 'macroexpand-all-environment)
+                                        macroexpand-all-environment)
+                                       ((boundp 'cl-macro-environment)
+                                        cl-macro-environment))))
+           (error `(signal ',(car err) ',(cdr err))))))
     (cond
      ((or (atom form) (ert--special-operator-p (car form)))
       (let ((value (cl-gensym "value-")))
@@ -303,8 +317,13 @@ DATA is displayed to the user and should state the reason for skipping."
               (args (cl-gensym "args-"))
               (value (cl-gensym "value-"))
               (default-value (cl-gensym "ert-form-evaluation-aborted-")))
-          `(let ((,fn (function ,fn-name))
-                 (,args (list ,@arg-forms)))
+          `(let* ((,fn (function ,fn-name))
+                  (,args (condition-case err
+                             (let ((signal-hook-function #'ert--should-signal-hook))
+                               (list ,@arg-forms))
+                           (error (progn (setq ,fn #'signal)
+                                         (list (car err)
+                                               (cdr err)))))))
              (let ((,value ',default-value))
                ,(funcall inner-expander
                          `(setq ,value (apply ,fn ,args))
@@ -766,6 +785,10 @@ This mainly sets up debugger-related bindings."
     ;; too expensive, we can remove it.
     (with-temp-buffer
       (save-window-excursion
+        ;; FIXME: Use `signal-hook-function' instead of `debugger' to
+        ;; handle ert errors. Once that's done, remove
+        ;; `ert--should-signal-hook'. See Bug#24402 and Bug#11218 for
+        ;; details.
         (let ((debugger (lambda (&rest args)
                           (ert--run-test-debugger test-execution-info
                                                   args)))
diff --git a/test/lisp/emacs-lisp/ert-tests.el b/test/lisp/emacs-lisp/ert-tests.el
index 317838b250..b6a7eb68da 100644
--- a/test/lisp/emacs-lisp/ert-tests.el
+++ b/test/lisp/emacs-lisp/ert-tests.el
@@ -294,6 +294,15 @@ failed or if there was a problem."
                   "the error signaled was a subtype of the expected type")))))
     ))
 
+(ert-deftest ert-test-should-error-argument ()
+  "Errors due to evaluating arguments should not break tests."
+  (should-error (identity (/ 1 0))))
+
+(ert-deftest ert-test-should-error-macroexpansion ()
+  "Errors due to expanding macros should not break tests."
+  (cl-macrolet ((test () (error "Foo")))
+    (should-error (test))))
+
 (ert-deftest ert-test-skip-unless ()
   ;; Don't skip.
   (let ((test (make-ert-test :body (lambda () (skip-unless t)))))
-- 
2.13.2


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* bug#24402: should-error doesn't catch all errors
  2017-07-16  3:49                                   ` Alex
@ 2017-07-17  0:46                                     ` npostavs
  2017-07-19 21:23                                     ` Gemini Lasswell
  1 sibling, 0 replies; 28+ messages in thread
From: npostavs @ 2017-07-17  0:46 UTC (permalink / raw)
  To: Alex; +Cc: Gemini Lasswell, 24402, Tino Calancha

Alex <agrambot@gmail.com> writes:

> Oddly enough, I can't reproduce this on master. I cloned a new copy, ran
> "./autogen.sh && ./configure && make -j4", then ran "make eieio-tests
> TEST_LOAD_EL=no" with no error. I cloned from 30444c695, then tried
> again with 7a0fb008. I also tried "make check-expensive TEST_LOAD_EL=no"
> and got only 2 errors (dom-tests and cl-lib-tests).
>
> Perhaps odder is that I can still reproduce your recipe in Bug#27718 in
> that same repository.

Uh, actually, now I'm getting the same results as you (i.e., make
eieio-tests TEST_LOAD_EL=no passes on master for me, though the #27718
test case does fail).  Perhaps I accidentally ran an eieio-tests.elc
file produced by a patched Emacs using a non-patched Emacs before?

>> I have a fix for the subr-tests failed, as for the others, I don't know
>> enough about the compilation process to untangle it yet.  I think we
>> should just leave the inline-function expansion part out for now, at
>> which point I believe your patch won't be making anything worse, so it
>> should be okay to install.
>
> Sounds good. It would be lucky if a fix to Bug#27718 also resolves the
> other inline function errors so that we could use the previous patch.
> Here's an updated patch with inline function excluded:

Okay, so the patch does make a couple more tests fail, but I think it's
actually an improvement since #27718 shows that the scenario was already
failing outside of ert-deftest, i.e., in this case your patch is making
code inside the test more like code outside the test.  We can just mark
those as expected failures when compiled.

I will merge to master in a few days, assuming there are no objections.





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#24402: should-error doesn't catch all errors
  2017-07-16  3:49                                   ` Alex
  2017-07-17  0:46                                     ` npostavs
@ 2017-07-19 21:23                                     ` Gemini Lasswell
  2017-07-19 22:40                                       ` Alex
  2017-07-19 23:04                                       ` npostavs
  1 sibling, 2 replies; 28+ messages in thread
From: Gemini Lasswell @ 2017-07-19 21:23 UTC (permalink / raw)
  To: Alex; +Cc: npostavs, Tino Calancha, 24402

[-- Attachment #1: Type: text/plain, Size: 358 bytes --]

Hello,

First, thank you for working on this bug!

I have a branch of Emacs which attempts to run all the tests under
Testcover, and I've tried it with Alex's latest patch. The patch has
fixed the problems with Testcover and should-error except for one weird
case. Here is a file that will let you reproduce the weird case on
master with the patch applied:


[-- Attachment #2: cyc-test.el --]
[-- Type: text/plain, Size: 449 bytes --]

(defun cyc1 (a)
  (let ((ls (make-list 10 a)))
    (nconc ls ls)
    ls))

(ert-deftest test-cycle-assq ()
  (let ((c1 (cyc1 '(1))))
    (should-error (assq 3 c1) :type 'circular-list)))

(ert-deftest test-cycle-assoc ()
  (let ((c1 (cyc1 '(1))))
    (should-error (assoc 2 c1) :type 'circular-list)))

(defvar testcover-started nil)
(unless testcover-started
  (setq testcover-started t)
  (testcover-start (or load-file-name (buffer-file-name))))

[-- Attachment #3: Type: text/plain, Size: 414 bytes --]


This is an excerpt of test/src/fns-tests.el with a few lines added at
the end to invoke Testcover. It contains two nearly identical tests
which should both pass, but one passes and one fails. If you then edit
the file and comment out test-cycle-assoc (the one that passes) and run
the test again, then the failing test will pass. I've reproduced it both
in batch mode (without TEST_LOAD_EL=no) and interactively.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#24402: should-error doesn't catch all errors
  2017-07-19 21:23                                     ` Gemini Lasswell
@ 2017-07-19 22:40                                       ` Alex
  2017-07-19 23:04                                       ` npostavs
  1 sibling, 0 replies; 28+ messages in thread
From: Alex @ 2017-07-19 22:40 UTC (permalink / raw)
  To: Gemini Lasswell; +Cc: npostavs, Tino Calancha, 24402

Gemini Lasswell <gazally@runbox.com> writes:

> Hello,
>
> First, thank you for working on this bug!
>
> I have a branch of Emacs which attempts to run all the tests under
> Testcover, and I've tried it with Alex's latest patch. The patch has
> fixed the problems with Testcover and should-error except for one weird
> case. Here is a file that will let you reproduce the weird case on
> master with the patch applied:
>
>
>
> This is an excerpt of test/src/fns-tests.el with a few lines added at
> the end to invoke Testcover. It contains two nearly identical tests
> which should both pass, but one passes and one fails. If you then edit
> the file and comment out test-cycle-assoc (the one that passes) and run
> the test again, then the failing test will pass. I've reproduced it both
> in batch mode (without TEST_LOAD_EL=no) and interactively.

Hmm, this isn't the behaviour that I see. I get the following errors
both with and without my patch, and both interactively and in batch
mode:

===============================================================================================
Edebug: cyc1
Edebug: test@test-cycle-assq
Edebug: test@test-cycle-assoc
Edebug: cyc1
Edebug: test@test-cycle-assq
Edebug: test@test-cycle-assoc
...
Edebug: cyc1
Edebug: test@test-cycle-assq
Compiler-macro error for cl--block-wrapper: (error "Lisp nesting exceeds ‘max-lisp-eval-depth’")
Edebug: test@test-cycle-assoc
Compiler-macro error for cl--block-wrapper: (error "Lisp nesting exceeds ‘max-lisp-eval-depth’")
Edebug: cyc1
Edebug: test@test-cycle-assq
Compiler-macro error for cl--block-wrapper: (error "Lisp nesting exceeds ‘max-lisp-eval-depth’")
Eager macro-expansion failure: (error "Lisp nesting exceeds ‘max-lisp-eval-depth’")
Compiler-macro error for cl--block-wrapper: (error "Lisp nesting exceeds ‘max-lisp-eval-depth’")
Eager macro-expansion failure: (error "Lisp nesting exceeds ‘max-lisp-eval-depth’")
Compiler-macro error for cl--block-wrapper: (error "Lisp nesting exceeds ‘max-lisp-eval-depth’")
Entering debugger...
cl--generic-make-next-function: Symbol’s function definition is void: t
===============================================================================================

The ... above represents Edebug cycling, for some reason, between the 3
functions.

Noam, can you reproduce this?





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#24402: should-error doesn't catch all errors
  2017-07-19 21:23                                     ` Gemini Lasswell
  2017-07-19 22:40                                       ` Alex
@ 2017-07-19 23:04                                       ` npostavs
  2017-07-20  4:04                                         ` Alex
  2017-07-20 19:23                                         ` Gemini Lasswell
  1 sibling, 2 replies; 28+ messages in thread
From: npostavs @ 2017-07-19 23:04 UTC (permalink / raw)
  To: Gemini Lasswell; +Cc: 24402, Alex, Tino Calancha

[-- Attachment #1: Type: text/plain, Size: 815 bytes --]

Gemini Lasswell <gazally@runbox.com> writes:

> This is an excerpt of test/src/fns-tests.el with a few lines added at
> the end to invoke Testcover. It contains two nearly identical tests
> which should both pass, but one passes and one fails.

If I run them again in the same Emacs session then they both fail.  The
problem seems to be that testcover saves values produced in tests, and
when it tries to compare the 2 circular lists produced by these tests, a
`circular-list' error is thrown.  In other words, this is actually a
totally separate bug (although it's hidden until a fix for #24402 is
applied).

The following appears to fix it, though perhaps we should use a smarter
equal function that would consider the circular lists to actually be
equal instead of bailing out and returning nil on circularity.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: patch --]
[-- Type: text/x-diff, Size: 1501 bytes --]

From 7160e8e45ef9e074360e394f99120d11b7ed4b8a Mon Sep 17 00:00:00 2001
From: Noam Postavsky <npostavs@gmail.com>
Date: Wed, 19 Jul 2017 18:48:50 -0400
Subject: [PATCH v1] Don't error on circular values in testcover

* lisp/emacs-lisp/testcover.el (testcover-after, testcover-1value):
Consider circular lists to be non-equal instead of signaling error.
---
 lisp/emacs-lisp/testcover.el | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/lisp/emacs-lisp/testcover.el b/lisp/emacs-lisp/testcover.el
index 433ad38a14..bc6004a709 100644
--- a/lisp/emacs-lisp/testcover.el
+++ b/lisp/emacs-lisp/testcover.el
@@ -463,7 +463,9 @@ (defun testcover-after (idx val)
   (cond
    ((eq (aref testcover-vector idx) 'unknown)
     (aset testcover-vector idx val))
-   ((not (equal (aref testcover-vector idx) val))
+   ((not (condition-case ()
+             (equal (aref testcover-vector idx) val)
+           (circular-list nil)))
     (aset testcover-vector idx 'ok-coverage)))
   val)
 
@@ -475,7 +477,9 @@ (defun testcover-1value (idx val)
    ((eq (aref testcover-vector idx) '1value)
     (aset testcover-vector idx (cons '1value val)))
    ((not (and (eq (car-safe (aref testcover-vector idx)) '1value)
-	      (equal (cdr (aref testcover-vector idx)) val)))
+	      (condition-case ()
+                  (equal (cdr (aref testcover-vector idx)) val)
+                (circular-list nil))))
     (error "Value of form marked with `1value' does vary: %s" val)))
   val)
 
-- 
2.11.1


[-- Attachment #3: Type: text/plain, Size: 745 bytes --]


Alex <agrambot@gmail.com> writes:

> Hmm, this isn't the behaviour that I see. I get the following errors
> both with and without my patch, and both interactively and in batch
> mode:
>
> ===============================================================================================
> Edebug: cyc1
> Edebug: test@test-cycle-assq
> Edebug: test@test-cycle-assoc
> Edebug: cyc1
> Edebug: test@test-cycle-assq
> Edebug: test@test-cycle-assoc
> ...
> Edebug: cyc1
> Edebug: test@test-cycle-assq
> Compiler-macro error for cl--block-wrapper: (error "Lisp nesting exceeds ‘max-lisp-eval-depth’")

Hmm, that's strange, I don't get that error (or any "Edebug: cyc1"
repetitions after the first) on master, or with your patch.

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* bug#24402: should-error doesn't catch all errors
  2017-07-19 23:04                                       ` npostavs
@ 2017-07-20  4:04                                         ` Alex
  2017-07-20 19:23                                         ` Gemini Lasswell
  1 sibling, 0 replies; 28+ messages in thread
From: Alex @ 2017-07-20  4:04 UTC (permalink / raw)
  To: npostavs; +Cc: Gemini Lasswell, 24402, Tino Calancha

npostavs@users.sourceforge.net writes:

> Gemini Lasswell <gazally@runbox.com> writes:
>
>> This is an excerpt of test/src/fns-tests.el with a few lines added at
>> the end to invoke Testcover. It contains two nearly identical tests
>> which should both pass, but one passes and one fails.
>
> If I run them again in the same Emacs session then they both fail.  The
> problem seems to be that testcover saves values produced in tests, and
> when it tries to compare the 2 circular lists produced by these tests, a
> `circular-list' error is thrown.  In other words, this is actually a
> totally separate bug (although it's hidden until a fix for #24402 is
> applied).
>
> The following appears to fix it, though perhaps we should use a smarter
> equal function that would consider the circular lists to actually be
> equal instead of bailing out and returning nil on circularity.

That would be nice.

> Alex <agrambot@gmail.com> writes:
> 
> > Hmm, this isn't the behaviour that I see. I get the following errors
> > both with and without my patch, and both interactively and in batch
> > mode:
> >
> > ===============================================================================================
> > Edebug: cyc1
> > Edebug: test@test-cycle-assq
> > Edebug: test@test-cycle-assoc
> > Edebug: cyc1
> > Edebug: test@test-cycle-assq
> > Edebug: test@test-cycle-assoc
> > ...
> > Edebug: cyc1
> > Edebug: test@test-cycle-assq
> > Compiler-macro error for cl--block-wrapper: (error "Lisp nesting exceeds ‘max-lisp-eval-depth’")
> 
> Hmm, that's strange, I don't get that error (or any "Edebug: cyc1"
> repetitions after the first) on master, or with your patch.

Whoops, I changed the defvar to a setq and forgot to change it back.
Doing this results in the error I posted. (Which makes sense since it
keeps reloading the file, resulting in the "Edebug:" loop. The
compiler-macro errors and `t' being called as a function are a bit odd,
though).

I get the same behaviour as you and Gemini now. Sorry about the noise.





^ permalink raw reply	[flat|nested] 28+ messages in thread

* bug#24402: should-error doesn't catch all errors
  2017-07-19 23:04                                       ` npostavs
  2017-07-20  4:04                                         ` Alex
@ 2017-07-20 19:23                                         ` Gemini Lasswell
  2017-08-08  1:15                                           ` npostavs
  1 sibling, 1 reply; 28+ messages in thread
From: Gemini Lasswell @ 2017-07-20 19:23 UTC (permalink / raw)
  To: npostavs; +Cc: 24402, Alex, Tino Calancha

[-- Attachment #1: Type: text/plain, Size: 530 bytes --]

npostavs@users.sourceforge.net writes:

> The following appears to fix it, though perhaps we should use a smarter
> equal function that would consider the circular lists to actually be
> equal instead of bailing out and returning nil on circularity.

Thanks for tracking this one down and making a patch, which looks good
to me. Does that smarter equal function already exist? It doesn't seem
worth the effort of writing one for this purpose only.

Here is a test to add to your patch, which fails without it and passes
with it:


[-- Attachment #2: 0001-Add-a-test-of-handling-of-circular-values-to-testcov.patch --]
[-- Type: text/plain, Size: 1206 bytes --]

From f401e3169ff3887b8215b6625d111d70e5340efe Mon Sep 17 00:00:00 2001
From: Gemini Lasswell <gazally@runbox.com>
Date: Thu, 20 Jul 2017 12:01:42 -0700
Subject: [PATCH] Add a test of handling of circular values to testcover-tests

* test/lisp/emacs-lisp-testcover-resources/testcases.el
(testcover-testcase-cyc1): New function.
(testcover-tests-circular-lists-bug-24402): New test.
---
 test/lisp/emacs-lisp/testcover-resources/testcases.el | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/test/lisp/emacs-lisp/testcover-resources/testcases.el b/test/lisp/emacs-lisp/testcover-resources/testcases.el
index 1eb791a993..c9a5a6daac 100644
--- a/test/lisp/emacs-lisp/testcover-resources/testcases.el
+++ b/test/lisp/emacs-lisp/testcover-resources/testcases.el
@@ -490,4 +490,14 @@ testcover-testcase-how-do-i-know-you
 
 (should (eq (testcover-testcase-how-do-i-know-you "Liz") 'unknown))
 
+;; ==== circular-lists-bug-24402 ====
+"Testcover captures and ignores circular list errors."
+;; ====
+(defun testcover-testcase-cyc1 (a)
+  (let ((ls (make-list 10 a%%%)))
+    (nconc ls ls)
+    ls))
+(testcover-testcase-cyc1 1)
+(testcover-testcase-cyc1 1)
+
 ;; testcases.el ends here.
-- 
2.12.2


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* bug#24402: should-error doesn't catch all errors
  2017-07-20 19:23                                         ` Gemini Lasswell
@ 2017-08-08  1:15                                           ` npostavs
  0 siblings, 0 replies; 28+ messages in thread
From: npostavs @ 2017-08-08  1:15 UTC (permalink / raw)
  To: Gemini Lasswell; +Cc: 24402, Alex, Tino Calancha

tags 24402 fixed
close 24402 26.1
quit

Sorry for the delay, I was moving apartment, and then I got a bit
distracted by my 'grep --null' mess.

Gemini Lasswell <gazally@runbox.com> writes:

> npostavs@users.sourceforge.net writes:
>
>> The following appears to fix it, though perhaps we should use a smarter
>> equal function that would consider the circular lists to actually be
>> equal instead of bailing out and returning nil on circularity.
>
> Thanks for tracking this one down and making a patch, which looks good
> to me. Does that smarter equal function already exist? It doesn't seem
> worth the effort of writing one for this purpose only.

Yeah, I left it as is with a TODO.  We can fix it later if it turns out
to cause an actual problem.

> Here is a test to add to your patch, which fails without it and passes
> with it:

Thanks, I pushed it to master along with the others.

[1: 054c198c12]: 2017-08-07 18:43:54 -0400
  Catch argument and macroexpansion errors in ert
  http://git.savannah.gnu.org/cgit/emacs.git/commit/?id=054c198c120c1f01a8ff753892d52710b740acc6

[2: 95a04fd26c]: 2017-08-07 18:43:55 -0400
  ; Avoid test failures when running from compiled test files
  http://git.savannah.gnu.org/cgit/emacs.git/commit/?id=95a04fd26c91e6c6c9191a629d26886f136e30fc

[3: 0508045ed7]: 2017-08-07 18:54:44 -0400
  Don't error on circular values in testcover
  http://git.savannah.gnu.org/cgit/emacs.git/commit/?id=0508045ed7159bce5b5ea3b5fb72cf78b8b4ee8e

[4: 00f7e31110]: 2017-08-07 18:54:48 -0400
  Add a test of handling of circular values to testcover-tests
  http://git.savannah.gnu.org/cgit/emacs.git/commit/?id=00f7e31110a27e568529192d7441d9631b9096bc





^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2017-08-08  1:15 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-09-10  1:26 bug#24402: 25.1.50; testcover-start breaks should-error Gemini Lasswell
     [not found] ` <handler.24402.B.14734739098199.ack@debbugs.gnu.org>
2016-09-20  4:27   ` bug#24402: More Information Gemini Lasswell
2017-07-04  3:28     ` bug#24402: should-error doesn't catch all errors (Was:bug#24402: More Information) Alex
2017-07-05  0:00       ` bug#24402: should-error doesn't catch all errors Alex
2017-07-05 13:43         ` Tino Calancha
2017-07-05 19:56           ` Alex
2017-07-07 10:15             ` Tino Calancha
2017-07-09  7:04               ` Alex
2017-07-11 12:18             ` npostavs
2017-07-12  3:47               ` Alex
2017-07-12 12:30                 ` npostavs
2017-07-12 16:45                   ` Alex
2017-07-13  1:31                     ` npostavs
2017-07-13  3:04                       ` Alex
2017-07-13  3:44                         ` npostavs
2017-07-13 22:45                           ` Alex
2017-07-13 23:49                             ` npostavs
2017-07-14  4:42                               ` Alex
2017-07-14  4:45                                 ` Alex
2017-07-15 21:57                                 ` npostavs
2017-07-16  3:49                                   ` Alex
2017-07-17  0:46                                     ` npostavs
2017-07-19 21:23                                     ` Gemini Lasswell
2017-07-19 22:40                                       ` Alex
2017-07-19 23:04                                       ` npostavs
2017-07-20  4:04                                         ` Alex
2017-07-20 19:23                                         ` Gemini Lasswell
2017-08-08  1:15                                           ` npostavs

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).