-
Notifications
You must be signed in to change notification settings - Fork 8k
scripts: west_commands: extend build.dir-fmt
format args
#96421
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
thorsten-klein
wants to merge
1
commit into
zephyrproject-rtos:main
Choose a base branch
from
thorsten-klein:extend-dir-fmt-format-args
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+261
−11
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
# Copyright (c) 2018 Nordic Semiconductor ASA | ||
# | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
import configparser | ||
import copy | ||
import os | ||
from argparse import Namespace | ||
from pathlib import Path | ||
|
||
import pytest | ||
from build import Build | ||
|
||
ROOT = Path(Path.cwd().anchor) | ||
TEST_CWD = ROOT / 'path' / 'to' / 'my' / 'current' / 'cwd' | ||
TEST_CWD_RELATIVE_TO_ROOT = TEST_CWD.relative_to(ROOT) | ||
|
||
|
||
def setup_test_build(monkeypatch, test_args=None): | ||
# mock configparser read method to keep tests independent from actual configs | ||
monkeypatch.setattr(configparser.ConfigParser, 'read', lambda self, filenames: None) | ||
# mock os.makedirs to be independent from actual filesystem | ||
monkeypatch.setattr('os.makedirs', lambda *a, **kw: None) | ||
# mock west_topdir so that tests run independent from user machine | ||
monkeypatch.setattr('build.west_topdir', lambda *a, **kw: str(west_topdir)) | ||
# mock os.getcwd and Path.cwd to use TEST_CWD | ||
monkeypatch.setattr('os.getcwd', lambda *a, **kw: str(TEST_CWD)) | ||
monkeypatch.setattr('pathlib.Path.cwd', lambda *a, **kw: TEST_CWD) | ||
# mock os.environ to ignore all environment variables during test | ||
monkeypatch.setattr('os.environ', {}) | ||
|
||
# set up Build | ||
b = Build() | ||
|
||
# apply test args | ||
b.args = copy.copy(DEFAULT_TEST_ARGS) | ||
if test_args: | ||
for k, v in vars(test_args).items(): | ||
setattr(b.args, k, v) | ||
|
||
return b | ||
|
||
|
||
# Use a hardcoded west_topdir to ensure that the tests run independently | ||
# from the actual user machine | ||
west_topdir = ROOT / 'any' / 'west' / 'workspace' | ||
|
||
DEFAULT_TEST_ARGS = Namespace( | ||
board=None, source_dir=west_topdir / 'subdir' / 'project' / 'app', build_dir=None | ||
) | ||
|
||
TEST_CASES_GET_DIR_FMT_CONTEXT = [ | ||
# (test_args, source_dir, expected) | ||
# fallback to cwd in default case | ||
( | ||
{}, | ||
None, | ||
{ | ||
'board': None, | ||
'west_topdir': str(west_topdir), | ||
'app': TEST_CWD.name, | ||
'source_dir': str(TEST_CWD), | ||
'source_dir_workspace': str(TEST_CWD_RELATIVE_TO_ROOT), | ||
}, | ||
), | ||
# check for correct source_dir and source_dir_workspace (if inside west_topdir) | ||
( | ||
{}, | ||
west_topdir / 'my' / 'project', | ||
{ | ||
'board': None, | ||
'west_topdir': str(west_topdir), | ||
'app': 'project', | ||
'source_dir': str(west_topdir / 'my' / 'project'), | ||
'source_dir_workspace': str(Path('my') / 'project'), | ||
}, | ||
), | ||
# check for correct source_dir and source_dir_workspace (if outside west_topdir) | ||
( | ||
{}, | ||
ROOT / 'path' / 'to' / 'my-project', | ||
{ | ||
'board': None, | ||
'west_topdir': str(west_topdir), | ||
'app': 'my-project', | ||
'source_dir': str(ROOT / 'path' / 'to' / 'my-project'), | ||
'source_dir_workspace': str(Path('path') / 'to' / 'my-project'), | ||
}, | ||
), | ||
# check for correct board | ||
( | ||
Namespace(board='native_sim'), | ||
None, | ||
{ | ||
'board': 'native_sim', | ||
'west_topdir': str(west_topdir), | ||
'app': TEST_CWD.name, | ||
'source_dir': str(TEST_CWD), | ||
'source_dir_workspace': str(TEST_CWD_RELATIVE_TO_ROOT), | ||
}, | ||
), | ||
] | ||
|
||
|
||
@pytest.mark.parametrize('test_case', TEST_CASES_GET_DIR_FMT_CONTEXT) | ||
def test_get_dir_fmt_context(monkeypatch, test_case): | ||
# extract data from the test case | ||
test_args, source_dir, expected = test_case | ||
|
||
# set up and run _get_dir_fmt_context | ||
b = setup_test_build(monkeypatch, test_args) | ||
b.args.source_dir = source_dir | ||
actual = b._get_dir_fmt_context() | ||
assert expected == actual | ||
|
||
|
||
TEST_CASES_BUILD_DIR = [ | ||
# (config_build, test_args, expected) | ||
# default build directory if no args and dir-fmt are specified | ||
({}, None, Path('build')), | ||
# build_dir from args should always be preferred (if it is specified) | ||
({}, Namespace(build_dir='from-args'), Path('from-args')), | ||
({'dir-fmt': 'from-dir-fmt'}, Namespace(build_dir='from-args'), Path('from-args')), | ||
# build_dir is determined by resolving dir-fmt format string | ||
# must be able to resolve a simple string | ||
({'dir-fmt': 'from-dir-fmt'}, None, 'from-dir-fmt'), | ||
# must be able to resolve west_topdir | ||
({'dir-fmt': '{west_topdir}/build'}, None, west_topdir / 'build'), | ||
# must be able to resolve app | ||
({'dir-fmt': '{app}'}, None, 'app'), | ||
# must be able to resolve source_dir (when it is inside west workspace) | ||
( | ||
{'dir-fmt': '{source_dir}'}, | ||
None, | ||
# source_dir resolves to relative path (relative to cwd), so build | ||
# directory is depending on cwd and ends up outside 'build' | ||
os.path.relpath(DEFAULT_TEST_ARGS.source_dir, TEST_CWD), | ||
), | ||
# source_dir dir is outside west workspace, so it is absolute path | ||
( | ||
{'dir-fmt': '{source_dir}'}, | ||
Namespace(source_dir=ROOT / 'outside' / 'living' / 'app'), | ||
os.path.relpath(ROOT / 'outside' / 'living' / 'app', TEST_CWD), | ||
), | ||
# must be able to resolve source_dir_workspace (when source_dir is inside west workspace) | ||
({'dir-fmt': '{source_dir_workspace}'}, None, Path('subdir') / 'project' / 'app'), | ||
# must be able to resolve source_dir_workspace (when source_dir is outside west workspace) | ||
( | ||
{'dir-fmt': 'build/{source_dir_workspace}'}, | ||
Namespace(source_dir=ROOT / 'outside' / 'living' / 'app'), | ||
Path('build') / 'outside' / 'living' / 'app', | ||
), | ||
# must be able to resolve board (must be specified) | ||
({'dir-fmt': '{board}'}, Namespace(board='native_sim'), 'native_sim'), | ||
] | ||
|
||
|
||
@pytest.mark.parametrize('test_case', TEST_CASES_BUILD_DIR) | ||
def test_dir_fmt(monkeypatch, test_case): | ||
# extract data from the test case | ||
config_build, test_args, expected = test_case | ||
|
||
# apply given config_build | ||
config = configparser.ConfigParser() | ||
config.add_section("build") | ||
for k, v in config_build.items(): | ||
config.set('build', k, v) | ||
monkeypatch.setattr("build_helpers.config", config) | ||
monkeypatch.setattr("build.config", config) | ||
|
||
# set up and run _setup_build_dir | ||
b = setup_test_build(monkeypatch, test_args) | ||
b._setup_build_dir() | ||
|
||
# check for expected build-dir | ||
assert os.path.abspath(expected) == b.build_dir |
40 changes: 40 additions & 0 deletions
40
scripts/west_commands/tests/west_build/test_resolve_build_dir.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# Copyright (c) 2018 Nordic Semiconductor ASA | ||
# | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
from pathlib import Path | ||
|
||
import pytest | ||
from build_helpers import _resolve_build_dir | ||
|
||
cwd = Path.cwd() | ||
root = Path(cwd.anchor) | ||
TEST_CWD = root / 'path' / 'to' / 'my' / 'current' / 'cwd' | ||
|
||
TEST_CASES_RESOLVE_BUILD_DIR = [ | ||
# (fmt, kwargs, expected) | ||
# simple string (no format string) | ||
('simple/string', {}, 'simple/string'), | ||
# source_dir is inside cwd | ||
('{source_dir}', {'source_dir': TEST_CWD / 'subdir'}, 'subdir'), | ||
# source_dir is outside cwd | ||
('{source_dir}', {'source_dir': TEST_CWD / '..' / 'subdir'}, str(Path('..') / 'subdir')), | ||
# cwd is inside source dir | ||
('{source_dir}', {'source_dir': TEST_CWD / '..'}, ''), | ||
# source dir not resolvable by default | ||
('{source_dir}', {}, None), | ||
# invalid format arg | ||
('{invalid}', {}, None), | ||
# app is defined by default | ||
('{app}', {}, None), | ||
] | ||
|
||
|
||
@pytest.mark.parametrize('test_case', TEST_CASES_RESOLVE_BUILD_DIR) | ||
def test_resolve_build_dir(test_case): | ||
fmt, kwargs, expected = test_case | ||
|
||
# test both guess=True and guess=False | ||
for guess in [True, False]: | ||
actual = _resolve_build_dir(cwd=TEST_CWD, guess=guess, fmt=fmt, **kwargs) | ||
assert actual == expected |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.