use protovalidate_buffa::cel::{AsCelValue, CelConstraint};
use protovalidate_buffa::Violation;
use cel_interpreter::Value;
struct Fake {
id: String,
ref_id: String,
}
impl AsCelValue for Fake {
fn as_cel_value(&self) -> Value {
let mut map = std::collections::HashMap::new();
map.insert("id".to_string(), Value::String(self.id.clone().into()));
map.insert(
"ref_id".to_string(),
Value::String(self.ref_id.clone().into()),
);
Value::Map(map.into())
}
}
fn run(constraint: &CelConstraint, fake: &Fake) -> Result<(), Violation> {
constraint.eval(fake)
}
static CHECK_ID_NOT_EMPTY: CelConstraint = CelConstraint::new(
"fake.id_not_empty",
"id must not be empty",
"this.id != ''",
);
#[test]
fn bool_true_passes() {
let fake = Fake {
id: "abc".into(),
ref_id: String::new(),
};
assert!(run(&CHECK_ID_NOT_EMPTY, &fake).is_ok());
}
#[test]
fn bool_false_fails_with_constraint_message() {
let fake = Fake {
id: String::new(),
ref_id: String::new(),
};
let err = run(&CHECK_ID_NOT_EMPTY, &fake).unwrap_err();
assert_eq!(err.rule_id, "fake.id_not_empty");
assert!(err.message.contains("id must not be empty"));
}
static EMPTY_STRING_MEANS_PASS: CelConstraint = CelConstraint::new(
"fake.legacy",
"",
"''", );
#[test]
fn empty_string_return_is_pass() {
let fake = Fake {
id: "abc".into(),
ref_id: String::new(),
};
assert!(run(&EMPTY_STRING_MEANS_PASS, &fake).is_ok());
}
static NON_EMPTY_STRING_RETURN: CelConstraint = CelConstraint::new(
"fake.dyn_msg",
"", "this.id == '' ? 'id needs to be set' : ''",
);
#[test]
fn non_empty_string_return_is_fail_with_returned_text() {
let fake = Fake {
id: String::new(),
ref_id: String::new(),
};
let err = run(&NON_EMPTY_STRING_RETURN, &fake).unwrap_err();
assert!(err.message.contains("id needs to be set"));
}
static NON_EMPTY_STRING_STATIC_MSG_WINS: CelConstraint = CelConstraint::new(
"fake.msg_wins",
"the static message wins",
"this.id == '' ? 'dynamic text that should be suppressed' : ''",
);
#[test]
fn static_message_overrides_returned_string() {
let fake = Fake {
id: String::new(),
ref_id: String::new(),
};
let err = run(&NON_EMPTY_STRING_STATIC_MSG_WINS, &fake).unwrap_err();
assert_eq!(err.message, "the static message wins");
assert!(!err.message.contains("dynamic text"));
}
#[test]
fn is_uuid_custom_fn_registered() {
static CHECK_UUID: CelConstraint = CelConstraint::new(
"fake.ref_id_uuid",
"ref_id must be a UUID",
"this.ref_id == '' || this.ref_id.isUuid()",
);
let ok = Fake {
id: String::new(),
ref_id: "550e8400-e29b-41d4-a716-446655440000".into(),
};
let bad = Fake {
id: String::new(),
ref_id: "not-uuid".into(),
};
assert!(CHECK_UUID.eval(&ok).is_ok());
assert!(CHECK_UUID.eval(&bad).is_err());
}