blob: 88b5569b05aedc03e9dbcf55f69bd5e93b9aea0e [file] [log] [blame]
# Pylint doesn't play well with fixtures and dependency injection from pytest
# pylint: disable=redefined-outer-name
import os
import pytest
from buildstream import _yaml
from buildstream.testing import cli # pylint: disable=unused-import
from buildstream.exceptions import ErrorDomain, LoadErrorReason
DATA_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "link",)
#
# Test links to elements, this tests both specifying the link as
# the main target, and also as a dependency of the main target.
#
@pytest.mark.datafiles(DATA_DIR)
@pytest.mark.parametrize("target", ["target.bst", "hello-link.bst"])
def test_simple_link(cli, tmpdir, datafiles, target):
project = os.path.join(str(datafiles), "simple")
checkoutdir = os.path.join(str(tmpdir), "checkout")
# Build, checkout
result = cli.run(project=project, args=["build", target])
result.assert_success()
result = cli.run(project=project, args=["artifact", "checkout", target, "--directory", checkoutdir])
result.assert_success()
# Check that the checkout contains the expected files from sub-sub-project
assert os.path.exists(os.path.join(checkoutdir, "hello.txt"))
#
# Test links to elements, this tests both specifying the link as
# the main target, and also as a dependency of the main target, while
# also using a conditional statement in the link
#
@pytest.mark.datafiles(DATA_DIR)
@pytest.mark.parametrize("target", ["target.bst", "target-link.bst"])
@pytest.mark.parametrize("greeting,expected_file", [("hello", "hello.txt"), ("goodbye", "goodbye.txt")])
def test_conditional_link(cli, tmpdir, datafiles, target, greeting, expected_file):
project = os.path.join(str(datafiles), "conditional")
checkoutdir = os.path.join(str(tmpdir), "checkout")
# Build, checkout
result = cli.run(project=project, args=["-o", "greeting", greeting, "build", target])
result.assert_success()
result = cli.run(
project=project, args=["-o", "greeting", greeting, "artifact", "checkout", target, "--directory", checkoutdir]
)
result.assert_success()
# Check that the checkout contains the expected files from sub-sub-project
assert os.path.exists(os.path.join(checkoutdir, expected_file))
#
# Test links to junctions from local projects and subprojects
#
@pytest.mark.datafiles(DATA_DIR)
@pytest.mark.parametrize(
"target", ["target-local.bst", "target-nested.bst", "full-path-link.bst", "target-full-path.bst"]
)
def test_simple_junctions(cli, tmpdir, datafiles, target):
project = os.path.join(str(datafiles), "simple-junctions")
checkoutdir = os.path.join(str(tmpdir), "checkout")
# Build, checkout
result = cli.run(project=project, args=["build", target])
result.assert_success()
result = cli.run(project=project, args=["artifact", "checkout", target, "--directory", checkoutdir])
result.assert_success()
# Check that the checkout contains the expected files from sub-sub-project
assert os.path.exists(os.path.join(checkoutdir, "hello.txt"))
#
# Test links which resolve junction targets conditionally
#
@pytest.mark.datafiles(DATA_DIR)
@pytest.mark.parametrize("greeting,expected_file", [("hello", "hello.txt"), ("goodbye", "goodbye.txt")])
def test_conditional_junctions(cli, tmpdir, datafiles, greeting, expected_file):
project = os.path.join(str(datafiles), "conditional-junctions")
checkoutdir = os.path.join(str(tmpdir), "checkout")
# Build, checkout
result = cli.run(project=project, args=["-o", "greeting", greeting, "build", "target.bst"])
result.assert_success()
result = cli.run(
project=project,
args=["-o", "greeting", greeting, "artifact", "checkout", "target.bst", "--directory", checkoutdir],
)
result.assert_success()
# Check that the checkout contains the expected files from sub-sub-project
assert os.path.exists(os.path.join(checkoutdir, expected_file))
#
# Tests links which refer to non-existing elements or junctions
#
@pytest.mark.datafiles(DATA_DIR)
@pytest.mark.parametrize(
"target,provenance",
[
# Target is a link to a non-existing local element
("link-target.bst", "link-target.bst [line 4 column 10]"),
# Target is a stack depending on a link to a non-existing local element
("depends-on-link-target.bst", "link-target.bst [line 4 column 10]",),
# Depends on non-existing subproject element, via a local link
("linked-local-junction-target.bst", "linked-local-junction-target.bst [line 4 column 2]",),
# Depends on non-existing subsubproject element, via a local link
("linked-nested-junction-target.bst", "linked-nested-junction-target.bst [line 4 column 2]",),
# Depends on an element via a link to a non-existing local junction
("linked-local-junction.bst", "subproject-link-notfound.bst [line 4 column 10]",),
# Depends on an element via a link to a non-existing subproject junction
("linked-nested-junction.bst", "subsubproject-link-notfound.bst [line 4 column 10]",),
# Target is a link to a non-existing nested element referred to with a full path
("link-full-path.bst", "link-full-path.bst [line 4 column 10]"),
# Target depends on a link to a non-existing nested element referred to with a full path
("target-full-path.bst", "link-full-path.bst [line 4 column 10]"),
],
)
def test_link_not_found(cli, tmpdir, datafiles, target, provenance):
project = os.path.join(str(datafiles), "notfound")
result = cli.run(project=project, args=["build", target])
result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.MISSING_FILE)
assert provenance in result.stderr
#
# Tests links with invalid configurations
#
@pytest.mark.datafiles(DATA_DIR)
@pytest.mark.parametrize(
"target,expected_error,expected_reason",
[
# Test link which declares sources, either directly of via a dependency
("link-with-sources.bst", ErrorDomain.ELEMENT, "element-forbidden-sources"),
("target-link-with-sources.bst", ErrorDomain.ELEMENT, "element-forbidden-sources"),
# Test link which declares dependencies, either directly of via a dependency
("link-with-dependencies.bst", ErrorDomain.LOAD, LoadErrorReason.LINK_FORBIDDEN_DEPENDENCIES),
],
)
def test_link_invalid_config(cli, tmpdir, datafiles, target, expected_error, expected_reason):
project = os.path.join(str(datafiles), "invalid")
result = cli.run(project=project, args=["show", target])
result.assert_main_error(expected_error, expected_reason)
#
# Test including files across the boundry a link to a subproject's junction
#
@pytest.mark.datafiles(DATA_DIR)
def test_cross_link_junction_include(cli, tmpdir, datafiles):
project = os.path.join(str(datafiles), "cross-link-junction-include")
# Show the variables and parse our test variable from the subsubproject
result = cli.run(project=project, args=["show", "--format", "%{vars}", "target.bst"])
result.assert_success()
# Read back some of our project defaults from the env
variables = _yaml.load_data(result.output)
assert variables.get_str("test") == "the test"