Skip to content
This repository was archived by the owner on Oct 9, 2019. It is now read-only.
This repository was archived by the owner on Oct 9, 2019. It is now read-only.

Should it be okay for invalid fuzzers to fail mid-test? #243

Open
@rtfeldman

Description

@rtfeldman

It seems like the two problems with Fuzz.andThen mentioned in #161 boil down to:

  1. Shrinking performance is often bad. However, as Document limitations of nested fuzzers #237 notes, Fuzz.andThen is only one of several ways to end up with slow tests when using fuzzers. If we need a general solution to that problem anyway, then removing Fuzz.andThen from the API doesn't solve it.
  2. "Invalid fuzzers" can go unnoticed at runtime if they are hidden behind a Fuzz.andThen. They may only sometimes show up as invalid. See Can create a crash by returning an invalid fuzzer from andThen #160

It seems that we have only two functions that can potentially return invalid fuzzers:

  1. Fuzz.oneOf. This doesn't need to use the concept of invalid fuzzers. It can be oneOf : Fuzzer a -> List (Fuzzer a) -> Fuzzer a so that it always has at least one value to work with.
  2. Fuzz.frequency. Even it did the same "one or more" trick as Fuzz.oneOf, it would still have two invalid cases: if any of its weights aren't positive numbers, or if all the weights do not add up to a positive number.

One potential solution would be if we didn't have Fuzz.frequency and instead only had Fuzz.oneOf with the "requires at least one element at compile time" API.

The example in the frequency docs is:

Fuzz.frequency
    [ ( 1, Fuzz.constant Leaf )
    , ( 2, Fuzz.map2 Branch (tree (i - 1)) (tree (i - 1)) )
    ]

This could also be written:

Fuzz.oneOf
    (Fuzz.constant Leaf)
    (List.repeat 2 (Fuzz.map2 Branch (tree (i - 1)) (tree (i - 1)) ))

In my opinion, this is not actually better. It's worse for performance, and List.repeat has the same problem as List.frequency: what happens when you pass it negative numbers? We're just shifting the burden elsewhere.

Realizing this made me rethink whether it's such a problem after all that you can get invalid fuzzers midway through a test run. The whole point of fuzzers is to expose edge cases; by using them at all, we accept that some of our tests will fail on some runs and not others - in fact, we're often hoping for that to happen!

Assuming we fixed the error message in #160 to be nice, how bad would it actually be if sometimes fuzzers turned out to be invalid midway through a run, leading to a failed test? It doesn't seem likely to lead to a whole lot of frustration in practice.

Note: If we did this, and kept andThen, I'd want to change both oneOf and frequency to accept the extra argument, so if you're using them in an andThen it's super clear that you need to provide at least one element in the list. We don't need to bikeshed about that now though!

Thoughts?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions