Skip to content
Snippets Groups Projects
Commit 5bee8f1f authored by Adrian Ciu's avatar Adrian Ciu Committed by adrianciu
Browse files

dedal: CLI; tests

parent 1d1d633b
No related branches found
No related tags found
1 merge request!7Dedal Release
Pipeline #59826 passed with stages
in 18 minutes and 17 seconds
import os
from dedal.model.SpackDescriptor import SpackDescriptor
from dedal.spack_factory.SpackOperationCreator import SpackOperationCreator
from dedal.configuration.SpackConfig import SpackConfig
class SpackManager:
"""
This class defines the logic used by the CLI
"""
def __init__(self, spack_config: SpackConfig = None, use_cache=False):
self._spack_config = spack_config
self._use_cache = use_cache
def _get_spack_operation(self):
return SpackOperationCreator.get_spack_operator(self._spack_config, self._use_cache)
def install_spack(self, version: str, bashrc_path=os.path.expanduser("~/.bashrc")):
self._get_spack_operation().install_spack(spack_version=f'v{version}', bashrc_path=bashrc_path)
def add_spack_repo(self, repo: SpackDescriptor):
"""
After additional repo was added, setup_spack_env must be invoked
"""
self._spack_config.add_repo(repo)
def setup_spack_env(self):
self._get_spack_operation().setup_spack_env()
def concretize_spack_env(self):
self._get_spack_operation().concretize_spack_env()
def install_packages(self, jobs: int):
self._get_spack_operation().install_packages(jobs=jobs)
import jsonpickle
import os
def save_config(spack_config_data, config_path: str):
"""Save config to JSON file."""
with open(config_path, "w") as data_file:
data_file.write(jsonpickle.encode(spack_config_data))
def load_config(config_path: str):
"""Load config from JSON file."""
if os.path.exists(config_path):
with open(config_path, "r") as data_file:
data = jsonpickle.decode(data_file.read())
return data
return {}
def clear_config(config_path: str):
"""Delete the JSON config file."""
if os.path.exists(config_path):
os.remove(config_path)
import os
from pathlib import Path
import click
import jsonpickle
from dedal.bll.SpackManager import SpackManager
from dedal.bll.cli_utils import save_config, load_config
from dedal.configuration.GpgConfig import GpgConfig
from dedal.configuration.SpackConfig import SpackConfig
from dedal.model.SpackDescriptor import SpackDescriptor
from dedal.utils.utils import resolve_path
SESSION_CONFIG_PATH = os.path.expanduser(f'~/tmp/dedal/dedal_session.json')
os.makedirs(os.path.dirname(SESSION_CONFIG_PATH), exist_ok=True)
@click.group()
@click.pass_context
def cli(ctx: click.Context):
config = load_config(SESSION_CONFIG_PATH)
if ctx.invoked_subcommand not in ['set-config', 'install-spack'] and not config:
click.echo('No configuration set. Use `set-config` first.')
ctx.exit(1)
if config:
config['env_path'] = resolve_path(config['env_path'])
env = SpackDescriptor(config['env_name'], config['env_path'], config['env_git_path'])
gpg = GpgConfig(config['gpg_name'], config['gpg_mail']) if config['gpg_name'] and config['gpg_mail'] else None
spack_config = SpackConfig(env=env, repos=None, install_dir=config['install_dir'],
upstream_instance=config['upstream_instance'],
concretization_dir=config['concretization_dir'],
buildcache_dir=config['buildcache_dir'],
system_name=config['system_name'], gpg=gpg,
use_spack_global=config['use_spack_global'])
ctx.obj = SpackManager(spack_config, use_cache=config['use_cache'])
@cli.command()
@click.option('--use_cache', is_flag=True, default=False, help='Enables cashing')
@click.option('--use_spack_global', is_flag=True, default=False, help='Uses spack installed globally on the os')
@click.option('--env_name', type=str, default=None, help='Environment name')
@click.option('--env_path', type=str, default=None, help='Environment path to download locally')
@click.option('--env_git_path', type=str, default=None, help='Git path to download the environment')
@click.option('--install_dir', type=str,
help='Install directory for installing spack; spack environments and repositories are stored here')
@click.option('--upstream_instance', type=str, default=None, help='Upstream instance for spack environment')
@click.option('--system_name', type=str, default=None, help='System name; it is used inside the spack environment')
@click.option('--concretization_dir', type=str, default=None,
help='Directory where the concretization caching (spack.lock) will be downloaded')
@click.option('--buildcache_dir', type=str, default=None,
help='Directory where the binary caching is downloaded for the spack packages')
@click.option('--gpg_name', type=str, default=None, help='Gpg name')
@click.option('--gpg_mail', type=str, default=None, help='Gpg mail contact address')
@click.option('--cache_version_concretize', type=str, default='v1', help='Cache version for concretizaion data')
@click.option('--cache_version_build', type=str, default='v1', help='Cache version for binary caches data')
def set_config(use_cache, env_name, env_path, env_git_path, install_dir, upstream_instance, system_name,
concretization_dir,
buildcache_dir, gpg_name, gpg_mail, use_spack_global, cache_version_concretize, cache_version_build):
"""Set configuration parameters for tahe session."""
spack_config_data = {
'use_cache': use_cache,
'env_name': env_name,
'env_path': env_path,
'env_git_path': env_git_path,
'install_dir': install_dir,
'upstream_instance': upstream_instance,
'system_name': system_name,
'concretization_dir': Path(concretization_dir) if concretization_dir else None,
'buildcache_dir': Path(buildcache_dir) if buildcache_dir else None,
'gpg_name': gpg_name,
'gpg_mail': gpg_mail,
'use_spack_global': use_spack_global,
'repos': [],
'cache_version_concretize': cache_version_concretize,
'cache_version_build': cache_version_build,
}
save_config(spack_config_data, SESSION_CONFIG_PATH)
click.echo('Configuration saved.')
@click.command()
def show_config():
"""Show the current configuration."""
config = load_config(SESSION_CONFIG_PATH)
if config:
click.echo(jsonpickle.encode(config, indent=2))
else:
click.echo('No configuration set. Use `set-config` first.')
@cli.command()
@click.option('--spack_version', type=str, default='0.23.0', help='Spack version')
@click.option('--bashrc_path', type=str, default="~/.bashrc", help='Path to .bashrc')
@click.pass_context
def install_spack(ctx: click.Context, spack_version: str, bashrc_path: str):
"""Install spack in the install_dir folder"""
bashrc_path = os.path.expanduser(bashrc_path)
if ctx.obj is None:
SpackManager().install_spack(spack_version, bashrc_path)
else:
ctx.obj.install_spack(spack_version, bashrc_path)
@cli.command()
@click.option('--repo_name', type=str, required=True, default=None, help='Repository name')
@click.option('--path', type=str, required=True, default=None, help='Repository path to download locally')
@click.option('--git_path', type=str, required=True, default=None, help='Git path to download the repository')
def add_spack_repo(repo_name: str, path: str, git_path: str = None):
"""Adds a spack repository to the spack environments. The setup command must be rerun."""
path = resolve_path(path)
repo = SpackDescriptor(repo_name, path, git_path)
config = load_config(SESSION_CONFIG_PATH)
config['repos'].append(repo)
save_config(config, SESSION_CONFIG_PATH)
click.echo('dedal setup_spack_env must be reran after each repo is added for the environment.')
@cli.command()
@click.pass_context
def setup_spack_env(ctx: click.Context):
"""Setups a spack environment according to the given configuration."""
ctx.obj.setup_spack_env()
@cli.command()
@click.pass_context
def concretize(ctx: click.Context):
"""Spack concretization step"""
ctx.obj.concretize_spack_env()
@cli.command()
@click.option('--jobs', type=int, default=2, help='Number of parallel jobs for spack installation')
@click.pass_context
def install_packages(ctx: click.Context, jobs):
"""Installs spack packages present in the spack environment defined in configuration"""
ctx.obj.install_packages(jobs=jobs)
@click.command()
def clear_config():
"""Clear stored configuration"""
if os.path.exists(SESSION_CONFIG_PATH):
os.remove(SESSION_CONFIG_PATH)
click.echo('Configuration cleared!')
else:
click.echo('No configuration to clear.')
cli.add_command(show_config)
cli.add_command(clear_config)
if __name__ == '__main__':
cli()
...@@ -7,7 +7,7 @@ class SpackDescriptor: ...@@ -7,7 +7,7 @@ class SpackDescriptor:
Provides details about the spack environment Provides details about the spack environment
""" """
def __init__(self, env_name: str, path: Path = Path(os.getcwd()).resolve(), git_path: str = None): def __init__(self, name: str, path: Path = Path(os.getcwd()).resolve(), git_path: str = None):
self.env_name = env_name self.name = name
self.path = path if isinstance(path,Path) else Path(path) self.path = path.resolve() if isinstance(path, Path) else Path(path).resolve()
self.git_path = git_path self.git_path = git_path
...@@ -39,24 +39,27 @@ class SpackOperation: ...@@ -39,24 +39,27 @@ class SpackOperation:
self.spack_config.buildcache_dir = spack_config.buildcache_dir self.spack_config.buildcache_dir = spack_config.buildcache_dir
if self.spack_config.buildcache_dir: if self.spack_config.buildcache_dir:
os.makedirs(self.spack_config.buildcache_dir, exist_ok=True) os.makedirs(self.spack_config.buildcache_dir, exist_ok=True)
if self.spack_config.env and spack_config.env.name:
self.env_path: Path = spack_config.env.path / spack_config.env.name
self.spack_command_on_env = f'{self.spack_setup_script} spack env activate -p {self.env_path}'
else:
self.spack_command_on_env = self.spack_setup_script
if self.spack_config.env and spack_config.env.path: if self.spack_config.env and spack_config.env.path:
self.spack_config.env.path = spack_config.env.path self.spack_config.env.path = spack_config.env.path
self.spack_config.env.path.mkdir(parents=True, exist_ok=True) self.spack_config.env.path.mkdir(parents=True, exist_ok=True)
self.env_path: Path = spack_config.env.path / spack_config.env.env_name
self.spack_command_on_env = f'{self.spack_setup_script} spack env activate -p {self.env_path}'
def create_fetch_spack_environment(self): def create_fetch_spack_environment(self):
if self.spack_config.env.git_path: if self.spack_config.env.git_path:
git_clone_repo(self.spack_config.env.env_name, self.spack_config.env.path / self.spack_config.env.env_name, git_clone_repo(self.spack_config.env.name, self.spack_config.env.path / self.spack_config.env.name,
self.spack_config.env.git_path, self.spack_config.env.git_path,
logger=self.logger) logger=self.logger)
else: else:
os.makedirs(self.spack_config.env.path / self.spack_config.env.env_name, exist_ok=True) os.makedirs(self.spack_config.env.path / self.spack_config.env.name, exist_ok=True)
run_command("bash", "-c", run_command("bash", "-c",
f'{self.spack_setup_script} spack env create -d {self.env_path}', f'{self.spack_setup_script} spack env create -d {self.env_path}',
check=True, logger=self.logger, check=True, logger=self.logger,
info_msg=f"Created {self.spack_config.env.env_name} spack environment", info_msg=f"Created {self.spack_config.env.name} spack environment",
exception_msg=f"Failed to create {self.spack_config.env.env_name} spack environment", exception_msg=f"Failed to create {self.spack_config.env.name} spack environment",
exception=BashCommandException) exception=BashCommandException)
def setup_spack_env(self): def setup_spack_env(self):
...@@ -79,13 +82,13 @@ class SpackOperation: ...@@ -79,13 +82,13 @@ class SpackOperation:
self.create_fetch_spack_environment() self.create_fetch_spack_environment()
if self.spack_config.install_dir.exists(): if self.spack_config.install_dir.exists():
for repo in self.spack_config.repos: for repo in self.spack_config.repos:
repo_dir = self.spack_config.install_dir / repo.path / repo.env_name repo_dir = self.spack_config.install_dir / repo.path / repo.name
git_clone_repo(repo.env_name, repo_dir, repo.git_path, logger=self.logger) git_clone_repo(repo.name, repo_dir, repo.git_path, logger=self.logger)
if not self.spack_repo_exists(repo.env_name): if not self.spack_repo_exists(repo.name):
self.add_spack_repo(repo.path, repo.env_name) self.add_spack_repo(repo.path, repo.name)
self.logger.debug(f'Added spack repository {repo.env_name}') self.logger.debug(f'Added spack repository {repo.name}')
else: else:
self.logger.debug(f'Spack repository {repo.env_name} already added') self.logger.debug(f'Spack repository {repo.name} already added')
def spack_repo_exists(self, repo_name: str) -> bool | None: def spack_repo_exists(self, repo_name: str) -> bool | None:
"""Check if the given Spack repository exists.""" """Check if the given Spack repository exists."""
...@@ -116,7 +119,7 @@ class SpackOperation: ...@@ -116,7 +119,7 @@ class SpackOperation:
self.spack_command_on_env, self.spack_command_on_env,
check=True, check=True,
capture_output=True, text=True, logger=self.logger, capture_output=True, text=True, logger=self.logger,
info_msg=f'Checking if environment {self.spack_config.env.env_name} exists') info_msg=f'Checking if environment {self.spack_config.env.name} exists')
if result is None: if result is None:
return False return False
return True return True
...@@ -127,8 +130,8 @@ class SpackOperation: ...@@ -127,8 +130,8 @@ class SpackOperation:
run_command("bash", "-c", run_command("bash", "-c",
f'{self.spack_command_on_env} && spack repo add {repo_path}/{repo_name}', f'{self.spack_command_on_env} && spack repo add {repo_path}/{repo_name}',
check=True, logger=self.logger, check=True, logger=self.logger,
info_msg=f"Added {repo_name} to spack environment {self.spack_config.env.env_name}", info_msg=f"Added {repo_name} to spack environment {self.spack_config.env.name}",
exception_msg=f"Failed to add {repo_name} to spack environment {self.spack_config.env.env_name}", exception_msg=f"Failed to add {repo_name} to spack environment {self.spack_config.env.name}",
exception=SpackRepoException) exception=SpackRepoException)
@check_spack_env @check_spack_env
...@@ -137,18 +140,18 @@ class SpackOperation: ...@@ -137,18 +140,18 @@ class SpackOperation:
f'{self.spack_command_on_env} && spack compiler list', f'{self.spack_command_on_env} && spack compiler list',
check=True, logger=self.logger, check=True, logger=self.logger,
capture_output=True, text=True, capture_output=True, text=True,
info_msg=f"Checking spack environment compiler version for {self.spack_config.env.env_name}", info_msg=f"Checking spack environment compiler version for {self.spack_config.env.name}",
exception_msg=f"Failed to checking spack environment compiler version for {self.spack_config.env.env_name}", exception_msg=f"Failed to checking spack environment compiler version for {self.spack_config.env.name}",
exception=BashCommandException) exception=BashCommandException)
# todo add error handling and tests # todo add error handling and tests
if result.stdout is None: if result.stdout is None:
self.logger.debug('No gcc found for {self.env.env_name}') self.logger.debug(f'No gcc found for {self.spack_config.env.name}')
return None return None
# Find the first occurrence of a GCC compiler using regex # Find the first occurrence of a GCC compiler using regex
match = re.search(r"gcc@([\d\.]+)", result.stdout) match = re.search(r"gcc@([\d\.]+)", result.stdout)
gcc_version = match.group(1) gcc_version = match.group(1)
self.logger.debug(f'Found gcc for {self.spack_config.env.env_name}: {gcc_version}') self.logger.debug(f'Found gcc for {self.spack_config.env.name}: {gcc_version}')
return gcc_version return gcc_version
def get_spack_installed_version(self): def get_spack_installed_version(self):
...@@ -168,8 +171,8 @@ class SpackOperation: ...@@ -168,8 +171,8 @@ class SpackOperation:
f'{self.spack_command_on_env} && spack concretize {force}', f'{self.spack_command_on_env} && spack concretize {force}',
check=True, check=True,
logger=self.logger, logger=self.logger,
info_msg=f'Concertization step for {self.spack_config.env.env_name}', info_msg=f'Concertization step for {self.spack_config.env.name}',
exception_msg=f'Failed the concertization step for {self.spack_config.env.env_name}', exception_msg=f'Failed the concertization step for {self.spack_config.env.name}',
exception=SpackConcertizeException) exception=SpackConcertizeException)
def create_gpg_keys(self): def create_gpg_keys(self):
...@@ -178,8 +181,8 @@ class SpackOperation: ...@@ -178,8 +181,8 @@ class SpackOperation:
f'{self.spack_setup_script} spack gpg init && spack gpg create {self.spack_config.gpg.name} {self.spack_config.gpg.mail}', f'{self.spack_setup_script} spack gpg init && spack gpg create {self.spack_config.gpg.name} {self.spack_config.gpg.mail}',
check=True, check=True,
logger=self.logger, logger=self.logger,
info_msg=f'Created pgp keys for {self.spack_config.env.env_name}', info_msg=f'Created pgp keys for {self.spack_config.env.name}',
exception_msg=f'Failed to create pgp keys mirror {self.spack_config.env.env_name}', exception_msg=f'Failed to create pgp keys mirror {self.spack_config.env.name}',
exception=SpackGpgException) exception=SpackGpgException)
else: else:
raise SpackGpgException('No GPG configuration was defined is spack configuration') raise SpackGpgException('No GPG configuration was defined is spack configuration')
...@@ -225,8 +228,8 @@ class SpackOperation: ...@@ -225,8 +228,8 @@ class SpackOperation:
stderr=subprocess.PIPE, stderr=subprocess.PIPE,
text=True, text=True,
logger=self.logger, logger=self.logger,
info_msg=f"Installing spack packages for {self.spack_config.env.env_name}", info_msg=f"Installing spack packages for {self.spack_config.env.name}",
exception_msg=f"Error installing spack packages for {self.spack_config.env.env_name}", exception_msg=f"Error installing spack packages for {self.spack_config.env.name}",
exception=SpackInstallPackagesException) exception=SpackInstallPackagesException)
log_command(install_result, str(Path(os.getcwd()).resolve() / ".generate_cache.log")) log_command(install_result, str(Path(os.getcwd()).resolve() / ".generate_cache.log"))
return install_result return install_result
......
...@@ -16,7 +16,7 @@ def test_spack_repo_exists_1(tmp_path): ...@@ -16,7 +16,7 @@ def test_spack_repo_exists_1(tmp_path):
spack_operation = SpackOperationCreator.get_spack_operator(config) spack_operation = SpackOperationCreator.get_spack_operator(config)
spack_operation.install_spack() spack_operation.install_spack()
with pytest.raises(NoSpackEnvironmentException): with pytest.raises(NoSpackEnvironmentException):
spack_operation.spack_repo_exists(env.env_name) spack_operation.spack_repo_exists(env.name)
def test_spack_repo_exists_2(tmp_path): def test_spack_repo_exists_2(tmp_path):
...@@ -27,7 +27,7 @@ def test_spack_repo_exists_2(tmp_path): ...@@ -27,7 +27,7 @@ def test_spack_repo_exists_2(tmp_path):
assert isinstance(spack_operation, SpackOperation) assert isinstance(spack_operation, SpackOperation)
spack_operation.install_spack() spack_operation.install_spack()
spack_operation.setup_spack_env() spack_operation.setup_spack_env()
assert spack_operation.spack_repo_exists(env.env_name) == False assert spack_operation.spack_repo_exists(env.name) == False
def test_spack_from_scratch_setup_1(tmp_path): def test_spack_from_scratch_setup_1(tmp_path):
...@@ -38,7 +38,7 @@ def test_spack_from_scratch_setup_1(tmp_path): ...@@ -38,7 +38,7 @@ def test_spack_from_scratch_setup_1(tmp_path):
assert isinstance(spack_operation, SpackOperation) assert isinstance(spack_operation, SpackOperation)
spack_operation.install_spack() spack_operation.install_spack()
spack_operation.setup_spack_env() spack_operation.setup_spack_env()
assert spack_operation.spack_repo_exists(env.env_name) == False assert spack_operation.spack_repo_exists(env.name) == False
def test_spack_from_scratch_setup_2(tmp_path): def test_spack_from_scratch_setup_2(tmp_path):
...@@ -52,7 +52,7 @@ def test_spack_from_scratch_setup_2(tmp_path): ...@@ -52,7 +52,7 @@ def test_spack_from_scratch_setup_2(tmp_path):
assert isinstance(spack_operation, SpackOperation) assert isinstance(spack_operation, SpackOperation)
spack_operation.install_spack() spack_operation.install_spack()
spack_operation.setup_spack_env() spack_operation.setup_spack_env()
assert spack_operation.spack_repo_exists(env.env_name) == True assert spack_operation.spack_repo_exists(env.name) == True
def test_spack_from_scratch_setup_3(tmp_path): def test_spack_from_scratch_setup_3(tmp_path):
...@@ -88,7 +88,7 @@ def test_spack_not_a_valid_repo(): ...@@ -88,7 +88,7 @@ def test_spack_not_a_valid_repo():
spack_operation = SpackOperationCreator.get_spack_operator(config) spack_operation = SpackOperationCreator.get_spack_operator(config)
assert isinstance(spack_operation, SpackOperation) assert isinstance(spack_operation, SpackOperation)
with pytest.raises(BashCommandException): with pytest.raises(BashCommandException):
spack_operation.add_spack_repo(repo.path, repo.env_name) spack_operation.add_spack_repo(repo.path, repo.name)
@pytest.mark.skip( @pytest.mark.skip(
......
from dedal.spack_factory.SpackOperationCreateCache import SpackOperationCreateCache
from dedal.configuration.SpackConfig import SpackConfig
from dedal.model.SpackDescriptor import SpackDescriptor
from dedal.spack_factory.SpackOperation import SpackOperation
from dedal.spack_factory.SpackOperationCreator import SpackOperationCreator
from dedal.spack_factory.SpackOperationUseCache import SpackOperationUseCache
from dedal.tests.testing_variables import ebrains_spack_builds_git, test_spack_env_git
def test_spack_creator_scratch_1(tmp_path):
install_dir = tmp_path
env = SpackDescriptor('test-spack-env', install_dir, test_spack_env_git)
repo = SpackDescriptor('ebrains-spack-builds', install_dir, ebrains_spack_builds_git)
spack_config = SpackConfig(env, install_dir=install_dir)
spack_config.add_repo(repo)
spack_operation = SpackOperationCreator.get_spack_operator(spack_config)
assert isinstance(spack_operation, SpackOperation)
def test_spack_creator_scratch_2(tmp_path):
spack_config = None
spack_operation = SpackOperationCreator.get_spack_operator(spack_config)
assert isinstance(spack_operation, SpackOperation)
def test_spack_creator_scratch_3():
spack_config = SpackConfig()
spack_operation = SpackOperationCreator.get_spack_operator(spack_config)
assert isinstance(spack_operation, SpackOperation)
def test_spack_creator_create_cache(tmp_path):
install_dir = tmp_path
env = SpackDescriptor('test-spack-env', install_dir, test_spack_env_git)
repo = SpackDescriptor('ebrains-spack-builds', install_dir, ebrains_spack_builds_git)
spack_config = SpackConfig(env, install_dir=install_dir, concretization_dir=install_dir, buildcache_dir=install_dir)
spack_config.add_repo(repo)
spack_operation = SpackOperationCreator.get_spack_operator(spack_config)
assert isinstance(spack_operation, SpackOperationCreateCache)
def test_spack_creator_use_cache(tmp_path):
install_dir = tmp_path
env = SpackDescriptor('test-spack-env', install_dir, test_spack_env_git)
repo = SpackDescriptor('ebrains-spack-builds', install_dir, ebrains_spack_builds_git)
spack_config = SpackConfig(env, install_dir=install_dir, concretization_dir=install_dir, buildcache_dir=install_dir)
spack_config.add_repo(repo)
spack_operation = SpackOperationCreator.get_spack_operator(spack_config, use_cache=True)
assert isinstance(spack_operation, SpackOperationUseCache)
import os
import pytest
from unittest.mock import patch, MagicMock
from click.testing import CliRunner
from dedal.cli.spack_manager_api import show_config, clear_config, install_spack, add_spack_repo, install_packages, \
setup_spack_env, concretize, set_config
from dedal.model.SpackDescriptor import SpackDescriptor
@pytest.fixture
def runner():
return CliRunner()
@pytest.fixture
def mocked_session_path():
return '/mocked/tmp/session.json'
@pytest.fixture
def mock_spack_manager():
mock_spack_manager = MagicMock()
mock_spack_manager.install_spack = MagicMock()
mock_spack_manager.add_spack_repo = MagicMock()
mock_spack_manager.setup_spack_env = MagicMock()
mock_spack_manager.concretize_spack_env = MagicMock()
mock_spack_manager.install_packages = MagicMock()
return mock_spack_manager
@pytest.fixture
def mock_load_config():
with patch('dedal.cli.spack_manager_api.load_config') as mock_load:
yield mock_load
@pytest.fixture
def mock_save_config():
with patch('dedal.cli.spack_manager_api.save_config') as mock_save:
yield mock_save
@pytest.fixture
def mock_clear_config():
with patch('dedal.cli.spack_manager_api.clear_config') as mock_clear:
yield mock_clear
def test_show_config_no_config(runner, mock_load_config):
mock_load_config.return_value = None
result = runner.invoke(show_config)
assert 'No configuration set. Use `set-config` first.' in result.output
def test_show_config_with_config(runner, mock_load_config):
"""Test the show_config command when config is present."""
mock_load_config.return_value = {"key": "value"}
result = runner.invoke(show_config)
assert result.exit_code == 0
assert '"key": "value"' in result.output
def test_clear_config(runner, mock_clear_config):
"""Test the clear_config command."""
with patch('os.path.exists', return_value=True), patch('os.remove') as mock_remove:
result = runner.invoke(clear_config)
assert 'Configuration cleared!' in result.output
mock_remove.assert_called_once()
def test_install_spack_no_context_1(runner, mock_spack_manager):
"""Test install_spack with no context, using SpackManager."""
with patch('dedal.cli.spack_manager_api.SpackManager', return_value=mock_spack_manager):
result = runner.invoke(install_spack, ['--spack_version', '0.24.0'])
mock_spack_manager.install_spack.assert_called_once_with('0.24.0', os.path.expanduser("~/.bashrc"))
assert result.exit_code == 0
def test_install_spack_no_context_2(runner, mock_spack_manager):
"""Test install_spack with no context, using SpackManager and the default value for spack_version."""
with patch('dedal.cli.spack_manager_api.SpackManager', return_value=mock_spack_manager):
result = runner.invoke(install_spack)
mock_spack_manager.install_spack.assert_called_once_with('0.23.0', os.path.expanduser("~/.bashrc"))
assert result.exit_code == 0
def test_install_spack_with_mocked_context_1(runner, mock_spack_manager):
"""Test install_spack with a mocked context, using ctx.obj as SpackManager."""
result = runner.invoke(install_spack, ['--spack_version', '0.24.0', '--bashrc_path', '/home/.bahsrc'], obj=mock_spack_manager)
mock_spack_manager.install_spack.assert_called_once_with('0.24.0', '/home/.bahsrc')
assert result.exit_code == 0
def test_install_spack_with_mocked_context_2(runner, mock_spack_manager):
"""Test install_spack with a mocked context, using ctx.obj as SpackManager and the default value for spack_version."""
result = runner.invoke(install_spack, obj=mock_spack_manager)
mock_spack_manager.install_spack.assert_called_once_with('0.23.0', os.path.expanduser("~/.bashrc"))
assert result.exit_code == 0
def test_setup_spack_env(runner, mock_spack_manager):
"""Test setup_spack_env with a mocked context, using ctx.obj as SpackManager."""
result = runner.invoke(setup_spack_env, obj=mock_spack_manager)
mock_spack_manager.setup_spack_env.assert_called_once_with()
assert result.exit_code == 0
def test_concretize(runner, mock_spack_manager):
"""Test install_spack with a mocked context, using ctx.obj as SpackManager."""
result = runner.invoke(concretize, obj=mock_spack_manager)
mock_spack_manager.concretize_spack_env.assert_called_once_with()
assert result.exit_code == 0
def test_install_packages_1(runner, mock_spack_manager):
"""Test install_packages with a mocked context, using ctx.obj as SpackManager."""
result = runner.invoke(install_packages, obj=mock_spack_manager)
mock_spack_manager.install_packages.assert_called_once_with(jobs=2)
assert result.exit_code == 0
def test_install_packages(runner, mock_spack_manager):
"""Test install_packages with a mocked context, using ctx.obj as SpackManager."""
result = runner.invoke(install_packages, ['--jobs', 3], obj=mock_spack_manager)
mock_spack_manager.install_packages.assert_called_once_with(jobs=3)
assert result.exit_code == 0
@patch('dedal.cli.spack_manager_api.resolve_path')
@patch('dedal.cli.spack_manager_api.SpackDescriptor')
def test_add_spack_repo(mock_spack_descriptor, mock_resolve_path, mock_load_config, mock_save_config,
mocked_session_path, runner):
"""Test adding a spack repository with mocks."""
expected_config = {'repos': [SpackDescriptor(name='test-repo')]}
repo_name = 'test-repo'
path = '/path'
git_path = 'https://example.com/repo.git'
mock_resolve_path.return_value = '/resolved/path'
mock_load_config.return_value = expected_config
mock_repo_instance = MagicMock()
mock_spack_descriptor.return_value = mock_repo_instance
with patch('dedal.cli.spack_manager_api.SESSION_CONFIG_PATH', mocked_session_path):
result = runner.invoke(add_spack_repo, ['--repo_name', repo_name, '--path', path, '--git_path', git_path])
assert result.exit_code == 0
assert 'dedal setup_spack_env must be reran after each repo is added' in result.output
mock_resolve_path.assert_called_once_with(path)
mock_spack_descriptor.assert_called_once_with(repo_name, '/resolved/path', git_path)
assert mock_repo_instance in expected_config['repos']
mock_save_config.assert_called_once_with(expected_config, mocked_session_path)
def test_set_config(runner, mock_save_config, mocked_session_path):
"""Test set_config."""
with patch('dedal.cli.spack_manager_api.SESSION_CONFIG_PATH', mocked_session_path):
result = runner.invoke(set_config, ['--env_name', 'test', '--system_name', 'sys'])
expected_config = {
'use_cache': False,
'env_name': 'test',
'env_path': None,
'env_git_path': None,
'install_dir': None,
'upstream_instance': None,
'system_name': 'sys',
'concretization_dir': None,
'buildcache_dir': None,
'gpg_name': None,
'gpg_mail': None,
'use_spack_global': False,
'repos': [],
'cache_version_concretize': 'v1',
'cache_version_build': 'v1',
}
mock_save_config.assert_called_once()
saved_config, saved_path = mock_save_config.call_args[0]
assert saved_path == mocked_session_path
assert saved_config == expected_config
assert result.exit_code == 0
assert 'Configuration saved.' in result.output
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment