use ldap_acis::*;
use proptest::prelude::*;
use acls_rs::algebra::{BoundedJoinSemilattice, BoundedMeetSemilattice};
use acls_rs::prelude::*;
fn arb_scope() -> impl Strategy<Value = Scope> {
prop_oneof![
Just(Scope::Base),
Just(Scope::OneLevel),
Just(Scope::Subtree),
]
}
fn arb_operation_type() -> impl Strategy<Value = OperationType> {
prop_oneof![
Just(OperationType::Bind),
Just(OperationType::Search),
Just(OperationType::Compare),
Just(OperationType::Read),
Just(OperationType::Add),
Just(OperationType::Delete),
Just(OperationType::Modify),
Just(OperationType::ModifyDn),
Just(OperationType::SelfWrite),
Just(OperationType::All),
]
}
fn arb_operation_set() -> impl Strategy<Value = OperationSet> {
prop::collection::vec(arb_operation_type(), 0..6)
.prop_map(|ops| ops.into_iter().collect::<OperationSet>())
}
fn arb_attr_name() -> impl Strategy<Value = String> {
prop_oneof![
Just("cn".to_string()),
Just("sn".to_string()),
Just("uid".to_string()),
Just("mail".to_string()),
Just("givenname".to_string()),
Just("memberof".to_string()),
]
}
fn arb_attribute_set() -> impl Strategy<Value = AttributeSet> {
prop_oneof![
Just(AttributeSet::All),
prop::collection::btree_set(arb_attr_name(), 0..4).prop_map(AttributeSet::Include),
prop::collection::btree_set(arb_attr_name(), 1..4).prop_map(AttributeSet::Exclude),
]
}
fn arb_target_filter_leaf() -> impl Strategy<Value = TargetFilter> {
prop_oneof![
Just(TargetFilter::All),
arb_attr_name().prop_map(TargetFilter::ObjectClass),
arb_attr_name().prop_map(TargetFilter::HasAttribute),
Just(TargetFilter::DnPattern(
"uid=*,dc=example,dc=com".to_string()
)),
]
}
fn arb_target_filter() -> impl Strategy<Value = TargetFilter> {
arb_target_filter_leaf().prop_recursive(2, 8, 4, |inner| {
prop_oneof![
prop::collection::vec(inner.clone(), 1..4).prop_map(TargetFilter::And),
prop::collection::vec(inner.clone(), 1..4).prop_map(TargetFilter::Or),
inner.prop_map(|f| TargetFilter::Not(Box::new(f))),
]
})
}
fn arb_bind_rule_leaf() -> impl Strategy<Value = BindRule> {
prop_oneof![
Just(BindRule::Anyone),
Just(BindRule::Authenticated),
Just(BindRule::SelfUser),
Just(BindRule::ParentDn),
arb_attr_name().prop_map(|s| BindRule::UserDn(format!("uid={},dc=example,dc=com", s))),
arb_attr_name().prop_map(|s| BindRule::GroupDn(format!("cn={},dc=example,dc=com", s))),
arb_attr_name().prop_map(BindRule::Ip),
]
}
fn arb_dn_scope() -> impl Strategy<Value = DnScope> {
let dn_strategy = prop_oneof![
Just(None),
Just(Some("dc=example,dc=com".to_string())),
Just(Some("ou=people,dc=example,dc=com".to_string())),
Just(Some("uid=alice,ou=people,dc=example,dc=com".to_string())),
Just(Some("ou=groups,dc=example,dc=com".to_string())),
Just(Some("cn=admins,ou=groups,dc=example,dc=com".to_string())),
];
(dn_strategy, arb_scope()).prop_map(|(dn, scope)| DnScope::new(dn, scope))
}
fn arb_bind_rule() -> impl Strategy<Value = BindRule> {
arb_bind_rule_leaf().prop_recursive(2, 8, 4, |inner| {
prop_oneof![
prop::collection::vec(inner.clone(), 1..4).prop_map(BindRule::And),
prop::collection::vec(inner.clone(), 1..4).prop_map(BindRule::Or),
inner.prop_map(|r| BindRule::Not(Box::new(r))),
]
})
}
macro_rules! partial_ord_laws {
($mod_name:ident, $strategy:expr) => {
mod $mod_name {
use super::*;
proptest! {
#[test]
fn reflexivity(a in $strategy) {
prop_assert_eq!(a.partial_cmp(&a), Some(std::cmp::Ordering::Equal));
}
#[test]
fn antisymmetry(a in $strategy, b in $strategy) {
if let (Some(ab), Some(ba)) = (a.partial_cmp(&b), b.partial_cmp(&a)) {
if ab == std::cmp::Ordering::Less && ba == std::cmp::Ordering::Less {
prop_assert!(false, "antisymmetry violated: a<b and b<a");
}
if ab == std::cmp::Ordering::Greater && ba == std::cmp::Ordering::Greater {
prop_assert!(false, "antisymmetry violated: a>b and b>a");
}
if ab == std::cmp::Ordering::Equal {
prop_assert_eq!(ba, std::cmp::Ordering::Equal);
}
}
}
#[test]
fn consistency(a in $strategy, b in $strategy) {
if let Some(ab) = a.partial_cmp(&b) {
if let Some(ba) = b.partial_cmp(&a) {
prop_assert_eq!(ab.reverse(), ba,
"partial_cmp not consistent with reverse");
}
}
}
}
}
};
}
partial_ord_laws!(scope_partial_ord, arb_scope());
partial_ord_laws!(operation_type_partial_ord, arb_operation_type());
partial_ord_laws!(operation_set_partial_ord, arb_operation_set());
partial_ord_laws!(attribute_set_partial_ord, arb_attribute_set());
partial_ord_laws!(target_filter_partial_ord, arb_target_filter());
partial_ord_laws!(dn_scope_partial_ord, arb_dn_scope());
partial_ord_laws!(bind_rule_partial_ord, arb_bind_rule());
macro_rules! lattice_laws {
($mod_name:ident, $strategy:expr, $type:ty) => {
mod $mod_name {
use super::*;
proptest! {
#[test]
fn meet_idempotent(a in $strategy) {
prop_assert_eq!(a.clone().meet(a.clone()), a);
}
#[test]
fn join_idempotent(a in $strategy) {
prop_assert_eq!(a.clone().join(a.clone()), a);
}
#[test]
fn meet_commutative(a in $strategy, b in $strategy) {
prop_assert_eq!(a.clone().meet(b.clone()), b.meet(a));
}
#[test]
fn join_commutative(a in $strategy, b in $strategy) {
prop_assert_eq!(a.clone().join(b.clone()), b.join(a));
}
#[test]
fn meet_associative(a in $strategy, b in $strategy, c in $strategy) {
let lhs = a.clone().meet(b.clone()).meet(c.clone());
let rhs = a.meet(b.meet(c));
prop_assert_eq!(lhs, rhs);
}
#[test]
fn join_associative(a in $strategy, b in $strategy, c in $strategy) {
let lhs = a.clone().join(b.clone()).join(c.clone());
let rhs = a.join(b.join(c));
prop_assert_eq!(lhs, rhs);
}
#[test]
fn join_identity(a in $strategy) {
let id = <$type>::identity();
prop_assert_eq!(a.clone().combine(id.clone()), a.clone());
prop_assert_eq!(id.combine(a.clone()), a);
}
#[test]
fn bounded_top(a in $strategy) {
prop_assert_eq!(a.clone().meet(<$type>::top()), a);
}
#[test]
fn bounded_bottom(a in $strategy) {
prop_assert_eq!(a.clone().join(<$type>::bottom()), a);
}
#[test]
fn absorption_meet_join(a in $strategy, b in $strategy) {
let result = a.clone().meet(a.clone().join(b));
prop_assert_eq!(result, a);
}
#[test]
fn absorption_join_meet(a in $strategy, b in $strategy) {
let result = a.clone().join(a.clone().meet(b));
prop_assert_eq!(result, a);
}
}
}
};
}
lattice_laws!(scope_lattice, arb_scope(), Scope);
lattice_laws!(operation_set_lattice, arb_operation_set(), OperationSet);
lattice_laws!(attribute_set_lattice, arb_attribute_set(), AttributeSet);