blob: 67a35ab0fcbbdf653147c7219addae9caf67f706 [file] [log] [blame]
import os
import pytest
import shutil
import subprocess
from ruamel.yaml.comments import CommentedSet
from tests.testutils import cli, create_repo, ALL_REPO_KINDS, site
from buildstream import _yaml
from buildstream._exceptions import ErrorDomain, LoadError, LoadErrorReason
from buildstream._workspaces import BST_WORKSPACE_FORMAT_VERSION
repo_kinds = [(kind) for kind in ALL_REPO_KINDS]
# Project directory
DATA_DIR = os.path.join(
os.path.dirname(os.path.realpath(__file__)),
"project",
)
def open_workspace(cli, tmpdir, datafiles, kind, track, suffix='', workspace_dir=None):
if not workspace_dir:
workspace_dir = os.path.join(str(tmpdir), 'workspace{}'.format(suffix))
project_path = os.path.join(datafiles.dirname, datafiles.basename)
bin_files_path = os.path.join(project_path, 'files', 'bin-files')
element_path = os.path.join(project_path, 'elements')
element_name = 'workspace-test-{}{}.bst'.format(kind, suffix)
# Create our repo object of the given source type with
# the bin files, and then collect the initial ref.
#
repo = create_repo(kind, str(tmpdir))
ref = repo.create(bin_files_path)
if track:
ref = None
# Write out our test target
element = {
'kind': 'import',
'sources': [
repo.source_config(ref=ref)
]
}
_yaml.dump(element,
os.path.join(element_path,
element_name))
# Assert that there is no reference, a track & fetch is needed
state = cli.get_element_state(project_path, element_name)
if track:
assert state == 'no reference'
else:
assert state == 'fetch needed'
# Now open the workspace, this should have the effect of automatically
# tracking & fetching the source from the repo.
args = ['workspace', 'open']
if track:
args.append('--track')
args.extend([element_name, workspace_dir])
result = cli.run(project=project_path, args=args)
result.assert_success()
# Assert that we are now buildable because the source is
# now cached.
assert cli.get_element_state(project_path, element_name) == 'buildable'
# Check that the executable hello file is found in the workspace
filename = os.path.join(workspace_dir, 'usr', 'bin', 'hello')
assert os.path.exists(filename)
return (element_name, project_path, workspace_dir)
@pytest.mark.datafiles(DATA_DIR)
@pytest.mark.parametrize("kind", repo_kinds)
def test_open(cli, tmpdir, datafiles, kind):
open_workspace(cli, tmpdir, datafiles, kind, False)
@pytest.mark.datafiles(DATA_DIR)
def test_open_bzr_customize(cli, tmpdir, datafiles):
element_name, project, workspace = open_workspace(cli, tmpdir, datafiles, "bzr", False)
# Check that the .bzr dir exists
bzrdir = os.path.join(workspace, ".bzr")
assert(os.path.isdir(bzrdir))
# Check that the correct origin branch is set
element_config = _yaml.load(os.path.join(project, "elements", element_name))
source_config = element_config['sources'][0]
output = subprocess.check_output(["bzr", "info"], cwd=workspace)
stripped_url = source_config['url'].lstrip("file:///")
expected_output_str = ("checkout of branch: /{}/{}"
.format(stripped_url, source_config['track']))
assert(expected_output_str in str(output))
@pytest.mark.datafiles(DATA_DIR)
@pytest.mark.parametrize("kind", repo_kinds)
def test_open_track(cli, tmpdir, datafiles, kind):
open_workspace(cli, tmpdir, datafiles, kind, True)
@pytest.mark.datafiles(DATA_DIR)
@pytest.mark.parametrize("kind", repo_kinds)
def test_open_force(cli, tmpdir, datafiles, kind):
element_name, project, workspace = open_workspace(cli, tmpdir, datafiles, kind, False)
# Close the workspace
result = cli.run(project=project, args=[
'workspace', 'close', element_name
])
result.assert_success()
# Assert the workspace dir still exists
assert os.path.exists(workspace)
# Now open the workspace again with --force, this should happily succeed
result = cli.run(project=project, args=[
'workspace', 'open', '--force', element_name, workspace
])
result.assert_success()
@pytest.mark.datafiles(DATA_DIR)
@pytest.mark.parametrize("kind", repo_kinds)
def test_open_force_open(cli, tmpdir, datafiles, kind):
element_name, project, workspace = open_workspace(cli, tmpdir, datafiles, kind, False)
# Assert the workspace dir exists
assert os.path.exists(workspace)
# Now open the workspace again with --force, this should happily succeed
result = cli.run(project=project, args=[
'workspace', 'open', '--force', element_name, workspace
])
result.assert_success()
@pytest.mark.datafiles(DATA_DIR)
@pytest.mark.parametrize("kind", repo_kinds)
def test_open_force_different_workspace(cli, tmpdir, datafiles, kind):
element_name, project, workspace = open_workspace(cli, tmpdir, datafiles, kind, False, "-alpha")
# Assert the workspace dir exists
assert os.path.exists(workspace)
hello_path = os.path.join(workspace, 'usr', 'bin', 'hello')
hello1_path = os.path.join(workspace, 'usr', 'bin', 'hello1')
tmpdir = os.path.join(str(tmpdir), "-beta")
shutil.move(hello_path, hello1_path)
element_name2, project2, workspace2 = open_workspace(cli, tmpdir, datafiles, kind, False, "-beta")
# Assert the workspace dir exists
assert os.path.exists(workspace2)
# Assert that workspace 1 contains the modified file
assert os.path.exists(hello1_path)
# Assert that workspace 2 contains the unmodified file
assert os.path.exists(os.path.join(workspace2, 'usr', 'bin', 'hello'))
# Now open the workspace again with --force, this should happily succeed
result = cli.run(project=project, args=[
'workspace', 'open', '--force', element_name2, workspace
])
# Assert that the file in workspace 1 has been replaced
# With the file from workspace 2
assert os.path.exists(hello_path)
assert not os.path.exists(hello1_path)
result.assert_success()
@pytest.mark.datafiles(DATA_DIR)
@pytest.mark.parametrize("kind", repo_kinds)
def test_close(cli, tmpdir, datafiles, kind):
element_name, project, workspace = open_workspace(cli, tmpdir, datafiles, kind, False)
# Close the workspace
result = cli.run(project=project, args=[
'workspace', 'close', '--remove-dir', element_name
])
result.assert_success()
# Assert the workspace dir has been deleted
assert not os.path.exists(workspace)
@pytest.mark.datafiles(DATA_DIR)
def test_close_external_after_move_project(cli, tmpdir, datafiles):
tmp_parent = os.path.dirname(str(tmpdir))
workspace_dir = os.path.join(tmp_parent, "workspace")
element_name, project_path, _ = open_workspace(cli, tmpdir, datafiles, 'git', False, "", workspace_dir)
assert os.path.exists(workspace_dir)
tmp_dir = os.path.join(tmp_parent, 'external_project')
shutil.move(project_path, tmp_dir)
assert os.path.exists(tmp_dir)
# Close the workspace
result = cli.run(configure=False, project=tmp_dir, args=[
'workspace', 'close', '--remove-dir', element_name
])
result.assert_success()
# Assert the workspace dir has been deleted
assert not os.path.exists(workspace_dir)
# Move directory back inside tmp directory so it can be recognised
shutil.move(tmp_dir, project_path)
@pytest.mark.datafiles(DATA_DIR)
def test_close_internal_after_move_project(cli, tmpdir, datafiles):
element_name, project, _ = open_workspace(cli, tmpdir, datafiles, 'git', False)
tmp_dir = os.path.join(os.path.dirname(str(tmpdir)), 'external_project')
shutil.move(str(tmpdir), tmp_dir)
assert os.path.exists(tmp_dir)
# Close the workspace
result = cli.run(configure=False, project=tmp_dir, args=[
'workspace', 'close', '--remove-dir', element_name
])
result.assert_success()
# Assert the workspace dir has been deleted
workspace = os.path.join(tmp_dir, 'workspace')
assert not os.path.exists(workspace)
@pytest.mark.datafiles(DATA_DIR)
def test_close_removed(cli, tmpdir, datafiles):
element_name, project, workspace = open_workspace(cli, tmpdir, datafiles, 'git', False)
# Remove it first, closing the workspace should work
shutil.rmtree(workspace)
# Close the workspace
result = cli.run(project=project, args=[
'workspace', 'close', element_name
])
result.assert_success()
# Assert the workspace dir has been deleted
assert not os.path.exists(workspace)
@pytest.mark.datafiles(DATA_DIR)
def test_close_nonexistant_element(cli, tmpdir, datafiles):
element_name, project, workspace = open_workspace(cli, tmpdir, datafiles, 'git', False)
element_path = os.path.join(datafiles.dirname, datafiles.basename, 'elements', element_name)
# First brutally remove the element.bst file, ensuring that
# the element does not exist anymore in the project where
# we want to close the workspace.
os.remove(element_path)
# Close the workspace
result = cli.run(project=project, args=[
'workspace', 'close', '--remove-dir', element_name
])
result.assert_success()
# Assert the workspace dir has been deleted
assert not os.path.exists(workspace)
@pytest.mark.datafiles(DATA_DIR)
def test_close_multiple(cli, tmpdir, datafiles):
tmpdir_alpha = os.path.join(str(tmpdir), 'alpha')
tmpdir_beta = os.path.join(str(tmpdir), 'beta')
alpha, project, workspace_alpha = open_workspace(
cli, tmpdir_alpha, datafiles, 'git', False, suffix='-alpha')
beta, project, workspace_beta = open_workspace(
cli, tmpdir_beta, datafiles, 'git', False, suffix='-beta')
# Close the workspaces
result = cli.run(project=project, args=[
'workspace', 'close', '--remove-dir', alpha, beta
])
result.assert_success()
# Assert the workspace dirs have been deleted
assert not os.path.exists(workspace_alpha)
assert not os.path.exists(workspace_beta)
@pytest.mark.datafiles(DATA_DIR)
def test_close_all(cli, tmpdir, datafiles):
tmpdir_alpha = os.path.join(str(tmpdir), 'alpha')
tmpdir_beta = os.path.join(str(tmpdir), 'beta')
alpha, project, workspace_alpha = open_workspace(
cli, tmpdir_alpha, datafiles, 'git', False, suffix='-alpha')
beta, project, workspace_beta = open_workspace(
cli, tmpdir_beta, datafiles, 'git', False, suffix='-beta')
# Close the workspaces
result = cli.run(project=project, args=[
'workspace', 'close', '--remove-dir', '--all'
])
result.assert_success()
# Assert the workspace dirs have been deleted
assert not os.path.exists(workspace_alpha)
assert not os.path.exists(workspace_beta)
@pytest.mark.datafiles(DATA_DIR)
def test_reset(cli, tmpdir, datafiles):
# Open the workspace
element_name, project, workspace = open_workspace(cli, tmpdir, datafiles, 'git', False)
# Modify workspace
shutil.rmtree(os.path.join(workspace, 'usr', 'bin'))
os.makedirs(os.path.join(workspace, 'etc'))
with open(os.path.join(workspace, 'etc', 'pony.conf'), 'w') as f:
f.write("PONY='pink'")
# Now reset the open workspace, this should have the
# effect of reverting our changes.
result = cli.run(project=project, args=[
'workspace', 'reset', element_name
])
result.assert_success()
assert os.path.exists(os.path.join(workspace, 'usr', 'bin', 'hello'))
assert not os.path.exists(os.path.join(workspace, 'etc', 'pony.conf'))
@pytest.mark.datafiles(DATA_DIR)
def test_reset_multiple(cli, tmpdir, datafiles):
# Open the workspaces
tmpdir_alpha = os.path.join(str(tmpdir), 'alpha')
tmpdir_beta = os.path.join(str(tmpdir), 'beta')
alpha, project, workspace_alpha = open_workspace(
cli, tmpdir_alpha, datafiles, 'git', False, suffix='-alpha')
beta, project, workspace_beta = open_workspace(
cli, tmpdir_beta, datafiles, 'git', False, suffix='-beta')
# Modify workspaces
shutil.rmtree(os.path.join(workspace_alpha, 'usr', 'bin'))
os.makedirs(os.path.join(workspace_beta, 'etc'))
with open(os.path.join(workspace_beta, 'etc', 'pony.conf'), 'w') as f:
f.write("PONY='pink'")
# Now reset the open workspaces, this should have the
# effect of reverting our changes.
result = cli.run(project=project, args=[
'workspace', 'reset', alpha, beta,
])
result.assert_success()
assert os.path.exists(os.path.join(workspace_alpha, 'usr', 'bin', 'hello'))
assert not os.path.exists(os.path.join(workspace_beta, 'etc', 'pony.conf'))
@pytest.mark.datafiles(DATA_DIR)
def test_reset_all(cli, tmpdir, datafiles):
# Open the workspaces
tmpdir_alpha = os.path.join(str(tmpdir), 'alpha')
tmpdir_beta = os.path.join(str(tmpdir), 'beta')
alpha, project, workspace_alpha = open_workspace(
cli, tmpdir_alpha, datafiles, 'git', False, suffix='-alpha')
beta, project, workspace_beta = open_workspace(
cli, tmpdir_beta, datafiles, 'git', False, suffix='-beta')
# Modify workspaces
shutil.rmtree(os.path.join(workspace_alpha, 'usr', 'bin'))
os.makedirs(os.path.join(workspace_beta, 'etc'))
with open(os.path.join(workspace_beta, 'etc', 'pony.conf'), 'w') as f:
f.write("PONY='pink'")
# Now reset the open workspace, this should have the
# effect of reverting our changes.
result = cli.run(project=project, args=[
'workspace', 'reset', '--all'
])
result.assert_success()
assert os.path.exists(os.path.join(workspace_alpha, 'usr', 'bin', 'hello'))
assert not os.path.exists(os.path.join(workspace_beta, 'etc', 'pony.conf'))
@pytest.mark.datafiles(DATA_DIR)
def test_list(cli, tmpdir, datafiles):
element_name, project, workspace = open_workspace(cli, tmpdir, datafiles, 'git', False)
# Now list the workspaces
result = cli.run(project=project, args=[
'workspace', 'list'
])
result.assert_success()
loaded = _yaml.load_data(result.output)
assert isinstance(loaded.get('workspaces'), list)
workspaces = loaded['workspaces']
assert len(workspaces) == 1
space = workspaces[0]
assert space['element'] == element_name
assert space['directory'] == workspace
@pytest.mark.datafiles(DATA_DIR)
@pytest.mark.parametrize("kind", repo_kinds)
@pytest.mark.parametrize("strict", [("strict"), ("non-strict")])
def test_build(cli, tmpdir, datafiles, kind, strict):
element_name, project, workspace = open_workspace(cli, tmpdir, datafiles, kind, False)
checkout = os.path.join(str(tmpdir), 'checkout')
# Modify workspace
shutil.rmtree(os.path.join(workspace, 'usr', 'bin'))
os.makedirs(os.path.join(workspace, 'etc'))
with open(os.path.join(workspace, 'etc', 'pony.conf'), 'w') as f:
f.write("PONY='pink'")
# Configure strict mode
strict_mode = True
if strict != 'strict':
strict_mode = False
cli.configure({
'projects': {
'test': {
'strict': strict_mode
}
}
})
# Build modified workspace
assert cli.get_element_state(project, element_name) == 'buildable'
assert cli.get_element_key(project, element_name) == "{:?<64}".format('')
result = cli.run(project=project, args=['build', element_name])
result.assert_success()
assert cli.get_element_state(project, element_name) == 'cached'
assert cli.get_element_key(project, element_name) != "{:?<64}".format('')
# Checkout the result
result = cli.run(project=project, args=[
'checkout', element_name, checkout
])
result.assert_success()
# Check that the pony.conf from the modified workspace exists
filename = os.path.join(checkout, 'etc', 'pony.conf')
assert os.path.exists(filename)
# Check that the original /usr/bin/hello is not in the checkout
assert not os.path.exists(os.path.join(checkout, 'usr', 'bin', 'hello'))
@pytest.mark.datafiles(DATA_DIR)
def test_buildable_no_ref(cli, tmpdir, datafiles):
project = os.path.join(datafiles.dirname, datafiles.basename)
element_name = 'workspace-test-no-ref.bst'
element_path = os.path.join(project, 'elements')
# Write out our test target without any source ref
repo = create_repo('git', str(tmpdir))
element = {
'kind': 'import',
'sources': [
repo.source_config()
]
}
_yaml.dump(element,
os.path.join(element_path,
element_name))
# Assert that this target is not buildable when no workspace is associated.
assert cli.get_element_state(project, element_name) == 'no reference'
# Now open the workspace. We don't need to checkout the source though.
workspace = os.path.join(str(tmpdir), 'workspace-no-ref')
os.makedirs(workspace)
args = ['workspace', 'open', '--no-checkout', element_name, workspace]
result = cli.run(project=project, args=args)
result.assert_success()
# Assert that the target is now buildable.
assert cli.get_element_state(project, element_name) == 'buildable'
@pytest.mark.datafiles(DATA_DIR)
@pytest.mark.parametrize("modification", [("addfile"), ("removefile"), ("modifyfile")])
@pytest.mark.parametrize("strict", [("strict"), ("non-strict")])
def test_detect_modifications(cli, tmpdir, datafiles, modification, strict):
element_name, project, workspace = open_workspace(cli, tmpdir, datafiles, 'git', False)
checkout = os.path.join(str(tmpdir), 'checkout')
# Configure strict mode
strict_mode = True
if strict != 'strict':
strict_mode = False
cli.configure({
'projects': {
'test': {
'strict': strict_mode
}
}
})
# Build clean workspace
assert cli.get_element_state(project, element_name) == 'buildable'
assert cli.get_element_key(project, element_name) == "{:?<64}".format('')
result = cli.run(project=project, args=['build', element_name])
result.assert_success()
assert cli.get_element_state(project, element_name) == 'cached'
assert cli.get_element_key(project, element_name) != "{:?<64}".format('')
# Modify the workspace in various different ways, ensuring we
# properly detect the changes.
#
if modification == 'addfile':
os.makedirs(os.path.join(workspace, 'etc'))
with open(os.path.join(workspace, 'etc', 'pony.conf'), 'w') as f:
f.write("PONY='pink'")
elif modification == 'removefile':
os.remove(os.path.join(workspace, 'usr', 'bin', 'hello'))
elif modification == 'modifyfile':
if not site.have_subsecond_mtime(tmpdir):
pytest.skip("Filesystem does not support subsecond mtime precision: {}".format(tmpdir))
with open(os.path.join(workspace, 'usr', 'bin', 'hello'), 'w') as f:
f.write('cookie')
else:
# This cannot be reached
assert 0
# First assert that the state is properly detected
assert cli.get_element_state(project, element_name) == 'buildable'
assert cli.get_element_key(project, element_name) == "{:?<64}".format('')
# Since there are different things going on at `bst build` time
# than `bst show` time, we also want to build / checkout again,
# and ensure that the result contains what we expect.
result = cli.run(project=project, args=['build', element_name])
result.assert_success()
assert cli.get_element_state(project, element_name) == 'cached'
assert cli.get_element_key(project, element_name) != "{:?<64}".format('')
# Checkout the result
result = cli.run(project=project, args=[
'checkout', element_name, checkout
])
result.assert_success()
# Check the result for the changes we made
#
if modification == 'addfile':
filename = os.path.join(checkout, 'etc', 'pony.conf')
assert os.path.exists(filename)
elif modification == 'removefile':
assert not os.path.exists(os.path.join(checkout, 'usr', 'bin', 'hello'))
elif modification == 'modifyfile':
with open(os.path.join(workspace, 'usr', 'bin', 'hello'), 'r') as f:
data = f.read()
assert data == 'cookie'
else:
# This cannot be reached
assert 0
# Ensure that various versions that should not be accepted raise a
# LoadError.INVALID_DATA
@pytest.mark.datafiles(DATA_DIR)
@pytest.mark.parametrize("workspace_cfg", [
# Test loading a negative workspace version
{"format-version": -1},
# Test loading version 0 with two sources
{
"format-version": 0,
"alpha.bst": {
0: "/workspaces/bravo",
1: "/workspaces/charlie",
}
},
# Test loading a version with decimals
{"format-version": 0.5},
# Test loading a future version
{"format-version": BST_WORKSPACE_FORMAT_VERSION + 1}
])
def test_list_unsupported_workspace(cli, tmpdir, datafiles, workspace_cfg):
project = os.path.join(datafiles.dirname, datafiles.basename)
bin_files_path = os.path.join(project, 'files', 'bin-files')
element_path = os.path.join(project, 'elements')
element_name = 'workspace-version.bst'
os.makedirs(os.path.join(project, '.bst'))
workspace_config_path = os.path.join(project, '.bst', 'workspaces.yml')
_yaml.dump(workspace_cfg, workspace_config_path)
result = cli.run(project=project, args=['workspace', 'list'])
result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.INVALID_DATA)
# Ensure that various versions that should be accepted are parsed
# correctly.
@pytest.mark.datafiles(DATA_DIR)
@pytest.mark.parametrize("workspace_cfg,expected", [
# Test loading version 0 without a dict
({
"alpha.bst": "/workspaces/bravo"
}, {
"format-version": BST_WORKSPACE_FORMAT_VERSION,
"workspaces": {
"alpha.bst": {
"prepared": False,
"path": "/workspaces/bravo",
"running_files": {}
}
}
}),
# Test loading version 0 with only one source
({
"alpha.bst": {
0: "/workspaces/bravo"
}
}, {
"format-version": BST_WORKSPACE_FORMAT_VERSION,
"workspaces": {
"alpha.bst": {
"prepared": False,
"path": "/workspaces/bravo",
"running_files": {}
}
}
}),
# Test loading version 1
({
"format-version": 1,
"workspaces": {
"alpha.bst": {
"path": "/workspaces/bravo"
}
}
}, {
"format-version": BST_WORKSPACE_FORMAT_VERSION,
"workspaces": {
"alpha.bst": {
"prepared": False,
"path": "/workspaces/bravo",
"running_files": {}
}
}
}),
# Test loading version 2
({
"format-version": 2,
"workspaces": {
"alpha.bst": {
"path": "/workspaces/bravo",
"last_successful": "some_key",
"running_files": {
"beta.bst": ["some_file"]
}
}
}
}, {
"format-version": BST_WORKSPACE_FORMAT_VERSION,
"workspaces": {
"alpha.bst": {
"prepared": False,
"path": "/workspaces/bravo",
"last_successful": "some_key",
"running_files": {
"beta.bst": ["some_file"]
}
}
}
}),
# Test loading version 3
({
"format-version": 3,
"workspaces": {
"alpha.bst": {
"prepared": True,
"path": "/workspaces/bravo",
"running_files": {}
}
}
}, {
"format-version": BST_WORKSPACE_FORMAT_VERSION,
"workspaces": {
"alpha.bst": {
"prepared": True,
"path": "/workspaces/bravo",
"running_files": {}
}
}
})
])
def test_list_supported_workspace(cli, tmpdir, datafiles, workspace_cfg, expected):
def parse_dict_as_yaml(node):
tempfile = os.path.join(str(tmpdir), 'yaml_dump')
_yaml.dump(node, tempfile)
return _yaml.node_sanitize(_yaml.load(tempfile))
project = os.path.join(datafiles.dirname, datafiles.basename)
os.makedirs(os.path.join(project, '.bst'))
workspace_config_path = os.path.join(project, '.bst', 'workspaces.yml')
_yaml.dump(workspace_cfg, workspace_config_path)
# Check that we can still read workspace config that is in old format
result = cli.run(project=project, args=['workspace', 'list'])
result.assert_success()
loaded_config = _yaml.node_sanitize(_yaml.load(workspace_config_path))
# Check that workspace config remains the same if no modifications
# to workspaces were made
assert loaded_config == parse_dict_as_yaml(workspace_cfg)
# Create a test bst file
bin_files_path = os.path.join(project, 'files', 'bin-files')
element_path = os.path.join(project, 'elements')
element_name = 'workspace-test.bst'
workspace = os.path.join(str(tmpdir), 'workspace')
# Create our repo object of the given source type with
# the bin files, and then collect the initial ref.
#
repo = create_repo('git', str(tmpdir))
ref = repo.create(bin_files_path)
# Write out our test target
element = {
'kind': 'import',
'sources': [
repo.source_config(ref=ref)
]
}
_yaml.dump(element,
os.path.join(element_path,
element_name))
# Make a change to the workspaces file
result = cli.run(project=project, args=['workspace', 'open', element_name, workspace])
result.assert_success()
result = cli.run(project=project, args=['workspace', 'close', '--remove-dir', element_name])
result.assert_success()
# Check that workspace config is converted correctly if necessary
loaded_config = _yaml.node_sanitize(_yaml.load(workspace_config_path))
assert loaded_config == parse_dict_as_yaml(expected)
@pytest.mark.datafiles(DATA_DIR)
@pytest.mark.parametrize("kind", repo_kinds)
def test_inconsitent_pipeline_message(cli, tmpdir, datafiles, kind):
element_name, project, workspace = open_workspace(cli, tmpdir, datafiles, kind, False)
shutil.rmtree(workspace)
result = cli.run(project=project, args=[
'build', element_name
])
result.assert_main_error(ErrorDomain.PIPELINE, "inconsistent-pipeline-workspaced")
@pytest.mark.datafiles(DATA_DIR)
@pytest.mark.parametrize("strict", [("strict"), ("non-strict")])
def test_cache_key_workspace_in_dependencies(cli, tmpdir, datafiles, strict):
checkout = os.path.join(str(tmpdir), 'checkout')
element_name, project, workspace = open_workspace(cli, os.path.join(str(tmpdir), 'repo-a'),
datafiles, 'git', False)
element_path = os.path.join(project, 'elements')
back_dep_element_name = 'workspace-test-back-dep.bst'
# Write out our test target
element = {
'kind': 'compose',
'depends': [
{
'filename': element_name,
'type': 'build'
}
]
}
_yaml.dump(element,
os.path.join(element_path,
back_dep_element_name))
# Modify workspace
shutil.rmtree(os.path.join(workspace, 'usr', 'bin'))
os.makedirs(os.path.join(workspace, 'etc'))
with open(os.path.join(workspace, 'etc', 'pony.conf'), 'w') as f:
f.write("PONY='pink'")
# Configure strict mode
strict_mode = True
if strict != 'strict':
strict_mode = False
cli.configure({
'projects': {
'test': {
'strict': strict_mode
}
}
})
# Build artifact with dependency's modified workspace
assert cli.get_element_state(project, element_name) == 'buildable'
assert cli.get_element_key(project, element_name) == "{:?<64}".format('')
assert cli.get_element_state(project, back_dep_element_name) == 'waiting'
assert cli.get_element_key(project, back_dep_element_name) == "{:?<64}".format('')
result = cli.run(project=project, args=['build', back_dep_element_name])
result.assert_success()
assert cli.get_element_state(project, element_name) == 'cached'
assert cli.get_element_key(project, element_name) != "{:?<64}".format('')
assert cli.get_element_state(project, back_dep_element_name) == 'cached'
assert cli.get_element_key(project, back_dep_element_name) != "{:?<64}".format('')
result = cli.run(project=project, args=['build', back_dep_element_name])
result.assert_success()
# Checkout the result
result = cli.run(project=project, args=[
'checkout', back_dep_element_name, checkout
])
result.assert_success()
# Check that the pony.conf from the modified workspace exists
filename = os.path.join(checkout, 'etc', 'pony.conf')
assert os.path.exists(filename)
# Check that the original /usr/bin/hello is not in the checkout
assert not os.path.exists(os.path.join(checkout, 'usr', 'bin', 'hello'))
# This strange test tests against a regression raised in issue #919,
# where opening a workspace on a runtime dependency of a build only
# dependency causes `bst build` to not build the specified target
# but just successfully builds the workspaced element and happily
# exits without completing the build.
#
TEST_DIR = os.path.join(
os.path.dirname(os.path.realpath(__file__))
)
@pytest.mark.datafiles(TEST_DIR)
@pytest.mark.parametrize(
["case", "non_workspaced_elements_state"],
[
("workspaced-build-dep", ["waiting", "waiting", "waiting", "waiting", "waiting"]),
("workspaced-runtime-dep", ["buildable", "buildable", "waiting", "waiting", "waiting"])
],
)
@pytest.mark.parametrize("strict", [("strict"), ("non-strict")])
def test_build_all(cli, tmpdir, datafiles, case, strict, non_workspaced_elements_state):
project = os.path.join(str(datafiles), case)
workspace = os.path.join(str(tmpdir), 'workspace')
non_leaf_elements = ["elem2.bst", "elem3.bst", "stack.bst", "elem4.bst", "elem5.bst"]
all_elements = ["elem1.bst", *non_leaf_elements]
# Configure strict mode
strict_mode = True
if strict != 'strict':
strict_mode = False
cli.configure({
'projects': {
'test': {
'strict': strict_mode
}
}
})
# First open the workspace
result = cli.run(project=project, args=['workspace', 'open', 'elem1.bst', workspace])
result.assert_success()
# Now build the targets elem4.bst and elem5.bst
result = cli.run(project=project, args=['build', 'elem4.bst', 'elem5.bst'])
result.assert_success()
# Assert that the target is built
for element in all_elements:
assert cli.get_element_state(project, element) == 'cached'