Skip to content

Commit b49d4dc

Browse files
committed
consolidate test_forced_* methods
1 parent 927ad08 commit b49d4dc

File tree

2 files changed

+42
-105
lines changed

2 files changed

+42
-105
lines changed

hypothesis-python/tests/conjecture/common.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ def boolean_kwargs(draw, *, use_forced=False):
343343
return {"p": p, "forced": forced}
344344

345345

346-
def kwargs_strategy(ir_type, strategy_kwargs=None):
346+
def kwargs_strategy(ir_type, strategy_kwargs=None, *, use_forced=False):
347347
strategy = {
348348
"boolean": boolean_kwargs,
349349
"integer": integer_kwargs,
@@ -353,13 +353,15 @@ def kwargs_strategy(ir_type, strategy_kwargs=None):
353353
}[ir_type]
354354
if strategy_kwargs is None:
355355
strategy_kwargs = {}
356-
return strategy(**strategy_kwargs.get(ir_type, {}))
356+
return strategy(**strategy_kwargs.get(ir_type, {}), use_forced=use_forced)
357357

358358

359-
def ir_types_and_kwargs(strategy_kwargs=None):
359+
def ir_types_and_kwargs(strategy_kwargs=None, *, use_forced=False):
360360
options = ["boolean", "integer", "float", "bytes", "string"]
361361
return st.one_of(
362-
st.tuples(st.just(name), kwargs_strategy(name, strategy_kwargs))
362+
st.tuples(
363+
st.just(name), kwargs_strategy(name, strategy_kwargs, use_forced=use_forced)
364+
)
363365
for name in options
364366
)
365367

hypothesis-python/tests/conjecture/test_forced.py

Lines changed: 36 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,10 @@
1515
import hypothesis.strategies as st
1616
from hypothesis import HealthCheck, assume, example, given, settings
1717
from hypothesis.internal.conjecture import utils as cu
18-
from hypothesis.internal.conjecture.data import ConjectureData
19-
from hypothesis.internal.conjecture.floats import float_to_lex
18+
from hypothesis.internal.conjecture.data import ConjectureData, ir_value_equal
2019
from hypothesis.internal.floats import SIGNALING_NAN, SMALLEST_SUBNORMAL
2120

22-
from tests.conjecture.common import (
23-
boolean_kwargs,
24-
bytes_kwargs,
25-
float_kwargs,
26-
fresh_data,
27-
integer_kwargs,
28-
string_kwargs,
29-
)
21+
from tests.conjecture.common import fresh_data, ir_types_and_kwargs
3022

3123

3224
@given(st.data())
@@ -67,105 +59,48 @@ def test_forced_many(data):
6759
assert not many.more()
6860

6961

