From 2a4c06b1e690e0d6c54d87ef16e7ae309d15db03 Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Tue, 30 Mar 2021 13:23:39 +0200 Subject: Fix clearing cache of InternalConfigScope (#22609) Co-authored-by: Massimiliano Culpo --- lib/spack/spack/config.py | 4 ++ lib/spack/spack/test/cmd/common/arguments.py | 60 ++++++++++------------------ lib/spack/spack/test/config.py | 21 ++++++++++ 3 files changed, 47 insertions(+), 38 deletions(-) diff --git a/lib/spack/spack/config.py b/lib/spack/spack/config.py index 5978db6967..4f7e61ea69 100644 --- a/lib/spack/spack/config.py +++ b/lib/spack/spack/config.py @@ -362,6 +362,10 @@ class InternalConfigScope(ConfigScope): def __repr__(self): return '' % self.name + def clear(self): + # no cache to clear here. + pass + @staticmethod def _process_dict_keyname_overrides(data): """Turn a trailing `:' in a key name into an override attribute.""" diff --git a/lib/spack/spack/test/cmd/common/arguments.py b/lib/spack/spack/test/cmd/common/arguments.py index d3c3f81279..2a290d5d43 100644 --- a/lib/spack/spack/test/cmd/common/arguments.py +++ b/lib/spack/spack/test/cmd/common/arguments.py @@ -16,53 +16,37 @@ import spack.environment as ev @pytest.fixture() -def parser(): +def job_parser(): + # --jobs needs to write to a command_line config scope, so this is the only + # scope we create. p = argparse.ArgumentParser() arguments.add_common_arguments(p, ['jobs']) - yield p - # Cleanup the command line scope if it was set during tests - spack.config.config.clear_caches() - if 'command_line' in spack.config.config.scopes: - spack.config.config.scopes['command_line'].clear() + scopes = [spack.config.InternalConfigScope('command_line', {'config': {}})] + with spack.config.use_configuration(*scopes): + yield p -@pytest.fixture(params=[1, 2, 4, 8, 16, 32]) -def ncores(monkeypatch, request): - """Mocks having a machine with n cores for the purpose of - computing config:build_jobs. - """ - def _cpu_count(): - return request.param - - # Patch multiprocessing.cpu_count() to return the value we need - monkeypatch.setattr(multiprocessing, 'cpu_count', _cpu_count) - # Patch the configuration parts that have been cached already - monkeypatch.setitem(spack.config.config_defaults['config'], - 'build_jobs', min(16, request.param)) - monkeypatch.setitem( - spack.config.config.scopes, '_builtin', - spack.config.InternalConfigScope( - '_builtin', spack.config.config_defaults - )) - return request.param - - -@pytest.mark.parametrize('cli_args,requested', [ - (['-j', '24'], 24), - # Here we report the default if we have enough cores, as the cap - # on the available number of cores will be taken care of in the test - ([], 16) -]) -def test_setting_parallel_jobs(parser, cli_args, ncores, requested): - expected = min(requested, ncores) - namespace = parser.parse_args(cli_args) + +@pytest.mark.parametrize("ncores", [1, 2, 4, 8, 16, 32]) +def test_setting_jobs_flag(job_parser, ncores, monkeypatch): + monkeypatch.setattr(multiprocessing, 'cpu_count', lambda: ncores) + namespace = job_parser.parse_args(['-j', '24']) + expected = min(24, ncores) assert namespace.jobs == expected assert spack.config.get('config:build_jobs') == expected -def test_negative_integers_not_allowed_for_parallel_jobs(parser): +@pytest.mark.parametrize("ncores", [1, 2, 4, 8, 16, 32]) +def test_omitted_job_flag(job_parser, ncores, monkeypatch): + monkeypatch.setattr(multiprocessing, 'cpu_count', lambda: ncores) + namespace = job_parser.parse_args([]) + assert namespace.jobs == min(ncores, 16) + assert spack.config.get('config:build_jobs') is None + + +def test_negative_integers_not_allowed_for_parallel_jobs(job_parser): with pytest.raises(ValueError) as exc_info: - parser.parse_args(['-j', '-2']) + job_parser.parse_args(['-j', '-2']) assert 'expected a positive integer' in str(exc_info.value) diff --git a/lib/spack/spack/test/config.py b/lib/spack/spack/test/config.py index 6dd9dae848..d47851462a 100644 --- a/lib/spack/spack/test/config.py +++ b/lib/spack/spack/test/config.py @@ -1132,3 +1132,24 @@ def test_single_file_scope_cache_clearing(env_yaml): after = scope.get_section('config') assert after assert before == after + + +@pytest.mark.regression('22611') +def test_internal_config_scope_cache_clearing(): + """ + An InternalConfigScope object is constructed from data that is already + in memory, therefore it doesn't have any cache to clear. Here we ensure + that calling the clear method is consistent with that.. + """ + data = { + 'config': { + 'build_jobs': 10 + } + } + internal_scope = spack.config.InternalConfigScope('internal', data) + # Ensure that the initial object is properly set + assert internal_scope.sections['config'] == data + # Call the clear method + internal_scope.clear() + # Check that this didn't affect the scope object + assert internal_scope.sections['config'] == data -- cgit v1.2.3-60-g2f50