Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test touchups in preparation for ir migration #3844

Merged
merged 5 commits into from
Jan 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions hypothesis-python/RELEASE.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
RELEASE_TYPE: patch

This patch refactors some internals, continuing our work on supporting alternative backends
(:issue:`3086`). There is no user-visible change.
11 changes: 2 additions & 9 deletions hypothesis-python/src/hypothesis/internal/conjecture/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -1553,6 +1553,8 @@ def draw_string(

def draw_bytes(self, size: int, *, forced: Optional[bytes] = None) -> bytes:
assert forced is None or len(forced) == size
assert size >= 0

return self.provider.draw_bytes(size, forced=forced)

def draw_boolean(self, p: float = 0.5, *, forced: Optional[bool] = None) -> bool:
Expand Down Expand Up @@ -1778,15 +1780,6 @@ def draw_bits(self, n: int, *, forced: Optional[int] = None) -> int:
assert result.bit_length() <= n
return result

def write(self, string: bytes) -> Optional[bytes]:
"""Write ``string`` to the output buffer."""
self.__assert_not_frozen("write")
string = bytes(string)
if not string:
return None
self.draw_bits(len(string) * 8, forced=int_from_bytes(string))
return self.buffer[-len(string) :]

Comment on lines -1781 to -1789
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed in favor of forced on all ir nodes.

def __check_capacity(self, n: int) -> None:
if self.index + n > self.max_length:
self.mark_overrun()
Expand Down
100 changes: 50 additions & 50 deletions hypothesis-python/tests/conjecture/test_data_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,64 +47,64 @@ def accept(tf):
def test_can_lookup_cached_examples():
@runner_for(b"\0\0", b"\0\1")
def runner(data):
data.draw_bits(8)
data.draw_bits(8)
data.draw_integer(0, 2**8 - 1)
data.draw_integer(0, 2**8 - 1)


def test_can_lookup_cached_examples_with_forced():
@runner_for(b"\0\0", b"\0\1")
def runner(data):
data.write(b"\1")
data.draw_bits(8)
data.draw_integer(0, 2**8 - 1, forced=1)
data.draw_integer(0, 2**8 - 1)


def test_can_detect_when_tree_is_exhausted():
@runner_for(b"\0", b"\1")
def runner(data):
data.draw_bits(1)
data.draw_boolean()

assert runner.tree.is_exhausted


def test_can_detect_when_tree_is_exhausted_variable_size():
@runner_for(b"\0", b"\1\0", b"\1\1")
def runner(data):
if data.draw_bits(1):
data.draw_bits(1)
if data.draw_boolean():
data.draw_integer(0, 1)

assert runner.tree.is_exhausted


def test_one_dead_branch():
@runner_for([[0, i] for i in range(16)] + [[i] for i in range(1, 16)])
def runner(data):
i = data.draw_bits(4)
i = data.draw_integer(0, 15)
if i > 0:
data.mark_invalid()
data.draw_bits(4)
data.draw_integer(0, 15)

assert runner.tree.is_exhausted


def test_non_dead_root():
@runner_for(b"\0\0", b"\1\0", b"\1\1")
def runner(data):
data.draw_bits(1)
data.draw_bits(1)
data.draw_boolean()
data.draw_boolean()


def test_can_reexecute_dead_examples():
@runner_for(b"\0\0", b"\0\1", b"\0\0")
def runner(data):
data.draw_bits(1)
data.draw_bits(1)
data.draw_boolean()
data.draw_boolean()


def test_novel_prefixes_are_novel():
def tf(data):
for _ in range(4):
data.write(b"\0")
data.draw_bits(2)
data.draw_bytes(1, forced=b"\0")
data.draw_integer(0, 3)

runner = ConjectureRunner(tf, settings=TEST_SETTINGS, random=Random(0))
for _ in range(100):
Expand All @@ -125,7 +125,7 @@ def test_overruns_if_not_enough_bytes_for_block():

def test_overruns_if_prefix():
runner = ConjectureRunner(
lambda data: [data.draw_bits(1) for _ in range(2)],
lambda data: [data.draw_boolean() for _ in range(2)],
settings=TEST_SETTINGS,
random=Random(0),
)
Expand All @@ -137,7 +137,7 @@ def test_stores_the_tree_flat_until_needed():
@runner_for(bytes(10))
def runner(data):
for _ in range(10):
data.draw_bits(1)
data.draw_boolean()
data.mark_interesting()

root = runner.tree.root
Expand All @@ -149,9 +149,9 @@ def runner(data):
def test_split_in_the_middle():
@runner_for([0, 0, 2], [0, 1, 3])
def runner(data):
data.draw_bits(1)
data.draw_bits(1)
data.draw_bits(4)
data.draw_integer(0, 1)
data.draw_integer(0, 1)
data.draw_integer(0, 15)
data.mark_interesting()

root = runner.tree.root
Expand All @@ -163,9 +163,9 @@ def runner(data):
def test_stores_forced_nodes():
@runner_for(bytes(3))
def runner(data):
data.draw_bits(1, forced=0)
data.draw_bits(1)
data.draw_bits(1, forced=0)
data.draw_integer(0, 1, forced=0)
data.draw_integer(0, 1)
data.draw_integer(0, 1, forced=0)
data.mark_interesting()

root = runner.tree.root
Expand All @@ -175,8 +175,8 @@ def runner(data):
def test_correctly_relocates_forced_nodes():
@runner_for([0, 0], [1, 0])
def runner(data):
data.draw_bits(1)
data.draw_bits(1, forced=0)
data.draw_integer(0, 1)
data.draw_integer(0, 1, forced=0)
data.mark_interesting()

root = runner.tree.root
Expand Down Expand Up @@ -209,7 +209,7 @@ def test_going_from_interesting_to_invalid_is_flaky():
def test_concluding_at_prefix_is_flaky():
tree = DataTree()
data = ConjectureData.for_buffer(b"\1", observer=tree.new_observer())
data.draw_bits(1)
data.draw_integer(0, 1)
with pytest.raises(StopTest):
data.conclude_test(Status.INTERESTING)

Expand All @@ -221,7 +221,7 @@ def test_concluding_at_prefix_is_flaky():
def test_concluding_with_overrun_at_prefix_is_not_flaky():
tree = DataTree()
data = ConjectureData.for_buffer(b"\1", observer=tree.new_observer())
data.draw_bits(1)
data.draw_integer(0, 1)
with pytest.raises(StopTest):
data.conclude_test(Status.INTERESTING)

Expand All @@ -233,67 +233,67 @@ def test_concluding_with_overrun_at_prefix_is_not_flaky():
def test_changing_n_bits_is_flaky_in_prefix():
tree = DataTree()
data = ConjectureData.for_buffer(b"\1", observer=tree.new_observer())
data.draw_bits(1)
data.draw_integer(0, 1)
with pytest.raises(StopTest):
data.conclude_test(Status.INTERESTING)

data = ConjectureData.for_buffer(b"\1", observer=tree.new_observer())
with pytest.raises(Flaky):
data.draw_bits(2)
data.draw_integer(0, 3)


def test_changing_n_bits_is_flaky_in_branch():
tree = DataTree()

for i in [0, 1]:
data = ConjectureData.for_buffer([i], observer=tree.new_observer())
data.draw_bits(1)
data.draw_integer(0, 1)
with pytest.raises(StopTest):
data.conclude_test(Status.INTERESTING)

data = ConjectureData.for_buffer(b"\1", observer=tree.new_observer())
with pytest.raises(Flaky):
data.draw_bits(2)
data.draw_integer(0, 3)


def test_extending_past_conclusion_is_flaky():
tree = DataTree()
data = ConjectureData.for_buffer(b"\1", observer=tree.new_observer())
data.draw_bits(1)
data.draw_integer(0, 1)
with pytest.raises(StopTest):
data.conclude_test(Status.INTERESTING)

data = ConjectureData.for_buffer(b"\1\0", observer=tree.new_observer())
data.draw_bits(1)
data.draw_integer(0, 1)

with pytest.raises(Flaky):
data.draw_bits(1)
data.draw_integer(0, 1)


def test_changing_to_forced_is_flaky():
tree = DataTree()
data = ConjectureData.for_buffer(b"\1", observer=tree.new_observer())
data.draw_bits(1)
data.draw_integer(0, 1)
with pytest.raises(StopTest):
data.conclude_test(Status.INTERESTING)

data = ConjectureData.for_buffer(b"\1\0", observer=tree.new_observer())

with pytest.raises(Flaky):
data.draw_bits(1, forced=0)
data.draw_integer(0, 1, forced=0)


def test_changing_value_of_forced_is_flaky():
tree = DataTree()
data = ConjectureData.for_buffer(b"\1", observer=tree.new_observer())
data.draw_bits(1, forced=1)
data.draw_integer(0, 1, forced=1)
with pytest.raises(StopTest):
data.conclude_test(Status.INTERESTING)

data = ConjectureData.for_buffer(b"\1\0", observer=tree.new_observer())

with pytest.raises(Flaky):
data.draw_bits(1, forced=0)
data.draw_integer(0, 1, forced=0)


def test_does_not_truncate_if_unseen():
Expand All @@ -308,8 +308,8 @@ def test_truncates_if_seen():
b = bytes([1, 2, 3, 4])

data = ConjectureData.for_buffer(b, observer=tree.new_observer())
data.draw_bits(8)
data.draw_bits(8)
data.draw_bytes(1)
data.draw_bytes(1)
data.freeze()

assert tree.rewrite(b) == (b[:2], Status.VALID)
Expand All @@ -318,13 +318,13 @@ def test_truncates_if_seen():
def test_child_becomes_exhausted_after_split():
tree = DataTree()
data = ConjectureData.for_buffer([0, 0], observer=tree.new_observer())
data.draw_bits(8)
data.draw_bits(8, forced=0)
data.draw_bytes(1)
data.draw_bytes(1, forced=b"\0")
data.freeze()

data = ConjectureData.for_buffer([1, 0], observer=tree.new_observer())
data.draw_bits(8)
data.draw_bits(8)
data.draw_bytes(1)
data.draw_bytes(1)
data.freeze()

assert not tree.is_exhausted
Expand All @@ -334,12 +334,12 @@ def test_child_becomes_exhausted_after_split():
def test_will_generate_novel_prefix_to_avoid_exhausted_branches():
tree = DataTree()
data = ConjectureData.for_buffer([1], observer=tree.new_observer())
data.draw_bits(1)
data.draw_integer(0, 1)
data.freeze()

data = ConjectureData.for_buffer([0, 1], observer=tree.new_observer())
data.draw_bits(1)
data.draw_bits(8)
data.draw_integer(0, 1)
data.draw_bytes(1)
data.freeze()

prefix = list(tree.generate_novel_prefix(Random(0)))
Expand All @@ -352,14 +352,14 @@ def test_will_mark_changes_in_discard_as_flaky():
tree = DataTree()
data = ConjectureData.for_buffer([1, 1], observer=tree.new_observer())
data.start_example(10)
data.draw_bits(1)
data.draw_integer(0, 1)
data.stop_example()
data.draw_bits(1)
data.draw_integer(0, 1)
data.freeze()

data = ConjectureData.for_buffer([1, 1], observer=tree.new_observer())
data.start_example(10)
data.draw_bits(1)
data.draw_integer(0, 1)

with pytest.raises(Flaky):
data.stop_example(discard=True)
10 changes: 5 additions & 5 deletions hypothesis-python/tests/conjecture/test_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ def test_returns_written():

@run_to_buffer
def written(data):
data.write(value)
data.draw_bytes(len(value), forced=value)
data.mark_interesting()

assert value == written
Expand Down Expand Up @@ -500,8 +500,8 @@ def test_can_write_bytes_towards_the_end():
def f(data):
if data.draw_boolean():
data.draw_bytes(5)
data.write(bytes(buf))
assert bytes(data.buffer[-len(buf) :]) == buf
data.draw_bytes(len(buf), forced=buf)
assert data.buffer[-len(buf) :] == buf

with buffer_size_limit(10):
ConjectureRunner(f).run()
Expand All @@ -511,7 +511,7 @@ def test_uniqueness_is_preserved_when_writing_at_beginning():
seen = set()

def f(data):
data.write(bytes(1))
data.draw_bytes(1, forced=bytes(1))
n = data.draw_integer(0, 2**3 - 1)
assert n not in seen
seen.add(n)
Expand Down Expand Up @@ -930,7 +930,7 @@ def test_cached_test_function_does_not_reinvoke_on_prefix():
def test_function(data):
call_count[0] += 1
data.draw_integer(0, 2**8 - 1)
data.write(bytes([7]))
data.draw_bytes(1, forced=bytes([7]))
data.draw_integer(0, 2**8 - 1)

with deterministic_PRNG():
Expand Down
Loading
Loading