blob: 11a0737ddbecee66c2b706e5a82f00c320b1d2e4 [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 shutil
import pytest
from buildstream._testing import create_repo
from buildstream._testing import cli # pylint: disable=unused-import
from buildstream.exceptions import ErrorDomain
from buildstream import _yaml
DATA_DIR = os.path.join(
os.path.dirname(os.path.realpath(__file__)),
"filter",
)
@pytest.mark.datafiles(os.path.join(DATA_DIR, "basic"))
def test_filter_include(datafiles, cli, tmpdir):
project = str(datafiles)
result = cli.run(project=project, args=["build", "output-include.bst"])
result.assert_success()
checkout = os.path.join(tmpdir.dirname, tmpdir.basename, "checkout")
result = cli.run(project=project, args=["artifact", "checkout", "output-include.bst", "--directory", checkout])
result.assert_success()
assert os.path.exists(os.path.join(checkout, "foo"))
assert not os.path.exists(os.path.join(checkout, "bar"))
@pytest.mark.datafiles(os.path.join(DATA_DIR, "basic"))
def test_filter_include_dynamic(datafiles, cli, tmpdir):
project = str(datafiles)
result = cli.run(project=project, args=["build", "output-dynamic-include.bst"])
result.assert_success()
checkout = os.path.join(tmpdir.dirname, tmpdir.basename, "checkout")
result = cli.run(
project=project, args=["artifact", "checkout", "output-dynamic-include.bst", "--directory", checkout]
)
result.assert_success()
assert os.path.exists(os.path.join(checkout, "foo"))
assert not os.path.exists(os.path.join(checkout, "bar"))
@pytest.mark.datafiles(os.path.join(DATA_DIR, "basic"))
def test_filter_exclude(datafiles, cli, tmpdir):
project = str(datafiles)
result = cli.run(project=project, args=["build", "output-exclude.bst"])
result.assert_success()
checkout = os.path.join(tmpdir.dirname, tmpdir.basename, "checkout")
result = cli.run(project=project, args=["artifact", "checkout", "output-exclude.bst", "--directory", checkout])
result.assert_success()
assert not os.path.exists(os.path.join(checkout, "foo"))
assert os.path.exists(os.path.join(checkout, "bar"))
@pytest.mark.datafiles(os.path.join(DATA_DIR, "basic"))
def test_filter_orphans(datafiles, cli, tmpdir):
project = str(datafiles)
result = cli.run(project=project, args=["build", "output-orphans.bst"])
result.assert_success()
checkout = os.path.join(tmpdir.dirname, tmpdir.basename, "checkout")
result = cli.run(project=project, args=["artifact", "checkout", "output-orphans.bst", "--directory", checkout])
result.assert_success()
assert os.path.exists(os.path.join(checkout, "baz"))
@pytest.mark.datafiles(os.path.join(DATA_DIR, "basic"))
def test_filter_deps_ok(datafiles, cli):
project = str(datafiles)
result = cli.run(project=project, args=["build", "deps-permitted.bst"])
result.assert_success()
result = cli.run(project=project, args=["show", "--deps=run", "--format='%{name}'", "deps-permitted.bst"])
result.assert_success()
assert "output-exclude.bst" in result.output
assert "output-orphans.bst" in result.output
@pytest.mark.datafiles(os.path.join(DATA_DIR, "basic"))
def test_filter_forbid_sources(datafiles, cli):
project = str(datafiles)
result = cli.run(project=project, args=["build", "forbidden-source.bst"])
result.assert_main_error(ErrorDomain.ELEMENT, "element-forbidden-sources")
@pytest.mark.datafiles(os.path.join(DATA_DIR, "basic"))
def test_filter_forbid_multi_bdep(datafiles, cli):
project = str(datafiles)
result = cli.run(project=project, args=["build", "forbidden-multi-bdep.bst"])
result.assert_main_error(ErrorDomain.ELEMENT, "filter-bdepend-wrong-count")
@pytest.mark.datafiles(os.path.join(DATA_DIR, "basic"))
def test_filter_forbid_no_bdep(datafiles, cli):
project = str(datafiles)
result = cli.run(project=project, args=["build", "forbidden-no-bdep.bst"])
result.assert_main_error(ErrorDomain.ELEMENT, "filter-bdepend-wrong-count")
@pytest.mark.datafiles(os.path.join(DATA_DIR, "basic"))
def test_filter_forbid_also_rdep(datafiles, cli):
project = str(datafiles)
result = cli.run(project=project, args=["build", "forbidden-also-rdep.bst"])
result.assert_main_error(ErrorDomain.ELEMENT, "filter-bdepend-also-rdepend")
@pytest.mark.datafiles(os.path.join(DATA_DIR, "basic"))
def test_filter_workspace_open(datafiles, cli, tmpdir):
project = str(datafiles)
workspace_dir = os.path.join(tmpdir.dirname, tmpdir.basename, "workspace")
result = cli.run(project=project, args=["workspace", "open", "--directory", workspace_dir, "deps-permitted.bst"])
result.assert_success()
assert os.path.exists(os.path.join(workspace_dir, "foo"))
assert os.path.exists(os.path.join(workspace_dir, "bar"))
assert os.path.exists(os.path.join(workspace_dir, "baz"))
@pytest.mark.datafiles(os.path.join(DATA_DIR, "basic"))
def test_filter_workspace_open_multi(datafiles, cli):
project = str(datafiles)
result = cli.run(
cwd=project, project=project, args=["workspace", "open", "deps-permitted.bst", "output-orphans.bst"]
)
result.assert_success()
assert os.path.exists(os.path.join(project, "input"))
@pytest.mark.datafiles(os.path.join(DATA_DIR, "basic"))
def test_filter_workspace_build(datafiles, cli, tmpdir):
project = str(datafiles)
tempdir = os.path.join(tmpdir.dirname, tmpdir.basename)
workspace_dir = os.path.join(tempdir, "workspace")
result = cli.run(project=project, args=["workspace", "open", "--directory", workspace_dir, "output-orphans.bst"])
result.assert_success()
src = os.path.join(workspace_dir, "foo")
dst = os.path.join(workspace_dir, "quux")
shutil.copyfile(src, dst)
result = cli.run(project=project, args=["build", "output-orphans.bst"])
result.assert_success()
checkout_dir = os.path.join(tempdir, "checkout")
result = cli.run(project=project, args=["artifact", "checkout", "output-orphans.bst", "--directory", checkout_dir])
result.assert_success()
assert os.path.exists(os.path.join(checkout_dir, "quux"))
@pytest.mark.datafiles(os.path.join(DATA_DIR, "basic"))
def test_filter_workspace_close(datafiles, cli, tmpdir):
project = str(datafiles)
tempdir = os.path.join(tmpdir.dirname, tmpdir.basename)
workspace_dir = os.path.join(tempdir, "workspace")
result = cli.run(project=project, args=["workspace", "open", "--directory", workspace_dir, "output-orphans.bst"])
result.assert_success()
src = os.path.join(workspace_dir, "foo")
dst = os.path.join(workspace_dir, "quux")
shutil.copyfile(src, dst)
result = cli.run(project=project, args=["workspace", "close", "deps-permitted.bst"])
result.assert_success()
result = cli.run(project=project, args=["build", "output-orphans.bst"])
result.assert_success()
checkout_dir = os.path.join(tempdir, "checkout")
result = cli.run(project=project, args=["artifact", "checkout", "output-orphans.bst", "--directory", checkout_dir])
result.assert_success()
assert not os.path.exists(os.path.join(checkout_dir, "quux"))
@pytest.mark.datafiles(os.path.join(DATA_DIR, "basic"))
def test_filter_workspace_reset(datafiles, cli, tmpdir):
project = str(datafiles)
tempdir = os.path.join(tmpdir.dirname, tmpdir.basename)
workspace_dir = os.path.join(tempdir, "workspace")
result = cli.run(project=project, args=["workspace", "open", "--directory", workspace_dir, "output-orphans.bst"])
result.assert_success()
src = os.path.join(workspace_dir, "foo")
dst = os.path.join(workspace_dir, "quux")
shutil.copyfile(src, dst)
result = cli.run(project=project, args=["workspace", "reset", "deps-permitted.bst"])
result.assert_success()
result = cli.run(project=project, args=["build", "output-orphans.bst"])
result.assert_success()
checkout_dir = os.path.join(tempdir, "checkout")
result = cli.run(project=project, args=["artifact", "checkout", "output-orphans.bst", "--directory", checkout_dir])
result.assert_success()
assert not os.path.exists(os.path.join(checkout_dir, "quux"))
@pytest.mark.datafiles(os.path.join(DATA_DIR, "basic"))
def test_filter_track(datafiles, cli, tmpdir):
repo = create_repo("tar", str(tmpdir))
ref = repo.create(os.path.join(str(datafiles), "files"))
elements_dir = os.path.join(str(tmpdir), "elements")
project = str(tmpdir)
input_name = "input.bst"
project_config = {
"name": "filter-track-test",
"min-version": "2.0",
"element-path": "elements",
}
project_file = os.path.join(str(tmpdir), "project.conf")
_yaml.roundtrip_dump(project_config, project_file)
input_config = {
"kind": "import",
"sources": [repo.source_config()],
}
input_file = os.path.join(elements_dir, input_name)
_yaml.roundtrip_dump(input_config, input_file)
filter1_config = {"kind": "filter", "depends": [{"filename": input_name, "type": "build"}]}
filter1_file = os.path.join(elements_dir, "filter1.bst")
_yaml.roundtrip_dump(filter1_config, filter1_file)
filter2_config = {"kind": "filter", "depends": [{"filename": "filter1.bst", "type": "build"}]}
filter2_file = os.path.join(elements_dir, "filter2.bst")
_yaml.roundtrip_dump(filter2_config, filter2_file)
# Assert that a fetch is needed
assert cli.get_element_state(project, input_name) == "no reference"
# Now try to track it
result = cli.run(project=project, args=["source", "track", "filter2.bst"])
result.assert_success()
# Now check that a ref field exists
new_input = _yaml.load(input_file, shortname=None)
source_node = new_input.get_sequence("sources").mapping_at(0)
new_input_ref = source_node.get_str("ref")
assert new_input_ref == ref
@pytest.mark.datafiles(os.path.join(DATA_DIR, "basic"))
def test_filter_track_excepted(datafiles, cli, tmpdir):
repo = create_repo("tar", str(tmpdir))
repo.create(os.path.join(str(datafiles), "files"))
elements_dir = os.path.join(str(tmpdir), "elements")
project = str(tmpdir)
input_name = "input.bst"
project_config = {
"name": "filter-track-test",
"min-version": "2.0",
"element-path": "elements",
}
project_file = os.path.join(str(tmpdir), "project.conf")
_yaml.roundtrip_dump(project_config, project_file)
input_config = {
"kind": "import",
"sources": [repo.source_config()],
}
input_file = os.path.join(elements_dir, input_name)
_yaml.roundtrip_dump(input_config, input_file)
filter1_config = {"kind": "filter", "depends": [{"filename": input_name, "type": "build"}]}
filter1_file = os.path.join(elements_dir, "filter1.bst")
_yaml.roundtrip_dump(filter1_config, filter1_file)
filter2_config = {"kind": "filter", "depends": [{"filename": "filter1.bst", "type": "build"}]}
filter2_file = os.path.join(elements_dir, "filter2.bst")
_yaml.roundtrip_dump(filter2_config, filter2_file)
# Assert that a fetch is needed
assert cli.get_element_state(project, input_name) == "no reference"
# Now try to track it
result = cli.run(project=project, args=["source", "track", "filter2.bst", "--except", "input.bst"])
result.assert_success()
# Now check that a ref field exists
new_input = _yaml.load(input_file, shortname=None)
source_node = new_input.get_sequence("sources").mapping_at(0)
assert "ref" not in source_node
@pytest.mark.datafiles(os.path.join(DATA_DIR, "basic"))
def test_filter_track_multi_to_one(datafiles, cli, tmpdir):
repo = create_repo("tar", str(tmpdir))
ref = repo.create(os.path.join(str(datafiles), "files"))
elements_dir = os.path.join(str(tmpdir), "elements")
project = str(tmpdir)
input_name = "input.bst"
project_config = {
"name": "filter-track-test",
"min-version": "2.0",
"element-path": "elements",
}
project_file = os.path.join(str(tmpdir), "project.conf")
_yaml.roundtrip_dump(project_config, project_file)
input_config = {
"kind": "import",
"sources": [repo.source_config()],
}
input_file = os.path.join(elements_dir, input_name)
_yaml.roundtrip_dump(input_config, input_file)
filter1_config = {"kind": "filter", "depends": [{"filename": input_name, "type": "build"}]}
filter1_file = os.path.join(elements_dir, "filter1.bst")
_yaml.roundtrip_dump(filter1_config, filter1_file)
filter2_config = {"kind": "filter", "depends": [{"filename": input_name, "type": "build"}]}
filter2_file = os.path.join(elements_dir, "filter2.bst")
_yaml.roundtrip_dump(filter2_config, filter2_file)
# Assert that a fetch is needed
assert cli.get_element_state(project, input_name) == "no reference"
# Now try to track it
result = cli.run(project=project, args=["source", "track", "filter1.bst", "filter2.bst"])
result.assert_success()
# Now check that a ref field exists
new_input = _yaml.load(input_file, shortname=None)
source_node = new_input.get_sequence("sources").mapping_at(0)
new_ref = source_node.get_str("ref")
assert new_ref == ref
@pytest.mark.datafiles(os.path.join(DATA_DIR, "basic"))
def test_filter_track_multi(datafiles, cli, tmpdir):
repo = create_repo("tar", str(tmpdir))
ref = repo.create(os.path.join(str(datafiles), "files"))
elements_dir = os.path.join(str(tmpdir), "elements")
project = str(tmpdir)
input_name = "input.bst"
input2_name = "input2.bst"
project_config = {
"name": "filter-track-test",
"min-version": "2.0",
"element-path": "elements",
}
project_file = os.path.join(str(tmpdir), "project.conf")
_yaml.roundtrip_dump(project_config, project_file)
input_config = {
"kind": "import",
"sources": [repo.source_config()],
}
input_file = os.path.join(elements_dir, input_name)
_yaml.roundtrip_dump(input_config, input_file)
input2_config = dict(input_config)
input2_file = os.path.join(elements_dir, input2_name)
_yaml.roundtrip_dump(input2_config, input2_file)
filter1_config = {"kind": "filter", "depends": [{"filename": input_name, "type": "build"}]}
filter1_file = os.path.join(elements_dir, "filter1.bst")
_yaml.roundtrip_dump(filter1_config, filter1_file)
filter2_config = {"kind": "filter", "depends": [{"filename": input2_name, "type": "build"}]}
filter2_file = os.path.join(elements_dir, "filter2.bst")
_yaml.roundtrip_dump(filter2_config, filter2_file)
# Assert that a fetch is needed
states = cli.get_element_states(project, [input_name, input2_name])
assert states == {
input_name: "no reference",
input2_name: "no reference",
}
# Now try to track it
result = cli.run(project=project, args=["source", "track", "filter1.bst", "filter2.bst"])
result.assert_success()
# Now check that a ref field exists
new_input = _yaml.load(input_file, shortname=None)
source_node = new_input.get_sequence("sources").mapping_at(0)
new_ref = source_node.get_str("ref")
assert new_ref == ref
new_input2 = _yaml.load(input2_file, shortname=None)
source_node2 = new_input2.get_sequence("sources").mapping_at(0)
new_ref2 = source_node2.get_str("ref")
assert new_ref2 == ref
@pytest.mark.datafiles(os.path.join(DATA_DIR, "basic"))
def test_filter_track_multi_exclude(datafiles, cli, tmpdir):
repo = create_repo("tar", str(tmpdir))
ref = repo.create(os.path.join(str(datafiles), "files"))
elements_dir = os.path.join(str(tmpdir), "elements")
project = str(tmpdir)
input_name = "input.bst"
input2_name = "input2.bst"
project_config = {
"name": "filter-track-test",
"min-version": "2.0",
"element-path": "elements",
}
project_file = os.path.join(str(tmpdir), "project.conf")
_yaml.roundtrip_dump(project_config, project_file)
input_config = {
"kind": "import",
"sources": [repo.source_config()],
}
input_file = os.path.join(elements_dir, input_name)
_yaml.roundtrip_dump(input_config, input_file)
input2_config = dict(input_config)
input2_file = os.path.join(elements_dir, input2_name)
_yaml.roundtrip_dump(input2_config, input2_file)
filter1_config = {"kind": "filter", "depends": [{"filename": input_name, "type": "build"}]}
filter1_file = os.path.join(elements_dir, "filter1.bst")
_yaml.roundtrip_dump(filter1_config, filter1_file)
filter2_config = {"kind": "filter", "depends": [{"filename": input2_name, "type": "build"}]}
filter2_file = os.path.join(elements_dir, "filter2.bst")
_yaml.roundtrip_dump(filter2_config, filter2_file)
# Assert that a fetch is needed
states = cli.get_element_states(project, [input_name, input2_name])
assert states == {
input_name: "no reference",
input2_name: "no reference",
}
# Now try to track it
result = cli.run(project=project, args=["source", "track", "filter1.bst", "filter2.bst", "--except", input_name])
result.assert_success()
# Now check that a ref field exists
new_input = _yaml.load(input_file, shortname=None)
source_node = new_input.get_sequence("sources").mapping_at(0)
assert "ref" not in source_node
new_input2 = _yaml.load(input2_file, shortname=None)
source_node2 = new_input2.get_sequence("sources").mapping_at(0)
new_ref2 = source_node2.get_str("ref")
assert new_ref2 == ref
@pytest.mark.datafiles(os.path.join(DATA_DIR, "basic"))
def test_filter_include_with_indirect_deps(datafiles, cli, tmpdir):
project = str(datafiles)
result = cli.run(project=project, args=["build", "output-include-with-indirect-deps.bst"])
result.assert_success()
checkout = os.path.join(tmpdir.dirname, tmpdir.basename, "checkout")
result = cli.run(
project=project,
args=["artifact", "checkout", "output-include-with-indirect-deps.bst", "--directory", checkout],
)
result.assert_success()
# direct dependencies should be staged and filtered
assert os.path.exists(os.path.join(checkout, "baz"))
# indirect dependencies shouldn't be staged and filtered
assert not os.path.exists(os.path.join(checkout, "foo"))
assert not os.path.exists(os.path.join(checkout, "bar"))
@pytest.mark.datafiles(os.path.join(DATA_DIR, "basic"))
def test_filter_fails_for_nonexisting_domain(datafiles, cli):
project = str(datafiles)
result = cli.run(project=project, args=["build", "output-include-nonexistent-domain.bst"])
result.assert_main_error(ErrorDomain.STREAM, None)
error = "Unknown domains were used in output-include-nonexistent-domain.bst [line 7 column 2]"
assert error in result.stderr
assert "- unknown_file" in result.stderr
@pytest.mark.datafiles(os.path.join(DATA_DIR, "basic"))
def test_filter_pass_integration(datafiles, cli):
project = str(datafiles)
# Explicitly not passing integration commands should be fine
result = cli.run(project=project, args=["build", "no-pass-integration.bst"])
result.assert_success()
# Passing integration commands should build nicely
result = cli.run(project=project, args=["build", "pass-integration.bst"])
result.assert_success()
# Checking out elements which don't pass integration commands should still work
checkout_dir = os.path.join(project, "no-pass")
result = cli.run(
project=project,
args=["artifact", "checkout", "--integrate", "--directory", checkout_dir, "no-pass-integration.bst"],
)
result.assert_success()
# Checking out the artifact should fail if we run integration commands, as
# the staged artifacts don't have a shell
checkout_dir = os.path.join(project, "pass")
result = cli.run(
project=project,
args=["artifact", "checkout", "--integrate", "--directory", checkout_dir, "pass-integration.bst"],
)
result.assert_main_error(ErrorDomain.STREAM, "missing-command")
@pytest.mark.datafiles(os.path.join(DATA_DIR, "basic"))
def test_filter_stack_depend_failure(datafiles, cli):
project = str(datafiles)
result = cli.run(project=project, args=["build", "forbidden-stack-dep.bst"])
result.assert_main_error(ErrorDomain.ELEMENT, "filter-bdepend-no-artifact")