Exemple #1
0
    def test_cache_config(self):
        cache = ClientCache(temp_folder(), TestBufferConanOutput())
        file_path = os.path.join(cache.cache_folder, "whatever_cacert")
        replace_in_file(cache.conan_conf_path,
                        "# cacert_path",
                        "cacert_path={}".format(file_path),
                        output=TestBufferConanOutput())
        save(file_path, "")
        cache.invalidate()

        requester = ConanRequester(cache.config)
        mocked_requester = MockRequesterGet()
        requester._http_requester = mocked_requester
        requester.get(url="bbbb", verify=True)
        self.assertEqual(mocked_requester.verify, file_path)
Exemple #2
0
class TestClient(object):
    """ Test wrap of the conans application to launch tests in the same way as
    in command line
    """
    def __init__(self,
                 base_folder=None,
                 current_folder=None,
                 servers=None,
                 users=None,
                 requester_class=None,
                 runner=None,
                 path_with_spaces=True,
                 revisions_enabled=None,
                 cpu_count=1):
        """
        storage_folder: Local storage path
        current_folder: Current execution folder
        servers: dict of {remote_name: TestServer}
        logins is a list of (user, password) for auto input in order
        if required==> [("lasote", "mypass"), ("other", "otherpass")]
        """

        self.all_output = ""  # For debugging purpose, append all the run outputs
        self.users = users
        if self.users is None:
            self.users = {
                "default":
                [(TESTING_REMOTE_PRIVATE_USER, TESTING_REMOTE_PRIVATE_PASS)]
            }

        self.base_folder = base_folder or temp_folder(path_with_spaces)

        # Define storage_folder, if not, it will be read from conf file & pointed to real user home
        self.storage_folder = os.path.join(self.base_folder, ".conan", "data")
        self.cache = ClientCache(self.base_folder, self.storage_folder,
                                 TestBufferConanOutput())

        self.requester_class = requester_class
        self.conan_runner = runner

        if revisions_enabled is None:
            revisions_enabled = get_env("TESTING_REVISIONS_ENABLED", False)

        self.tune_conan_conf(base_folder, cpu_count, revisions_enabled)

        if servers and len(servers) > 1 and not isinstance(
                servers, OrderedDict):
            raise Exception(
                """Testing framework error: Servers should be an OrderedDict. e.g:
servers = OrderedDict()
servers["r1"] = server
servers["r2"] = TestServer()
""")

        self.servers = servers or {}
        if servers is not False:  # Do not mess with registry remotes
            self.update_servers()

        self.init_dynamic_vars()

        logger.debug("Client storage = %s" % self.storage_folder)
        self.current_folder = current_folder or temp_folder(path_with_spaces)

    def _set_revisions(self, value):
        current_conf = load(self.cache.conan_conf_path)
        if "revisions_enabled" in current_conf:  # Invalidate any previous value to be sure
            replace_in_file(self.cache.conan_conf_path,
                            "revisions_enabled",
                            "#revisions_enabled",
                            output=TestBufferConanOutput())

        replace_in_file(self.cache.conan_conf_path,
                        "[general]",
                        "[general]\nrevisions_enabled = %s" % value,
                        output=TestBufferConanOutput())
        # Invalidate the cached config
        self.cache.invalidate()

    def enable_revisions(self):
        self._set_revisions("1")
        assert self.cache.config.revisions_enabled

    def disable_revisions(self):
        self._set_revisions("0")
        assert not self.cache.config.revisions_enabled

    def tune_conan_conf(self, base_folder, cpu_count, revisions_enabled):
        # Create the default
        self.cache.config

        if cpu_count:
            replace_in_file(self.cache.conan_conf_path,
                            "# cpu_count = 1",
                            "cpu_count = %s" % cpu_count,
                            output=TestBufferConanOutput(),
                            strict=not bool(base_folder))

        current_conf = load(self.cache.conan_conf_path)
        if "revisions_enabled" in current_conf:  # Invalidate any previous value to be sure
            replace_in_file(self.cache.conan_conf_path,
                            "revisions_enabled",
                            "#revisions_enabled",
                            output=TestBufferConanOutput())
        if revisions_enabled:
            replace_in_file(self.cache.conan_conf_path,
                            "[general]",
                            "[general]\nrevisions_enabled = 1",
                            output=TestBufferConanOutput())

        # Invalidate the cached config
        self.cache.invalidate()

    def update_servers(self):
        save(self.cache.registry_path, dump_registry({}, {}, {}))
        registry = self.cache.registry

        def add_server_to_registry(name, server):
            if isinstance(server, ArtifactoryServer):
                registry.remotes.add(name, server.repo_api_url)
                self.users.update({
                    name:
                    [(ARTIFACTORY_DEFAULT_USER, ARTIFACTORY_DEFAULT_PASSWORD)]
                })
            elif isinstance(server, TestServer):
                registry.remotes.add(name, server.fake_url)
            else:
                registry.remotes.add(name, server)

        for name, server in self.servers.items():
            if name == "default":
                add_server_to_registry(name, server)

        for name, server in self.servers.items():
            if name != "default":
                add_server_to_registry(name, server)

    @property
    def default_compiler_visual_studio(self):
        settings = self.cache.default_profile.settings
        return settings.get("compiler", None) == "Visual Studio"

    @property
    def out(self):
        return self.user_io.out

    @contextmanager
    def chdir(self, newdir):
        old_dir = self.current_folder
        if not os.path.isabs(newdir):
            newdir = os.path.join(old_dir, newdir)
        mkdir(newdir)
        self.current_folder = newdir
        try:
            yield
        finally:
            self.current_folder = old_dir

    def _init_collaborators(self, user_io=None):

        output = TestBufferConanOutput()
        self.user_io = user_io or MockedUserIO(self.users, out=output)
        self.cache = ClientCache(self.base_folder, self.storage_folder, output)
        self.runner = TestRunner(output, runner=self.conan_runner)

        # Check if servers are real
        real_servers = False
        for server in self.servers.values():
            if isinstance(server, str) or isinstance(
                    server, ArtifactoryServer):  # Just URI
                real_servers = True
                break

        with tools.environment_append(self.cache.config.env_vars):
            if real_servers:
                requester = requests.Session()
            else:
                if self.requester_class:
                    requester = self.requester_class(self.servers)
                else:
                    requester = TestRequester(self.servers)

            self.requester = ConanRequester(requester, self.cache,
                                            get_request_timeout())

            self.hook_manager = HookManager(self.cache.hooks_path,
                                            get_env("CONAN_HOOKS", list()),
                                            self.user_io.out)

            self.localdb, self.rest_api_client, self.remote_manager = \
                Conan.instance_remote_manager(self.requester, self.cache,
                                              self.user_io, self.hook_manager)
            return output, self.requester

    def init_dynamic_vars(self, user_io=None):
        # Migration system
        self.cache = migrate_and_get_cache(self.base_folder,
                                           TestBufferConanOutput(),
                                           storage_folder=self.storage_folder)

        # Maybe something have changed with migrations
        return self._init_collaborators(user_io)

    def run(self, command_line, user_io=None, assert_error=False):
        """ run a single command as in the command line.
            If user or password is filled, user_io will be mocked to return this
            tuple if required
        """
        output, requester = self.init_dynamic_vars(user_io)
        with tools.environment_append(self.cache.config.env_vars):
            # Settings preprocessor
            interactive = not get_env("CONAN_NON_INTERACTIVE", False)
            conan = Conan(self.cache,
                          self.user_io,
                          self.runner,
                          self.remote_manager,
                          self.hook_manager,
                          requester,
                          interactive=interactive)
        outputer = CommandOutputer(self.user_io, self.cache)
        command = Command(conan, self.cache, self.user_io, outputer)
        args = shlex.split(command_line)
        current_dir = os.getcwd()
        os.chdir(self.current_folder)
        old_path = sys.path[:]
        sys.path.append(os.path.join(self.cache.conan_folder, "python"))
        old_modules = list(sys.modules.keys())

        old_output, old_requester = set_global_instances(output, requester)
        try:
            error = command.run(args)
        finally:
            set_global_instances(old_output, old_requester)
            sys.path = old_path
            os.chdir(current_dir)
            # Reset sys.modules to its prev state. A .copy() DOES NOT WORK
            added_modules = set(sys.modules).difference(old_modules)
            for added in added_modules:
                sys.modules.pop(added, None)

        if (assert_error and not error) or (not assert_error and error):
            if assert_error:
                msg = " Command succeeded (failure expected): "
            else:
                msg = " Command failed (unexpectedly): "
            exc_message = "\n{header}\n{cmd}\n{output_header}\n{output}\n{output_footer}\n".format(
                header='{:-^80}'.format(msg),
                output_header='{:-^80}'.format(" Output: "),
                output_footer='-' * 80,
                cmd=command_line,
                output=self.user_io.out)
            raise Exception(exc_message)

        self.all_output += str(self.user_io.out)
        return error

    def save(self, files, path=None, clean_first=False):
        """ helper metod, will store files in the current folder
        param files: dict{filename: filecontents}
        """
        path = path or self.current_folder
        if clean_first:
            shutil.rmtree(self.current_folder, ignore_errors=True)
        save_files(path, files)
        if not files:
            mkdir(self.current_folder)