# Pylint doesn't play well with fixtures and dependency injection from pytest # pylint: disable=redefined-outer-name import os import pytest from buildstream.testing import create_repo from buildstream.testing import cli # pylint: disable=unused-import from buildstream import _yaml # Project directory DATA_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "project",) # create_element() # # Args: # project (str): The project directory where testing is happening # name (str): The element name to create # dependencies (list): The list of dependencies to dump into YAML format # # Returns: # (Repo): The corresponding git repository created for the element def create_element(project, name, dependencies): dev_files_path = os.path.join(project, "files", "dev-files") element_path = os.path.join(project, "elements") repo = create_repo("git", project, "{}-repo".format(name)) ref = repo.create(dev_files_path) element = {"kind": "import", "sources": [repo.source_config(ref=ref)], "depends": dependencies} _yaml.roundtrip_dump(element, os.path.join(element_path, name)) return repo # This tests a variety of scenarios and checks that the order in # which things are processed remains stable. # # This is especially important in order to ensure that our # depth sorting and optimization of which elements should be # processed first is doing it's job right, and that we are # promoting elements to the build queue as soon as possible # # Parameters: # targets (target elements): The targets to invoke bst with # template (dict): The project template dictionary, for create_element() # expected (list): A list of element names in the expected order # @pytest.mark.datafiles(os.path.join(DATA_DIR)) @pytest.mark.parametrize( "target,template,expected", [ # First simple test ( "3.bst", {"0.bst": ["1.bst"], "1.bst": [], "2.bst": ["0.bst"], "3.bst": ["0.bst", "1.bst", "2.bst"]}, ["1.bst", "0.bst", "2.bst", "3.bst"], ), # A more complicated test with build of build dependencies ( "target.bst", { "a.bst": [], "base.bst": [], "timezones.bst": [], "middleware.bst": [{"filename": "base.bst", "type": "build"}], "app.bst": [{"filename": "middleware.bst", "type": "build"}], "target.bst": ["a.bst", "base.bst", "middleware.bst", "app.bst", "timezones.bst"], }, ["base.bst", "middleware.bst", "a.bst", "app.bst", "timezones.bst", "target.bst"], ), ], ) @pytest.mark.parametrize("operation", [("show"), ("fetch"), ("build")]) def test_order(cli, datafiles, operation, target, template, expected): project = str(datafiles) # Configure to only allow one fetcher at a time, make it easy to # determine what is being planned in what order. cli.configure({"scheduler": {"fetchers": 1, "builders": 1}}) # Build the project from the template, make import elements # all with the same repo # for element, dependencies in template.items(): create_element(project, element, dependencies) # Run test and collect results if operation == "show": result = cli.run(args=["show", "--deps", "plan", "--format", "%{name}", target], project=project, silent=True) result.assert_success() results = result.output.splitlines() else: if operation == "fetch": result = cli.run(args=["source", "fetch", target], project=project, silent=True) else: result = cli.run(args=[operation, target], project=project, silent=True) result.assert_success() results = result.get_start_order(operation) # Assert the order print("Expected order: {}".format(expected)) print("Observed result order: {}".format(results)) assert results == expected