1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
|
"""
Tests for coroutines.
Imported into test_coroutine.py when running tests under Python 3.5 or later;
in earlier versions of Python this code is a syntax error.
"""
import asyncio
from unittest import TestCase
from ..testing import capture_logging
from ..parse import Parser
from .. import start_action
async def standalone_coro():
"""
Log a message inside a new coroutine.
"""
await asyncio.sleep(0.1)
with start_action(action_type="standalone"):
pass
async def calling_coro():
"""
Log an action inside a coroutine, and call another coroutine.
"""
with start_action(action_type="calling"):
await standalone_coro()
def run_coroutines(*async_functions):
"""
Run a coroutine until it finishes.
"""
loop = asyncio.get_event_loop()
futures = [asyncio.ensure_future(f()) for f in async_functions]
async def wait_for_futures():
for future in futures:
await future
loop.run_until_complete(wait_for_futures())
class CoroutineTests(TestCase):
"""
Tests for coroutines.
"""
@capture_logging(None)
def test_multiple_coroutines_contexts(self, logger):
"""
Each top-level coroutine has its own Eliot logging context.
"""
async def waiting_coro():
with start_action(action_type="waiting"):
await asyncio.sleep(0.5)
run_coroutines(waiting_coro, standalone_coro)
trees = Parser.parse_stream(logger.messages)
self.assertEqual(
sorted([(t.root().action_type, t.root().children) for t in trees]),
[("standalone", []), ("waiting", [])],
)
@capture_logging(None)
def test_await_inherits_coroutine_contexts(self, logger):
"""
awaited coroutines inherit the logging context.
"""
run_coroutines(calling_coro)
[tree] = Parser.parse_stream(logger.messages)
root = tree.root()
[child] = root.children
self.assertEqual(
(root.action_type, child.action_type, child.children),
("calling", "standalone", []),
)
@capture_logging(None)
def test_interleaved_coroutines(self, logger):
"""
start_action() started in one coroutine doesn't impact another in a
different coroutine.
"""
async def coro_sleep(delay, action_type):
with start_action(action_type=action_type):
await asyncio.sleep(delay)
async def main():
with start_action(action_type="main"):
f1 = asyncio.ensure_future(coro_sleep(1, "a"))
f2 = asyncio.ensure_future(coro_sleep(0.5, "b"))
await f1
await f2
run_coroutines(main)
[tree] = list(Parser.parse_stream(logger.messages))
root = tree.root()
self.assertEqual(root.action_type, "main")
self.assertEqual(sorted([c.action_type for c in root.children]), ["a", "b"])
|