Ejemplo n.º 1
0
def test_gomod_vendor_without_flag(test_env):
    """
    Validate failing of gomod vendor request without flag.

    Checks:
    * The request failed with expected error message
    """
    env_data = utils.load_test_data(
        "gomod_packages.yaml")["vendored_without_flag"]
    client = utils.Client(test_env["api_url"], test_env["api_auth_type"],
                          test_env.get("timeout"))
    initial_response = client.create_new_request(payload={
        "repo":
        env_data["repo"],
        "ref":
        env_data["ref"],
        "pkg_managers":
        env_data["pkg_managers"],
    }, )
    completed_response = client.wait_for_complete_request(initial_response)
    if test_env.get("strict_mode_enabled"):
        assert completed_response.status == 200
        assert completed_response.data["state"] == "failed"
        error_msg = (
            'The "gomod-vendor" flag must be set when your repository has vendored dependencies'
        )
        assert error_msg in completed_response.data["state_reason"], (
            f"#{completed_response.id}: Request failed correctly, but with unexpected message: "
            f"{completed_response.data['state_reason']}. Expected message was: {error_msg}"
        )
    else:
        utils.assert_properly_completed_response(completed_response)
Ejemplo n.º 2
0
def assert_successful_cached_request(response, env_data, tmpdir, client):
    """
    Provide all verifications for Cachito request with cached dependencies.

    :param Response response: completed Cachito response
    :param dict env_data: the test data
    :param tmpdir: the path to directory with testing files
    :param Client client: the Cachito client to make requests
    """
    utils.assert_properly_completed_response(response)

    response_data = response.data
    expected_response_data = env_data["response_expectations"]
    utils.assert_elements_from_response(response_data, expected_response_data)

    client.download_and_extract_archive(response.id, tmpdir)
    source_path = tmpdir.join(f"download_{str(response.id)}")
    expected_files = env_data["expected_files"]
    utils.assert_expected_files(source_path, expected_files, tmpdir)

    purl = env_data["purl"]
    deps_purls = []
    source_purls = []
    if "dep_purls" in env_data:
        deps_purls = [{"purl": x} for x in env_data["dep_purls"]]
    if "source_purls" in env_data:
        source_purls = [{"purl": x} for x in env_data["source_purls"]]

    image_contents = [{"dependencies": deps_purls, "purl": purl, "sources": source_purls}]
    utils.assert_content_manifest(client, response.id, image_contents)
def test_git_dir_not_included_by_default(test_env, default_requests, tmpdir):
    """
    Check that the bundle does not include the .git file objects by default.

    Process:
    * Send new request to Cachito API
    * Send request to download appropriate bundle from Cachito

    Checks:
    * Check that response code is 200
    * Check that state is "complete"
    * Check the downloaded data are in gzip format and valid
    * Check that downloaded data does not contain any .git files
    """
    response = default_requests["gomod"].complete_response
    utils.assert_properly_completed_response(response)
    client = utils.Client(test_env["api_url"], test_env["api_auth_type"], test_env.get("timeout"))

    client.download_and_extract_archive(response.id, tmpdir)
    file_name_tar = tmpdir.join(f"download_{str(response.id)}.tar.gz")

    with tarfile.open(file_name_tar, mode="r:gz") as tar:
        git_files = {
            member.name for member in tar.getmembers() if path.basename(member.name) == ".git"
        }

    assert not git_files, (
        f"#{response.id}: There are unexpected .git files in archive {file_name_tar}: "
        f"{git_files}"
    )
Ejemplo n.º 4
0
def test_run_app_from_bundle(test_env, default_requests, tmpdir):
    """
    Check that downloaded bundle could be used to run the application.

    Process:
    * Send new request to Cachito API
    * Download a bundle from the request
    * Run go build
    * Run the application

    Checks:
    * Check that the state of request is complete
    * Check that the bundle is properly downloaded
    * Check that the application runs successfully
    """
    response = default_requests["gomod"].complete_response
    utils.assert_properly_completed_response(response)

    client = utils.Client(test_env["api_url"], test_env["api_auth_type"],
                          test_env.get("timeout"))
    client.download_and_extract_archive(response.id, tmpdir)
    bundle_dir = tmpdir.join(f"download_{str(response.id)}")
    app_name = test_env["run_app"]["app_name"]
    app_binary_file = str(tmpdir.join(app_name))
    subprocess.run(
        [
            "go", "build", "-o", app_binary_file,
            str(bundle_dir.join("app", "main.go"))
        ],
        env={
            "GOPATH":
            str(bundle_dir.join("deps", "gomod")),
            "GOCACHE":
            str(bundle_dir.join("deps", "gomod")),
            "GOMODCACHE":
            "{}/pkg/mod".format(str(bundle_dir.join("deps", "gomod"))),
        },
        cwd=str(bundle_dir.join("app")),
        check=True,
    )

    assert path.exists(
        app_binary_file
    ), f"#{response.id}: Path for application binary file {app_binary_file} does not exist"
    sp = subprocess.run([app_binary_file, "--help"],
                        stdout=subprocess.PIPE,
                        stderr=subprocess.PIPE)
    assert sp.returncode == 0
