///|
fn audit_suite(
machine : Machine,
words : Array[Value],
) -> Value raise InputError {
if words.length() > 4096 {
raise InputError("suite exceeds 4096 tests")
}
let covered : Map[String, Bool] = Map([])
let rejected : Array[Value] = []
let mut steps = 0
for index, value in words {
let sequence = word(value)
let mut state = machine.initial
for i, symbol in sequence {
steps += 1
if steps > 1000000 {
raise InputError("suite exceeds 1000000 total steps")
}
let key = edge_key(state, symbol)
match machine.edges.get(key) {
None => {
rejected.push(
record([
("test", Number(index.to_double())),
("rejected_at", Number(i.to_double())),
]),
)
break
}
Some(edge) => {
covered[key] = true
state = edge.target
}
}
}
}
let (reached, _) = reachable(machine)
let missing : Array[Value] = []
let mut total = 0
for state in reached {
for symbol in machine.alphabet {
let key = edge_key(state, symbol)
if machine.edges.contains(key) {
total += 1
if !covered.contains(key) {
missing.push(
record([
("state", String(machine.states[state])),
("input", String(symbol)),
]),
)
}
}
}
}
record([
("complete", Bool(missing.is_empty())),
("reachable_transitions", Number(total.to_double())),
("covered_transitions", Number(covered.length().to_double())),
("uncovered", Array(missing)),
("rejected_tests", Array(rejected)),
("reset_required", Bool(true)),
])
}