66 lines
2.0 KiB
Python
66 lines
2.0 KiB
Python
from __future__ import annotations
|
|
|
|
import ast
|
|
import sys
|
|
import unittest
|
|
from pathlib import Path
|
|
from unittest.mock import patch
|
|
|
|
from backend.bootstrap import runtime
|
|
|
|
|
|
class BackgroundLifecycleTests(unittest.TestCase):
|
|
def test_service_construction_does_not_start_the_scheduler(self) -> None:
|
|
source = (Path(__file__).parents[1] / "backend" / "application.py").read_text(
|
|
encoding="utf-8"
|
|
)
|
|
tree = ast.parse(source)
|
|
service_class = next(
|
|
node for node in tree.body
|
|
if isinstance(node, ast.ClassDef) and node.name == "DashboardService"
|
|
)
|
|
constructor = next(
|
|
node for node in service_class.body
|
|
if isinstance(node, ast.FunctionDef) and node.name == "__init__"
|
|
)
|
|
called_methods = {
|
|
node.func.attr for node in ast.walk(constructor)
|
|
if isinstance(node, ast.Call) and isinstance(node.func, ast.Attribute)
|
|
}
|
|
self.assertNotIn("start_scheduler", called_methods)
|
|
|
|
def test_runtime_starts_jobs_after_bind_and_stops_before_close(self) -> None:
|
|
events: list[str] = []
|
|
|
|
class Service:
|
|
def start_background_jobs(self) -> None:
|
|
events.append("start-jobs")
|
|
|
|
def stop_background_jobs(self) -> None:
|
|
events.append("stop-jobs")
|
|
|
|
class Server:
|
|
def __init__(self, address: tuple[str, int], handler: object) -> None:
|
|
events.append("bind")
|
|
|
|
def serve_forever(self) -> None:
|
|
events.append("serve")
|
|
raise KeyboardInterrupt
|
|
|
|
def server_close(self) -> None:
|
|
events.append("close")
|
|
|
|
with (
|
|
patch.object(runtime, "ThreadingHTTPServer", Server),
|
|
patch.object(sys, "argv", ["server.py", "--port", "8797"]),
|
|
):
|
|
runtime.main(object, Service())
|
|
|
|
self.assertEqual(
|
|
events, ["bind", "start-jobs", "serve", "stop-jobs", "close"]
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|