import logging import git import pytest from cloner_test_fixtures import support_data_path, path_repo_base, path_repo_changed_branches, \ path_repo_different_tags, path_repo_new_commits, path_repo_reduced from pathlib import Path from repo_cloner.lib.repo_tool import RepoTool base_repo_branches = [ ('br0', '1fe320fe278a40bfd6813860d9952b03caf5e2ea'), ('branch-a', '71ce433cd98f899c723184b9ea1e0bcdf97d5c1a'), ('branch-d', '5551c9980c9ff2b94865596df35e38527d9fcfbd'), ( 'dependabot/npm_and_yarn/dot-github/actions/test-action/node-fetch-2.6.7', '8298c84342db5cb93972426188f06431fc498681'), ('master', 'e0c7e2a72579e24657c05e875201011d2b48bf94'), ('orph', '3de11d7640ed17f93ce38d31c9dea0fd65774077'), ('pr-1', '378d1f9e27dbacfcad0ee93355f0305c6c4432f1'), ('pr-3', 'e2bf0be1b64f345077fa96671d1c27f0c3476ac4'), ('release/1.2.3', 'f5eee554aecbee6f2f8e18de089476c3bf957ddc'), ('release/4.5.6', 'be3cb4b2590091dbaf5ce0d861da0f7979c5fc23'), ('release/7.7.10', '23478a09ad05642d64f44920f3247f7708d4bcae'), ('release/7.7.11', 'c014e918175915e07eef0150984a24ff8c33e154'), ('release/7.7.12', 'a7c8068c7c0a45f842400ffb2c4a245ab2f7a388'), ('release/7.7.13', 'c49c48572f1422e8b222db854d7ecbeba27b8020'), ('release/7.7.7', 'da67fad037eea0c065a5ea52a894d5522eb9f248'), ('release/7.7.8', '85003adc6bc0e91391edd97efb7f515cbd6d303e'), ('release/7.7.9', '73aaf9a4377bab721ba716776e81dc76bec25beb'), ('symlink-readme', '8a2844f55fc1adde2e346d0999ef3e12aafbe511'), ('v1/foo/bar', '6e3325f7dc37f67b48e719de1ce4a4c9d33d1042'), ('v1/nix', 'c55e6953ff343f9eeb42dc04eb6aa5dfed6f0756')] base_repo_tags = [ ('meh', '703de123eaa9832f4ce15baf6b702cd7f72fea5a'), ('v', '85003adc6bc0e91391edd97efb7f515cbd6d303e'), ('v1.2.3', '8f3d75c010a30babe3ee8a4176bb16136c5949b3'), ('v4.5.6', '8a2844f55fc1adde2e346d0999ef3e12aafbe511'), ('v7.7.10', '23478a09ad05642d64f44920f3247f7708d4bcae'), ('v7.7.11', 'c014e918175915e07eef0150984a24ff8c33e154'), ('v7.7.12', 'a7c8068c7c0a45f842400ffb2c4a245ab2f7a388'), ('v7.7.13', 'c49c48572f1422e8b222db854d7ecbeba27b8020'), ('v7.7.9', 'dd62ea5560a6944a04c1f8fbdbbb09c01f1b4a21'), ('wip-001', 'adbb090758d7bc201a35b5a7a470a3c01a3e5a95'), ('wip-002', 'a05c54d8623558963b8774bb01962fe0683c46bf'), ('wip-003', 'd3e906333be8a6ff09f96e827199d51694a16dc1'), ('wip-r/1', '030cc2b97d8ecbf07b7bd361105f07e631393f00')] def test_init(support_data_path: Path): test_repos_path = support_data_path.joinpath("tool_repos") # test on non-existent dir rt = RepoTool(test_repos_path.joinpath("nonexistent.git").as_posix()) assert not rt.initialized # uninitialized, but existing repo rt = RepoTool(test_repos_path.joinpath("uninitialized.git").as_posix()) assert not rt.initialized assert not rt.bare # initialized, existing repo rt = RepoTool(test_repos_path.joinpath("initialized.git").as_posix()) assert rt.initialized assert rt.bare rt = RepoTool(test_repos_path.joinpath("non-bare-init").as_posix()) assert rt.initialized assert not rt.bare def test_initialized(tmp_path, monkeypatch): rt = RepoTool(tmp_path.as_posix()) monkeypatch.setattr(rt, "_initialized", False) assert not rt.initialized monkeypatch.setattr(rt, "_initialized", True) assert rt.initialized def test_bare(tmp_path, monkeypatch): rt = RepoTool(tmp_path.as_posix()) monkeypatch.setattr(rt, "_bare", False) assert not rt.bare monkeypatch.setattr(rt, "_bare", True) assert rt.bare def test_path(tmp_path, monkeypatch): rt = RepoTool(tmp_path.as_posix()) assert tmp_path.as_posix() == rt.path monkeypatch.setattr(rt, "_path", "/tmp") assert "/tmp" == rt.path def test_cloned_submodules_url_list(tmp_path, monkeypatch): rt = RepoTool(tmp_path.as_posix()) assert rt.cloned_submodules_url_list == [] monkeypatch.setattr(rt, "_recursive_discovery_cloned", {"https://repo.git/1", "git@hosting:/name/repo.git"}) assert rt.cloned_submodules_url_list == list({"https://repo.git/1", "git@hosting:/name/repo.git"}) def test_discovered_submodules_commits(tmp_path, monkeypatch): commits = [ 'a22b74fba976631f123d4b2348aba531cf6430fd', 'b1b0554e60fc5f0feb542bf54d1cadbc1d0418d6', 'd0c808ab0fc075497cb50d9c704b024bcc6cfa95', 'f8e168561a824da72f7d441932e77f3912039f9a,', '8a150c63c5b688f39db15769db5c7d7c0fd52349', ] rt = RepoTool(tmp_path.as_posix()) assert rt.discovered_submodules_commits == [] monkeypatch.setattr(rt, "_submodule_discovery_history", commits) assert rt.discovered_submodules_commits == commits def test_clone_initialized_repo(tmp_path, caplog, support_data_path): from git import Repo # initialize repo Repo().init(tmp_path, bare = True) rt = RepoTool(tmp_path.as_posix()) # check it assert rt.initialized assert rt.bare # try clone test_repo = support_data_path.joinpath("test-repo-base").as_uri() assert not rt.clone(test_repo) r = caplog.records[0] assert r.levelname == "WARNING" assert r.message == "Trying to clone to initialized repository!" def test_check_initialized(tmp_path, monkeypatch, caplog): # hard testing directly, testing via fetch rt = RepoTool(tmp_path.as_posix()) assert not rt.initialized assert not rt.fetch() assert caplog.records[1].levelname == "CRITICAL" assert caplog.records[1].message == f"Repo {tmp_path.as_posix()} is not initialized!" def test_clone_okay(tmp_path, caplog, support_data_path): rt = RepoTool(tmp_path.as_posix()) assert not rt.initialized caplog.set_level(logging.INFO) # try clone test_repo = support_data_path.joinpath("test-repo-base").as_uri() assert rt.clone(test_repo) # warning about uninit repo assert caplog.records[0].levelname == "WARNING" # info cloning assert caplog.records[1].levelname == "INFO" assert "Cloning repository from url: file:///" in caplog.records[1].message # progress states counting_cnt = 0 compressing_cnt = 0 receiving_cnt = 0 resolving_cnt = 0 for x in range(1, len(caplog.records)): rec = caplog.records[x] assert rec.levelname == "INFO" if "GIT COUNTING" in rec.message: counting_cnt += 1 if "GIT COMPRESSING" in rec.message: compressing_cnt += 1 if "GIT RECEIVING" in rec.message: receiving_cnt += 1 if "GIT RESOLVING" in rec.message: resolving_cnt += 1 assert counting_cnt >= 2 assert compressing_cnt >= 2 assert receiving_cnt >= 2 assert resolving_cnt >= 2 def test_fetch_uninitialized(tmp_path, caplog): repo_a = tmp_path.joinpath("A.git") repo_a.mkdir() rt = RepoTool(repo_a.as_posix()) assert not rt.initialized assert not rt.fetch() assert f"Repo {repo_a.as_posix()} is not initialized!" def test_fetch_no_remotes(tmp_path, caplog): repo_a = tmp_path.joinpath("A.git") git.Repo().init(repo_a.as_posix()) rt = RepoTool(repo_a.as_posix()) assert not rt.fetch() assert caplog.records[0].levelname == "WARNING" assert caplog.records[0].message == f"Repo: {repo_a.as_posix()} does not contain any remotes!" def test_fetch_ok(tmp_path): repo_a = tmp_path.joinpath("A.git") repo_b = tmp_path.joinpath("B.git") r = git.Repo().init(repo_a.as_posix()) rt = RepoTool(repo_b.as_posix()) assert rt.clone(repo_a.as_uri()) # new file repo_a.joinpath(".gitignore").touch() # commit it r.git.add(".gitignore") with r.config_writer("repository") as cw: cw.add_section("user") cw.add_value("user", "name", "Tester") cw.add_value("user", "email", "test@a.b") r.git.commit(message = "Test Commit") hash = r.commit("master").hexsha assert rt.fetch() assert rt._repo.commit(hash) @pytest.fixture def cloned_base_repo_obj(tmp_path: Path, path_repo_base: Path) -> RepoTool: rt = RepoTool(tmp_path.joinpath("repo.git").as_posix()) assert rt.clone(path_repo_base.as_uri()) return rt def prepare_collection_list(collection) -> list: result = [] items = {} for item in collection: items[item.name] = str(item.commit) keys = list(items.keys()) keys.sort() for key in list(keys): result.append((key, str(items[key]))) return result def test_fetch_changed_branches(cloned_base_repo_obj: RepoTool, path_repo_changed_branches: Path): cloned_base_repo_obj._repo.remotes[0].set_url(path_repo_changed_branches.as_uri()) branches = prepare_collection_list(cloned_base_repo_obj._repo.branches) assert branches == base_repo_branches tags = prepare_collection_list(cloned_base_repo_obj._repo.tags) assert tags == base_repo_tags assert cloned_base_repo_obj.fetch() branches = prepare_collection_list(cloned_base_repo_obj._repo.branches) assert branches == [ ('branch-a', '71ce433cd98f899c723184b9ea1e0bcdf97d5c1a'), ('branch-d', '5551c9980c9ff2b94865596df35e38527d9fcfbd'), ( 'dependabot/npm_and_yarn/dot-github/actions/test-action/node-fetch-2.6.7', '8298c84342db5cb93972426188f06431fc498681'), ('master', 'e0c7e2a72579e24657c05e875201011d2b48bf94'), ('orph', '3de11d7640ed17f93ce38d31c9dea0fd65774077'), ('pr-1', '378d1f9e27dbacfcad0ee93355f0305c6c4432f1'), ('pr-3', 'e2bf0be1b64f345077fa96671d1c27f0c3476ac4'), ('release/1.2.3', 'f5eee554aecbee6f2f8e18de089476c3bf957ddc'), ('release/4.5.6', 'be3cb4b2590091dbaf5ce0d861da0f7979c5fc23'), ('release/7.7.10', '23478a09ad05642d64f44920f3247f7708d4bcae'), ('release/7.7.11', 'c014e918175915e07eef0150984a24ff8c33e154'), ('release/7.7.12', 'a7c8068c7c0a45f842400ffb2c4a245ab2f7a388'), ('release/7.7.13', 'c49c48572f1422e8b222db854d7ecbeba27b8020'), ('release/7.7.7', 'da67fad037eea0c065a5ea52a894d5522eb9f248'), ('release/7.7.8', '85003adc6bc0e91391edd97efb7f515cbd6d303e'), ('release/7.7.9', '73aaf9a4377bab721ba716776e81dc76bec25beb'), ('v1/foo/bar', '6e3325f7dc37f67b48e719de1ce4a4c9d33d1042'), ('v1/nix', '64ab804caa81c6a1c302cc03c3671d80f767c2c9'), ('wut', '3254380703607d4f632688e8ac8b3eec1eb69397')] tags = prepare_collection_list(cloned_base_repo_obj._repo.tags) assert tags == [ ('meh', '703de123eaa9832f4ce15baf6b702cd7f72fea5a'), ('v', '85003adc6bc0e91391edd97efb7f515cbd6d303e'), ('v1.2.3', '8f3d75c010a30babe3ee8a4176bb16136c5949b3'), ('v4.5.6', '8a2844f55fc1adde2e346d0999ef3e12aafbe511'), ('v7.7.10', '23478a09ad05642d64f44920f3247f7708d4bcae'), ('v7.7.11', 'c014e918175915e07eef0150984a24ff8c33e154'), ('v7.7.12', 'a7c8068c7c0a45f842400ffb2c4a245ab2f7a388'), ('v7.7.13', 'c49c48572f1422e8b222db854d7ecbeba27b8020'), ('v7.7.9', 'dd62ea5560a6944a04c1f8fbdbbb09c01f1b4a21'), ('wip-001', 'adbb090758d7bc201a35b5a7a470a3c01a3e5a95'), ('wip-002', 'a05c54d8623558963b8774bb01962fe0683c46bf'), ('wip-003', 'd3e906333be8a6ff09f96e827199d51694a16dc1'), ('wip-r/1', '030cc2b97d8ecbf07b7bd361105f07e631393f00')] def test_fetch_diferent_tags(cloned_base_repo_obj: RepoTool, path_repo_different_tags: Path): cloned_base_repo_obj._repo.remotes[0].set_url(path_repo_different_tags.as_uri()) branches = prepare_collection_list(cloned_base_repo_obj._repo.branches) assert branches == base_repo_branches tags = prepare_collection_list(cloned_base_repo_obj._repo.tags) assert tags == base_repo_tags assert cloned_base_repo_obj.fetch() branches = prepare_collection_list(cloned_base_repo_obj._repo.branches) assert branches == [ ('br0', '1fe320fe278a40bfd6813860d9952b03caf5e2ea'), ('branch-a', '71ce433cd98f899c723184b9ea1e0bcdf97d5c1a'), ('branch-d', '5551c9980c9ff2b94865596df35e38527d9fcfbd'), ( 'dependabot/npm_and_yarn/dot-github/actions/test-action/node-fetch-2.6.7', '8298c84342db5cb93972426188f06431fc498681'), ('master', 'e0c7e2a72579e24657c05e875201011d2b48bf94'), ('orph', '3de11d7640ed17f93ce38d31c9dea0fd65774077'), ('pr-1', '378d1f9e27dbacfcad0ee93355f0305c6c4432f1'), ('pr-3', 'e2bf0be1b64f345077fa96671d1c27f0c3476ac4'), ('release/1.2.3', 'f5eee554aecbee6f2f8e18de089476c3bf957ddc'), ('release/4.5.6', 'be3cb4b2590091dbaf5ce0d861da0f7979c5fc23'), ('release/7.7.10', '23478a09ad05642d64f44920f3247f7708d4bcae'), ('release/7.7.11', 'c014e918175915e07eef0150984a24ff8c33e154'), ('release/7.7.12', 'a7c8068c7c0a45f842400ffb2c4a245ab2f7a388'), ('release/7.7.13', 'c49c48572f1422e8b222db854d7ecbeba27b8020'), ('release/7.7.7', 'da67fad037eea0c065a5ea52a894d5522eb9f248'), ('release/7.7.8', '85003adc6bc0e91391edd97efb7f515cbd6d303e'), ('release/7.7.9', '73aaf9a4377bab721ba716776e81dc76bec25beb'), ('symlink-readme', '8a2844f55fc1adde2e346d0999ef3e12aafbe511'), ('v1/foo/bar', '6e3325f7dc37f67b48e719de1ce4a4c9d33d1042'), ('v1/nix', 'c55e6953ff343f9eeb42dc04eb6aa5dfed6f0756') ] tags = prepare_collection_list(cloned_base_repo_obj._repo.tags) assert tags == [ ('meh', 'e0c7e2a72579e24657c05e875201011d2b48bf94'), ('v1.2.3', '8f3d75c010a30babe3ee8a4176bb16136c5949b3'), ('v4.5.6', '8a2844f55fc1adde2e346d0999ef3e12aafbe511'), ('v7.7.10', '23478a09ad05642d64f44920f3247f7708d4bcae'), ('v7.7.11', 'c014e918175915e07eef0150984a24ff8c33e154'), ('v7.7.12', 'a7c8068c7c0a45f842400ffb2c4a245ab2f7a388'), ('v7.7.13', 'c49c48572f1422e8b222db854d7ecbeba27b8020'), ('v7.7.9', 'dd62ea5560a6944a04c1f8fbdbbb09c01f1b4a21'), ('vv', '85003adc6bc0e91391edd97efb7f515cbd6d303e'), ('wip-001', 'adbb090758d7bc201a35b5a7a470a3c01a3e5a95'), ('wip-002', 'a05c54d8623558963b8774bb01962fe0683c46bf'), ('wip-003', 'd3e906333be8a6ff09f96e827199d51694a16dc1'), ('wip-r/1', '030cc2b97d8ecbf07b7bd361105f07e631393f00') ] def test_fetch_new_commits(cloned_base_repo_obj: RepoTool, path_repo_new_commits: Path): cloned_base_repo_obj._repo.remotes[0].set_url(path_repo_new_commits.as_uri()) branches = prepare_collection_list(cloned_base_repo_obj._repo.branches) assert branches == base_repo_branches tags = prepare_collection_list(cloned_base_repo_obj._repo.tags) assert tags == base_repo_tags assert cloned_base_repo_obj.fetch() branches = prepare_collection_list(cloned_base_repo_obj._repo.branches) assert branches == [ ('br0', '1fe320fe278a40bfd6813860d9952b03caf5e2ea'), ('branch-a', '442ea9bbc1d5c0fb48325801d3edcb966cc26db2'), ('branch-d', '201e167782b51e363fe6c1b15f9cec1b28cd1b2b'), ( 'dependabot/npm_and_yarn/dot-github/actions/test-action/node-fetch-2.6.7', '8298c84342db5cb93972426188f06431fc498681'), ('master', 'f110a678f5c5a71c8f61bd7d88eeb9c729fd2b38'), ('orph', '3de11d7640ed17f93ce38d31c9dea0fd65774077'), ('pr-1', '378d1f9e27dbacfcad0ee93355f0305c6c4432f1'), ('pr-3', 'e2bf0be1b64f345077fa96671d1c27f0c3476ac4'), ('release/1.2.3', 'f5eee554aecbee6f2f8e18de089476c3bf957ddc'), ('release/4.5.6', 'be3cb4b2590091dbaf5ce0d861da0f7979c5fc23'), ('release/7.7.10', '23478a09ad05642d64f44920f3247f7708d4bcae'), ('release/7.7.11', 'c014e918175915e07eef0150984a24ff8c33e154'), ('release/7.7.12', 'a7c8068c7c0a45f842400ffb2c4a245ab2f7a388'), ('release/7.7.13', 'c49c48572f1422e8b222db854d7ecbeba27b8020'), ('release/7.7.7', 'da67fad037eea0c065a5ea52a894d5522eb9f248'), ('release/7.7.8', '85003adc6bc0e91391edd97efb7f515cbd6d303e'), ('release/7.7.9', '73aaf9a4377bab721ba716776e81dc76bec25beb'), ('symlink-readme', '8a2844f55fc1adde2e346d0999ef3e12aafbe511'), ('v1/foo/bar', '6e3325f7dc37f67b48e719de1ce4a4c9d33d1042'), ('v1/nix', 'c55e6953ff343f9eeb42dc04eb6aa5dfed6f0756') ] tags = prepare_collection_list(cloned_base_repo_obj._repo.tags) assert tags == base_repo_tags def test_fetch_reduced(cloned_base_repo_obj: RepoTool, path_repo_reduced: Path): cloned_base_repo_obj._repo.remotes[0].set_url(path_repo_reduced.as_uri()) branches = prepare_collection_list(cloned_base_repo_obj._repo.branches) assert branches == base_repo_branches tags = prepare_collection_list(cloned_base_repo_obj._repo.tags) assert tags == base_repo_tags assert cloned_base_repo_obj.fetch() branches = prepare_collection_list(cloned_base_repo_obj._repo.branches) assert branches == [ ('master', 'e0c7e2a72579e24657c05e875201011d2b48bf94'), ('pr-1', '378d1f9e27dbacfcad0ee93355f0305c6c4432f1'), ('pr-3', 'e2bf0be1b64f345077fa96671d1c27f0c3476ac4'), ('release/1.2.3', 'f5eee554aecbee6f2f8e18de089476c3bf957ddc'), ('release/4.5.6', 'be3cb4b2590091dbaf5ce0d861da0f7979c5fc23'), ('release/7.7.10', '23478a09ad05642d64f44920f3247f7708d4bcae'), ('release/7.7.11', 'c014e918175915e07eef0150984a24ff8c33e154'), ('release/7.7.12', 'a7c8068c7c0a45f842400ffb2c4a245ab2f7a388'), ('release/7.7.13', 'c49c48572f1422e8b222db854d7ecbeba27b8020'), ('release/7.7.7', 'da67fad037eea0c065a5ea52a894d5522eb9f248'), ('release/7.7.8', '85003adc6bc0e91391edd97efb7f515cbd6d303e'), ('release/7.7.9', '73aaf9a4377bab721ba716776e81dc76bec25beb'), ('symlink-readme', '8a2844f55fc1adde2e346d0999ef3e12aafbe511'), ] tags = prepare_collection_list(cloned_base_repo_obj._repo.tags) assert tags == [ ('wip-001', 'adbb090758d7bc201a35b5a7a470a3c01a3e5a95'), ('wip-002', 'a05c54d8623558963b8774bb01962fe0683c46bf'), ('wip-003', 'd3e906333be8a6ff09f96e827199d51694a16dc1'), ('wip-r/1', '030cc2b97d8ecbf07b7bd361105f07e631393f00') ] @pytest.mark.parametrize("repo,hash", [ ("test-repo-base", "d5803947514ee6d7834157421171a94174a516dc9606de6aa52e28e71cea2c0e"), ("test-repo-different-tags", "30a8507cb85c5fe7d07c1ef9a95eeed55fedd5c874f4fe723c2f9f56b0a96856"), ("test-repo-changed-branches", "a987fd182cb173f6913eaeb774aa710c26112dc9f5ea8cd10c75efa614768444"), ("test-repo-new-commits", "1a67df432e2206089ec019e272d91051b7ead0334dd03955352656e29e603813"), ("test-repo-reduced", "fb7fd812ec30265ecc3014824e467746112403dab114cf37907facb10a85a3e2"), ("nonexistent-repo.git", False), ]) def test_fingerprint(support_data_path: Path, repo: str, hash): path = support_data_path.joinpath(repo).as_posix() rt = RepoTool(path) if hash: assert rt.initialized else: assert not rt.initialized assert rt.repo_fingerprint() == hash def test_list_submodules_no_submodules(cloned_base_repo_obj): assert cloned_base_repo_obj.list_submodules() == [] assert cloned_base_repo_obj.discovered_submodules_commits == ["e0c7e2a72579e24657c05e875201011d2b48bf94"] def test_list_submodules_ok(tmp_path, support_data_path): rt = RepoTool(tmp_path.joinpath("repo.git").as_posix()) rt.clone(support_data_path.joinpath("test-repo-submodules").as_uri()) assert rt.list_submodules() == ['https://git.sw3.cz/kamikaze/test-repo-base.git'] assert rt.list_submodules("HEAD") == ['https://git.sw3.cz/kamikaze/test-repo-base.git'] assert rt.list_submodules("cc58d514348d0d2c8f0b75ad1f7ff96eb02781d5") == [ 'https://git.sw3.cz/kamikaze/test-repo-base.git', 'https://git.sw3.cz/kamikaze/test-repo-reduced.git' ] assert rt.cloned_submodules_url_list == [] assert rt.discovered_submodules_commits == [ '1946eeb4dda03473e796a8cc78b1946fc85df0fd', 'cc58d514348d0d2c8f0b75ad1f7ff96eb02781d5', ] def test_list_submodules_history(tmp_path, support_data_path): rt = RepoTool(tmp_path.joinpath("repo.git").as_posix()) rt.clone(support_data_path.joinpath("test-repo-submodules").as_uri()) history = rt.list_submodules_history() history.sort() assert history == [ 'https://git.sw3.cz/kamikaze/test-repo-base.git', 'https://git.sw3.cz/kamikaze/test-repo-different-tags.git', 'https://git.sw3.cz/kamikaze/test-repo-reduced.git', ] assert rt.list_submodules_history(100) == [] assert rt.list_submodules_history(120) == ['https://git.sw3.cz/kamikaze/test-repo-different-tags.git'] history = rt.list_submodules_history(320) history.sort() assert history == [ 'https://git.sw3.cz/kamikaze/test-repo-base.git', 'https://git.sw3.cz/kamikaze/test-repo-different-tags.git', 'https://git.sw3.cz/kamikaze/test-repo-reduced.git', ] assert len(rt.discovered_submodules_commits) == 645 def test_list_submodules_history_progress(support_data_path, caplog, monkeypatch): mocked_time = 1659059078 def fake_time() -> float: nonlocal mocked_time mocked_time += 0.2 return mocked_time rt = RepoTool(support_data_path.joinpath("test-repo-submodules-long").as_posix()) caplog.set_level(logging.INFO) caplog.clear() with monkeypatch.context() as m: import time m.setattr(time, "time", fake_time) rt.list_submodules_history(22) assert all(x.levelname == "INFO" for x in caplog.records) import re regex = re.compile("Submodule discovery: \\d+ commits finished, 1 discovered") assert 8 == len(caplog.records) assert 7 == sum(1 if regex.match(x.message) else 0 for x in caplog.records) assert len(rt.discovered_submodules_commits) == 22