blob: 7f6433dd667d97b49a3abc1b1b6862fe96f45658 [file] [log] [blame]
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Pylint doesn't play well with fixtures and dependency injection from pytest
# pylint: disable=redefined-outer-name
import os
import textwrap
import pytest
from buildstream import _yaml
from buildstream.exceptions import ErrorDomain, LoadErrorReason
from buildstream._testing import cli # pylint: disable=unused-import
from buildstream._testing import create_repo
from tests.testutils import generate_junction
# Project directory
DATA_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "include")
@pytest.mark.datafiles(DATA_DIR)
def test_include_project_file(cli, datafiles):
project = os.path.join(str(datafiles), "file")
result = cli.run(project=project, args=["show", "--deps", "none", "--format", "%{vars}", "element.bst"])
result.assert_success()
loaded = _yaml.load_data(result.output)
assert loaded.get_bool("included")
def test_include_missing_file(cli, tmpdir):
tmpdir.join("project.conf").write('{"name": "test", "min-version": "2.0"}')
element = tmpdir.join("include_missing_file.bst")
# Normally we would use dicts and _yaml.roundtrip_dump to write such things, but here
# we want to be sure of a stable line and column number.
element.write(
textwrap.dedent(
"""
kind: manual
"(@)":
- nosuch.yaml
"""
).strip()
)
result = cli.run(project=str(tmpdir), args=["show", str(element.basename)])
result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.MISSING_FILE)
# Make sure the root cause provenance is in the output.
assert "include_missing_file.bst [line 4 column 4]" in result.stderr
def test_include_dir(cli, tmpdir):
tmpdir.join("project.conf").write('{"name": "test", "min-version": "2.0"}')
tmpdir.mkdir("subdir")
element = tmpdir.join("include_dir.bst")
# Normally we would use dicts and _yaml.roundtrip_dump to write such things, but here
# we want to be sure of a stable line and column number.
element.write(
textwrap.dedent(
"""
kind: manual
"(@)":
- subdir/
"""
).strip()
)
result = cli.run(project=str(tmpdir), args=["show", str(element.basename)])
result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.LOADING_DIRECTORY)
# Make sure the root cause provenance is in the output.
assert "include_dir.bst [line 4 column 4]" in result.stderr
@pytest.mark.datafiles(DATA_DIR)
def test_include_junction_file(cli, tmpdir, datafiles):
project = os.path.join(str(datafiles), "junction")
generate_junction(
tmpdir, os.path.join(project, "subproject"), os.path.join(project, "junction.bst"), store_ref=True
)
result = cli.run(project=project, args=["show", "--deps", "none", "--format", "%{vars}", "element.bst"])
result.assert_success()
loaded = _yaml.load_data(result.output)
assert loaded.get_bool("included")
@pytest.mark.datafiles(DATA_DIR)
def test_include_junction_options(cli, datafiles):
project = os.path.join(str(datafiles), "options")
result = cli.run(
project=project,
args=["-o", "build_arch", "x86_64", "show", "--deps", "none", "--format", "%{vars}", "element.bst"],
)
result.assert_success()
loaded = _yaml.load_data(result.output)
assert loaded.get_str("build_arch") == "x86_64"
@pytest.mark.datafiles(DATA_DIR)
def test_junction_element_partial_project_project(cli, tmpdir, datafiles):
"""
Junction elements never depend on fully include processed project.
"""
project = os.path.join(str(datafiles), "junction")
subproject_path = os.path.join(project, "subproject")
junction_path = os.path.join(project, "junction.bst")
repo = create_repo("tar", str(tmpdir))
ref = repo.create(subproject_path)
element = {"kind": "junction", "sources": [repo.source_config(ref=ref)]}
_yaml.roundtrip_dump(element, junction_path)
result = cli.run(project=project, args=["show", "--deps", "none", "--format", "%{vars}", "junction.bst"])
result.assert_success()
loaded = _yaml.load_data(result.output)
assert loaded.get_str("included", default=None) is None
@pytest.mark.datafiles(DATA_DIR)
def test_junction_element_not_partial_project_file(cli, tmpdir, datafiles):
"""
Junction elements never depend on fully include processed project.
"""
project = os.path.join(str(datafiles), "file_with_subproject")
subproject_path = os.path.join(project, "subproject")
junction_path = os.path.join(project, "junction.bst")
repo = create_repo("tar", str(tmpdir))
ref = repo.create(subproject_path)
element = {"kind": "junction", "sources": [repo.source_config(ref=ref)]}
_yaml.roundtrip_dump(element, junction_path)
result = cli.run(project=project, args=["show", "--deps", "none", "--format", "%{vars}", "junction.bst"])
result.assert_success()
loaded = _yaml.load_data(result.output)
assert loaded.get_str("included", default=None) is not None
@pytest.mark.datafiles(DATA_DIR)
def test_include_element_overrides(cli, datafiles):
project = os.path.join(str(datafiles), "overrides")
result = cli.run(project=project, args=["show", "--deps", "none", "--format", "%{vars}", "element.bst"])
result.assert_success()
loaded = _yaml.load_data(result.output)
assert loaded.get_str("manual_main_override", default=None) is not None
assert loaded.get_str("manual_included_override", default=None) is not None
@pytest.mark.datafiles(DATA_DIR)
def test_include_element_overrides_composition(cli, datafiles):
project = os.path.join(str(datafiles), "overrides")
result = cli.run(project=project, args=["show", "--deps", "none", "--format", "%{config}", "element.bst"])
result.assert_success()
loaded = _yaml.load_data(result.output)
assert loaded.get_str_list("build-commands") == ["first", "second"]
@pytest.mark.datafiles(DATA_DIR)
def test_list_overide_does_not_fail_upon_first_composition(cli, datafiles):
project = os.path.join(str(datafiles), "eventual_overrides")
result = cli.run(project=project, args=["show", "--deps", "none", "--format", "%{public}", "element.bst"])
result.assert_success()
loaded = _yaml.load_data(result.output)
# Assert that the explicitly overwritten public data is present
bst = loaded.get_mapping("bst")
assert "foo-commands" in bst
assert bst.get_str_list("foo-commands") == ["need", "this"]
@pytest.mark.datafiles(DATA_DIR)
def test_include_element_overrides_sub_include(cli, datafiles):
project = os.path.join(str(datafiles), "sub-include")
result = cli.run(project=project, args=["show", "--deps", "none", "--format", "%{vars}", "element.bst"])
result.assert_success()
loaded = _yaml.load_data(result.output)
assert loaded.get_str("included", default=None) is not None
@pytest.mark.datafiles(DATA_DIR)
def test_junction_do_not_use_included_overrides(cli, tmpdir, datafiles):
project = os.path.join(str(datafiles), "overrides-junction")
generate_junction(
tmpdir, os.path.join(project, "subproject"), os.path.join(project, "junction.bst"), store_ref=True
)
result = cli.run(project=project, args=["show", "--deps", "none", "--format", "%{vars}", "junction.bst"])
result.assert_success()
loaded = _yaml.load_data(result.output)
assert loaded.get_str("main_override", default=None) is not None
assert loaded.get_str("included_override", default=None) is None
@pytest.mark.datafiles(DATA_DIR)
def test_conditional_in_fragment(cli, datafiles):
project = os.path.join(str(datafiles), "conditional")
result = cli.run(
project=project,
args=["-o", "build_arch", "x86_64", "show", "--deps", "none", "--format", "%{vars}", "element.bst"],
)
result.assert_success()
loaded = _yaml.load_data(result.output)
assert loaded.get_str("size") == "8"
@pytest.mark.parametrize(
"project_dir",
[
"conditional-conflicts-project",
"conditional-conflicts-element",
"conditional-conflicts-options-included",
"conditional-conflicts-complex",
"conditional-conflicts-toplevel-precedence",
],
)
@pytest.mark.datafiles(DATA_DIR)
def test_preserve_conditionals(cli, datafiles, project_dir):
project = os.path.join(str(datafiles), project_dir)
result = cli.run(
project=project,
args=["-o", "build_arch", "i586", "show", "--deps", "none", "--format", "%{vars}", "element.bst"],
)
result.assert_success()
loaded = _yaml.load_data(result.output)
assert loaded.get_str("enable-work-around") == "true"
assert loaded.get_str("size") == "4"
@pytest.mark.datafiles(DATA_DIR)
def test_inner(cli, datafiles):
project = os.path.join(str(datafiles), "inner")
result = cli.run(
project=project,
args=["-o", "build_arch", "x86_64", "show", "--deps", "none", "--format", "%{vars}", "element.bst"],
)
result.assert_success()
loaded = _yaml.load_data(result.output)
assert loaded.get_str("build_arch") == "x86_64"
@pytest.mark.datafiles(DATA_DIR)
def test_recursive_include(cli, datafiles):
project = os.path.join(str(datafiles), "recursive")
result = cli.run(project=project, args=["show", "--deps", "none", "--format", "%{vars}", "element.bst"])
result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.RECURSIVE_INCLUDE)
assert "line 2 column 2" in result.stderr
@pytest.mark.datafiles(DATA_DIR)
def test_local_to_junction(cli, tmpdir, datafiles):
project = os.path.join(str(datafiles), "local_to_junction")
generate_junction(
tmpdir, os.path.join(project, "subproject"), os.path.join(project, "junction.bst"), store_ref=True
)
result = cli.run(project=project, args=["show", "--deps", "none", "--format", "%{vars}", "element.bst"])
result.assert_success()
loaded = _yaml.load_data(result.output)
assert loaded.get_bool("included")
@pytest.mark.datafiles(DATA_DIR)
def test_option_from_junction(cli, tmpdir, datafiles):
project = os.path.join(str(datafiles), "junction_options")
generate_junction(
tmpdir,
os.path.join(project, "subproject"),
os.path.join(project, "junction.bst"),
store_ref=True,
options={"local_option": "set"},
)
result = cli.run(project=project, args=["show", "--deps", "none", "--format", "%{vars}", "element.bst"])
result.assert_success()
loaded = _yaml.load_data(result.output)
assert not loaded.get_bool("is-default")
@pytest.mark.datafiles(DATA_DIR)
def test_option_from_junction_element(cli, tmpdir, datafiles):
project = os.path.join(str(datafiles), "junction_options_element")
generate_junction(
tmpdir,
os.path.join(project, "subproject"),
os.path.join(project, "junction.bst"),
store_ref=True,
options={"local_option": "set"},
)
result = cli.run(project=project, args=["show", "--deps", "none", "--format", "%{vars}", "element.bst"])
result.assert_success()
loaded = _yaml.load_data(result.output)
assert not loaded.get_bool("is-default")
@pytest.mark.datafiles(DATA_DIR)
def test_option_from_deep_junction(cli, tmpdir, datafiles):
project = os.path.join(str(datafiles), "junction_options_deep")
junction_repo_a = os.path.join(tmpdir, "a")
junction_repo_b = os.path.join(tmpdir, "b")
generate_junction(
junction_repo_a,
os.path.join(project, "subproject-2"),
os.path.join(project, "subproject-1", "junction-2.bst"),
store_ref=True,
options={"local_option": "set"},
)
generate_junction(
junction_repo_b,
os.path.join(project, "subproject-1"),
os.path.join(project, "junction-1.bst"),
store_ref=True,
)
result = cli.run(project=project, args=["show", "--deps", "none", "--format", "%{vars}", "element.bst"])
result.assert_success()
loaded = _yaml.load_data(result.output)
assert not loaded.get_bool("is-default")
@pytest.mark.datafiles(DATA_DIR)
def test_include_full_path(cli, tmpdir, datafiles):
project = os.path.join(str(datafiles), "full_path")
result = cli.run(project=project, args=["show", "--deps", "none", "--format", "%{vars}", "element.bst"])
result.assert_success()
loaded = _yaml.load_data(result.output)
assert loaded.get_str("bar") == "red"
assert loaded.get_str("foo") == "blue"
@pytest.mark.datafiles(DATA_DIR)
def test_include_invalid_full_path(cli, tmpdir, datafiles):
project = os.path.join(str(datafiles), "full_path")
result = cli.run(project=project, args=["show", "--deps", "none", "--format", "%{vars}", "invalid.bst"])
result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.MISSING_FILE)
# Make sure the root cause provenance is in the output.
assert "invalid.bst [line 4 column 7]" in result.stderr