def test_already_synced(): a = MemoryStorage(fileext=".a") b = MemoryStorage(fileext=".b") item = Item("UID:1") a.upload(item) b.upload(item) status = { "1": ( { "href": "1.a", "hash": item.hash, "etag": a.get("1.a")[1] }, { "href": "1.b", "hash": item.hash, "etag": b.get("1.b")[1] }, ) } old_status = deepcopy(status) a.update = b.update = a.upload = b.upload = lambda *a, **kw: pytest.fail( "Method shouldn't have been called.") for _ in (1, 2): sync(a, b, status) assert status == old_status assert items(a) == items(b) == {item.raw}
def test_already_synced(): a = MemoryStorage(fileext='.a') b = MemoryStorage(fileext='.b') item = Item(u'UID:1') a.upload(item) b.upload(item) status = { '1': ({ 'href': '1.a', 'hash': item.hash, 'etag': a.get('1.a')[1] }, { 'href': '1.b', 'hash': item.hash, 'etag': b.get('1.b')[1] }) } old_status = deepcopy(status) a.update = b.update = a.upload = b.upload = \ lambda *a, **kw: pytest.fail('Method shouldn\'t have been called.') for _ in (1, 2): sync(a, b, status) assert status == old_status assert items(a) == items(b) == {item.raw}
def test_already_synced(): a = MemoryStorage(fileext='.a') b = MemoryStorage(fileext='.b') item = Item('UID:1') a.upload(item) b.upload(item) status = { '1': ({ 'href': '1.a', 'hash': item.hash, 'etag': a.get('1.a')[1] }, { 'href': '1.b', 'hash': item.hash, 'etag': b.get('1.b')[1] }) } old_status = deepcopy(status) a.update = b.update = a.upload = b.upload = \ lambda *a, **kw: pytest.fail('Method shouldn\'t have been called.') for _ in (1, 2): sync(a, b, status) assert status == old_status assert items(a) == items(b) == {item.raw}
def test_no_uids(): a = MemoryStorage() b = MemoryStorage() href_a, _ = a.upload(Item(u'ASDF')) href_b, _ = b.upload(Item(u'FOOBAR')) status = {} sync(a, b, status) a_items = set(a.get(href)[0].raw for href, etag in a.list()) b_items = set(b.get(href)[0].raw for href, etag in b.list()) assert a_items == b_items == {u'ASDF', u'FOOBAR'}
def test_repair_unsafe_uids(uid): s = MemoryStorage() item = Item(u'BEGIN:VCARD\nUID:123\nEND:VCARD').with_uid(uid) href, etag = s.upload(item) assert s.get(href)[0].uid == uid assert not href_safe(uid) repair_storage(s, repair_unsafe_uid=True) new_href = list(s.list())[0][0] assert href_safe(new_href) newuid = s.get(new_href)[0].uid assert href_safe(newuid)
def test_repair_unsafe_uids(uid): s = MemoryStorage() item = Item('BEGIN:VCARD\nUID:{}\nEND:VCARD'.format(uid)) href, etag = s.upload(item) assert s.get(href)[0].uid == uid assert not href_safe(uid) repair_storage(s, repair_unsafe_uid=True) new_href = list(s.list())[0][0] assert href_safe(new_href) newuid = s.get(new_href)[0].uid assert href_safe(newuid)
def test_repair_unsafe_uids(uid): assert not href_safe(uid) s = MemoryStorage() href, etag = s.upload(Item(u'BEGIN:VCARD\nUID:{}\nEND:VCARD'.format(uid))) assert s.get(href)[0].uid == uid repair_storage(s) new_href = list(s.list())[0][0] assert href_safe(new_href) newuid = s.get(new_href)[0].uid assert href_safe(newuid)
def test_repair_uids(uid): s = MemoryStorage() s.items = { 'one': ('asdf', Item(f'BEGIN:VCARD\nFN:Hans\nUID:{uid}\nEND:VCARD')), 'two': ('asdf', Item(f'BEGIN:VCARD\nFN:Peppi\nUID:{uid}\nEND:VCARD')) } uid1, uid2 = [s.get(href)[0].uid for href, etag in s.list()] assert uid1 == uid2 repair_storage(s, repair_unsafe_uid=False) uid1, uid2 = [s.get(href)[0].uid for href, etag in s.list()] assert uid1 != uid2
def test_missing_status_and_different_items(): a = MemoryStorage() b = MemoryStorage() status = {} item1 = Item(u'UID:1\nhaha') item2 = Item(u'UID:1\nhoho') a.upload(item1) b.upload(item2) with pytest.raises(SyncConflict): sync(a, b, status) assert not status sync(a, b, status, conflict_resolution='a wins') assert_item_equals(item1, b.get('1.txt')[0]) assert_item_equals(item1, a.get('1.txt')[0])
def test_repair_unsafe_uids(uid): s = MemoryStorage() item = Item(u'BEGIN:VCARD\nUID:{}\nEND:VCARD'.format(uid)) print(repr(item.raw)) href, etag = s.upload(item) assert s.get(href)[0].uid == uid assert not href_safe(uid) repair_storage(s, repair_unsafe_uid=True) new_href = list(s.list())[0][0] assert href_safe(new_href) newuid = s.get(new_href)[0].uid assert href_safe(newuid)
def test_missing_status_and_different_items(): a = MemoryStorage() b = MemoryStorage() status = {} item1 = Item(u'UID:1\nhaha') item2 = Item(u'UID:1\nhoho') a.upload(item1) b.upload(item2) with pytest.raises(SyncConflict): sync(a, b, status) assert not status sync(a, b, status, conflict_resolution='a wins') assert_item_equals(item1, b.get('1')[0]) assert_item_equals(item1, a.get('1')[0])
def test_repair_uids(uid): s = MemoryStorage() s.items = { "one": ("asdf", Item(f"BEGIN:VCARD\nFN:Hans\nUID:{uid}\nEND:VCARD")), "two": ("asdf", Item(f"BEGIN:VCARD\nFN:Peppi\nUID:{uid}\nEND:VCARD")), } uid1, uid2 = [s.get(href)[0].uid for href, etag in s.list()] assert uid1 == uid2 repair_storage(s, repair_unsafe_uid=False) uid1, uid2 = [s.get(href)[0].uid for href, etag in s.list()] assert uid1 != uid2
def test_repair_uids(): s = MemoryStorage() s.items = { 'one': ('asdf', Item(u'BEGIN:VCARD\nFN:Hans\nUID:asdf\nEND:VCARD')), 'two': ('asdf', Item(u'BEGIN:VCARD\nFN:Peppi\nUID:asdf\nEND:VCARD')) } uid1, uid2 = [s.get(href)[0].uid for href, etag in s.list()] assert uid1 == uid2 repair_storage(s) uid1, uid2 = [s.get(href)[0].uid for href, etag in s.list()] assert uid1 != uid2
def test_already_synced(): a = MemoryStorage() b = MemoryStorage() item = Item(u'UID:1') a.upload(item) b.upload(item) status = {'1': ('1', a.get('1')[1], '1', b.get('1')[1])} old_status = dict(status) a.update = b.update = a.upload = b.upload = \ lambda *a, **kw: pytest.fail('Method shouldn\'t have been called.') for i in (1, 2): sync(a, b, status) assert status == old_status assert a.has('1') and b.has('1')
def test_repair_uids(): s = MemoryStorage() s.upload(Item(u'BEGIN:VCARD\nEND:VCARD')) repair_storage(s) uid, = [s.get(href)[0].uid for href, etag in s.list()] s.upload(Item(u'BEGIN:VCARD\nUID:{}\nEND:VCARD'.format(uid))) uid1, uid2 = [s.get(href)[0].uid for href, etag in s.list()] assert uid1 == uid2 repair_storage(s) uid1, uid2 = [s.get(href)[0].uid for href, etag in s.list()] assert uid1 != uid2
def test_already_synced(): a = MemoryStorage() b = MemoryStorage() item = Item(u'UID:1') a.upload(item) b.upload(item) status = { '1': ('1.txt', a.get('1.txt')[1], '1.txt', b.get('1.txt')[1]) } old_status = dict(status) a.update = b.update = a.upload = b.upload = \ lambda *a, **kw: pytest.fail('Method shouldn\'t have been called.') for i in (1, 2): sync(a, b, status) assert status == old_status assert a.has('1.txt') and b.has('1.txt')
def test_deletion(): a = MemoryStorage() b = MemoryStorage() status = {} item = Item(u'UID:1') a.upload(item) a.upload(Item(u'UID:2')) sync(a, b, status) b.delete('1', b.get('1')[1]) sync(a, b, status) assert not a.has('1') and not b.has('1') a.upload(item) sync(a, b, status) assert a.has('1') and b.has('1') a.delete('1', a.get('1')[1]) sync(a, b, status) assert not a.has('1') and not b.has('1')
def test_deletion(): a = MemoryStorage(fileext=".a") b = MemoryStorage(fileext=".b") status = {} item = Item(u"UID:1") a.upload(item) a.upload(Item(u"UID:2")) sync(a, b, status) b.delete("1.b", b.get("1.b")[1]) sync(a, b, status) assert not a.has("1.a") and not b.has("1.b") a.upload(item) sync(a, b, status) assert a.has("1.a") and b.has("1.b") a.delete("1.a", a.get("1.a")[1]) sync(a, b, status) assert not a.has("1.a") and not b.has("1.b")
def test_deletion(): a = MemoryStorage() b = MemoryStorage() status = {} item = Item(u'UID:1') a.upload(item) a.upload(Item(u'UID:2')) sync(a, b, status) b.delete('1.txt', b.get('1.txt')[1]) sync(a, b, status) assert not a.has('1.txt') and not b.has('1.txt') a.upload(item) sync(a, b, status) assert a.has('1.txt') and b.has('1.txt') a.delete('1.txt', a.get('1.txt')[1]) sync(a, b, status) assert not a.has('1.txt') and not b.has('1.txt')
def test_conflict_resolution_both_etags_new(winning_storage): a = MemoryStorage() b = MemoryStorage() item = Item(u"UID:1") href_a, etag_a = a.upload(item) href_b, etag_b = b.upload(item) status = {} sync(a, b, status) assert status a.update(href_a, Item(u"UID:1\nitem a"), etag_a) b.update(href_b, Item(u"UID:1\nitem b"), etag_b) with pytest.raises(SyncConflict): sync(a, b, status) sync(a, b, status, conflict_resolution="{} wins".format(winning_storage)) item_a, _ = a.get(href_a) item_b, _ = b.get(href_b) assert_item_equals(item_a, item_b) n = item_a.raw.splitlines() assert u"UID:1" in n assert u"item {}".format(winning_storage) in n
def test_deletion(): a = MemoryStorage(fileext=".a") b = MemoryStorage(fileext=".b") status = {} item = Item("UID:1") a.upload(item) item2 = Item("UID:2") a.upload(item2) sync(a, b, status) b.delete("1.b", b.get("1.b")[1]) sync(a, b, status) assert items(a) == items(b) == {item2.raw} a.upload(item) sync(a, b, status) assert items(a) == items(b) == {item.raw, item2.raw} a.delete("1.a", a.get("1.a")[1]) sync(a, b, status) assert items(a) == items(b) == {item2.raw}
def test_conflict_resolution_both_etags_new(winning_storage): a = MemoryStorage() b = MemoryStorage() item = Item(u'UID:1') href_a, etag_a = a.upload(item) href_b, etag_b = b.upload(item) status = {} sync(a, b, status) assert status a.update(href_a, Item(u'UID:1\nitem a'), etag_a) b.update(href_b, Item(u'UID:1\nitem b'), etag_b) with pytest.raises(SyncConflict): sync(a, b, status) sync(a, b, status, conflict_resolution='{} wins'.format(winning_storage)) item_a, _ = a.get(href_a) item_b, _ = b.get(href_b) assert_item_equals(item_a, item_b) n = normalize_item(item_a) assert u'UID:1' in n assert u'item {}'.format(winning_storage) in n
def test_repair_uids(uid): s = MemoryStorage() s.items = { 'one': ( 'asdf', Item(u'BEGIN:VCARD\nFN:Hans\nUID:{}\nEND:VCARD'.format(uid)) ), 'two': ( 'asdf', Item(u'BEGIN:VCARD\nFN:Peppi\nUID:{}\nEND:VCARD'.format(uid)) ) } uid1, uid2 = [s.get(href)[0].uid for href, etag in s.list()] assert uid1 == uid2 repair_storage(s, repair_unsafe_uid=False) uid1, uid2 = [s.get(href)[0].uid for href, etag in s.list()] assert uid1 != uid2
def test_deletion(): a = MemoryStorage(fileext='.a') b = MemoryStorage(fileext='.b') status = {} item = Item(u'UID:1') a.upload(item) item2 = Item(u'UID:2') a.upload(item2) sync(a, b, status) b.delete('1.b', b.get('1.b')[1]) sync(a, b, status) assert items(a) == items(b) == {item2.raw} a.upload(item) sync(a, b, status) assert items(a) == items(b) == {item.raw, item2.raw} a.delete('1.a', a.get('1.a')[1]) sync(a, b, status) assert items(a) == items(b) == {item2.raw}
def test_deletion(): a = MemoryStorage(fileext='.a') b = MemoryStorage(fileext='.b') status = {} item = Item('UID:1') a.upload(item) item2 = Item('UID:2') a.upload(item2) sync(a, b, status) b.delete('1.b', b.get('1.b')[1]) sync(a, b, status) assert items(a) == items(b) == {item2.raw} a.upload(item) sync(a, b, status) assert items(a) == items(b) == {item.raw, item2.raw} a.delete('1.a', a.get('1.a')[1]) sync(a, b, status) assert items(a) == items(b) == {item2.raw}
def newstorage(self, read_only, flaky_etags): s = MemoryStorage() s.read_only = read_only if flaky_etags: def get(href): _, item = s.items[href] etag = _random_string() s.items[href] = etag, item return item, etag s.get = get return s
def test_already_synced(): a = MemoryStorage(fileext=".a") b = MemoryStorage(fileext=".b") item = Item(u"UID:1") a.upload(item) b.upload(item) status = {"1": ({"href": "1.a", "etag": a.get("1.a")[1]}, {"href": "1.b", "etag": b.get("1.b")[1]})} old_status = dict(status) a.update = b.update = a.upload = b.upload = lambda *a, **kw: pytest.fail("Method shouldn't have been called.") for i in (1, 2): sync(a, b, status) assert status == old_status assert a.has("1.a") and b.has("1.b")
def test_already_synced(): a = MemoryStorage(fileext='.a') b = MemoryStorage(fileext='.b') item = Item(u'UID:1') a.upload(item) b.upload(item) status = { '1': ({ 'href': '1.a', 'etag': a.get('1.a')[1] }, { 'href': '1.b', 'etag': b.get('1.b')[1] }) } old_status = dict(status) a.update = b.update = a.upload = b.upload = \ lambda *a, **kw: pytest.fail('Method shouldn\'t have been called.') for i in (1, 2): sync(a, b, status) assert status == old_status assert a.has('1.a') and b.has('1.b')
def test_upload_and_update(): a = MemoryStorage(fileext='.a') b = MemoryStorage(fileext='.b') status = {} item = Item('UID:1') # new item 1 in a a.upload(item) sync(a, b, status) assert items(b) == items(a) == {item.raw} item = Item('UID:1\nASDF:YES') # update of item 1 in b b.update('1.b', item, b.get('1.b')[1]) sync(a, b, status) assert items(b) == items(a) == {item.raw} item2 = Item('UID:2') # new item 2 in b b.upload(item2) sync(a, b, status) assert items(b) == items(a) == {item.raw, item2.raw} item2 = Item('UID:2\nASDF:YES') # update of item 2 in a a.update('2.a', item2, a.get('2.a')[1]) sync(a, b, status) assert items(b) == items(a) == {item.raw, item2.raw}
def test_upload_and_update(): a = MemoryStorage(fileext='.a') b = MemoryStorage(fileext='.b') status = {} item = Item(u'UID:1') # new item 1 in a a.upload(item) sync(a, b, status) assert items(b) == items(a) == {item.raw} item = Item(u'UID:1\nASDF:YES') # update of item 1 in b b.update('1.b', item, b.get('1.b')[1]) sync(a, b, status) assert items(b) == items(a) == {item.raw} item2 = Item(u'UID:2') # new item 2 in b b.upload(item2) sync(a, b, status) assert items(b) == items(a) == {item.raw, item2.raw} item2 = Item(u'UID:2\nASDF:YES') # update of item 2 in a a.update('2.a', item2, a.get('2.a')[1]) sync(a, b, status) assert items(b) == items(a) == {item.raw, item2.raw}
def test_upload_and_update(): a = MemoryStorage(fileext=".a") b = MemoryStorage(fileext=".b") status = {} item = Item("UID:1") # new item 1 in a a.upload(item) sync(a, b, status) assert items(b) == items(a) == {item.raw} item = Item("UID:1\nASDF:YES") # update of item 1 in b b.update("1.b", item, b.get("1.b")[1]) sync(a, b, status) assert items(b) == items(a) == {item.raw} item2 = Item("UID:2") # new item 2 in b b.upload(item2) sync(a, b, status) assert items(b) == items(a) == {item.raw, item2.raw} item2 = Item("UID:2\nASDF:YES") # update of item 2 in a a.update("2.a", item2, a.get("2.a")[1]) sync(a, b, status) assert items(b) == items(a) == {item.raw, item2.raw}
def newstorage(self, flaky_etags, null_etag_on_upload): s = MemoryStorage() if flaky_etags: def get(href): old_etag, item = s.items[href] etag = _random_string() s.items[href] = etag, item return item, etag s.get = get if null_etag_on_upload: _old_upload = s.upload _old_update = s.update s.upload = lambda item: (_old_upload(item)[0], 'NULL') s.update = lambda h, i, e: _old_update(h, i, e) and 'NULL' return s
def test_bogus_etag_change(): """Assert that sync algorithm is resilient against etag changes if content didn\'t change. In this particular case we test a scenario where both etags have been updated, but only one side actually changed its item content. """ a = MemoryStorage() b = MemoryStorage() status = {} href_a, etag_a = a.upload(Item(u"UID:ASDASD")) sync(a, b, status) assert len(status) == len(list(a.list())) == len(list(b.list())) == 1 (href_b, etag_b), = b.list() a.update(href_a, Item(u"UID:ASDASD"), etag_a) b.update(href_b, Item(u"UID:ASDASD\nACTUALCHANGE:YES"), etag_b) b.delete = b.update = b.upload = blow_up sync(a, b, status) assert len(status) == len(list(a.list())) == len(list(b.list())) == 1 assert a.get(href_a)[0].raw == u"UID:ASDASD\nACTUALCHANGE:YES"
def test_bogus_etag_change(): '''Assert that sync algorithm is resilient against etag changes if content didn\'t change. In this particular case we test a scenario where both etags have been updated, but only one side actually changed its item content. ''' a = MemoryStorage() b = MemoryStorage() status = {} href_a, etag_a = a.upload(Item(u'UID:ASDASD')) sync(a, b, status) assert len(status) == len(list(a.list())) == len(list(b.list())) == 1 (href_b, etag_b), = b.list() a.update(href_a, Item(u'UID:ASDASD'), etag_a) b.update(href_b, Item(u'UID:ASDASD\nACTUALCHANGE:YES'), etag_b) b.delete = b.update = b.upload = blow_up sync(a, b, status) assert len(status) == len(list(a.list())) == len(list(b.list())) == 1 assert a.get(href_a)[0].raw == u'UID:ASDASD\nACTUALCHANGE:YES'
def test_upload_and_update(): a = MemoryStorage() b = MemoryStorage() status = {} item = Item(u'UID:1') # new item 1 in a a.upload(item) sync(a, b, status) assert_item_equals(b.get('1')[0], item) item = Item(u'UID:1\nASDF:YES') # update of item 1 in b b.update('1', item, b.get('1')[1]) sync(a, b, status) assert_item_equals(a.get('1')[0], item) item2 = Item(u'UID:2') # new item 2 in b b.upload(item2) sync(a, b, status) assert_item_equals(a.get('2')[0], item2) item2 = Item(u'UID:2\nASDF:YES') # update of item 2 in a a.update('2', item2, a.get('2')[1]) sync(a, b, status) assert_item_equals(b.get('2')[0], item2)
def test_upload_and_update(): a = MemoryStorage(fileext=".a") b = MemoryStorage(fileext=".b") status = {} item = Item(u"UID:1") # new item 1 in a a.upload(item) sync(a, b, status) assert_item_equals(b.get("1.b")[0], item) item = Item(u"UID:1\nASDF:YES") # update of item 1 in b b.update("1.b", item, b.get("1.b")[1]) sync(a, b, status) assert_item_equals(a.get("1.a")[0], item) item2 = Item(u"UID:2") # new item 2 in b b.upload(item2) sync(a, b, status) assert_item_equals(a.get("2.a")[0], item2) item2 = Item(u"UID:2\nASDF:YES") # update of item 2 in a a.update("2.a", item2, a.get("2.a")[1]) sync(a, b, status) assert_item_equals(b.get("2.b")[0], item2)
def test_upload_and_update(): a = MemoryStorage() b = MemoryStorage() status = {} item = Item(u'UID:1') # new item 1 in a a.upload(item) sync(a, b, status) assert_item_equals(b.get('1.txt')[0], item) item = Item(u'UID:1\nASDF:YES') # update of item 1 in b b.update('1.txt', item, b.get('1.txt')[1]) sync(a, b, status) assert_item_equals(a.get('1.txt')[0], item) item2 = Item(u'UID:2') # new item 2 in b b.upload(item2) sync(a, b, status) assert_item_equals(a.get('2.txt')[0], item2) item2 = Item(u'UID:2\nASDF:YES') # update of item 2 in a a.update('2.txt', item2, a.get('2.txt')[1]) sync(a, b, status) assert_item_equals(b.get('2.txt')[0], item2)