mod common;
use dcbor::prelude::*;
use dcbor_parse::parse_dcbor_item;
use dcbor_pattern::{Matcher, Pattern, format_paths};
use indoc::indoc;
fn cbor(s: &str) -> CBOR { parse_dcbor_item(s).unwrap() }
fn parse(s: &str) -> Pattern { Pattern::parse(s).unwrap() }
#[test]
fn test_bool_pattern_any() {
let pattern = parse("bool");
let true_cbor = cbor("true");
let paths = pattern.paths(&true_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
true
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let false_cbor = cbor("false");
let paths = pattern.paths(&false_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
false
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let number_cbor = cbor("42");
assert!(!pattern.matches(&number_cbor));
}
#[test]
fn test_bool_pattern_specific() {
let true_pattern = parse("true");
let false_pattern = parse("false");
let true_cbor = cbor("true");
let false_cbor = cbor("false");
let number_cbor = cbor("42");
let paths = true_pattern.paths(&true_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
true
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
assert!(!true_pattern.matches(&false_cbor));
assert!(!true_pattern.matches(&number_cbor));
assert!(!false_pattern.matches(&true_cbor));
let paths = false_pattern.paths(&false_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
false
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
assert!(!false_pattern.matches(&number_cbor));
}
#[test]
fn test_bool_pattern_display() {
assert_eq!(parse("bool").to_string(), "bool");
assert_eq!(parse("true").to_string(), "true");
assert_eq!(parse("false").to_string(), "false");
}
#[test]
fn test_text_pattern_any() {
let pattern = parse("text");
let hello_cbor = cbor(r#""Hello""#);
let paths = pattern.paths(&hello_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
"Hello"
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let empty_cbor = cbor(r#""""#);
let paths = pattern.paths(&empty_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
""
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let number_cbor = cbor("42");
assert!(!pattern.matches(&number_cbor));
}
#[test]
fn test_text_pattern_specific() {
let hello_pattern = parse(r#""Hello""#);
let world_pattern = parse(r#""World""#);
let hello_cbor = cbor(r#""Hello""#);
let world_cbor = cbor(r#""World""#);
let number_cbor = cbor("42");
let paths = hello_pattern.paths(&hello_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
"Hello"
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
assert!(!hello_pattern.matches(&world_cbor));
assert!(!hello_pattern.matches(&number_cbor));
assert!(!world_pattern.matches(&hello_cbor));
let paths = world_pattern.paths(&world_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
"World"
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
assert!(!world_pattern.matches(&number_cbor));
}
#[test]
fn test_text_pattern_regex() {
let digits_regex = regex::Regex::new(r"^\d+$").unwrap();
let digits_pattern = Pattern::text_regex(digits_regex);
let digits_cbor = cbor(r#""12345""#);
let letters_cbor = cbor(r#""Hello""#);
let mixed_cbor = cbor(r#""Hello123""#);
let number_cbor = cbor("42");
let paths = digits_pattern.paths(&digits_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
"12345"
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
assert!(!digits_pattern.matches(&letters_cbor));
assert!(!digits_pattern.matches(&mixed_cbor));
assert!(!digits_pattern.matches(&number_cbor));
}
#[test]
fn test_text_pattern_display() {
assert_eq!(parse("text").to_string(), "text");
assert_eq!(parse(r#""Hello""#).to_string(), r#""Hello""#);
let regex_pattern =
Pattern::text_regex(regex::Regex::new(r"^\d+$").unwrap());
assert_eq!(regex_pattern.to_string(), r#"/^\d+$/"#);
}
#[test]
fn test_number_pattern_any() {
let pattern = parse("number");
let int_cbor = cbor("42");
let paths = pattern.paths(&int_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
42
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let float_cbor = cbor("3.2222");
let paths = pattern.paths(&float_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
3.2222
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let neg_cbor = cbor("-5");
let paths = pattern.paths(&neg_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
-5
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let text_cbor = cbor(r#""42""#);
assert!(!pattern.matches(&text_cbor));
}
#[test]
fn test_number_pattern_specific() {
let int_pattern = parse("42");
let float_pattern = parse("3.2222");
let int_cbor = cbor("42");
let float_cbor = cbor("3.2222");
let different_int_cbor = cbor("24");
let text_cbor = cbor(r#""42""#);
let paths = int_pattern.paths(&int_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
42
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
assert!(!int_pattern.matches(&float_cbor));
assert!(!int_pattern.matches(&different_int_cbor));
assert!(!int_pattern.matches(&text_cbor));
assert!(!float_pattern.matches(&int_cbor));
let paths = float_pattern.paths(&float_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
3.2222
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
assert!(!float_pattern.matches(&text_cbor));
}
#[test]
fn test_number_pattern_range() {
let range_pattern = parse("10...20");
let in_range_cbor = cbor("15");
let boundary_low_cbor = cbor("10");
let boundary_high_cbor = cbor("20");
let below_range_cbor = cbor("5");
let above_range_cbor = cbor("25");
let text_cbor = cbor(r#""15""#);
let paths = range_pattern.paths(&in_range_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
15
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let paths = range_pattern.paths(&boundary_low_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
10
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let paths = range_pattern.paths(&boundary_high_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
20
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
assert!(!range_pattern.matches(&below_range_cbor));
assert!(!range_pattern.matches(&above_range_cbor));
assert!(!range_pattern.matches(&text_cbor));
}
#[test]
fn test_number_pattern_comparisons() {
let gt_pattern = parse(">10");
let gte_pattern = parse(">=10");
let lt_pattern = parse("<10");
let lte_pattern = parse("<=10");
let equal_cbor = cbor("10");
let greater_cbor = cbor("15");
let lesser_cbor = cbor("5");
assert!(!gt_pattern.matches(&equal_cbor));
let paths = gt_pattern.paths(&greater_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
15
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
assert!(!gt_pattern.matches(&lesser_cbor));
let paths = gte_pattern.paths(&equal_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
10
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
assert!(gte_pattern.matches(&greater_cbor));
assert!(!gte_pattern.matches(&lesser_cbor));
assert!(!lt_pattern.matches(&equal_cbor));
assert!(!lt_pattern.matches(&greater_cbor));
let paths = lt_pattern.paths(&lesser_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
5
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
assert!(lte_pattern.matches(&equal_cbor));
assert!(!lte_pattern.matches(&greater_cbor));
assert!(lte_pattern.matches(&lesser_cbor));
}
#[test]
fn test_number_pattern_nan() {
let nan_pattern = parse("NaN");
let nan_cbor = cbor("NaN");
let number_cbor = cbor("42");
let text_cbor = cbor(r#""NaN""#);
let paths = nan_pattern.paths(&nan_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
NaN
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
assert!(!nan_pattern.matches(&number_cbor));
assert!(!nan_pattern.matches(&text_cbor));
}
#[test]
fn test_number_pattern_display() {
assert_eq!(parse("number").to_string(), "number");
assert_eq!(parse("42").to_string(), "42");
assert_eq!(parse("3.2222").to_string(), "3.2222");
assert_eq!(parse("10...20").to_string(), "10...20");
assert_eq!(parse(">10").to_string(), ">10");
assert_eq!(parse(">=10").to_string(), ">=10");
assert_eq!(parse("<10").to_string(), "<10");
assert_eq!(parse("<=10").to_string(), "<=10");
assert_eq!(parse("NaN").to_string(), "NaN");
}
#[test]
fn test_byte_string_pattern_any() {
let pattern = parse("bstr");
let cbor_bytes = cbor("h'01020304'");
let paths = pattern.paths(&cbor_bytes);
#[rustfmt::skip]
let expected = indoc! {r#"
h'01020304'
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let empty_cbor = cbor("h''");
let paths = pattern.paths(&empty_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
h''
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let text_cbor = cbor(r#""hello""#);
assert!(!pattern.matches(&text_cbor));
}
#[test]
fn test_byte_string_pattern_specific() {
let exact_pattern = parse("h'01020304'");
let different_pattern = parse("h'0506'");
let cbor_bytes = cbor("h'01020304'");
let different_cbor = cbor("h'0506'");
let text_cbor = cbor(r#""hello""#);
let paths = exact_pattern.paths(&cbor_bytes);
#[rustfmt::skip]
let expected = indoc! {r#"
h'01020304'
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
assert!(!exact_pattern.matches(&different_cbor));
assert!(!exact_pattern.matches(&text_cbor));
assert!(!different_pattern.matches(&cbor_bytes));
let paths = different_pattern.paths(&different_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
h'0506'
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
assert!(!different_pattern.matches(&text_cbor));
}
#[test]
fn test_byte_string_pattern_regex() {
let digits_regex = regex::bytes::Regex::new(r"^\d+$").unwrap();
let digits_pattern = Pattern::byte_string_regex(digits_regex);
let digits_cbor = cbor("h'3132333435'"); let letters_cbor = cbor("h'48656c6c6f'"); let mixed_cbor = cbor("h'48656c6c6f313233'"); let text_cbor = cbor(r#""12345""#);
let paths = digits_pattern.paths(&digits_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
h'3132333435'
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
assert!(!digits_pattern.matches(&letters_cbor));
assert!(!digits_pattern.matches(&mixed_cbor));
assert!(!digits_pattern.matches(&text_cbor));
}
#[test]
fn test_byte_string_pattern_binary_data() {
let pattern = parse("bstr");
let binary_cbor = cbor("h'00010203fffefd'");
let paths = pattern.paths(&binary_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
h'00010203fffefd'
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let exact_pattern = parse("h'00010203fffefd'");
let paths = exact_pattern.paths(&binary_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
h'00010203fffefd'
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let different_pattern = parse("h'000102'");
assert!(!different_pattern.matches(&binary_cbor));
let starts_with_zero_regex = regex::bytes::Regex::new(r"^\x00").unwrap();
let starts_with_zero_pattern =
Pattern::byte_string_regex(starts_with_zero_regex);
let paths = starts_with_zero_pattern.paths(&binary_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
h'00010203fffefd'
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let starts_with_one_regex = regex::bytes::Regex::new(r"^\x01").unwrap();
let starts_with_one_pattern =
Pattern::byte_string_regex(starts_with_one_regex);
assert!(!starts_with_one_pattern.matches(&binary_cbor));
}
#[test]
fn test_byte_string_pattern_display() {
assert_eq!(parse("bstr").to_string(), "bstr");
assert_eq!(parse("h'deadbeef'").to_string(), "h'deadbeef'");
let regex = regex::bytes::Regex::new(r"^test.*").unwrap();
let regex_pattern = Pattern::byte_string_regex(regex);
assert_eq!(regex_pattern.to_string(), "h'/^test.*/'");
}
#[test]
fn test_date_pattern_any() {
bc_components::register_tags();
let pattern = parse("date");
let date = Date::from_ymd(2023, 12, 25);
let date_cbor = date.to_cbor();
let paths = pattern.paths(&date_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
2023-12-25
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let text_cbor = cbor(r#""2023-12-25""#);
assert!(!pattern.matches(&text_cbor));
let number_cbor = cbor("1703462400"); assert!(!pattern.matches(&number_cbor));
}
#[test]
fn test_date_pattern_specific() {
bc_components::register_tags();
let date = Date::from_ymd(2023, 12, 25);
let pattern = Pattern::date(date);
let date_cbor = date.to_cbor();
let paths = pattern.paths(&date_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
2023-12-25
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let other_date = Date::from_ymd(2024, 1, 1);
let other_date_cbor = other_date.to_cbor();
assert!(!pattern.matches(&other_date_cbor));
let text_cbor = cbor(r#""2023-12-25""#);
assert!(!pattern.matches(&text_cbor));
}
#[test]
fn test_date_pattern_range() {
bc_components::register_tags();
let start_date = Date::from_ymd(2023, 12, 20);
let end_date = Date::from_ymd(2023, 12, 30);
let pattern = Pattern::date_range(start_date..=end_date);
let middle_date = Date::from_ymd(2023, 12, 25);
let middle_date_cbor = middle_date.to_cbor();
let paths = pattern.paths(&middle_date_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
2023-12-25
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let start_date_cbor = start_date.to_cbor();
let paths = pattern.paths(&start_date_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
2023-12-20
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let end_date_cbor = end_date.to_cbor();
let paths = pattern.paths(&end_date_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
2023-12-30
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let early_date = Date::from_ymd(2023, 12, 15);
let early_date_cbor = early_date.to_cbor();
assert!(!pattern.matches(&early_date_cbor));
let late_date = Date::from_ymd(2024, 1, 5);
let late_date_cbor = late_date.to_cbor();
assert!(!pattern.matches(&late_date_cbor));
}
#[test]
fn test_date_pattern_earliest() {
bc_components::register_tags();
let earliest_date = Date::from_ymd(2023, 12, 20);
let pattern = Pattern::date_earliest(earliest_date);
let earliest_date_cbor = earliest_date.to_cbor();
let paths = pattern.paths(&earliest_date_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
2023-12-20
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let later_date = Date::from_ymd(2023, 12, 25);
let later_date_cbor = later_date.to_cbor();
let paths = pattern.paths(&later_date_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
2023-12-25
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let earlier_date = Date::from_ymd(2023, 12, 15);
let earlier_date_cbor = earlier_date.to_cbor();
assert!(!pattern.matches(&earlier_date_cbor));
}
#[test]
fn test_date_pattern_latest() {
bc_components::register_tags();
let latest_date = Date::from_ymd(2023, 12, 30);
let pattern = Pattern::date_latest(latest_date);
let latest_date_cbor = latest_date.to_cbor();
let paths = pattern.paths(&latest_date_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
2023-12-30
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let earlier_date = Date::from_ymd(2023, 12, 25);
let earlier_date_cbor = earlier_date.to_cbor();
let paths = pattern.paths(&earlier_date_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
2023-12-25
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let later_date = Date::from_ymd(2024, 1, 5);
let later_date_cbor = later_date.to_cbor();
assert!(!pattern.matches(&later_date_cbor));
}
#[test]
fn test_date_pattern_iso8601() {
bc_components::register_tags();
let date = Date::from_ymd(2023, 12, 25);
let iso_string = date.to_string();
let pattern = Pattern::date_iso8601(iso_string.clone());
let date_cbor = date.to_cbor();
let paths = pattern.paths(&date_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
2023-12-25
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let other_date = Date::from_ymd(2024, 1, 1);
let other_date_cbor = other_date.to_cbor();
assert!(!pattern.matches(&other_date_cbor));
}
#[test]
fn test_date_pattern_regex() {
bc_components::register_tags();
let regex = regex::Regex::new(r"^2023-").unwrap();
let pattern = Pattern::date_regex(regex);
let date_2023 = Date::from_ymd(2023, 12, 25);
let date_2023_cbor = date_2023.to_cbor();
let paths = pattern.paths(&date_2023_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
2023-12-25
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let date_2024 = Date::from_ymd(2024, 1, 1);
let date_2024_cbor = date_2024.to_cbor();
assert!(!pattern.matches(&date_2024_cbor));
let december_regex = regex::Regex::new(r"-12-").unwrap();
let december_pattern = Pattern::date_regex(december_regex);
let paths = december_pattern.paths(&date_2023_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
2023-12-25
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let january_date = Date::from_ymd(2023, 1, 15);
let january_date_cbor = january_date.to_cbor();
assert!(!december_pattern.matches(&january_date_cbor));
}
#[test]
fn test_date_pattern_with_time() {
bc_components::register_tags();
let datetime = Date::from_timestamp(1703462400.0); let pattern = parse("date");
let datetime_cbor = datetime.to_cbor();
let paths = pattern.paths(&datetime_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
2023-12-25
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let specific_pattern = Pattern::date(datetime);
let paths = specific_pattern.paths(&datetime_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
2023-12-25
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let datetime_with_millis = Date::from_timestamp(1703462400.123);
let datetime_with_millis_cbor = datetime_with_millis.to_cbor();
let paths = pattern.paths(&datetime_with_millis_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
2023-12-25
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
}
#[test]
fn test_date_pattern_display() {
assert_eq!(parse("date").to_string(), "date");
let date = Date::from_ymd(2023, 12, 25);
assert_eq!(Pattern::date(date).to_string(), format!("date'{}'", date));
let start_date = Date::from_ymd(2023, 12, 20);
let end_date = Date::from_ymd(2023, 12, 30);
assert_eq!(
Pattern::date_range(start_date..=end_date).to_string(),
format!("date'{}...{}'", start_date, end_date)
);
assert_eq!(
Pattern::date_earliest(date).to_string(),
format!("date'{}...'", date)
);
assert_eq!(
Pattern::date_latest(date).to_string(),
format!("date'...{}'", date)
);
assert_eq!(
Pattern::date_iso8601("2023-12-25T00:00:00Z").to_string(),
"date'2023-12-25T00:00:00Z'"
);
let regex = regex::Regex::new(r"^2023-").unwrap();
assert_eq!(Pattern::date_regex(regex).to_string(), "date'/^2023-/'");
}
#[test]
fn test_null_pattern() {
let pattern = parse("null");
let null_cbor = cbor("null");
let paths = pattern.paths(&null_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
null
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let true_cbor = cbor("true");
assert!(!pattern.matches(&true_cbor));
let false_cbor = cbor("false");
assert!(!pattern.matches(&false_cbor));
let number_cbor = cbor("42");
assert!(!pattern.matches(&number_cbor));
let text_cbor = cbor(r#""hello""#);
assert!(!pattern.matches(&text_cbor));
let array_cbor = cbor("[1, 2, 3]");
assert!(!pattern.matches(&array_cbor));
}
#[test]
fn test_null_pattern_display() {
assert_eq!(parse("null").to_string(), "null");
}
#[test]
fn test_known_value_pattern_any() {
let pattern = parse("known");
let known_value_cbor = cbor("'1'"); let paths = pattern.paths(&known_value_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
40000(1)
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let date_value_cbor = cbor("'16'"); let paths = pattern.paths(&date_value_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
40000(16)
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let custom_value_cbor = cbor("'12345'");
let paths = pattern.paths(&custom_value_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
40000(12345)
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let plain_int_cbor = cbor("1");
assert!(!pattern.matches(&plain_int_cbor));
let text_cbor = cbor(r#""hello""#);
assert!(!pattern.matches(&text_cbor));
let negative_cbor = cbor("-1");
assert!(!pattern.matches(&negative_cbor));
}
#[test]
fn test_known_value_pattern_specific() {
bc_components::register_tags();
let is_a_pattern = parse("'isA'");
let date_pattern = parse("'date'");
let is_a_cbor = cbor("'1'"); let date_cbor = cbor("'16'"); let other_cbor = cbor("'42'"); let plain_int_cbor = cbor("1"); let text_cbor = cbor(r#""hello""#);
let paths = is_a_pattern.paths(&is_a_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
40000(1)
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
assert!(!is_a_pattern.matches(&date_cbor));
assert!(!is_a_pattern.matches(&other_cbor));
assert!(!is_a_pattern.matches(&plain_int_cbor)); assert!(!is_a_pattern.matches(&text_cbor));
assert!(!date_pattern.matches(&is_a_cbor));
let paths = date_pattern.paths(&date_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
40000(16)
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
assert!(!date_pattern.matches(&other_cbor));
assert!(!date_pattern.matches(&plain_int_cbor)); assert!(!date_pattern.matches(&text_cbor));
}
#[test]
fn test_known_value_pattern_named() {
bc_components::register_tags();
let is_a_pattern = parse("'isA'");
let date_pattern = parse("'date'");
let unknown_pattern = parse("'unknownValue'");
let is_a_cbor = cbor("'isA'"); let date_cbor = cbor("'date'"); let other_cbor = cbor("'42'"); let plain_int_cbor = cbor("1"); let text_cbor = cbor(r#""hello""#);
let paths = is_a_pattern.paths(&is_a_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
40000(1)
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
assert!(!is_a_pattern.matches(&date_cbor));
assert!(!is_a_pattern.matches(&other_cbor));
assert!(!is_a_pattern.matches(&plain_int_cbor)); assert!(!is_a_pattern.matches(&text_cbor));
assert!(!date_pattern.matches(&is_a_cbor));
let paths = date_pattern.paths(&date_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
40000(16)
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
assert!(!date_pattern.matches(&other_cbor));
assert!(!date_pattern.matches(&plain_int_cbor)); assert!(!date_pattern.matches(&text_cbor));
assert!(!unknown_pattern.matches(&is_a_cbor));
assert!(!unknown_pattern.matches(&date_cbor));
assert!(!unknown_pattern.matches(&other_cbor));
assert!(!unknown_pattern.matches(&plain_int_cbor));
assert!(!unknown_pattern.matches(&text_cbor));
}
#[test]
fn test_known_value_pattern_regex() {
let is_pattern =
Pattern::known_value_regex(regex::Regex::new(r"^is.*").unwrap());
let te_pattern =
Pattern::known_value_regex(regex::Regex::new(r".*te$").unwrap());
let no_match_pattern =
Pattern::known_value_regex(regex::Regex::new(r"^xyz.*").unwrap());
let is_a_cbor = cbor("'1'"); let date_cbor = cbor("'16'"); let note_cbor = cbor("'4'"); let other_cbor = cbor("'42'"); let plain_int_cbor = cbor("1"); let text_cbor = cbor(r#""hello""#);
let paths = is_pattern.paths(&is_a_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
40000(1)
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
assert!(!is_pattern.matches(&date_cbor));
assert!(!is_pattern.matches(¬e_cbor));
assert!(!is_pattern.matches(&other_cbor));
assert!(!is_pattern.matches(&plain_int_cbor)); assert!(!is_pattern.matches(&text_cbor));
assert!(!te_pattern.matches(&is_a_cbor));
let paths = te_pattern.paths(&date_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
40000(16)
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let paths = te_pattern.paths(¬e_cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
40000(4)
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
assert!(!te_pattern.matches(&other_cbor));
assert!(!te_pattern.matches(&plain_int_cbor)); assert!(!te_pattern.matches(&text_cbor));
assert!(!no_match_pattern.matches(&is_a_cbor));
assert!(!no_match_pattern.matches(&date_cbor));
assert!(!no_match_pattern.matches(¬e_cbor));
assert!(!no_match_pattern.matches(&other_cbor));
assert!(!no_match_pattern.matches(&plain_int_cbor));
assert!(!no_match_pattern.matches(&text_cbor));
}
#[test]
fn test_known_value_pattern_display() {
let any_pattern = parse("known");
assert_eq!(any_pattern.to_string(), "known");
let is_a_pattern = Pattern::known_value(known_values::IS_A);
assert_eq!(is_a_pattern.to_string(), "'isA'");
let date_pattern = Pattern::known_value(known_values::DATE);
assert_eq!(date_pattern.to_string(), "'date'");
let named_pattern = Pattern::known_value_named("customName");
assert_eq!(named_pattern.to_string(), "'customName'");
let regex_pattern =
Pattern::known_value_regex(regex::Regex::new(r"^is.*").unwrap());
assert_eq!(regex_pattern.to_string(), "'/^is.*/'");
}
#[test]
fn test_map_int_keys() {
let map_pattern = Pattern::parse(r#"{1: text}"#).unwrap();
let cbor = parse_dcbor_item(r#"{1: "first", 2: "second"}"#).unwrap();
let paths = map_pattern.paths(&cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
{1: "first", 2: "second"}
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
}
#[test]
fn test_map_negative_keys() {
let map_pattern = Pattern::parse(r#"{-1: text}"#).unwrap();
let cbor = parse_dcbor_item(r#"{-1: "first", 2: "second"}"#).unwrap();
let paths = map_pattern.paths(&cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
{2: "second", -1: "first"}
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
}
#[test]
fn test_map_float_keys() {
let map_pattern = Pattern::parse(r#"{3.2222: text}"#).unwrap();
let cbor = parse_dcbor_item(r#"{3.2222: "first", 2: "second"}"#).unwrap();
let paths = map_pattern.paths(&cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
{2: "second", 3.2222: "first"}
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
}
#[test]
fn test_map_bool_keys() {
let map_pattern = Pattern::parse(r#"{true: text}"#).unwrap();
let cbor = parse_dcbor_item(r#"{true: "first", false: "second"}"#).unwrap();
let paths = map_pattern.paths(&cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
{false: "second", true: "first"}
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
}
#[test]
fn test_map_bstr_keys() {
let map_pattern = Pattern::parse(r#"{h'68656c6c6f': text}"#).unwrap();
let cbor = parse_dcbor_item(
r#"{h'68656c6c6f': "first", h'776f726c64': "second"}"#,
)
.unwrap();
let paths = map_pattern.paths(&cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
{h'68656c6c6f': "first", h'776f726c64': "second"}
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
}
#[test]
fn test_map_known_value_keys() {
bc_components::register_tags();
let map_pattern = Pattern::parse(r#"{'100': text}"#).unwrap();
let cbor =
parse_dcbor_item(r#"{'100': "first", '200': "second"}"#).unwrap();
let paths = map_pattern.paths(&cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
{40000(100): "first", 40000(200): "second"}
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
}
#[test]
fn test_map_complex_keys() {
let map_pattern = Pattern::parse(r#"{"a"|"b": text}"#).unwrap();
let cbor = parse_dcbor_item(r#"{"z": "first", "b": "second"}"#).unwrap();
let paths = map_pattern.paths(&cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
{"b": "second", "z": "first"}
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
}
#[test]
fn test_array_complex_elements() {
let pattern = Pattern::parse(r#"["a"|"b"]"#).unwrap();
let cbor = parse_dcbor_item(r#"["b"]"#).unwrap();
let paths = pattern.paths(&cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
["b"]
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let sequence_pattern = Pattern::parse(r#"[(1|2), "hello"]"#).unwrap();
let cbor = parse_dcbor_item(r#"[2, "hello"]"#).unwrap();
let paths = sequence_pattern.paths(&cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
[2, "hello"]
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let complex_pattern = Pattern::parse(r#"["hello", "a"|"b"]"#).unwrap();
let cbor = parse_dcbor_item(r#"["hello", "b"]"#).unwrap();
let paths = complex_pattern.paths(&cbor);
#[rustfmt::skip]
let expected = indoc! {r#"
["hello", "b"]
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
}
#[test]
fn test_array_or_precedence_issue() {
let pattern = Pattern::parse(r#"[1|2, "hello"]"#).unwrap();
println!("Pattern display: {}", pattern);
let cbor_1_hello = parse_dcbor_item(r#"[1, "hello"]"#).unwrap();
let cbor_2_hello = parse_dcbor_item(r#"[2, "hello"]"#).unwrap();
let cbor_1_only = parse_dcbor_item(r#"[1]"#).unwrap();
println!("Matches [1, \"hello\"]: {}", pattern.matches(&cbor_1_hello));
println!("Matches [2, \"hello\"]: {}", pattern.matches(&cbor_2_hello));
println!("Matches [1]: {}", pattern.matches(&cbor_1_only));
assert!(
pattern.matches(&cbor_1_hello),
"[1, \"hello\"] should match"
);
assert!(
pattern.matches(&cbor_2_hello),
"[2, \"hello\"] should match"
);
assert!(!pattern.matches(&cbor_1_only), "[1] should NOT match");
}