comparison testcases.py @ 61:24f144e11b5e

Accurate run-time reporting on Win32
author Oleg Oshmyan <chortos@inbox.lv>
date Tue, 21 Dec 2010 19:38:58 +0200
parents c95addbe0851
children 593ad09cd69b
comparison
equal deleted inserted replaced
60:7c6dba0b84f2 61:24f144e11b5e
92 from signal import SIGCHLD, signal, SIG_DFL 92 from signal import SIGCHLD, signal, SIG_DFL
93 from select import select, error as select_error 93 from select import select, error as select_error
94 from errno import EINTR 94 from errno import EINTR
95 except ImportError: 95 except ImportError:
96 try: 96 try:
97 from _subprocess import WAIT_OBJECT_0, STD_INPUT_HANDLE, INFINITE
98 except ImportError:
99 WAIT_OBJECT_0 = 0
100 STD_INPUT_HANDLE = -10
101 INFINITE = -1
102 try:
97 import ctypes 103 import ctypes
104 SetConsoleMode = ctypes.windll.kernel32.SetConsoleMode
105 FlushConsoleInputBuffer = ctypes.windll.kernel32.FlushConsoleInputBuffer
98 WaitForMultipleObjects = ctypes.windll.kernel32.WaitForMultipleObjects 106 WaitForMultipleObjects = ctypes.windll.kernel32.WaitForMultipleObjects
107 ReadConsoleInputA = ctypes.windll.kernel32.ReadConsoleInputA
108 try:
109 from _subprocess import GetStdHandle
110 except ImportError:
111 GetStdHandle = ctypes.windll.kernel32.GetStdHandle
99 except (ImportError, AttributeError): 112 except (ImportError, AttributeError):
100 pass 113 console_input = False
101 else: 114 else:
102 # TODO: implement Win32 call() 115 hStdin = GetStdHandle(STD_INPUT_HANDLE)
103 pass 116 console_input = bool(SetConsoleMode(hStdin, 1))
104 call = None 117 if console_input:
118 FlushConsoleInputBuffer(hStdin)
119 class KEY_EVENT_RECORD(ctypes.Structure):
120 _fields_ = (("bKeyDown", ctypes.c_int),
121 ("wRepeatCount", ctypes.c_ushort),
122 ("wVirtualKeyCode", ctypes.c_ushort),
123 ("wVirtualScanCode", ctypes.c_ushort),
124 ("UnicodeChar", ctypes.c_wchar),
125 ("dwControlKeyState", ctypes.c_uint))
126 class INPUT_RECORD(ctypes.Structure):
127 _fields_ = (("EventType", ctypes.c_int),
128 ("KeyEvent", KEY_EVENT_RECORD))
129 # Memory limits (currently) are not supported
130 def call(*args, **kwargs):
131 case = kwargs.pop('case')
132 try:
133 case.process = Popen(*args, **kwargs)
134 except OSError:
135 raise CannotStartTestee(sys.exc_info()[1])
136 case.time_started = clock()
137 if not console_input:
138 if case.maxtime:
139 if WaitForSingleObject(case.process._handle, int(case.maxtime * 1000)) != WAIT_OBJECT_0:
140 raise TimeLimitExceeded
141 else:
142 case.process.wait()
143 else:
144 ir = INPUT_RECORD()
145 n = ctypes.c_int()
146 lpHandles = (ctypes.c_int * 2)(hStdin, case.process._handle)
147 if case.maxtime:
148 time_end = clock() + case.maxtime
149 while case.process.poll() is None:
150 remaining = time_end - clock()
151 if remaining > 0:
152 if WaitForMultipleObjects(2, lpHandles, False, int(remaining * 1000)) == WAIT_OBJECT_0:
153 ReadConsoleInputA(hStdin, ctypes.byref(ir), 1, ctypes.byref(n))
154 if ir.EventType == 1 and ir.KeyEvent.bKeyDown and ir.KeyEvent.wVirtualKeyCode == 27:
155 raise CanceledByUser
156 else:
157 raise TimeLimitExceeded
158 else:
159 while case.process.poll() is None:
160 if WaitForMultipleObjects(2, lpHandles, False, INFINITE) == WAIT_OBJECT_0:
161 ReadConsoleInputA(hStdin, ctypes.byref(ir), 1, ctypes.byref(n))
162 if ir.EventType == 1 and ir.KeyEvent.bKeyDown and ir.KeyEvent.wVirtualKeyCode == 27:
163 raise CanceledByUser
164 case.time_stopped = clock()
165 if not console_input:
166 try:
167 try:
168 from _subprocess import WaitForSingleObject
169 except ImportError:
170 import ctypes
171 WaitForSingleObject = ctypes.windll.kernel32.WaitForSingleObject
172 except (ImportError, AttributeError):
173 # TODO: move the default implementation here
174 call = None
105 else: 175 else:
106 # Make SIGCHLD interrupt sleep() and select() 176 # Make SIGCHLD interrupt sleep() and select()
107 def bury_child(signum, frame): 177 def bury_child(signum, frame):
108 try: 178 try:
109 bury_child.case.time_stopped = clock() 179 bury_child.case.time_stopped = clock()
112 signal(SIGCHLD, bury_child) 182 signal(SIGCHLD, bury_child)
113 183
114 # If you want this to work, don't set any stdio argument to PIPE 184 # If you want this to work, don't set any stdio argument to PIPE
115 def call_real(*args, **kwargs): 185 def call_real(*args, **kwargs):
116 bury_child.case = case = kwargs.pop('case') 186 bury_child.case = case = kwargs.pop('case')
117 # FIXME: kill the process no matter what
118 try: 187 try:
119 case.process = Popen(*args, **kwargs) 188 case.process = Popen(*args, **kwargs)
120 except OSError: 189 except OSError:
121 raise CannotStartTestee(sys.exc_info()[1]) 190 raise CannotStartTestee(sys.exc_info()[1])
122 case.time_started = clock() 191 case.time_started = clock()