test_git.py
162 lines
| 6.2 KiB
| text/x-python
|
PythonLexer
r130 | # RhodeCode VCSServer provides access to different vcs backends via network. | |||
r1327 | # Copyright (C) 2014-2024 RhodeCode GmbH | |||
r130 | # | |||
# This program is free software; you can redistribute it and/or modify | ||||
# it under the terms of the GNU General Public License as published by | ||||
# the Free Software Foundation; either version 3 of the License, or | ||||
# (at your option) any later version. | ||||
# | ||||
# This program is distributed in the hope that it will be useful, | ||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
# GNU General Public License for more details. | ||||
# | ||||
# You should have received a copy of the GNU General Public License | ||||
# along with this program; if not, write to the Free Software Foundation, | ||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||||
import inspect | ||||
import pytest | ||||
import dulwich.errors | ||||
from mock import Mock, patch | ||||
r1145 | from vcsserver.remote import git_remote | |||
r130 | ||||
SAMPLE_REFS = { | ||||
'HEAD': 'fd627b9e0dd80b47be81af07c4a98518244ed2f7', | ||||
'refs/tags/v0.1.9': '341d28f0eec5ddf0b6b77871e13c2bbd6bec685c', | ||||
'refs/tags/v0.1.8': '74ebce002c088b8a5ecf40073db09375515ecd68', | ||||
'refs/tags/v0.1.1': 'e6ea6d16e2f26250124a1f4b4fe37a912f9d86a0', | ||||
'refs/tags/v0.1.3': '5a3a8fb005554692b16e21dee62bf02667d8dc3e', | ||||
} | ||||
@pytest.fixture | ||||
r1145 | def git_remote_fix(): | |||
r130 | """ | |||
A GitRemote instance with a mock factory. | ||||
""" | ||||
factory = Mock() | ||||
r1145 | remote = git_remote.GitRemote(factory) | |||
r130 | return remote | |||
r1145 | def test_discover_git_version(git_remote_fix): | |||
version = git_remote_fix.discover_git_version() | ||||
r130 | assert version | |||
r1152 | class TestGitFetch: | |||
r1048 | def setup_method(self): | |||
r130 | self.mock_repo = Mock() | |||
factory = Mock() | ||||
factory.repo = Mock(return_value=self.mock_repo) | ||||
r1145 | self.remote_git = git_remote.GitRemote(factory) | |||
r130 | ||||
def test_fetches_all_when_no_commit_ids_specified(self): | ||||
def side_effect(determine_wants, *args, **kwargs): | ||||
determine_wants(SAMPLE_REFS) | ||||
with patch('dulwich.client.LocalGitClient.fetch') as mock_fetch: | ||||
mock_fetch.side_effect = side_effect | ||||
r739 | self.remote_git.pull(wire={}, url='/tmp/', apply_refs=False) | |||
r130 | determine_wants = self.mock_repo.object_store.determine_wants_all | |||
determine_wants.assert_called_once_with(SAMPLE_REFS) | ||||
def test_fetches_specified_commits(self): | ||||
selected_refs = { | ||||
r1080 | 'refs/tags/v0.1.8': b'74ebce002c088b8a5ecf40073db09375515ecd68', | |||
'refs/tags/v0.1.3': b'5a3a8fb005554692b16e21dee62bf02667d8dc3e', | ||||
r130 | } | |||
def side_effect(determine_wants, *args, **kwargs): | ||||
result = determine_wants(SAMPLE_REFS) | ||||
assert sorted(result) == sorted(selected_refs.values()) | ||||
return result | ||||
with patch('dulwich.client.LocalGitClient.fetch') as mock_fetch: | ||||
mock_fetch.side_effect = side_effect | ||||
r550 | self.remote_git.pull( | |||
r739 | wire={}, url='/tmp/', apply_refs=False, | |||
r1054 | refs=list(selected_refs.keys())) | |||
r130 | determine_wants = self.mock_repo.object_store.determine_wants_all | |||
assert determine_wants.call_count == 0 | ||||
def test_get_remote_refs(self): | ||||
factory = Mock() | ||||
r1145 | remote_git = git_remote.GitRemote(factory) | |||
url = 'https://example.com/test/test.git' | ||||
r130 | sample_refs = { | |||
'refs/tags/v0.1.8': '74ebce002c088b8a5ecf40073db09375515ecd68', | ||||
'refs/tags/v0.1.3': '5a3a8fb005554692b16e21dee62bf02667d8dc3e', | ||||
} | ||||
r1145 | with patch('vcsserver.remote.git_remote.Repo', create=False) as mock_repo: | |||
r130 | mock_repo().get_refs.return_value = sample_refs | |||
r739 | remote_refs = remote_git.get_remote_refs(wire={}, url=url) | |||
r130 | mock_repo().get_refs.assert_called_once_with() | |||
assert remote_refs == sample_refs | ||||
r1152 | class TestReraiseSafeExceptions: | |||
r725 | ||||
r130 | def test_method_decorated_with_reraise_safe_exceptions(self): | |||
factory = Mock() | ||||
r1145 | git_remote_instance = git_remote.GitRemote(factory) | |||
r130 | ||||
def fake_function(): | ||||
return None | ||||
r1145 | decorator = git_remote.reraise_safe_exceptions(fake_function) | |||
r130 | ||||
r1145 | methods = inspect.getmembers(git_remote_instance, predicate=inspect.ismethod) | |||
r130 | for method_name, method in methods: | |||
r964 | if not method_name.startswith('_') and method_name not in ['vcsserver_invalidate_cache']: | |||
r1044 | assert method.__func__.__code__ == decorator.__code__ | |||
r130 | ||||
@pytest.mark.parametrize('side_effect, expected_type', [ | ||||
(dulwich.errors.ChecksumMismatch('0000000', 'deadbeef'), 'lookup'), | ||||
(dulwich.errors.NotCommitError('deadbeef'), 'lookup'), | ||||
(dulwich.errors.MissingCommitError('deadbeef'), 'lookup'), | ||||
(dulwich.errors.ObjectMissing('deadbeef'), 'lookup'), | ||||
(dulwich.errors.HangupException(), 'error'), | ||||
(dulwich.errors.UnexpectedCommandError('test-cmd'), 'error'), | ||||
]) | ||||
def test_safe_exceptions_reraised(self, side_effect, expected_type): | ||||
r1145 | @git_remote.reraise_safe_exceptions | |||
r130 | def fake_method(): | |||
raise side_effect | ||||
with pytest.raises(Exception) as exc_info: | ||||
fake_method() | ||||
assert type(exc_info.value) == Exception | ||||
assert exc_info.value._vcs_kind == expected_type | ||||
r1152 | class TestDulwichRepoWrapper: | |||
r130 | def test_calls_close_on_delete(self): | |||
isdir_patcher = patch('dulwich.repo.os.path.isdir', return_value=True) | ||||
r1145 | with patch.object(git_remote.Repo, 'close') as close_mock: | |||
r1048 | with isdir_patcher: | |||
r1145 | repo = git_remote.Repo('/tmp/abcde') | |||
r1048 | assert repo is not None | |||
repo.__del__() | ||||
# can't use del repo as in python3 this isn't always calling .__del__() | ||||
close_mock.assert_called_once_with() | ||||
r130 | ||||
r1152 | class TestGitFactory: | |||
r130 | def test_create_repo_returns_dulwich_wrapper(self): | |||
r483 | ||||
with patch('vcsserver.lib.rc_cache.region_meta.dogpile_cache_regions') as mock: | ||||
mock.side_effect = {'repo_objects': ''} | ||||
r1145 | factory = git_remote.GitFactory() | |||
r483 | wire = { | |||
'path': '/tmp/abcde' | ||||
} | ||||
isdir_patcher = patch('dulwich.repo.os.path.isdir', return_value=True) | ||||
with isdir_patcher: | ||||
result = factory._create_repo(wire, True) | ||||
r1145 | assert isinstance(result, git_remote.Repo) | |||