|
| 1 | +#!/usr/bin/env python3 |
| 2 | + |
| 3 | +"""Run the Firedrake smoke tests.""" |
| 4 | + |
| 5 | +import argparse |
| 6 | +import logging |
| 7 | +import importlib |
| 8 | +import os |
| 9 | +import pathlib |
| 10 | +import subprocess |
| 11 | +import sys |
| 12 | + |
| 13 | + |
| 14 | +# smoke tests grouped by number of processors |
| 15 | +TESTS = { |
| 16 | + 1: ( |
| 17 | + "tests/firedrake/regression/test_stokes_mini.py::test_stokes_mini", |
| 18 | + # spatialindex |
| 19 | + "tests/firedrake/regression/test_locate_cell.py", |
| 20 | + # supermesh |
| 21 | + "tests/firedrake/supermesh/test_assemble_mixed_mass_matrix.py::test_assemble_mixed_mass_matrix[2-CG-CG-0-0]", |
| 22 | + # fieldsplit |
| 23 | + "tests/firedrake/regression/test_matrix_free.py::test_fieldsplitting[parameters3-cofunc_rhs-variational]", |
| 24 | + # near nullspace |
| 25 | + "tests/firedrake/regression/test_nullspace.py::test_near_nullspace", |
| 26 | + ), |
| 27 | + 3: ( |
| 28 | + "tests/firedrake/regression/test_dg_advection.py::test_dg_advection_icosahedral_sphere[nprocs=3]", |
| 29 | + # vertex-only mesh |
| 30 | + "tests/firedrake/regression/test_interpolate_cross_mesh.py::test_interpolate_cross_mesh_parallel[extrudedcube]", |
| 31 | + ), |
| 32 | +} |
| 33 | + |
| 34 | + |
| 35 | +# log to terminal at INFO level |
| 36 | +logging.basicConfig(format="%(message)s", level=logging.INFO) |
| 37 | + |
| 38 | + |
| 39 | +def main() -> None: |
| 40 | + args = parse_args() |
| 41 | + |
| 42 | + for nprocs, tests in TESTS.items(): |
| 43 | + if nprocs == 1: |
| 44 | + logging.info(" Running serial smoke tests") |
| 45 | + else: |
| 46 | + logging.info(f" Running parallel smoke tests (nprocs={nprocs})") |
| 47 | + run_tests(tests, nprocs, args.mpiexec) |
| 48 | + logging.info(" Tests passed") |
| 49 | + |
| 50 | + |
| 51 | +def parse_args() -> argparse.Namespace: |
| 52 | + parser = argparse.ArgumentParser() |
| 53 | + parser.add_argument( |
| 54 | + "--mpiexec", |
| 55 | + type=str, |
| 56 | + default="mpiexec -n", |
| 57 | + help=( |
| 58 | + "Command used to launch MPI. The command must end with the flag " |
| 59 | + "taking the number of processors, e.g. '-n' for mpiexec." |
| 60 | + ), |
| 61 | + ) |
| 62 | + return parser.parse_args() |
| 63 | + |
| 64 | + |
| 65 | +def run_tests(tests: tuple[str], nprocs: int, mpiexec: str) -> None: |
| 66 | + # Find the path to firedrake._check. Don't actually import Firedrake here |
| 67 | + # because that will initialise MPI and can prevent us calling 'mpiexec' |
| 68 | + # below. This only causes issues on some systems. |
| 69 | + firedrake_dir = pathlib.Path( |
| 70 | + importlib.util.find_spec("firedrake").origin |
| 71 | + ).parent |
| 72 | + test_dir = firedrake_dir / "_check" |
| 73 | + |
| 74 | + # Do verbose checking if running on CI and always set no:cacheprovider because |
| 75 | + # we don't want to generate any cache files in $VIRTUAL_ENV/lib/.../firedrake/_check |
| 76 | + if "FIREDRAKE_CI" in os.environ: |
| 77 | + check_flags = "--verbose -p no:cacheprovider" |
| 78 | + else: |
| 79 | + check_flags = "--quiet -p no:cacheprovider" |
| 80 | + |
| 81 | + cmd = f"{mpiexec} {nprocs} {sys.executable} -m pytest {check_flags} -m parallel[{nprocs}]".split() |
| 82 | + cmd.extend(tests) |
| 83 | + |
| 84 | + subprocess.run(cmd, cwd=test_dir, check=True) |
| 85 | + |
| 86 | + |
| 87 | +if __name__ == "__main__": |
| 88 | + main() |
0 commit comments