use qcheck::Arbitrary;
use radicle::identity::RepoId;
use radicle::node::NodeId;
use radicle::test::arbitrary::{oid, refstring};
use super::EventFilter;
impl Arbitrary for EventFilter {
fn arbitrary(g: &mut qcheck::Gen) -> Self {
use EventFilter::*;
#[derive(Clone, Copy)]
enum Variants {
Repository,
Branch,
BranchCreated,
BranchUpdated,
BranchDeleted,
Patch,
PatchCreated,
PatchUpdated,
Node,
Allow,
Deny,
Not,
And,
Or,
}
let leaves = [
Variants::Repository,
Variants::Branch,
Variants::BranchCreated,
Variants::BranchUpdated,
Variants::BranchDeleted,
Variants::Patch,
Variants::PatchCreated,
Variants::PatchUpdated,
Variants::Node,
Variants::Allow,
Variants::Deny,
];
let branches = [Variants::Not, Variants::And, Variants::Or];
let n = i8::arbitrary(g).clamp(1, 10);
// Choose a branch 7 out of 10 times, to ensure that we get more complex
// filters when generating them
//
// SAFETY: the leaves and branches slices are non-empty so this will
// always return a value
let variant = if n < 7 {
*g.choose(&branches)
.expect("BUG: will always provide an EventFilter")
} else {
*g.choose(&leaves)
.expect("BUG: will always provide an EventFilter")
};
// N.b. reduce the size to so that the recursive type eventually reduces
// to pick a leaf branch
let size = (3 * g.size() / 4).max(1);
match variant {
Variants::Repository => Repository(RepoId::arbitrary(g)),
Variants::Branch => Branch(refstring(10)),
Variants::BranchCreated => BranchCreated,
Variants::BranchUpdated => BranchUpdated,
Variants::BranchDeleted => BranchDeleted,
Variants::Patch => Patch(oid()),
Variants::PatchCreated => PatchCreated,
Variants::PatchUpdated => PatchUpdated,
Variants::Node => Node(NodeId::arbitrary(g)),
Variants::Allow => Allow,
Variants::Deny => Deny,
Variants::Not => {
g.set_size(size);
Not(vec![Self::arbitrary(g)])
}
Variants::And => {
g.set_size(size);
And(Vec::arbitrary(g))
}
Variants::Or => {
g.set_size(size);
Or(Vec::arbitrary(g))
}
}
}
}