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

WIP implementation of proptest-attributes #166

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

davidbarsky
Copy link

(cc: @Centril)

A WIP implementation of the the proc macros discussed in #153. This currently supports:

  • A single argument + strategy per test.

This does not support:

That said, some feedback is better than none, so here we are. The changes are better seen than described, so take a look at the modified parse_date example, located in proptest-attributes/tests/hello.rs:

use proptest::{
    prelude::*, prop_assert_eq, strategy::Strategy, string::string_regex,
};
use proptest_attributes::proptest;

fn parse_date(s: &str) -> Option<(u32, u32, u32)> {
    if 10 != s.len() {
        return None;
    }

    // NEW: Ignore non-ASCII strings so we don't need to deal with Unicode.
    if !s.is_ascii() {
        return None;
    }

    if "-" != &s[4..5] || "-" != &s[7..8] {
        return None;
    }

    let year = &s[0..4];
    let month = &s[5..7];
    let day = &s[8..10];

    year.parse::<u32>().ok().and_then(|y| {
        month
            .parse::<u32>()
            .ok()
            .and_then(|m| day.parse::<u32>().ok().map(|d| (y, m, d)))
    })
}

fn gen_valid_date() -> impl Strategy<Value = String> {
    let expr = "[0-9]{4}-[0-9]{2}-[0-9]{2}";
    string_regex(expr).unwrap()
}

fn gen_all_utf8() -> impl Strategy<Value = String> {
    let expr = "\\PC*";
    string_regex(expr).unwrap()
}

prop_compose! {
  fn gen_parsed_date()(year in 0u32..10000, month in 1u32..13, day in 1u32..32) -> (u32, u32, u32) {
    (year, month, day)
  }
}

#[proptest(gen_valid_date())]
fn parses_all_valid_dates(s: String) {
    parse_date(&s).unwrap();
}

#[proptest(gen_all_utf8())]
fn doesnt_crash(s: String) {
    parse_date(&s);
}

#[proptest(gen_parsed_date())]
fn parses_date_back_to_original(date_tuple: (u32, u32, u32)) {
    let (y, m, d) = date_tuple;
    let (y2, m2, d2) =
        parse_date(&format!("{:04}-{:02}-{:02}", y, m, d)).unwrap();
    // prop_assert_eq! is basically the same as assert_eq!, but doesn't
    // cause a bunch of panic messages to be printed on intermediate
    // test failures. Which one to use is largely a matter of taste.
    prop_assert_eq!((y, m, d), (y2, m2, d2));
}

I think that, beyond what was described in #153, there might be an opportunity to simplify the prop_compose! macro with a proc macro.

Copy link
Collaborator

@Centril Centril left a comment

Choose a reason for hiding this comment

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

Looks good as an initial impl aside from some comments I have below.

proptest-attributes/src/lib.rs Outdated Show resolved Hide resolved
proptest-attributes/src/lib.rs Outdated Show resolved Hide resolved
proptest-attributes/src/lib.rs Outdated Show resolved Hide resolved
proptest-attributes/tests/compile-fail/method.stderr Outdated Show resolved Hide resolved
@davidbarsky davidbarsky marked this pull request as ready for review September 20, 2019 17:39
@davidbarsky
Copy link
Author

davidbarsky commented Sep 20, 2019

Hi @AltSysrq! I think this is ready to review! I'll be happy to change the authorship of the crate to "proptest contributers".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants