项目文件夹

文件
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

584 行
21 KiB
Python

"""
Coverage tests for benchmarks/datasets/xbench_deepsearch.py.
Targets the 74 missing lines:
- get_dataset_info / get_default_dataset_path
- load() with/without num_examples
- load_data() via datasets library – encrypted and plain prompts
- load_data() datasets.ImportError fallback to _load_from_url
- load_data() exception fallback to _load_from_url
- _load_from_url() success, exception (returns [])
- process_example()
- xor_decrypt
"""
import base64
from unittest.mock import MagicMock, Mock, patch
MODULE = "local_deep_research.benchmarks.datasets.xbench_deepsearch"
def _make_dataset(**kwargs):
from local_deep_research.benchmarks.datasets.xbench_deepsearch import (
XBenchDeepSearchDataset,
)
return XBenchDeepSearchDataset(**kwargs)
# ---------------------------------------------------------------------------
# Static helpers
# ---------------------------------------------------------------------------
class TestXorDecrypt:
# test_xor_decrypt_roundtrip is defined first so it runs first and warms up
# the expensive module import within the 60-second pytest-timeout window.
def test_xor_decrypt_roundtrip(self):
from local_deep_research.benchmarks.datasets.xbench_deepsearch import (
XBenchDeepSearchDataset,
)
plaintext = b"Hello, World!"
key = "secret"
encrypted = XBenchDeepSearchDataset.xor_decrypt(plaintext, key)
decrypted = XBenchDeepSearchDataset.xor_decrypt(encrypted, key)
assert decrypted == plaintext
def test_xor_decrypt_basic(self):
"""Pure XOR decrypt: a key XOR'd twice returns the original data."""
from local_deep_research.benchmarks.datasets.xbench_deepsearch import (
XBenchDeepSearchDataset,
)
plaintext = b"Hello, World!"
key = "secret"
encrypted = XBenchDeepSearchDataset.xor_decrypt(plaintext, key)
# XOR is its own inverse
decrypted = XBenchDeepSearchDataset.xor_decrypt(encrypted, key)
assert decrypted == plaintext
def test_xor_decrypt_empty_data(self):
from local_deep_research.benchmarks.datasets.xbench_deepsearch import (
XBenchDeepSearchDataset,
)
result = XBenchDeepSearchDataset.xor_decrypt(b"", "key")
assert result == b""
def test_xor_decrypt_key_wraps_around(self):
"""Key shorter than data: key bytes repeat (modulo)."""
from local_deep_research.benchmarks.datasets.xbench_deepsearch import (
XBenchDeepSearchDataset,
)
data = b"ABCDEF"
key = "AB" # 2 bytes, data is 6 bytes – wraps 3 times
result = XBenchDeepSearchDataset.xor_decrypt(data, key)
assert len(result) == 6
key_bytes = key.encode("utf-8")
expected = bytes(data[i] ^ key_bytes[i % 2] for i in range(6))
assert result == expected
# ---------------------------------------------------------------------------
# Dataset metadata
# ---------------------------------------------------------------------------
class TestDatasetInfo:
def test_get_dataset_info_returns_required_keys(self):
from local_deep_research.benchmarks.datasets.xbench_deepsearch import (
XBenchDeepSearchDataset,
)
info = XBenchDeepSearchDataset.get_dataset_info()
assert info["id"] == "xbench_deepsearch"
assert "name" in info
assert "description" in info
assert "url" in info
def test_get_dataset_info(self):
"""get_dataset_info returns a dict with all expected keys and correct id."""
from local_deep_research.benchmarks.datasets.xbench_deepsearch import (
XBenchDeepSearchDataset,
)
info = XBenchDeepSearchDataset.get_dataset_info()
assert isinstance(info, dict)
for key in ("id", "name", "description", "url"):
assert key in info, f"Missing key: {key}"
assert info["id"] == "xbench_deepsearch"
assert "xbench" in info["url"].lower() or "DeepSearch" in info["url"]
def test_get_default_dataset_path(self):
"""get_default_dataset_path returns a non-empty string."""
from local_deep_research.benchmarks.datasets.xbench_deepsearch import (
XBenchDeepSearchDataset,
)
path = XBenchDeepSearchDataset.get_default_dataset_path()
assert isinstance(path, str)
assert len(path) > 0
assert "xbench" in path.lower() or "DeepSearch" in path
def test_get_default_dataset_path_is_huggingface_identifier(self):
from local_deep_research.benchmarks.datasets.xbench_deepsearch import (
XBenchDeepSearchDataset,
)
path = XBenchDeepSearchDataset.get_default_dataset_path()
assert "/" in path
# ---------------------------------------------------------------------------
# process_example
# ---------------------------------------------------------------------------
class TestProcessExample:
def test_process_example_adds_metadata(self):
ds = _make_dataset()
example = {"id": "q1", "problem": "What is X?", "answer": "Y"}
result = ds.process_example(example)
assert result["requires_deep_search"] is True
assert result["expected_iterations"] == 4
assert "evaluation_criteria" in result
def test_process_example(self):
"""process_example adds requires_deep_search, expected_iterations, evaluation_criteria."""
ds = _make_dataset()
example = {
"id": "q42",
"problem": "Who invented calculus?",
"answer": "Newton and Leibniz",
"canary": "somekey",
}
result = ds.process_example(example)
assert result["requires_deep_search"] is True
assert result["expected_iterations"] == 4
criteria = result["evaluation_criteria"]
assert "accuracy" in criteria
assert "completeness" in criteria
assert "reasoning" in criteria
assert "sources" in criteria
def test_process_example_preserves_original_fields(self):
ds = _make_dataset()
example = {
"id": "q2",
"problem": "question",
"answer": "ans",
"canary": "key",
}
result = ds.process_example(example)
assert result["id"] == "q2"
assert result["problem"] == "question"
assert result["answer"] == "ans"
def test_evaluation_criteria_weights_sum_to_one(self):
ds = _make_dataset()
example = {"id": "q3", "problem": "Q", "answer": "A"}
result = ds.process_example(example)
total = sum(result["evaluation_criteria"].values())
assert abs(total - 1.0) < 1e-9
def test_process_example_does_not_mutate_input(self):
"""process_example returns a copy, original dict unchanged."""
ds = _make_dataset()
example = {"id": "q5", "problem": "P", "answer": "A"}
original_keys = set(example.keys())
ds.process_example(example)
assert set(example.keys()) == original_keys
# ---------------------------------------------------------------------------
# load() method
# ---------------------------------------------------------------------------
class TestLoad:
def test_load_returns_list_of_processed_examples(self):
ds = _make_dataset()
raw = [
{"id": "1", "problem": "P1", "answer": "A1", "canary": ""},
{"id": "2", "problem": "P2", "answer": "A2", "canary": ""},
]
with patch.object(ds, "load_data", return_value=raw):
result = ds.load()
assert len(result) == 2
assert result[0]["requires_deep_search"] is True
def test_load_with_sampling(self):
"""load() samples when num_examples < total length."""
ds = _make_dataset(num_examples=3, seed=42)
raw = [
{
"id": str(i),
"problem": f"Q{i}",
"answer": f"A{i}",
"canary": "",
}
for i in range(10)
]
with patch.object(ds, "load_data", return_value=raw):
result = ds.load()
assert len(result) == 3
for item in result:
assert item["requires_deep_search"] is True
def test_load_samples_when_num_examples_set(self):
ds = _make_dataset(num_examples=3, seed=42)
raw = [
{
"id": str(i),
"problem": f"Q{i}",
"answer": f"A{i}",
"canary": "",
}
for i in range(10)
]
with patch.object(ds, "load_data", return_value=raw):
result = ds.load()
assert len(result) == 3
def test_load_no_sampling_when_num_examples_none(self):
ds = _make_dataset()
raw = [
{
"id": str(i),
"problem": f"Q{i}",
"answer": f"A{i}",
"canary": "",
}
for i in range(5)
]
with patch.object(ds, "load_data", return_value=raw):
result = ds.load()
assert len(result) == 5
def test_load_full_integration(self):
"""load() calls load_data then process_example for each item."""
ds = _make_dataset()
raw = [
{
"id": "a",
"problem": "Integration Q",
"answer": "Integration A",
"canary": "",
},
]
with patch.object(ds, "load_data", return_value=raw) as mock_load:
with patch.object(
ds, "process_example", wraps=ds.process_example
) as mock_process:
result = ds.load()
mock_load.assert_called_once()
mock_process.assert_called_once_with(raw[0])
assert len(result) == 1
assert result[0]["requires_deep_search"] is True
def test_load_caches_results(self):
"""A second load() returns the cached examples without reloading."""
ds = _make_dataset()
raw = [{"id": "1", "problem": "P", "answer": "A", "canary": ""}]
with patch.object(ds, "load_data", return_value=raw) as mock_load:
first = ds.load()
second = ds.load()
mock_load.assert_called_once()
assert first is second
def test_registry_load_dataset_respects_num_examples(self):
"""Regression test for #4451: DatasetRegistry.load_dataset() calls
load() with no arguments, so sampling must honor the constructor's
num_examples instead of loading the full dataset."""
from local_deep_research.benchmarks.datasets.base import (
DatasetRegistry,
)
from local_deep_research.benchmarks.datasets.xbench_deepsearch import (
XBenchDeepSearchDataset,
)
raw = [
{
"id": str(i),
"problem": f"Q{i}",
"answer": f"A{i}",
"canary": "",
}
for i in range(100)
]
with patch.object(
XBenchDeepSearchDataset, "load_data", return_value=raw
):
result = DatasetRegistry.load_dataset(
"xbench_deepsearch", num_examples=10, seed=None
)
assert len(result) == 10
# ---------------------------------------------------------------------------
# load_data() – datasets library available, plain text fields
# ---------------------------------------------------------------------------
class TestLoadDataPlainText:
def test_load_via_datasets_library(self):
"""load_data uses datasets.load_dataset when available and returns formatted items."""
ds = _make_dataset()
mock_item = {
"id": "plain_1",
"prompt": "What is the speed of light?",
"answer": "299,792,458 m/s",
"canary": "testkey",
"reference_steps": "",
}
mock_dataset = [mock_item]
mock_load_dataset = Mock(return_value=mock_dataset)
with patch.dict(
"sys.modules", {"datasets": Mock(load_dataset=mock_load_dataset)}
):
with patch(f"{MODULE}.logger"):
result = ds.load_data()
assert len(result) == 1
assert result[0]["problem"] == "What is the speed of light?"
assert result[0]["answer"] == "299,792,458 m/s"
def test_load_data_plain_text_prompt_and_answer(self):
ds = _make_dataset()
mock_item = {
"id": "plain_1",
"prompt": "What is the speed of light?",
"answer": "299,792,458 m/s",
"canary": "testkey",
"reference_steps": "",
}
mock_dataset = [mock_item]
mock_load_dataset = Mock(return_value=mock_dataset)
with patch.dict(
"sys.modules", {"datasets": Mock(load_dataset=mock_load_dataset)}
):
with patch(f"{MODULE}.logger"):
result = ds.load_data()
assert len(result) == 1
assert result[0]["problem"] == "What is the speed of light?"
assert result[0]["answer"] == "299,792,458 m/s"
def test_load_data_uses_default_path_when_none(self):
ds = _make_dataset()
mock_dataset = []
mock_load_dataset = Mock(return_value=mock_dataset)
with patch.dict(
"sys.modules", {"datasets": Mock(load_dataset=mock_load_dataset)}
):
with patch(f"{MODULE}.logger"):
result = ds.load_data(dataset_path=None)
mock_load_dataset.assert_called_once_with(
"xbench/DeepSearch", split="train"
)
assert result == []
def test_load_data_formatted_item_has_required_keys(self):
ds = _make_dataset()
mock_item = {
"id": "test_id",
"prompt": "Some plain question",
"answer": "Some plain answer",
"canary": "k",
"reference_steps": "step1",
}
mock_load_dataset = Mock(return_value=[mock_item])
with patch.dict(
"sys.modules", {"datasets": Mock(load_dataset=mock_load_dataset)}
):
with patch(f"{MODULE}.logger"):
result = ds.load_data()
item = result[0]
for key in ("id", "problem", "answer", "reference_steps", "canary"):
assert key in item, f"Missing key: {key}"
assert item["id"] == "test_id"
# ---------------------------------------------------------------------------
# load_data() – encrypted fields (base64-like prompt)
# ---------------------------------------------------------------------------
class TestLoadDataEncryptedFields:
def test_load_data_decrypts_base64_encoded_prompt(self):
ds = _make_dataset()
key = "mykey"
plaintext = b"This is the real question"
key_bytes = key.encode("utf-8")
xored = bytes(
[
plaintext[i] ^ key_bytes[i % len(key_bytes)]
for i in range(len(plaintext))
]
)
encoded_prompt = base64.b64encode(xored).decode("utf-8")
mock_item = {
"id": "enc_1",
"prompt": encoded_prompt,
"answer": "some plain answer",
"canary": key,
"reference_steps": "",
}
mock_dataset = [mock_item]
mock_load_dataset = Mock(return_value=mock_dataset)
with patch.dict(
"sys.modules", {"datasets": Mock(load_dataset=mock_load_dataset)}
):
with patch(f"{MODULE}.logger"):
result = ds.load_data()
assert result[0]["problem"] == "This is the real question"
# ---------------------------------------------------------------------------
# load_data() – datasets ImportError falls back to _load_from_url
# ---------------------------------------------------------------------------
class TestLoadDatasetsImportErrorFallback:
def test_load_datasets_import_error_fallback(self):
"""When 'datasets' library is not installed, _load_from_url is called."""
ds = _make_dataset()
fallback_data = [
{"id": "url_1", "problem": "Q", "answer": "A", "canary": ""}
]
with patch.object(
ds, "_load_from_url", return_value=fallback_data
) as mock_url:
with patch.dict("sys.modules", {"datasets": None}):
result = ds.load_data()
mock_url.assert_called_once()
assert result == fallback_data
def test_import_error_falls_back_to_url(self):
ds = _make_dataset()
fallback_data = [
{"id": "url_1", "problem": "Q", "answer": "A", "canary": ""}
]
with patch.object(
ds, "_load_from_url", return_value=fallback_data
) as mock_url:
with patch.dict("sys.modules", {"datasets": None}):
result = ds.load_data()
mock_url.assert_called_once()
assert result == fallback_data
# ---------------------------------------------------------------------------
# load_data() – datasets exception falls back to _load_from_url
# ---------------------------------------------------------------------------
class TestLoadDatasetsExceptionFallback:
def test_load_datasets_exception_fallback(self):
"""When load_dataset raises an exception, falls back to _load_from_url."""
ds = _make_dataset()
fallback_data = [
{"id": "fb_1", "problem": "Q", "answer": "A", "canary": ""}
]
mock_load_dataset = Mock(side_effect=RuntimeError("network error"))
with patch.object(
ds, "_load_from_url", return_value=fallback_data
) as mock_url:
with patch.dict(
"sys.modules",
{"datasets": Mock(load_dataset=mock_load_dataset)},
):
with patch(f"{MODULE}.logger"):
result = ds.load_data()
mock_url.assert_called_once()
assert result == fallback_data
def test_exception_in_load_dataset_falls_back_to_url(self):
ds = _make_dataset()
fallback_data = [
{"id": "fb_1", "problem": "Q", "answer": "A", "canary": ""}
]
mock_load_dataset = Mock(side_effect=RuntimeError("network error"))
with patch.object(
ds, "_load_from_url", return_value=fallback_data
) as mock_url:
with patch.dict(
"sys.modules",
{"datasets": Mock(load_dataset=mock_load_dataset)},
):
with patch(f"{MODULE}.logger"):
result = ds.load_data()
mock_url.assert_called_once()
assert result == fallback_data
# ---------------------------------------------------------------------------
# _load_from_url – success and failure paths
# ---------------------------------------------------------------------------
class TestLoadFromUrl:
def test_load_from_url_success(self):
"""_load_from_url calls pd.read_parquet and returns a list of dicts."""
ds = _make_dataset()
mock_df = MagicMock()
row = MagicMock()
row.get = lambda key, default="": {
"id": "url_q1",
"prompt": "Direct URL question",
"answer": "Direct URL answer",
"canary": "",
"reference_steps": "",
}.get(key, default)
mock_df.iterrows.return_value = [(0, row)]
mock_pd = Mock()
mock_pd.read_parquet.return_value = mock_df
with patch.dict("sys.modules", {"pandas": mock_pd}):
with patch(f"{MODULE}.logger"):
result = ds._load_from_url()
mock_pd.read_parquet.assert_called_once()
assert len(result) == 1
assert result[0]["problem"] == "Direct URL question"
def test_load_from_url_success_returns_list(self):
ds = _make_dataset()
mock_df = MagicMock()
row = MagicMock()
row.get = lambda key, default="": {
"id": "url_q1",
"prompt": "Direct URL question",
"answer": "Direct URL answer",
"canary": "",
"reference_steps": "",
}.get(key, default)
mock_df.iterrows.return_value = [(0, row)]
mock_pd = Mock()
mock_pd.read_parquet.return_value = mock_df
with patch.dict("sys.modules", {"pandas": mock_pd}):
with patch(f"{MODULE}.logger"):
result = ds._load_from_url()
assert len(result) == 1
assert result[0]["problem"] == "Direct URL question"
def test_load_from_url_failure_returns_empty(self):
"""_load_from_url returns [] when an exception occurs (e.g. connection error)."""
ds = _make_dataset()
mock_pd = Mock()
mock_pd.read_parquet.side_effect = Exception("connection refused")
with patch.dict("sys.modules", {"pandas": mock_pd}):
with patch(f"{MODULE}.logger"):
result = ds._load_from_url()
assert result == []
def test_load_from_url_exception_returns_empty_list(self):
ds = _make_dataset()
mock_pd = Mock()
mock_pd.read_parquet.side_effect = Exception("connection refused")
with patch.dict("sys.modules", {"pandas": mock_pd}):
with patch(f"{MODULE}.logger"):
result = ds._load_from_url()
assert result == []