diff -r eec4758e3a45 Lib/test/test_asyncio/echo.py --- a/Lib/test/test_asyncio/echo.py Thu Nov 21 10:25:09 2013 +0100 +++ b/Lib/test/test_asyncio/echo.py Thu Nov 21 11:09:41 2013 +0100 @@ -1,6 +1,9 @@ import os +from test.test_asyncio.watchdog import setup_watchdog if __name__ == '__main__': + setup_watchdog() + while True: buf = os.read(0, 1024) if not buf: diff -r eec4758e3a45 Lib/test/test_asyncio/echo2.py --- a/Lib/test/test_asyncio/echo2.py Thu Nov 21 10:25:09 2013 +0100 +++ b/Lib/test/test_asyncio/echo2.py Thu Nov 21 11:09:41 2013 +0100 @@ -1,6 +1,9 @@ import os +from test.test_asyncio.watchdog import setup_watchdog if __name__ == '__main__': + setup_watchdog() + buf = os.read(0, 1024) os.write(1, b'OUT:'+buf) os.write(2, b'ERR:'+buf) diff -r eec4758e3a45 Lib/test/test_asyncio/echo3.py --- a/Lib/test/test_asyncio/echo3.py Thu Nov 21 10:25:09 2013 +0100 +++ b/Lib/test/test_asyncio/echo3.py Thu Nov 21 11:09:41 2013 +0100 @@ -1,6 +1,9 @@ import os +from test.test_asyncio.watchdog import setup_watchdog if __name__ == '__main__': + setup_watchdog() + while True: buf = os.read(0, 1024) if not buf: diff -r eec4758e3a45 Lib/test/test_asyncio/test_events.py --- a/Lib/test/test_asyncio/test_events.py Thu Nov 21 10:25:09 2013 +0100 +++ b/Lib/test/test_asyncio/test_events.py Thu Nov 21 11:09:41 2013 +0100 @@ -162,6 +162,8 @@ class MySubprocessProtocol(protocols.Sub assert self.state == 'CONNECTED', self.state self.state = 'CLOSED' self.completed.set_result(None) + for event in self.got_data.values(): + event.set() def pipe_data_received(self, fd, data): assert self.state == 'CONNECTED', self.state @@ -960,19 +962,26 @@ class EventLoopTestsMixin: class SubprocessTestsMixin: - def check_terminated(self, returncode): + def debug_info(self, proto): + return ("returncode=%r, stdout=%a, stderr=%a" + % (proto.returncode, proto.data[1], proto.data[2])) + + def check_returncode(self, proto, exitcode): + self.assertEqual(exitcode, proto.returncode, self.debug_info(proto)) + + def check_terminated(self, proto): if sys.platform == 'win32': - self.assertIsInstance(returncode, int) + self.assertIsInstance(proto.returncode, int) # expect 1 but sometimes get 0 else: - self.assertEqual(-signal.SIGTERM, returncode) + self.check_returncode(proto, -signal.SIGTERM) - def check_killed(self, returncode): + def check_killed(self, proto): if sys.platform == 'win32': - self.assertIsInstance(returncode, int) + self.assertIsInstance(proto.returncode, int) # expect 1 but sometimes get 0 else: - self.assertEqual(-signal.SIGKILL, returncode) + self.check_returncode(proto, -signal.SIGKILL) def test_subprocess_exec(self): proto = None @@ -997,7 +1006,7 @@ class SubprocessTestsMixin: self.loop.run_until_complete(proto.got_data[1].wait()) transp.close() self.loop.run_until_complete(proto.completed) - self.check_terminated(proto.returncode) + self.check_terminated(proto) self.assertEqual(b'Python The Winner', proto.data[1]) def test_subprocess_interactive(self): @@ -1032,7 +1041,7 @@ class SubprocessTestsMixin: transp.close() self.loop.run_until_complete(proto.completed) - self.check_terminated(proto.returncode) + self.check_terminated(proto) def test_subprocess_shell(self): proto = None @@ -1051,7 +1060,7 @@ class SubprocessTestsMixin: transp.get_pipe_transport(0).close() self.loop.run_until_complete(proto.completed) - self.assertEqual(0, proto.returncode) + self.check_returncode(proto, 0) self.assertTrue(all(f.done() for f in proto.disconnects.values())) self.assertEqual(proto.data[1].rstrip(b'\r\n'), b'Python') self.assertEqual(proto.data[2], b'') @@ -1069,7 +1078,7 @@ class SubprocessTestsMixin: self.loop.run_until_complete(connect()) self.loop.run_until_complete(proto.completed) - self.assertEqual(7, proto.returncode) + self.check_returncode(proto, 7) def test_subprocess_close_after_finish(self): proto = None @@ -1088,7 +1097,7 @@ class SubprocessTestsMixin: self.assertIsNone(transp.get_pipe_transport(1)) self.assertIsNone(transp.get_pipe_transport(2)) self.loop.run_until_complete(proto.completed) - self.assertEqual(7, proto.returncode) + self.check_returncode(proto, 7) self.assertIsNone(transp.close()) def test_subprocess_kill(self): @@ -1110,7 +1119,7 @@ class SubprocessTestsMixin: transp.kill() self.loop.run_until_complete(proto.completed) - self.check_killed(proto.returncode) + self.check_killed(proto) def test_subprocess_terminate(self): proto = None @@ -1131,7 +1140,7 @@ class SubprocessTestsMixin: transp.terminate() self.loop.run_until_complete(proto.completed) - self.check_terminated(proto.returncode) + self.check_terminated(proto) @unittest.skipIf(sys.platform == 'win32', "Don't have SIGHUP") def test_subprocess_send_signal(self): @@ -1153,7 +1162,8 @@ class SubprocessTestsMixin: transp.send_signal(signal.SIGHUP) self.loop.run_until_complete(proto.completed) - self.assertEqual(-signal.SIGHUP, proto.returncode) + self.check_returncode(proto, -signal.SIGHUP) + def test_subprocess_stderr(self): proto = None @@ -1178,9 +1188,10 @@ class SubprocessTestsMixin: self.loop.run_until_complete(proto.completed) transp.close() + self.check_returncode(proto, 0) + self.assertEqual(b'OUT:test', proto.data[1]) self.assertTrue(proto.data[2].startswith(b'ERR:test'), proto.data[2]) - self.assertEqual(0, proto.returncode) def test_subprocess_stderr_redirect_to_stdout(self): proto = None @@ -1205,12 +1216,13 @@ class SubprocessTestsMixin: stdin.write(b'test') self.loop.run_until_complete(proto.completed) + self.check_returncode(proto, 0) + self.assertTrue(proto.data[1].startswith(b'OUT:testERR:test'), proto.data[1]) self.assertEqual(b'', proto.data[2]) transp.close() - self.assertEqual(0, proto.returncode) def test_subprocess_close_client_stream(self): proto = None @@ -1233,23 +1245,26 @@ class SubprocessTestsMixin: stdout = transp.get_pipe_transport(1) stdin.write(b'test') self.loop.run_until_complete(proto.got_data[1].wait()) - self.assertEqual(b'OUT:test', proto.data[1]) + self.assertEqual(b'OUT:test', proto.data[1], + self.debug_info(proto)) stdout.close() self.loop.run_until_complete(proto.disconnects[1]) stdin.write(b'xxx') self.loop.run_until_complete(proto.got_data[2].wait()) if sys.platform != 'win32': - self.assertEqual(b'ERR:BrokenPipeError', proto.data[2]) + self.assertEqual(b'ERR:BrokenPipeError', proto.data[2], + self.debug_info(proto)) else: # After closing the read-end of a pipe, writing to the # write-end using os.write() fails with errno==EINVAL and # GetLastError()==ERROR_INVALID_NAME on Windows!?! (Using # WriteFile() we get ERROR_BROKEN_PIPE as expected.) - self.assertEqual(b'ERR:OSError', proto.data[2]) + self.assertEqual(b'ERR:OSError', proto.data[2], + self.debug_info(proto)) transp.close() self.loop.run_until_complete(proto.completed) - self.check_terminated(proto.returncode) + self.check_terminated(proto) def test_subprocess_wait_no_same_group(self): proto = None @@ -1267,7 +1282,7 @@ class SubprocessTestsMixin: self.loop.run_until_complete(connect()) self.loop.run_until_complete(proto.completed) - self.assertEqual(7, proto.returncode) + self.check_returncode(proto, 7) if sys.platform == 'win32': diff -r eec4758e3a45 Lib/test/test_asyncio/watchdog.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Lib/test/test_asyncio/watchdog.py Thu Nov 21 11:09:41 2013 +0100 @@ -0,0 +1,12 @@ +def setup_watchdog(timeout=5*60): + """ + Setup a watchdog killing the process if it runs longer than timeout + seconds. + """ + try: + import faulthandler + except ImportError: + pass + else: + faulthandler.dump_traceback_later(timeout, exit=True) +