##// END OF EJS Templates
release: Finish preparation for 4.23.0
release: Finish preparation for 4.23.0

File last commit:

r4306:09801de9 default
r4569:a9655707 v4.23.0 stable
Show More
test_hg_vcsserver_cache_invalidation.py
191 lines | 8.1 KiB | text/x-python | PythonLexer
/ rhodecode / tests / vcs / test_hg_vcsserver_cache_invalidation.py
Martin Bornhold
tests: Add tests for hg invalidation of vcsserver cache.
r406 # -*- coding: utf-8 -*-
code: update copyrights to 2020
r4306 # Copyright (C) 2016-2020 RhodeCode GmbH
Martin Bornhold
tests: Add tests for hg invalidation of vcsserver cache.
r406 #
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License, version 3
# (only), as published by the Free Software Foundation.
#
# 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 Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# This program is dual-licensed. If you wish to learn more about the
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
import pytest
Martin Bornhold
tests: Adapt tests to changes in mercurial vcs backend.
r408 from mock import call, patch
Martin Bornhold
tests: Add tests for hg invalidation of vcsserver cache.
r406
from rhodecode.lib.vcs.backends.base import Reference
class TestMercurialRemoteRepoInvalidation(object):
Martin Bornhold
tests: Skip test for Pyro4 connection and added doc strings.
r434 """
If the VCSServer is running with multiple processes or/and instances.
Operations on repositories are potentially handled by different processes
in a random fashion. The mercurial repository objects used in the VCSServer
are caching the commits of the repo. Therefore we have to invalidate the
VCSServer caching of these objects after a writing operation.
"""
# Default reference used as a dummy during tests.
Martin Bornhold
tests: Adapt tests to changes in mercurial vcs backend.
r408 default_ref = Reference('branch', 'default', None)
Martin Bornhold
tests: Skip test for Pyro4 connection and added doc strings.
r434
# Methods of vcsserver.hg.HgRemote that are "writing" operations.
Martin Bornhold
tests: Adapt tests to changes in mercurial vcs backend.
r408 writing_methods = [
Martin Bornhold
tests: Add tests for hg invalidation of vcsserver cache.
r406 'bookmark',
'commit',
Martin Bornhold
tests: Adapt tests to changes in mercurial vcs backend.
r408 'merge',
Martin Bornhold
tests: Add tests for hg invalidation of vcsserver cache.
r406 'pull',
'pull_cmd',
'rebase',
'strip',
Martin Bornhold
tests: Adapt tests to changes in mercurial vcs backend.
r408 'tag',
]
@pytest.mark.parametrize('method_name, method_args', [
('_local_merge', [default_ref, None, None, None, default_ref]),
('_local_pull', ['', default_ref]),
('bookmark', [None]),
('pull', ['', default_ref]),
('remove_tag', ['mytag', None]),
('strip', [None]),
('tag', ['newtag', None]),
Martin Bornhold
tests: Add tests for hg invalidation of vcsserver cache.
r406 ])
def test_method_invokes_invalidate_on_remote_repo(
Martin Bornhold
tests: Adapt tests to changes in mercurial vcs backend.
r408 self, method_name, method_args, backend_hg):
"""
Check that the listed methods are invalidating the VCSServer cache
after invoking a writing method of their remote repository object.
Martin Bornhold
tests: Add tests for hg invalidation of vcsserver cache.
r406 """
Martin Bornhold
tests: Adapt tests to changes in mercurial vcs backend.
r408 tags = {'mytag': 'mytag-id'}
def add_tag(name, raw_id, *args, **kwds):
tags[name] = raw_id
Martin Bornhold
tests: Add tests for hg invalidation of vcsserver cache.
r406 repo = backend_hg.repo.scm_instance()
commits: updated logic of in-memory-commits, fixed tests and re-architectured a bit how commit_ids are calculated and updated....
r3743
Martin Bornhold
tests: Adapt tests to changes in mercurial vcs backend.
r408 with patch.object(repo, '_remote') as remote:
commits: updated logic of in-memory-commits, fixed tests and re-architectured a bit how commit_ids are calculated and updated....
r3743 repo.tags = tags
Martin Bornhold
tests: Adapt tests to changes in mercurial vcs backend.
r408 remote.lookup.return_value = ('commit-id', 'commit-idx')
remote.tags.return_value = tags
remote._get_tags.return_value = tags
commits: updated logic of in-memory-commits, fixed tests and re-architectured a bit how commit_ids are calculated and updated....
r3743 remote.is_empty.return_value = False
Martin Bornhold
tests: Adapt tests to changes in mercurial vcs backend.
r408 remote.tag.side_effect = add_tag
# Invoke method.
method = getattr(repo, method_name)
method(*method_args)
# Assert that every "writing" method is followed by an invocation
# of the cache invalidation method.
for counter, method_call in enumerate(remote.method_calls):
call_name = method_call[0]
if call_name in self.writing_methods:
next_call = remote.method_calls[counter + 1]
assert next_call == call.invalidate_vcs_cache()
Martin Bornhold
tests: Add tests for hg invalidation of vcsserver cache.
r406
def _prepare_shadow_repo(self, pull_request):
"""
Helper that creates a shadow repo that can be used to reproduce the
CommitDoesNotExistError when pulling in from target and source
references.
"""
from rhodecode.model.pull_request import PullRequestModel
tests: fixed name generation for shadow repos
r2890 repo_id = pull_request.target_repo.repo_id
Martin Bornhold
tests: Add tests for hg invalidation of vcsserver cache.
r406 target_vcs = pull_request.target_repo.scm_instance()
target_ref = pull_request.target_ref_parts
source_ref = pull_request.source_ref_parts
# Create shadow repository.
pr = PullRequestModel()
workspace_id = pr._workspace_id(pull_request)
shadow_repository_path = target_vcs._maybe_prepare_merge_workspace(
shadow-repos: use numeric repo id for creation of shadow repos....
r2810 repo_id, workspace_id, target_ref, source_ref)
caches: updated cache backend to new vcsserver caches implementation.
r3848 shadow_repo = target_vcs.get_shadow_instance(shadow_repository_path, cache=True)
Martin Bornhold
tests: Add tests for hg invalidation of vcsserver cache.
r406
# This will populate the cache of the mercurial repository object
# inside of the VCSServer.
shadow_repo.get_commit()
return shadow_repo, source_ref, target_ref
@pytest.mark.backends('hg')
home: moved home and repo group views into pyramid....
r1774 def test_commit_does_not_exist_error_happens(self, pr_util, app):
Martin Bornhold
tests: Skip test for Pyro4 connection and added doc strings.
r434 """
This test is somewhat special. It does not really test the system
instead it is more or less a precondition for the
"test_commit_does_not_exist_error_does_not_happen". It deactivates the
cache invalidation and asserts that the error occurs.
"""
Martin Bornhold
tests: Add tests for hg invalidation of vcsserver cache.
r406 from rhodecode.lib.vcs.exceptions import CommitDoesNotExistError
pull_request = pr_util.create_pull_request()
caches: updated cache backend to new vcsserver caches implementation.
r3848
Martin Bornhold
tests: Add tests for hg invalidation of vcsserver cache.
r406 target_vcs = pull_request.target_repo.scm_instance()
source_vcs = pull_request.source_repo.scm_instance()
caches: updated cache backend to new vcsserver caches implementation.
r3848 shadow_repo, source_ref, target_ref = self._prepare_shadow_repo(pull_request)
initial_cache_uid = shadow_repo._remote._wire['context']
initial_commit_ids = shadow_repo._remote.get_all_commit_ids('visible')
Martin Bornhold
tests: Add tests for hg invalidation of vcsserver cache.
r406
# Pull from target and source references but without invalidation of
caches: updated cache backend to new vcsserver caches implementation.
r3848 # RemoteRepo objects and without VCSServer caching of mercurial repository objects.
Martin Bornhold
tests: Add tests for hg invalidation of vcsserver cache.
r406 with patch.object(shadow_repo._remote, 'invalidate_vcs_cache'):
# NOTE: Do not use patch.dict() to disable the cache because it
# restores the WHOLE dict and not only the patched keys.
shadow_repo._remote._wire['cache'] = False
shadow_repo._local_pull(target_vcs.path, target_ref)
shadow_repo._local_pull(source_vcs.path, source_ref)
caches: updated cache backend to new vcsserver caches implementation.
r3848 shadow_repo._remote._wire['cache'] = True
Martin Bornhold
tests: Add tests for hg invalidation of vcsserver cache.
r406
# Try to lookup the target_ref in shadow repo. This should work because
caches: updated cache backend to new vcsserver caches implementation.
r3848 # test_repo_maker_uses_session_for_instance_methods
Martin Bornhold
tests: Add tests for hg invalidation of vcsserver cache.
r406 # the shadow repo is a clone of the target and always contains all off
# it's commits in the initial cache.
shadow_repo.get_commit(target_ref.commit_id)
caches: updated cache backend to new vcsserver caches implementation.
r3848 # we ensure that call context has not changed, this is what
# `invalidate_vcs_cache` does
assert initial_cache_uid == shadow_repo._remote._wire['context']
# If we try to lookup all commits.
Martin Bornhold
tests: Add tests for hg invalidation of vcsserver cache.
r406 # repo commit cache doesn't get invalidated. (Due to patched
# invalidation and caching above).
caches: updated cache backend to new vcsserver caches implementation.
r3848 assert initial_commit_ids == shadow_repo._remote.get_all_commit_ids('visible')
Martin Bornhold
tests: Add tests for hg invalidation of vcsserver cache.
r406
@pytest.mark.backends('hg')
home: moved home and repo group views into pyramid....
r1774 def test_commit_does_not_exist_error_does_not_happen(self, pr_util, app):
Martin Bornhold
tests: Skip test for Pyro4 connection and added doc strings.
r434 """
This test simulates a pull request merge in which the pull operations
are handled by a different VCSServer process than all other operations.
Without correct cache invalidation this leads to an error when
retrieving the pulled commits afterwards.
"""
Martin Bornhold
tests: Add tests for hg invalidation of vcsserver cache.
r406 pull_request = pr_util.create_pull_request()
target_vcs = pull_request.target_repo.scm_instance()
source_vcs = pull_request.source_repo.scm_instance()
caches: updated cache backend to new vcsserver caches implementation.
r3848 shadow_repo, source_ref, target_ref = self._prepare_shadow_repo(pull_request)
Martin Bornhold
tests: Add tests for hg invalidation of vcsserver cache.
r406
# Pull from target and source references without without VCSServer
# caching of mercurial repository objects but with active invalidation
# of RemoteRepo objects.
# NOTE: Do not use patch.dict() to disable the cache because it
# restores the WHOLE dict and not only the patched keys.
shadow_repo._remote._wire['cache'] = False
shadow_repo._local_pull(target_vcs.path, target_ref)
shadow_repo._local_pull(source_vcs.path, source_ref)
caches: updated cache backend to new vcsserver caches implementation.
r3848 shadow_repo._remote._wire['cache'] = True
Martin Bornhold
tests: Add tests for hg invalidation of vcsserver cache.
r406
# Try to lookup the target and source references in shadow repo. This
# should work because the RemoteRepo object gets invalidated during the
# above pull operations.
shadow_repo.get_commit(target_ref.commit_id)
shadow_repo.get_commit(source_ref.commit_id)