70-
@example({"p": 1e-19, "forced": True}) # 64 bit p
71-
@example({"p": 3e-19, "forced": True}) # 62 bit p
72-
@given(boolean_kwargs(use_forced=True))
73-
def test_forced_boolean(kwargs):
74-
forced = kwargs["forced"]
75-
76-
data = fresh_data()
77-
assert data.draw_boolean(**kwargs) == forced
78-
79-
# now make sure the written buffer reproduces the forced value, even without
80-
# specifying forced=.
81-
del kwargs["forced"]
82-
data = ConjectureData.for_buffer(data.buffer)
83-
assert data.draw_boolean(**kwargs) == forced
84-
85-
86-
@settings(derandomize=True)
87-
@given(integer_kwargs(use_forced=True))
88-
def test_forced_integer(kwargs):
89-
forced = kwargs["forced"]
90-
91-
data = fresh_data()
92-
assert data.draw_integer(**kwargs) == forced
93-
94-
del kwargs["forced"]
95-
data = ConjectureData.for_buffer(data.buffer)
96-
assert data.draw_integer(**kwargs) == forced
97-
98-
99-
@pytest.mark.parametrize("use_min_size", [True, False])
100-
@pytest.mark.parametrize("use_max_size", [True, False])
101-
def test_forced_string(use_min_size, use_max_size):
102-
@given(
103-
string_kwargs(
104-
use_min_size=use_min_size, use_max_size=use_max_size, use_forced=True
105-
)
62+
@example(("boolean", {"p": 1e-19, "forced": True})) # 64 bit p
63+
@example(("boolean", {"p": 3e-19, "forced": True})) # 62 bit p
64+
@example(("float", {"forced": 0.0}))
65+
@example(("float", {"forced": -0.0}))
66+
@example(("float", {"forced": 1.0}))
67+
@example(("float", {"forced": 1.2345}))
68+
@example(("float", {"forced": SMALLEST_SUBNORMAL}))
69+
@example(("float", {"forced": -SMALLEST_SUBNORMAL}))
70+
@example(("float", {"forced": 100 * SMALLEST_SUBNORMAL}))
71+
@example(("float", {"forced": math.nan}))
72+
@example(("float", {"forced": -math.nan}))
73+
@example(("float", {"forced": SIGNALING_NAN}))
74+
@example(("float", {"forced": -SIGNALING_NAN}))
75+
@example(("float", {"forced": 1e999}))
76+
@example(("float", {"forced": -1e999}))
77+
# previously errored on our {pos, neg}_clamper logic not considering nans.
78+
@example(
79+
(
80+
"float",
81+
{"min_value": -1 * math.inf, "max_value": -1 * math.inf, "forced": math.nan},
10682
)
107-
def test(kwargs):
108-
forced = kwargs["forced"]
109-
110-
data = fresh_data()
111-
assert data.draw_string(**kwargs) == forced
112-
113-
del kwargs["forced"]
114-
data = ConjectureData.for_buffer(data.buffer)
115-
assert data.draw_string(**kwargs) == forced
116-
117-
test()
118-
119-
120-
@given(st.data())
121-
def test_forced_bytes(data):
122-
kwargs = data.draw(bytes_kwargs(use_forced=True))
123-
forced = kwargs["forced"]
83+
)
84+
@given(ir_types_and_kwargs(use_forced=True))
85+
def test_forced_values(ir_type_and_kwargs):
86+
(ir_type, kwargs) = ir_type_and_kwargs
12487

125-
data = fresh_data()
126-
assert data.draw_bytes(**kwargs) == forced
127-
128-
del kwargs["forced"]
129-
data = ConjectureData.for_buffer(data.buffer)
130-
assert data.draw_bytes(**kwargs) == forced
131-
132-
133-
@example({"forced": 0.0})
134-
@example({"forced": -0.0})
135-
@example({"forced": 1.0})
136-
@example({"forced": 1.2345})
137-
@example({"forced": SMALLEST_SUBNORMAL})
138-
@example({"forced": -SMALLEST_SUBNORMAL})
139-
@example({"forced": 100 * SMALLEST_SUBNORMAL})
140-
@example({"forced": math.nan})
141-
@example({"forced": -math.nan})
142-
@example({"forced": SIGNALING_NAN})
143-
@example({"forced": -SIGNALING_NAN})
144-
@example({"forced": 1e999})
145-
@example({"forced": -1e999})
146-
# previously errored on our {pos, neg}_clamper logic not considering nans.
147-
@example({"min_value": -1 * math.inf, "max_value": -1 * math.inf, "forced": math.nan})
148-
@given(float_kwargs(use_forced=True))
149-
def test_forced_floats(kwargs):
150-
# TODO intentionally avoid triggering a bug with forcing nan values
151-
# while both min and max value have the opposite sign.
152-
# Once we fix the aforementioned bug we can remove this intentional
153-
# weakening of the test.
154-
assume(not math.isnan(kwargs["forced"]))
88+
if ir_type == "float":
89+
# TODO intentionally avoid triggering a bug with forcing nan values
90+
# while both min and max value have the opposite sign.
91+
# Once we fix the aforementioned bug we can remove this intentional
92+
# weakening of the test.
93+
assume(not math.isnan(kwargs["forced"]))
15594

15695
forced = kwargs["forced"]
157-
15896
data = fresh_data()
159-
drawn = data.draw_float(**kwargs)
160-
# Bitwise equality check to handle nan, snan, -nan, +0, -0, etc.
161-
assert math.copysign(1, drawn) == math.copysign(1, forced)
162-
assert float_to_lex(abs(drawn)) == float_to_lex(abs(forced))
97+
assert ir_value_equal(ir_type, getattr(data, f"draw_{ir_type}")(**kwargs), forced)
16398

99+
# now make sure the written buffer reproduces the forced value, even without
100+
# specifying forced=.
164101
del kwargs["forced"]
165102
data = ConjectureData.for_buffer(data.buffer)
166-
drawn = data.draw_float(**kwargs)
167-
assert math.copysign(1, drawn) == math.copysign(1, forced)
168-
assert float_to_lex(abs(drawn)) == float_to_lex(abs(forced))
103+
assert ir_value_equal(ir_type, getattr(data, f"draw_{ir_type}")(**kwargs), forced)
169104

170105

171106
@pytest.mark.parametrize("sign", [1, -1])

0 commit comments

Comments
 (0)