asyncio: Add asyncio tests for new task features.
This commit is contained in:
parent
adbb02d9e3
commit
e0d3123138
|
@ -0,0 +1,54 @@
|
|||
# Test the Task.add_done_callback() method
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
print("SKIP")
|
||||
raise SystemExit
|
||||
|
||||
|
||||
async def task(t, exc=None):
|
||||
if t >= 0:
|
||||
await asyncio.sleep(t)
|
||||
if exc:
|
||||
raise exc
|
||||
|
||||
|
||||
def done_callback(t, er):
|
||||
print("done", repr(t), repr(er))
|
||||
|
||||
|
||||
async def main():
|
||||
# Tasks that aren't done only execute done callback after finishing
|
||||
print("=" * 10)
|
||||
t = asyncio.create_task(task(-1))
|
||||
t.add_done_callback(done_callback)
|
||||
print("Waiting for task to complete")
|
||||
await asyncio.sleep(0)
|
||||
print("Task has completed")
|
||||
|
||||
# Task that are done run the callback immediately
|
||||
print("=" * 10)
|
||||
t = asyncio.create_task(task(-1))
|
||||
await asyncio.sleep(0)
|
||||
print("Task has completed")
|
||||
t.add_done_callback(done_callback)
|
||||
print("Callback Added")
|
||||
|
||||
# Task that starts, runs and finishes without an exception should return None
|
||||
print("=" * 10)
|
||||
t = asyncio.create_task(task(0.01))
|
||||
t.add_done_callback(done_callback)
|
||||
try:
|
||||
t.add_done_callback(done_callback)
|
||||
except RuntimeError as e:
|
||||
print("Second call to add_done_callback emits error:", repr(e))
|
||||
|
||||
# Task that raises immediately should still run done callback
|
||||
print("=" * 10)
|
||||
t = asyncio.create_task(task(-1, ValueError))
|
||||
t.add_done_callback(done_callback)
|
||||
await asyncio.sleep(0)
|
||||
|
||||
|
||||
asyncio.run(main())
|
|
@ -0,0 +1,12 @@
|
|||
==========
|
||||
Waiting for task to complete
|
||||
done <Task> StopIteration()
|
||||
Task has completed
|
||||
==========
|
||||
Task has completed
|
||||
done <Task> StopIteration()
|
||||
Callback Added
|
||||
==========
|
||||
Second call to add_done_callback emits error: RuntimeError('>1 callback unsupported',)
|
||||
==========
|
||||
done <Task> ValueError()
|
|
@ -0,0 +1,54 @@
|
|||
# Test the `Task.cancelled` method
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
print("SKIP")
|
||||
raise SystemExit
|
||||
|
||||
|
||||
async def task(t):
|
||||
await asyncio.sleep(t)
|
||||
|
||||
|
||||
async def main():
|
||||
# Cancel task immediately doesn't mark the task as cancelled
|
||||
print("=" * 10)
|
||||
t = asyncio.create_task(task(2))
|
||||
t.cancel()
|
||||
print("Expecting task to not be cancelled because it is not done:", t.cancelled())
|
||||
|
||||
# Cancel task immediately and wait for cancellation to complete
|
||||
print("=" * 10)
|
||||
t = asyncio.create_task(task(2))
|
||||
t.cancel()
|
||||
await asyncio.sleep(0)
|
||||
print("Expecting Task to be Cancelled:", t.cancelled())
|
||||
|
||||
# Cancel task and wait for cancellation to complete
|
||||
print("=" * 10)
|
||||
t = asyncio.create_task(task(2))
|
||||
await asyncio.sleep(0.01)
|
||||
t.cancel()
|
||||
await asyncio.sleep(0)
|
||||
print("Expecting Task to be Cancelled:", t.cancelled())
|
||||
|
||||
# Cancel task multiple times after it has started
|
||||
print("=" * 10)
|
||||
t = asyncio.create_task(task(2))
|
||||
await asyncio.sleep(0.01)
|
||||
for _ in range(4):
|
||||
t.cancel()
|
||||
await asyncio.sleep(0.01)
|
||||
|
||||
print("Expecting Task to be Cancelled:", t.cancelled())
|
||||
|
||||
# Cancel task after it has finished
|
||||
print("=" * 10)
|
||||
t = asyncio.create_task(task(0.01))
|
||||
await asyncio.sleep(0.05)
|
||||
t.cancel()
|
||||
print("Expecting task to not be Cancelled:", t.cancelled())
|
||||
|
||||
|
||||
asyncio.run(main())
|
|
@ -0,0 +1,10 @@
|
|||
==========
|
||||
Expecting task to not be cancelled because it is not done: False
|
||||
==========
|
||||
Expecting Task to be Cancelled: True
|
||||
==========
|
||||
Expecting Task to be Cancelled: True
|
||||
==========
|
||||
Expecting Task to be Cancelled: True
|
||||
==========
|
||||
Expecting task to not be Cancelled: False
|
|
@ -0,0 +1,64 @@
|
|||
# Test the Task.exception() method
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
print("SKIP")
|
||||
raise SystemExit
|
||||
|
||||
|
||||
async def task(t, exc=None):
|
||||
if t >= 0:
|
||||
await asyncio.sleep(t)
|
||||
if exc:
|
||||
raise exc
|
||||
|
||||
|
||||
async def main():
|
||||
# Task that is not done yet raises an InvalidStateError
|
||||
print("=" * 10)
|
||||
t = asyncio.create_task(task(1))
|
||||
await asyncio.sleep(0)
|
||||
try:
|
||||
t.exception()
|
||||
assert False, "Should not get here"
|
||||
except Exception as e:
|
||||
print("Tasks that aren't done yet raise an InvalidStateError:", repr(e))
|
||||
|
||||
# Task that is cancelled raises CancelledError
|
||||
print("=" * 10)
|
||||
t = asyncio.create_task(task(1))
|
||||
t.cancel()
|
||||
await asyncio.sleep(0)
|
||||
try:
|
||||
print(repr(t.exception()))
|
||||
print(t.cancelled())
|
||||
assert False, "Should not get here"
|
||||
except asyncio.CancelledError as e:
|
||||
print("Cancelled tasks cannot retrieve exception:", repr(e))
|
||||
|
||||
# Task that starts, runs and finishes without an exception should return None
|
||||
print("=" * 10)
|
||||
t = asyncio.create_task(task(0.01))
|
||||
await t
|
||||
print("None when no exception:", t.exception())
|
||||
|
||||
# Task that raises immediately should return that exception
|
||||
print("=" * 10)
|
||||
t = asyncio.create_task(task(-1, ValueError))
|
||||
try:
|
||||
await t
|
||||
assert False, "Should not get here"
|
||||
except ValueError as e:
|
||||
pass
|
||||
print("Returned Exception:", repr(t.exception()))
|
||||
|
||||
# Task returns `none` when somehow an exception isn't in data
|
||||
print("=" * 10)
|
||||
t = asyncio.create_task(task(-1))
|
||||
await t
|
||||
t.data = "Example"
|
||||
print(t.exception())
|
||||
|
||||
|
||||
asyncio.run(main())
|
|
@ -0,0 +1,10 @@
|
|||
==========
|
||||
Tasks that aren't done yet raise an InvalidStateError: InvalidStateError()
|
||||
==========
|
||||
Cancelled tasks cannot retrieve exception: CancelledError()
|
||||
==========
|
||||
None when no exception: None
|
||||
==========
|
||||
Returned Exception: ValueError()
|
||||
==========
|
||||
None
|
|
@ -0,0 +1,28 @@
|
|||
# Test the `Task.get_coro()` method
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
print("SKIP")
|
||||
raise SystemExit
|
||||
|
||||
|
||||
async def action():
|
||||
pass
|
||||
|
||||
|
||||
async def main():
|
||||
# Check that the coro we include is the same coro we get back
|
||||
print("=" * 10)
|
||||
|
||||
coro = action()
|
||||
t = asyncio.create_task(coro)
|
||||
print(t.get_coro() == coro)
|
||||
|
||||
# Check that the coro prop matches the get_coro() result
|
||||
print("=" * 10)
|
||||
t = asyncio.create_task(action())
|
||||
print(t.get_coro() == t.coro)
|
||||
|
||||
|
||||
asyncio.run(main())
|
|
@ -0,0 +1,4 @@
|
|||
==========
|
||||
True
|
||||
==========
|
||||
True
|
|
@ -0,0 +1,39 @@
|
|||
# Test hash unary operator for a Task
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
print("SKIP")
|
||||
raise SystemExit
|
||||
|
||||
|
||||
async def task():
|
||||
pass
|
||||
|
||||
|
||||
async def main():
|
||||
# Confirm that the hash is an int
|
||||
print("=" * 10)
|
||||
t1 = asyncio.create_task(task())
|
||||
t2 = asyncio.create_task(task())
|
||||
print(type(hash(t2)))
|
||||
print(type(hash(t1)))
|
||||
|
||||
# Check that two tasks don't have the same hash
|
||||
print("=" * 10)
|
||||
t1 = asyncio.create_task(task())
|
||||
t2 = asyncio.create_task(task())
|
||||
print(hash(t1) != hash(t2))
|
||||
|
||||
# Add tasks to a set
|
||||
print("=" * 10)
|
||||
t1 = asyncio.create_task(task())
|
||||
t2 = asyncio.create_task(task())
|
||||
|
||||
tasks = set()
|
||||
tasks.add(t1)
|
||||
print(t1 in tasks)
|
||||
print(t2 in tasks)
|
||||
|
||||
|
||||
asyncio.run(main())
|
|
@ -0,0 +1,8 @@
|
|||
==========
|
||||
<class 'int'>
|
||||
<class 'int'>
|
||||
==========
|
||||
True
|
||||
==========
|
||||
True
|
||||
False
|
|
@ -0,0 +1,59 @@
|
|||
# Test the Task.remove_done_callback() method
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
print("SKIP")
|
||||
raise SystemExit
|
||||
|
||||
|
||||
async def task(t, exc=None):
|
||||
if t >= 0:
|
||||
await asyncio.sleep(t)
|
||||
if exc:
|
||||
raise exc
|
||||
|
||||
|
||||
def done_callback():
|
||||
print("done")
|
||||
|
||||
|
||||
def done_callback_2():
|
||||
print("done 2")
|
||||
|
||||
|
||||
async def main():
|
||||
# Removing a callback returns 0 when no callbacks have been set
|
||||
print("=" * 10)
|
||||
t = asyncio.create_task(task(1))
|
||||
print("Returns 0 when no done callback has been set:", t.remove_done_callback(done_callback))
|
||||
|
||||
# Done callback removal only works once
|
||||
print("=" * 10)
|
||||
t = asyncio.create_task(task(1))
|
||||
t.add_done_callback(done_callback)
|
||||
print(
|
||||
"Returns 1 when a callback matches and is removed:", t.remove_done_callback(done_callback)
|
||||
)
|
||||
print(
|
||||
"Returns 0 on second attempt to remove the callback:",
|
||||
t.remove_done_callback(done_callback),
|
||||
)
|
||||
|
||||
# Only removes done callback when match
|
||||
print("=" * 10)
|
||||
t = asyncio.create_task(task(0.01))
|
||||
t.add_done_callback(done_callback)
|
||||
print("Returns 0 when done callbacks don't match:", t.remove_done_callback(done_callback_2))
|
||||
|
||||
# A removed done callback does not execute
|
||||
print("=" * 10)
|
||||
t = asyncio.create_task(task(-1))
|
||||
t.add_done_callback(done_callback)
|
||||
t.remove_done_callback(done_callback)
|
||||
print("Waiting for task to complete")
|
||||
await t
|
||||
print("Task completed")
|
||||
|
||||
|
||||
asyncio.run(main())
|
|
@ -0,0 +1,10 @@
|
|||
==========
|
||||
Returns 0 when no done callback has been set: 0
|
||||
==========
|
||||
Returns 1 when a callback matches and is removed: 1
|
||||
Returns 0 on second attempt to remove the callback: 0
|
||||
==========
|
||||
Returns 0 when done callbacks don't match: 0
|
||||
==========
|
||||
Waiting for task to complete
|
||||
Task completed
|
|
@ -0,0 +1,69 @@
|
|||
# Test the Task.result() method
|
||||
|
||||
try:
|
||||
import asyncio
|
||||
except ImportError:
|
||||
print("SKIP")
|
||||
raise SystemExit
|
||||
|
||||
|
||||
async def task(t, exc=None, ret=None):
|
||||
if t >= 0:
|
||||
await asyncio.sleep(t)
|
||||
if exc:
|
||||
raise exc
|
||||
return ret
|
||||
|
||||
|
||||
async def main():
|
||||
# Task that is not done yet raises an InvalidStateError
|
||||
print("=" * 10)
|
||||
t = asyncio.create_task(task(1))
|
||||
await asyncio.sleep(0)
|
||||
try:
|
||||
t.result()
|
||||
assert False, "Should not get here"
|
||||
except Exception as e:
|
||||
print("InvalidStateError if still running:", repr(e))
|
||||
|
||||
# Task that is cancelled raises CancelledError
|
||||
print("=" * 10)
|
||||
t = asyncio.create_task(task(1))
|
||||
t.cancel()
|
||||
await asyncio.sleep(0)
|
||||
try:
|
||||
t.result()
|
||||
assert False, "Should not get here"
|
||||
except asyncio.CancelledError as e:
|
||||
print("CancelledError when retrieving result from cancelled task:", repr(e))
|
||||
|
||||
# Task that raises immediately should raise that exception when calling result
|
||||
print("=" * 10)
|
||||
t = asyncio.create_task(task(-1, ValueError))
|
||||
try:
|
||||
await t
|
||||
assert False, "Should not get here"
|
||||
except ValueError as e:
|
||||
pass
|
||||
|
||||
try:
|
||||
t.result()
|
||||
assert False, "Should not get here"
|
||||
except ValueError as e:
|
||||
print("Error raised when result is attempted on task with error:", repr(e))
|
||||
|
||||
# Task that starts, runs and finishes without an exception or value should return None
|
||||
print("=" * 10)
|
||||
t = asyncio.create_task(task(0.01))
|
||||
await t
|
||||
print("Empty Result should be None:", t.result())
|
||||
assert t.result() is None
|
||||
|
||||
# Task that starts, runs and finishes without exception should return result
|
||||
print("=" * 10)
|
||||
t = asyncio.create_task(task(0.01, None, "hello world"))
|
||||
await t
|
||||
print("Happy path, result is returned:", t.result())
|
||||
|
||||
|
||||
asyncio.run(main())
|
|
@ -0,0 +1,10 @@
|
|||
==========
|
||||
InvalidStateError if still running: InvalidStateError()
|
||||
==========
|
||||
CancelledError when retrieving result from cancelled task: CancelledError()
|
||||
==========
|
||||
Error raised when result is attempted on task with error: ValueError()
|
||||
==========
|
||||
Empty Result should be None: None
|
||||
==========
|
||||
Happy path, result is returned: hello world
|
Loading…
Reference in New Issue