diff options
author | Martin Panter <vadmium+py@gmail.com> | 2016-02-28 00:18:43 (GMT) |
---|---|---|
committer | Martin Panter <vadmium+py@gmail.com> | 2016-02-28 00:18:43 (GMT) |
commit | ef85a1ac1510203a06c15f1483b76f2f20b80ede (patch) | |
tree | 8440aa6d04968755fd02e9c421c75f45f70dcf3f /Lib/test/test_exceptions.py | |
parent | f9ce84b19531531d2f5748fb51404f5149fbd0fb (diff) | |
download | cpython-ef85a1ac1510203a06c15f1483b76f2f20b80ede.zip cpython-ef85a1ac1510203a06c15f1483b76f2f20b80ede.tar.gz cpython-ef85a1ac1510203a06c15f1483b76f2f20b80ede.tar.bz2 |
Issue #22836: Keep exception reports sensible despite errors
Diffstat (limited to 'Lib/test/test_exceptions.py')
-rw-r--r-- | Lib/test/test_exceptions.py | 69 |
1 files changed, 65 insertions, 4 deletions
diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index b950031..bc8944d 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -5,10 +5,15 @@ import sys import unittest import pickle, cPickle -from test.test_support import (TESTFN, unlink, run_unittest, captured_output, +from test.test_support import (TESTFN, unlink, run_unittest, captured_stderr, check_warnings, cpython_only) from test.test_pep352 import ignore_deprecation_warnings +class BrokenStrException(Exception): + def __str__(self): + raise Exception("str() is broken") + __repr__ = __str__ # Python 2's PyErr_WriteUnraisable() uses repr() + # XXX This is not really enough, each *operation* should be tested! class ExceptionTests(unittest.TestCase): @@ -375,7 +380,7 @@ class ExceptionTests(unittest.TestCase): # The test prints an unraisable recursion error when # doing "except ValueError", this is because subclass # checking has recursion checking too. - with captured_output("stderr"): + with captured_stderr(): try: g() except RuntimeError: @@ -448,7 +453,7 @@ class ExceptionTests(unittest.TestCase): __metaclass__ = Meta pass - with captured_output("stderr") as stderr: + with captured_stderr() as stderr: try: raise KeyError() except MyException, e: @@ -460,7 +465,7 @@ class ExceptionTests(unittest.TestCase): else: self.fail("Should have raised KeyError") - with captured_output("stderr") as stderr: + with captured_stderr() as stderr: def g(): try: return g() @@ -644,6 +649,62 @@ class TestSameStrAndUnicodeMsg(unittest.TestCase): self.assertEqual(error5.a, 1) self.assertEqual(error5.__doc__, "") + def test_unraisable(self): + # Issue #22836: PyErr_WriteUnraisable() should give sensible reports + class BrokenDel: + def __del__(self): + exc = ValueError("del is broken") + # In Python 3, the following line would be in the report: + raise exc + + class BrokenRepr(BrokenDel): + def __repr__(self): + raise AttributeError("repr() is broken") + + class BrokenExceptionDel: + def __del__(self): + exc = BrokenStrException() + # In Python 3, the following line would be in the report: + raise exc + + for test_class in (BrokenDel, BrokenRepr, BrokenExceptionDel): + obj = test_class() + with captured_stderr() as stderr: + del obj + report = stderr.getvalue() + self.assertRegexpMatches(report, "Exception.* ignored") + if test_class is BrokenRepr: + self.assertIn("<object repr() failed>", report) + else: + self.assertIn("__del__", report) + if test_class is BrokenExceptionDel: + self.assertIn("BrokenStrException", report) + self.assertIn("<exception repr() failed>", report) + else: + self.assertIn("ValueError", report) + self.assertIn("del is broken", report) + self.assertTrue(report.endswith("\n")) + + def test_unhandled(self): + # Check for sensible reporting of unhandled exceptions + for exc_type in (ValueError, BrokenStrException): + try: + exc = exc_type("test message") + # The following line is included in the traceback report: + raise exc + except exc_type: + with captured_stderr() as stderr: + sys.__excepthook__(*sys.exc_info()) + report = stderr.getvalue() + self.assertIn("test_exceptions.py", report) + self.assertIn("raise exc", report) + self.assertIn(exc_type.__name__, report) + if exc_type is BrokenStrException: + self.assertIn("<exception str() failed>", report) + else: + self.assertIn("test message", report) + self.assertTrue(report.endswith("\n")) + def test_main(): run_unittest(ExceptionTests, TestSameStrAndUnicodeMsg) |