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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
|
# Copyright 2013-2022 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 pytest
import llnl.util.tty as tty
import spack.store
from spack.main import SpackCommand, SpackCommandError
uninstall = SpackCommand('uninstall')
install = SpackCommand('install')
# pytestmark = pytest.mark.skipif(sys.platform == "win32",
# reason="does not run on windows")
class MockArgs(object):
def __init__(self, packages, all=False, force=False, dependents=False):
self.packages = packages
self.all = all
self.force = force
self.dependents = dependents
self.yes_to_all = True
@pytest.mark.db
def test_multiple_matches(mutable_database):
"""Test unable to uninstall when multiple matches."""
with pytest.raises(SpackCommandError):
uninstall('-y', 'mpileaks')
@pytest.mark.db
def test_installed_dependents(mutable_database):
"""Test can't uninstall when there are installed dependents."""
with pytest.raises(SpackCommandError):
uninstall('-y', 'libelf')
@pytest.mark.db
def test_recursive_uninstall(mutable_database):
"""Test recursive uninstall."""
uninstall('-y', '-a', '--dependents', 'callpath')
all_specs = spack.store.layout.all_specs()
assert len(all_specs) == 9
# query specs with multiple configurations
mpileaks_specs = [s for s in all_specs if s.satisfies('mpileaks')]
callpath_specs = [s for s in all_specs if s.satisfies('callpath')]
mpi_specs = [s for s in all_specs if s.satisfies('mpi')]
assert len(mpileaks_specs) == 0
assert len(callpath_specs) == 0
assert len(mpi_specs) == 3
@pytest.mark.db
@pytest.mark.regression('3690')
@pytest.mark.parametrize('constraint,expected_number_of_specs', [
('dyninst', 8), ('libelf', 6)
])
def test_uninstall_spec_with_multiple_roots(
constraint, expected_number_of_specs, mutable_database
):
uninstall('-y', '-a', '--dependents', constraint)
all_specs = spack.store.layout.all_specs()
assert len(all_specs) == expected_number_of_specs
@pytest.mark.db
@pytest.mark.parametrize('constraint,expected_number_of_specs', [
('dyninst', 14), ('libelf', 14)
])
def test_force_uninstall_spec_with_ref_count_not_zero(
constraint, expected_number_of_specs, mutable_database
):
uninstall('-f', '-y', constraint)
all_specs = spack.store.layout.all_specs()
assert len(all_specs) == expected_number_of_specs
@pytest.mark.db
def test_force_uninstall_and_reinstall_by_hash(mutable_database):
"""Test forced uninstall and reinstall of old specs."""
# this is the spec to be removed
callpath_spec = spack.store.db.query_one('callpath ^mpich')
dag_hash = callpath_spec.dag_hash()
# ensure can look up by hash and that it's a dependent of mpileaks
def validate_callpath_spec(installed):
assert installed is True or installed is False
specs = spack.store.db.get_by_hash(dag_hash, installed=installed)
assert len(specs) == 1 and specs[0] == callpath_spec
specs = spack.store.db.get_by_hash(dag_hash[:7], installed=installed)
assert len(specs) == 1 and specs[0] == callpath_spec
specs = spack.store.db.get_by_hash(dag_hash, installed=any)
assert len(specs) == 1 and specs[0] == callpath_spec
specs = spack.store.db.get_by_hash(dag_hash[:7], installed=any)
assert len(specs) == 1 and specs[0] == callpath_spec
specs = spack.store.db.get_by_hash(dag_hash, installed=not installed)
assert specs is None
specs = spack.store.db.get_by_hash(dag_hash[:7],
installed=not installed)
assert specs is None
mpileaks_spec = spack.store.db.query_one('mpileaks ^mpich')
assert callpath_spec in mpileaks_spec
spec = spack.store.db.query_one('callpath ^mpich', installed=installed)
assert spec == callpath_spec
spec = spack.store.db.query_one('callpath ^mpich', installed=any)
assert spec == callpath_spec
spec = spack.store.db.query_one('callpath ^mpich',
installed=not installed)
assert spec is None
validate_callpath_spec(True)
uninstall('-y', '-f', 'callpath ^mpich')
# ensure that you can still look up by hash and see deps, EVEN though
# the callpath spec is missing.
validate_callpath_spec(False)
# BUT, make sure that the removed callpath spec is not in queries
def db_specs():
all_specs = spack.store.layout.all_specs()
return (
all_specs,
[s for s in all_specs if s.satisfies('mpileaks')],
[s for s in all_specs if s.satisfies('callpath')],
[s for s in all_specs if s.satisfies('mpi')]
)
all_specs, mpileaks_specs, callpath_specs, mpi_specs = db_specs()
total_specs = len(all_specs)
assert total_specs == 14
assert len(mpileaks_specs) == 3
assert len(callpath_specs) == 2
assert len(mpi_specs) == 3
# Now, REINSTALL the spec and make sure everything still holds
install('--fake', '/%s' % dag_hash[:7])
validate_callpath_spec(True)
all_specs, mpileaks_specs, callpath_specs, mpi_specs = db_specs()
assert len(all_specs) == total_specs + 1 # back to total_specs+1
assert len(mpileaks_specs) == 3
assert len(callpath_specs) == 3 # back to 3
assert len(mpi_specs) == 3
@pytest.mark.db
@pytest.mark.regression('15773')
def test_in_memory_consistency_when_uninstalling(
mutable_database, monkeypatch
):
"""Test that uninstalling doesn't raise warnings"""
def _warn(*args, **kwargs):
raise RuntimeError('a warning was triggered!')
monkeypatch.setattr(tty, 'warn', _warn)
# Now try to uninstall and check this doesn't trigger warnings
uninstall('-y', '-a')
|