Skip to content

Commit e31f37f

Browse files
committed
Enhance tests for 'sh' and 'bat' shells
The existing tests exercise much of the code for implementing colcon's shell subsystem, but it doesn't validate the results. If the platform supports the shell, we should check that the code for appending and prepending paths to lists function as intended.
1 parent 3310754 commit e31f37f

File tree

3 files changed

+352
-43
lines changed

3 files changed

+352
-43
lines changed

colcon_core/shell/template/prefix_util.py.em

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ def _remove_ending_separators():
377377
commands = []
378378
for name in env_state:
379379
# skip variables that already had values before this script started prepending
380-
if name in os.environ:
380+
if os.environ.get(name):
381381
continue
382382
commands += [
383383
FORMAT_STR_REMOVE_LEADING_SEPARATOR.format_map({'name': name}),

test/test_shell_bat.py

Lines changed: 169 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@
55
from pathlib import Path
66
import sys
77
from tempfile import TemporaryDirectory
8+
from unittest.mock import patch
89

910
from colcon_core import shell
11+
from colcon_core.location import get_relative_package_index_path
1012
from colcon_core.plugin_system import SkipExtensionException
13+
from colcon_core.shell import get_environment_variables
1114
from colcon_core.shell.bat import BatShell
15+
from colcon_core.shell.dsv import DsvShell
1216
import pytest
1317

1418
from .run_until_complete import run_until_complete
@@ -20,6 +24,7 @@ def test_extension():
2024
try:
2125
with TemporaryDirectory(prefix='test_colcon_') as prefix_path:
2226
_test_extension(Path(prefix_path))
27+
_test_prefix_script(Path(prefix_path))
2328
finally:
2429
shell.use_all_shell_extensions = use_all_shell_extensions
2530

@@ -39,33 +44,36 @@ def _test_extension(prefix_path):
3944
extension.create_prefix_script(prefix_path, False)
4045
assert (prefix_path / 'local_setup.bat').exists()
4146

47+
# create_hook_append_value
48+
append_hook_path = extension.create_hook_append_value(
49+
'append_env_hook_name', prefix_path, 'pkg_name',
50+
'APPEND_NAME', 'subdirectory')
51+
assert append_hook_path.exists()
52+
assert append_hook_path.name == 'append_env_hook_name.bat'
53+
content = append_hook_path.read_text()
54+
assert 'APPEND_NAME' in content
55+
56+
# create_hook_prepend_value
57+
prepend_hook_path = extension.create_hook_prepend_value(
58+
'prepend_env_hook_name', prefix_path, 'pkg_name',
59+
'PREPEND_NAME', 'subdirectory')
60+
assert prepend_hook_path.exists()
61+
assert prepend_hook_path.name == 'prepend_env_hook_name.bat'
62+
content = prepend_hook_path.read_text()
63+
assert 'PREPEND_NAME' in content
64+
4265
# create_package_script
4366
extension.create_package_script(
4467
prefix_path, 'pkg_name', [
45-
('hookA.bat', '/some/path/hookA.bat'),
68+
(append_hook_path.relative_to(prefix_path), ()),
69+
(prepend_hook_path.relative_to(prefix_path), ()),
4670
('hookB.other', '/some/path/hookB.other')])
4771
assert (prefix_path / 'share' / 'pkg_name' / 'package.bat').exists()
4872
content = (prefix_path / 'share' / 'pkg_name' / 'package.bat').read_text()
49-
assert 'hookA' in content
73+
assert append_hook_path.name in content
74+
assert prepend_hook_path.name in content
5075
assert 'hookB' not in content
5176

52-
# create_hook_append_value
53-
hook_path = extension.create_hook_append_value(
54-
'append_env_hook_name', prefix_path, 'pkg_name',
55-
'APPEND_NAME', 'append_subdirectory')
56-
assert hook_path.exists()
57-
assert hook_path.name == 'append_env_hook_name.bat'
58-
content = hook_path.read_text()
59-
assert 'APPEND_NAME' in content
60-
61-
# create_hook_prepend_value
62-
hook_path = extension.create_hook_prepend_value(
63-
'env_hook_name', prefix_path, 'pkg_name', 'NAME', 'subdirectory')
64-
assert hook_path.exists()
65-
assert hook_path.name == 'env_hook_name.bat'
66-
content = hook_path.read_text()
67-
assert 'NAME' in content
68-
6977
# generate_command_environment
7078
if sys.platform != 'win32':
7179
with pytest.raises(SkipExtensionException) as e:
@@ -93,3 +101,145 @@ def _test_extension(prefix_path):
93101
'task_name', prefix_path, {'dep': str(prefix_path)})
94102
env = run_until_complete(coroutine)
95103
assert isinstance(env, dict)
104+
105+
subdirectory_path = str(prefix_path / 'subdirectory')
106+
107+
# validate appending/prepending without existing values
108+
with patch.dict(os.environ) as env_patch:
109+
env_patch.pop('APPEND_NAME', None)
110+
env_patch.pop('PREPEND_NAME', None)
111+
coroutine = extension.generate_command_environment(
112+
'task_name', prefix_path, {'pkg_name': str(prefix_path)})
113+
env = run_until_complete(coroutine)
114+
assert env.get('APPEND_NAME') == subdirectory_path
115+
assert env.get('PREPEND_NAME') == subdirectory_path
116+
117+
# validate appending/prepending with existing values
118+
with patch.dict(os.environ, {
119+
'APPEND_NAME': 'control',
120+
'PREPEND_NAME': 'control',
121+
}):
122+
coroutine = extension.generate_command_environment(
123+
'task_name', prefix_path, {'pkg_name': str(prefix_path)})
124+
env = run_until_complete(coroutine)
125+
assert env.get('APPEND_NAME') == os.pathsep.join((
126+
'control',
127+
subdirectory_path,
128+
))
129+
assert env.get('PREPEND_NAME') == os.pathsep.join((
130+
subdirectory_path,
131+
'control',
132+
))
133+
134+
# validate appending/prepending unique values
135+
with patch.dict(os.environ, {
136+
'APPEND_NAME': os.pathsep.join((subdirectory_path, 'control')),
137+
'PREPEND_NAME': os.pathsep.join(('control', subdirectory_path)),
138+
}):
139+
coroutine = extension.generate_command_environment(
140+
'task_name', prefix_path, {'pkg_name': str(prefix_path)})
141+
env = run_until_complete(coroutine)
142+
# Expect no change, value already appears earlier in the list
143+
assert env.get('APPEND_NAME') == os.pathsep.join((
144+
subdirectory_path,
145+
'control',
146+
))
147+
# Expect value to be *moved* to the front of the list
148+
assert env.get('PREPEND_NAME') == os.pathsep.join((
149+
subdirectory_path,
150+
'control',
151+
))
152+
153+
154+
def _test_prefix_script(prefix_path):
155+
extension = BatShell()
156+
157+
# BatShell requires the (non-primary) DsvShell extension as well
158+
dsv_extension = DsvShell()
159+
160+
# create_hook_append_value
161+
append_hook_path = dsv_extension.create_hook_append_value(
162+
'append_env_hook_name', prefix_path, 'pkg_name',
163+
'APPEND_NAME', 'subdirectory')
164+
assert append_hook_path.exists()
165+
assert append_hook_path.name == 'append_env_hook_name.dsv'
166+
content = append_hook_path.read_text()
167+
assert 'APPEND_NAME' in content
168+
169+
# create_hook_prepend_value
170+
prepend_hook_path = dsv_extension.create_hook_prepend_value(
171+
'prepend_env_hook_name', prefix_path, 'pkg_name',
172+
'PREPEND_NAME', 'subdirectory')
173+
assert prepend_hook_path.exists()
174+
assert prepend_hook_path.name == 'prepend_env_hook_name.dsv'
175+
content = prepend_hook_path.read_text()
176+
assert 'PREPEND_NAME' in content
177+
178+
# mark package as installed
179+
package_index = prefix_path / get_relative_package_index_path()
180+
package_index.mkdir(parents=True)
181+
(package_index / 'pkg_name').write_text('')
182+
183+
# create_package_script
184+
dsv_extension.create_package_script(
185+
prefix_path, 'pkg_name', [
186+
(append_hook_path.relative_to(prefix_path), ()),
187+
(prepend_hook_path.relative_to(prefix_path), ())])
188+
assert (prefix_path / 'share' / 'pkg_name' / 'package.dsv').exists()
189+
content = (prefix_path / 'share' / 'pkg_name' / 'package.dsv').read_text()
190+
assert append_hook_path.name in content
191+
assert prepend_hook_path.name in content
192+
193+
# create_prefix_script
194+
extension.create_prefix_script(prefix_path, True)
195+
prefix_script = prefix_path / 'local_setup.bat'
196+
prefix_script.exists()
197+
assert (prefix_path / '_local_setup_util_bat.py').exists()
198+
199+
if sys.platform == 'win32':
200+
subdirectory_path = str(prefix_path / 'subdirectory')
201+
202+
# validate appending/prepending without existing values
203+
with patch.dict(os.environ, {
204+
'APPEND_NAME': '',
205+
'PREPEND_NAME': '',
206+
}):
207+
coroutine = get_environment_variables([prefix_script, '&&', 'set'])
208+
env = run_until_complete(coroutine)
209+
assert env.get('APPEND_NAME') == subdirectory_path
210+
assert env.get('PREPEND_NAME') == subdirectory_path
211+
212+
# validate appending/prepending with existing values
213+
with patch.dict(os.environ, {
214+
'APPEND_NAME': 'control',
215+
'PREPEND_NAME': 'control',
216+
}):
217+
coroutine = get_environment_variables([prefix_script, '&&', 'set'])
218+
env = run_until_complete(coroutine)
219+
assert env.get('APPEND_NAME') == os.pathsep.join((
220+
'control',
221+
subdirectory_path,
222+
))
223+
assert env.get('PREPEND_NAME') == os.pathsep.join((
224+
subdirectory_path,
225+
'control',
226+
))
227+
228+
# validate appending/prepending unique values
229+
with patch.dict(os.environ, {
230+
'APPEND_NAME': os.pathsep.join((subdirectory_path, 'control')),
231+
'PREPEND_NAME': os.pathsep.join(('control', subdirectory_path)),
232+
}):
233+
coroutine = get_environment_variables([prefix_script, '&&', 'set'])
234+
env = run_until_complete(coroutine)
235+
# Expect no change, value already appears earlier in the list
236+
assert env.get('APPEND_NAME') == os.pathsep.join((
237+
subdirectory_path,
238+
'control',
239+
))
240+
# TODO: The DsvShell behavior doesn't align with BatShell!
241+
# ~~Expect value to be *moved* to the front of the list~~
242+
assert env.get('PREPEND_NAME') == os.pathsep.join((
243+
'control',
244+
subdirectory_path,
245+
))

0 commit comments

Comments
 (0)