def test_close_dont_kill_finished(self): @asyncio.coroutine def kill_running(): create = self.loop.subprocess_exec(asyncio.SubprocessProtocol, *PROGRAM_BLOCKED) transport, protocol = yield From(create) proc = transport.get_extra_info('subprocess') # kill the process (but asyncio is not notified immediatly) proc.kill() proc.wait() proc.kill = mock.Mock() proc_returncode = proc.poll() transport_returncode = transport.get_returncode() transport.close() raise Return(proc_returncode, transport_returncode, proc.kill.called) # Ignore "Unknown child process pid ..." log of SafeChildWatcher, # emitted because the test already consumes the exit status: # proc.wait() with test_utils.disable_logger(): result = self.loop.run_until_complete(kill_running()) test_utils.run_briefly(self.loop) proc_returncode, transport_return_code, killed = result self.assertIsNotNone(proc_returncode) self.assertIsNone(transport_return_code) # transport.close() must not kill the process if it finished, even if # the transport was not notified yet self.assertFalse(killed)
def tearDown(self): # just in case if we have transport close callbacks test_utils.run_briefly(self.loop) self.loop.close() gc.collect() super(StreamReaderTests, self).tearDown()
def test_wrap_future_cancel(self): f1 = concurrent.futures.Future() f2 = asyncio.wrap_future(f1, loop=self.loop) f2.cancel() test_utils.run_briefly(self.loop) self.assertTrue(f1.cancelled()) self.assertTrue(f2.cancelled())
def test_clear_with_waiters(self): ev = asyncio.Event(loop=self.loop) result = [] @asyncio.coroutine def c1(result): if (yield From(ev.wait())): result.append(1) raise Return(True) t = asyncio.Task(c1(result), loop=self.loop) test_utils.run_briefly(self.loop) self.assertEqual([], result) ev.set() ev.clear() self.assertFalse(ev.is_set()) ev.set() ev.set() self.assertEqual(1, len(ev._waiters)) test_utils.run_briefly(self.loop) self.assertEqual([1], result) self.assertEqual(0, len(ev._waiters)) self.assertTrue(t.done()) self.assertTrue(t.result())
def test_get_with_waiting_putters(self): q = asyncio.Queue(loop=self.loop, maxsize=1) asyncio.Task(q.put('a'), loop=self.loop) asyncio.Task(q.put('b'), loop=self.loop) test_utils.run_briefly(self.loop) self.assertEqual(self.loop.run_until_complete(q.get()), 'a') self.assertEqual(self.loop.run_until_complete(q.get()), 'b')
def test_ctor(self): fut = asyncio.Future(loop=self.loop) tr = self.socket_transport(waiter=fut) test_utils.run_briefly(self.loop) self.assertIsNone(fut.result()) self.protocol.connection_made(tr) self.proactor.recv.assert_called_with(self.sock, 4096)
def test_close_kill_running(self): @asyncio.coroutine def kill_running(): create = self.loop.subprocess_exec(asyncio.SubprocessProtocol, *PROGRAM_BLOCKED) transport, protocol = yield From(create) non_local = {'kill_called': False} def kill(): non_local['kill_called'] = True orig_kill() proc = transport.get_extra_info('subprocess') orig_kill = proc.kill proc.kill = kill returncode = transport.get_returncode() transport.close() yield From(transport._wait()) raise Return(returncode, non_local['kill_called']) # Ignore "Close running child process: kill ..." log with test_utils.disable_logger(): returncode, killed = self.loop.run_until_complete(kill_running()) self.assertIsNone(returncode) # transport.close() must kill the process if it is still running self.assertTrue(killed) test_utils.run_briefly(self.loop)
def test_fatal_error_2(self): tr = self.socket_transport() tr._buffer = [b'data'] tr._force_close(None) test_utils.run_briefly(self.loop) self.protocol.connection_lost.assert_called_with(None) self.assertEqual(None, tr._buffer)
def test_fatal_error_2(self): tr = _ProactorSocketTransport(self.loop, self.sock, self.protocol) tr._buffer = [b'data'] tr._force_close(None) test_utils.run_briefly(self.loop) self.protocol.connection_lost.assert_called_with(None) self.assertEqual(None, tr._buffer)
def _basetest_open_connection_error(self, open_connection_fut): reader, writer = self.loop.run_until_complete(open_connection_fut) writer._protocol.connection_lost(ZeroDivisionError()) f = reader.read() with self.assertRaises(ZeroDivisionError): self.loop.run_until_complete(f) writer.close() test_utils.run_briefly(self.loop)
def test_wrap_future_cancel2(self): f1 = concurrent.futures.Future() f2 = asyncio.wrap_future(f1, loop=self.loop) f1.set_result(42) f2.cancel() test_utils.run_briefly(self.loop) self.assertFalse(f1.cancelled()) self.assertEqual(f1.result(), 42) self.assertTrue(f2.cancelled())
def test_tb_logger_exception_unretrieved(self, m_log): self.loop.set_debug(True) asyncio.set_event_loop(self.loop) fut = asyncio.Future(loop=self.loop) fut.set_exception(RuntimeError('boom')) del fut test_utils.run_briefly(self.loop) support.gc_collect() self.assertTrue(m_log.error.called)
def test_tb_logger_exception_unretrieved(self, m_log): self.loop.set_debug(True) asyncio.set_event_loop(self.loop) fut = asyncio.Future(loop=self.loop) fut.set_exception(RuntimeError("boom")) del fut test_utils.run_briefly(self.loop) support.gc_collect() self.assertTrue(m_log.error.called)
def test_loop_writing_closing(self): fut = asyncio.Future(loop=self.loop) fut.set_result(1) tr = _ProactorSocketTransport(self.loop, self.sock, self.protocol) tr._write_fut = fut tr.close() tr._loop_writing(fut) self.assertIsNone(tr._write_fut) test_utils.run_briefly(self.loop) self.protocol.connection_lost.assert_called_with(None)
def test_call_later_negative_delays(self): calls = [] def cb(arg): calls.append(arg) self.loop._process_events = mock.Mock() self.loop.call_later(-1, cb, "a") self.loop.call_later(-2, cb, "b") test_utils.run_briefly(self.loop) self.assertEqual(calls, ["b", "a"])
def test_call_later_negative_delays(self): calls = [] def cb(arg): calls.append(arg) self.loop._process_events = mock.Mock() self.loop.call_later(-1, cb, 'a') self.loop.call_later(-2, cb, 'b') test_utils.run_briefly(self.loop) self.assertEqual(calls, ['b', 'a'])
def test_loop_writing_closing(self): fut = asyncio.Future(loop=self.loop) fut.set_result(1) tr = self.socket_transport() tr._write_fut = fut tr.close() tr._loop_writing(fut) self.assertIsNone(tr._write_fut) test_utils.run_briefly(self.loop) self.protocol.connection_lost.assert_called_with(None)
def test_acquire(self): lock = asyncio.Lock(loop=self.loop) result = [] self.assertTrue(self.loop.run_until_complete(lock.acquire())) @asyncio.coroutine def c1(result): if (yield From(lock.acquire())): result.append(1) raise Return(True) @asyncio.coroutine def c2(result): if (yield From(lock.acquire())): result.append(2) raise Return(True) @asyncio.coroutine def c3(result): if (yield From(lock.acquire())): result.append(3) raise Return(True) t1 = asyncio.Task(c1(result), loop=self.loop) t2 = asyncio.Task(c2(result), loop=self.loop) test_utils.run_briefly(self.loop) self.assertEqual([], result) lock.release() test_utils.run_briefly(self.loop) self.assertEqual([1], result) test_utils.run_briefly(self.loop) self.assertEqual([1], result) t3 = asyncio.Task(c3(result), loop=self.loop) lock.release() test_utils.run_briefly(self.loop) self.assertEqual([1, 2], result) lock.release() test_utils.run_briefly(self.loop) self.assertEqual([1, 2, 3], result) self.assertTrue(t1.done()) self.assertTrue(t1.result()) self.assertTrue(t2.done()) self.assertTrue(t2.result()) self.assertTrue(t3.done()) self.assertTrue(t3.result())
def test_close(self): tr = _ProactorSocketTransport(self.loop, self.sock, self.protocol) tr.close() test_utils.run_briefly(self.loop) self.protocol.connection_lost.assert_called_with(None) self.assertTrue(tr._closing) self.assertEqual(tr._conn_lost, 1) self.protocol.connection_lost.reset_mock() tr.close() test_utils.run_briefly(self.loop) self.assertFalse(self.protocol.connection_lost.called)
def test_close(self): tr = self.socket_transport() tr.close() test_utils.run_briefly(self.loop) self.protocol.connection_lost.assert_called_with(None) self.assertTrue(tr._closing) self.assertEqual(tr._conn_lost, 1) self.protocol.connection_lost.reset_mock() tr.close() test_utils.run_briefly(self.loop) self.assertFalse(self.protocol.connection_lost.called)
def test_force_close(self): tr = _ProactorSocketTransport(self.loop, self.sock, self.protocol) tr._buffer = [b'data'] read_fut = tr._read_fut = mock.Mock() write_fut = tr._write_fut = mock.Mock() tr._force_close(None) read_fut.cancel.assert_called_with() write_fut.cancel.assert_called_with() test_utils.run_briefly(self.loop) self.protocol.connection_lost.assert_called_with(None) self.assertEqual(None, tr._buffer) self.assertEqual(tr._conn_lost, 1)
def test_force_close(self): tr = self.socket_transport() tr._buffer = [b'data'] read_fut = tr._read_fut = mock.Mock() write_fut = tr._write_fut = mock.Mock() tr._force_close(None) read_fut.cancel.assert_called_with() write_fut.cancel.assert_called_with() test_utils.run_briefly(self.loop) self.protocol.connection_lost.assert_called_with(None) self.assertEqual(None, tr._buffer) self.assertEqual(tr._conn_lost, 1)
def test_put_cancelled_race(self): q = asyncio.Queue(loop=self.loop, maxsize=1) put_a = asyncio.Task(q.put('a'), loop=self.loop) put_b = asyncio.Task(q.put('b'), loop=self.loop) put_c = asyncio.Task(q.put('X'), loop=self.loop) test_utils.run_briefly(self.loop) self.assertTrue(put_a.done()) self.assertFalse(put_b.done()) put_c.cancel() test_utils.run_briefly(self.loop) self.assertTrue(put_c.done()) self.assertEqual(q.get_nowait(), 'a') self.assertEqual(q.get_nowait(), 'b') self.loop.run_until_complete(put_b)
def test_cancel_post_init(self): @asyncio.coroutine def cancel_make_transport(): coro = self.loop.subprocess_exec(asyncio.SubprocessProtocol, *PROGRAM_BLOCKED) task = self.loop.create_task(coro) self.loop.call_soon(task.cancel) try: yield From(task) except asyncio.CancelledError: pass # ignore the log: # "Exception during subprocess creation, kill the subprocess" with test_utils.disable_logger(): self.loop.run_until_complete(cancel_make_transport()) test_utils.run_briefly(self.loop)
def test_wait(self): ev = asyncio.Event(loop=self.loop) self.assertFalse(ev.is_set()) result = [] @asyncio.coroutine def c1(result): if (yield From(ev.wait())): result.append(1) @asyncio.coroutine def c2(result): if (yield From(ev.wait())): result.append(2) @asyncio.coroutine def c3(result): if (yield From(ev.wait())): result.append(3) t1 = asyncio.Task(c1(result), loop=self.loop) t2 = asyncio.Task(c2(result), loop=self.loop) test_utils.run_briefly(self.loop, 2) self.assertEqual([], result) t3 = asyncio.Task(c3(result), loop=self.loop) ev.set() test_utils.run_briefly(self.loop, 2) self.assertEqual([1, 2, 3], result) self.assertTrue(t1.done()) self.assertIsNone(t1.result()) self.assertTrue(t2.done()) self.assertIsNone(t2.result()) self.assertTrue(t3.done()) self.assertIsNone(t3.result())
def test_notify_all(self): cond = asyncio.Condition(loop=self.loop) result = [] @asyncio.coroutine def c1(result): yield From(cond.acquire()) if (yield From(cond.wait())): result.append(1) cond.release() raise Return(True) @asyncio.coroutine def c2(result): yield From(cond.acquire()) if (yield From(cond.wait())): result.append(2) cond.release() raise Return(True) t1 = asyncio.Task(c1(result), loop=self.loop) t2 = asyncio.Task(c2(result), loop=self.loop) test_utils.run_briefly(self.loop) self.assertEqual([], result) self.loop.run_until_complete(cond.acquire()) cond.notify_all() cond.release() # each coroutine requires 2 runs of the event loop test_utils.run_briefly(self.loop, 4) self.assertEqual([1, 2], result) self.assertTrue(t1.done()) self.assertTrue(t1.result()) self.assertTrue(t2.done()) self.assertTrue(t2.result())
def test_cancel_race(self): # Several tasks: # - A acquires the lock # - B is blocked in aqcuire() # - C is blocked in aqcuire() # # Now, concurrently: # - B is cancelled # - A releases the lock # # If B's waiter is marked cancelled but not yet removed from # _waiters, A's release() call will crash when trying to set # B's waiter; instead, it should move on to C's waiter. # Setup: A has the lock, b and c are waiting. lock = asyncio.Lock(loop=self.loop) @asyncio.coroutine def lockit(name, blocker): yield From(lock.acquire()) try: if blocker is not None: yield From(blocker) finally: lock.release() fa = asyncio.Future(loop=self.loop) ta = asyncio.Task(lockit('A', fa), loop=self.loop) test_utils.run_briefly(self.loop, 2) self.assertTrue(lock.locked()) tb = asyncio.Task(lockit('B', None), loop=self.loop) test_utils.run_briefly(self.loop, 2) self.assertEqual(len(lock._waiters), 1) tc = asyncio.Task(lockit('C', None), loop=self.loop) test_utils.run_briefly(self.loop, 2) self.assertEqual(len(lock._waiters), 2) # Create the race and check. # Without the fix this failed at the last assert. fa.set_result(None) tb.cancel() self.assertTrue(lock._waiters[0].cancelled()) test_utils.run_briefly(self.loop, 2) self.assertFalse(lock.locked()) self.assertTrue(ta.done()) self.assertTrue(tb.cancelled()) self.assertTrue(tc.done())
def test_exception_cancel(self): stream = asyncio.StreamReader(loop=self.loop) t = asyncio.Task(stream.readline(), loop=self.loop) test_utils.run_briefly(self.loop) t.cancel() test_utils.run_briefly(self.loop) # The following line fails if set_exception() isn't careful. stream.set_exception(RuntimeError('message')) test_utils.run_briefly(self.loop) self.assertIs(stream._waiter, None)
def test_get_cancelled_race(self): q = asyncio.Queue(loop=self.loop) t1 = asyncio.Task(q.get(), loop=self.loop) t2 = asyncio.Task(q.get(), loop=self.loop) test_utils.run_briefly(self.loop) t1.cancel() test_utils.run_briefly(self.loop) self.assertTrue(t1.done()) q.put_nowait('a') test_utils.run_briefly(self.loop) self.assertEqual(t2.result(), 'a')
def test_wait_for(self): cond = asyncio.Condition(loop=self.loop) presult = False def predicate(): return presult result = [] @asyncio.coroutine def c1(result): yield From(cond.acquire()) if (yield From(cond.wait_for(predicate))): result.append(1) cond.release() raise Return(True) t = asyncio.Task(c1(result), loop=self.loop) test_utils.run_briefly(self.loop) self.assertEqual([], result) self.loop.run_until_complete(cond.acquire()) cond.notify() cond.release() test_utils.run_briefly(self.loop) self.assertEqual([], result) presult = True self.loop.run_until_complete(cond.acquire()) cond.notify() cond.release() test_utils.run_briefly(self.loop) self.assertEqual([1], result) self.assertTrue(t.done()) self.assertTrue(t.result())
def test_force_close_idempotent(self): tr = self.socket_transport() tr._closing = True tr._force_close(None) test_utils.run_briefly(self.loop) self.assertFalse(self.protocol.connection_lost.called)
def test_put_with_waiting_getters(self): q = asyncio.Queue(loop=self.loop) t = asyncio.Task(q.get(), loop=self.loop) test_utils.run_briefly(self.loop) self.loop.run_until_complete(q.put('a')) self.assertEqual(self.loop.run_until_complete(t), 'a')
def test_acquire(self): sem = asyncio.Semaphore(3, loop=self.loop) result = [] self.assertTrue(self.loop.run_until_complete(sem.acquire())) self.assertTrue(self.loop.run_until_complete(sem.acquire())) self.assertFalse(sem.locked()) @asyncio.coroutine def c1(result): yield From(sem.acquire()) result.append(1) raise Return(True) @asyncio.coroutine def c2(result): yield From(sem.acquire()) result.append(2) raise Return(True) @asyncio.coroutine def c3(result): yield From(sem.acquire()) result.append(3) raise Return(True) @asyncio.coroutine def c4(result): yield From(sem.acquire()) result.append(4) raise Return(True) t1 = asyncio.Task(c1(result), loop=self.loop) t2 = asyncio.Task(c2(result), loop=self.loop) t3 = asyncio.Task(c3(result), loop=self.loop) # each coroutine requires 2 runs of the event loop test_utils.run_briefly(self.loop, 2) self.assertEqual([1], result) self.assertTrue(sem.locked()) self.assertEqual(2, len(sem._waiters)) self.assertEqual(0, sem._value) t4 = asyncio.Task(c4(result), loop=self.loop) sem.release() sem.release() self.assertEqual(2, sem._value) test_utils.run_briefly(self.loop) self.assertEqual(0, sem._value) self.assertEqual([1, 2, 3], result) self.assertTrue(sem.locked()) self.assertEqual(1, len(sem._waiters)) self.assertEqual(0, sem._value) self.assertTrue(t1.done()) self.assertTrue(t1.result()) self.assertTrue(t2.done()) self.assertTrue(t2.result()) self.assertTrue(t3.done()) self.assertTrue(t3.result()) self.assertFalse(t4.done()) # cleanup locked semaphore sem.release() self.loop.run_until_complete(t4)
def test_close_write_fut(self): tr = _ProactorSocketTransport(self.loop, self.sock, self.protocol) tr._write_fut = mock.Mock() tr.close() test_utils.run_briefly(self.loop) self.assertFalse(self.protocol.connection_lost.called)
def test_wait(self): cond = asyncio.Condition(loop=self.loop) result = [] @asyncio.coroutine def c1(result): yield From(cond.acquire()) if (yield From(cond.wait())): result.append(1) raise Return(True) @asyncio.coroutine def c2(result): yield From(cond.acquire()) if (yield From(cond.wait())): result.append(2) raise Return(True) @asyncio.coroutine def c3(result): yield From(cond.acquire()) if (yield From(cond.wait())): result.append(3) raise Return(True) t1 = asyncio.Task(c1(result), loop=self.loop) t2 = asyncio.Task(c2(result), loop=self.loop) t3 = asyncio.Task(c3(result), loop=self.loop) test_utils.run_briefly(self.loop, 2) self.assertEqual([], result) self.assertFalse(cond.locked()) self.assertTrue(self.loop.run_until_complete(cond.acquire())) cond.notify() test_utils.run_briefly(self.loop, 2) self.assertEqual([], result) self.assertTrue(cond.locked()) cond.release() test_utils.run_briefly(self.loop, 2) self.assertEqual([1], result) self.assertTrue(cond.locked()) cond.notify(2) test_utils.run_briefly(self.loop, 2) self.assertEqual([1], result) self.assertTrue(cond.locked()) cond.release() test_utils.run_briefly(self.loop, 2) self.assertEqual([1, 2], result) self.assertTrue(cond.locked()) cond.release() test_utils.run_briefly(self.loop, 2) self.assertEqual([1, 2, 3], result) self.assertTrue(cond.locked()) self.assertTrue(t1.done()) self.assertTrue(t1.result()) self.assertTrue(t2.done()) self.assertTrue(t2.result()) self.assertTrue(t3.done()) self.assertTrue(t3.result())
def run_briefly(self): test_utils.run_briefly(self.loop)
def check_future_exception_never_retrieved(self, debug, m_log): self.loop.set_debug(debug) def memory_error(): try: raise MemoryError() except BaseException as exc: return exc exc = memory_error() future = asyncio.Future(loop=self.loop) if debug: source_traceback = future._source_traceback future.set_exception(exc) future = None test_utils.run_briefly(self.loop) support.gc_collect() if sys.version_info >= (3, 4): if debug: frame = source_traceback[-1] regex = (r'^Future exception was never retrieved\n' r'future: <Future finished exception=MemoryError\(\) ' r'created at {filename}:{lineno}>\n' r'source_traceback: Object ' r'created at \(most recent call last\):\n' r' File' r'.*\n' r' File "{filename}", line {lineno}, ' r'in check_future_exception_never_retrieved\n' r' future = asyncio\.Future\(loop=self\.loop\)$' ).format(filename=re.escape(frame[0]), lineno=frame[1]) else: regex = (r'^Future exception was never retrieved\n' r'future: ' r'<Future finished exception=MemoryError\(\)>$') exc_info = (type(exc), exc, exc.__traceback__) m_log.error.assert_called_once_with(mock.ANY, exc_info=exc_info) else: if debug: frame = source_traceback[-1] regex = (r'^Future/Task exception was never retrieved\n' r'Future/Task created at \(most recent call last\):\n' r' File' r'.*\n' r' File "{filename}", line {lineno}, ' r'in check_future_exception_never_retrieved\n' r' future = asyncio\.Future\(loop=self\.loop\)\n' r'Traceback \(most recent call last\):\n' r'.*\n' r'MemoryError$').format(filename=re.escape(frame[0]), lineno=frame[1]) elif compat.PY3: regex = (r'^Future/Task exception was never retrieved\n' r'Traceback \(most recent call last\):\n' r'.*\n' r'MemoryError$') else: regex = (r'^Future/Task exception was never retrieved\n' r'MemoryError$') m_log.error.assert_called_once_with(mock.ANY, exc_info=False) message = m_log.error.call_args[0][0] self.assertRegex(message, re.compile(regex, re.DOTALL))
def test_close_buffer(self): tr = _ProactorSocketTransport(self.loop, self.sock, self.protocol) tr._buffer = [b'data'] tr.close() test_utils.run_briefly(self.loop) self.assertFalse(self.protocol.connection_lost.called)
def check_future_exception_never_retrieved(self, debug, m_log): self.loop.set_debug(debug) def memory_error(): try: raise MemoryError() except BaseException as exc: return exc exc = memory_error() future = asyncio.Future(loop=self.loop) if debug: source_traceback = future._source_traceback future.set_exception(exc) future = None test_utils.run_briefly(self.loop) support.gc_collect() if sys.version_info >= (3, 4): if debug: frame = source_traceback[-1] regex = ( r"^Future exception was never retrieved\n" r"future: <Future finished exception=MemoryError\(\) created at {filename}:{lineno}>\n" r"source_traceback: Object created at \(most recent call last\):\n" r" File" r".*\n" r' File "{filename}", line {lineno}, in check_future_exception_never_retrieved\n' r" future = asyncio\.Future\(loop=self\.loop\)$" ).format(filename=re.escape(frame[0]), lineno=frame[1]) else: regex = ( r"^Future exception was never retrieved\n" r"future: <Future finished exception=MemoryError\(\)>$" ) exc_info = (type(exc), exc, exc.__traceback__) m_log.error.assert_called_once_with(mock.ANY, exc_info=exc_info) else: if debug: frame = source_traceback[-1] regex = ( r"^Future/Task exception was never retrieved\n" r"Future/Task created at \(most recent call last\):\n" r" File" r".*\n" r' File "{filename}", line {lineno}, in check_future_exception_never_retrieved\n' r" future = asyncio\.Future\(loop=self\.loop\)\n" r"Traceback \(most recent call last\):\n" r".*\n" r"MemoryError$" ).format(filename=re.escape(frame[0]), lineno=frame[1]) elif compat.PY3: regex = ( r"^Future/Task exception was never retrieved\n" r"Traceback \(most recent call last\):\n" r".*\n" r"MemoryError$" ) else: regex = r"^Future/Task exception was never retrieved\n" r"MemoryError$" m_log.error.assert_called_once_with(mock.ANY, exc_info=False) message = m_log.error.call_args[0][0] self.assertRegex(message, re.compile(regex, re.DOTALL))
def test_force_close_idempotent(self): tr = _ProactorSocketTransport(self.loop, self.sock, self.protocol) tr._closing = True tr._force_close(None) test_utils.run_briefly(self.loop) self.assertFalse(self.protocol.connection_lost.called)