54 lines
2.1 KiB
Python
54 lines
2.1 KiB
Python
"""Actual loopback WebSocket checks; no application, database or external calls."""
|
|
import importlib.machinery
|
|
import importlib.util
|
|
from pathlib import Path
|
|
import socketserver
|
|
import threading
|
|
import unittest
|
|
|
|
|
|
HAS_TRANSPORT = all(importlib.util.find_spec(name) for name in ("uvicorn", "wsproto"))
|
|
|
|
|
|
@unittest.skipUnless(HAS_TRANSPORT, "Install pinned uvicorn and wsproto to run the transport tests")
|
|
class WebSocketHealthcheckTests(unittest.TestCase):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
path = Path(__file__).resolve().parents[1] / "eusrr-deploy-healthcheck"
|
|
loader = importlib.machinery.SourceFileLoader("deploy_healthcheck", str(path))
|
|
cls.probe = importlib.util.module_from_spec(importlib.util.spec_from_loader(loader.name, loader))
|
|
loader.exec_module(cls.probe)
|
|
|
|
def test_actual_uvicorn_101_and_asgi_frame(self):
|
|
self.probe.check_transport()
|
|
|
|
def run_rejection_server(self, status):
|
|
class Handler(socketserver.BaseRequestHandler):
|
|
def handle(self):
|
|
self.request.recv(4096)
|
|
self.request.sendall(
|
|
f"HTTP/1.1 {status} Response\r\nContent-Length: 0\r\nConnection: close\r\n\r\n".encode()
|
|
)
|
|
|
|
server = socketserver.TCPServer(("127.0.0.1", 0), Handler)
|
|
thread = threading.Thread(target=server.handle_request, daemon=True)
|
|
thread.start()
|
|
self.addCleanup(server.server_close)
|
|
self.addCleanup(lambda: thread.join(timeout=5))
|
|
return server.server_address[1]
|
|
|
|
def test_anonymous_rejection_is_expected(self):
|
|
self.probe.handshake(self.run_rejection_server(403), "/ws/", 403)
|
|
|
|
def test_http_fallback_404_does_not_pass(self):
|
|
with self.assertRaisesRegex(RuntimeError, "Unexpected WebSocket HTTP status"):
|
|
self.probe.handshake(self.run_rejection_server(404), "/ws/", 403)
|
|
|
|
def test_bogus_101_without_accept_does_not_pass(self):
|
|
with self.assertRaisesRegex(RuntimeError, "Invalid WebSocket upgrade"):
|
|
self.probe.handshake(self.run_rejection_server(101), "/", 101)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|