diff --git a/Lib/test/crashers/mutation_inside_cyclegc.py b/Lib/test/crashers/mutation_inside_cyclegc.py deleted file mode 100644 index 2b67398bccce23..00000000000000 --- a/Lib/test/crashers/mutation_inside_cyclegc.py +++ /dev/null @@ -1,31 +0,0 @@ - -# The cycle GC collector can be executed when any GC-tracked object is -# allocated, e.g. during a call to PyList_New(), PyDict_New(), ... -# Moreover, it can invoke arbitrary Python code via a weakref callback. -# This means that there are many places in the source where an arbitrary -# mutation could unexpectedly occur. - -# The example below shows list_slice() not expecting the call to -# PyList_New to mutate the input list. (Of course there are many -# more examples like this one.) - - -import weakref - -class A(object): - pass - -def callback(x): - del lst[:] - - -keepalive = [] - -for i in range(100): - lst = [str(i)] - a = A() - a.cycle = a - keepalive.append(weakref.ref(a, callback)) - del a - while lst: - keepalive.append(lst[:]) diff --git a/Lib/test/crashers/recursive_call.py b/Lib/test/crashers/recursive_call.py deleted file mode 100755 index 2d160a7de5dac7..00000000000000 --- a/Lib/test/crashers/recursive_call.py +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env python3 - -# No bug report AFAIK, mail on python-dev on 2006-01-10 - -# This is a "won't fix" case. It is known that setting a high enough -# recursion limit crashes by overflowing the stack. Unless this is -# redesigned somehow, it won't go away. - -import sys - -sys.setrecursionlimit(1 << 30) -f = lambda f:f(f) - -if __name__ == '__main__': - f(f) diff --git a/Lib/test/crashers/trace_at_recursion_limit.py b/Lib/test/crashers/trace_at_recursion_limit.py deleted file mode 100644 index acd863f5509c49..00000000000000 --- a/Lib/test/crashers/trace_at_recursion_limit.py +++ /dev/null @@ -1,27 +0,0 @@ -""" -From http://bugs.python.org/issue6717 - -A misbehaving trace hook can trigger a segfault by exceeding the recursion -limit. -""" -import sys - - -def x(): - pass - -def g(*args): - if True: # change to True to crash interpreter - try: - x() - except: - pass - return g - -def f(): - print(sys.getrecursionlimit()) - f() - -sys.settrace(g) - -f() diff --git a/Lib/test/crashers/README b/Lib/test/test_crashers/README similarity index 75% rename from Lib/test/crashers/README rename to Lib/test/test_crashers/README index 0259a0688cbc67..19f67b7ea2c94e 100644 --- a/Lib/test/crashers/README +++ b/Lib/test/test_crashers/README @@ -5,7 +5,7 @@ too obscure to invest the effort. Each test should fail when run from the command line: - ./python Lib/test/crashers/weakref_in_del.py + ./python Lib/test/test_crashers/bogus_code_obj.py Put as much info into a docstring or comments to help determine the cause of the failure, as well as a bugs.python.org issue number if it exists. Particularly @@ -15,6 +15,6 @@ Once the crash is fixed, the test case should be moved into an appropriate test (even if it was originally from the test suite). This ensures the regression doesn't happen again. And if it does, it should be easier to track down. -Also see Lib/test_crashers.py which exercises the crashers in this directory. -In particular, make sure to add any new infinite loop crashers to the black -list so it doesn't try to run them. +Also see Lib/test/test_crashers/__init__.py which exercises the crashers in +this directory. In particular, make sure to add any new infinite loop crashers +to the black list so it doesn't try to run them. diff --git a/Lib/test/test_crashers.py b/Lib/test/test_crashers/__init__.py similarity index 56% rename from Lib/test/test_crashers.py rename to Lib/test/test_crashers/__init__.py index 31b712028f8a12..44c4e94673fbb0 100644 --- a/Lib/test/test_crashers.py +++ b/Lib/test/test_crashers/__init__.py @@ -4,34 +4,40 @@ # If a crasher is fixed, it should be moved elsewhere in the test suite to # ensure it continues to work correctly. -import unittest import glob import os.path -import test.support +import unittest +from test import support from test.support.script_helper import assert_python_failure -CRASHER_DIR = os.path.join(os.path.dirname(__file__), "crashers") + +CRASHER_DIR = os.path.abspath(os.path.dirname(__file__)) CRASHER_FILES = os.path.join(glob.escape(CRASHER_DIR), "*.py") +infinite_loops = frozenset(["infinite_loop_re.py"]) -infinite_loops = ["infinite_loop_re.py", "nasty_eq_vs_dict.py"] class CrasherTest(unittest.TestCase): - - @unittest.skip("these tests are too fragile") - @test.support.cpython_only + @support.cpython_only def test_crashers_crash(self): + if support.verbose: + print() for fname in glob.glob(CRASHER_FILES): - if os.path.basename(fname) in infinite_loops: + script = os.path.basename(fname) + if script == "__init__.py": + continue + if script in infinite_loops: continue # Some "crashers" only trigger an exception rather than a # segfault. Consider that an acceptable outcome. - if test.support.verbose: - print("Checking crasher:", fname) - assert_python_failure(fname) + if support.verbose: + print(f"Checking crasher: {script}", flush=True) + proc = assert_python_failure(fname) + self.assertLess(proc.rc, 0, proc) def tearDownModule(): - test.support.reap_children() + support.reap_children() + if __name__ == "__main__": unittest.main() diff --git a/Lib/test/crashers/bogus_code_obj.py b/Lib/test/test_crashers/bogus_code_obj.py similarity index 71% rename from Lib/test/crashers/bogus_code_obj.py rename to Lib/test/test_crashers/bogus_code_obj.py index e71b3582cf2d76..125ebf762e7021 100644 --- a/Lib/test/crashers/bogus_code_obj.py +++ b/Lib/test/test_crashers/bogus_code_obj.py @@ -12,8 +12,13 @@ """ -import types +from test.support import SuppressCrashReport -co = types.CodeType(0, 0, 0, 0, 0, 0, b'\x04\x00\x71\x00', - (), (), (), '', '', 1, b'') -exec(co) +def func(): + pass + +invalid_code = b'\x04\x00\x71\x00' +func.__code__ = func.__code__.replace(co_code=invalid_code) + +with SuppressCrashReport(): + func() diff --git a/Lib/test/crashers/gc_inspection.py b/Lib/test/test_crashers/gc_inspection.py similarity index 82% rename from Lib/test/crashers/gc_inspection.py rename to Lib/test/test_crashers/gc_inspection.py index ae85f97a74adc9..2df6013a34f2a0 100644 --- a/Lib/test/crashers/gc_inspection.py +++ b/Lib/test/test_crashers/gc_inspection.py @@ -15,9 +15,14 @@ fixes to the documentation for extension module writers. It's unlikely to happen, though. So this is currently classified as "gc.get_referrers() is dangerous, use only for debugging". + +* https://github.com/python/cpython/issues/39117 +* https://github.com/python/cpython/issues/59313 +* https://github.com/python/cpython/pull/107183 """ import gc +from test.support import SuppressCrashReport def g(): @@ -29,4 +34,5 @@ def g(): print(tup[1]) -tuple(g()) +with SuppressCrashReport(): + tuple(g()) diff --git a/Lib/test/crashers/infinite_loop_re.py b/Lib/test/test_crashers/infinite_loop_re.py similarity index 100% rename from Lib/test/crashers/infinite_loop_re.py rename to Lib/test/test_crashers/infinite_loop_re.py diff --git a/Lib/test/crashers/underlying_dict.py b/Lib/test/test_crashers/underlying_dict.py similarity index 70% rename from Lib/test/crashers/underlying_dict.py rename to Lib/test/test_crashers/underlying_dict.py index a4b799374381d5..219a5d31bb2a20 100644 --- a/Lib/test/crashers/underlying_dict.py +++ b/Lib/test/test_crashers/underlying_dict.py @@ -1,3 +1,4 @@ +from test.support import SuppressCrashReport import gc thingy = object() @@ -17,4 +18,5 @@ def f(self): a.f() dct["f"] = lambda self: 2 -print(a.f()) # should print 1 +with SuppressCrashReport(): + print(a.f()) # should print 1 diff --git a/Makefile.pre.in b/Makefile.pre.in index d66764e6165409..2a3328d920a2f6 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -2144,7 +2144,6 @@ TESTSUBDIRS= idlelib/idle_test \ test/audiodata \ test/capath \ test/cjkencodings \ - test/crashers \ test/data \ test/decimaltestdata \ test/dtracedata \ @@ -2157,6 +2156,7 @@ TESTSUBDIRS= idlelib/idle_test \ test/test_asyncio \ test/test_capi \ test/test_cppext \ + test/test_crashers \ test/test_ctypes \ test/test_email \ test/test_email/data \