Files
wehub-resource-sync 7a0da7932b
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:08:55 +08:00

249 lines
9.0 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Coverage tests for benchmarks/datasets/browsecomp.py.
Targets the 37 missing lines:
- get_dataset_info / get_default_dataset_path
- process_example() with canary and without canary
- process_example() known_answer_map lookup
- process_example() still-encrypted answer fallback keys
- process_example() decryption exception
- get_question / get_answer
"""
from unittest.mock import patch
MODULE = "local_deep_research.benchmarks.datasets.browsecomp"
def _make_dataset(**kwargs):
from local_deep_research.benchmarks.datasets.browsecomp import (
BrowseCompDataset,
)
return BrowseCompDataset(**kwargs)
# ---------------------------------------------------------------------------
# Dataset metadata
# ---------------------------------------------------------------------------
class TestDatasetInfo:
def test_get_dataset_info_has_browsecomp_id(self):
from local_deep_research.benchmarks.datasets.browsecomp import (
BrowseCompDataset,
)
info = BrowseCompDataset.get_dataset_info()
assert info["id"] == "browsecomp"
assert "name" in info
assert "description" in info
def test_get_default_dataset_path_is_url(self):
from local_deep_research.benchmarks.datasets.browsecomp import (
BrowseCompDataset,
)
path = BrowseCompDataset.get_default_dataset_path()
assert path.startswith("https://")
assert "browse_comp" in path or "browsecomp" in path.lower()
# ---------------------------------------------------------------------------
# process_example no canary
# ---------------------------------------------------------------------------
class TestProcessExampleNoCanary:
@patch(f"{MODULE}.get_known_answer_map", return_value={})
@patch(f"{MODULE}.decrypt")
def test_no_canary_returns_original(self, mock_decrypt, mock_known_map):
ds = _make_dataset()
example = {"problem": "encoded_problem", "answer": "encoded_answer"}
result = ds.process_example(example)
# Without canary, decryption is skipped
mock_decrypt.assert_not_called()
assert result["problem"] == "encoded_problem"
@patch(f"{MODULE}.get_known_answer_map", return_value={})
@patch(f"{MODULE}.decrypt")
def test_empty_canary_returns_original(self, mock_decrypt, mock_known_map):
ds = _make_dataset()
example = {
"problem": "some_problem",
"answer": "some_answer",
"canary": "",
}
ds.process_example(example)
mock_decrypt.assert_not_called()
# ---------------------------------------------------------------------------
# process_example with canary, problem too short to decrypt
# ---------------------------------------------------------------------------
class TestProcessExampleShortProblem:
@patch(f"{MODULE}.get_known_answer_map", return_value={})
@patch(f"{MODULE}.decrypt", return_value="decrypted_answer")
def test_short_problem_not_decrypted(self, mock_decrypt, mock_known_map):
ds = _make_dataset()
example = {
"problem": "short", # len <= 20, not decrypted
"answer": "some_answer",
"canary": "mykey",
}
ds.process_example(example)
# decrypt called for answer but not problem
decrypt_calls = [c[0][1] for c in mock_decrypt.call_args_list]
assert "short" not in decrypt_calls
# ---------------------------------------------------------------------------
# process_example known_answer_map lookup
# ---------------------------------------------------------------------------
class TestProcessExampleKnownAnswerMap:
@patch(f"{MODULE}.get_known_answer_map")
@patch(f"{MODULE}.decrypt")
def test_known_answer_used_without_decrypt(
self, mock_decrypt, mock_known_map
):
known_map = {"encoded_answer_xyz": "Real Answer"}
mock_known_map.return_value = known_map
# decrypt returns something different to confirm it's not called for known answers
mock_decrypt.return_value = "decrypted_problem_text"
ds = _make_dataset()
problem_str = "A" * 25 # long enough to trigger problem decryption
example = {
"problem": problem_str,
"answer": "encoded_answer_xyz",
"canary": "key",
}
result = ds.process_example(example)
assert result["answer"] == "Real Answer"
assert result["correct_answer"] == "Real Answer"
# ---------------------------------------------------------------------------
# process_example regular decryption when not in known map
# ---------------------------------------------------------------------------
class TestProcessExampleRegularDecryption:
@patch(f"{MODULE}.get_known_answer_map", return_value={})
@patch(f"{MODULE}.decrypt")
def test_decrypt_called_for_long_problem_and_answer(
self, mock_decrypt, mock_known_map
):
mock_decrypt.side_effect = lambda text, key: f"decrypted_{text}"
ds = _make_dataset()
long_problem = "P" * 25
example = {
"problem": long_problem,
"answer": "some_answer",
"canary": "key",
}
result = ds.process_example(example)
assert result["problem"] == f"decrypted_{long_problem}"
assert result["answer"] == "decrypted_some_answer"
assert result["correct_answer"] == "decrypted_some_answer"
@patch(f"{MODULE}.get_known_answer_map", return_value={})
@patch(f"{MODULE}.decrypt")
def test_no_answer_field_not_processed(self, mock_decrypt, mock_known_map):
mock_decrypt.return_value = "decrypted"
ds = _make_dataset()
example = {"problem": "P" * 25, "canary": "key"}
result = ds.process_example(example)
# No answer field → answer decryption not attempted
assert "answer" not in result or result.get("answer", "") == ""
# ---------------------------------------------------------------------------
# process_example still-encrypted answer with fallback keys
# ---------------------------------------------------------------------------
class TestProcessExampleFallbackKeys:
@patch(f"{MODULE}.get_known_answer_map", return_value={})
@patch(f"{MODULE}.decrypt")
def test_fallback_key_used_when_still_looks_encrypted(
self, mock_decrypt, mock_known_map
):
# First call (with canary) returns same base64 text (still encrypted)
# Second call (with fallback key "MHGGF2022!") returns plaintext
base64_answer = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/="
call_count = [0]
def decrypt_side_effect(text, key):
call_count[0] += 1
if call_count[0] == 1:
return text # problem decryption
if call_count[0] == 2:
return text # answer with canary still looks encrypted
if key == "MHGGF2022!":
return "Plaintext Answer From Fallback"
return text
mock_decrypt.side_effect = decrypt_side_effect
ds = _make_dataset()
example = {
"problem": "P" * 25,
"answer": base64_answer,
"canary": "wrongkey",
}
result = ds.process_example(example)
# The answer should have been updated by the fallback decryption
assert "answer" in result
# ---------------------------------------------------------------------------
# process_example decryption exception
# ---------------------------------------------------------------------------
class TestProcessExampleDecryptException:
@patch(f"{MODULE}.get_known_answer_map", return_value={})
@patch(f"{MODULE}.decrypt", side_effect=Exception("decode error"))
def test_exception_during_decrypt_logged_not_raised(
self, mock_decrypt, mock_known_map
):
ds = _make_dataset()
example = {
"problem": "P" * 25,
"answer": "some_answer",
"canary": "key",
}
# Should not raise
result = ds.process_example(example)
# Result should still be a dict
assert isinstance(result, dict)
# ---------------------------------------------------------------------------
# get_question / get_answer
# ---------------------------------------------------------------------------
class TestGetQuestionAndAnswer:
def test_get_question_returns_problem(self):
ds = _make_dataset()
example = {"problem": "What is 2+2?", "answer": "4"}
assert ds.get_question(example) == "What is 2+2?"
def test_get_question_returns_empty_when_missing(self):
ds = _make_dataset()
assert ds.get_question({}) == ""
def test_get_answer_prefers_correct_answer(self):
ds = _make_dataset()
example = {"answer": "raw_answer", "correct_answer": "preferred_answer"}
assert ds.get_answer(example) == "preferred_answer"
def test_get_answer_falls_back_to_answer(self):
ds = _make_dataset()
example = {"answer": "fallback"}
assert ds.get_answer(example) == "fallback"