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)
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)