///|
pub(all) enum Coverage {
Reachable
Partial
Shadowed
} derive(Eq, Debug)
///|
pub(all) struct RuleAudit {
rule_id : String
coverage : Coverage
reachable_witness : Packet?
blocked_witness : Packet?
blocked_by : String?
} derive(Eq, Debug)
///|
/// Coverage subtracts the union of all earlier rules, regardless of their action.
pub fn Policy::audit(
self : Policy,
max_nodes? : Int = 100000,
) -> Array[RuleAudit] raise PolicyError {
let e = Engine::new(max_nodes)
let c = e.compile(self)
let reports = []
for i, rule in self.rules {
let active = c.effective[i]
let blocked = e.both(c.predicates[i], e.not(active))
let reachable_witness = e.witness(active)
let blocked_witness = e.witness(blocked)
if reachable_witness is Some(p) {
if self.evaluate(p).rule_id != Some(rule.id) {
raise Internal("internal reachability witness mismatch")
}
}
let blocked_by = match blocked_witness {
None => None
Some(p) => {
let d = self.evaluate(p)
if !rule.matches(p) ||
d.rule_id is None ||
d.rule_id == Some(rule.id) ||
d.tested_rules > i {
raise Internal("internal shadow witness mismatch")
}
d.rule_id
}
}
let coverage = if reachable_witness is None {
Shadowed
} else if blocked_witness is Some(_) {
Partial
} else {
Reachable
}
reports.push({
rule_id: rule.id,
coverage,
reachable_witness,
blocked_witness,
blocked_by,
})
}
reports
}