derive-quickcheck

Crates.ioderive-quickcheck
lib.rsderive-quickcheck
version0.2.0
sourcesrc
created_at2023-05-20 11:25:52.72865
updated_at2023-07-02 10:49:02.465131
descriptionAutomatic `derive` for `quickcheck::Arbitrary`.
homepage
repositoryhttps://github.com/wrsturgeon/derive-quickcheck
max_upload_size
id869352
size88,984
Will Sturgeon (wrsturgeon)

documentation

README

#[derive(QuickCheck)]

Automatically implements quickcheck::Arbitrary for any data structure.

Rules:

  • For structs (or, generally, when you have all of a collection of types), we simply call quickcheck::Arbitrary::arbitrary on each.
  • For enums (or, generally, when you have one of a collection of types), we weight all variants equally.
  • All type parameters (<A, ...>) must implement quickcheck::Arbitrary. If not, the struct will still work outside quickcheck, but you can't property-test it.
    • Caveat: We might in the future check if you actually use that type parameter, but for now, we don't (e.g. PhantomData<A> still requires <A: Arbitrary>).

Structs

//                     vvvvvvvvvv
#[derive(Clone, Debug, QuickCheck)]
struct StructWithABunchOfEdgeCases<A, B, T, const N: usize> {
    a: A,
    b: B,
    t1: T,
    t2: T,
    t3: T,
}

automatically writes the following:

impl<
    A: ::quickcheck::Arbitrary,
    B: ::quickcheck::Arbitrary,
    T: ::quickcheck::Arbitrary,
    const N: usize, // recognizes this is not a type
> ::quickcheck::Arbitrary for StructWithABunchOfEdgeCases<A, B, T, { N }> {
    #[inline]
    fn arbitrary(g: &mut ::quickcheck::Gen) -> Self {
        a: <A as ::quickcheck::Arbitrary>::arbitrary(g),
        b: <B as ::quickcheck::Arbitrary>::arbitrary(g),
        t1: <T as ::quickcheck::Arbitrary>::arbitrary(g),
        t2: <T as ::quickcheck::Arbitrary>::arbitrary(g),
        t3: <T as ::quickcheck::Arbitrary>::arbitrary(g),
    }
}

Enums

#[derive(Clone, Debug, QuickCheck)]
enum Enum<A, B, C> {
    First(A, B, C),
    Second(A, B, C),
    Third(A, B, C),
}

becomes

impl<
    A: ::quickcheck::Arbitrary,
    B: ::quickcheck::Arbitrary,
    C: ::quickcheck::Arbitrary,
> ::quickcheck::Arbitrary for Enum<A, B, C> {
    #[inline]
    fn arbitrary(g: &mut ::quickcheck::Gen) -> Self {
            g.choose::<fn(&mut ::quickcheck::Gen) -> Self>(&[
                (move |g| Self::First(
                    <A as ::quickcheck::Arbitrary>::arbitrary(g),
                    <B as ::quickcheck::Arbitrary>::arbitrary(g),
                    <C as ::quickcheck::Arbitrary>::arbitrary(g),
                )) as fn(&mut ::quickcheck::Gen) -> Self,
                (move |g| Self::Second(
                    <A as ::quickcheck::Arbitrary>::arbitrary(g),
                    <B as ::quickcheck::Arbitrary>::arbitrary(g),
                    <C as ::quickcheck::Arbitrary>::arbitrary(g),
                )) as fn(&mut ::quickcheck::Gen) -> Self,
                (move |g| Self::Third(
                    <A as ::quickcheck::Arbitrary>::arbitrary(g),
                    <B as ::quickcheck::Arbitrary>::arbitrary(g),
                    <C as ::quickcheck::Arbitrary>::arbitrary(g),
                )) as fn(&mut ::quickcheck::Gen) -> Self,
            ]).unwrap()(g)
        }
    }

All credit for the incredible quickcheck library goes to its authors, not me! :)

Commit count: 15

cargo fmt