| | |
| | | from __future__ import annotations |
| | | |
| | | import importlib.util |
| | | import io |
| | | import sys |
| | | import unittest |
| | | from pathlib import Path |
| | | |
| | |
| | | Path(handler.translate_path("/shared/data/raw/01-object-detection/sample.jpeg")), |
| | | ROOT / "shared" / "data" / "raw" / "01-object-detection" / "sample.jpeg", |
| | | ) |
| | | self.assertEqual( |
| | | Path(handler.translate_path("/shared/data/raw/02-semantic-mapping/sample.tif")), |
| | | ROOT / "shared" / "data" / "raw" / "02-semantic-mapping" / "sample.tif", |
| | | ) |
| | | |
| | | def test_upload_name_is_sanitized_and_extension_is_allowlisted(self) -> None: |
| | | self.assertEqual(MODULE.safe_file_name("../../unsafe name.JPG", {".jpg"}), "unsafe_name.jpg") |
| | | with self.assertRaises(MODULE.ApiError): |
| | | MODULE.safe_file_name("image.exe", {".jpg", ".png"}) |
| | | |
| | | def test_oversized_request_is_rejected_before_reading_body(self) -> None: |
| | | handler = self.make_handler() |
| | | handler.headers = {"Content-Length": str(MODULE.MAX_REQUEST_BYTES + 1), "Content-Type": "application/json"} |
| | | handler.rfile = io.BytesIO(b"") |
| | | with self.assertRaises(MODULE.ApiError): |
| | | handler.read_json_body() |
| | | |
| | | def test_script_failure_becomes_a_useful_api_error(self) -> None: |
| | | handler = self.make_handler() |
| | | with self.assertRaisesRegex(MODULE.ApiError, "Processing failed"): |
| | | handler.run_command([sys.executable, "-c", "raise SystemExit(2)"], timeout=10) |
| | | |
| | | def test_semantic_validation_run_is_discovered(self) -> None: |
| | | runs = MODULE.semantic_runs(ROOT) |
| | | self.assertTrue(any(item["id"] == "validation-20260817" for item in runs)) |
| | | |
| | | def test_semantic_task_catalog_only_enables_verified_baseline(self) -> None: |
| | | tasks = MODULE.semantic_tasks(ROOT) |
| | | self.assertEqual(len(tasks), 5) |
| | | selectable = [item["id"] for item in tasks if item.get("selectable") is True] |
| | | self.assertEqual(selectable, ["color_baseline"]) |
| | | handler = self.make_handler() |
| | | with self.assertRaisesRegex(MODULE.ApiError, "not runnable yet"): |
| | | handler.create_semantic_run({"taskId": "drainage_blockage", "images": []}) |
| | | |
| | | def test_blocks_repository_files_and_encoded_traversal(self) -> None: |
| | | handler = self.make_handler() |