alibuild 1.17.19__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- alibuild-1.17.19.data/scripts/aliBuild +137 -0
- alibuild-1.17.19.data/scripts/aliDeps +7 -0
- alibuild-1.17.19.data/scripts/aliDoctor +7 -0
- alibuild-1.17.19.data/scripts/alienv +344 -0
- alibuild-1.17.19.data/scripts/pb +7 -0
- alibuild-1.17.19.dist-info/METADATA +78 -0
- alibuild-1.17.19.dist-info/RECORD +74 -0
- alibuild-1.17.19.dist-info/WHEEL +5 -0
- alibuild-1.17.19.dist-info/licenses/LICENSE.md +674 -0
- alibuild-1.17.19.dist-info/top_level.txt +5 -0
- alibuild_helpers/__init__.py +21 -0
- alibuild_helpers/_version.py +21 -0
- alibuild_helpers/analytics.py +120 -0
- alibuild_helpers/args.py +493 -0
- alibuild_helpers/build.py +1209 -0
- alibuild_helpers/build_template.sh +314 -0
- alibuild_helpers/clean.py +83 -0
- alibuild_helpers/cmd.py +154 -0
- alibuild_helpers/deps.py +116 -0
- alibuild_helpers/doctor.py +195 -0
- alibuild_helpers/git.py +104 -0
- alibuild_helpers/init.py +103 -0
- alibuild_helpers/log.py +132 -0
- alibuild_helpers/scm.py +31 -0
- alibuild_helpers/sl.py +62 -0
- alibuild_helpers/sync.py +693 -0
- alibuild_helpers/templating_plugin.py +18 -0
- alibuild_helpers/utilities.py +662 -0
- alibuild_helpers/workarea.py +179 -0
- debian/changelog +11 -0
- debian/compat +1 -0
- debian/control +14 -0
- debian/copyright +10 -0
- debian/files +1 -0
- debian/rules +7 -0
- docs/README.md +1 -0
- docs/SUPPORT +3 -0
- docs/docs/alice_logo.png +0 -0
- docs/docs/deps.png +0 -0
- docs/docs/index.md +75 -0
- docs/docs/quick.md +89 -0
- docs/docs/reference.md +430 -0
- docs/docs/stylesheets/extra.css +9 -0
- docs/docs/troubleshooting.md +346 -0
- docs/docs/user.md +413 -0
- docs/mkdocs.yml +37 -0
- templates/alibuild_to_please.jnj +63 -0
- tests/test_analytics.py +42 -0
- tests/test_args.py +119 -0
- tests/test_build.py +426 -0
- tests/test_clean.py +154 -0
- tests/test_cmd.py +73 -0
- tests/test_deps.py +79 -0
- tests/test_doctor.py +128 -0
- tests/test_git.py +48 -0
- tests/test_hashing.py +67 -0
- tests/test_init.py +103 -0
- tests/test_log.py +50 -0
- tests/test_packagelist.py +235 -0
- tests/test_parseRecipe.py +132 -0
- tests/test_sync.py +332 -0
- tests/test_utilities.py +383 -0
- tests/test_workarea.py +101 -0
- tests/testdist/broken1.sh +1 -0
- tests/testdist/broken2.sh +1 -0
- tests/testdist/broken3.sh +3 -0
- tests/testdist/broken4.sh +2 -0
- tests/testdist/broken5.sh +2 -0
- tests/testdist/broken6.sh +2 -0
- tests/testdist/broken7.sh +5 -0
- tests/testdist/clobber-initdotsh.sh +4 -0
- tests/testdist/defaults-o2.sh +10 -0
- tests/testdist/delete-etc.sh +4 -0
- tests/testdist/tracking-env.sh +6 -0
tests/test_build.py
ADDED
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
from argparse import Namespace
|
|
2
|
+
import os
|
|
3
|
+
import os.path
|
|
4
|
+
import re
|
|
5
|
+
import sys
|
|
6
|
+
import unittest
|
|
7
|
+
# Assuming you are using the mock library to ... mock things
|
|
8
|
+
from unittest.mock import call, patch, MagicMock, DEFAULT
|
|
9
|
+
from io import StringIO
|
|
10
|
+
from collections import OrderedDict
|
|
11
|
+
|
|
12
|
+
from alibuild_helpers.utilities import parseRecipe, resolve_tag
|
|
13
|
+
from alibuild_helpers.build import doBuild, storeHashes, generate_initdotsh
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
TEST_DEFAULT_RELEASE = """\
|
|
17
|
+
package: defaults-release
|
|
18
|
+
version: v1
|
|
19
|
+
---
|
|
20
|
+
: this line should trigger a warning
|
|
21
|
+
"""
|
|
22
|
+
TEST_DEFAULT_RELEASE_BUILD_HASH = "27ce49698e818e8efb56b6eff6dd785e503df341"
|
|
23
|
+
|
|
24
|
+
TEST_ZLIB_RECIPE = """\
|
|
25
|
+
package: zlib
|
|
26
|
+
version: v1.2.3
|
|
27
|
+
source: https://github.com/madler/zlib
|
|
28
|
+
tag: master
|
|
29
|
+
---
|
|
30
|
+
./configure
|
|
31
|
+
make
|
|
32
|
+
make install
|
|
33
|
+
"""
|
|
34
|
+
TEST_ZLIB_GIT_REFS = "8822efa61f2a385e0bc83ca5819d608111b2168a\trefs/heads/master"
|
|
35
|
+
TEST_ZLIB_BUILD_HASH = "8cd1f56c450f05ffbba3276bad08eae30f814999"
|
|
36
|
+
|
|
37
|
+
TEST_ROOT_RECIPE = """\
|
|
38
|
+
package: ROOT
|
|
39
|
+
version: v6-08-30
|
|
40
|
+
source: https://github.com/root-mirror/root
|
|
41
|
+
tag: v6-08-00-patches
|
|
42
|
+
requires:
|
|
43
|
+
- zlib
|
|
44
|
+
env:
|
|
45
|
+
ROOT_TEST_1: "root test 1"
|
|
46
|
+
ROOT_TEST_2: "root test 2"
|
|
47
|
+
ROOT_TEST_3: "root test 3"
|
|
48
|
+
ROOT_TEST_4: "root test 4"
|
|
49
|
+
ROOT_TEST_5: "root test 5"
|
|
50
|
+
ROOT_TEST_6: "root test 6"
|
|
51
|
+
prepend_path:
|
|
52
|
+
PREPEND_ROOT_1: "prepend root 1"
|
|
53
|
+
PREPEND_ROOT_2: "prepend root 2"
|
|
54
|
+
PREPEND_ROOT_3: "prepend root 3"
|
|
55
|
+
PREPEND_ROOT_4: "prepend root 4"
|
|
56
|
+
PREPEND_ROOT_5: "prepend root 5"
|
|
57
|
+
PREPEND_ROOT_6: "prepend root 6"
|
|
58
|
+
append_path:
|
|
59
|
+
APPEND_ROOT_1: "append root 1"
|
|
60
|
+
APPEND_ROOT_2: "append root 2"
|
|
61
|
+
APPEND_ROOT_3: "append root 3"
|
|
62
|
+
APPEND_ROOT_4: "append root 4"
|
|
63
|
+
APPEND_ROOT_5: "append root 5"
|
|
64
|
+
APPEND_ROOT_6: "append root 6"
|
|
65
|
+
---
|
|
66
|
+
./configure
|
|
67
|
+
make
|
|
68
|
+
make install
|
|
69
|
+
"""
|
|
70
|
+
TEST_ROOT_GIT_REFS = """\
|
|
71
|
+
87b87c4322d2a3fad315c919cb2e2dd73f2154dc\trefs/heads/master
|
|
72
|
+
f7b336611753f1f4aaa94222b0d620748ae230c0\trefs/heads/v6-08-00-patches
|
|
73
|
+
f7b336611753f1f4aaa94222b0d620748ae230c0\trefs/tags/test-tag"""
|
|
74
|
+
TEST_ROOT_BUILD_HASH = ("8ec3f41b6b585ef86a02e9c595eed67f34d63f08")
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
TEST_EXTRA_RECIPE = """\
|
|
78
|
+
package: Extra
|
|
79
|
+
version: v1
|
|
80
|
+
tag: v1
|
|
81
|
+
source: file:///dev/null
|
|
82
|
+
requires:
|
|
83
|
+
- ROOT
|
|
84
|
+
---
|
|
85
|
+
"""
|
|
86
|
+
TEST_EXTRA_GIT_REFS = """\
|
|
87
|
+
f000\trefs/heads/master
|
|
88
|
+
ba22\trefs/tags/v1
|
|
89
|
+
ba22\trefs/tags/v2
|
|
90
|
+
baad\trefs/tags/v3"""
|
|
91
|
+
TEST_EXTRA_BUILD_HASH = ("5afae57bfc6a374e74c1c4427698ab5edebce0bc")
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
GIT_CLONE_REF_ZLIB_ARGS = ("clone", "--bare", "https://github.com/madler/zlib",
|
|
95
|
+
"/sw/MIRROR/zlib", "--filter=blob:none"), ".", False
|
|
96
|
+
GIT_CLONE_SRC_ZLIB_ARGS = ("clone", "-n", "https://github.com/madler/zlib",
|
|
97
|
+
"/sw/SOURCES/zlib/v1.2.3/8822efa61f",
|
|
98
|
+
"--dissociate", "--reference", "/sw/MIRROR/zlib", "--filter=blob:none"), ".", False
|
|
99
|
+
GIT_SET_URL_ZLIB_ARGS = ("remote", "set-url", "--push", "origin", "https://github.com/madler/zlib"), \
|
|
100
|
+
"/sw/SOURCES/zlib/v1.2.3/8822efa61f", False
|
|
101
|
+
GIT_CHECKOUT_ZLIB_ARGS = ("checkout", "-f", "master"), \
|
|
102
|
+
"/sw/SOURCES/zlib/v1.2.3/8822efa61f", False
|
|
103
|
+
|
|
104
|
+
GIT_FETCH_REF_ROOT_ARGS = ("fetch", "-f", "--filter=blob:none", "https://github.com/root-mirror/root", "+refs/tags/*:refs/tags/*",
|
|
105
|
+
"+refs/heads/*:refs/heads/*"), "/sw/MIRROR/root", False
|
|
106
|
+
GIT_CLONE_SRC_ROOT_ARGS = ("clone", "-n", "https://github.com/root-mirror/root",
|
|
107
|
+
"/sw/SOURCES/ROOT/v6-08-30/f7b3366117",
|
|
108
|
+
"--dissociate", "--reference", "/sw/MIRROR/root", "--filter=blob:none"), ".", False
|
|
109
|
+
GIT_SET_URL_ROOT_ARGS = ("remote", "set-url", "--push", "origin", "https://github.com/root-mirror/root"), \
|
|
110
|
+
"/sw/SOURCES/ROOT/v6-08-30/f7b3366117", False
|
|
111
|
+
GIT_CHECKOUT_ROOT_ARGS = ("checkout", "-f", "v6-08-00-patches"), \
|
|
112
|
+
"/sw/SOURCES/ROOT/v6-08-30/f7b3366117", False
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def dummy_git(args, directory=".", check=True, prompt=True):
|
|
116
|
+
return {
|
|
117
|
+
(("symbolic-ref", "-q", "HEAD"), "/alidist", False): (0, "master"),
|
|
118
|
+
(("rev-parse", "HEAD"), "/alidist", True): "6cec7b7b3769826219dfa85e5daa6de6522229a0",
|
|
119
|
+
(("ls-remote", "--heads", "--tags", "/sw/MIRROR/root"), ".", False): (0, TEST_ROOT_GIT_REFS),
|
|
120
|
+
(("ls-remote", "--heads", "--tags", "/sw/MIRROR/zlib"), ".", False): (0, TEST_ZLIB_GIT_REFS),
|
|
121
|
+
GIT_CLONE_REF_ZLIB_ARGS: (0, ""),
|
|
122
|
+
GIT_CLONE_SRC_ZLIB_ARGS: (0, ""),
|
|
123
|
+
GIT_SET_URL_ZLIB_ARGS: (0, ""),
|
|
124
|
+
GIT_CHECKOUT_ZLIB_ARGS: (0, ""),
|
|
125
|
+
GIT_FETCH_REF_ROOT_ARGS: (0, ""),
|
|
126
|
+
GIT_CLONE_SRC_ROOT_ARGS: (0, ""),
|
|
127
|
+
GIT_SET_URL_ROOT_ARGS: (0, ""),
|
|
128
|
+
GIT_CHECKOUT_ROOT_ARGS: (0, ""),
|
|
129
|
+
}[(tuple(args), directory, check)]
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
TIMES_ASKED = {}
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def dummy_open(x, mode="r", encoding=None, errors=None):
|
|
136
|
+
if x.endswith("/fetch-log.txt") and mode == "w":
|
|
137
|
+
return MagicMock(__enter__=lambda _: StringIO())
|
|
138
|
+
if x.endswith("/alibuild_helpers/build_template.sh"):
|
|
139
|
+
return DEFAULT # actually open the real build_template.sh
|
|
140
|
+
if mode == "r":
|
|
141
|
+
try:
|
|
142
|
+
threshold, result = {
|
|
143
|
+
"/sw/BUILD/%s/defaults-release/.build_succeeded" % TEST_DEFAULT_RELEASE_BUILD_HASH: (0, StringIO("0")),
|
|
144
|
+
"/sw/BUILD/%s/zlib/.build_succeeded" % TEST_ZLIB_BUILD_HASH: (0, StringIO("0")),
|
|
145
|
+
"/sw/BUILD/%s/ROOT/.build_succeeded" % TEST_ROOT_BUILD_HASH: (0, StringIO("0")),
|
|
146
|
+
"/sw/osx_x86-64/defaults-release/v1-1/.build-hash": (1, StringIO(TEST_DEFAULT_RELEASE_BUILD_HASH)),
|
|
147
|
+
"/sw/osx_x86-64/zlib/v1.2.3-local1/.build-hash": (1, StringIO(TEST_ZLIB_BUILD_HASH)),
|
|
148
|
+
"/sw/osx_x86-64/ROOT/v6-08-30-local1/.build-hash": (1, StringIO(TEST_ROOT_BUILD_HASH))
|
|
149
|
+
}[x]
|
|
150
|
+
except KeyError:
|
|
151
|
+
return DEFAULT
|
|
152
|
+
if threshold > TIMES_ASKED.get(x, 0):
|
|
153
|
+
result = None
|
|
154
|
+
TIMES_ASKED[x] = TIMES_ASKED.get(x, 0) + 1
|
|
155
|
+
if not result:
|
|
156
|
+
raise IOError
|
|
157
|
+
return result
|
|
158
|
+
return DEFAULT
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def dummy_execute(x, **kwds):
|
|
162
|
+
s = " ".join(x) if isinstance(x, list) else x
|
|
163
|
+
if re.match(".*ln -sfn.*TARS", s):
|
|
164
|
+
return 0
|
|
165
|
+
return {
|
|
166
|
+
"/bin/bash -e -x /sw/SPECS/osx_x86-64/defaults-release/v1-1/build.sh 2>&1": 0,
|
|
167
|
+
'/bin/bash -e -x /sw/SPECS/osx_x86-64/zlib/v1.2.3-local1/build.sh 2>&1': 0,
|
|
168
|
+
'/bin/bash -e -x /sw/SPECS/osx_x86-64/ROOT/v6-08-30-local1/build.sh 2>&1': 0,
|
|
169
|
+
}[s]
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def dummy_readlink(x):
|
|
173
|
+
return {
|
|
174
|
+
"/sw/TARS/osx_x86-64/defaults-release/defaults-release-v1-1.osx_x86-64.tar.gz":
|
|
175
|
+
"../../osx_x86-64/store/%s/%s/defaults-release-v1-1.osx_x86-64.tar.gz" %
|
|
176
|
+
(TEST_DEFAULT_RELEASE_BUILD_HASH[:2], TEST_DEFAULT_RELEASE_BUILD_HASH)
|
|
177
|
+
}[x]
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def dummy_exists(x):
|
|
181
|
+
if x.endswith("alibuild_helpers/.git"):
|
|
182
|
+
return False
|
|
183
|
+
return {
|
|
184
|
+
"/alidist": True,
|
|
185
|
+
"/alidist/.git": True,
|
|
186
|
+
"/alidist/.sl": False,
|
|
187
|
+
"/sw": True,
|
|
188
|
+
"/sw/SPECS": False,
|
|
189
|
+
"/sw/MIRROR/root": True,
|
|
190
|
+
"/sw/MIRROR/zlib": False,
|
|
191
|
+
}.get(x, DEFAULT)
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
# A few errors we should handle, together with the expected result
|
|
195
|
+
@patch("alibuild_helpers.git.clone_speedup_options",
|
|
196
|
+
new=MagicMock(return_value=["--filter=blob:none"]))
|
|
197
|
+
@patch("alibuild_helpers.build.BASH", new="/bin/bash")
|
|
198
|
+
class BuildTestCase(unittest.TestCase):
|
|
199
|
+
@patch("alibuild_helpers.analytics", new=MagicMock())
|
|
200
|
+
@patch("requests.Session.get", new=MagicMock())
|
|
201
|
+
@patch("alibuild_helpers.sync.execute", new=dummy_execute)
|
|
202
|
+
@patch("alibuild_helpers.git.git")
|
|
203
|
+
@patch("alibuild_helpers.build.exists", new=MagicMock(side_effect=dummy_exists))
|
|
204
|
+
@patch("os.path.exists", new=MagicMock(side_effect=dummy_exists))
|
|
205
|
+
@patch("alibuild_helpers.build.dieOnError", new=MagicMock())
|
|
206
|
+
@patch("alibuild_helpers.utilities.dieOnError", new=MagicMock())
|
|
207
|
+
@patch("alibuild_helpers.utilities.warning")
|
|
208
|
+
@patch("alibuild_helpers.build.readDefaults",
|
|
209
|
+
new=MagicMock(return_value=(OrderedDict({"package": "defaults-release", "disable": []}), "")))
|
|
210
|
+
@patch("shutil.rmtree", new=MagicMock(return_value=None))
|
|
211
|
+
@patch("os.makedirs", new=MagicMock(return_value=None))
|
|
212
|
+
@patch("alibuild_helpers.build.makedirs", new=MagicMock(return_value=None))
|
|
213
|
+
@patch("alibuild_helpers.build.symlink", new=MagicMock(return_value=None))
|
|
214
|
+
@patch("alibuild_helpers.workarea.symlink", new=MagicMock(return_value=None))
|
|
215
|
+
@patch("alibuild_helpers.utilities.open", new=lambda x: {
|
|
216
|
+
"/alidist/root.sh": StringIO(TEST_ROOT_RECIPE),
|
|
217
|
+
"/alidist/zlib.sh": StringIO(TEST_ZLIB_RECIPE),
|
|
218
|
+
"/alidist/defaults-release.sh": StringIO(TEST_DEFAULT_RELEASE)
|
|
219
|
+
}[x])
|
|
220
|
+
@patch("alibuild_helpers.sync.open", new=MagicMock(side_effect=dummy_open))
|
|
221
|
+
@patch("alibuild_helpers.build.open", new=MagicMock(side_effect=dummy_open))
|
|
222
|
+
@patch("codecs.open", new=MagicMock(side_effect=dummy_open))
|
|
223
|
+
@patch("alibuild_helpers.build.shutil", new=MagicMock())
|
|
224
|
+
@patch("os.listdir")
|
|
225
|
+
@patch("alibuild_helpers.build.glob", new=lambda pattern: {
|
|
226
|
+
"*": ["zlib"],
|
|
227
|
+
"/sw/TARS/osx_x86-64/store/%s/%s/*gz" % (TEST_DEFAULT_RELEASE_BUILD_HASH[:2],
|
|
228
|
+
TEST_DEFAULT_RELEASE_BUILD_HASH): [],
|
|
229
|
+
"/sw/TARS/osx_x86-64/store/%s/%s/*gz" % (TEST_ZLIB_BUILD_HASH[:2], TEST_ZLIB_BUILD_HASH): [],
|
|
230
|
+
"/sw/TARS/osx_x86-64/store/%s/%s/*gz" % (TEST_ROOT_BUILD_HASH[:2], TEST_ROOT_BUILD_HASH): [],
|
|
231
|
+
"/sw/TARS/osx_x86-64/defaults-release/defaults-release-v1-1.osx_x86-64.tar.gz":
|
|
232
|
+
["../../osx_x86-64/store/%s/%s/defaults-release-v1-1.osx_x86-64.tar.gz" %
|
|
233
|
+
(TEST_DEFAULT_RELEASE_BUILD_HASH[:2], TEST_DEFAULT_RELEASE_BUILD_HASH)],
|
|
234
|
+
}[pattern])
|
|
235
|
+
@patch("alibuild_helpers.build.readlink", new=dummy_readlink)
|
|
236
|
+
@patch("alibuild_helpers.build.banner", new=MagicMock(return_value=None))
|
|
237
|
+
@patch("alibuild_helpers.build.debug")
|
|
238
|
+
@patch("alibuild_helpers.workarea.is_writeable", new=MagicMock(return_value=True))
|
|
239
|
+
@patch("alibuild_helpers.build.basename", new=MagicMock(return_value="aliBuild"))
|
|
240
|
+
@patch("alibuild_helpers.build.install_wrapper_script", new=MagicMock())
|
|
241
|
+
def test_coverDoBuild(self, mock_debug, mock_listdir, mock_warning, mock_git_git) -> None:
|
|
242
|
+
mock_git_git.side_effect = dummy_git
|
|
243
|
+
mock_debug.side_effect = lambda *args: None
|
|
244
|
+
mock_warning.side_effect = lambda *args: None
|
|
245
|
+
mock_listdir.side_effect = lambda directory: {
|
|
246
|
+
"/sw/TARS/osx_x86-64/defaults-release": ["defaults-release-v1-1.osx_x86-64.tar.gz"],
|
|
247
|
+
"/sw/TARS/osx_x86-64/zlib": [],
|
|
248
|
+
"/sw/TARS/osx_x86-64/ROOT": [],
|
|
249
|
+
}.get(directory, DEFAULT)
|
|
250
|
+
os.environ["ALIBUILD_NO_ANALYTICS"] = "1"
|
|
251
|
+
|
|
252
|
+
mock_parser = MagicMock()
|
|
253
|
+
args = Namespace(
|
|
254
|
+
remoteStore="",
|
|
255
|
+
writeStore="",
|
|
256
|
+
referenceSources="/sw/MIRROR",
|
|
257
|
+
docker=False,
|
|
258
|
+
dockerImage=None,
|
|
259
|
+
docker_extra_args=["--network=host"],
|
|
260
|
+
architecture="osx_x86-64",
|
|
261
|
+
workDir="/sw",
|
|
262
|
+
pkgname=["root"],
|
|
263
|
+
configDir="/alidist",
|
|
264
|
+
disable=[],
|
|
265
|
+
force_rebuild=[],
|
|
266
|
+
defaults="release",
|
|
267
|
+
jobs=2,
|
|
268
|
+
annotate={},
|
|
269
|
+
preferSystem=[],
|
|
270
|
+
noSystem=None,
|
|
271
|
+
debug=True,
|
|
272
|
+
dryRun=False,
|
|
273
|
+
aggressiveCleanup=False,
|
|
274
|
+
environment={},
|
|
275
|
+
autoCleanup=False,
|
|
276
|
+
noDevel=[],
|
|
277
|
+
onlyDeps=False,
|
|
278
|
+
fetchRepos=False,
|
|
279
|
+
forceTracked=False,
|
|
280
|
+
plugin="legacy"
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
def mkcall(args):
|
|
284
|
+
cmd, directory, check = args
|
|
285
|
+
return call(list(cmd), directory=directory, check=check, prompt=False)
|
|
286
|
+
|
|
287
|
+
common_calls = [
|
|
288
|
+
call(("rev-parse", "HEAD"), args.configDir),
|
|
289
|
+
mkcall(GIT_CLONE_REF_ZLIB_ARGS),
|
|
290
|
+
call(["ls-remote", "--heads", "--tags", args.referenceSources + "/zlib"],
|
|
291
|
+
directory=".", check=False, prompt=False),
|
|
292
|
+
call(["ls-remote", "--heads", "--tags", args.referenceSources + "/root"],
|
|
293
|
+
directory=".", check=False, prompt=False),
|
|
294
|
+
]
|
|
295
|
+
|
|
296
|
+
mock_git_git.reset_mock()
|
|
297
|
+
mock_debug.reset_mock()
|
|
298
|
+
mock_warning.reset_mock()
|
|
299
|
+
doBuild(args, mock_parser)
|
|
300
|
+
mock_warning.assert_called_with("%s.sh contains a recipe, which will be ignored", "defaults-release")
|
|
301
|
+
mock_debug.assert_called_with("Everything done")
|
|
302
|
+
# After this run, .build-hash files will be simulated to exist
|
|
303
|
+
# already, so sw/SOURCES repos must only be checked out on this run.
|
|
304
|
+
mock_git_git.assert_has_calls(common_calls + [
|
|
305
|
+
mkcall(GIT_CLONE_SRC_ZLIB_ARGS),
|
|
306
|
+
mkcall(GIT_SET_URL_ZLIB_ARGS),
|
|
307
|
+
mkcall(GIT_CHECKOUT_ZLIB_ARGS),
|
|
308
|
+
mkcall(GIT_CLONE_SRC_ROOT_ARGS),
|
|
309
|
+
mkcall(GIT_SET_URL_ROOT_ARGS),
|
|
310
|
+
mkcall(GIT_CHECKOUT_ROOT_ARGS),
|
|
311
|
+
], any_order=True)
|
|
312
|
+
self.assertEqual(mock_git_git.call_count, len(common_calls) + 6)
|
|
313
|
+
|
|
314
|
+
# Force fetching repos
|
|
315
|
+
mock_git_git.reset_mock()
|
|
316
|
+
mock_debug.reset_mock()
|
|
317
|
+
mock_warning.reset_mock()
|
|
318
|
+
args.fetchRepos = True
|
|
319
|
+
doBuild(args, mock_parser)
|
|
320
|
+
mock_warning.assert_called_with("%s.sh contains a recipe, which will be ignored", "defaults-release")
|
|
321
|
+
mock_debug.assert_called_with("Everything done")
|
|
322
|
+
mock_listdir.assert_called_with("/sw/TARS/osx_x86-64/ROOT")
|
|
323
|
+
# We can't compare directly against the list of calls here as they
|
|
324
|
+
# might happen in any order.
|
|
325
|
+
mock_git_git.assert_has_calls(common_calls + [
|
|
326
|
+
mkcall(GIT_FETCH_REF_ROOT_ARGS),
|
|
327
|
+
], any_order=True)
|
|
328
|
+
self.assertEqual(mock_git_git.call_count, len(common_calls) + 1)
|
|
329
|
+
|
|
330
|
+
def setup_spec(self, script):
|
|
331
|
+
"""Parse the alidist recipe in SCRIPT and return its spec."""
|
|
332
|
+
err, spec, recipe = parseRecipe(lambda: script)
|
|
333
|
+
self.assertIsNone(err)
|
|
334
|
+
spec["recipe"] = "" if spec["package"].startswith("defaults-") else recipe.strip("\n")
|
|
335
|
+
spec.setdefault("tag", spec["version"])
|
|
336
|
+
spec["tag"] = resolve_tag(spec)
|
|
337
|
+
return spec
|
|
338
|
+
|
|
339
|
+
def test_hashing(self) -> None:
|
|
340
|
+
"""Check that the hashes assigned to packages remain constant."""
|
|
341
|
+
default = self.setup_spec(TEST_DEFAULT_RELEASE)
|
|
342
|
+
zlib = self.setup_spec(TEST_ZLIB_RECIPE)
|
|
343
|
+
root = self.setup_spec(TEST_ROOT_RECIPE)
|
|
344
|
+
extra = self.setup_spec(TEST_EXTRA_RECIPE)
|
|
345
|
+
default["commit_hash"] = "0"
|
|
346
|
+
for spec, refs in ((zlib, TEST_ZLIB_GIT_REFS),
|
|
347
|
+
(root, TEST_ROOT_GIT_REFS),
|
|
348
|
+
(extra, TEST_EXTRA_GIT_REFS)):
|
|
349
|
+
spec.setdefault("requires", []).append(default["package"])
|
|
350
|
+
spec["scm_refs"] = {ref: hash for hash, _, ref in (
|
|
351
|
+
line.partition("\t") for line in refs.splitlines()
|
|
352
|
+
)}
|
|
353
|
+
try:
|
|
354
|
+
spec["commit_hash"] = spec["scm_refs"]["refs/tags/" + spec["tag"]]
|
|
355
|
+
except KeyError:
|
|
356
|
+
spec["commit_hash"] = spec["scm_refs"]["refs/heads/" + spec["tag"]]
|
|
357
|
+
specs = {pkg["package"]: pkg for pkg in (default, zlib, root, extra)}
|
|
358
|
+
for spec in specs.values():
|
|
359
|
+
spec["is_devel_pkg"] = False
|
|
360
|
+
|
|
361
|
+
storeHashes("defaults-release", specs, considerRelocation=False)
|
|
362
|
+
default["hash"] = default["remote_revision_hash"]
|
|
363
|
+
self.assertEqual(default["hash"], TEST_DEFAULT_RELEASE_BUILD_HASH)
|
|
364
|
+
self.assertEqual(default["remote_hashes"], [TEST_DEFAULT_RELEASE_BUILD_HASH])
|
|
365
|
+
|
|
366
|
+
storeHashes("zlib", specs, considerRelocation=False)
|
|
367
|
+
zlib["hash"] = zlib["local_revision_hash"]
|
|
368
|
+
self.assertEqual(zlib["hash"], TEST_ZLIB_BUILD_HASH)
|
|
369
|
+
self.assertEqual(zlib["local_hashes"], [TEST_ZLIB_BUILD_HASH])
|
|
370
|
+
|
|
371
|
+
storeHashes("ROOT", specs, considerRelocation=False)
|
|
372
|
+
root["hash"] = root["local_revision_hash"]
|
|
373
|
+
self.assertEqual(root["hash"], TEST_ROOT_BUILD_HASH)
|
|
374
|
+
# Equivalent "commit hashes": "f7b336611753f1f4aaa94222b0d620748ae230c0"
|
|
375
|
+
# (head of v6-08-00-patches and commit of test-tag), and "test-tag".
|
|
376
|
+
self.assertEqual(len(root["local_hashes"]), 2)
|
|
377
|
+
self.assertEqual(root["local_hashes"][0], TEST_ROOT_BUILD_HASH)
|
|
378
|
+
|
|
379
|
+
storeHashes("Extra", specs, considerRelocation=False)
|
|
380
|
+
extra["hash"] = extra["local_revision_hash"]
|
|
381
|
+
self.assertEqual(extra["hash"], TEST_EXTRA_BUILD_HASH)
|
|
382
|
+
# Equivalent "commit hashes": "v1", "v2", "ba22".
|
|
383
|
+
self.assertEqual(len(extra["local_hashes"]), 3)
|
|
384
|
+
self.assertEqual(len(extra["remote_hashes"]), 3)
|
|
385
|
+
self.assertEqual(extra["local_hashes"][0], TEST_EXTRA_BUILD_HASH)
|
|
386
|
+
|
|
387
|
+
def test_initdotsh(self) -> None:
|
|
388
|
+
"""Sanity-check the generated init.sh for a few variables."""
|
|
389
|
+
specs = {
|
|
390
|
+
# Add some attributes that are normally set by doBuild(), but
|
|
391
|
+
# required by generate_initdotsh().
|
|
392
|
+
spec["package"]: dict(spec, revision="1", commit_hash="424242", hash="010101")
|
|
393
|
+
for spec in map(self.setup_spec, (
|
|
394
|
+
TEST_DEFAULT_RELEASE,
|
|
395
|
+
TEST_ZLIB_RECIPE,
|
|
396
|
+
TEST_ROOT_RECIPE,
|
|
397
|
+
TEST_EXTRA_RECIPE,
|
|
398
|
+
))
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
setup_initdotsh = generate_initdotsh("ROOT", specs, "slc7_x86-64", post_build=False)
|
|
402
|
+
complete_initdotsh = generate_initdotsh("ROOT", specs, "slc7_x86-64", post_build=True)
|
|
403
|
+
|
|
404
|
+
# We only generate init.sh for ROOT, so Extra should not appear at all.
|
|
405
|
+
self.assertNotIn("Extra", setup_initdotsh)
|
|
406
|
+
self.assertNotIn("Extra", complete_initdotsh)
|
|
407
|
+
|
|
408
|
+
# Dependencies must be loaded both for this build and for subsequent ones.
|
|
409
|
+
self.assertIn('. "$WORK_DIR/$ALIBUILD_ARCH_PREFIX"/zlib/v1.2.3-1/etc/profile.d/init.sh', setup_initdotsh)
|
|
410
|
+
self.assertIn('. "$WORK_DIR/$ALIBUILD_ARCH_PREFIX"/zlib/v1.2.3-1/etc/profile.d/init.sh', complete_initdotsh)
|
|
411
|
+
|
|
412
|
+
# ROOT-specific variables must not be set during ROOT's build yet...
|
|
413
|
+
self.assertNotIn("export ROOT_VERSION=", setup_initdotsh)
|
|
414
|
+
self.assertNotIn("export ROOT_TEST_1=", setup_initdotsh)
|
|
415
|
+
self.assertNotIn("export APPEND_ROOT_1=", setup_initdotsh)
|
|
416
|
+
self.assertNotIn("export PREPEND_ROOT_1=", setup_initdotsh)
|
|
417
|
+
|
|
418
|
+
# ...but they must be set once ROOT's build has completed.
|
|
419
|
+
self.assertIn("export ROOT_VERSION=v6-08-30", complete_initdotsh)
|
|
420
|
+
self.assertIn('export ROOT_TEST_1="root test 1"', complete_initdotsh)
|
|
421
|
+
self.assertIn("export APPEND_ROOT_1=", complete_initdotsh)
|
|
422
|
+
self.assertIn("export PREPEND_ROOT_1=", complete_initdotsh)
|
|
423
|
+
|
|
424
|
+
|
|
425
|
+
if __name__ == '__main__':
|
|
426
|
+
unittest.main()
|
tests/test_clean.py
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# Assuming you are using the mock library to ... mock things
|
|
2
|
+
from unittest.mock import patch, call
|
|
3
|
+
|
|
4
|
+
from alibuild_helpers.clean import decideClean, doClean
|
|
5
|
+
|
|
6
|
+
import unittest
|
|
7
|
+
|
|
8
|
+
REALPATH_WITH_OBSOLETE_FILES = {
|
|
9
|
+
"sw/BUILD/a-latest": "/sw/BUILD/f339115741c6ab9cf291d3210f44bee795c56e16",
|
|
10
|
+
"sw/BUILD/b-latest": "/sw/BUILD/fcdfc2e1c9f0433c60b3b000e0e2737d297a9b1c",
|
|
11
|
+
"sw/BUILD/f339115741c6ab9cf291d3210f44bee795c56e16": "/sw/BUILD/f339115741c6ab9cf291d3210f44bee795c56e16",
|
|
12
|
+
"sw/BUILD/fcdfc2e1c9f0433c60b3b000e0e2737d297a9b1c": "/sw/BUILD/fcdfc2e1c9f0433c60b3b000e0e2737d297a9b1c",
|
|
13
|
+
"sw/BUILD/somethingtodelete": "/sw/BUILD/somethingtodelete",
|
|
14
|
+
"sw/osx_x86-64/b/latest": "/sw/osx_x86-64/b/v2",
|
|
15
|
+
"sw/osx_x86-64/a/latest": "/sw/osx_x86-64/a/v1",
|
|
16
|
+
"sw/osx_x86-64/b/latest-root6": "/sw/osx_x86-64/b/v4",
|
|
17
|
+
"sw/osx_x86-64/b/latest-release": "/sw/osx_x86-64/b/v2",
|
|
18
|
+
"sw/osx_x86-64/a/latest-release": "/sw/osx_x86-64/a/v1",
|
|
19
|
+
"sw/osx_x86-64/b/v4": "/sw/osx_x86-64/b/v4",
|
|
20
|
+
"sw/osx_x86-64/b/v3": "/sw/osx_x86-64/b/v3",
|
|
21
|
+
"sw/osx_x86-64/b/v2": "/sw/osx_x86-64/b/v2",
|
|
22
|
+
"sw/osx_x86-64/b/v1": "/sw/osx_x86-64/b/v1",
|
|
23
|
+
"sw/osx_x86-64/a/v1": "/sw/osx_x86-64/a/v1"
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
GLOB_WITH_OBSOLETE_FILES = {
|
|
27
|
+
"sw/BUILD/*-latest*": ["sw/BUILD/a-latest", "sw/BUILD/b-latest"],
|
|
28
|
+
"sw/BUILD/*": ["sw/BUILD/a-latest",
|
|
29
|
+
"sw/BUILD/b-latest",
|
|
30
|
+
"sw/BUILD/f339115741c6ab9cf291d3210f44bee795c56e16",
|
|
31
|
+
"sw/BUILD/fcdfc2e1c9f0433c60b3b000e0e2737d297a9b1c",
|
|
32
|
+
"sw/BUILD/somethingtodelete"],
|
|
33
|
+
"sw/osx_x86-64/*/": ["sw/osx_x86-64/a/", "sw/osx_x86-64/b/"],
|
|
34
|
+
"sw/osx_x86-64/b/latest*": ["sw/osx_x86-64/b/latest",
|
|
35
|
+
"sw/osx_x86-64/b/latest-release",
|
|
36
|
+
"sw/osx_x86-64/b/latest-root6"],
|
|
37
|
+
"sw/osx_x86-64/a/latest*": ["sw/osx_x86-64/a/latest", "sw/osx_x86-64/a/latest-release"],
|
|
38
|
+
"sw/osx_x86-64/*/*": ["sw/osx_x86-64/a/latest", "sw/osx_x86-64/a/v1",
|
|
39
|
+
"sw/osx_x86-64/b/latest", "sw/osx_x86-64/b/v1",
|
|
40
|
+
"sw/osx_x86-64/b/v2", "sw/osx_x86-64/b/v3",
|
|
41
|
+
"sw/osx_x86-64/b/v4"],
|
|
42
|
+
"sw/slc7_x86-64/*/": [],
|
|
43
|
+
"sw/slc7_x86-64/*/*": []
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
READLINK_MOCKUP_DB = {
|
|
47
|
+
"sw/BUILD/a-latest": "f339115741c6ab9cf291d3210f44bee795c56e16",
|
|
48
|
+
"sw/BUILD/b-latest": "fcdfc2e1c9f0433c60b3b000e0e2737d297a9b1c"
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class CleanTestCase(unittest.TestCase):
|
|
53
|
+
@patch('alibuild_helpers.clean.glob')
|
|
54
|
+
@patch('alibuild_helpers.clean.os')
|
|
55
|
+
@patch('alibuild_helpers.clean.path')
|
|
56
|
+
def test_decideClean(self, mock_path, mock_os, mock_glob):
|
|
57
|
+
mock_path.realpath.side_effect = lambda x : REALPATH_WITH_OBSOLETE_FILES[x]
|
|
58
|
+
mock_path.islink.side_effect = lambda x : "latest" in x
|
|
59
|
+
mock_glob.glob.side_effect = lambda x : GLOB_WITH_OBSOLETE_FILES[x]
|
|
60
|
+
mock_os.readlink.side_effect = lambda x : READLINK_MOCKUP_DB[x]
|
|
61
|
+
toDelete = decideClean(workDir="sw", architecture="osx_x86-64", aggressiveCleanup=False)
|
|
62
|
+
mock_os.readlink.assert_called_with("sw/BUILD/b-latest")
|
|
63
|
+
mock_path.islink.assert_called_with("sw/osx_x86-64/b/v4")
|
|
64
|
+
mock_path.exists.assert_called_with("sw/osx_x86-64/b/v3")
|
|
65
|
+
self.assertEqual(toDelete, ['sw/TMP', 'sw/INSTALLROOT', 'sw/BUILD/somethingtodelete',
|
|
66
|
+
'sw/osx_x86-64/b/v1', 'sw/osx_x86-64/b/v3'])
|
|
67
|
+
toDelete = decideClean(workDir="sw", architecture="osx_x86-64", aggressiveCleanup=True)
|
|
68
|
+
self.assertEqual(toDelete, ['sw/TMP', 'sw/INSTALLROOT', 'sw/TARS/osx_x86-64/store',
|
|
69
|
+
'sw/SOURCES', 'sw/BUILD/somethingtodelete',
|
|
70
|
+
'sw/osx_x86-64/b/v1', 'sw/osx_x86-64/b/v3'])
|
|
71
|
+
toDelete = decideClean(workDir="sw", architecture="slc7_x86-64", aggressiveCleanup=True)
|
|
72
|
+
self.assertEqual(toDelete, ['sw/TMP', 'sw/INSTALLROOT', 'sw/TARS/slc7_x86-64/store',
|
|
73
|
+
'sw/SOURCES', 'sw/BUILD/somethingtodelete'])
|
|
74
|
+
|
|
75
|
+
@patch('alibuild_helpers.clean.glob')
|
|
76
|
+
@patch('alibuild_helpers.clean.os')
|
|
77
|
+
@patch('alibuild_helpers.clean.path')
|
|
78
|
+
@patch('alibuild_helpers.clean.shutil')
|
|
79
|
+
@patch('alibuild_helpers.clean.log')
|
|
80
|
+
def test_doClean(self, mock_log, mock_shutil, mock_path, mock_os, mock_glob):
|
|
81
|
+
mock_path.realpath.side_effect = lambda x: REALPATH_WITH_OBSOLETE_FILES[x]
|
|
82
|
+
mock_path.islink.side_effect = lambda x: "latest" in x
|
|
83
|
+
mock_os.readlink.side_effect = lambda x: READLINK_MOCKUP_DB[x]
|
|
84
|
+
|
|
85
|
+
files_to_delete = [
|
|
86
|
+
"sw/TMP",
|
|
87
|
+
"sw/INSTALLROOT",
|
|
88
|
+
"sw/TARS/osx_x86-64/store",
|
|
89
|
+
"sw/SOURCES",
|
|
90
|
+
"sw/BUILD/somethingtodelete",
|
|
91
|
+
"sw/osx_x86-64/b/v1",
|
|
92
|
+
"sw/osx_x86-64/b/v3",
|
|
93
|
+
]
|
|
94
|
+
remove_files_calls = list(map(call, files_to_delete))
|
|
95
|
+
files_delete_formatarg = "\n".join(files_to_delete)
|
|
96
|
+
|
|
97
|
+
mock_glob.glob.side_effect = lambda x: []
|
|
98
|
+
# To get rid of default entries like sw/TMP, sw/INSTALLROOT.
|
|
99
|
+
mock_path.exists.return_value = False
|
|
100
|
+
|
|
101
|
+
with self.assertRaises(SystemExit) as cm:
|
|
102
|
+
doClean(workDir="sw", architecture="osx_x86-64", aggressiveCleanup=True, dryRun=True)
|
|
103
|
+
self.assertEqual(cm.exception.code, 0)
|
|
104
|
+
mock_shutil.rmtree.assert_not_called()
|
|
105
|
+
mock_log.info.assert_called_with("Nothing to delete.")
|
|
106
|
+
mock_log.banner.assert_not_called()
|
|
107
|
+
|
|
108
|
+
mock_log.banner.reset_mock()
|
|
109
|
+
mock_log.info.reset_mock()
|
|
110
|
+
|
|
111
|
+
mock_glob.glob.side_effect = lambda x: GLOB_WITH_OBSOLETE_FILES[x]
|
|
112
|
+
mock_path.exists.return_value = True
|
|
113
|
+
|
|
114
|
+
with self.assertRaises(SystemExit) as cm:
|
|
115
|
+
doClean(workDir="sw", architecture="osx_x86-64", aggressiveCleanup=True, dryRun=True)
|
|
116
|
+
self.assertEqual(cm.exception.code, 0)
|
|
117
|
+
mock_shutil.rmtree.assert_not_called()
|
|
118
|
+
mock_log.banner.assert_called_with("This %s delete the following directories:\n%s",
|
|
119
|
+
"would", files_delete_formatarg)
|
|
120
|
+
mock_log.info.assert_called_with("--dry-run / -n specified. Doing nothing.")
|
|
121
|
+
|
|
122
|
+
mock_log.banner.reset_mock()
|
|
123
|
+
mock_log.info.reset_mock()
|
|
124
|
+
|
|
125
|
+
with self.assertRaises(SystemExit) as cm:
|
|
126
|
+
doClean(workDir="sw", architecture="osx_x86-64", aggressiveCleanup=True, dryRun=False)
|
|
127
|
+
self.assertEqual(cm.exception.code, 0)
|
|
128
|
+
self.assertEqual(mock_shutil.rmtree.mock_calls, remove_files_calls)
|
|
129
|
+
mock_log.banner.assert_called_with("This %s delete the following directories:\n%s",
|
|
130
|
+
"will", files_delete_formatarg)
|
|
131
|
+
mock_log.info.assert_not_called()
|
|
132
|
+
|
|
133
|
+
mock_log.banner.reset_mock()
|
|
134
|
+
mock_log.info.reset_mock()
|
|
135
|
+
mock_shutil.rmtree.reset_mock()
|
|
136
|
+
|
|
137
|
+
def failing_rmtree(directory):
|
|
138
|
+
raise OSError("sentinel exception")
|
|
139
|
+
|
|
140
|
+
mock_shutil.rmtree.side_effect = failing_rmtree
|
|
141
|
+
|
|
142
|
+
with self.assertRaises(SystemExit) as cm:
|
|
143
|
+
doClean(workDir="sw", architecture="osx_x86-64", aggressiveCleanup=True, dryRun=False)
|
|
144
|
+
self.assertEqual(cm.exception.code, 1)
|
|
145
|
+
# Make sure the function still attempts to delete all of the
|
|
146
|
+
# directories, even if some fail.
|
|
147
|
+
self.assertEqual(mock_shutil.rmtree.mock_calls, remove_files_calls)
|
|
148
|
+
mock_log.banner.assert_called_with("This %s delete the following directories:\n%s",
|
|
149
|
+
"will", files_delete_formatarg)
|
|
150
|
+
mock_log.info.assert_not_called()
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
if __name__ == '__main__':
|
|
154
|
+
unittest.main()
|
tests/test_cmd.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Assuming you are using the mock library to ... mock things
|
|
2
|
+
from unittest import mock
|
|
3
|
+
|
|
4
|
+
from alibuild_helpers.cmd import execute, DockerRunner
|
|
5
|
+
|
|
6
|
+
import unittest
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@mock.patch("alibuild_helpers.cmd.BASH", new="/bin/bash")
|
|
10
|
+
class CmdTestCase(unittest.TestCase):
|
|
11
|
+
@mock.patch("alibuild_helpers.cmd.debug")
|
|
12
|
+
def test_execute(self, mock_debug):
|
|
13
|
+
err = execute("echo foo", mock_debug)
|
|
14
|
+
self.assertEqual(err, 0)
|
|
15
|
+
self.assertEqual(mock_debug.mock_calls, [mock.call("%s", "foo")])
|
|
16
|
+
mock_debug.reset_mock()
|
|
17
|
+
err = execute("echoo 2> /dev/null", mock_debug)
|
|
18
|
+
self.assertEqual(err, 127)
|
|
19
|
+
self.assertEqual(mock_debug.mock_calls, [])
|
|
20
|
+
|
|
21
|
+
@mock.patch("alibuild_helpers.cmd.getoutput")
|
|
22
|
+
@mock.patch("alibuild_helpers.cmd.getstatusoutput")
|
|
23
|
+
def test_DockerRunner(self, mock_getstatusoutput, mock_getoutput):
|
|
24
|
+
mock_getoutput.side_effect = lambda cmd: "container-id\n"
|
|
25
|
+
with DockerRunner("image", ["extra arg"]) as getstatusoutput_docker:
|
|
26
|
+
mock_getoutput.assert_called_with(["docker", "run", "--detach", "--rm", "--entrypoint=",
|
|
27
|
+
"extra arg", "image", "sleep", "inf"])
|
|
28
|
+
getstatusoutput_docker("echo foo")
|
|
29
|
+
mock_getstatusoutput.assert_called_with(["docker", "container", "exec", "container-id", "bash", "-c", "echo foo"], cwd=None)
|
|
30
|
+
mock_getstatusoutput.assert_called_with("docker container kill container-id")
|
|
31
|
+
|
|
32
|
+
mock_getoutput.reset_mock()
|
|
33
|
+
mock_getstatusoutput.reset_mock()
|
|
34
|
+
with DockerRunner("") as getstatusoutput_docker:
|
|
35
|
+
mock_getoutput.assert_not_called()
|
|
36
|
+
getstatusoutput_docker("echo foo")
|
|
37
|
+
mock_getstatusoutput.assert_called_with("/bin/bash -c 'echo foo'", cwd=None)
|
|
38
|
+
mock_getstatusoutput.reset_mock()
|
|
39
|
+
mock_getstatusoutput.assert_not_called()
|
|
40
|
+
|
|
41
|
+
@mock.patch("alibuild_helpers.cmd.getoutput")
|
|
42
|
+
@mock.patch("alibuild_helpers.cmd.getstatusoutput")
|
|
43
|
+
def test_DockerRunner_with_env_vars(self, mock_getstatusoutput, mock_getoutput):
|
|
44
|
+
# Test that environment variables are properly injected into docker exec commands.
|
|
45
|
+
mock_getoutput.side_effect = lambda cmd: "container-id\n"
|
|
46
|
+
|
|
47
|
+
# Test with environment variables
|
|
48
|
+
extra_env = {"TEST_VAR": "test_value", "ANOTHER_VAR": "another_value"}
|
|
49
|
+
with DockerRunner("image", extra_env=extra_env) as getstatusoutput_docker:
|
|
50
|
+
# Verify container creation includes environment variables
|
|
51
|
+
mock_getoutput.assert_called_with(["docker", "run", "--detach",
|
|
52
|
+
"-e", "TEST_VAR=test_value",
|
|
53
|
+
"-e", "ANOTHER_VAR=another_value",
|
|
54
|
+
"--rm", "--entrypoint=", "image", "sleep", "inf"])
|
|
55
|
+
|
|
56
|
+
# Test that exec command includes environment variables
|
|
57
|
+
getstatusoutput_docker("echo test")
|
|
58
|
+
mock_getstatusoutput.assert_called_with(["docker", "container", "exec",
|
|
59
|
+
"-e", "TEST_VAR=test_value",
|
|
60
|
+
"-e", "ANOTHER_VAR=another_value",
|
|
61
|
+
"container-id", "bash", "-c", "echo test"], cwd=None)
|
|
62
|
+
|
|
63
|
+
# Test host execution with environment variables
|
|
64
|
+
mock_getoutput.reset_mock()
|
|
65
|
+
mock_getstatusoutput.reset_mock()
|
|
66
|
+
with DockerRunner("", extra_env=extra_env) as getstatusoutput_docker:
|
|
67
|
+
mock_getoutput.assert_not_called()
|
|
68
|
+
getstatusoutput_docker("echo test")
|
|
69
|
+
mock_getstatusoutput.assert_called_with("env TEST_VAR=test_value ANOTHER_VAR=another_value /bin/bash -c 'echo test'", cwd=None)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
if __name__ == '__main__':
|
|
73
|
+
unittest.main()
|