use oatf::primitives::{evaluate_condition, evaluate_predicate};
use oatf::types::{Condition, MatchCondition, MatchEntry};
use proptest::prelude::*;
use serde_json::{Value, json};
use std::collections::HashMap;
fn empty_match_condition() -> MatchCondition {
MatchCondition {
contains: None,
starts_with: None,
ends_with: None,
regex: None,
any_of: None,
gt: None,
lt: None,
gte: None,
lte: None,
exists: None,
}
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(256))]
#[test]
fn empty_predicate_is_true(n in -100i64..100) {
let predicate = HashMap::new();
let value = json!(n);
prop_assert!(evaluate_predicate(&predicate, &value));
}
#[test]
fn scalar_equality_existing_path(
key in "[a-z]{1,6}",
val in -100i64..100,
) {
let mut obj = serde_json::Map::new();
obj.insert(key.clone(), json!(val));
let value = Value::Object(obj);
let mut predicate = HashMap::new();
predicate.insert(key, MatchEntry::Scalar(json!(val)));
prop_assert!(evaluate_predicate(&predicate, &value));
}
#[test]
fn nonexistent_path_returns_false(
key in "[a-z]{1,6}",
val in -100i64..100,
) {
let value = json!({"other_key": val});
let mut predicate = HashMap::new();
predicate.insert(key.clone(), MatchEntry::Scalar(json!(val)));
let expected = key == "other_key";
prop_assert_eq!(evaluate_predicate(&predicate, &value), expected);
}
#[test]
fn exists_true_existing(
key in "[a-z]{1,6}",
val in -100i64..100,
) {
let mut obj = serde_json::Map::new();
obj.insert(key.clone(), json!(val));
let value = Value::Object(obj);
let mut predicate = HashMap::new();
predicate.insert(key, MatchEntry::Condition(MatchCondition {
exists: Some(true),
..empty_match_condition()
}));
prop_assert!(evaluate_predicate(&predicate, &value));
}
#[test]
fn exists_false_missing(
key in "[a-z]{1,6}",
) {
let value = json!({});
let mut predicate = HashMap::new();
predicate.insert(key, MatchEntry::Condition(MatchCondition {
exists: Some(false),
..empty_match_condition()
}));
prop_assert!(evaluate_predicate(&predicate, &value));
}
#[test]
fn exists_true_missing(
key in "[a-z]{1,6}",
) {
let value = json!({});
let mut predicate = HashMap::new();
predicate.insert(key, MatchEntry::Condition(MatchCondition {
exists: Some(true),
..empty_match_condition()
}));
prop_assert!(!evaluate_predicate(&predicate, &value));
}
#[test]
fn exists_false_existing(
key in "[a-z]{1,6}",
val in -100i64..100,
) {
let mut obj = serde_json::Map::new();
obj.insert(key.clone(), json!(val));
let value = Value::Object(obj);
let mut predicate = HashMap::new();
predicate.insert(key, MatchEntry::Condition(MatchCondition {
exists: Some(false),
..empty_match_condition()
}));
prop_assert!(!evaluate_predicate(&predicate, &value));
}
#[test]
fn multi_entry_and_logic(a in -50i64..50, b in -50i64..50) {
let value = json!({"x": a, "y": b});
let mut pred_match = HashMap::new();
pred_match.insert("x".to_string(), MatchEntry::Scalar(json!(a)));
pred_match.insert("y".to_string(), MatchEntry::Scalar(json!(b)));
prop_assert!(evaluate_predicate(&pred_match, &value));
let mut pred_wrong = HashMap::new();
pred_wrong.insert("x".to_string(), MatchEntry::Scalar(json!(a)));
pred_wrong.insert("y".to_string(), MatchEntry::Scalar(json!(b + 1)));
let expected = false; prop_assert_eq!(evaluate_predicate(&pred_wrong, &value), expected);
}
#[test]
fn predicate_condition_consistent_with_evaluate_condition(
val in "[a-zA-Z0-9]{1,20}",
substring in "[a-zA-Z0-9]{0,5}",
) {
let json_value = json!({"field": val.clone()});
let cond = MatchCondition {
contains: Some(substring.clone()),
..empty_match_condition()
};
let mut predicate = HashMap::new();
predicate.insert("field".to_string(), MatchEntry::Condition(cond.clone()));
let cond_result = evaluate_condition(
&Condition::Operators(cond),
&Value::String(val),
);
let pred_result = evaluate_predicate(&predicate, &json_value);
prop_assert_eq!(pred_result, cond_result);
}
}