2015-03-22 18:21:15 +00:00
|
|
|
"""
|
|
|
|
Property-based tests using https://warehouse.python.org/project/hypothesis/
|
|
|
|
"""
|
|
|
|
|
2015-12-25 19:13:02 +00:00
|
|
|
from bidict import bidict, orderedbidict
|
2016-01-13 16:54:29 +00:00
|
|
|
from hypothesis import assume, given, settings
|
2015-12-21 03:05:20 +00:00
|
|
|
from hypothesis.strategies import (
|
|
|
|
binary, booleans, choices, dictionaries, floats, frozensets, integers,
|
|
|
|
lists, none, recursive, text, tuples)
|
2015-03-22 18:21:15 +00:00
|
|
|
from math import isnan
|
2016-01-13 16:54:29 +00:00
|
|
|
from os import getenv
|
|
|
|
|
|
|
|
|
|
|
|
# https://groups.google.com/d/msg/hypothesis-users/8FVs--1yUl4/JEkJ02euEwAJ
|
|
|
|
settings.register_profile('default', settings(strict=True))
|
|
|
|
settings.load_profile(getenv('HYPOTHESIS_PROFILE', 'default'))
|
2015-03-22 18:21:15 +00:00
|
|
|
|
|
|
|
|
2015-04-29 18:29:33 +00:00
|
|
|
def inv(d):
|
|
|
|
return {v: k for (k, v) in d.items()}
|
|
|
|
|
2015-12-21 03:05:20 +00:00
|
|
|
|
2015-04-29 18:29:33 +00:00
|
|
|
def prune_dup_vals(d):
|
|
|
|
pruned = inv(inv(d))
|
2015-12-21 03:05:20 +00:00
|
|
|
assume(len(pruned) >= len(d) // 2)
|
2015-04-29 18:29:33 +00:00
|
|
|
return pruned
|
2015-03-22 18:21:15 +00:00
|
|
|
|
2015-12-21 03:05:20 +00:00
|
|
|
|
|
|
|
def both_nan(a, b):
|
|
|
|
return isinstance(a, float) and isinstance(b, float) and \
|
|
|
|
isnan(a) and isnan(b)
|
|
|
|
|
|
|
|
|
|
|
|
def eq_nan(a, b):
|
|
|
|
return a == b or both_nan(a, b)
|
|
|
|
|
|
|
|
|
|
|
|
mutating_methods_by_arity = {
|
2015-12-25 19:13:02 +00:00
|
|
|
0: (bidict.clear, bidict.popitem, orderedbidict.popitem,),
|
|
|
|
1: (bidict.__delitem__, bidict.pop, bidict.setdefault,
|
|
|
|
orderedbidict.move_to_end,),
|
2015-12-21 03:05:20 +00:00
|
|
|
2: (bidict.__setitem__, bidict.pop, bidict.put, bidict.forceput,
|
|
|
|
bidict.setdefault,),
|
|
|
|
-1: (bidict.update, bidict.forceupdate,),
|
|
|
|
}
|
2016-01-13 16:54:29 +00:00
|
|
|
# otherwise data gen. in hypothesis>=1.19 is so slow the health checks fail:
|
|
|
|
kw = dict(average_size=2)
|
|
|
|
immu_atom = none() | booleans() | integers() | floats() | text(**kw) | binary(**kw)
|
|
|
|
immu_coll = lambda e: frozensets(e, **kw) | lists(e, **kw).map(tuple)
|
|
|
|
immutable = recursive(immu_atom, immu_coll)
|
|
|
|
d = dictionaries(immutable, immutable, average_size=5).map(prune_dup_vals)
|
2015-12-21 03:05:20 +00:00
|
|
|
|
2015-03-22 18:21:15 +00:00
|
|
|
|
2015-04-29 18:29:33 +00:00
|
|
|
@given(d)
|
|
|
|
def test_len(d):
|
2015-12-21 03:05:20 +00:00
|
|
|
b = bidict(d)
|
|
|
|
assert len(b) == len(b.inv) == len(d)
|
2015-03-22 18:21:15 +00:00
|
|
|
|
|
|
|
|
2015-04-29 18:29:33 +00:00
|
|
|
@given(d)
|
|
|
|
def test_bidirectional_mappings(d):
|
|
|
|
b = bidict(d)
|
2015-03-22 18:21:15 +00:00
|
|
|
for k, v in b.items():
|
2015-12-21 03:05:20 +00:00
|
|
|
assert eq_nan(k, b.inv[v])
|
2015-03-22 18:21:15 +00:00
|
|
|
|
2015-04-29 18:29:33 +00:00
|
|
|
|
|
|
|
# work around https://bitbucket.org/pypy/pypy/issue/1974
|
|
|
|
nan = float('nan')
|
|
|
|
WORKAROUND_NAN_BUG = (nan, nan) != (nan, nan)
|
|
|
|
|
2015-12-21 03:05:20 +00:00
|
|
|
|
2015-04-29 18:29:33 +00:00
|
|
|
@given(d)
|
|
|
|
def test_equality(d):
|
2015-05-04 15:08:25 +00:00
|
|
|
if WORKAROUND_NAN_BUG:
|
|
|
|
assume(nan not in d)
|
2015-04-29 18:29:33 +00:00
|
|
|
i = inv(d)
|
2015-05-04 15:08:25 +00:00
|
|
|
if WORKAROUND_NAN_BUG:
|
|
|
|
assume(nan not in i)
|
2015-04-29 18:29:33 +00:00
|
|
|
b = bidict(d)
|
|
|
|
assert b == d
|
2015-11-25 22:52:52 +00:00
|
|
|
assert b.inv == i
|
2015-04-29 18:29:33 +00:00
|
|
|
assert not b != d
|
2015-11-25 22:52:52 +00:00
|
|
|
assert not b.inv != i
|
2015-05-26 05:37:42 +00:00
|
|
|
|
2015-12-21 03:05:20 +00:00
|
|
|
|
|
|
|
@given(d, immutable, lists(tuples(immutable, immutable)))
|
|
|
|
def test_consistency_after_mutation(d, arg, itemlist):
|
|
|
|
for arity, mms in mutating_methods_by_arity.items():
|
|
|
|
for mm in mms:
|
2015-12-25 19:13:02 +00:00
|
|
|
b = orderedbidict(d) if 'orderedbidict' in repr(mm) else bidict(d)
|
2015-12-21 03:05:20 +00:00
|
|
|
args = []
|
|
|
|
if arity > 0:
|
|
|
|
args.append(arg)
|
|
|
|
if arity > 1:
|
|
|
|
args.append(arg)
|
|
|
|
if arity == -1: # update and forceupdate
|
|
|
|
args.append(itemlist)
|
|
|
|
assert b == inv(b.inv)
|
|
|
|
assert b.inv == inv(b)
|
|
|
|
try:
|
|
|
|
mm(b, *args)
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
assert b == inv(b.inv)
|
|
|
|
assert b.inv == inv(b)
|