import importlib.util import json import os import tempfile import unittest from unittest import mock from pathlib import Path def load_validate_fortran(): module_path = Path(__file__).resolve().parent / "validate_fortran.py" spec = importlib.util.spec_from_file_location("validate_fortran", module_path) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) return module class ValidateFortranTests(unittest.TestCase): def test_auto_mode_has_no_commands_when_manifest_is_missing(self): validate_fortran = load_validate_fortran() with tempfile.TemporaryDirectory() as tmp: root = Path(tmp) with mock.patch.dict(os.environ, {}, clear=True): commands = validate_fortran.discover_commands(root) self.assertEqual(commands, []) def test_off_mode_skips_manifest(self): validate_fortran = load_validate_fortran() with tempfile.TemporaryDirectory() as tmp: root = Path(tmp) manifest = root / "tests" / "fortran" / "manifest.json" manifest.parent.mkdir(parents=True) manifest.write_text(json.dumps({"tests": []}), encoding="utf-8") with mock.patch.dict(os.environ, {"HARNESS_FORTRAN_VALIDATION": "off"}, clear=True): commands = validate_fortran.discover_commands(root) self.assertEqual(commands, []) def test_manifest_requires_available_compiler(self): validate_fortran = load_validate_fortran() with tempfile.TemporaryDirectory() as tmp: root = Path(tmp) manifest = root / "tests" / "fortran" / "manifest.json" manifest.parent.mkdir(parents=True) manifest.write_text(json.dumps({"tests": [{"name": "case", "sources": ["a.f90"]}]}), encoding="utf-8") with mock.patch.dict(os.environ, {}, clear=True): with mock.patch.object(validate_fortran, "resolve_toolchain", return_value=None): with self.assertRaises(validate_fortran.FortranValidationError): validate_fortran.discover_commands(root) def test_manifest_generates_compile_and_run_commands(self): validate_fortran = load_validate_fortran() with tempfile.TemporaryDirectory() as tmp: root = Path(tmp) manifest = root / "tests" / "fortran" / "manifest.json" manifest.parent.mkdir(parents=True) manifest.write_text( json.dumps( { "tests": [ { "name": "umat_linear_elastic_kernel", "sources": [ "src/fortran/kernels/linear_elastic.f90", "tests/fortran/test_umat_linear_elastic.f90", ], } ] } ), encoding="utf-8", ) toolchain = validate_fortran.FortranToolchain(name="ifx", executable="ifx", env_script=None) with mock.patch.dict(os.environ, {}, clear=True): with mock.patch.object(validate_fortran, "resolve_toolchain", return_value=toolchain): commands = validate_fortran.discover_commands(root) self.assertEqual(len(commands), 2) self.assertIn("ifx /nologo", commands[0]) self.assertIn("src\\fortran\\kernels\\linear_elastic.f90", commands[0]) self.assertIn("/exe:", commands[0]) self.assertTrue(commands[1].endswith("umat_linear_elastic_kernel.exe")) def test_manifest_build_commands_create_test_build_directories(self): validate_fortran = load_validate_fortran() with tempfile.TemporaryDirectory() as tmp: root = Path(tmp) manifest = root / "tests" / "fortran" / "manifest.json" manifest.parent.mkdir(parents=True) manifest.write_text( json.dumps( { "tests": [ { "name": "uel_3d_euler_beam_kernel_stiffness", "sources": [ "src/fortran/uel_3d_euler_beam_kernel.f90", "tests/fortran/test_uel_3d_euler_beam_kernel.f90", ], } ] } ), encoding="utf-8", ) toolchain = validate_fortran.FortranToolchain(name="ifx", executable="ifx", env_script=None) with mock.patch.dict(os.environ, {}, clear=True): with mock.patch.object(validate_fortran, "resolve_toolchain", return_value=toolchain): validate_fortran.discover_commands(root) build_dir = root / "build" / "fortran-tests" / "uel_3d_euler_beam_kernel_stiffness" self.assertTrue(build_dir.is_dir()) if __name__ == "__main__": unittest.main()