File: test_sampled_from.py

package info (click to toggle)
python-hypothesis 6.138.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 15,272 kB
  • sloc: python: 62,853; ruby: 1,107; sh: 253; makefile: 41; javascript: 6
file content (152 lines) | stat: -rw-r--r-- 4,146 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# This file is part of Hypothesis, which may be found at
# https://github.com/HypothesisWorks/hypothesis/
#
# Copyright the Hypothesis Authors.
# Individual contributors are listed in AUTHORS.rst and the git log.
#
# This Source Code Form is subject to the terms of the Mozilla Public License,
# v. 2.0. If a copy of the MPL was not distributed with this file, You can
# obtain one at https://mozilla.org/MPL/2.0/.

import enum
import functools
import itertools
import operator

import pytest

from hypothesis import given, settings, strategies as st
from hypothesis.errors import InvalidArgument
from hypothesis.internal.compat import bit_count
from hypothesis.strategies._internal.strategies import SampledFromStrategy

from tests.common.debug import find_any, minimal
from tests.common.utils import fails_with


@pytest.mark.parametrize("size", [100, 10**5, 10**6, 2**25])
@given(data=st.data())
def test_filter_large_lists(data, size):
    n_calls = 0

    def cond(x):
        nonlocal n_calls
        n_calls += 1
        return x % 2 != 0

    s = data.draw(st.sampled_from(range(size)).filter(cond))

    assert s % 2 != 0
    assert n_calls <= SampledFromStrategy._MAX_FILTER_CALLS


def rare_value_strategy(n, target):
    def forbid(s, forbidden):
        """Helper function to avoid Python variable scoping issues."""
        return s.filter(lambda x: x != forbidden)

    s = st.sampled_from(range(n))
    for i in range(n):
        if i != target:
            s = forbid(s, i)

    return s


@given(rare_value_strategy(n=128, target=80))
def test_chained_filters_find_rare_value(x):
    assert x == 80


@fails_with(InvalidArgument)
@given(st.sets(st.sampled_from(range(10)), min_size=11))
def test_unsat_sets_of_samples(x):
    raise AssertionError


@given(st.sets(st.sampled_from(range(50)), min_size=50))
def test_efficient_sets_of_samples(x):
    assert x == set(range(50))


class AnEnum(enum.Enum):
    a = enum.auto()
    b = enum.auto()


def test_enum_repr_uses_class_not_a_list():
    # The repr should have enough detail to find the class again
    # (which is very useful for the ghostwriter logic we're working on)
    lazy_repr = repr(st.sampled_from(AnEnum))
    assert lazy_repr == "sampled_from(tests.nocover.test_sampled_from.AnEnum)"


def test_repr_truncates_with_many_elements():
    s = st.sampled_from(list(range(10_000)))
    repr_limit = 512
    assert repr(s) == f"sampled_from([{', '.join(map(str, range(repr_limit)))}, ...])"


class AFlag(enum.Flag):
    a = enum.auto()
    b = enum.auto()
    c = enum.auto()


LargeFlag = enum.Flag("LargeFlag", {f"bit{i}": enum.auto() for i in range(64)})


class UnnamedFlag(enum.Flag):
    # Would fail under EnumCheck.NAMED_FLAGS
    a = 0
    b = 7


def test_flag_enum_repr_uses_class_not_a_list():
    lazy_repr = repr(st.sampled_from(AFlag))
    assert lazy_repr == "sampled_from(tests.nocover.test_sampled_from.AFlag)"


def test_exhaustive_flags():
    # Generate powerset of flag combinations. There are only 2^3 of them, so
    # we can reasonably expect that they are all are found.
    unseen_flags = {
        functools.reduce(operator.or_, flaglist, AFlag(0))
        for r in range(len(AFlag) + 1)
        for flaglist in itertools.combinations(AFlag, r)
    }

    @given(st.sampled_from(AFlag))
    def accept(flag):
        unseen_flags.discard(flag)

    accept()

    assert not unseen_flags


def test_flags_minimize_to_first_named_flag():
    assert minimal(st.sampled_from(LargeFlag)) == LargeFlag.bit0


def test_flags_minimizes_bit_count():
    assert (
        minimal(st.sampled_from(LargeFlag), lambda f: bit_count(f.value) > 1)
        == LargeFlag.bit0 | LargeFlag.bit1
    )


@pytest.mark.skipif(
    settings._current_profile == "crosshair",
    reason="takes ~10 mins; path tree is too large",
)
def test_flags_finds_all_bits_set():
    assert find_any(st.sampled_from(LargeFlag), lambda f: f == ~LargeFlag(0))


def test_sample_unnamed_alias():
    assert find_any(st.sampled_from(UnnamedFlag), lambda f: f == UnnamedFlag.b)


def test_shrink_to_named_empty():
    assert minimal(st.sampled_from(UnnamedFlag)) == UnnamedFlag(0)