From 29f93af0aa77bc1733dd9ecc9fdce17481bd1203 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Hozza?= Date: Fri, 14 Feb 2025 09:55:09 +0100 Subject: [PATCH] tools/test/depsolve: factor out search repo combos test case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Testing all repo config combos for each search test case does not really increase the test coverage for repo config combos. It just increases the run time of the test. Move the repo config combos testing to a dedicated test case, which will test search for two packages from two different repositories. For the original `test_search()`, always use repo configs in the request. Signed-off-by: Tomáš Hozza --- tools/test/test_depsolve.py | 106 ++++++++++++++++++++++++++++++++++-- 1 file changed, 101 insertions(+), 5 deletions(-) diff --git a/tools/test/test_depsolve.py b/tools/test/test_depsolve.py index 0a611cdf..c9024e52 100644 --- a/tools/test/test_depsolve.py +++ b/tools/test/test_depsolve.py @@ -1143,6 +1143,52 @@ dump_test_cases = [ ] +search_test_case_basic_2pkgs_2repos = { + "id": "basic_2pkgs_2repos", + "enabled_repos": ["baseos", "custom"], + "search_args": { + "latest": True, + "packages": [ + "zsh", + "pkg-with-no-deps", + ], + }, + "results": [ + { + "name": "zsh", + "summary": "Powerful interactive shell", + "description": """The zsh shell is a command interpreter usable as an interactive login +shell and as a shell script command processor. Zsh resembles the ksh +shell (the Korn shell), but includes many enhancements. Zsh supports +command line editing, built-in spelling correction, programmable +command completion, shell functions (with autoloading), a history +mechanism, and more.""", + "url": "http://zsh.sourceforge.net/", + "repo_id": "baseos", + "epoch": 0, + "version": "5.8", + "release": "9.el9", + "arch": "x86_64", + "buildtime": "2022-02-23T13:47:24Z", + "license": "MIT", + }, + { + 'arch': 'noarch', + 'buildtime': '2024-04-15T18:09:19Z', + 'description': 'Provides pkg-with-no-deps', + 'epoch': 0, + 'license': 'BSD', + 'name': 'pkg-with-no-deps', + 'release': '0', + 'repo_id': 'custom', + 'summary': 'Provides pkg-with-no-deps', + 'url': None, + 'version': '1.0.0', + }, + ], +} + + search_test_cases = [ { "id": "1pkg_latest", @@ -1242,7 +1288,7 @@ mechanism, and more.""", "error_kind": "RepoError", "error_reason_re": r"There was a problem reading a repository: Failed to download metadata.*['\"]broken['\"].*", }, -] +] + [search_test_case_basic_2pkgs_2repos] def make_dnf_scafolding(base_dir): @@ -1593,20 +1639,23 @@ def test_dump(tmp_path, repo_servers, dnf_config, detect_fn, test_case): assert n_filelist_files == 0 -@pytest.mark.parametrize("test_case", search_test_cases, ids=tcase_idfn) @pytest.mark.parametrize("dnf_config, detect_fn", [ (None, assert_dnf), ({"use_dnf5": False}, assert_dnf), ({"use_dnf5": True}, assert_dnf5), ], ids=["no-config", "dnf4", "dnf5"]) -def test_search(tmp_path, repo_servers, dnf_config, detect_fn, test_case): +def test_search_config_combos(tmp_path, repo_servers, dnf_config, detect_fn): + """ + Test all possible configurations of repository configurations for the search function. + Test on a single test case which searches for two packages from two repositories. + """ try: detect_fn() except RuntimeError as e: pytest.skip(str(e)) + test_case = search_test_case_basic_2pkgs_2repos tc_repo_servers = get_test_case_repo_servers(test_case, repo_servers) - search_args = test_case["search_args"] for repo_configs, root_dir, opt_metadata in config_combos(tmp_path, tc_repo_servers): @@ -1620,7 +1669,16 @@ def test_search(tmp_path, repo_servers, dnf_config, detect_fn, test_case): continue assert exit_code == 0 - assert res == test_case["results"] + for res, exp in zip(res, test_case["results"]): + # if the url in the package is empty, DNF4 returns None, DNF5 returns an empty string + exp = exp.copy() + exp_url = exp.pop("url") + res_url = res.pop("url") + if exp_url is None and dnf_config and dnf_config.get("use_dnf5", False): + assert res_url == "" + else: + assert res_url == exp_url + assert res == exp # if opt_metadata includes 'filelists', then each repository 'repodata' must include a file that matches # *filelists* @@ -1631,6 +1689,44 @@ def test_search(tmp_path, repo_servers, dnf_config, detect_fn, test_case): assert n_filelist_files == 0 +@pytest.mark.parametrize("test_case", search_test_cases, ids=tcase_idfn) +@pytest.mark.parametrize("dnf_config, detect_fn", [ + (None, assert_dnf), + ({"use_dnf5": False}, assert_dnf), + ({"use_dnf5": True}, assert_dnf5), +], ids=["no-config", "dnf4", "dnf5"]) +def test_search(repo_servers, dnf_config, detect_fn, test_case): + try: + detect_fn() + except RuntimeError as e: + pytest.skip(str(e)) + + tc_repo_servers = get_test_case_repo_servers(test_case, repo_servers) + repo_configs = [gen_repo_config(server) for server in tc_repo_servers] + search_args = test_case["search_args"] + + with TemporaryDirectory() as cache_dir: + res, exit_code = search(search_args, cache_dir, dnf_config, repo_configs) + + if test_case.get("error", False): + assert exit_code != 0 + assert res["kind"] == test_case["error_kind"] + assert re.match(test_case["error_reason_re"], res["reason"], re.DOTALL) + return + + assert exit_code == 0 + for res, exp in zip(res, test_case["results"]): + # if the url in the package is empty, DNF4 returns None, DNF5 returns an empty string + exp = exp.copy() + exp_url = exp.pop("url") + res_url = res.pop("url") + if exp_url is None and dnf_config and dnf_config.get("use_dnf5", False): + assert res_url == "" + else: + assert res_url == exp_url + assert res == exp + + def test_depsolve_result_api(tmp_path, repo_servers): """ Test the result of depsolve() API.