Skip to content

Commit 1bc1aaf

Browse files
committed
feat(validate): add --all flag to validate all example case files
1 parent 9d866bd commit 1bc1aaf

2 files changed

Lines changed: 68 additions & 5 deletions

File tree

toolchain/mfc/cli/commands.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,15 +547,27 @@
547547
Positional(
548548
name="input",
549549
help="Path to case file to validate.",
550+
nargs="?",
551+
default=None,
550552
completion=Completion(type=CompletionType.FILES_PY),
551553
),
552554
],
555+
arguments=[
556+
Argument(
557+
name="all",
558+
short="a",
559+
help="Validate all example case files instead of a single file.",
560+
action=ArgAction.STORE_TRUE,
561+
),
562+
],
553563
examples=[
554564
Example("./mfc.sh validate case.py", "Check syntax and constraints"),
555565
Example("./mfc.sh validate case.py -d", "Validate with toolchain debug output"),
566+
Example("./mfc.sh validate --all", "Validate every example case file"),
556567
],
557568
key_options=[
558569
("-d, --debug-log", "Enable toolchain debug logging"),
570+
("-a, --all", "Validate all example case files"),
559571
],
560572
)
561573

toolchain/mfc/validate.py

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import os
66
import sys
7+
import glob
78

89
from .case_validator import CaseConstraintError, CaseValidator
910
from .common import MFCException
@@ -12,23 +13,75 @@
1213
from .state import ARG
1314

1415

16+
def _validate_one(input_file):
17+
"""Validate a single case file. Returns True if passed, False if failed."""
18+
try:
19+
case = run_input.load(input_file, do_print=False)
20+
stages = ["pre_process", "simulation", "post_process"]
21+
all_passed = True
22+
for stage in stages:
23+
try:
24+
validator = CaseValidator(case.params)
25+
validator.validate(stage)
26+
except CaseConstraintError:
27+
all_passed = False
28+
return all_passed
29+
except MFCException:
30+
return False
31+
32+
1533
def validate():
1634
"""Validate a case file without building or running."""
35+
36+
if ARG("all"):
37+
example_files = sorted(glob.glob("examples/**/case.py", recursive=True))
38+
39+
if not example_files:
40+
cons.print("[bold red]No example case files found in examples/[/bold red]")
41+
sys.exit(1)
42+
43+
cons.print(f"Validating [bold]{len(example_files)}[/bold] example case files...\n")
44+
45+
passed = []
46+
failed = []
47+
48+
for f in example_files:
49+
if _validate_one(f):
50+
passed.append(f)
51+
cons.print(f"[bold green]✓[/bold green] {f}")
52+
else:
53+
failed.append(f)
54+
cons.print(f"[bold red]✗[/bold red] {f}")
55+
56+
cons.print()
57+
cons.print(f"[bold green]{len(passed)} passed[/bold green], [bold red]{len(failed)} failed[/bold red] out of {len(example_files)} total.")
58+
59+
if failed:
60+
cons.print("\n[bold red]Failed cases:[/bold red]")
61+
for f in failed:
62+
cons.print(f" {f}")
63+
sys.exit(1)
64+
else:
65+
cons.print("[bold green]All example cases passed validation![/bold green]")
66+
return
67+
1768
input_file = ARG("input")
1869

70+
if not input_file:
71+
cons.print("[bold red]Error:[/bold red] Provide a case file or use --all to validate all examples.")
72+
sys.exit(1)
73+
1974
if not os.path.isfile(input_file):
2075
cons.print(f"[bold red]Error:[/bold red] File not found: {input_file}")
2176
sys.exit(1)
2277

2378
cons.print(f"Validating [bold magenta]{input_file}[/bold magenta]...\n")
2479

2580
try:
26-
# Step 1: Load and parse case file (checks syntax)
2781
case = run_input.load(input_file, do_print=False)
2882
cons.print("[bold green]✓[/bold green] Syntax valid - case file parsed successfully")
2983
cons.print(f" [dim]Loaded {len(case.params)} parameters[/dim]")
3084

31-
# Step 2: Run constraint validation for each stage
3285
stages = ["pre_process", "simulation", "post_process"]
3386
all_passed = True
3487

@@ -45,12 +98,10 @@ def validate():
4598
except CaseConstraintError as e:
4699
all_passed = False
47100
cons.print(f"[bold yellow]![/bold yellow] {stage} constraints: issues found")
48-
# Show the constraint violations indented
49101
for line in str(e).split("\n"):
50102
if line.strip():
51103
cons.print(f" [dim]{line}[/dim]")
52104

53-
# Step 3: Show summary
54105
cons.print()
55106
if all_passed:
56107
cons.print("[bold green]Case validation complete - all checks passed![/bold green]")
@@ -61,4 +112,4 @@ def validate():
61112
except MFCException as e:
62113
cons.print("\n[bold red]✗ Validation failed:[/bold red]")
63114
cons.print(f"{e}")
64-
sys.exit(1)
115+
sys.exit(1)

0 commit comments

Comments
 (0)