mirror of
https://github.com/samsonjs/vdirsyncer.git
synced 2026-03-25 08:55:50 +00:00
More tests for vobject (#541)
* More tests for vobject * wip * wip * stylefix
This commit is contained in:
parent
f756366081
commit
3514d7348c
2 changed files with 152 additions and 6 deletions
|
|
@ -3,7 +3,8 @@
|
|||
from textwrap import dedent
|
||||
|
||||
import hypothesis.strategies as st
|
||||
from hypothesis import given
|
||||
from hypothesis import assume, given
|
||||
from hypothesis.stateful import Bundle, RuleBasedStateMachine, rule
|
||||
|
||||
import pytest
|
||||
|
||||
|
|
@ -214,3 +215,128 @@ def test_replace_uid(template, uid):
|
|||
assert item.raw.count('\nUID:{}'.format(uid)) == 1
|
||||
else:
|
||||
assert '\nUID:' not in item.raw
|
||||
|
||||
|
||||
def test_broken_item():
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
vobject._Component.parse('END:FOO')
|
||||
|
||||
assert 'Parsing error at line 1' in str(excinfo.value)
|
||||
|
||||
item = vobject.Item('END:FOO')
|
||||
assert item.parsed is None
|
||||
|
||||
|
||||
def test_multiple_items():
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
vobject._Component.parse([
|
||||
'BEGIN:FOO',
|
||||
'END:FOO',
|
||||
'BEGIN:FOO',
|
||||
'END:FOO',
|
||||
])
|
||||
|
||||
assert 'Found 2 components, expected one' in str(excinfo.value)
|
||||
|
||||
c1, c2 = vobject._Component.parse([
|
||||
'BEGIN:FOO',
|
||||
'END:FOO',
|
||||
'BEGIN:FOO',
|
||||
'END:FOO',
|
||||
], multiple=True)
|
||||
assert c1.name == c2.name == 'FOO'
|
||||
|
||||
|
||||
def test_input_types():
|
||||
lines = ['BEGIN:FOO', 'FOO:BAR', 'END:FOO']
|
||||
|
||||
for x in (lines, '\r\n'.join(lines), '\r\n'.join(lines).encode('ascii')):
|
||||
c = vobject._Component.parse(x)
|
||||
assert c.name == 'FOO'
|
||||
assert c.props == ['FOO:BAR']
|
||||
assert not c.subcomponents
|
||||
|
||||
|
||||
value_strategy = st.text(
|
||||
st.characters(blacklist_categories=(
|
||||
'Zs', 'Zl', 'Zp',
|
||||
'Cc', 'Cs'
|
||||
), blacklist_characters=':='),
|
||||
min_size=1
|
||||
).filter(lambda x: x.strip() == x)
|
||||
|
||||
|
||||
class VobjectMachine(RuleBasedStateMachine):
|
||||
Unparsed = Bundle('unparsed')
|
||||
Parsed = Bundle('parsed')
|
||||
|
||||
@rule(target=Unparsed,
|
||||
joined=st.booleans(),
|
||||
encoded=st.booleans())
|
||||
def get_unparsed_lines(self, joined, encoded):
|
||||
rv = ['BEGIN:FOO', 'FOO:YES', 'END:FOO']
|
||||
if joined:
|
||||
rv = '\r\n'.join(rv)
|
||||
if encoded:
|
||||
rv = rv.encode('utf-8')
|
||||
elif encoded:
|
||||
assume(False)
|
||||
return rv
|
||||
|
||||
@rule(unparsed=Unparsed, target=Parsed)
|
||||
def parse(self, unparsed):
|
||||
return vobject._Component.parse(unparsed)
|
||||
|
||||
@rule(parsed=Parsed, target=Unparsed)
|
||||
def serialize(self, parsed):
|
||||
return list(parsed.dump_lines())
|
||||
|
||||
@rule(c=Parsed,
|
||||
key=uid_strategy,
|
||||
value=uid_strategy)
|
||||
def add_prop(self, c, key, value):
|
||||
c[key] = value
|
||||
assert c[key] == value
|
||||
assert key in c
|
||||
assert c.get(key) == value
|
||||
dump = '\r\n'.join(c.dump_lines())
|
||||
assert key in dump and value in dump
|
||||
|
||||
@rule(c=Parsed,
|
||||
key=uid_strategy,
|
||||
value=uid_strategy,
|
||||
params=st.lists(st.tuples(value_strategy, value_strategy)))
|
||||
def add_prop_raw(self, c, key, value, params):
|
||||
params_str = ','.join(k + '=' + v for k, v in params)
|
||||
c.props.append('{};{}:{}'.format(key, params_str, value))
|
||||
assert c[key] == value
|
||||
assert key in c
|
||||
assert c.get(key) == value
|
||||
|
||||
@rule(c=Parsed, sub_c=Parsed)
|
||||
def add_component(self, c, sub_c):
|
||||
assume(sub_c is not c and sub_c not in c)
|
||||
c.subcomponents.append(sub_c)
|
||||
assert '\r\n'.join(sub_c.dump_lines()) in '\r\n'.join(c.dump_lines())
|
||||
|
||||
@rule(c=Parsed)
|
||||
def sanity_check(self, c):
|
||||
c1 = vobject._Component.parse(c.dump_lines())
|
||||
assert c1 == c
|
||||
|
||||
|
||||
TestVobjectMachine = VobjectMachine.TestCase
|
||||
|
||||
|
||||
def test_component_contains():
|
||||
item = vobject._Component.parse([
|
||||
'BEGIN:FOO',
|
||||
'FOO:YES',
|
||||
'END:FOO'
|
||||
])
|
||||
|
||||
assert 'FOO' in item
|
||||
assert 'BAZ' not in item
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
42 in item
|
||||
|
|
|
|||
|
|
@ -272,8 +272,7 @@ class _Component(object):
|
|||
if line.strip():
|
||||
stack[-1].props.append(line)
|
||||
except IndexError:
|
||||
raise ValueError('Parsing error at line {}. Check the debug log '
|
||||
'for more information.'.format(_i + 1))
|
||||
raise ValueError('Parsing error at line {}'.format(_i + 1))
|
||||
|
||||
if multiple:
|
||||
return rv
|
||||
|
|
@ -319,12 +318,25 @@ class _Component(object):
|
|||
line = u'{}:{}'.format(key, val)
|
||||
self.props.append(line)
|
||||
|
||||
def __contains__(self, obj):
|
||||
if isinstance(obj, type(self)):
|
||||
return obj not in self.subcomponents and \
|
||||
not any(obj in x for x in self.subcomponents)
|
||||
elif isinstance(obj, str):
|
||||
return self.get(obj, None) is not None
|
||||
else:
|
||||
raise ValueError(obj)
|
||||
|
||||
def __getitem__(self, key):
|
||||
prefix = (u'{}:'.format(key), u'{};'.format(key))
|
||||
prefix_without_params = '{}:'.format(key)
|
||||
prefix_with_params = '{};'.format(key)
|
||||
iterlines = iter(self.props)
|
||||
for line in iterlines:
|
||||
if line.startswith(prefix):
|
||||
rv = line.split(u':', 1)[-1]
|
||||
if line.startswith(prefix_without_params):
|
||||
rv = line[len(prefix_without_params):]
|
||||
break
|
||||
elif line.startswith(prefix_with_params):
|
||||
rv = line[len(prefix_with_params):].split(':', 1)[-1]
|
||||
break
|
||||
else:
|
||||
raise KeyError()
|
||||
|
|
@ -342,3 +354,11 @@ class _Component(object):
|
|||
return self[key]
|
||||
except KeyError:
|
||||
return default
|
||||
|
||||
def __eq__(self, other):
|
||||
return (
|
||||
isinstance(other, type(self)) and
|
||||
self.name == other.name and
|
||||
self.props == other.props and
|
||||
self.subcomponents == other.subcomponents
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in a new issue