-
Notifications
You must be signed in to change notification settings - Fork 0
🧪 [add tests for compute_free_model_score] #54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,7 @@ | ||
| ## 2024-06-24 - [Test implementation of detect_active_tool] | ||
| **Learning:** `router/main.py` requires configuration context (`CONFIG_PATH`) to be set, otherwise importing it for unit tests throws an error since it attempts to read config upon importing. | ||
| **Action:** Always mock or provide required environment variables such as `CONFIG_PATH` before importing functions from `router/main.py`. | ||
| ## 2024-06-16 - Synchronous I/O in Async API Handlers | ||
| **Learning:** `save_persisted_stats()` was being called synchronously on every API request, cache hit, and tool usage log, triggering blocking disk I/O in the main event loop. | ||
| **Action:** Always throttle or batch background telemetry writes in async Python applications to prevent blocking the event loop under load. | ||
|
|
||
| ## 2026-06-24 - Async Offloading for SQLite I/O | ||
| **Learning:** Synchronous blocking I/O (like SQLite queries) inside an async event loop handler can cause significant latency spikes and block other requests. | ||
| **Action:** Use `asyncio.to_thread()` to offload synchronous database interactions to a worker thread, ensuring the main event loop remains responsive. |
This file was deleted.
This file was deleted.
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| import pytest | ||
| from unittest.mock import patch, mock_open | ||
| import json | ||
|
|
||
| from router import main as router_main | ||
| from router.main import compute_free_model_score | ||
|
|
||
| @pytest.fixture(autouse=True) | ||
| def reset_cache(): | ||
| """Reset the global cache state before each test.""" | ||
| router_main._AA_SCORES_CACHE = {} | ||
| router_main._AA_SCORES_LOADED = False | ||
| yield | ||
| router_main._AA_SCORES_CACHE = {} | ||
| router_main._AA_SCORES_LOADED = False | ||
|
|
||
| def test_compute_free_model_score_known_model(): | ||
| """Test when the model id exists in the cache.""" | ||
| mock_data = json.dumps({"scores": {"model-a": 85.5}}) | ||
| with patch("builtins.open", mock_open(read_data=mock_data)): | ||
| score = compute_free_model_score({"id": "model-a"}) | ||
| assert score == 85.5 | ||
|
|
||
| def test_compute_free_model_score_unknown_model(): | ||
| """Test when the model id is not in the cache.""" | ||
| mock_data = json.dumps({"scores": {"model-a": 85.5}}) | ||
| with patch("builtins.open", mock_open(read_data=mock_data)): | ||
| score = compute_free_model_score({"id": "model-b"}) | ||
| assert score == 25.0 | ||
|
|
||
| def test_compute_free_model_score_missing_id(): | ||
| """Test when the model dictionary is missing an 'id'.""" | ||
| mock_data = json.dumps({"scores": {"model-a": 85.5}}) | ||
| with patch("builtins.open", mock_open(read_data=mock_data)): | ||
| score = compute_free_model_score({"name": "just a name"}) | ||
| assert score == 25.0 | ||
|
|
||
| def test_compute_free_model_score_file_not_found(): | ||
| """Test fallback when the aa_scores.json file is missing or fails to load.""" | ||
| with patch("builtins.open", side_effect=FileNotFoundError): | ||
| score = compute_free_model_score({"id": "model-a"}) | ||
| assert score == 25.0 | ||
| assert router_main._AA_SCORES_LOADED is True | ||
| assert router_main._AA_SCORES_CACHE == {} | ||
|
Comment on lines
+17
to
+44
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Patching def test_compute_free_model_score_known_model():
"""Test when the model id exists in the cache."""
mock_data = json.dumps({"scores": {"model-a": 85.5}})
with patch("router.main.open", mock_open(read_data=mock_data)):
score = compute_free_model_score({"id": "model-a"})
assert score == 85.5
def test_compute_free_model_score_unknown_model():
"""Test when the model id is not in the cache."""
mock_data = json.dumps({"scores": {"model-a": 85.5}})
with patch("router.main.open", mock_open(read_data=mock_data)):
score = compute_free_model_score({"id": "model-b"})
assert score == 25.0
def test_compute_free_model_score_missing_id():
"""Test when the model dictionary is missing an 'id'."""
mock_data = json.dumps({"scores": {"model-a": 85.5}})
with patch("router.main.open", mock_open(read_data=mock_data)):
score = compute_free_model_score({"name": "just a name"})
assert score == 25.0
def test_compute_free_model_score_file_not_found():
"""Test fallback when the aa_scores.json file is missing or fails to load."""
with patch("router.main.open", side_effect=FileNotFoundError):
score = compute_free_model_score({"id": "model-a"})
assert score == 25.0
assert router_main._AA_SCORES_LOADED is True
assert router_main._AA_SCORES_CACHE == {} |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Add a true malformed-
idcase.Line 31 only covers the missing-key path. A present-but-malformed
id(for exampleNoneor123) still flows throughm.get("id", ""), so this suite does not quite cover the “malformed or missing IDs” contract yet.Suggested test shape
📝 Committable suggestion
🧰 Tools
🪛 ast-grep (0.44.0)
[info] 32-32: use jsonify instead of json.dumps for JSON output
Context: json.dumps({"scores": {"model-a": 85.5}})
Note: [CWE-116] Improper Encoding or Escaping of Output.
(use-jsonify)
🤖 Prompt for AI Agents