use std::collections::{BTreeMap, BTreeSet};
use serde_json::Value;
use super::Outcome;
pub(super) type Outside = BTreeMap<String, bool>;
pub(super) fn tally(outside: &mut Outside, outcome: &Outcome, caught: &BTreeSet<String>) {
for test in caught {
let witnessed = outside.entry(test.clone()).or_default();
*witnessed = *witnessed || matches!(outcome, Outcome::Survived);
}
}
pub(super) fn merge(into: &mut Outside, from: Outside) {
for (test, witnessed) in from {
let into = into.entry(test).or_default();
*into = *into || witnessed;
}
}
pub(super) fn duplicates(outside: &Outside) -> Vec<String> {
outside
.iter()
.filter(|(_, witnessed)| !**witnessed)
.map(|(test, _)| test.clone())
.collect()
}
pub(super) fn duplicate(test: &str) -> String {
format!(
"{test}: every mutant it catches, the Contract catches too, so it duplicates the Contract"
)
}
pub(super) fn witnessed(outcome: &Outcome, caught: &BTreeSet<String>) -> String {
if !matches!(outcome, Outcome::Survived) || caught.is_empty() {
return String::new();
}
let tests: Vec<&str> = caught.iter().map(String::as_str).collect();
format!(", witnessed by {}", tests.join(", "))
}
pub(super) fn annotate(doc: &mut Value, caught: &[BTreeSet<String>]) {
if let Some(mutants) = doc["mutants"].as_array_mut() {
for (mutant, tests) in mutants.iter_mut().zip(caught) {
mutant["outside"] = tests.iter().cloned().collect();
}
}
}