# 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 import _yaml from buildstream.testing import cli_integration as cli # pylint: disable=unused-import from buildstream.testing._utils.site import HAVE_SANDBOX pytestmark = pytest.mark.integration DATA_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "project") def create_manual_element(name, path, config, variables, environment, sources=None): element = { "kind": "manual", "depends": [{"filename": "base.bst", "type": "build"}], "config": config, "variables": variables, "environment": environment, } if sources: element["sources"] = sources os.makedirs(os.path.dirname(os.path.join(path, name)), exist_ok=True) _yaml.roundtrip_dump(element, os.path.join(path, name)) @pytest.mark.datafiles(DATA_DIR) @pytest.mark.skipif(not HAVE_SANDBOX, reason="Only available with a functioning sandbox") def test_manual_element(cli, datafiles): project = str(datafiles) checkout = os.path.join(cli.directory, "checkout") element_path = os.path.join(project, "elements") element_name = "import/import.bst" create_manual_element( element_name, element_path, { "configure-commands": ["echo './configure' >> test"], "build-commands": ["echo 'make' >> test"], "install-commands": ["echo 'make install' >> test", "cp test %{install-root}"], "strip-commands": ["echo 'strip' >> %{install-root}/test"], }, {}, {}, ) res = cli.run(project=project, args=["build", element_name]) assert res.exit_code == 0 res = cli.run(project=project, args=["artifact", "checkout", element_name, "--directory", checkout]) assert res.exit_code == 0 with open(os.path.join(checkout, "test")) as f: text = f.read() assert ( text == """./configure make make install strip """ ) @pytest.mark.datafiles(DATA_DIR) @pytest.mark.skipif(not HAVE_SANDBOX, reason="Only available with a functioning sandbox") def test_manual_element_environment(cli, datafiles): project = str(datafiles) checkout = os.path.join(cli.directory, "checkout") element_path = os.path.join(project, "elements") element_name = "import/import.bst" create_manual_element( element_name, element_path, {"install-commands": ["echo $V >> test", "cp test %{install-root}"]}, {}, {"V": 2} ) res = cli.run(project=project, args=["build", element_name]) assert res.exit_code == 0 res = cli.run(project=project, args=["artifact", "checkout", element_name, "--directory", checkout]) assert res.exit_code == 0 with open(os.path.join(checkout, "test")) as f: text = f.read() assert text == "2\n" @pytest.mark.datafiles(DATA_DIR) @pytest.mark.skipif(not HAVE_SANDBOX, reason="Only available with a functioning sandbox") def test_manual_element_noparallel(cli, datafiles): project = str(datafiles) checkout = os.path.join(cli.directory, "checkout") element_path = os.path.join(project, "elements") element_name = "import/import.bst" create_manual_element( element_name, element_path, {"install-commands": ["echo $MAKEFLAGS >> test", "echo $V >> test", "cp test %{install-root}"]}, {"notparallel": True}, {"MAKEFLAGS": "-j%{max-jobs} -Wall", "V": 2}, ) res = cli.run(project=project, args=["build", element_name]) assert res.exit_code == 0 res = cli.run(project=project, args=["artifact", "checkout", element_name, "--directory", checkout]) assert res.exit_code == 0 with open(os.path.join(checkout, "test")) as f: text = f.read() assert ( text == """-j1 -Wall 2 """ ) @pytest.mark.datafiles(DATA_DIR) @pytest.mark.skipif(not HAVE_SANDBOX, reason="Only available with a functioning sandbox") def test_manual_element_logging(cli, datafiles): project = str(datafiles) element_path = os.path.join(project, "elements") element_name = "import/import.bst" create_manual_element( element_name, element_path, { "configure-commands": ["echo configure"], "build-commands": ["echo build"], "install-commands": ["echo install"], "strip-commands": ["echo strip"], }, {}, {}, ) res = cli.run(project=project, args=["build", element_name]) assert res.exit_code == 0 # Verify that individual commands are logged assert "echo configure" in res.stderr assert "echo build" in res.stderr assert "echo install" in res.stderr assert "echo strip" in res.stderr # Regression test for https://gitlab.com/BuildStream/buildstream/-/issues/1295. # # Test that the command-subdir variable works as expected. @pytest.mark.datafiles(DATA_DIR) @pytest.mark.skipif(not HAVE_SANDBOX, reason="Only available with a functioning sandbox") def test_manual_command_subdir(cli, datafiles): project = str(datafiles) checkout = os.path.join(cli.directory, "checkout") element_path = os.path.join(project, "elements") element_name = "manual/command-subdir.bst" sources = [{"kind": "local", "path": "files/manual-element/root"}] create_manual_element( element_name, element_path, {"install-commands": ["cp hello %{install-root}"]}, {}, {}, sources=sources, ) # First, verify that element builds, and has the correct expected output. result = cli.run(project=project, args=["build", element_name]) result.assert_success() result = cli.run(project=project, args=["artifact", "checkout", element_name, "--directory", checkout]) result.assert_success() with open(os.path.join(checkout, "hello")) as f: assert f.read() == "hello from root\n" # Now, change element configuration to have a different command-subdir. # This should result in a different cache key. create_manual_element( element_name, element_path, {"install-commands": ["cp hello %{install-root}"]}, {"command-subdir": "subdir"}, {}, sources=sources, ) # Verify that the element needs to be rebuilt. assert cli.get_element_state(project, element_name) == "buildable" # Finally, ensure that the variable actually takes effect. result = cli.run(project=project, args=["build", element_name]) result.assert_success() shutil.rmtree(checkout) result = cli.run(project=project, args=["artifact", "checkout", element_name, "--directory", checkout]) result.assert_success() with open(os.path.join(checkout, "hello")) as f: assert f.read() == "hello from subdir\n" # Test staging artifacts into subdirectories @pytest.mark.datafiles(DATA_DIR) @pytest.mark.skipif(not HAVE_SANDBOX, reason="Only available with a functioning sandbox") def test_manual_stage_custom(cli, datafiles): project = str(datafiles) checkout = os.path.join(cli.directory, "checkout") # Verify that the element builds, and has the correct expected output. result = cli.run(project=project, args=["build", "manual/manual-stage-custom.bst"]) result.assert_success() result = cli.run( project=project, args=["artifact", "checkout", "manual/manual-stage-custom.bst", "--directory", checkout] ) result.assert_success() with open(os.path.join(checkout, "test.txt")) as f: assert f.read() == "This is another test\n"