# HG changeset patch # User Oleg Oshmyan # Date 1292953138 -7200 # Node ID 24f144e11b5e0b7d937a5e371d8d0553d76c91a0 # Parent 7c6dba0b84f216acb879c682bc6ed0899c92bad7 Accurate run-time reporting on Win32 diff -r 7c6dba0b84f2 -r 24f144e11b5e testcases.py --- a/testcases.py Tue Dec 21 03:08:04 2010 +0200 +++ b/testcases.py Tue Dec 21 19:38:58 2010 +0200 @@ -94,14 +94,84 @@ from errno import EINTR except ImportError: try: + from _subprocess import WAIT_OBJECT_0, STD_INPUT_HANDLE, INFINITE + except ImportError: + WAIT_OBJECT_0 = 0 + STD_INPUT_HANDLE = -10 + INFINITE = -1 + try: import ctypes + SetConsoleMode = ctypes.windll.kernel32.SetConsoleMode + FlushConsoleInputBuffer = ctypes.windll.kernel32.FlushConsoleInputBuffer WaitForMultipleObjects = ctypes.windll.kernel32.WaitForMultipleObjects + ReadConsoleInputA = ctypes.windll.kernel32.ReadConsoleInputA + try: + from _subprocess import GetStdHandle + except ImportError: + GetStdHandle = ctypes.windll.kernel32.GetStdHandle except (ImportError, AttributeError): - pass + console_input = False else: - # TODO: implement Win32 call() - pass - call = None + hStdin = GetStdHandle(STD_INPUT_HANDLE) + console_input = bool(SetConsoleMode(hStdin, 1)) + if console_input: + FlushConsoleInputBuffer(hStdin) + class KEY_EVENT_RECORD(ctypes.Structure): + _fields_ = (("bKeyDown", ctypes.c_int), + ("wRepeatCount", ctypes.c_ushort), + ("wVirtualKeyCode", ctypes.c_ushort), + ("wVirtualScanCode", ctypes.c_ushort), + ("UnicodeChar", ctypes.c_wchar), + ("dwControlKeyState", ctypes.c_uint)) + class INPUT_RECORD(ctypes.Structure): + _fields_ = (("EventType", ctypes.c_int), + ("KeyEvent", KEY_EVENT_RECORD)) + # Memory limits (currently) are not supported + def call(*args, **kwargs): + case = kwargs.pop('case') + try: + case.process = Popen(*args, **kwargs) + except OSError: + raise CannotStartTestee(sys.exc_info()[1]) + case.time_started = clock() + if not console_input: + if case.maxtime: + if WaitForSingleObject(case.process._handle, int(case.maxtime * 1000)) != WAIT_OBJECT_0: + raise TimeLimitExceeded + else: + case.process.wait() + else: + ir = INPUT_RECORD() + n = ctypes.c_int() + lpHandles = (ctypes.c_int * 2)(hStdin, case.process._handle) + if case.maxtime: + time_end = clock() + case.maxtime + while case.process.poll() is None: + remaining = time_end - clock() + if remaining > 0: + if WaitForMultipleObjects(2, lpHandles, False, int(remaining * 1000)) == WAIT_OBJECT_0: + ReadConsoleInputA(hStdin, ctypes.byref(ir), 1, ctypes.byref(n)) + if ir.EventType == 1 and ir.KeyEvent.bKeyDown and ir.KeyEvent.wVirtualKeyCode == 27: + raise CanceledByUser + else: + raise TimeLimitExceeded + else: + while case.process.poll() is None: + if WaitForMultipleObjects(2, lpHandles, False, INFINITE) == WAIT_OBJECT_0: + ReadConsoleInputA(hStdin, ctypes.byref(ir), 1, ctypes.byref(n)) + if ir.EventType == 1 and ir.KeyEvent.bKeyDown and ir.KeyEvent.wVirtualKeyCode == 27: + raise CanceledByUser + case.time_stopped = clock() + if not console_input: + try: + try: + from _subprocess import WaitForSingleObject + except ImportError: + import ctypes + WaitForSingleObject = ctypes.windll.kernel32.WaitForSingleObject + except (ImportError, AttributeError): + # TODO: move the default implementation here + call = None else: # Make SIGCHLD interrupt sleep() and select() def bury_child(signum, frame): @@ -114,7 +184,6 @@ # If you want this to work, don't set any stdio argument to PIPE def call_real(*args, **kwargs): bury_child.case = case = kwargs.pop('case') - # FIXME: kill the process no matter what try: case.process = Popen(*args, **kwargs) except OSError: