mirror of
https://github.com/samsonjs/vdirsyncer.git
synced 2026-03-25 08:55:50 +00:00
More tests
This commit is contained in:
parent
e7910e92aa
commit
41794f095d
3 changed files with 80 additions and 21 deletions
|
|
@ -7,7 +7,8 @@ import pytest
|
|||
|
||||
from tests import blow_up
|
||||
|
||||
from vdirsyncer.metasync import MetaSyncConflict, metasync
|
||||
from vdirsyncer.exceptions import UserError
|
||||
from vdirsyncer.metasync import MetaSyncConflict, logger, metasync
|
||||
from vdirsyncer.storage.base import normalize_meta_value
|
||||
from vdirsyncer.storage.memory import MemoryStorage
|
||||
|
||||
|
|
@ -46,19 +47,50 @@ def test_basic(monkeypatch):
|
|||
assert not a.get_meta('foo') and not b.get_meta('foo')
|
||||
|
||||
|
||||
def test_conflict():
|
||||
@pytest.fixture
|
||||
def conflict_state(request):
|
||||
a = MemoryStorage()
|
||||
b = MemoryStorage()
|
||||
status = {}
|
||||
a.set_meta('foo', 'bar')
|
||||
b.set_meta('foo', 'baz')
|
||||
|
||||
def cleanup():
|
||||
assert a.get_meta('foo') == 'bar'
|
||||
assert b.get_meta('foo') == 'baz'
|
||||
assert not status
|
||||
|
||||
request.addfinalizer(cleanup)
|
||||
|
||||
return a, b, status
|
||||
|
||||
|
||||
def test_conflict(conflict_state):
|
||||
a, b, status = conflict_state
|
||||
|
||||
with pytest.raises(MetaSyncConflict):
|
||||
metasync(a, b, status, keys=['foo'])
|
||||
|
||||
assert a.get_meta('foo') == 'bar'
|
||||
assert b.get_meta('foo') == 'baz'
|
||||
assert not status
|
||||
|
||||
def test_invalid_conflict_resolution(conflict_state):
|
||||
a, b, status = conflict_state
|
||||
|
||||
with pytest.raises(UserError) as excinfo:
|
||||
metasync(a, b, status, keys=['foo'], conflict_resolution='foo')
|
||||
|
||||
assert 'Invalid conflict resolution setting' in str(excinfo.value)
|
||||
|
||||
|
||||
def test_warning_on_custom_conflict_commands(conflict_state, monkeypatch):
|
||||
a, b, status = conflict_state
|
||||
warnings = []
|
||||
monkeypatch.setattr(logger, 'warning', warnings.append)
|
||||
|
||||
with pytest.raises(MetaSyncConflict):
|
||||
metasync(a, b, status, keys=['foo'],
|
||||
conflict_resolution=lambda *a, **kw: None)
|
||||
|
||||
assert warnings == ['Custom commands don\'t work on metasync.']
|
||||
|
||||
|
||||
def test_conflict_same_content():
|
||||
|
|
|
|||
|
|
@ -80,6 +80,18 @@ def test_read_only_and_prefetch():
|
|||
assert not items(a) and not items(b)
|
||||
|
||||
|
||||
def test_partial_sync_error():
|
||||
a = MemoryStorage()
|
||||
b = MemoryStorage()
|
||||
status = {}
|
||||
|
||||
a.upload(Item('UID:0'))
|
||||
b.read_only = True
|
||||
|
||||
with pytest.raises(PartialSync):
|
||||
sync(a, b, status, partial_sync='error')
|
||||
|
||||
|
||||
def test_partial_sync_ignore():
|
||||
a = MemoryStorage()
|
||||
b = MemoryStorage()
|
||||
|
|
@ -357,20 +369,37 @@ def test_both_readonly():
|
|||
sync(a, b, status)
|
||||
|
||||
|
||||
def test_readonly():
|
||||
def test_partial_sync_revert():
|
||||
a = MemoryStorage(instance_name='a')
|
||||
b = MemoryStorage(instance_name='b')
|
||||
status = {}
|
||||
href_a, _ = a.upload(Item(u'UID:1'))
|
||||
href_b, _ = b.upload(Item(u'UID:2'))
|
||||
a.upload(Item(u'UID:1'))
|
||||
b.upload(Item(u'UID:2'))
|
||||
b.read_only = True
|
||||
with pytest.raises(exceptions.ReadOnlyError):
|
||||
b.upload(Item(u'UID:3'))
|
||||
|
||||
sync(a, b, status, partial_sync='revert')
|
||||
assert len(status) == 2 and a.has(href_a) and not b.has(href_a)
|
||||
assert len(status) == 2
|
||||
assert items(a) == {'UID:1', 'UID:2'}
|
||||
assert items(b) == {'UID:2'}
|
||||
|
||||
sync(a, b, status, partial_sync='revert')
|
||||
assert len(status) == 1 and not a.has(href_a) and not b.has(href_a)
|
||||
assert len(status) == 1
|
||||
assert items(a) == {'UID:2'}
|
||||
assert items(b) == {'UID:2'}
|
||||
|
||||
# Check that updates get reverted
|
||||
a.items[next(iter(a.items))] = ('foo', Item('UID:2\nupdated'))
|
||||
assert items(a) == {'UID:2\nupdated'}
|
||||
sync(a, b, status, partial_sync='revert')
|
||||
assert items(a) == {'UID:2\nupdated'}
|
||||
sync(a, b, status, partial_sync='revert')
|
||||
assert items(a) == {'UID:2'}
|
||||
|
||||
# Check that deletions get reverted
|
||||
a.items.clear()
|
||||
sync(a, b, status, partial_sync='revert', force_delete=True)
|
||||
sync(a, b, status, partial_sync='revert', force_delete=True)
|
||||
assert items(a) == {'UID:2'}
|
||||
|
||||
|
||||
@pytest.mark.parametrize('sync_inbetween', (True, False))
|
||||
|
|
@ -472,12 +501,10 @@ class SyncMachine(RuleBasedStateMachine):
|
|||
Storage = Bundle('storage')
|
||||
|
||||
@rule(target=Storage,
|
||||
read_only=st.booleans(),
|
||||
flaky_etags=st.booleans(),
|
||||
null_etag_on_upload=st.booleans())
|
||||
def newstorage(self, read_only, flaky_etags, null_etag_on_upload):
|
||||
def newstorage(self, flaky_etags, null_etag_on_upload):
|
||||
s = MemoryStorage()
|
||||
s.read_only = read_only
|
||||
if flaky_etags:
|
||||
def get(href):
|
||||
old_etag, item = s.items[href]
|
||||
|
|
@ -494,6 +521,11 @@ class SyncMachine(RuleBasedStateMachine):
|
|||
|
||||
return s
|
||||
|
||||
@rule(s=Storage, read_only=st.booleans())
|
||||
def is_read_only(self, s, read_only):
|
||||
assume(s.read_only != read_only)
|
||||
s.read_only = read_only
|
||||
|
||||
@rule(s=Storage)
|
||||
def actions_fail(self, s):
|
||||
s.upload = action_failure
|
||||
|
|
|
|||
|
|
@ -197,10 +197,6 @@ def _migrate_status(status):
|
|||
'href': href_b,
|
||||
'etag': etag_b,
|
||||
})
|
||||
elif len(value) == 2:
|
||||
a, b = value
|
||||
a.setdefault('hash', '')
|
||||
b.setdefault('hash', '')
|
||||
|
||||
|
||||
def sync(storage_a, storage_b, status, conflict_resolution=None,
|
||||
|
|
@ -283,7 +279,7 @@ def sync(storage_a, storage_b, status, conflict_resolution=None,
|
|||
|
||||
|
||||
class Action:
|
||||
def _run_impl(self, a, b):
|
||||
def _run_impl(self, a, b): # pragma: no cover
|
||||
raise NotImplementedError()
|
||||
|
||||
def run(self, a, b, conflict_resolution, partial_sync):
|
||||
|
|
@ -345,7 +341,6 @@ class Update(Action):
|
|||
self.dest = dest
|
||||
|
||||
def _run_impl(self, a, b):
|
||||
|
||||
if self.dest.storage.read_only:
|
||||
meta = _ItemMetadata(item=self.item)
|
||||
else:
|
||||
|
|
|
|||
Loading…
Reference in a new issue