Skip to content

Commit 1eabc9f

Browse files
committed
test(evaluation): add tests for LCB eval error handling
Worker tests: generic exceptions still return (qid, False), the three infra error types propagate. Pipeline tests: one failing sample scores 0 and the run continues, an infra error in a worker aborts the run, a failing load_lcb_benchmark raises before the pool is created. The pool is replaced with an in-process fake so the tests don't depend on the multiprocessing start method. Also add mlperf_eval to the mypy ignore_errors overrides: these tests are the first import of eval_accuracy, which pulls it into mypy's scope past the path exclude (same treatment as openai_types_gen and metrics/reporter). On main the infra/pre-flight tests fail and the two swallow-behavior tests pass.
1 parent 11b70c1 commit 1eabc9f

2 files changed

Lines changed: 147 additions & 0 deletions

File tree

‎pyproject.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,5 +279,6 @@ exclude = [
279279
module = [
280280
"inference_endpoint.openai.openai_types_gen",
281281
"inference_endpoint.metrics.reporter",
282+
"inference_endpoint.evaluation.legacy_mlperf_deepseek_r1.mlperf_eval.*",
282283
]
283284
ignore_errors = true
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2026 CoreWeave, Inc. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
"""Tests for the LCB local eval error handling in eval_accuracy.py.
17+
18+
evaluate_livecodebench_worker re-raises ImportError/FileNotFoundError/
19+
RuntimeError (broken judge env) and keeps returning False for anything
20+
else (bad generated code). Generated code runs inside the LCB grader
21+
subprocesses, not in the worker, so a bad import in a sample shows up
22+
as a normal grading failure, not as an ImportError here.
23+
24+
The executor is replaced with an in-process fake so monkeypatching
25+
works regardless of the multiprocessing start method.
26+
"""
27+
28+
import pandas as pd
29+
import pytest
30+
from inference_endpoint.evaluation.legacy_mlperf_deepseek_r1.mlperf_eval import (
31+
eval_accuracy,
32+
)
33+
34+
35+
class ImmediateFuture:
36+
def __init__(self, fn, *args):
37+
self._exc = None
38+
self._value = None
39+
try:
40+
self._value = fn(*args)
41+
except BaseException as exc:
42+
self._exc = exc
43+
44+
def result(self, timeout=None):
45+
if self._exc is not None:
46+
raise self._exc
47+
return self._value
48+
49+
50+
class ImmediateExecutor:
51+
def __init__(self, max_workers=None):
52+
pass
53+
54+
def __enter__(self):
55+
return self
56+
57+
def __exit__(self, *exc_info):
58+
return False
59+
60+
def submit(self, fn, *args):
61+
return ImmediateFuture(fn, *args)
62+
63+
64+
@pytest.fixture
65+
def inline_pool(monkeypatch):
66+
monkeypatch.setattr(eval_accuracy, "ProcessPoolExecutor", ImmediateExecutor)
67+
monkeypatch.setattr(
68+
eval_accuracy, "as_completed", lambda futures, timeout=None: list(futures)
69+
)
70+
71+
72+
def _lcb_df(n):
73+
return pd.DataFrame(
74+
{
75+
"dataset": ["livecodebench"] * n,
76+
"extracted_answer": [f"code_{i}" for i in range(n)],
77+
"ground_truth": [f"qid_{i}" for i in range(n)],
78+
"prompt_accuracy": [0.0] * n,
79+
}
80+
)
81+
82+
83+
class TestWorker:
84+
def test_sample_level_failure_scores_incorrect(self, monkeypatch):
85+
# Pre-existing behavior, unchanged by the fix.
86+
def boom(code, question_id):
87+
raise ValueError("bad generated code")
88+
89+
monkeypatch.setattr(eval_accuracy, "evaluate_livecodebench", boom)
90+
assert eval_accuracy.evaluate_livecodebench_worker(("code", "qid")) == (
91+
"qid",
92+
False,
93+
)
94+
95+
@pytest.mark.parametrize("exc_type", [ImportError, FileNotFoundError, RuntimeError])
96+
def test_infra_failure_reraises(self, monkeypatch, exc_type):
97+
def boom(code, question_id):
98+
raise exc_type("judge is broken")
99+
100+
monkeypatch.setattr(eval_accuracy, "evaluate_livecodebench", boom)
101+
with pytest.raises(exc_type):
102+
eval_accuracy.evaluate_livecodebench_worker(("code", "qid"))
103+
104+
105+
class TestProcessLivecodebenchParallel:
106+
def test_one_bad_sample_does_not_abort_run(self, monkeypatch, inline_pool):
107+
monkeypatch.setattr(eval_accuracy, "load_lcb_benchmark", lambda: {})
108+
109+
def grade(code, question_id):
110+
if question_id == "qid_1":
111+
raise ValueError("bad generated code")
112+
return True
113+
114+
monkeypatch.setattr(eval_accuracy, "evaluate_livecodebench", grade)
115+
116+
df = _lcb_df(3)
117+
correct, total = eval_accuracy.process_livecodebench_parallel(df, df.index)
118+
119+
assert (correct, total) == (2, 3)
120+
assert df["prompt_accuracy"].tolist() == [100.0, 0.0, 100.0]
121+
122+
def test_broken_judge_in_worker_raises(self, monkeypatch, inline_pool):
123+
# The 0/335 case: every worker hits the same env error.
124+
monkeypatch.setattr(eval_accuracy, "load_lcb_benchmark", lambda: {})
125+
126+
def grade(code, question_id):
127+
raise ImportError("No module named 'anthropic'")
128+
129+
monkeypatch.setattr(eval_accuracy, "evaluate_livecodebench", grade)
130+
131+
with pytest.raises(ImportError):
132+
eval_accuracy.process_livecodebench_parallel(_lcb_df(3), _lcb_df(3).index)
133+
134+
def test_preflight_raises_before_spawning_workers(self, monkeypatch):
135+
def broken_benchmark():
136+
raise RuntimeError("Dataset scripts are no longer supported")
137+
138+
monkeypatch.setattr(eval_accuracy, "load_lcb_benchmark", broken_benchmark)
139+
140+
def no_pool(*args, **kwargs):
141+
raise AssertionError("worker pool must not be created")
142+
143+
monkeypatch.setattr(eval_accuracy, "ProcessPoolExecutor", no_pool)
144+
145+
with pytest.raises(RuntimeError, match="no longer supported"):
146+
eval_accuracy.process_livecodebench_parallel(_lcb_df(2), _lcb_df(2).index)

0 commit comments

Comments
 (0)