# 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"