Ejemplo n.º 5
0
def test_various_packages(test_env):
    client = utils.Client(test_env["api_url"], test_env["api_auth_type"],
                          test_env.get("timeout"))
    for pkg_manager, package in test_env["various_packages"].items():
        initial_response = client.create_new_request(payload={
            "repo":
            package["repo"],
            "ref":
            package["ref"],
            "pkg_managers": [pkg_manager],
        }, )
        completed_response = client.wait_for_complete_request(initial_response)
        utils.assert_properly_completed_response(completed_response)

        assert len(completed_response.data["dependencies"]
                   ) == package["dependencies_count"]
Ejemplo n.º 6
0
def test_npm_basic(test_env, default_requests):
    """
    A basic integration test for the npm package manager.

    Process:
    * Send new request to the Cachito API
    * Send request to check status of existing request

    Checks:
    * Verify that the request completes successfully
    * Verify that there is a correct package entry
    * Verify that there is a correct number of dependencies
    * Verify that the tslib dependency is not a dev dependency (dev key in the dependencies array)
    * Verify that the other dependencies are dev (dev key in the dependencies array)
    * Verify that the environment variables "CHROMEDRIVER_SKIP_DOWNLOAD": "true",
        "CYPRESS_INSTALL_BINARY": "0", "GECKODRIVER_SKIP_DOWNLOAD": "true",
        and "SKIP_SASS_BINARY_DOWNLOAD_FOR_CI": "true" are set.
    """
    response = default_requests["npm"].complete_response
    utils.assert_properly_completed_response(response)

    response_packages = utils.make_list_of_packages_hashable(
        response.data["packages"])
    expected_packages = test_env["get"]["npm"]["packages"]
    assert response_packages == expected_packages

    assert len(response.data["dependencies"]
               ) == test_env["get"]["npm"]["dependencies_count"]

    for item in response.data["dependencies"]:
        if item["name"] not in test_env["get"]["npm"]["non_dev_dependencies"]:
            assert item["dev"], (
                f"dependency {item['name']} is not listed as non-dev in the test expectations,"
                f"but is listed as non-dev in the response")
        else:
            assert not item["dev"], (
                f"dependency {item['name']} is listed as non-dev in the test expectations,"
                f"but is not listed as non-dev in the response")

    env_variables = response.data["environment_variables"]
    assert env_variables["CHROMEDRIVER_SKIP_DOWNLOAD"] == "true"
    assert env_variables["CYPRESS_INSTALL_BINARY"] == "0"
    assert env_variables["GECKODRIVER_SKIP_DOWNLOAD"] == "true"
    assert env_variables["SKIP_SASS_BINARY_DOWNLOAD_FOR_CI"] == "true"
Ejemplo n.º 7
0
def test_git_dir_included_by_flag(test_env, tmpdir):
    """
    Check that the bundle includes the .git file objects when include-git-dir flag is used.

    Process:
    * Send new request to Cachito API
    * Send request to download appropriate bundle from Cachito

    Checks:
    * Check that response code is 200
    * Check that state is "complete"
    * Check the downloaded data are in gzip format and valid
    * Check that downloaded data contains app/.git file object, directory
    """
    package_info = test_env["packages"]["gomod"]
    client = utils.Client(test_env["api_url"], test_env["api_auth_type"],
                          test_env.get("timeout"))
    initial_response = client.create_new_request(payload={
        "repo":
        package_info["repo"],
        "ref":
        package_info["ref"],
        "pkg_managers":
        package_info["pkg_managers"],
        "flags": ["include-git-dir"],
    }, )
    response = client.wait_for_complete_request(initial_response)
    utils.assert_properly_completed_response(response)

    client.download_and_extract_archive(response.id, tmpdir)
    file_name_tar = tmpdir.join(f"download_{str(response.id)}.tar.gz")

    with tarfile.open(file_name_tar, mode="r:gz") as tar:
        git_files = {
            member.name
            for member in tar.getmembers()
            if path.basename(member.name) == ".git"
        }

    assert git_files == {
        "app/.git"
    }, (f"#{response.id}: There are unexpected, or missing, .git files in archive {file_name_tar}: "
        f"{git_files}")
