|
9 | 9 | import os |
10 | 10 | from argparse import ArgumentParser |
11 | 11 |
|
| 12 | +import manager.manager_cmds.distribution as distribution |
| 13 | +import pytest |
| 14 | + |
12 | 15 | import spack |
13 | 16 | import spack.cmd.bootstrap as test_bootstrap_parse |
| 17 | +import spack.cmd.buildcache as test_buildcache_parse |
| 18 | +import spack.cmd.mirror as test_mirror_parse |
14 | 19 | import spack.environment |
15 | | -import spack.extensions.manager.manager_cmds.distribution as distribution |
| 20 | +import spack.spec |
16 | 21 | import spack.util.spack_yaml |
17 | 22 |
|
18 | 23 |
|
@@ -202,6 +207,152 @@ def test_get_valid_env_scopes(tmpdir): |
202 | 207 | assert len(scope_names) == 2 |
203 | 208 |
|
204 | 209 |
|
| 210 | +class MockArgs: |
| 211 | + def __init__(self, source=False, binary=False): |
| 212 | + self.source_only = source |
| 213 | + self.binary_only = binary |
| 214 | + |
| 215 | + |
| 216 | +class MockSpec: |
| 217 | + def __init__(self, name, status, dependencies=None): |
| 218 | + self.name = name |
| 219 | + self.status = status |
| 220 | + self._dependencies = dependencies or [] |
| 221 | + |
| 222 | + def install_status(self): |
| 223 | + return self.status |
| 224 | + |
| 225 | + def dependencies(self, *args, **kwargs): |
| 226 | + return self._dependencies |
| 227 | + |
| 228 | + |
| 229 | +class MockEnv: |
| 230 | + def __init__(self, specs): |
| 231 | + self.specs = [(x, f"{x}.concrete") for x in specs] |
| 232 | + |
| 233 | + def concretized_specs(self): |
| 234 | + return self.specs |
| 235 | + |
| 236 | + |
| 237 | +def test_is_installed_true(): |
| 238 | + """ |
| 239 | + This test verifies that `is_installed` returns False if a package reports its |
| 240 | + status as something other than missing or absent. |
| 241 | + """ |
| 242 | + spec = MockSpec("hdf5", "fake_valid_status") |
| 243 | + result = distribution.is_installed(spec) |
| 244 | + assert result |
| 245 | + |
| 246 | + |
| 247 | +def test_is_installed_missing(): |
| 248 | + """ |
| 249 | + This test verifies that `is_installed` returns False if a package reports |
| 250 | + its status as missing. |
| 251 | + """ |
| 252 | + spec = MockSpec("hdf5", spack.spec.InstallStatus.missing) |
| 253 | + result = distribution.is_installed(spec) |
| 254 | + assert not result |
| 255 | + |
| 256 | + |
| 257 | +def test_is_installed_absent(): |
| 258 | + """ |
| 259 | + This test verifies that `is_installed` returns False if a package reports |
| 260 | + its status as absent. |
| 261 | + """ |
| 262 | + spec = MockSpec("hdf5", spack.spec.InstallStatus.absent) |
| 263 | + result = distribution.is_installed(spec) |
| 264 | + assert not result |
| 265 | + |
| 266 | + |
| 267 | +def test_is_installed_missing_dependency(): |
| 268 | + """ |
| 269 | + This test verifies that `is_installed` returns False if a package is installed but its |
| 270 | + depenency is missing. |
| 271 | + """ |
| 272 | + deps = [ |
| 273 | + MockSpec("a", spack.spec.InstallStatus.installed), |
| 274 | + MockSpec("b", spack.spec.InstallStatus.missing), |
| 275 | + ] |
| 276 | + spec = MockSpec("hdf5", spack.spec.InstallStatus.installed, dependencies=deps) |
| 277 | + result = distribution.is_installed(spec) |
| 278 | + assert not result |
| 279 | + |
| 280 | + |
| 281 | +def test_correct_mirror_args_does_not_modify_args_when_source_only(monkeypatch): |
| 282 | + """ |
| 283 | + This test verifies that `correct_mirror_args` does nothing if source_only was requested. |
| 284 | + """ |
| 285 | + args = MockArgs(source=True) |
| 286 | + env = MockEnv(["hdf5"]) |
| 287 | + |
| 288 | + assert args.source_only |
| 289 | + assert not args.binary_only |
| 290 | + monkeypatch.setattr(distribution, "is_installed", lambda x: False) |
| 291 | + distribution.correct_mirror_args(env, args) |
| 292 | + assert args.source_only |
| 293 | + assert not args.binary_only |
| 294 | + |
| 295 | + |
| 296 | +def test_correct_mirror_args_sets_source_only_if_no_concretized_specs_in_env(): |
| 297 | + """ |
| 298 | + This test verifies that `correct_mirror_args` reverts to source_only if binaries aren't in env. |
| 299 | + """ |
| 300 | + args = MockArgs() |
| 301 | + env = MockEnv([]) |
| 302 | + assert not args.source_only |
| 303 | + assert not args.binary_only |
| 304 | + distribution.correct_mirror_args(env, args) |
| 305 | + assert args.source_only |
| 306 | + assert not args.binary_only |
| 307 | + |
| 308 | + |
| 309 | +def test_correct_mirror_args_sets_source_only_if_install_not_verified(monkeypatch): |
| 310 | + """ |
| 311 | + This test verifies that `correct_mirror_args` reverts to source_only if binaries aren't |
| 312 | + verified as correct. |
| 313 | + """ |
| 314 | + args = MockArgs() |
| 315 | + env = MockEnv(["hdf5.error"]) |
| 316 | + |
| 317 | + assert not args.source_only |
| 318 | + assert not args.binary_only |
| 319 | + monkeypatch.setattr(distribution, "is_installed", lambda x: False) |
| 320 | + distribution.correct_mirror_args(env, args) |
| 321 | + assert args.source_only |
| 322 | + assert not args.binary_only |
| 323 | + |
| 324 | + |
| 325 | +def test_correct_mirror_args_does_no_modification_if_install_verified(monkeypatch): |
| 326 | + """ |
| 327 | + This test verifies that `correct_mirror_args` does nothing if binaries exist. |
| 328 | + """ |
| 329 | + args = MockArgs() |
| 330 | + env = MockEnv(["hdf5.valid"]) |
| 331 | + |
| 332 | + assert not args.source_only |
| 333 | + assert not args.binary_only |
| 334 | + monkeypatch.setattr(distribution, "is_installed", lambda x: True) |
| 335 | + distribution.correct_mirror_args(env, args) |
| 336 | + assert not args.source_only |
| 337 | + assert not args.binary_only |
| 338 | + |
| 339 | + |
| 340 | +def test_correct_mirror_args_does_errors_if_binary_only_but_no_binaries_exist(monkeypatch): |
| 341 | + """ |
| 342 | + This test verifies that `correct_mirror_args` errors out if binary_only |
| 343 | + is True and source_only gets defaulted to True. |
| 344 | + """ |
| 345 | + args = MockArgs(binary=True) |
| 346 | + env = MockEnv(["hdf5.error"]) |
| 347 | + |
| 348 | + assert not args.source_only |
| 349 | + assert args.binary_only |
| 350 | + |
| 351 | + monkeypatch.setattr(distribution, "is_installed", lambda x: False) |
| 352 | + with pytest.raises(SystemExit): |
| 353 | + distribution.correct_mirror_args(env, args) |
| 354 | + |
| 355 | + |
205 | 356 | def test_DistributionPackager_init_distro_dir(tmpdir): |
206 | 357 | """ |
207 | 358 | This test verifies that `init_distro_dir` correctly creates a directory |
@@ -578,7 +729,7 @@ def mirror_for_specs(*args, **kwargs): |
578 | 729 | pkgr.configure_source_mirror() |
579 | 730 |
|
580 | 731 | content = get_manifest(pkgr.env) |
581 | | - expected = {"internal": "../mirror"} |
| 732 | + expected = {"internal-source": "../source-mirror"} |
582 | 733 | assert "mirrors" in content["spack"] |
583 | 734 | assert content["spack"]["mirrors"] == expected |
584 | 735 |
|
@@ -631,7 +782,7 @@ def mirror_for_specs(*args, **kwargs): |
631 | 782 |
|
632 | 783 | content = get_manifest(pkgr.env) |
633 | 784 | assert "mirrors" in content["spack"] |
634 | | - assert content["spack"]["mirrors"] == {"internal": "../mirror"} |
| 785 | + assert content["spack"]["mirrors"] == {"internal-source": "../source-mirror"} |
635 | 786 |
|
636 | 787 |
|
637 | 788 | def test_DistributionPackager_configure_bootstrap_mirror(tmpdir, monkeypatch): |
@@ -670,3 +821,44 @@ def __call__(self, *args, **kwargs): |
670 | 821 | with pkgr.env: |
671 | 822 | for call in MockCommand.call_args: |
672 | 823 | parser.parse_args(call) |
| 824 | + |
| 825 | + |
| 826 | +def test_DistributionPackager_configure_binary_mirror(tmpdir, monkeypatch): |
| 827 | + """ |
| 828 | + This test verifies that `configure_binary_mirror` does not construct a call to |
| 829 | + `spack buildcache` or `spack mirror` that violates its API. |
| 830 | + """ |
| 831 | + manifest = os.path.join(tmpdir.strpath, "base-env", "spack.yaml") |
| 832 | + create_spack_manifest(manifest) |
| 833 | + env = spack.environment.Environment(os.path.dirname(manifest)) |
| 834 | + root = os.path.join(tmpdir.strpath, "root") |
| 835 | + pkgr = distribution.DistributionPackager(env, root) |
| 836 | + |
| 837 | + class MockCommand: |
| 838 | + args = [] |
| 839 | + kwargs = {} |
| 840 | + call_args = [] |
| 841 | + |
| 842 | + def __init__(self, *args, **kwargs): |
| 843 | + self.args += list(args) |
| 844 | + self.kwargs.update(kwargs) |
| 845 | + |
| 846 | + def __call__(self, *args, **kwargs): |
| 847 | + self.call_args.append(list(args)) |
| 848 | + self.kwargs.update(kwargs) |
| 849 | + |
| 850 | + monkeypatch.setattr(distribution, "SpackCommand", MockCommand) |
| 851 | + pkgr.configure_binary_mirror() |
| 852 | + |
| 853 | + assert MockCommand.args == ["buildcache", "mirror"] |
| 854 | + assert MockCommand.kwargs == {} |
| 855 | + assert len(MockCommand.call_args) == 3 |
| 856 | + |
| 857 | + buildcache_parser = ArgumentParser() |
| 858 | + test_buildcache_parse.setup_parser(buildcache_parser) |
| 859 | + mirror_parser = ArgumentParser() |
| 860 | + test_mirror_parse.setup_parser(mirror_parser) |
| 861 | + with pkgr.env: |
| 862 | + buildcache_parser.parse_args(MockCommand.call_args[0]) |
| 863 | + buildcache_parser.parse_args(MockCommand.call_args[1]) |
| 864 | + mirror_parser.parse_args(MockCommand.call_args[2]) |
0 commit comments