blob: 3acb47c8fc85ef7917692d07f4a807f20dd59e82 [file] [log] [blame]
# Copyright (c) 2018 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: Apache-2.0
from argparse import Namespace
from build import Build
from build_helpers import DEFAULT_BUILD_DIR
from pathlib import Path
import configparser
import os
import pytest
TEST_CASES = [
{'r': [],
's': None, 'c': None},
{'r': ['source_dir'],
's': 'source_dir', 'c': None},
{'r': ['source_dir', '--'],
's': 'source_dir', 'c': None},
{'r': ['source_dir', '--', 'cmake_opt'],
's': 'source_dir', 'c': ['cmake_opt']},
{'r': ['source_dir', '--', 'cmake_opt', 'cmake_opt2'],
's': 'source_dir', 'c': ['cmake_opt', 'cmake_opt2']},
{'r': ['thing_one', 'thing_two'],
's': 'thing_one', 'c': ['thing_two']},
{'r': ['thing_one', 'thing_two', 'thing_three'],
's': 'thing_one', 'c': ['thing_two', 'thing_three']},
{'r': ['--'],
's': None, 'c': None},
{'r': ['--', '--'],
's': None, 'c': ['--']},
{'r': ['--', 'cmake_opt'],
's': None, 'c': ['cmake_opt']},
{'r': ['--', 'cmake_opt', 'cmake_opt2'],
's': None, 'c': ['cmake_opt', 'cmake_opt2']},
{'r': ['--', 'cmake_opt', 'cmake_opt2', '--'],
's': None, 'c': ['cmake_opt', 'cmake_opt2', '--']},
{'r': ['--', 'cmake_opt', 'cmake_opt2', '--', 'tool_opt'],
's': None, 'c': ['cmake_opt', 'cmake_opt2', '--', 'tool_opt']},
{'r': ['--', 'cmake_opt', 'cmake_opt2', '--', 'tool_opt', 'tool_opt2'],
's': None, 'c': ['cmake_opt', 'cmake_opt2', '--', 'tool_opt',
'tool_opt2']},
{'r': ['--', 'cmake_opt', 'cmake_opt2', '--', 'tool_opt', 'tool_opt2',
'--'],
's': None, 'c': ['cmake_opt', 'cmake_opt2', '--', 'tool_opt', 'tool_opt2',
'--']},
]
ARGS = Namespace(board=None, build_dir=None, cmake=False, command='build',
force=False, help=None, target=None, verbose=3, version=False,
zephyr_base=None)
@pytest.mark.parametrize('test_case', TEST_CASES)
def test_parse_remainder(test_case):
b = Build()
b.args = Namespace()
b._parse_remainder(test_case['r'])
assert b.args.source_dir == test_case['s']
assert b.args.cmake_opts == test_case['c']
cwd = Path(os.getcwd())
DEFAULT_ARGS = Namespace(
build_dir=None,
board='native_sim',
source_dir=os.path.join("any", "project", "app")
)
BUILD_DIR_FMT_VALID = [
# dir_fmt, expected
('resolvable-{board}', cwd / f'resolvable-{DEFAULT_ARGS.board}'),
('my-dir-fmt-build-folder', cwd / 'my-dir-fmt-build-folder'),
]
BUILD_DIR_FMT_INVALID = [
'unresolvable-because-of-unknown-{board}',
'{invalid}'
]
def mock_dir_fmt_config(monkeypatch, dir_fmt):
config = configparser.ConfigParser()
config.add_section("build")
config.set("build", "dir-fmt", dir_fmt)
monkeypatch.setattr("build_helpers.config", config)
monkeypatch.setattr("build.config", config)
def mock_is_zephyr_build(monkeypatch, func):
monkeypatch.setattr("build_helpers.is_zephyr_build", func)
@pytest.fixture
def build_instance(monkeypatch):
"""Create a Build instance with default args and patched helpers."""
b = Build()
b.args = DEFAULT_ARGS
b.config_board = None
# mock configparser read method to bypass configs during test
monkeypatch.setattr(configparser.ConfigParser, "read", lambda self, filenames: None)
# mock os.makedirs to avoid filesystem operations during test
monkeypatch.setattr("os.makedirs", lambda *a, **kw: None)
# mock is_zephyr_build to always return False
monkeypatch.setattr("build_helpers.is_zephyr_build", lambda path: False)
# mock os.environ to make tests independent from environment variables
monkeypatch.setattr("os.environ", {})
return b
def test_build_dir_fallback(monkeypatch, build_instance):
"""Test: Fallback to DEFAULT_BUILD_DIR if no build dirs exist"""
b = build_instance
b._setup_build_dir()
assert Path(b.build_dir) == cwd / DEFAULT_BUILD_DIR
@pytest.mark.parametrize('test_case', BUILD_DIR_FMT_VALID)
def test_build_dir_fmt_is_used(monkeypatch, build_instance, test_case):
"""Test: build.dir-fmt is used if it is resolvable (no matter if it exists)"""
dir_fmt, expected = test_case
b = build_instance
# mock the config
mock_dir_fmt_config(monkeypatch, dir_fmt)
b._setup_build_dir()
assert Path(b.build_dir) == expected
@pytest.mark.parametrize('dir_fmt', BUILD_DIR_FMT_INVALID)
def test_build_dir_fmt_is_not_resolvable(monkeypatch, build_instance, dir_fmt):
"""Test: Fallback to DEFAULT_BUILD_DIR if build.dir-fmt is not resolvable."""
b = build_instance
b.args.board = None
# mock the config
mock_dir_fmt_config(monkeypatch, dir_fmt)
b._setup_build_dir()
assert Path(b.build_dir) == cwd / DEFAULT_BUILD_DIR
def test_dir_fmt_preferred_over_others(monkeypatch, build_instance):
"""Test: build.dir-fmt is preferred over cwd and DEFAULT_BUILD_DIR (if all exist)"""
b = build_instance
dir_fmt = "my-dir-fmt-build-folder"
# mock the config and is_zephyr_build
mock_dir_fmt_config(monkeypatch, dir_fmt)
mock_is_zephyr_build(monkeypatch,
lambda path: path in [dir_fmt, cwd, DEFAULT_BUILD_DIR])
b._setup_build_dir()
assert Path(b.build_dir) == cwd / dir_fmt
def test_non_existent_dir_fmt_preferred_over_others(monkeypatch, build_instance):
"""Test: build.dir-fmt is preferred over cwd and DEFAULT_BUILD_DIR (if it not exists)"""
b = build_instance
dir_fmt = "my-dir-fmt-build-folder"
# mock the config and is_zephyr_build
mock_dir_fmt_config(monkeypatch, dir_fmt)
mock_is_zephyr_build(monkeypatch,
lambda path: path in [cwd, DEFAULT_BUILD_DIR])
b._setup_build_dir()
assert Path(b.build_dir) == cwd / dir_fmt
def test_cwd_preferred_over_default_build_dir(monkeypatch, build_instance):
"""Test: cwd is preferred over DEFAULT_BUILD_DIR (if both exist)"""
b = build_instance
# mock is_zephyr_build
mock_is_zephyr_build(monkeypatch,
lambda path: path in [str(cwd), DEFAULT_BUILD_DIR])
b._setup_build_dir()
assert Path(b.build_dir) == cwd
@pytest.mark.parametrize('dir_fmt', BUILD_DIR_FMT_INVALID)
def test_cwd_preferred_over_non_resolvable_dir_fmt(monkeypatch, build_instance, dir_fmt):
"""Test: cwd is preferred over dir-fmt, if dir-fmt is not resolvable"""
b = build_instance
# mock the config and is_zephyr_build
mock_dir_fmt_config(monkeypatch, dir_fmt)
mock_is_zephyr_build(monkeypatch,
lambda path: path in [str(cwd)])
b._setup_build_dir()
assert Path(b.build_dir) == cwd
@pytest.mark.parametrize('test_case', BUILD_DIR_FMT_VALID)
def test_cwd_preferred_over_non_existent_dir_fmt(monkeypatch, build_instance, test_case):
"""Test: cwd is preferred over build.dir-fmt if cwd is a build directory and dir_fmt not"""
dir_fmt, _ = test_case
b = build_instance
# mock the config and is_zephyr_build
mock_dir_fmt_config(monkeypatch, dir_fmt)
mock_is_zephyr_build(monkeypatch,
lambda path: path in [str(cwd)])
b._setup_build_dir()
assert Path(b.build_dir) == cwd