Skip to content

Commit 574c277

Browse files
committed
fix: harden error handling in direct test execution
- _extract_mpi_config: use 'mpi_config =' pattern to avoid matching usage sites; wrap ast.literal_eval in try/except for malformed templates; use find() instead of index() to avoid ValueError - TestCase.run(): add try/except for TimeoutExpired, SubprocessError, OSError around subprocess.run(); add 3600s timeout - _get_mpi_config: defensive 'ARG("--") or []' for None safety - test.py: add missing returncode check for --test-all post_process path (pre-existing bug)
1 parent 3a0804f commit 574c277

2 files changed

Lines changed: 55 additions & 25 deletions

File tree

toolchain/mfc/test/case.py

Lines changed: 51 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -32,24 +32,33 @@ def _extract_mpi_config(template_name: str) -> Optional[MPIConfig]:
3232
return None
3333

3434
content = common.file_read(filepath)
35-
idx = content.find("mpi_config")
35+
# Anchor on the assignment to avoid matching usage sites like ${mpi_config['binary']}
36+
idx = content.find("mpi_config =")
37+
if idx == -1:
38+
idx = content.find("mpi_config=")
3639
if idx == -1:
3740
return None
3841

39-
brace_start = content.index("{", idx)
40-
depth = 0
41-
for i in range(brace_start, len(content)):
42-
if content[i] == "{":
43-
depth += 1
44-
elif content[i] == "}":
45-
depth -= 1
46-
if depth == 0:
47-
d = ast.literal_eval(content[brace_start : i + 1])
48-
return MPIConfig(
49-
binary=d["binary"],
50-
flags=d.get("flags", []),
51-
env=d.get("env", {}),
52-
)
42+
brace_start = content.find("{", idx)
43+
if brace_start == -1:
44+
return None
45+
46+
try:
47+
depth = 0
48+
for i in range(brace_start, len(content)):
49+
if content[i] == "{":
50+
depth += 1
51+
elif content[i] == "}":
52+
depth -= 1
53+
if depth == 0:
54+
d = ast.literal_eval(content[brace_start : i + 1])
55+
return MPIConfig(
56+
binary=d["binary"],
57+
flags=d.get("flags", []),
58+
env=d.get("env", {}),
59+
)
60+
except (ValueError, SyntaxError, KeyError):
61+
return None
5362

5463
return None
5564

@@ -69,7 +78,7 @@ def _get_mpi_config() -> MPIConfig:
6978
if _resolved_mpi_config is not None:
7079
return _resolved_mpi_config
7180

72-
extra = ARG("--")
81+
extra = ARG("--") or []
7382
computer = None
7483
for i, arg in enumerate(extra):
7584
if arg in ("-c", "--computer") and i + 1 < len(extra):
@@ -295,15 +304,32 @@ def run(self, targets: List[Union[str, MFCTarget]], gpus: Set[int]) -> subproces
295304
bin_path = target_obj.get_install_binpath(slug_case)
296305
cmd = _mpi_cmd(cfg, self.ppn, bin_path)
297306

298-
result = subprocess.run(
299-
cmd,
300-
cwd=dirpath,
301-
env=env,
302-
text=True,
303-
stdout=subprocess.PIPE,
304-
stderr=subprocess.STDOUT,
305-
check=False,
306-
)
307+
try:
308+
result = subprocess.run(
309+
cmd,
310+
cwd=dirpath,
311+
env=env,
312+
text=True,
313+
stdout=subprocess.PIPE,
314+
stderr=subprocess.STDOUT,
315+
check=False,
316+
timeout=3600,
317+
)
318+
except subprocess.TimeoutExpired:
319+
all_output.append(f"TIMEOUT after 3600s: {' '.join(cmd)}")
320+
return subprocess.CompletedProcess(
321+
args=cmd,
322+
returncode=-1,
323+
stdout="\n".join(all_output),
324+
)
325+
except (subprocess.SubprocessError, OSError) as exc:
326+
all_output.append(f"LAUNCH FAILED: {exc}")
327+
return subprocess.CompletedProcess(
328+
args=cmd,
329+
returncode=-1,
330+
stdout="\n".join(all_output),
331+
)
332+
307333
all_output.append(result.stdout or "")
308334

309335
if result.returncode != 0:

toolchain/mfc/test/test.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,10 @@ def _handle_case(case: TestCase, devices: typing.Set[int]):
506506
out_filepath = os.path.join(case.get_dirpath(), "out_post.txt")
507507
common.file_write(out_filepath, cmd.stdout)
508508

509+
if cmd.returncode != 0:
510+
cons.print(cmd.stdout)
511+
raise MFCException(f"Test {case}: Failed to execute MFC (post_process pass).")
512+
509513
silo_dir = os.path.join(case.get_dirpath(), "silo_hdf5", "p0")
510514
if os.path.isdir(silo_dir):
511515
for silo_filename in os.listdir(silo_dir):

0 commit comments

Comments
 (0)