Ejemplo n.º 8
0
    def test_using_cached_packages(self, tmpdir, test_env):
        """
        Check that the cached packages are used instead of downloading them from repo again.

        Preconditions:
        * On git instance prepare an empty repository

        Process:
        * Clone the package from the upstream repository
        * Create empty commit on new test branch and push it to the prepared repository
        * Send new request to Cachito API which would fetch data from the prepared repository
        * Delete branch with the corresponding commit
        * Send the same request to Cachito API

        Checks:
        * Check that the state of the first request is complete
        * Check that the commit is not available in the repository after the branch is deleted
        * Check that the state of the second request is complete
        """
        generated_suffix = "".join(
            random.choice(string.ascii_letters + string.digits) for x in range(10)
        )
        branch_name = f"test-{generated_suffix}"
        repo = git.repo.Repo.clone_from(self.env_data["seed_repo"]["https_url"], tmpdir)
        remote = repo.create_remote("test", url=self.env_data["test_repo"]["ssh_url"])
        assert remote.exists(), f"Remote {remote.name} does not exist"

        # set user configuration, if available
        if self.git_user:
            repo.config_writer().set_value("user", "name", self.git_user).release()
        if self.git_email:
            repo.config_writer().set_value("user", "email", self.git_email).release()

        try:
            repo.create_head(branch_name).checkout()
            repo.git.commit("--allow-empty", m="Commit created in integration test for Cachito")
            repo.git.push("-u", remote.name, branch_name)
            commit = repo.head.commit.hexsha

            client = utils.Client(
                test_env["api_url"], test_env["api_auth_type"], test_env.get("timeout"),
            )
            response = client.create_new_request(
                payload={
                    "repo": self.env_data["test_repo"]["https_url"],
                    "ref": commit,
                    "pkg_managers": self.env_data["test_repo"]["pkg_managers"],
                },
            )
            first_response = client.wait_for_complete_request(response)
            utils.assert_properly_completed_response(first_response)
            assert repo.git.branch(
                "-a", "--contains", commit
            ), f"Commit {commit} is not in branches (it should be there)."

        finally:
            delete_branch_and_check(branch_name, repo, remote, [commit])

        response = client.create_new_request(
            payload={
                "repo": self.env_data["test_repo"]["https_url"],
                "ref": commit,
                "pkg_managers": self.env_data["test_repo"]["pkg_managers"],
            },
        )
        second_response = client.wait_for_complete_request(response)
        utils.assert_properly_completed_response(second_response)
        assert first_response.data["ref"] == second_response.data["ref"]
        assert first_response.data["repo"] == second_response.data["repo"]
        assert set(first_response.data["pkg_managers"]) == set(second_response.data["pkg_managers"])
        first_pkgs = utils.make_list_of_packages_hashable(first_response.data["packages"])
        second_pkgs = utils.make_list_of_packages_hashable(second_response.data["packages"])
        assert first_pkgs == second_pkgs
        first_deps = utils.make_list_of_packages_hashable(first_response.data["dependencies"])
        second_deps = utils.make_list_of_packages_hashable(second_response.data["dependencies"])
        assert first_deps == second_deps
