142 lines
4.7 KiB
Python
142 lines
4.7 KiB
Python
import io
|
|
import json
|
|
import unittest
|
|
|
|
from src.api.server import APIRequestHandler
|
|
|
|
|
|
def _dependencies(cases=None, progress=None) -> dict:
|
|
return {
|
|
"training_cases": cases or (lambda **kwargs: []),
|
|
"training_progress": progress or (lambda **kwargs: []),
|
|
}
|
|
|
|
|
|
class _GetHandlerHarness(APIRequestHandler):
|
|
def __init__(self, path: str, dependencies: dict) -> None:
|
|
self.path = path
|
|
self.wfile = io.BytesIO()
|
|
self.dependencies = dependencies
|
|
self.status = None
|
|
self.response_headers = {}
|
|
|
|
def send_response(self, code, message=None): # noqa: D401
|
|
self.status = code
|
|
|
|
def send_header(self, keyword, value):
|
|
self.response_headers[keyword] = value
|
|
|
|
def end_headers(self):
|
|
return None
|
|
|
|
def log_message(self, format, *args):
|
|
return None
|
|
|
|
def json_body(self):
|
|
return json.loads(self.wfile.getvalue().decode("utf-8"))
|
|
|
|
|
|
class TrainingApiM4Tests(unittest.TestCase):
|
|
def test_training_cases_rejects_invalid_limits(self) -> None:
|
|
calls = []
|
|
|
|
def list_cases(**kwargs):
|
|
calls.append(kwargs)
|
|
return []
|
|
|
|
for path in (
|
|
"/training/cases?limit=",
|
|
"/training/cases?limit=0",
|
|
"/training/cases?limit=-1",
|
|
"/training/cases?limit=101",
|
|
"/training/cases?limit=not-a-number",
|
|
):
|
|
with self.subTest(path=path):
|
|
handler = _GetHandlerHarness(path, _dependencies(cases=list_cases))
|
|
|
|
handler.do_GET()
|
|
|
|
self.assertEqual(handler.status, 400)
|
|
self.assertEqual(handler.json_body(), {"error": "invalid_limit_query_param:limit"})
|
|
|
|
self.assertEqual(calls, [])
|
|
|
|
def test_training_progress_rejects_invalid_limits(self) -> None:
|
|
calls = []
|
|
|
|
def get_progress(**kwargs):
|
|
calls.append(kwargs)
|
|
return []
|
|
|
|
for path in (
|
|
"/training/progress?limit=",
|
|
"/training/progress?limit=0",
|
|
"/training/progress?limit=-1",
|
|
"/training/progress?limit=101",
|
|
"/training/progress?limit=not-a-number",
|
|
):
|
|
with self.subTest(path=path):
|
|
handler = _GetHandlerHarness(path, _dependencies(progress=get_progress))
|
|
|
|
handler.do_GET()
|
|
|
|
self.assertEqual(handler.status, 400)
|
|
self.assertEqual(handler.json_body(), {"error": "invalid_limit_query_param:limit"})
|
|
|
|
self.assertEqual(calls, [])
|
|
|
|
def test_training_limits_accept_upper_bound(self) -> None:
|
|
case_calls = []
|
|
progress_calls = []
|
|
|
|
def list_cases(**kwargs):
|
|
case_calls.append(kwargs)
|
|
return []
|
|
|
|
def get_progress(**kwargs):
|
|
progress_calls.append(kwargs)
|
|
return []
|
|
|
|
cases_handler = _GetHandlerHarness("/training/cases?limit=100", _dependencies(cases=list_cases))
|
|
progress_handler = _GetHandlerHarness("/training/progress?limit=100", _dependencies(progress=get_progress))
|
|
|
|
cases_handler.do_GET()
|
|
progress_handler.do_GET()
|
|
|
|
self.assertEqual(cases_handler.status, 200)
|
|
self.assertEqual(progress_handler.status, 200)
|
|
self.assertEqual(case_calls[0]["limit"], 100)
|
|
self.assertEqual(progress_calls[0]["limit"], 100)
|
|
|
|
def test_unknown_exception_response_hides_internal_detail(self) -> None:
|
|
def list_cases(**kwargs):
|
|
raise RuntimeError("raw internal failure marker")
|
|
|
|
handler = _GetHandlerHarness("/training/cases", _dependencies(cases=list_cases))
|
|
|
|
handler.do_GET()
|
|
|
|
body = handler.json_body()
|
|
serialized = json.dumps(body)
|
|
self.assertEqual(handler.status, 500)
|
|
self.assertEqual(body, {"error": "internal_server_error"})
|
|
self.assertNotIn("raw internal failure marker", serialized)
|
|
|
|
def test_training_case_selector_queries_reject_invalid_values(self) -> None:
|
|
for path, expected in (
|
|
("/training/cases?quality_rank=elite", {"error": "invalid_quality_rank_query_param:quality_rank"}),
|
|
("/training/cases?min_quality_score=-1", {"error": "invalid_min_quality_score_query_param:min_quality_score"}),
|
|
("/training/cases?min_quality_score=101", {"error": "invalid_min_quality_score_query_param:min_quality_score"}),
|
|
("/training/cases?sort_by=unknown", {"error": "invalid_sort_query_param:sort_by"}),
|
|
):
|
|
with self.subTest(path=path):
|
|
handler = _GetHandlerHarness(path, _dependencies())
|
|
handler.do_GET()
|
|
|
|
self.assertEqual(handler.status, 400)
|
|
self.assertEqual(handler.json_body(), expected)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|