Spaces:
Sleeping
Sleeping
| from __future__ import annotations | |
| import os | |
| import tempfile | |
| import unittest | |
| from pathlib import Path | |
| from unittest.mock import Mock, patch | |
| import requests | |
| from lilith_agent.scoring_client import ScoringApiClient | |
| class ScoringApiClientTests(unittest.TestCase): | |
| def test_get_questions_returns_api_payload_on_success(self) -> None: | |
| response = Mock() | |
| response.json.return_value = [{"task_id": "t1", "question": "Q"}] | |
| response.raise_for_status.return_value = None | |
| session = Mock() | |
| session.get.return_value = response | |
| client = ScoringApiClient(api_url="https://example.com", session=session) | |
| payload = client.get_questions() | |
| self.assertEqual(payload, [{"task_id": "t1", "question": "Q"}]) | |
| self.assertIsNone(client.last_warning) | |
| session.get.assert_called_once_with("https://example.com/questions", timeout=30) | |
| def test_get_questions_falls_back_to_dataset_on_429(self) -> None: | |
| response = Mock(status_code=429, headers={}) | |
| error = requests.HTTPError("Too Many Requests", response=response) | |
| response.raise_for_status.side_effect = error | |
| session = Mock() | |
| session.get.return_value = response | |
| dataset_client = Mock() | |
| dataset_client.get_questions.return_value = [{"task_id": "fallback", "question": "Q2"}] | |
| client = ScoringApiClient( | |
| api_url="https://example.com", | |
| session=session, | |
| dataset_client=dataset_client, | |
| ) | |
| payload = client.get_questions() | |
| self.assertEqual(payload, [{"task_id": "fallback", "question": "Q2"}]) | |
| self.assertIn("429", client.last_warning or "") | |
| dataset_client.get_questions.assert_called_once_with() | |
| def test_fallback_prints_hf_visible_warning(self) -> None: | |
| response = Mock(status_code=503, headers={}) | |
| error = requests.HTTPError("Service Unavailable", response=response) | |
| response.raise_for_status.side_effect = error | |
| session = Mock() | |
| session.get.return_value = response | |
| dataset_client = Mock() | |
| dataset_client.get_questions.return_value = [] | |
| client = ScoringApiClient( | |
| api_url="https://example.com", | |
| session=session, | |
| dataset_client=dataset_client, | |
| ) | |
| with patch("builtins.print") as printed: | |
| client.get_questions() | |
| printed.assert_any_call( | |
| "Scoring API unavailable while trying to fetch questions (status=503); falling back to GAIA dataset.", | |
| flush=True, | |
| ) | |
| def test_download_file_falls_back_to_dataset_on_429(self) -> None: | |
| response = Mock(status_code=429, headers={}) | |
| error = requests.HTTPError("Too Many Requests", response=response) | |
| response.raise_for_status.side_effect = error | |
| session = Mock() | |
| session.get.return_value = response | |
| dataset_client = Mock() | |
| with tempfile.TemporaryDirectory() as tmpdir: | |
| fallback_path = Path(tmpdir) / "from-dataset.txt" | |
| fallback_path.write_text("ok") | |
| dataset_client.download_file.return_value = fallback_path | |
| client = ScoringApiClient( | |
| api_url="https://example.com", | |
| session=session, | |
| dataset_client=dataset_client, | |
| ) | |
| payload = client.download_file("task-123", tmpdir) | |
| self.assertEqual(payload, fallback_path) | |
| self.assertIn("429", client.last_warning or "") | |
| dataset_client.download_file.assert_called_once_with("task-123", Path(tmpdir)) | |
| def test_download_file_falls_back_to_dataset_on_404(self) -> None: | |
| response = Mock(status_code=404, headers={}) | |
| error = requests.HTTPError("Not Found", response=response) | |
| response.raise_for_status.side_effect = error | |
| session = Mock() | |
| session.get.return_value = response | |
| dataset_client = Mock() | |
| with tempfile.TemporaryDirectory() as tmpdir: | |
| fallback_path = Path(tmpdir) / "from-dataset.png" | |
| fallback_path.write_bytes(b"image-bytes") | |
| dataset_client.download_file.return_value = fallback_path | |
| client = ScoringApiClient( | |
| api_url="https://example.com", | |
| session=session, | |
| dataset_client=dataset_client, | |
| ) | |
| with patch("builtins.print") as printed: | |
| payload = client.download_file("task-404", tmpdir) | |
| self.assertEqual(payload, fallback_path) | |
| self.assertIn("404", client.last_warning or "") | |
| dataset_client.download_file.assert_called_once_with("task-404", Path(tmpdir)) | |
| printed.assert_any_call( | |
| "Scoring API unavailable while trying to download file for task-404 (status=404); falling back to GAIA dataset.", | |
| flush=True, | |
| ) | |
| def test_download_file_falls_back_when_api_returns_tiny_json_payload(self) -> None: | |
| response = Mock(status_code=200, headers={"content-type": "application/json"}) | |
| response.content = b'{"detail":"file not found"}' | |
| response.raise_for_status.return_value = None | |
| session = Mock() | |
| session.get.return_value = response | |
| dataset_client = Mock() | |
| with tempfile.TemporaryDirectory() as tmpdir: | |
| fallback_path = Path(tmpdir) / "from-dataset.png" | |
| fallback_path.write_bytes(b"image-bytes") | |
| dataset_client.download_file.return_value = fallback_path | |
| client = ScoringApiClient( | |
| api_url="https://example.com", | |
| session=session, | |
| dataset_client=dataset_client, | |
| ) | |
| with patch("builtins.print") as printed: | |
| payload = client.download_file("task-json", tmpdir) | |
| self.assertEqual(payload, fallback_path) | |
| dataset_client.download_file.assert_called_once_with("task-json", Path(tmpdir)) | |
| printed.assert_any_call( | |
| "[scoring] invalid file payload task=task-json status=200 bytes=27 content_type='application/json'; trying dataset fallback", | |
| flush=True, | |
| ) | |
| def test_default_dataset_client_is_built_lazily(self) -> None: | |
| session = Mock() | |
| response = Mock(status_code=429, headers={}) | |
| error = requests.HTTPError("Too Many Requests", response=response) | |
| response.raise_for_status.side_effect = error | |
| session.get.return_value = response | |
| dataset_instance = Mock() | |
| dataset_instance.get_questions.return_value = [] | |
| with patch.object(ScoringApiClient, "_get_dataset_client", return_value=dataset_instance) as getter: | |
| client = ScoringApiClient(api_url="https://example.com", session=session) | |
| client.get_questions() | |
| getter.assert_called_once_with() | |
| def test_default_dataset_client_uses_validation_split(self) -> None: | |
| dataset_instance = Mock() | |
| with patch.dict(os.environ, {}, clear=True), patch( | |
| "lilith_agent.gaia_dataset.GaiaDatasetClient", | |
| return_value=dataset_instance, | |
| ) as dataset_client: | |
| client = ScoringApiClient(api_url="https://example.com", session=Mock()) | |
| payload = client._get_dataset_client() | |
| self.assertIs(payload, dataset_instance) | |
| dataset_client.assert_called_once_with( | |
| config="2023_all", | |
| split="validation", | |
| level=None, | |
| token=None, | |
| ) | |
| if __name__ == "__main__": | |
| unittest.main() | |