133 lines
4.4 KiB
Python
133 lines
4.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Run no-Abaqus Intel Fortran manifest tests."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
try:
|
|
from fortran_toolchain import FortranToolchain, resolve_toolchain, wrap_command
|
|
except ModuleNotFoundError:
|
|
from scripts.fortran_toolchain import FortranToolchain, resolve_toolchain, wrap_command
|
|
|
|
|
|
MANIFEST_PATH = Path("tests/fortran/manifest.json")
|
|
BUILD_ROOT = Path("build/fortran-tests")
|
|
VALIDATION_MODES = {"off", "detect", "auto", "compile"}
|
|
|
|
|
|
class FortranValidationError(RuntimeError):
|
|
pass
|
|
|
|
|
|
def validation_mode(env: dict[str, str] | None = None) -> str:
|
|
env = env or os.environ
|
|
mode = env.get("HARNESS_FORTRAN_VALIDATION", "auto").lower()
|
|
if mode not in VALIDATION_MODES:
|
|
raise FortranValidationError(f"Unsupported HARNESS_FORTRAN_VALIDATION: {mode}")
|
|
return mode
|
|
|
|
|
|
def load_manifest(root: Path) -> dict | None:
|
|
manifest = root / MANIFEST_PATH
|
|
if not manifest.exists():
|
|
return None
|
|
try:
|
|
payload = json.loads(manifest.read_text(encoding="utf-8"))
|
|
except json.JSONDecodeError as exc:
|
|
raise FortranValidationError(f"Invalid Fortran manifest JSON: {manifest}: {exc}") from exc
|
|
if not isinstance(payload, dict) or not isinstance(payload.get("tests", []), list):
|
|
raise FortranValidationError(f"Fortran manifest must contain a tests array: {manifest}")
|
|
return payload
|
|
|
|
|
|
def _validate_test_record(record: dict) -> tuple[str, list[str]]:
|
|
if not isinstance(record, dict):
|
|
raise FortranValidationError("Fortran manifest test record must be an object.")
|
|
name = record.get("name")
|
|
sources = record.get("sources")
|
|
if not isinstance(name, str) or not name:
|
|
raise FortranValidationError("Fortran manifest test record is missing name.")
|
|
if not isinstance(sources, list) or not all(isinstance(source, str) and source for source in sources):
|
|
raise FortranValidationError(f"Fortran manifest test {name} must define source paths.")
|
|
return name, sources
|
|
|
|
|
|
def build_test_commands(root: Path, manifest: dict, toolchain: FortranToolchain) -> list[str]:
|
|
commands: list[str] = []
|
|
for record in manifest.get("tests", []):
|
|
name, sources = _validate_test_record(record)
|
|
build_dir = root / BUILD_ROOT / name
|
|
build_dir.mkdir(parents=True, exist_ok=True)
|
|
exe_path = build_dir / f"{name}.exe"
|
|
source_paths = [root / source for source in sources]
|
|
compile_args: list[str | Path] = [
|
|
toolchain.executable,
|
|
"/nologo",
|
|
*source_paths,
|
|
f"/exe:{exe_path}",
|
|
]
|
|
commands.append(wrap_command(toolchain, compile_args))
|
|
commands.append(str(exe_path))
|
|
return commands
|
|
|
|
|
|
def discover_commands(root: Path, env: dict[str, str] | None = None) -> list[str]:
|
|
env = env or os.environ
|
|
mode = validation_mode(env)
|
|
if mode == "off":
|
|
return []
|
|
|
|
manifest = load_manifest(root)
|
|
if manifest is None:
|
|
return []
|
|
|
|
toolchain = resolve_toolchain(env)
|
|
if toolchain is None:
|
|
raise FortranValidationError("Fortran validation manifest exists, but no Intel oneAPI Fortran compiler was found.")
|
|
|
|
if mode == "detect":
|
|
return []
|
|
return build_test_commands(root, manifest, toolchain)
|
|
|
|
|
|
def run_command(command: str, root: Path) -> subprocess.CompletedProcess:
|
|
return subprocess.run(command, cwd=root, shell=True, capture_output=True, text=True, encoding="utf-8", errors="replace")
|
|
|
|
|
|
def main() -> int:
|
|
root = Path(__file__).resolve().parent.parent
|
|
try:
|
|
commands = discover_commands(root)
|
|
except FortranValidationError as exc:
|
|
print(f"Fortran validation failed: {exc}", file=sys.stderr)
|
|
return 2
|
|
|
|
if not commands:
|
|
print("No Fortran validation commands configured.")
|
|
return 0
|
|
|
|
for command in commands:
|
|
print(f"$ {command}")
|
|
result = run_command(command, root)
|
|
if result.stdout.strip():
|
|
print("[stdout]")
|
|
print(result.stdout.strip())
|
|
if result.stderr.strip():
|
|
print("[stderr]", file=sys.stderr)
|
|
print(result.stderr.strip(), file=sys.stderr)
|
|
if result.returncode != 0:
|
|
print(f"Fortran validation failed: {command}", file=sys.stderr)
|
|
return result.returncode
|
|
|
|
print("Fortran validation succeeded.")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|