summaryrefslogtreecommitdiff
path: root/lib/spack/spack/test/cmd/common/arguments.py
blob: c1f75e99f3bdbd79d5c1d02d068fc144e76df565 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

import argparse

import pytest

import spack.cmd
import spack.cmd.common.arguments as arguments
import spack.config
import spack.environment as ev
import spack.main


@pytest.fixture()
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"])
    scopes = [spack.config.InternalConfigScope("command_line", {"config": {}})]

    with spack.config.use_configuration(*scopes):
        yield p


def test_setting_jobs_flag(job_parser):
    namespace = job_parser.parse_args(["-j", "24"])
    assert namespace.jobs == 24
    assert spack.config.get("config:build_jobs", scope="command_line") == 24


def test_omitted_job_flag(job_parser):
    namespace = job_parser.parse_args([])
    assert namespace.jobs is None
    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:
        job_parser.parse_args(["-j", "-2"])

    assert "expected a positive integer" in str(exc_info.value)


@pytest.mark.parametrize(
    "specs,cflags,propagation,negated_variants",
    [
        (['coreutils cflags="-O3 -g"'], ["-O3", "-g"], [False, False], []),
        (['coreutils cflags=="-O3 -g"'], ["-O3", "-g"], [True, True], []),
        (["coreutils", "cflags=-O3 -g"], ["-O3", "-g"], [False, False], []),
        (["coreutils", "cflags==-O3 -g"], ["-O3", "-g"], [True, True], []),
        (["coreutils", "cflags=-O3", "-g"], ["-O3"], [False], ["g"]),
    ],
)
@pytest.mark.regression("12951")
def test_parse_spec_flags_with_spaces(specs, cflags, propagation, negated_variants):
    spec_list = spack.cmd.parse_specs(specs)
    assert len(spec_list) == 1

    s = spec_list.pop()

    compiler_flags = [flag for flag in s.compiler_flags["cflags"]]
    flag_propagation = [flag.propagate for flag in s.compiler_flags["cflags"]]

    assert compiler_flags == cflags
    assert flag_propagation == propagation
    assert list(s.variants.keys()) == negated_variants
    for v in negated_variants:
        assert "~{0}".format(v) in s


@pytest.mark.usefixtures("config")
def test_match_spec_env(mock_packages, mutable_mock_env_path):
    """
    Concretize a spec with non-default options in an environment. Make
    sure that when we ask for a matching spec when the environment is
    active that we get the instance concretized in the environment.
    """
    # Initial sanity check: we are planning on choosing a non-default
    # value, so make sure that is in fact not the default.
    check_defaults = spack.cmd.parse_specs(["a"], concretize=True)[0]
    assert not check_defaults.satisfies("foobar=baz")

    e = ev.create("test")
    e.add("a foobar=baz")
    e.concretize()
    with e:
        env_spec = spack.cmd.matching_spec_from_env(spack.cmd.parse_specs(["a"])[0])
        assert env_spec.satisfies("foobar=baz")
        assert env_spec.concrete


@pytest.mark.usefixtures("config")
def test_multiple_env_match_raises_error(mock_packages, mutable_mock_env_path):
    e = ev.create("test")
    e.add("a foobar=baz")
    e.add("a foobar=fee")
    e.concretize()
    with e:
        with pytest.raises(ev.SpackEnvironmentError) as exc_info:
            spack.cmd.matching_spec_from_env(spack.cmd.parse_specs(["a"])[0])

    assert "matches multiple specs" in exc_info.value.message


@pytest.mark.usefixtures("config")
def test_root_and_dep_match_returns_root(mock_packages, mutable_mock_env_path):
    e = ev.create("test")
    e.add("b@0.9")
    e.add("a foobar=bar")  # Depends on b, should choose b@1.0
    e.concretize()
    with e:
        # This query matches the root b and b as a dependency of a. In that
        # case the root instance should be preferred.
        env_spec1 = spack.cmd.matching_spec_from_env(spack.cmd.parse_specs(["b"])[0])
        assert env_spec1.satisfies("@0.9")

        env_spec2 = spack.cmd.matching_spec_from_env(spack.cmd.parse_specs(["b@1.0"])[0])
        assert env_spec2


@pytest.mark.parametrize(
    "arg,config", [("--reuse", True), ("--fresh", False), ("--reuse-deps", "dependencies")]
)
def test_concretizer_arguments(mutable_config, mock_packages, arg, config):
    """Ensure that ConfigSetAction is doing the right thing."""
    spec = spack.main.SpackCommand("spec")

    assert spack.config.get("concretizer:reuse", None) is None

    spec(arg, "zlib")

    assert spack.config.get("concretizer:reuse", None) == config


def test_use_buildcache_type():
    assert arguments.use_buildcache("only") == ("only", "only")
    assert arguments.use_buildcache("never") == ("never", "never")
    assert arguments.use_buildcache("auto") == ("auto", "auto")
    assert arguments.use_buildcache("package:never,dependencies:only") == ("never", "only")
    assert arguments.use_buildcache("only,package:never") == ("never", "only")
    assert arguments.use_buildcache("package:only,package:never") == ("never", "auto")
    assert arguments.use_buildcache("auto , package: only") == ("only", "auto")

    with pytest.raises(argparse.ArgumentTypeError):
        assert arguments.use_buildcache("pkg:only,deps:never")

    with pytest.raises(argparse.ArgumentTypeError):
        assert arguments.use_buildcache("sometimes")