from __future__ import annotations import aiostream import pytest from hypothesis import HealthCheck from hypothesis import given from hypothesis import settings from tests import uid_strategy from vdirsyncer.repair import IrreparableItem from vdirsyncer.repair import repair_item from vdirsyncer.repair import repair_storage from vdirsyncer.storage.memory import MemoryStorage from vdirsyncer.utils import href_safe from vdirsyncer.vobject import Item @given(uid=uid_strategy) # Using the random module for UIDs: @settings(suppress_health_check=list(HealthCheck)) @pytest.mark.asyncio async 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 = [(await s.get(href))[0].uid async for href, etag in s.list()] assert uid1 == uid2 await repair_storage(s, repair_unsafe_uid=False) uid1, uid2 = [ (await s.get(href))[0].uid for href, etag in await aiostream.stream.list(s.list()) ] assert uid1 != uid2 @given(uid=uid_strategy.filter(lambda x: not href_safe(x))) # Using the random module for UIDs: @settings(suppress_health_check=list(HealthCheck)) @pytest.mark.asyncio async def test_repair_unsafe_uids(uid): s = MemoryStorage() item = Item(f"BEGIN:VCARD\nUID:{uid}\nEND:VCARD") href, _etag = await s.upload(item) assert (await s.get(href))[0].uid == uid assert not href_safe(uid) await repair_storage(s, repair_unsafe_uid=True) new_href = (await aiostream.stream.list(s.list()))[0][0] assert href_safe(new_href) newuid = (await s.get(new_href))[0].uid assert href_safe(newuid) @pytest.mark.parametrize( ("uid", "href"), [("b@dh0mbr3", "perfectly-fine"), ("perfectly-fine", "b@dh0mbr3")] ) def test_repair_unsafe_href(uid, href): item = Item(f"BEGIN:VCARD\nUID:{uid}\nEND:VCARD") new_item = repair_item(href, item, set(), True) assert new_item.raw != item.raw assert new_item.uid != item.uid assert href_safe(new_item.uid) def test_repair_do_nothing(): item = Item("BEGIN:VCARD\nUID:justfine\nEND:VCARD") assert repair_item("fine", item, set(), True) is item assert repair_item("@@@@/fine", item, set(), True) is item @pytest.mark.parametrize( "raw", ["AYYY", "", "@@@@", "BEGIN:VCARD", "BEGIN:FOO\nEND:FOO"] ) def test_repair_irreparable(raw): with pytest.raises(IrreparableItem): repair_item("fine", Item(raw), set(), True)