def test_shrinker_skips_stale_examples(monkeypatch, pass_name):
    # Pretend that all example identifiers are stale, to test that this case
    # is handled cleanly.
    monkeypatch.setattr(
        Shrinker, "example_for_stable_identifier", counts_calls(lambda self, x: None)
    )

    # For "example_deletion_with_block_lowering", also pretend that all blocks
    # are shrinking blocks, so that steps can be generated.
    monkeypatch.setattr(
        Shrinker, "is_shrinking_block", counts_calls(lambda self, i: True)
    )

    # Declare a test function that should satisfy step generation for all of
    # the relevant shrink passes.
    @shrinking_from([255] * 5)
    def shrinker(data):
        total = 0
        data.start_example(0)
        for _ in range(5):
            data.start_example(0)
            total += data.draw_bits(8)
            data.stop_example(0)
        data.stop_example(0)

        data.mark_interesting()

    # Run the shrink pass; this should not throw.
    shrinker.fixate_shrink_passes([pass_name])

    # Confirm that the pass had to deal with stale examples.
    assert Shrinker.example_for_stable_identifier.calls > 0
Exemple #2
0
def test_block_programs_fail_efficiently(monkeypatch):
    # Create 256 byte-sized blocks. None of the blocks can be deleted, and
    # every deletion attempt produces a different buffer.
    @shrinking_from(bytes(range(256)))
    def shrinker(data):
        values = set()
        for _ in range(256):
            v = data.draw_bits(8)
            values.add(v)
        if len(values) == 256:
            data.mark_interesting()

    monkeypatch.setattr(
        Shrinker, "run_block_program", counts_calls(Shrinker.run_block_program)
    )

    shrinker.max_stall = 500

    shrinker.fixate_shrink_passes([block_program("XX")])

    assert shrinker.shrinks == 0
    assert 250 <= shrinker.calls <= 260

    # The block program should have been run roughly 255 times, with a little
    # bit of wiggle room for implementation details.
    #   - Too many calls mean that failing steps are doing too much work.
    #   - Too few calls mean that this test is probably miscounting and buggy.
    assert 250 <= Shrinker.run_block_program.calls <= 260
def test_block_programs_fail_efficiently(monkeypatch):
    # Create 256 byte-sized blocks. None of the blocks can be deleted, and
    # every deletion attempt produces a different buffer.
    @shrinking_from(hbytes(hrange(256)))
    def shrinker(data):
        values = set()
        for _ in hrange(256):
            v = data.draw_bits(8)
            values.add(v)
        if len(values) == 256:
            data.mark_interesting()

    monkeypatch.setattr(
        Shrinker, "run_block_program", counts_calls(Shrinker.run_block_program)
    )

    shrinker.fixate_shrink_passes([block_program("XX")])

    assert shrinker.shrinks == 0
    assert 250 <= shrinker.calls <= 260

    # The block program should have been run roughly 255 times, with a little
    # bit of wiggle room for implementation details.
    #   - Too many calls mean that failing steps are doing too much work.
    #   - Too few calls mean that this test is probably miscounting and buggy.
    assert 250 <= Shrinker.run_block_program.calls <= 260