def test_mutual_recursion(): t = st.deferred(lambda: a | b) a = st.deferred(lambda: st.none() | st.tuples(st.just("a"), b)) b = st.deferred(lambda: st.none() | st.tuples(st.just("b"), a)) for c in ("a", "b"): assert minimal(t, lambda x: x is not None and x[0] == c) == (c, None)
def quoted_forms(): return tuples( one_of( symbol_table[q] for q in ['quote', 'quasiquote', 'unquote', 'unquote-splicing']), deferred(lambda: forms), ).map(lambda elems: list(*elems))
def test_recursion_in_middle(): # This test is significant because the integers().map(abs) is not checked # in the initial pass - when we recurse into x initially we decide that # x is empty, so the tuple is empty, and don't need to check the third # argument. Then when we do the more refined test we've discovered that x # is non-empty, so we need to check the non-emptiness of the last component # to determine the non-emptiness of the tuples. x = st.deferred(lambda: st.tuples(st.none(), x, st.integers().map(abs)) | st.none()) assert not x.is_empty
def message_to_strategy(message_obj, env, overrides=None): """Generate strategy from message.""" # Protobuf messages may have recursive dependencies. # We can manage these by lazily constructing strategies using st.deferred return st.deferred(lambda: st.builds( buildable(message_obj), **{ field_name: field_to_strategy(field, env, overrides=overrides) for field_name, field in message_obj.DESCRIPTOR.fields_by_name. items() }))
def build_strategy_for_indices(base, ixs, deferred): def f(): return base(*[strategies[i] for i in ixs]) f.__name__ = '%s([%s])' % (base.__name__, ', '.join('strategies[%d]' % (i, ) for i in ixs)) if deferred: return st.deferred(f) else: return f()
def test_literals_strategy_is_valid(): literals = st.deferred(lambda: st.one_of(st.booleans( ), st.tuples(literals, literals), literals.map(lambda x: [x]))) @given(literals) def test(e): pass test() assert not literals.has_reusable_values
def st_hashable(): x = st.deferred(lambda: st.text() | st.binary() | st.integers() | st.floats(allow_nan=False) | st.decimals(allow_nan=False) | st.fractions() | st.datetimes() | st.tuples(x) | st.frozensets(x)) return x
def generate_measurements(self, day): """Generate measurements using Hypothesis""" return lists(from_model(Measurement, # deferred so that select happens only after # they are guaranteed to exist (created in # setUp) metric=deferred( lambda: just(Metric.objects.first())), channel=deferred( lambda: just(Channel.objects.first())), user=deferred( lambda: just(get_user_model().objects\ .first()) ), value=integers( min_value=-(10**16) + 1, max_value=(10**16) - 1), # constrain end times to be in range starttime=datetimes( min_value=day + relativedelta(seconds=1), max_value=day + relativedelta(hours=23), timezones=just(pytz.UTC))))
def composites(draw: Draw, unique_identifiers: ty.Generator[ID, None, None]) -> Composite: return draw( st.one_of( opaque(), sequences( st.one_of( scalars(unique_identifiers, multiple_of_8=True), st.deferred(lambda: non_null_messages(unique_identifiers)), ), unique_identifiers, ), ) )
def test_literals_strategy_is_valid(): literals = st.deferred(lambda: st.one_of( st.booleans(), st.tuples(literals, literals), literals.map(lambda x: [x]), )) @given(literals) def test(e): pass test() assert not literals.has_reusable_values
def sample_type_of(f, depth=0): def try_sample(cls): try: return f(cls) except AttributeError: return st.nothing() # NOTE: 1) Use deferring to work with the circular dependency in the type # modules: they import this module and types() function imports them. 2) # First select the type, then apply try_sample to it. If one would apply # try_sample to all types and then select one of the results, it would lead # to infinite recursion as all possible paths are traversed. 3) Use flatmap # instead of map! return st.deferred(lambda: st.sampled_from(types())).flatmap(try_sample)
def test_non_trivial_json(): json = st.deferred(lambda: st.none() | st.floats() | st.text() | lists | objects) lists = st.lists(json) objects = st.dictionaries(st.text(), json) assert minimal(json) is None small_list = minimal(json, lambda x: isinstance(x, list) and x) assert small_list == [None] x = minimal(json, lambda x: isinstance(x, dict) and isinstance(x.get(""), list)) assert x == {"": []}
def test_mutually_recursive_types_with_typevar(data): # The previously-failing example from the issue A = Dict[bool, "B"] # noqa: F821 - an undefined name is the whole point! B = Union[List[bool], A] with pytest.raises(ResolutionFailed, match=r"Could not resolve ForwardRef\('B'\)"): data.draw(st.from_type(A)) with utils.temp_registered( ForwardRef("B"), lambda _: st.deferred(lambda: b_strategy), ): b_strategy = st.from_type(B) data.draw(b_strategy) data.draw(st.from_type(A)) data.draw(st.from_type(B))
def test_mutually_recursive_types_with_typevar_alternate(data): # It's not particularly clear why this version passed when the previous # test failed, but different behaviour means we add both to the suite. C = Union[List[bool], "D"] # noqa: F821 - an undefined name is the whole point! D = Dict[bool, C] with pytest.raises(ResolutionFailed, match=r"Could not resolve ForwardRef\('D'\)"): data.draw(st.from_type(C)) with utils.temp_registered( ForwardRef("D"), lambda _: st.deferred(lambda: d_strategy), ): d_strategy = st.from_type(D) data.draw(d_strategy) data.draw(st.from_type(C)) data.draw(st.from_type(D))
def test_calculator_benchmark(): """This test comes from https://github.com/jlink/shrinking-challenge/blob/main/challenges/calculator.md, which is originally from Pike, Lee. "SmartCheck: automatic and efficient counterexample reduction and generalization." Proceedings of the 2014 ACM SIGPLAN symposium on Haskell. 2014. """ expression = st.deferred( lambda: st.one_of( st.integers(), st.tuples(st.just("+"), expression, expression), st.tuples(st.just("/"), expression, expression), ) ) def div_subterms(e): if isinstance(e, int): return True if e[0] == "/" and e[-1] == 0: return False return div_subterms(e[1]) and div_subterms(e[2]) def evaluate(e): if isinstance(e, int): return e elif e[0] == "+": return evaluate(e[1]) + evaluate(e[2]) else: assert e[0] == "/" return evaluate(e[1]) // evaluate(e[2]) def is_failing(e): assume(div_subterms(e)) try: evaluate(e) return False except ZeroDivisionError: return True x = minimal(expression, is_failing) assert x == ("/", 0, ("+", 0, 0))
def run_multiple_state_machines(parameters, data): arguments = {} init_args, _, _, default = inspect.getargspec(rtl_class.__init__) if default is None: default = [] init_args = init_args[1:len(init_args) - len(default)] if set(init_args) - set(parameters.keys()): raise ValueError(""" Found arg in rtl model __init__ args not int init_strategy! - init_strategy: {strategy_func_arg} - rtl __init__ : {init_args} """.format(strategy_func_arg=list_string(parameters.keys()), init_args=list_string(init_args))) args, _, _, _ = inspect.getargspec(method_strategy_class.__init__) args = args[1:] if set(init_args) - set(args): raise ValueError(""" Found arg in rtl model __init__ args not int method_strategy class __init__! - method_strategy: {strategy_func_arg} - rtl model : {init_args} """.format(strategy_func_arg=list_string(args), init_args=list_string(init_args))) method_strategy = method_strategy_class(**parameters) for k, v in inspect.getmembers(method_strategy): if isinstance(v, ArgumentStrategy): target = arguments.setdefault(k, {}) for arg_name, strategy in v.arguments.iteritems(): target[arg_name] = st.deferred(lambda s=strategy: s) state_machine_factory = TestModel._create_test_state_machine( rtl_class, reference_class, parameters, translate_model=translate_model, argument_strategy=arguments, release_cycle_accuracy=release_cycle_accuracy, customized_comparators=customized_comparators) TestModel._run_state_machine(state_machine_factory)
def sample_value(cls, a, max_depth=3): # It's not possible to sample linked lists lazily because hypothesis # doesn't support that sampling happens at some later point (the # sampler gets "frozen"). So, we must sample everything at once, # although we then add the "lazy" lambda wrapping to the pre-sampled # values. # # This non-lazy sampling could be implemented recursively as follows: # return ( st.just(Nil) if max_depth <= 0 else st.deferred( lambda: st.one_of( st.just(Nil), a.flatmap( lambda x: cls.sample_value(a, max_depth=max_depth-1).map( lambda xs: Cons(x, lambda: xs) ) ) ) ) )
def test_bad_branching_tree(): tree = st.deferred( lambda: st.tuples(tree, tree, tree, tree, tree) | st.integers()) assert minimal(tree) == 0 assert minimal(tree, lambda x: isinstance(x, tuple)) == (0,) * 5
def test_binary_tree(): tree = st.deferred(lambda: st.integers() | st.tuples(tree, tree)) assert minimal(tree) == 0 assert minimal(tree, lambda x: isinstance(x, tuple)) == (0, 0)
def test_self_recursive_lists(): x = st.deferred(lambda: st.lists(x)) assert minimal(x) == [] assert minimal(x, bool) == [[]] assert minimal(x, lambda x: len(x) > 1) == [[], []]
child = attr.ib() @attr.s() class Branch(object): bits = attr.ib() children = attr.ib(default=attr.Factory(dict)) @attr.s() class Terminal(object): status = attr.ib() payload = attr.ib(default=None) nodes = st.deferred(lambda: terminals | writes | branches) # Does not include Status.OVERFLOW by design: That happens because of the size # of the string, not the input language. terminals = st.one_of( st.just(Terminal(Status.VALID)), st.just(Terminal(Status.INVALID)), st.builds(Terminal, status=st.just(Status.INTERESTING), payload=st.integers(0, 10)), ) branches = st.builds(Branch, bits=st.integers(1, 64)) writes = st.builds(Write, value=st.binary(min_size=1), child=nodes)
def s_expressions(*args, **kwargs): return st.builds(SExpression.from_iterable, st.lists(*args, **kwargs)) def quoteds(strategy): return st.builds(Quoted, strategy) symbols = st.builds( s, st.from_regex(r'''[^0-9"'();.\s][^"'();\s]*''', fullmatch=True)) strings = st.builds(sl, st.text()) ast_objects = st.deferred(lambda: (symbols | strings | st.integers() | st.floats(allow_nan=False, allow_infinity=False) | quoteds(ast_objects) | s_expressions(ast_objects))) ast_lists = st.lists(ast_objects) def deparse(exprs): for expr in exprs: if type(expr) in {int, float, s, sl}: yield expr elif isinstance(expr, Quoted): yield q yield from deparse([expr.elem]) elif expr is NIL: yield lp
def test_errors_on_definition_as_self(): x = st.deferred(lambda: x) with pytest.raises(InvalidArgument): x.example()
def test_label_of_deferred_strategy_is_well_defined(): recursive = st.deferred(lambda: st.lists(recursive)) recursive.label
def test_recursion_does_not_break_reusability(): x = st.deferred(lambda: st.none() | st.tuples(x)) assert x.has_reusable_values
import hypothesis.strategies as st from hypothesis import assume from evalcommon import eval_given expression = st.deferred(lambda: st.one_of( st.integers(), st.tuples(st.just('+'), expression, expression), st.tuples(st.just('/'), expression, expression), )) def div_subterms(e): if isinstance(e, int): return True if e[0] == '/' and e[-1] == 0: return False return div_subterms(e[1]) and div_subterms(e[2]) def evaluate(e): if isinstance(e, int): return e elif e[0] == '+': return evaluate(e[1]) + evaluate(e[2]) else: assert e[0] == '/' return evaluate(e[1]) // evaluate(e[2]) if __name__ == '__main__':
def comp(f): return st.deferred(st.composite(f))
""" Tests for the head() utility function """ import random import string import pytest from hypothesis import given, strategies as st from pypiper.utils import head __author__ = "Vince Reuter" __email__ = "*****@*****.**" NUMBERS_AND_LETTERS = list(string.ascii_letters) + list(range(-9, 10)) # Strategy for generating a pretty arbitrary atomic ATOMICS = st.deferred(lambda: st.booleans() | st.characters() | st.integers() | st.floats(allow_nan=False) | st.text()) def pytest_generate_tests(metafunc): """ Test case generation/parameterization for this module. """ if "seqtype" in metafunc.fixturenames: metafunc.parametrize("seqtype", [tuple, list]) if "iter_cast" in metafunc.fixturenames: metafunc.parametrize("iter_cast", [lambda c: c, lambda c: iter(c)]) if "h" in metafunc.fixturenames and "xs" in metafunc.fixturenames: metafunc.parametrize(["h", "xs"], [(random.choice(NUMBERS_AND_LETTERS), [ random.choice(NUMBERS_AND_LETTERS) for _ in range(random.randint(5, 10)) ]) for _ in range(10)])
def test_branches_pass_through_deferred(): x = st.one_of(st.booleans(), st.integers()) y = st.deferred(lambda: x) assert x.branches == y.branches
@serializable class Foo(object): pass primitives_st = st.sampled_from([Int, Bool, Float, Str, NoneType, KnownClass]) strings = (st.text(st.characters(min_codepoint=32, max_codepoint=126)).map(str) if six.PY2 else st.text()) proxytypes = st.deferred(lambda: ( primitives_st | st.builds(List.__class_getitem__, proxytypes) | st.builds(Dict.__class_getitem__, st.tuples(primitives_st, proxytypes)) | st.builds(Tuple.__class_getitem__, st.lists(proxytypes, max_size=8).map(tuple)) | st.builds(Struct.__class_getitem__, st.dictionaries(strings, proxytypes, max_size=8)) | st.builds( Function.__class_getitem__, st.tuples(st.dictionaries(strings, proxytypes, max_size=8), proxytypes ), ))) @given(proxytypes) @settings(suppress_health_check=[HealthCheck.too_slow]) def test_roundtrip(cls): assert deserialize_typespec(serialize_typespec(cls)) == cls
def test_errors_on_non_function_define(): x = st.deferred(1) with pytest.raises(InvalidArgument): x.example()
def test_errors_if_define_does_not_return_search_strategy(): x = st.deferred(lambda: 1) with pytest.raises(InvalidArgument): x.example()
def test_mutually_recursive_tuples_draw_nothing(): x = st.deferred(lambda: st.tuples(y)) y = st.tuples(x) assert_no_examples(x) assert_no_examples(y)
consts = s.builds(astroid.Const, s.none() | s.integers() | s.text()) def subscripts(values, slice_): return s.builds(Subscript, values, slice_) def lists(vals, max_size=3): return s.builds(List, s.lists(vals, max_size=max_size)) def dicts(keys, vals, max_size=3): return s.builds(Dict, s.lists(s.tuples(keys, vals), max_size=max_size)) NestedLists = s.deferred(lambda: consts | lists(NestedLists)) @given(subscripts(NestedLists, consts)) def test_slice_does_not_raise_nested_lists(subscript): pylint_protobuf._slice(subscript) NestedDicts = s.deferred(lambda: consts | dicts(consts, NestedDicts)) @pytest.mark.skip(reason='appears to get caught in infinite loop') @given(subscripts(NestedDicts, consts)) def test_slice_does_not_raise_nested_dicts(subscript): pylint_protobuf._slice(subscript)
h.assume(not pa.types.is_null(key_type)) value_type = draw(item_strategy) return pa.map_(key_type, value_type) # union type # extension type def schemas(type_strategy=primitive_types, max_fields=None): children = st.lists(fields(type_strategy), max_size=max_fields) return st.builds(pa.schema, children) all_types = st.deferred(lambda: (primitive_types | list_types() | struct_types( ) | dictionary_types() | map_types() | list_types(all_types) | struct_types( all_types))) all_fields = fields(all_types) all_schemas = schemas(all_types) _default_array_sizes = st.integers(min_value=0, max_value=20) @st.composite def _pylist(draw, value_type, size, nullable=True): arr = draw(arrays(value_type, size=size, nullable=False)) return arr.to_pylist() @st.composite def _pymap(draw, key_type, value_type, size, nullable=True):
def test_large_branching_tree(): tree = st.deferred( lambda: st.integers() | st.tuples(tree, tree, tree, tree, tree)) assert minimal(tree) == 0 assert minimal(tree, lambda x: isinstance(x, tuple)) == (0, ) * 5
def test_impossible_self_recursion(): x = st.deferred(lambda: st.tuples(st.none(), x)) assert x.is_empty assert x.has_reusable_values
def test_can_draw_one_of_self(): x = st.deferred(lambda: st.one_of(st.booleans(), x)) assert minimal(x) is False assert len(x.branches) == 1
def strat(i): if i == 0: return st.deferred(lambda: st.one_of(strategies + [st.none()])) else: return st.deferred( lambda: st.tuples(strategies[(i + 1) % len(strategies)]))
child = attr.ib() @attr.s() class Branch(object): bits = attr.ib() children = attr.ib(default=attr.Factory(dict)) @attr.s() class Terminal(object): status = attr.ib() payload = attr.ib(default=None) nodes = st.deferred(lambda: terminals | writes | branches) # Does not include Status.OVERFLOW by design: That happens because of the size # of the string, not the input language. terminals = st.one_of( st.just(Terminal(Status.VALID)), st.just(Terminal(Status.INVALID)), st.builds( Terminal, status=st.just(Status.INTERESTING), payload=st.integers(0, 10) ) ) branches = st.builds(Branch, bits=st.integers(1, 64)) writes = st.builds(
def test_hidden_self_references_just_result_in_no_example(): bad = st.deferred(lambda: st.none().flatmap(lambda _: bad)) assert_no_examples(bad)
ddb_number_set = sets(ddb_number, min_size=1) ddb_binary = binary(min_size=1, max_size=MAX_ITEM_BYTES).map(Binary) ddb_binary_set = sets(ddb_binary, min_size=1) ddb_boolean = booleans() ddb_null = none() ddb_scalar_types = ddb_string | ddb_number | ddb_binary | ddb_boolean | ddb_null ddb_set_types = ddb_string_set | ddb_number_set | ddb_binary_set ddb_attribute_names = text(min_size=1, max_size=255) # List and Map types have a max depth of 32 # https://github.com/aws/aws-dynamodb-encryption-python/issues/141 ddb_map_type = deferred(lambda: dictionaries( keys=ddb_attribute_names, values=(ddb_scalar_types | ddb_set_types | ddb_list_type | ddb_map_type), min_size=1)) ddb_list_type = deferred(lambda: lists(ddb_scalar_types | ddb_set_types | ddb_list_type | ddb_map_type, min_size=1)) ddb_document_types = ddb_map_type | ddb_list_type ddb_attribute_values = ddb_scalar_types | ddb_set_types | ddb_list_type ddb_items = dictionaries(keys=ddb_attribute_names, values=ddb_attribute_values, min_size=1) material_descriptions = deferred( lambda: dictionaries(keys=text(), values=text(), min_size=1))
def test_self_recursive_flatmap(): bad = st.deferred(lambda: bad.flatmap(lambda x: st.none())) assert_no_examples(bad)
def random_invalid_hex_triplet() -> SearchStrategy[str]: return deferred(lambda: text() | text_starting_with_hash() | text_starting_with_hash_with_len_7())
def test_self_reference_through_one_of_can_detect_emptiness(): bad = st.deferred(lambda: st.one_of(bad, bad)) assert bad.is_empty
from _wagyu import (Box, Point, Ring) from hypothesis import strategies from tests.strategies import (coordinates, floats, sizes) from tests.utils import to_maybe booleans = strategies.booleans() floats = floats sizes = sizes points = strategies.builds(Point, coordinates, coordinates) points_lists = strategies.lists(points) boxes = strategies.builds(Box, points, points) maybe_rings = to_maybe(strategies.deferred(lambda: rings)) maybe_rings_lists = strategies.lists(maybe_rings) rings = strategies.builds(Ring, sizes, maybe_rings_lists, points_lists, booleans)
def test_self_tuple_draws_nothing(): x = st.deferred(lambda: st.tuples(x)) assert_no_examples(x)