def test_check_downloaded_output(test_env, default_requests, tmpdir):
    """
    Check that the bundle has all the necessities.

    Process:
    * Send new request to Cachito API
    * Send request to download appropriate bundle from Cachito

    Checks:
    * Check that response code is 200
    * Check that state is "complete"
    * Check the downloaded data are in gzip format and valid
    * Check that dir deps/gomod/… contains cached dependencies
    * Check that dir app/ contains application source code
    * Check that the same full path filename is not duplicated
    """
    response = default_requests["gomod"].complete_response
    utils.assert_properly_completed_response(response)
    client = utils.Client(test_env["api_url"], test_env["api_auth_type"], test_env.get("timeout"))

    file_name = tmpdir.join(f"download_{str(response.id)}")
    client.download_and_extract_archive(response.id, tmpdir)

    pkg_managers = test_env["downloaded_output"]["pkg_managers"]
    dependencies_path = path.join("deps", "gomod", "pkg", "mod", "cache", "download")
    names = [i["name"] for i in response.data["dependencies"] if i["type"] in pkg_managers]
    for dependency in names:
        package_name = utils.escape_path_go(dependency)
        dependency_path = path.join(file_name, dependencies_path, package_name)
        assert path.exists(
            dependency_path
        ), f"#{response.id}: Dependency path does not exist: {dependency_path}"

    go_mod_path = path.join(file_name, "app", "go.mod")
    assert path.exists(
        go_mod_path
    ), f"#{response.id}: File go.mod does not exist in location: {go_mod_path}"
    with open(go_mod_path, "r") as file:
        module_names = []
        for line in file:
            if line.startswith("module "):
                module_names.append(line.split()[-1])
                break
        expected_packages = [
            i["name"] for i in response.data["packages"] if i["type"] in pkg_managers
        ]
        assert set(module_names) == set(expected_packages)

    list_go_files = []
    for app_path in Path(path.join(file_name, "app")).rglob("*.go"):
        list_go_files.append(app_path)
    assert len(list_go_files) > 0

    file_name_tar = tmpdir.join(f"download_{str(response.id)}.tar.gz")
    with tarfile.open(file_name_tar, mode="r:gz") as tar:
        members = tar.getmembers()
        path_names = set()
        for dependency in members:
            assert dependency.name not in path_names, (
                f"#{response.id}: There is an unexpected duplicate {dependency.name} "
                f"in archive {file_name_tar}"
            )
            path_names.add(dependency.name)
Ejemplo n.º 10
0
def test_dependency_replacement(test_env, tmpdir):
    """
    Check that proper versions of dependencies were used.

    Process:
    * Send new request to Cachito API to fetch retrodep with another version of dependency package
    * Download a bundle archive

    Checks:
    * Check that the state of request is complete
    * Check that in the response there is a key "replaces" with dict values which was replaced
    * Check that dir deps/gomod/pkg/mod/cache/download/github.com/pkg/errors/@v/… contains
        only the required version
    * Check that app/go.mod file has replace directive for the specified package
    """
    dependency_replacements = test_env["dep_replacement"][
        "dependency_replacements"]
    client = utils.Client(test_env["api_url"], test_env["api_auth_type"],
                          test_env.get("timeout"))
    response_created_req = client.create_new_request(payload={
        "repo":
        test_env["packages"]["gomod"]["repo"],
        "ref":
        test_env["packages"]["gomod"]["ref"],
        "pkg_managers":
        test_env["packages"]["gomod"]["pkg_managers"],
        "dependency_replacements":
        dependency_replacements,
    }, )
    response = client.wait_for_complete_request(response_created_req)
    utils.assert_properly_completed_response(response)

    names_replaced_dependencies = {
        i["replaces"]["name"]
        for i in response.data["dependencies"] if i["replaces"] is not None
    }
    supposed_replaced_dependencies = set(i["name"]
                                         for i in dependency_replacements)
    assert names_replaced_dependencies == supposed_replaced_dependencies

    bundle_dir_name = tmpdir.join(f"download_{str(response.id)}")
    client.download_and_extract_archive(response.id, tmpdir)

    for dependency in dependency_replacements:
        dep_name = utils.escape_path_go(dependency["name"])
        dependency_version_file = path.join(
            bundle_dir_name,
            "deps",
            "gomod",
            "pkg",
            "mod",
            "cache",
            "download",
            dep_name,
            "@v",
            "list",
        )
        assert path.exists(dependency_version_file), (
            f"#{response.id}: Path for version of dependency "
            f"{dep_name} does not exist: {dependency_version_file}")
        with open(dependency_version_file, "r") as file:
            lines = {line.rstrip() for line in file.readlines()}
            assert dependency["version"] in lines, (
                f"#{response.id}: File {dependency_version_file} does not contain"
                f" version {dependency['version']} that should have replaced the original one."
            )

    go_mod_path = path.join(bundle_dir_name, "app", "go.mod")
    assert path.exists(
        go_mod_path
    ), f"#{response.id}: File go.mod does not exist in location: {go_mod_path}"
    with open(go_mod_path, "r") as file:
        go_mod_replace = []
        for line in file:
            if line.startswith("replace "):
                go_mod_replace.append({
                    "name": line.split()[-2],
                    "type": "gomod",
                    "version": line.split()[-1]
                })
        sorted_dep_replacements = utils.make_list_of_packages_hashable(
            dependency_replacements)
        sorted_go_mod_replace = utils.make_list_of_packages_hashable(
            go_mod_replace)
        assert sorted_go_mod_replace == sorted_dep_replacements