//! Property tests that generalize the brute-force checks.

mod common;

use common::to_regex;
use proptest::prelude::*;
use regex_range::{to_regex_range, Options};

proptest! {
    /// The compiled regex matches a probe iff the probe lies in range.
    #[test]
    fn semantic_in_range(
        a in -5000i64..5000,
        b in -5000i64..5000,
        probe in -6000i64..6000,
    ) {
        let src = to_regex_range(&a.to_string(), Some(&b.to_string()), &Options::default()).unwrap();
        let re = to_regex(&src);
        let lo = a.min(b);
        let hi = a.max(b);
        let want = lo <= probe && hi >= probe;
        prop_assert_eq!(re.is_match(&probe.to_string()), want);
    }

    /// Shorthand output matches the same set as default output.
    #[test]
    fn shorthand_matches_same_set(
        a in 0i64..5000,
        b in 0i64..5000,
        probe in 0i64..6000,
    ) {
        let default = to_regex_range(&a.to_string(), Some(&b.to_string()), &Options::default()).unwrap();
        let short = to_regex_range(
            &a.to_string(),
            Some(&b.to_string()),
            &Options::default().shorthand(true),
        )
        .unwrap();
        let re_d = to_regex(&default);
        let re_s = to_regex(&short);
        let p = probe.to_string();
        prop_assert_eq!(re_d.is_match(&p), re_s.is_match(&p));
    }

    /// Wrapping a wrap:false result in a non-capturing group reproduces the
    /// default output whenever the default was wrapped.
    #[test]
    fn wrap_false_plus_group_equals_default(
        a in -3000i64..3000,
        b in -3000i64..3000,
    ) {
        let default = to_regex_range(&a.to_string(), Some(&b.to_string()), &Options::default()).unwrap();
        let bare = to_regex_range(
            &a.to_string(),
            Some(&b.to_string()),
            &Options::default().wrap(false),
        )
        .unwrap();
        if default.starts_with("(?:") && default.ends_with(')') {
            prop_assert_eq!(default, format!("(?:{bare})"));
        } else {
            prop_assert_eq!(default, bare);
        }
    }
}
