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

Remove the ability to run a single shrink pass #2033

Merged
merged 4 commits into from Jul 3, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

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

This release removes some defunct internal functionality that was only being used
for testing. It should have no user visible impact.
Expand Up @@ -106,7 +106,7 @@ def accept(run_step):
)

def run(self):
return self.run_shrink_pass(definition.name)
assert False, "Shrink passes should not be run directly"
Copy link
Contributor

Choose a reason for hiding this comment

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

This is what's causing the coverage failure, so presumably it just needs to be suppressed.

Copy link
Member Author

Choose a reason for hiding this comment

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

Huh. I thought the assert False was automatically a coverage exclusion. Oh well, easy enough to add the pragma.


run.__name__ = run_step.__name__
run.is_shrink_pass = True
Expand Down Expand Up @@ -395,27 +395,6 @@ def debug(self, msg):
def random(self):
return self.__engine.random

def run_shrink_pass(self, sp):
"""Runs the function associated with ShrinkPass sp and updates the
relevant metadata.

Note that sp may or may not be a pass currently associated with
this shrinker. This does not handle any requeing that is
required.
"""
sp = self.shrink_pass(sp)

self.debug("Shrink Pass %s" % (sp.name,))
try:
sp.runs += 1

steps = sp.generate_steps()
self.random.shuffle(steps)
for s in steps:
sp.run_step(s)
finally:
self.debug("Shrink Pass %s completed." % (sp.name,))

