From 1f38621a336932754b242cd4779e7d0545fd0dfe Mon Sep 17 00:00:00 2001 From: Ezio Melotti Date: Thu, 7 Mar 2013 18:44:29 +0200 Subject: [PATCH] #11732: add a new suppress_crash_popup() context manager to test.support that disables crash popups on Windows and use it in test_ctypes. --- Doc/library/test.rst | 7 +++++++ Lib/test/support.py | 26 +++++++++++++++++++++++++- Lib/test/test_capi.py | 11 ++++++----- Misc/NEWS | 3 +++ 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/Doc/library/test.rst b/Doc/library/test.rst index 40f4115ead0..24e06d52152 100644 --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -365,6 +365,13 @@ The :mod:`test.support` module defines the following functions: assert s.getvalue() == "hello\n" +.. function:: suppress_crash_popup() + + A context manager that disables Windows Error Reporting dialogs using + `SetErrorMode `_. + On other platforms it's a no-op. + + .. function:: import_module(name, deprecated=False) This function imports and returns the named module. Unlike a normal diff --git a/Lib/test/support.py b/Lib/test/support.py index 66ddf4b0fde..ddda380f354 100644 --- a/Lib/test/support.py +++ b/Lib/test/support.py @@ -56,7 +56,7 @@ __all__ = [ "reap_children", "cpython_only", "check_impl_detail", "get_attribute", "swap_item", "swap_attr", "requires_IEEE_754", "TestHandler", "Matcher", "can_symlink", "skip_unless_symlink", - "import_fresh_module", "failfast", "run_with_tz" + "import_fresh_module", "failfast", "run_with_tz", "suppress_crash_popup", ] class Error(Exception): @@ -1775,6 +1775,30 @@ def skip_unless_symlink(test): msg = "Requires functional symlink implementation" return test if ok else unittest.skip(msg)(test) + +if sys.platform.startswith('win'): + @contextlib.contextmanager + def suppress_crash_popup(): + """Disable Windows Error Reporting dialogs using SetErrorMode.""" + # see http://msdn.microsoft.com/en-us/library/windows/desktop/ms680621%28v=vs.85%29.aspx + # GetErrorMode is not available on Windows XP and Windows Server 2003, + # but SetErrorMode returns the previous value, so we can use that + import ctypes + k32 = ctypes.windll.kernel32 + SEM_NOGPFAULTERRORBOX = 0x02 + old_error_mode = k32.SetErrorMode(SEM_NOGPFAULTERRORBOX) + k32.SetErrorMode(old_error_mode | SEM_NOGPFAULTERRORBOX) + try: + yield + finally: + k32.SetErrorMode(old_error_mode) +else: + # this is a no-op for other platforms + @contextlib.contextmanager + def suppress_crash_popup(): + yield + + def patch(test_instance, object_to_patch, attr_name, new_value): """Override 'object_to_patch'.'attr_name' with 'new_value'. diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py index 0ab145807e1..1c4c0f8c46e 100644 --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -46,11 +46,12 @@ class CAPITest(unittest.TestCase): @unittest.skipUnless(threading, 'Threading required for this test.') def test_no_FatalError_infinite_loop(self): - p = subprocess.Popen([sys.executable, "-c", - 'import _testcapi;' - '_testcapi.crash_no_current_thread()'], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) + with support.suppress_crash_popup(): + p = subprocess.Popen([sys.executable, "-c", + 'import _testcapi;' + '_testcapi.crash_no_current_thread()'], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) (out, err) = p.communicate() self.assertEqual(out, b'') # This used to cause an infinite loop. diff --git a/Misc/NEWS b/Misc/NEWS index e9c78b3b31a..8cbf191814f 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -950,6 +950,9 @@ Extension Modules Tests ----- +- Issue #11732: add a new suppress_crash_popup() context manager to test.support + that disables crash popups on Windows and use it in test_ctypes. + - Issue #13898: test_ssl no longer prints a spurious stack trace on Ubuntu. - Issue #17249: convert a test in test_capi to use unittest and reap threads.