tests/*mpi*: convert to new stand-alone test process (#35802)
This commit is contained in:
parent
8164712264
commit
05b6ac16bc
3 changed files with 92 additions and 128 deletions
|
@ -14,20 +14,19 @@ class Mpi(Package):
|
||||||
homepage = "https://www.mpi-forum.org/"
|
homepage = "https://www.mpi-forum.org/"
|
||||||
virtual = True
|
virtual = True
|
||||||
|
|
||||||
def test(self):
|
def test_mpi_hello(self):
|
||||||
|
"""build and run mpi hello world"""
|
||||||
for lang in ("c", "f"):
|
for lang in ("c", "f"):
|
||||||
filename = self.test_suite.current_test_data_dir.join("mpi_hello." + lang)
|
filename = self.test_suite.current_test_data_dir.join("mpi_hello." + lang)
|
||||||
|
|
||||||
compiler_var = "MPICC" if lang == "c" else "MPIF90"
|
compiler_var = "MPICC" if lang == "c" else "MPIF90"
|
||||||
compiler = os.environ[compiler_var]
|
compiler = which(os.environ[compiler_var])
|
||||||
|
mpirun = which(self.prefix.bin.mpirun)
|
||||||
|
|
||||||
exe_name = "mpi_hello_%s" % lang
|
exe_name = "mpi_hello_%s" % lang
|
||||||
mpirun = join_path(self.prefix.bin, "mpirun")
|
|
||||||
|
|
||||||
compiled = self.run_test(compiler, options=["-o", exe_name, filename])
|
with test_part(self, f"test_mpi_hello_{lang}", purpose=f"build and run {filename}"):
|
||||||
if compiled:
|
compiler("-o", exe_name, filename)
|
||||||
self.run_test(
|
out = mpirun("-np", "1", exe_name, output=str.split, error=str.split)
|
||||||
mpirun,
|
expected = [r"Hello world! From rank \s*0 of \s*1"]
|
||||||
options=["-np", "1", exe_name],
|
check_outputs(expected, out)
|
||||||
expected=[r"Hello world! From rank \s*0 of \s*1"],
|
|
||||||
)
|
|
||||||
|
|
|
@ -600,27 +600,47 @@ def cache_test_sources(self):
|
||||||
install test subdirectory for use during `spack test run`."""
|
install test subdirectory for use during `spack test run`."""
|
||||||
self.cache_extra_test_sources(["examples", join_path("test", "mpi")])
|
self.cache_extra_test_sources(["examples", join_path("test", "mpi")])
|
||||||
|
|
||||||
def run_mpich_test(self, example_dir, exe):
|
def mpi_launcher(self):
|
||||||
"""Run stand alone tests"""
|
"""Determine the appropriate launcher."""
|
||||||
|
commands = [
|
||||||
|
join_path(self.spec.prefix.bin, "mpirun"),
|
||||||
|
join_path(self.spec.prefix.bin, "mpiexec"),
|
||||||
|
]
|
||||||
|
if "+slurm" in self.spec:
|
||||||
|
commands.insert(0, join_path(self.spec["slurm"].prefix.bin))
|
||||||
|
return which(*commands)
|
||||||
|
|
||||||
test_dir = join_path(self.test_suite.current_test_cache_dir, example_dir)
|
def run_mpich_test(self, subdir, exe, num_procs=1):
|
||||||
exe_source = join_path(test_dir, "{0}.c".format(exe))
|
"""Compile and run the test program."""
|
||||||
|
path = self.test_suite.current_test_cache_dir.join(subdir)
|
||||||
|
with working_dir(path):
|
||||||
|
src = f"{exe}.c"
|
||||||
|
if not os.path.isfile(src):
|
||||||
|
raise SkipTest(f"{src} is missing")
|
||||||
|
|
||||||
if not os.path.isfile(exe_source):
|
mpicc = which(os.environ["MPICC"])
|
||||||
print("Skipping {0} test".format(exe))
|
mpicc("-Wall", "-g", "-o", exe, src)
|
||||||
return
|
if num_procs > 1:
|
||||||
|
launcher = self.mpi_launcher()
|
||||||
|
if launcher is not None:
|
||||||
|
launcher("-n", str(num_procs), exe)
|
||||||
|
return
|
||||||
|
|
||||||
self.run_test(
|
test_exe = which(exe)
|
||||||
self.prefix.bin.mpicc,
|
test_exe()
|
||||||
options=[exe_source, "-Wall", "-g", "-o", exe],
|
|
||||||
purpose="test: generate {0} file".format(exe),
|
|
||||||
work_dir=test_dir,
|
|
||||||
)
|
|
||||||
|
|
||||||
self.run_test(exe, purpose="test: run {0} example".format(exe), work_dir=test_dir)
|
def test_cpi(self):
|
||||||
|
"""build and run cpi"""
|
||||||
def test(self):
|
|
||||||
self.run_mpich_test(join_path("test", "mpi", "init"), "finalized")
|
|
||||||
self.run_mpich_test(join_path("test", "mpi", "basic"), "sendrecv")
|
|
||||||
self.run_mpich_test(join_path("test", "mpi", "perf"), "manyrma")
|
|
||||||
self.run_mpich_test("examples", "cpi")
|
self.run_mpich_test("examples", "cpi")
|
||||||
|
|
||||||
|
def test_finalized(self):
|
||||||
|
"""build and run finalized"""
|
||||||
|
self.run_mpich_test(join_path("test", "mpi", "init"), "finalized")
|
||||||
|
|
||||||
|
def test_manyrma(self):
|
||||||
|
"""build and run manyrma"""
|
||||||
|
self.run_mpich_test(join_path("test", "mpi", "perf"), "manyrma", 2)
|
||||||
|
|
||||||
|
def test_sendrecv(self):
|
||||||
|
"""build and run sendrecv"""
|
||||||
|
self.run_mpich_test(join_path("test", "mpi", "basic"), "sendrecv", 2)
|
||||||
|
|
|
@ -1150,28 +1150,27 @@ def setup_install_tests(self):
|
||||||
"""
|
"""
|
||||||
self.cache_extra_test_sources(self.extra_install_tests)
|
self.cache_extra_test_sources(self.extra_install_tests)
|
||||||
|
|
||||||
def _test_bin_ops(self):
|
def run_installed_binary(self, bin, options, expected):
|
||||||
info = ([], ["Ident string: {0}".format(self.spec.version), "MCA"], 0)
|
"""run and check outputs for the installed binary"""
|
||||||
|
exe_path = join_path(self.prefix.bin, bin)
|
||||||
|
if not os.path.exists(exe_path):
|
||||||
|
raise SkipTest(f"{bin} is not installed")
|
||||||
|
|
||||||
ls = (["-n", "1", "ls", ".."], ["openmpi-{0}".format(self.spec.version)], 0)
|
exe = which(exe_path)
|
||||||
|
out = exe(*options, output=str.split, error=str.split)
|
||||||
|
check_outputs(expected, out)
|
||||||
|
|
||||||
checks = {
|
def test_mpirun(self):
|
||||||
"mpirun": ls,
|
"""test installed mpirun"""
|
||||||
"ompi_info": info,
|
options = ["-n", "1", "ls", ".."]
|
||||||
"oshmem_info": info,
|
self.run_installed_binary("mpirun", options, [f"openmpi-{self.spec.version}"])
|
||||||
"oshrun": ls,
|
|
||||||
"shmemrun": ls,
|
|
||||||
}
|
|
||||||
|
|
||||||
for binary in checks:
|
def test_opmpi_info(self):
|
||||||
options, expected, status = checks[binary]
|
"""test installed mpirun"""
|
||||||
exe = join_path(self.prefix.bin, binary)
|
self.run_installed_binary("ompi_info", [], [f"Ident string: {self.spec.version}", "MCA"])
|
||||||
reason = "test: checking {0} output".format(binary)
|
|
||||||
self.run_test(
|
|
||||||
exe, options, expected, status, installed=True, purpose=reason, skip_missing=True
|
|
||||||
)
|
|
||||||
|
|
||||||
def _test_check_versions(self):
|
def test_version(self):
|
||||||
|
"""check versions of installed software"""
|
||||||
comp_vers = str(self.spec.compiler.version)
|
comp_vers = str(self.spec.compiler.version)
|
||||||
spec_vers = str(self.spec.version)
|
spec_vers = str(self.spec.version)
|
||||||
checks = {
|
checks = {
|
||||||
|
@ -1188,116 +1187,62 @@ def _test_check_versions(self):
|
||||||
"ompi_info": spec_vers,
|
"ompi_info": spec_vers,
|
||||||
"ortecc": comp_vers,
|
"ortecc": comp_vers,
|
||||||
"orterun": spec_vers,
|
"orterun": spec_vers,
|
||||||
# Binaries available in versions 2.0.0 through 2.1.6
|
|
||||||
"ompi-submit": spec_vers,
|
|
||||||
"orte-submit": spec_vers,
|
|
||||||
# Binaries available in versions 2.0.0 through 3.1.5
|
|
||||||
"ompi-dvm": spec_vers,
|
|
||||||
"orte-dvm": spec_vers,
|
|
||||||
"oshcc": comp_vers,
|
|
||||||
"oshfort": comp_vers,
|
|
||||||
"oshmem_info": spec_vers,
|
|
||||||
"oshrun": spec_vers,
|
|
||||||
"shmemcc": comp_vers,
|
|
||||||
"shmemfort": comp_vers,
|
|
||||||
"shmemrun": spec_vers,
|
|
||||||
# Binary available in version 3.1.0 through 3.1.5
|
|
||||||
"prun": spec_vers,
|
|
||||||
# Binaries available in versions 3.0.0 through 3.1.5
|
|
||||||
"oshCC": comp_vers,
|
|
||||||
"oshc++": comp_vers,
|
|
||||||
"oshcxx": comp_vers,
|
|
||||||
"shmemCC": comp_vers,
|
|
||||||
"shmemc++": comp_vers,
|
|
||||||
"shmemcxx": comp_vers,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for binary in checks:
|
for bin in checks:
|
||||||
expected = checks[binary]
|
expected = checks[bin]
|
||||||
purpose = "test: ensuring version of {0} is {1}".format(binary, expected)
|
with test_part(
|
||||||
exe = join_path(self.prefix.bin, binary)
|
self, f"test_version_{bin}", purpose=f"ensure version of {bin} is {expected}"
|
||||||
self.run_test(
|
):
|
||||||
exe, "--version", expected, installed=True, purpose=purpose, skip_missing=True
|
self.run_installed_binary(bin, ["--version"], [expected])
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _cached_tests_work_dir(self):
|
def _cached_tests_work_dir(self):
|
||||||
"""The working directory for cached test sources."""
|
"""The working directory for cached test sources."""
|
||||||
return join_path(self.test_suite.current_test_cache_dir, self.extra_install_tests)
|
return join_path(self.test_suite.current_test_cache_dir, self.extra_install_tests)
|
||||||
|
|
||||||
def _test_examples(self):
|
def test_example(self):
|
||||||
"""Run test examples copied from source at build-time."""
|
"""Run test examples copied from source at build-time."""
|
||||||
# Build the copied, cached test examples
|
# Build the copied, cached test examples
|
||||||
self.run_test(
|
with test_part(
|
||||||
"make",
|
self,
|
||||||
["all"],
|
"test_example_make",
|
||||||
[],
|
|
||||||
purpose="test: building cached test examples",
|
purpose="test: building cached test examples",
|
||||||
work_dir=self._cached_tests_work_dir,
|
work_dir=self._cached_tests_work_dir,
|
||||||
)
|
):
|
||||||
|
make("all")
|
||||||
|
|
||||||
# Run examples with known, simple-to-verify results
|
# Run basic examples with known, simple-to-verify results
|
||||||
have_spml = self.spec.satisfies("@2:2.1.6")
|
hello_world = ["Hello, world", "I am", "0 of", "1"]
|
||||||
|
ring_out = ["1 processes in ring", "0 exiting"]
|
||||||
hello_world = (["Hello, world", "I am", "0 of", "1"], 0)
|
|
||||||
|
|
||||||
max_red = (["0/1 dst = 0 1 2"], 0)
|
|
||||||
|
|
||||||
missing_spml = (["No available spml components"], 1)
|
|
||||||
|
|
||||||
no_out = ([""], 0)
|
|
||||||
|
|
||||||
ring_out = (["1 processes in ring", "0 exiting"], 0)
|
|
||||||
|
|
||||||
strided = (["not in valid range"], 255)
|
|
||||||
|
|
||||||
checks = {
|
checks = {
|
||||||
"hello_c": hello_world,
|
"hello_c": hello_world,
|
||||||
"hello_cxx": hello_world,
|
"hello_cxx": hello_world,
|
||||||
"hello_mpifh": hello_world,
|
"hello_mpifh": hello_world,
|
||||||
"hello_oshmem": hello_world if have_spml else missing_spml,
|
|
||||||
"hello_oshmemcxx": hello_world if have_spml else missing_spml,
|
|
||||||
"hello_oshmemfh": hello_world if have_spml else missing_spml,
|
|
||||||
"hello_usempi": hello_world,
|
"hello_usempi": hello_world,
|
||||||
"hello_usempif08": hello_world,
|
"hello_usempif08": hello_world,
|
||||||
"oshmem_circular_shift": ring_out if have_spml else missing_spml,
|
|
||||||
"oshmem_max_reduction": max_red if have_spml else missing_spml,
|
|
||||||
"oshmem_shmalloc": no_out if have_spml else missing_spml,
|
|
||||||
"oshmem_strided_puts": strided if have_spml else missing_spml,
|
|
||||||
"oshmem_symmetric_data": no_out if have_spml else missing_spml,
|
|
||||||
"ring_c": ring_out,
|
"ring_c": ring_out,
|
||||||
"ring_cxx": ring_out,
|
"ring_cxx": ring_out,
|
||||||
"ring_mpifh": ring_out,
|
"ring_mpifh": ring_out,
|
||||||
"ring_oshmem": ring_out if have_spml else missing_spml,
|
|
||||||
"ring_oshmemfh": ring_out if have_spml else missing_spml,
|
|
||||||
"ring_usempi": ring_out,
|
"ring_usempi": ring_out,
|
||||||
"ring_usempif08": ring_out,
|
"ring_usempif08": ring_out,
|
||||||
}
|
}
|
||||||
|
|
||||||
for exe in checks:
|
for binary in checks:
|
||||||
expected, status = checks[exe]
|
expected = checks[binary]
|
||||||
reason = "test: checking {0} example output and status ({1})".format(exe, status)
|
with test_part(
|
||||||
self.run_test(
|
self,
|
||||||
exe,
|
f"test_example_{binary}",
|
||||||
[],
|
purpose="run and check output",
|
||||||
expected,
|
|
||||||
status,
|
|
||||||
installed=False,
|
|
||||||
purpose=reason,
|
|
||||||
skip_missing=True,
|
|
||||||
work_dir=self._cached_tests_work_dir,
|
work_dir=self._cached_tests_work_dir,
|
||||||
)
|
):
|
||||||
|
exe = which(binary)
|
||||||
|
if not exe:
|
||||||
|
raise SkipTest(f"{binary} is missing")
|
||||||
|
|
||||||
def test(self):
|
out = exe(output=str.split, error=str.split)
|
||||||
"""Perform stand-alone/smoke tests on the installed package."""
|
check_outputs(expected, out)
|
||||||
# Simple version check tests on selected installed binaries
|
|
||||||
self._test_check_versions()
|
|
||||||
|
|
||||||
# Test the operation of selected executables
|
|
||||||
self._test_bin_ops()
|
|
||||||
|
|
||||||
# Test example programs pulled from the build
|
|
||||||
self._test_examples()
|
|
||||||
|
|
||||||
|
|
||||||
def get_spack_compiler_spec(compiler):
|
def get_spack_compiler_spec(compiler):
|
||||||
|
|
Loading…
Reference in a new issue