def shrink(self):
"""Run the full set of shrinks and update shrink_target.

Expand Down
98 changes: 29 additions & 69 deletions hypothesis-python/tests/cover/test_conjecture_engine.py
Expand Up @@ -479,14 +479,18 @@ def shrinker(data):
# We normally would have populated this in minimize_individual_blocks
shrinker.is_shrinking_block = lambda x: True

fixate(Shrinker.example_deletion_with_block_lowering)(shrinker)
shrinker.fixate_shrink_passes(["example_deletion_with_block_lowering"])

assert list(shrinker.shrink_target.buffer) == [1, 1]


def test_deletion_and_lowering_fails_to_shrink(monkeypatch):
monkeypatch.setattr(
Shrinker, "shrink", Shrinker.example_deletion_with_block_lowering
Shrinker,
"shrink",
lambda self: self.fixate_shrink_passes(
["example_deletion_with_block_lowering"]
),
)
# Would normally be added by minimize_individual_blocks, but we skip
# that phase in this test.
Expand Down Expand Up @@ -761,16 +765,6 @@ def x(data):
assert x == hbytes(hbytes([1]) * 10)


def fixate(f):
def accept(self):
prev = None
while self.shrink_target is not prev:
prev = self.shrink_target
f(self)

return accept


def test_can_remove_discarded_data():
@shrinking_from(hbytes([0] * 10) + hbytes([11]))
def shrinker(data):
Expand Down Expand Up @@ -813,13 +807,6 @@ def shrinker(data):
assert shrinker.shrink_target.has_discards


def shrink_pass(name):
def run(self):
self.run_shrink_pass(name)

return run


def test_discarding_can_fail(monkeypatch):
@shrinking_from(hbytes([1]))
def shrinker(data):
Expand Down Expand Up @@ -936,11 +923,8 @@ def shrink(buffer, *passes):
def accept(f):
shrinker = shrinking_from(buffer)(f)

prev = None
while shrinker.shrink_target is not prev:
prev = shrinker.shrink_target
for p in passes:
shrinker.run_shrink_pass(p)
shrinker.fixate_shrink_passes(passes)

return list(shrinker.buffer)

return accept
Expand All @@ -954,10 +938,8 @@ def shrinker(data):
if abs(m - n) <= 1 and max(m, n) > 0:
data.mark_interesting()

# Run minimize_individual_blocks twice so we have both blocks show
# as changed regardless of which order this happens in.
shrinker.minimize_individual_blocks()
shrinker.minimize_individual_blocks()
shrinker.mark_changed(0)
shrinker.mark_changed(1)
shrinker.lower_common_block_offset()

x = shrinker.shrink_target.buffer
Expand All @@ -966,7 +948,11 @@ def shrinker(data):


def test_handle_empty_draws(monkeypatch):
monkeypatch.setattr(Shrinker, "shrink", Shrinker.adaptive_example_deletion)
monkeypatch.setattr(
Shrinker,
"shrink",
lambda self: self.fixate_shrink_passes(["adaptive_example_deletion"]),
)

@run_to_buffer
def x(data):
Expand Down Expand Up @@ -1005,17 +991,9 @@ def f(data):
assert runner.exit_reason == ExitReason.finished


def test_can_reorder_examples(monkeypatch):
monkeypatch.setattr(
ConjectureRunner,
"generate_new_examples",
lambda runner: runner.cached_test_function([1, 0, 1, 1, 0, 1, 0, 0, 0]),
)

monkeypatch.setattr(Shrinker, "shrink", Shrinker.reorder_examples)

@run_to_buffer
def x(data):
def test_can_reorder_examples():
@shrinking_from([1, 0, 1, 1, 0, 1, 0, 0, 0])
def shrinker(data):
total = 0
for _ in range(5):
data.start_example(0)
Expand All @@ -1025,7 +1003,9 @@ def x(data):
if total == 2:
data.mark_interesting()

assert list(x) == [0, 0, 0, 1, 0, 1, 1, 0, 1]
shrinker.fixate_shrink_passes(["reorder_examples"])

assert list(shrinker.buffer) == [0, 0, 0, 1, 0, 1, 1, 0, 1]


def test_permits_but_ignores_raising_order(monkeypatch):
Expand Down Expand Up @@ -1058,8 +1038,7 @@ def shrinker(data):
if n == 4:
data.mark_interesting()

for i in range(1, 5):
shrinker.run_shrink_pass(block_program("X" * i))
shrinker.fixate_shrink_passes([block_program("X" * i) for i in range(1, 5)])
assert list(shrinker.shrink_target.buffer) == [0, 4] * 5


Expand Down Expand Up @@ -1128,7 +1107,7 @@ def shrinker(data):
if result >= 32768 and cap == 1:
data.mark_interesting()

shrinker.minimize_individual_blocks()
shrinker.fixate_shrink_passes(["minimize_individual_blocks"])
assert list(shrinker.shrink_target.buffer) == [1, 1, 0, 1, 0, 0, 1]


Expand Down Expand Up @@ -1272,7 +1251,7 @@ def shrinker(data):
if n == 1:
data.mark_interesting()

shrinker.minimize_individual_blocks()
shrinker.fixate_shrink_passes(["minimize_individual_blocks"])
assert list(shrinker.shrink_target.buffer) == [0, 1]


Expand All @@ -1285,7 +1264,7 @@ def shrinker(data):
else:
data.draw_bits(8)

shrinker.minimize_individual_blocks()
shrinker.fixate_shrink_passes(["minimize_individual_blocks"])


def test_zero_examples_will_zero_blocks():
Expand All @@ -1297,7 +1276,7 @@ def shrinker(data):
if n == m == 1:
data.mark_interesting()

shrinker.run_shrink_pass("zero_examples")
shrinker.fixate_shrink_passes(["zero_examples"])
assert list(shrinker.shrink_target.buffer) == [1, 0, 1]


Expand All @@ -1314,7 +1293,7 @@ def shrinker(data):
data.draw_bits(16)
data.mark_interesting()

shrinker.minimize_individual_blocks()
shrinker.fixate_shrink_passes(["minimize_individual_blocks"])
assert list(shrinker.shrink_target.buffer) == [0, 0, 0]


Expand Down Expand Up @@ -1360,7 +1339,7 @@ def shrinker(data):
if data.draw_bits(8) == 7:
data.mark_interesting()

shrinker.run_shrink_pass(block_program("-XX"))
shrinker.fixate_shrink_passes([block_program("-XX")])
assert list(shrinker.shrink_target.buffer) == [1, 7]


Expand Down Expand Up @@ -1477,7 +1456,7 @@ def shrinker(data):
if hbytes(data.buffer) == base_buf:
data.mark_interesting()

shrinker.minimize_floats()
shrinker.fixate_shrink_passes(["minimize_floats"])

assert shrinker.shrink_target.buffer == base_buf

Expand Down Expand Up @@ -1539,25 +1518,6 @@ def shrinker(data):
assert shrinker.calls <= 60


def test_zero_examples_does_not_try_to_adapt_across_different_sizes():
Copy link
Member Author

Choose a reason for hiding this comment

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

I removed this test because I couldn't figure out a sensible way to adapt it and it seemed fragile and hyper-specific.

@shrinking_from([1, 0, 0] * 10 + [1])
def shrinker(data):
for _ in hrange(10):
data.draw_bits(1)
data.draw_bits(16)
if data.draw_bits(1):
data.mark_interesting()

initial = shrinker.calls
shrinker.zero_examples()
assert shrinker.shrink_target.buffer == hbytes(30) + hbytes([1])

# Tried each of the 1-bit blocks, plus the whole example, plus the final
# single-bit block. Did not try to expand regions into the trivial two-byte
# blocks on each side.
assert shrinker.calls == initial + 12


def test_stable_identifiers_match_their_examples():
def tree(data):
data.start_example(1)
Expand Down