diff options
Diffstat (limited to 'tests/integration/shell.py')
-rw-r--r-- | tests/integration/shell.py | 348 |
1 files changed, 161 insertions, 187 deletions
diff --git a/tests/integration/shell.py b/tests/integration/shell.py index 49e9a5950..e331a5fe0 100644 --- a/tests/integration/shell.py +++ b/tests/integration/shell.py @@ -16,10 +16,7 @@ from tests.testutils import create_artifact_share pytestmark = pytest.mark.integration -DATA_DIR = os.path.join( - os.path.dirname(os.path.realpath(__file__)), - "project" -) +DATA_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "project") # execute_shell() @@ -35,28 +32,26 @@ DATA_DIR = os.path.join( # element (str): The element to build and run a shell with # isolate (bool): Whether to pass --isolate to `bst shell` # -def execute_shell(cli, project, command, *, config=None, mount=None, element='base.bst', isolate=False): +def execute_shell(cli, project, command, *, config=None, mount=None, element="base.bst", isolate=False): # Ensure the element is built - result = cli.run_project_config( - project=project, project_config=config, args=['build', element]) + result = cli.run_project_config(project=project, project_config=config, args=["build", element]) assert result.exit_code == 0 - args = ['shell'] + args = ["shell"] if isolate: - args += ['--isolate'] + args += ["--isolate"] if mount is not None: host_path, target_path = mount - args += ['--mount', host_path, target_path] - args += [element, '--', *command] + args += ["--mount", host_path, target_path] + args += [element, "--", *command] - return cli.run_project_config( - project=project, project_config=config, args=args) + return cli.run_project_config(project=project, project_config=config, args=args) # Test running something through a shell, allowing it to find the # executable @pytest.mark.datafiles(DATA_DIR) -@pytest.mark.skipif(not HAVE_SANDBOX, reason='Only available with a functioning sandbox') +@pytest.mark.skipif(not HAVE_SANDBOX, reason="Only available with a functioning sandbox") def test_shell(cli, datafiles): project = str(datafiles) @@ -67,7 +62,7 @@ def test_shell(cli, datafiles): # Test running an executable directly @pytest.mark.datafiles(DATA_DIR) -@pytest.mark.skipif(not HAVE_SANDBOX, reason='Only available with a functioning sandbox') +@pytest.mark.skipif(not HAVE_SANDBOX, reason="Only available with a functioning sandbox") def test_executable(cli, datafiles): project = str(datafiles) @@ -79,19 +74,15 @@ def test_executable(cli, datafiles): # Test shell environment variable explicit assignments @pytest.mark.parametrize("animal", [("Horse"), ("Pony")]) @pytest.mark.datafiles(DATA_DIR) -@pytest.mark.skipif(not HAVE_SANDBOX, reason='Only available with a functioning sandbox') +@pytest.mark.skipif(not HAVE_SANDBOX, reason="Only available with a functioning sandbox") # This test seems to fail or pass depending on if this file is run or the hole test suite def test_env_assign(cli, datafiles, animal): project = str(datafiles) - expected = animal + '\n' + expected = animal + "\n" - result = execute_shell(cli, project, ['/bin/sh', '-c', 'echo ${ANIMAL}'], config={ - 'shell': { - 'environment': { - 'ANIMAL': animal - } - } - }) + result = execute_shell( + cli, project, ["/bin/sh", "-c", "echo ${ANIMAL}"], config={"shell": {"environment": {"ANIMAL": animal}}} + ) assert result.exit_code == 0 assert result.output == expected @@ -100,21 +91,20 @@ def test_env_assign(cli, datafiles, animal): # Test shell environment variable explicit assignments with host env var expansion @pytest.mark.parametrize("animal", [("Horse"), ("Pony")]) @pytest.mark.datafiles(DATA_DIR) -@pytest.mark.skipif(not HAVE_SANDBOX, reason='Only available with a functioning sandbox') +@pytest.mark.skipif(not HAVE_SANDBOX, reason="Only available with a functioning sandbox") # This test seems to fail or pass depending on if this file is run or the hole test suite def test_env_assign_expand_host_environ(cli, datafiles, animal): project = str(datafiles) - expected = 'The animal is: {}\n'.format(animal) + expected = "The animal is: {}\n".format(animal) - os.environ['BEAST'] = animal + os.environ["BEAST"] = animal - result = execute_shell(cli, project, ['/bin/sh', '-c', 'echo ${ANIMAL}'], config={ - 'shell': { - 'environment': { - 'ANIMAL': 'The animal is: ${BEAST}' - } - } - }) + result = execute_shell( + cli, + project, + ["/bin/sh", "-c", "echo ${ANIMAL}"], + config={"shell": {"environment": {"ANIMAL": "The animal is: ${BEAST}"}}}, + ) assert result.exit_code == 0 assert result.output == expected @@ -124,51 +114,42 @@ def test_env_assign_expand_host_environ(cli, datafiles, animal): # when running an isolated shell @pytest.mark.parametrize("animal", [("Horse"), ("Pony")]) @pytest.mark.datafiles(DATA_DIR) -@pytest.mark.skipif(not HAVE_SANDBOX, reason='Only available with a functioning sandbox') +@pytest.mark.skipif(not HAVE_SANDBOX, reason="Only available with a functioning sandbox") # This test seems to faili or pass depending on if this file is run or the hole test suite def test_env_assign_isolated(cli, datafiles, animal): project = str(datafiles) - result = execute_shell(cli, project, ['/bin/sh', '-c', 'echo ${ANIMAL}'], isolate=True, config={ - 'shell': { - 'environment': { - 'ANIMAL': animal - } - } - }) + result = execute_shell( + cli, + project, + ["/bin/sh", "-c", "echo ${ANIMAL}"], + isolate=True, + config={"shell": {"environment": {"ANIMAL": animal}}}, + ) assert result.exit_code == 0 - assert result.output == '\n' + assert result.output == "\n" # Test running an executable in a runtime with no shell (i.e., no # /bin/sh) @pytest.mark.datafiles(DATA_DIR) -@pytest.mark.skipif(not HAVE_SANDBOX, reason='Only available with a functioning sandbox') +@pytest.mark.skipif(not HAVE_SANDBOX, reason="Only available with a functioning sandbox") def test_no_shell(cli, datafiles): project = str(datafiles) - element_path = os.path.join(project, 'elements') - element_name = 'shell/no-shell.bst' + element_path = os.path.join(project, "elements") + element_name = "shell/no-shell.bst" # Create an element that removes /bin/sh from the base runtime element = { - 'kind': 'script', - 'depends': [{ - 'filename': 'base.bst', - 'type': 'build' - }], - 'variables': { - 'install-root': '/' - }, - 'config': { - 'commands': [ - 'rm /bin/sh' - ] - } + "kind": "script", + "depends": [{"filename": "base.bst", "type": "build"}], + "variables": {"install-root": "/"}, + "config": {"commands": ["rm /bin/sh"]}, } os.makedirs(os.path.dirname(os.path.join(element_path, element_name)), exist_ok=True) _yaml.roundtrip_dump(element, os.path.join(element_path, element_name)) - result = execute_shell(cli, project, ['/bin/echo', 'Pegasissies!'], element=element_name) + result = execute_shell(cli, project, ["/bin/echo", "Pegasissies!"], element=element_name) assert result.exit_code == 0 assert result.output == "Pegasissies!\n" @@ -176,99 +157,82 @@ def test_no_shell(cli, datafiles): # Test that bind mounts defined in project.conf work @pytest.mark.parametrize("path", [("/etc/pony.conf"), ("/usr/share/pony/pony.txt")]) @pytest.mark.datafiles(DATA_DIR) -@pytest.mark.skipif(not HAVE_SANDBOX, reason='Only available with a functioning sandbox') -@pytest.mark.xfail(HAVE_SANDBOX == 'buildbox', reason='Not working with BuildBox') +@pytest.mark.skipif(not HAVE_SANDBOX, reason="Only available with a functioning sandbox") +@pytest.mark.xfail(HAVE_SANDBOX == "buildbox", reason="Not working with BuildBox") def test_host_files(cli, datafiles, path): project = str(datafiles) - ponyfile = os.path.join(project, 'files', 'shell-mount', 'pony.txt') - result = execute_shell(cli, project, ['cat', path], config={ - 'shell': { - 'host-files': [ - { - 'host_path': ponyfile, - 'path': path - } - ] - } - }) + ponyfile = os.path.join(project, "files", "shell-mount", "pony.txt") + result = execute_shell( + cli, project, ["cat", path], config={"shell": {"host-files": [{"host_path": ponyfile, "path": path}]}} + ) assert result.exit_code == 0 - assert result.output == 'pony\n' + assert result.output == "pony\n" # Test that bind mounts defined in project.conf work @pytest.mark.parametrize("path", [("/etc"), ("/usr/share/pony")]) @pytest.mark.datafiles(DATA_DIR) -@pytest.mark.skipif(not HAVE_SANDBOX, reason='Only available with a functioning sandbox') -@pytest.mark.xfail(HAVE_SANDBOX == 'buildbox', reason='Not working with BuildBox') +@pytest.mark.skipif(not HAVE_SANDBOX, reason="Only available with a functioning sandbox") +@pytest.mark.xfail(HAVE_SANDBOX == "buildbox", reason="Not working with BuildBox") def test_host_files_expand_environ(cli, datafiles, path): project = str(datafiles) - hostpath = os.path.join(project, 'files', 'shell-mount') - fullpath = os.path.join(path, 'pony.txt') - - os.environ['BASE_PONY'] = path - os.environ['HOST_PONY_PATH'] = hostpath - - result = execute_shell(cli, project, ['cat', fullpath], config={ - 'shell': { - 'host-files': [ - { - 'host_path': '${HOST_PONY_PATH}/pony.txt', - 'path': '${BASE_PONY}/pony.txt' - } - ] - } - }) + hostpath = os.path.join(project, "files", "shell-mount") + fullpath = os.path.join(path, "pony.txt") + + os.environ["BASE_PONY"] = path + os.environ["HOST_PONY_PATH"] = hostpath + + result = execute_shell( + cli, + project, + ["cat", fullpath], + config={ + "shell": {"host-files": [{"host_path": "${HOST_PONY_PATH}/pony.txt", "path": "${BASE_PONY}/pony.txt"}]} + }, + ) assert result.exit_code == 0 - assert result.output == 'pony\n' + assert result.output == "pony\n" # Test that bind mounts defined in project.conf dont mount in isolation @pytest.mark.parametrize("path", [("/etc/pony.conf"), ("/usr/share/pony/pony.txt")]) @pytest.mark.datafiles(DATA_DIR) -@pytest.mark.skipif(not HAVE_SANDBOX, reason='Only available with a functioning sandbox') +@pytest.mark.skipif(not HAVE_SANDBOX, reason="Only available with a functioning sandbox") def test_isolated_no_mount(cli, datafiles, path): project = str(datafiles) - ponyfile = os.path.join(project, 'files', 'shell-mount', 'pony.txt') - result = execute_shell(cli, project, ['cat', path], isolate=True, config={ - 'shell': { - 'host-files': [ - { - 'host_path': ponyfile, - 'path': path - } - ] - } - }) + ponyfile = os.path.join(project, "files", "shell-mount", "pony.txt") + result = execute_shell( + cli, + project, + ["cat", path], + isolate=True, + config={"shell": {"host-files": [{"host_path": ponyfile, "path": path}]}}, + ) assert result.exit_code != 0 assert path in result.stderr - assert 'No such file or directory' in result.stderr + assert "No such file or directory" in result.stderr # Test that we warn about non-existing files on the host if the mount is not # declared as optional, and that there is no warning if it is optional @pytest.mark.parametrize("optional", [("mandatory"), ("optional")]) @pytest.mark.datafiles(DATA_DIR) -@pytest.mark.skipif(not HAVE_SANDBOX, reason='Only available with a functioning sandbox') +@pytest.mark.skipif(not HAVE_SANDBOX, reason="Only available with a functioning sandbox") def test_host_files_missing(cli, datafiles, optional): project = str(datafiles) - ponyfile = os.path.join(project, 'files', 'shell-mount', 'horsy.txt') + ponyfile = os.path.join(project, "files", "shell-mount", "horsy.txt") - option = (optional == "optional") + option = optional == "optional" # Assert that we did successfully run something in the shell anyway - result = execute_shell(cli, project, ['echo', 'Hello'], config={ - 'shell': { - 'host-files': [ - { - 'host_path': ponyfile, - 'path': '/etc/pony.conf', - 'optional': option - } - ] - } - }) + result = execute_shell( + cli, + project, + ["echo", "Hello"], + config={"shell": {"host-files": [{"host_path": ponyfile, "path": "/etc/pony.conf", "optional": option}]}}, + ) assert result.exit_code == 0 - assert result.output == 'Hello\n' + assert result.output == "Hello\n" if option: # Assert that there was no warning about the mount @@ -281,92 +245,100 @@ def test_host_files_missing(cli, datafiles, optional): # Test that bind mounts defined in project.conf work @pytest.mark.parametrize("path", [("/etc/pony.conf"), ("/usr/share/pony/pony.txt")]) @pytest.mark.datafiles(DATA_DIR) -@pytest.mark.skipif(not HAVE_SANDBOX, reason='Only available with a functioning sandbox') -@pytest.mark.xfail(HAVE_SANDBOX == 'buildbox', reason='Not working with BuildBox') +@pytest.mark.skipif(not HAVE_SANDBOX, reason="Only available with a functioning sandbox") +@pytest.mark.xfail(HAVE_SANDBOX == "buildbox", reason="Not working with BuildBox") def test_cli_mount(cli, datafiles, path): project = str(datafiles) - ponyfile = os.path.join(project, 'files', 'shell-mount', 'pony.txt') + ponyfile = os.path.join(project, "files", "shell-mount", "pony.txt") - result = execute_shell(cli, project, ['cat', path], mount=(ponyfile, path)) + result = execute_shell(cli, project, ["cat", path], mount=(ponyfile, path)) assert result.exit_code == 0 - assert result.output == 'pony\n' + assert result.output == "pony\n" # Test that we can see the workspace files in a shell @pytest.mark.datafiles(DATA_DIR) -@pytest.mark.skipif(not HAVE_SANDBOX, reason='Only available with a functioning sandbox') +@pytest.mark.skipif(not HAVE_SANDBOX, reason="Only available with a functioning sandbox") def test_workspace_visible(cli, datafiles): project = str(datafiles) - workspace = os.path.join(cli.directory, 'workspace') - element_name = 'workspace/workspace-mount-fail.bst' + workspace = os.path.join(cli.directory, "workspace") + element_name = "workspace/workspace-mount-fail.bst" # Open a workspace on our build failing element # - res = cli.run(project=project, args=['workspace', 'open', '--directory', workspace, element_name]) + res = cli.run(project=project, args=["workspace", "open", "--directory", workspace, element_name]) assert res.exit_code == 0 # Ensure the dependencies of our build failing element are built - result = cli.run(project=project, args=['build', 'base.bst']) + result = cli.run(project=project, args=["build", "base.bst"]) assert result.exit_code == 0 # Obtain a copy of the hello.c content from the workspace # - workspace_hello_path = os.path.join(cli.directory, 'workspace', 'hello.c') + workspace_hello_path = os.path.join(cli.directory, "workspace", "hello.c") assert os.path.exists(workspace_hello_path) - with open(workspace_hello_path, 'r') as f: + with open(workspace_hello_path, "r") as f: workspace_hello = f.read() # Cat the hello.c file from a bst shell command, and assert # that we got the same content here # - result = cli.run(project=project, args=[ - 'source', 'fetch', element_name]) + result = cli.run(project=project, args=["source", "fetch", element_name]) assert result.exit_code == 0 - result = cli.run(project=project, args=[ - 'shell', '--build', element_name, '--', 'cat', 'hello.c' - ]) + result = cli.run(project=project, args=["shell", "--build", element_name, "--", "cat", "hello.c"]) assert result.exit_code == 0 assert result.output == workspace_hello # Test that '--sysroot' works @pytest.mark.datafiles(DATA_DIR) -@pytest.mark.skipif(not HAVE_SANDBOX, reason='Only available with a functioning sandbox') -@pytest.mark.xfail(HAVE_SANDBOX == 'buildbox', reason='Not working with BuildBox') +@pytest.mark.skipif(not HAVE_SANDBOX, reason="Only available with a functioning sandbox") +@pytest.mark.xfail(HAVE_SANDBOX == "buildbox", reason="Not working with BuildBox") def test_sysroot(cli, tmpdir, datafiles): project = str(datafiles) base_element = "base/base-alpine.bst" # test element only needs to be something lightweight for this test test_element = "script/script.bst" - checkout_dir = os.path.join(str(tmpdir), 'alpine-sysroot') - test_file = 'hello' + checkout_dir = os.path.join(str(tmpdir), "alpine-sysroot") + test_file = "hello" # Build and check out a sysroot - res = cli.run(project=project, args=['build', base_element]) + res = cli.run(project=project, args=["build", base_element]) res.assert_success() - res = cli.run(project=project, args=['artifact', 'checkout', base_element, '--directory', checkout_dir]) + res = cli.run(project=project, args=["artifact", "checkout", base_element, "--directory", checkout_dir]) res.assert_success() # Mutate the sysroot test_path = os.path.join(checkout_dir, test_file) - with open(test_path, 'w') as f: - f.write('hello\n') + with open(test_path, "w") as f: + f.write("hello\n") # Shell into the sysroot and check the test file exists - res = cli.run(project=project, args=[ - 'shell', '--build', '--sysroot', checkout_dir, test_element, '--', - 'grep', '-q', 'hello', '/' + test_file - ]) + res = cli.run( + project=project, + args=[ + "shell", + "--build", + "--sysroot", + checkout_dir, + test_element, + "--", + "grep", + "-q", + "hello", + "/" + test_file, + ], + ) res.assert_success() # Test system integration commands can access devices in /dev @pytest.mark.datafiles(DATA_DIR) -@pytest.mark.skipif(not HAVE_SANDBOX, reason='Only available with a functioning sandbox') +@pytest.mark.skipif(not HAVE_SANDBOX, reason="Only available with a functioning sandbox") def test_integration_devices(cli, datafiles): project = str(datafiles) - element_name = 'integration.bst' + element_name = "integration.bst" result = execute_shell(cli, project, ["true"], element=element_name) assert result.exit_code == 0 @@ -376,79 +348,81 @@ def test_integration_devices(cli, datafiles): @pytest.mark.datafiles(DATA_DIR) @pytest.mark.parametrize("build_shell", [("build"), ("nobuild")]) @pytest.mark.parametrize("guess_element", [True, False], ids=["guess", "no-guess"]) -@pytest.mark.skipif(not HAVE_SANDBOX, reason='Only available with a functioning sandbox') +@pytest.mark.skipif(not HAVE_SANDBOX, reason="Only available with a functioning sandbox") def test_integration_external_workspace(cli, tmpdir_factory, datafiles, build_shell, guess_element): tmpdir = tmpdir_factory.mktemp("") project = str(datafiles) - element_name = 'autotools/amhello.bst' - workspace_dir = os.path.join(str(tmpdir), 'workspace') + element_name = "autotools/amhello.bst" + workspace_dir = os.path.join(str(tmpdir), "workspace") if guess_element: # Mutate the project.conf to use a default shell command - project_file = os.path.join(project, 'project.conf') - config_text = "shell:\n"\ - " command: ['true']\n" - with open(project_file, 'a') as f: + project_file = os.path.join(project, "project.conf") + config_text = "shell:\n" " command: ['true']\n" + with open(project_file, "a") as f: f.write(config_text) - result = cli.run(project=project, args=[ - 'workspace', 'open', '--directory', workspace_dir, element_name - ]) + result = cli.run(project=project, args=["workspace", "open", "--directory", workspace_dir, element_name]) result.assert_success() - result = cli.run(project=project, args=['-C', workspace_dir, 'build', element_name]) + result = cli.run(project=project, args=["-C", workspace_dir, "build", element_name]) result.assert_success() - command = ['-C', workspace_dir, 'shell'] - if build_shell == 'build': - command.append('--build') + command = ["-C", workspace_dir, "shell"] + if build_shell == "build": + command.append("--build") if not guess_element: - command.extend([element_name, '--', 'true']) + command.extend([element_name, "--", "true"]) result = cli.run(project=project, cwd=workspace_dir, args=command) result.assert_success() @pytest.mark.datafiles(DATA_DIR) -@pytest.mark.skipif(not HAVE_SANDBOX, reason='Only available with a functioning sandbox') +@pytest.mark.skipif(not HAVE_SANDBOX, reason="Only available with a functioning sandbox") def test_integration_partial_artifact(cli, datafiles, tmpdir, integration_cache): project = str(datafiles) - element_name = 'autotools/amhello.bst' + element_name = "autotools/amhello.bst" # push to an artifact server so we can pull from it later. - with create_artifact_share(os.path.join(str(tmpdir), 'artifactshare')) as share: - cli.configure({'artifacts': { - 'url': share.repo, - 'push': True - }}) - result = cli.run(project=project, args=['build', element_name]) + with create_artifact_share(os.path.join(str(tmpdir), "artifactshare")) as share: + cli.configure({"artifacts": {"url": share.repo, "push": True}}) + result = cli.run(project=project, args=["build", element_name]) result.assert_success() # If the build is cached then it might not push to the artifact cache - result = cli.run(project=project, args=['artifact', 'push', element_name]) + result = cli.run(project=project, args=["artifact", "push", element_name]) result.assert_success() - result = cli.run(project=project, args=['shell', element_name]) + result = cli.run(project=project, args=["shell", element_name]) result.assert_success() # do a checkout and get the digest of the hello binary. - result = cli.run(project=project, args=[ - 'artifact', 'checkout', '--deps', 'none', - '--directory', os.path.join(str(tmpdir), 'tmp'), - 'autotools/amhello.bst']) + result = cli.run( + project=project, + args=[ + "artifact", + "checkout", + "--deps", + "none", + "--directory", + os.path.join(str(tmpdir), "tmp"), + "autotools/amhello.bst", + ], + ) result.assert_success() - digest = utils.sha256sum(os.path.join(str(tmpdir), 'tmp', 'usr', 'bin', 'hello')) + digest = utils.sha256sum(os.path.join(str(tmpdir), "tmp", "usr", "bin", "hello")) # Remove the binary from the CAS - cachedir = cli.config['cachedir'] - objpath = os.path.join(cachedir, 'cas', 'objects', digest[:2], digest[2:]) + cachedir = cli.config["cachedir"] + objpath = os.path.join(cachedir, "cas", "objects", digest[:2], digest[2:]) os.unlink(objpath) # check shell doesn't work - result = cli.run(project=project, args=['shell', element_name, '--', 'hello']) + result = cli.run(project=project, args=["shell", element_name, "--", "hello"]) result.assert_main_error(ErrorDomain.APP, None) # check the artifact gets completed with '--pull' specified - result = cli.run(project=project, args=['shell', '--pull', element_name, '--', 'hello']) + result = cli.run(project=project, args=["shell", "--pull", element_name, "--", "hello"]) result.assert_success() - assert 'autotools/amhello.bst' in result.get_pulled_elements() + assert "autotools/amhello.bst" in result.get_pulled_elements() |