sanic/tests/test_server_events.py

221 lines
6.0 KiB
Python
Raw Normal View History

import asyncio
import signal
Fix Ctrl+C and tests on Windows. (#1808) * Fix Ctrl+C on Windows. * Disable testing of a function N/A on Windows. * Add test for coverage, avoid crash on missing _stopping. * Initialise StreamingHTTPResponse.protocol = None * Improved comments. * Reduce amount of data in test_request_stream to avoid failures on Windows. * The Windows test doesn't work on Windows :( * Use port numbers more likely to be free than 8000. * Disable the other signal tests on Windows as well. * Windows doesn't properly support SO_REUSEADDR, so that's disabled in Python, and thus rebinding fails. For successful testing, reuse port instead. * app.run argument handling: added server kwargs (alike create_server), added warning on extra kwargs, made auto_reload explicit argument. Another go at Windows tests * Revert "app.run argument handling: added server kwargs (alike create_server), added warning on extra kwargs, made auto_reload explicit argument. Another go at Windows tests" This reverts commit dc5d682448e3f6595bdca5cb764e5f26ca29e295. * Use random test server port on most tests. Should avoid port/addr reuse issues. * Another test to random port instead of 8000. * Fix deprecation warnings about missing name on Sanic() in tests. * Linter and typing * Increase test coverage * Rewrite test for ctrlc_windows_workaround * py36 compat * py36 compat * py36 compat * Don't rely on loop internals but add a stopping flag to app. * App may be restarted. * py36 compat * Linter * Add a constant for OS checking. Co-authored-by: L. Kärkkäinen <tronic@users.noreply.github.com>
2020-03-26 04:42:46 +00:00
from contextlib import closing
from socket import socket
import pytest
2021-01-19 13:54:20 +00:00
from sanic_testing.testing import HOST, PORT
from sanic.exceptions import BadRequest, SanicException
2021-02-15 19:50:20 +00:00
AVAILABLE_LISTENERS = [
2018-12-30 11:18:06 +00:00
"before_server_start",
"after_server_start",
"before_server_stop",
"after_server_stop",
]
def create_listener(listener_name, in_list):
async def _listener(app, loop):
print(f"DEBUG MESSAGE FOR PYTEST for {listener_name}")
in_list.insert(0, app.name + listener_name)
2018-12-30 11:18:06 +00:00
return _listener
def create_listener_no_loop(listener_name, in_list):
async def _listener(app):
print(f"DEBUG MESSAGE FOR PYTEST for {listener_name}")
in_list.insert(0, app.name + listener_name)
return _listener
def start_stop_app(random_name_app, **run_kwargs):
@random_name_app.after_server_start
async def shutdown(app):
await asyncio.sleep(1.1)
app.stop()
try:
random_name_app.run(HOST, PORT, single_process=True, **run_kwargs)
except KeyboardInterrupt:
pass
2018-12-30 11:18:06 +00:00
@pytest.mark.parametrize("listener_name", AVAILABLE_LISTENERS)
2018-08-26 15:43:14 +01:00
def test_single_listener(app, listener_name):
"""Test that listeners on their own work"""
2018-08-26 15:43:14 +01:00
output = []
# Register listener
2018-12-30 11:18:06 +00:00
app.listener(listener_name)(create_listener(listener_name, output))
2018-08-26 15:43:14 +01:00
start_stop_app(app)
assert app.name + listener_name == output.pop()
@pytest.mark.parametrize("listener_name", AVAILABLE_LISTENERS)
def test_single_listener_no_loop(app, listener_name):
"""Test that listeners on their own work"""
output = []
# Register listener
app.listener(listener_name)(create_listener_no_loop(listener_name, output))
start_stop_app(app)
assert app.name + listener_name == output.pop()
2018-12-30 11:18:06 +00:00
@pytest.mark.parametrize("listener_name", AVAILABLE_LISTENERS)
2018-08-26 15:43:14 +01:00
def test_register_listener(app, listener_name):
"""
Test that listeners on their own work with
app.register_listener method
"""
2018-08-26 15:43:14 +01:00
output = []
# Register listener
listener = create_listener(listener_name, output)
2018-09-29 18:54:47 +01:00
app.register_listener(listener, event=listener_name)
2018-08-26 15:43:14 +01:00
start_stop_app(app)
assert app.name + listener_name == output.pop()
2018-08-26 15:43:14 +01:00
def test_all_listeners(app):
output = []
for listener_name in AVAILABLE_LISTENERS:
listener = create_listener(listener_name, output)
2018-08-26 15:43:14 +01:00
app.listener(listener_name)(listener)
start_stop_app(app)
for listener_name in AVAILABLE_LISTENERS:
2018-08-26 15:43:14 +01:00
assert app.name + listener_name == output.pop()
2017-08-09 06:21:40 +01:00
2021-02-15 19:50:20 +00:00
def test_all_listeners_as_convenience(app):
output = []
for listener_name in AVAILABLE_LISTENERS:
listener = create_listener(listener_name, output)
method = getattr(app, listener_name)
method(listener)
start_stop_app(app)
for listener_name in AVAILABLE_LISTENERS:
assert app.name + listener_name == output.pop()
2019-06-04 08:58:00 +01:00
@pytest.mark.asyncio
2018-08-26 15:43:14 +01:00
async def test_trigger_before_events_create_server(app):
2017-08-09 06:21:40 +01:00
class MySanicDb:
pass
2018-12-30 11:18:06 +00:00
@app.listener("before_server_start")
2017-08-09 06:21:40 +01:00
async def init_db(app, loop):
app.ctx.db = MySanicDb()
2017-08-09 06:21:40 +01:00
srv = await app.create_server(
debug=True, return_asyncio_server=True, port=PORT
)
await srv.startup()
await srv.before_start()
2017-08-09 06:21:40 +01:00
assert hasattr(app.ctx, "db")
assert isinstance(app.ctx.db, MySanicDb)
2021-02-15 19:50:20 +00:00
@pytest.mark.asyncio
async def test_trigger_before_events_create_server_missing_event(app):
class MySanicDb:
pass
with pytest.raises(BadRequest):
2021-02-15 19:50:20 +00:00
@app.listener
async def init_db(app, loop):
app.ctx.db = MySanicDb()
2021-02-15 19:50:20 +00:00
assert not hasattr(app.ctx, "db")
2021-02-15 19:50:20 +00:00
def test_create_server_trigger_events(app):
"""Test if create_server can trigger server events"""
2022-01-16 07:03:04 +00:00
def stop_on_alarm(signum, frame):
raise KeyboardInterrupt("...")
flag1 = False
flag2 = False
flag3 = False
async def stop(app, loop):
nonlocal flag1
flag1 = True
async def before_stop(app, loop):
nonlocal flag2
flag2 = True
async def after_stop(app, loop):
nonlocal flag3
flag3 = True
app.listener("after_server_start")(stop)
app.listener("before_server_stop")(before_stop)
app.listener("after_server_stop")(after_stop)
loop = asyncio.get_event_loop()
Fix Ctrl+C and tests on Windows. (#1808) * Fix Ctrl+C on Windows. * Disable testing of a function N/A on Windows. * Add test for coverage, avoid crash on missing _stopping. * Initialise StreamingHTTPResponse.protocol = None * Improved comments. * Reduce amount of data in test_request_stream to avoid failures on Windows. * The Windows test doesn't work on Windows :( * Use port numbers more likely to be free than 8000. * Disable the other signal tests on Windows as well. * Windows doesn't properly support SO_REUSEADDR, so that's disabled in Python, and thus rebinding fails. For successful testing, reuse port instead. * app.run argument handling: added server kwargs (alike create_server), added warning on extra kwargs, made auto_reload explicit argument. Another go at Windows tests * Revert "app.run argument handling: added server kwargs (alike create_server), added warning on extra kwargs, made auto_reload explicit argument. Another go at Windows tests" This reverts commit dc5d682448e3f6595bdca5cb764e5f26ca29e295. * Use random test server port on most tests. Should avoid port/addr reuse issues. * Another test to random port instead of 8000. * Fix deprecation warnings about missing name on Sanic() in tests. * Linter and typing * Increase test coverage * Rewrite test for ctrlc_windows_workaround * py36 compat * py36 compat * py36 compat * Don't rely on loop internals but add a stopping flag to app. * App may be restarted. * py36 compat * Linter * Add a constant for OS checking. Co-authored-by: L. Kärkkäinen <tronic@users.noreply.github.com>
2020-03-26 04:42:46 +00:00
# Use random port for tests
2022-01-16 07:03:04 +00:00
signal.signal(signal.SIGALRM, stop_on_alarm)
signal.alarm(1)
Fix Ctrl+C and tests on Windows. (#1808) * Fix Ctrl+C on Windows. * Disable testing of a function N/A on Windows. * Add test for coverage, avoid crash on missing _stopping. * Initialise StreamingHTTPResponse.protocol = None * Improved comments. * Reduce amount of data in test_request_stream to avoid failures on Windows. * The Windows test doesn't work on Windows :( * Use port numbers more likely to be free than 8000. * Disable the other signal tests on Windows as well. * Windows doesn't properly support SO_REUSEADDR, so that's disabled in Python, and thus rebinding fails. For successful testing, reuse port instead. * app.run argument handling: added server kwargs (alike create_server), added warning on extra kwargs, made auto_reload explicit argument. Another go at Windows tests * Revert "app.run argument handling: added server kwargs (alike create_server), added warning on extra kwargs, made auto_reload explicit argument. Another go at Windows tests" This reverts commit dc5d682448e3f6595bdca5cb764e5f26ca29e295. * Use random test server port on most tests. Should avoid port/addr reuse issues. * Another test to random port instead of 8000. * Fix deprecation warnings about missing name on Sanic() in tests. * Linter and typing * Increase test coverage * Rewrite test for ctrlc_windows_workaround * py36 compat * py36 compat * py36 compat * Don't rely on loop internals but add a stopping flag to app. * App may be restarted. * py36 compat * Linter * Add a constant for OS checking. Co-authored-by: L. Kärkkäinen <tronic@users.noreply.github.com>
2020-03-26 04:42:46 +00:00
with closing(socket()) as sock:
sock.bind(("127.0.0.1", 0))
serv_coro = app.create_server(
return_asyncio_server=True, sock=sock, debug=True
)
Fix Ctrl+C and tests on Windows. (#1808) * Fix Ctrl+C on Windows. * Disable testing of a function N/A on Windows. * Add test for coverage, avoid crash on missing _stopping. * Initialise StreamingHTTPResponse.protocol = None * Improved comments. * Reduce amount of data in test_request_stream to avoid failures on Windows. * The Windows test doesn't work on Windows :( * Use port numbers more likely to be free than 8000. * Disable the other signal tests on Windows as well. * Windows doesn't properly support SO_REUSEADDR, so that's disabled in Python, and thus rebinding fails. For successful testing, reuse port instead. * app.run argument handling: added server kwargs (alike create_server), added warning on extra kwargs, made auto_reload explicit argument. Another go at Windows tests * Revert "app.run argument handling: added server kwargs (alike create_server), added warning on extra kwargs, made auto_reload explicit argument. Another go at Windows tests" This reverts commit dc5d682448e3f6595bdca5cb764e5f26ca29e295. * Use random test server port on most tests. Should avoid port/addr reuse issues. * Another test to random port instead of 8000. * Fix deprecation warnings about missing name on Sanic() in tests. * Linter and typing * Increase test coverage * Rewrite test for ctrlc_windows_workaround * py36 compat * py36 compat * py36 compat * Don't rely on loop internals but add a stopping flag to app. * App may be restarted. * py36 compat * Linter * Add a constant for OS checking. Co-authored-by: L. Kärkkäinen <tronic@users.noreply.github.com>
2020-03-26 04:42:46 +00:00
serv_task = asyncio.ensure_future(serv_coro, loop=loop)
server = loop.run_until_complete(serv_task)
loop.run_until_complete(server.startup())
loop.run_until_complete(server.after_start())
Fix Ctrl+C and tests on Windows. (#1808) * Fix Ctrl+C on Windows. * Disable testing of a function N/A on Windows. * Add test for coverage, avoid crash on missing _stopping. * Initialise StreamingHTTPResponse.protocol = None * Improved comments. * Reduce amount of data in test_request_stream to avoid failures on Windows. * The Windows test doesn't work on Windows :( * Use port numbers more likely to be free than 8000. * Disable the other signal tests on Windows as well. * Windows doesn't properly support SO_REUSEADDR, so that's disabled in Python, and thus rebinding fails. For successful testing, reuse port instead. * app.run argument handling: added server kwargs (alike create_server), added warning on extra kwargs, made auto_reload explicit argument. Another go at Windows tests * Revert "app.run argument handling: added server kwargs (alike create_server), added warning on extra kwargs, made auto_reload explicit argument. Another go at Windows tests" This reverts commit dc5d682448e3f6595bdca5cb764e5f26ca29e295. * Use random test server port on most tests. Should avoid port/addr reuse issues. * Another test to random port instead of 8000. * Fix deprecation warnings about missing name on Sanic() in tests. * Linter and typing * Increase test coverage * Rewrite test for ctrlc_windows_workaround * py36 compat * py36 compat * py36 compat * Don't rely on loop internals but add a stopping flag to app. * App may be restarted. * py36 compat * Linter * Add a constant for OS checking. Co-authored-by: L. Kärkkäinen <tronic@users.noreply.github.com>
2020-03-26 04:42:46 +00:00
try:
loop.run_forever()
except KeyboardInterrupt:
Fix Ctrl+C and tests on Windows. (#1808) * Fix Ctrl+C on Windows. * Disable testing of a function N/A on Windows. * Add test for coverage, avoid crash on missing _stopping. * Initialise StreamingHTTPResponse.protocol = None * Improved comments. * Reduce amount of data in test_request_stream to avoid failures on Windows. * The Windows test doesn't work on Windows :( * Use port numbers more likely to be free than 8000. * Disable the other signal tests on Windows as well. * Windows doesn't properly support SO_REUSEADDR, so that's disabled in Python, and thus rebinding fails. For successful testing, reuse port instead. * app.run argument handling: added server kwargs (alike create_server), added warning on extra kwargs, made auto_reload explicit argument. Another go at Windows tests * Revert "app.run argument handling: added server kwargs (alike create_server), added warning on extra kwargs, made auto_reload explicit argument. Another go at Windows tests" This reverts commit dc5d682448e3f6595bdca5cb764e5f26ca29e295. * Use random test server port on most tests. Should avoid port/addr reuse issues. * Another test to random port instead of 8000. * Fix deprecation warnings about missing name on Sanic() in tests. * Linter and typing * Increase test coverage * Rewrite test for ctrlc_windows_workaround * py36 compat * py36 compat * py36 compat * Don't rely on loop internals but add a stopping flag to app. * App may be restarted. * py36 compat * Linter * Add a constant for OS checking. Co-authored-by: L. Kärkkäinen <tronic@users.noreply.github.com>
2020-03-26 04:42:46 +00:00
loop.stop()
finally:
# Run the on_stop function if provided
loop.run_until_complete(server.before_stop())
Fix Ctrl+C and tests on Windows. (#1808) * Fix Ctrl+C on Windows. * Disable testing of a function N/A on Windows. * Add test for coverage, avoid crash on missing _stopping. * Initialise StreamingHTTPResponse.protocol = None * Improved comments. * Reduce amount of data in test_request_stream to avoid failures on Windows. * The Windows test doesn't work on Windows :( * Use port numbers more likely to be free than 8000. * Disable the other signal tests on Windows as well. * Windows doesn't properly support SO_REUSEADDR, so that's disabled in Python, and thus rebinding fails. For successful testing, reuse port instead. * app.run argument handling: added server kwargs (alike create_server), added warning on extra kwargs, made auto_reload explicit argument. Another go at Windows tests * Revert "app.run argument handling: added server kwargs (alike create_server), added warning on extra kwargs, made auto_reload explicit argument. Another go at Windows tests" This reverts commit dc5d682448e3f6595bdca5cb764e5f26ca29e295. * Use random test server port on most tests. Should avoid port/addr reuse issues. * Another test to random port instead of 8000. * Fix deprecation warnings about missing name on Sanic() in tests. * Linter and typing * Increase test coverage * Rewrite test for ctrlc_windows_workaround * py36 compat * py36 compat * py36 compat * Don't rely on loop internals but add a stopping flag to app. * App may be restarted. * py36 compat * Linter * Add a constant for OS checking. Co-authored-by: L. Kärkkäinen <tronic@users.noreply.github.com>
2020-03-26 04:42:46 +00:00
# Wait for server to close
close_task = server.close()
loop.run_until_complete(close_task)
# Complete all tasks on the loop
for connection in server.connections:
connection.close_if_idle()
loop.run_until_complete(server.after_stop())
Fix Ctrl+C and tests on Windows. (#1808) * Fix Ctrl+C on Windows. * Disable testing of a function N/A on Windows. * Add test for coverage, avoid crash on missing _stopping. * Initialise StreamingHTTPResponse.protocol = None * Improved comments. * Reduce amount of data in test_request_stream to avoid failures on Windows. * The Windows test doesn't work on Windows :( * Use port numbers more likely to be free than 8000. * Disable the other signal tests on Windows as well. * Windows doesn't properly support SO_REUSEADDR, so that's disabled in Python, and thus rebinding fails. For successful testing, reuse port instead. * app.run argument handling: added server kwargs (alike create_server), added warning on extra kwargs, made auto_reload explicit argument. Another go at Windows tests * Revert "app.run argument handling: added server kwargs (alike create_server), added warning on extra kwargs, made auto_reload explicit argument. Another go at Windows tests" This reverts commit dc5d682448e3f6595bdca5cb764e5f26ca29e295. * Use random test server port on most tests. Should avoid port/addr reuse issues. * Another test to random port instead of 8000. * Fix deprecation warnings about missing name on Sanic() in tests. * Linter and typing * Increase test coverage * Rewrite test for ctrlc_windows_workaround * py36 compat * py36 compat * py36 compat * Don't rely on loop internals but add a stopping flag to app. * App may be restarted. * py36 compat * Linter * Add a constant for OS checking. Co-authored-by: L. Kärkkäinen <tronic@users.noreply.github.com>
2020-03-26 04:42:46 +00:00
assert flag1 and flag2 and flag3
@pytest.mark.asyncio
async def test_missing_startup_raises_exception(app):
@app.listener("before_server_start")
async def init_db(app, loop):
...
srv = await app.create_server(
debug=True, return_asyncio_server=True, port=PORT
)
with pytest.raises(SanicException):
await srv.before_start()
def test_reload_listeners_attached(app):
async def dummy(*_):
...
app.reload_process_start(dummy)
app.reload_process_stop(dummy)
app.listener("reload_process_start")(dummy)
app.listener("reload_process_stop")(dummy)
assert len(app.listeners.get("reload_process_start")) == 2
assert len(app.listeners.get("reload_process_stop")) == 2