|
2 | 2 | # |
3 | 3 | # SPDX-License-Identifier: Apache-2.0 |
4 | 4 |
|
| 5 | +import contextlib |
5 | 6 | import os |
6 | 7 | import platform |
7 | 8 | import shutil |
|
13 | 14 |
|
14 | 15 | import pytest |
15 | 16 |
|
16 | | -from west import configuration as config |
17 | | - |
18 | 17 | GIT = shutil.which('git') |
19 | 18 |
|
20 | 19 | # Git capabilities are discovered at runtime in |
|
62 | 61 | WINDOWS = platform.system() == 'Windows' |
63 | 62 |
|
64 | 63 | # |
65 | | -# Test fixtures |
| 64 | +# Contextmanager |
| 65 | +# |
| 66 | + |
| 67 | + |
| 68 | +@contextlib.contextmanager |
| 69 | +def update_env(env: dict[str, str | None]): |
| 70 | + """ |
| 71 | + Temporarily update the process environment variables. |
| 72 | + This context manager updates `os.environ` with the key-value pairs |
| 73 | + provided in the `env` dictionary for the duration of the `with` block. |
| 74 | + The existing environment is preserved and fully restored when the block |
| 75 | + exits. If the value is set to None, the environment variable is unset. |
| 76 | + """ |
| 77 | + env_bak = dict(os.environ) |
| 78 | + env_vars = {} |
| 79 | + for k, v in env.items(): |
| 80 | + # unset if value is None |
| 81 | + if v is None and k in os.environ: |
| 82 | + del os.environ[k] |
| 83 | + # set env variable to new value only if v is not None |
| 84 | + elif v is not None: |
| 85 | + env_vars[k] = v |
| 86 | + # apply the new environment |
| 87 | + os.environ.update(env_vars) |
| 88 | + try: |
| 89 | + yield |
| 90 | + finally: |
| 91 | + # reset to previous environment |
| 92 | + os.environ.clear() |
| 93 | + os.environ.update(env_bak) |
| 94 | + |
| 95 | + |
| 96 | +@contextlib.contextmanager |
| 97 | +def chdir(path): |
| 98 | + """ |
| 99 | + Temporarily change the current working directory. |
| 100 | + This context manager changes the current working directory to `path` |
| 101 | + for the duration of the `with` block. After the block exits, the |
| 102 | + working directory is restored to its original value. |
| 103 | + """ |
| 104 | + oldpwd = os.getcwd() |
| 105 | + os.chdir(path) |
| 106 | + try: |
| 107 | + yield |
| 108 | + finally: |
| 109 | + os.chdir(oldpwd) |
| 110 | + |
| 111 | + |
| 112 | +# |
| 113 | +# Test fixtures (autouse=True) |
66 | 114 | # |
67 | 115 |
|
68 | 116 |
|
@@ -90,6 +138,35 @@ def _check_git_capabilities(tmpdir_factory): |
90 | 138 | pass |
91 | 139 |
|
92 | 140 |
|
| 141 | +@pytest.fixture(autouse=True) |
| 142 | +def independent_global_and_system_config(tmpdir_factory): |
| 143 | + # Fixture to ensure that the user's actual global and system configuration |
| 144 | + # files are neither used nor touched during test. |
| 145 | + # |
| 146 | + # We also set ZEPHYR_BASE (to avoid complaints in subcommand |
| 147 | + # stderr), but to a spurious location (so that attempts to read |
| 148 | + # from inside of it are caught here). |
| 149 | + # |
| 150 | + tmpdir = Path(tmpdir_factory.mktemp("test-configs")) |
| 151 | + |
| 152 | + # config paths |
| 153 | + system = tmpdir / 'config.system' |
| 154 | + glbl = tmpdir / 'config.global' |
| 155 | + |
| 156 | + # run with environment variables set |
| 157 | + with update_env({ |
| 158 | + 'WEST_CONFIG_SYSTEM': str(system), |
| 159 | + 'WEST_CONFIG_GLOBAL': str(glbl), |
| 160 | + 'ZEPHYR_BASE': str(tmpdir / 'no-zephyr-here'), |
| 161 | + }): |
| 162 | + yield |
| 163 | + |
| 164 | + |
| 165 | +# |
| 166 | +# Test fixtures |
| 167 | +# |
| 168 | + |
| 169 | + |
93 | 170 | @pytest.fixture(scope='session') |
94 | 171 | def _session_repos(tmp_path_factory): |
95 | 172 | '''Just a helper, do not use directly.''' |
@@ -254,64 +331,20 @@ def west_init_tmpdir(repos_tmpdir): |
254 | 331 | @pytest.fixture |
255 | 332 | def config_tmpdir(tmpdir): |
256 | 333 | # Fixture for running from a temporary directory with |
257 | | - # environmental overrides in place so all configuration files |
258 | | - # live inside of it. This makes sure we don't touch |
259 | | - # the user's actual files. |
260 | | - # |
261 | | - # We also set ZEPHYR_BASE (to avoid complaints in subcommand |
262 | | - # stderr), but to a spurious location (so that attempts to read |
263 | | - # from inside of it are caught here). |
| 334 | + # environmental overrides in place so local configuration file |
| 335 | + # live inside of it. This ensures we don't touch the user's local config. |
264 | 336 | # |
265 | 337 | # Using this makes the tests run faster than if we used |
266 | 338 | # west_init_tmpdir from conftest.py, and also ensures that the |
267 | 339 | # configuration code doesn't depend on features like the existence |
268 | 340 | # of a manifest file, helping separate concerns. |
269 | | - system = tmpdir / 'config.system' |
270 | | - glbl = tmpdir / 'config.global' |
271 | | - local = tmpdir / 'config.local' |
272 | | - |
273 | | - os.environ['ZEPHYR_BASE'] = str(tmpdir.join('no-zephyr-here')) |
274 | | - os.environ['WEST_CONFIG_SYSTEM'] = str(system) |
275 | | - os.environ['WEST_CONFIG_GLOBAL'] = str(glbl) |
276 | | - os.environ['WEST_CONFIG_LOCAL'] = str(local) |
277 | 341 |
|
278 | | - # Make sure our environment variables (as well as other topdirs) |
279 | | - # are respected from tmpdir, and we aren't going to touch the |
280 | | - # user's real files. |
281 | | - start_dir = os.getcwd() |
282 | | - tmpdir.chdir() |
| 342 | + # determine a local config in tmp dir |
| 343 | + local_config = tmpdir / 'config.local' |
283 | 344 |
|
284 | | - try: |
285 | | - assert config._location(config.ConfigFile.SYSTEM) == str(system) |
286 | | - assert config._location(config.ConfigFile.GLOBAL) == str(glbl) |
287 | | - td = tmpdir / 'test-topdir' |
288 | | - td.ensure(dir=True) |
289 | | - (td / '.west').ensure(dir=True) |
290 | | - (td / '.west' / 'config').ensure(file=True) |
291 | | - assert config._location(config.ConfigFile.LOCAL) == str(local) |
292 | | - assert config._location(config.ConfigFile.LOCAL, topdir=str(td)) == str(local) |
293 | | - td.remove(rec=1) |
294 | | - assert not td.exists() |
295 | | - |
296 | | - assert not local.exists() |
297 | | - |
298 | | - # All clear: switch to the temporary directory and run the test. |
| 345 | + # run the test within tmpdir and with env variable set |
| 346 | + with chdir(tmpdir), update_env({'WEST_CONFIG_LOCAL': str(local_config)}): |
299 | 347 | yield tmpdir |
300 | | - finally: |
301 | | - # Go back to where we started, for repeatability of results. |
302 | | - os.chdir(start_dir) |
303 | | - |
304 | | - # Clean up after ourselves so other test cases don't know |
305 | | - # about this tmpdir. It's OK if test cases deleted these |
306 | | - # settings already. |
307 | | - if 'ZEPHYR_BASE' in os.environ: |
308 | | - del os.environ['ZEPHYR_BASE'] |
309 | | - if 'WEST_CONFIG_SYSTEM' in os.environ: |
310 | | - del os.environ['WEST_CONFIG_SYSTEM'] |
311 | | - if 'WEST_CONFIG_GLOBAL' in os.environ: |
312 | | - del os.environ['WEST_CONFIG_GLOBAL'] |
313 | | - if 'WEST_CONFIG_LOCAL' in os.environ: |
314 | | - del os.environ['WEST_CONFIG_LOCAL'] |
315 | 348 |
|
316 | 349 |
|
317 | 350 | # |
|
0 commit comments