Mercurial > ~astiob > upreckon > hgweb
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() |