import os import pytest import importlib import subprocess import time import shutil from pathlib import Path mod = importlib.import_module("install-mpsd-software-environment") def test_os_chdir(tmp_path): # create a temporary directory for testing temp_dir = tmp_path / "test_os_chdir" temp_dir.mkdir() # initial current working directory initial_cwd = os.getcwd() # change to the temporary directory using os_chdir with mod.os_chdir(str(temp_dir)): assert os.getcwd() == str(temp_dir) # current working directory should be back to initial directory assert os.getcwd() == initial_cwd def test_prepare_environment(tmp_path): # simulate running ./install-software-environment.py --release dev-23a --target-directory /tmp/test_prepare_env # prepare_env is run when cmd is not specified, we can test cmd='prepare' and cmd=None to check both cases script_dir = tmp_path / "test_prepare_env" spack_environments = "spack-environments" mpsd_release_to_test = "dev-23a" release_base_dir = script_dir / mpsd_release_to_test # check that the test directory does not exist assert not script_dir.exists() result = mod.prepare_environment( mpsd_release=mpsd_release_to_test, script_dir=(script_dir) ) # wait for 20 seconds for the git clone to finish # time.sleep(20) # check if the directory now is created assert release_base_dir.exists() # check for spack-environments directory assert spack_environments in os.listdir(release_base_dir) # check if the git branch is correctly checked out assert ( subprocess.run( f"cd {str(release_base_dir/spack_environments)} && git branch", shell=True, capture_output=True, ) .stdout.decode("utf-8") .split("\n")[0] == f"* {mpsd_release_to_test}" ) # check that result is a list and contains atleast ['global','foss2021a-mpi'] assert isinstance(result, list) assert "global" in result assert "foss2021a-mpi" in result # Expect an Exception when wrong mpsd_release is provided with pytest.raises(Exception): result = mod.prepare_environment( mpsd_release="wrong-mpsd-release", script_dir=(script_dir) ) def test_setup_log_cmd(tmp_path): # check that logs/install-software-environment.log is updated when the module is run log_file = "install.log" script_dir = tmp_path / "test_prepare_env" spack_environments = "spack-environments" mpsd_release_to_test = "dev-23a" release_base_dir = script_dir / mpsd_release_to_test if os.path.exists(release_base_dir/log_file): initial_bytes = os.path.getsize(log_file) else: initial_bytes = 0 # run the prepare_env functionality result = mod.prepare_environment( mpsd_release=mpsd_release_to_test, script_dir=(script_dir) ) # check that logs/install-software-environment.log is updated assert os.path.exists(release_base_dir/log_file) assert os.path.getsize(release_base_dir/log_file) > initial_bytes # Check that the log file has "Spack environments branch: dev-23a " in the last line with open(release_base_dir/log_file, "r") as f: last_line = f.readlines()[-1] assert "Spack environments branch: dev-23a " in last_line def test_install_environment(tmp_path): # Test the installation part # This is a long test, its handy to test this with print statements printed to stdout, use: # pytest -s # Expect an Exception when wrong toolchains are provided with pytest.raises(Exception): mod.install_environment( mpsd_release="dev-23a", toolchains=["wrong-toolchain"], script_dir=(tmp_path), ) # Expect an Exception when wrong mpsd_release is provided ( part of prepare_environment) with pytest.raises(Exception): mod.install_environment( mpsd_release="wrong-mpsd-release", toolchains=["foss2021a-mpi"], script_dir=(tmp_path), ) # prepare a test of global generic with only zlib to test the installation # prepare dev-23a release # script_dir = tmp_path / "test_global_generic" # for actaual installation avoid tmp_path as the lenght of the path is too long and spack complains script_dir = Path('/tmp/test_global_generic') script_dir.mkdir(exist_ok=True, parents=True) spack_environments = "spack-environments" mpsd_release_to_test = "dev-23a" mpsd_microarch=os.getenv("MPSD_MICROARCH",'UNKNOWN_MICROARCH') release_base_dir = script_dir / mpsd_release_to_test prepare_result = mod.prepare_environment( mpsd_release=mpsd_release_to_test, script_dir=(script_dir) ) # Patch the spack environments to create a fake global_generic # create a test toolchain toolchain_src_dir = release_base_dir / "spack-environments" / "toolchains" # with mod.os_chdir(toolchain_src_dir): # subprocess.run( # "cp -r foss2021a-mpi fuss1999a", shell=True, capture_output=True # ) # add zlib as a spec to global_generic with open(toolchain_src_dir / "global_generic" / "global_packages.list", "w") as f: f.write("zlib@1.2.13 \n") # add zlib to whitelist of module creation file by replacing anaconda3%gcc@10.2.1 with zlib@1.2.13 # in release_base_dir / "spack-environments/spack_overlay/etc/spack/modules.yaml" module_file = release_base_dir / "spack-environments/spack_overlay/etc/spack/modules.yaml" with open(module_file,'r') as f: lines = f.read().replace('anaconda3%gcc@10.2.1','zlib@1.2.13') with open(module_file,'w') as f: f.write(lines) # Replace gcc@10.2.1 with gcc#13.1.1 or available system gcc for testing on laptop gcc_ver = subprocess.run(['gcc -dumpfullversion'],shell=True,capture_output=True).stdout.decode('utf-8').strip() setup_file = release_base_dir / "spack-environments/spack_setup.sh" with open(setup_file,'r') as f: lines = f.read().replace('system_compiler="gcc@10.2.1"',f'system_compiler="gcc@{gcc_ver}"') with open(setup_file,'w') as f: f.write(lines) # install global_generic toolchain install_result = mod.install_environment( mpsd_release="dev-23a", toolchains=["global_generic"], script_dir=script_dir, enable_build_cache=False ) # assert that log files exists assert os.path.exists(release_base_dir/'install.log') assert os.path.exists(release_base_dir/mpsd_microarch) assert os.path.exists(release_base_dir/mpsd_microarch/'lmod') # assert that lmod/module-index.yaml contains zlib with open(release_base_dir/mpsd_microarch/'lmod'/'module-index.yaml','r') as f: lines = f.read() assert 'zlib' in lines def test_interface(tmp_path): pass # ensure that installing without toolchains only passes the available toolchains # check that the script branch and hash are correct when running the script # check that the help message is printed when no arguments are provided # check that the help message is printed when -h is provided