///|
pub fn diff_scenario_matrices(
before : ScenarioMatrix,
after : ScenarioMatrix,
) -> ScenarioDiff {
let added : Array[String] = []
let removed : Array[String] = []
let regressed : Array[String] = []
let recovered : Array[String] = []
let mut unchanged = 0
let mut after_spec_index = 0
while after_spec_index < after.specs.length() {
let spec = after.specs[after_spec_index]
let mut target_index = 0
while target_index < spec.targets.length() {
let target = spec.targets[target_index]
let key = scenario_case_key(spec.id, target)
if !matrix_has_case(before, spec.id, target) {
added.push(key)
} else {
let before_passed = matrix_case_passed(before, spec.id, target)
let after_passed = matrix_case_passed(after, spec.id, target)
if before_passed && !after_passed {
regressed.push(key)
} else if !before_passed && after_passed {
recovered.push(key)
} else {
unchanged += 1
}
}
target_index += 1
}
after_spec_index += 1
}
let mut before_spec_index = 0
while before_spec_index < before.specs.length() {
let spec = before.specs[before_spec_index]
let mut target_index = 0
while target_index < spec.targets.length() {
let target = spec.targets[target_index]
if !matrix_has_case(after, spec.id, target) {
removed.push(scenario_case_key(spec.id, target))
}
target_index += 1
}
before_spec_index += 1
}
ScenarioDiff::{
added_ids: added,
removed_ids: removed,
regressed_ids: regressed,
recovered_ids: recovered,
unchanged_count: unchanged,
}
}
///|
pub fn ScenarioDiff::summary(self : ScenarioDiff) -> String {
"added=" +
self.added_ids.length().to_string() +
", removed=" +
self.removed_ids.length().to_string() +
", regressed=" +
self.regressed_ids.length().to_string() +
", recovered=" +
self.recovered_ids.length().to_string() +
", unchanged=" +
self.unchanged_count.to_string()
}
///|
pub fn ScenarioDiff::to_markdown(self : ScenarioDiff) -> String {
let mut out = "# Scenario Matrix Diff\n\n"
out = out + "- Added: " + self.added_ids.length().to_string() + "\n"
out = out + "- Removed: " + self.removed_ids.length().to_string() + "\n"
out = out + "- Regressed: " + self.regressed_ids.length().to_string() + "\n"
out = out + "- Recovered: " + self.recovered_ids.length().to_string() + "\n"
out = out + "- Unchanged: " + self.unchanged_count.to_string() + "\n\n"
out = out + diff_list("Added", self.added_ids)
out = out + diff_list("Removed", self.removed_ids)
out = out + diff_list("Regressed", self.regressed_ids)
out + diff_list("Recovered", self.recovered_ids)
}
///|
pub fn ScenarioDiff::to_json(self : ScenarioDiff) -> String {
"{\"added\":" +
string_array_json(self.added_ids) +
",\"removed\":" +
string_array_json(self.removed_ids) +
",\"regressed\":" +
string_array_json(self.regressed_ids) +
",\"recovered\":" +
string_array_json(self.recovered_ids) +
",\"unchanged\":" +
self.unchanged_count.to_string() +
"}"
}
///|
fn matrix_has_case(
matrix : ScenarioMatrix,
id : String,
target : ScenarioTarget,
) -> Bool {
let mut index = 0
while index < matrix.specs.length() {
if matrix.specs[index].id == id && matrix.specs[index].has_target(target) {
return true
}
index += 1
}
false
}
///|
fn matrix_case_passed(
matrix : ScenarioMatrix,
id : String,
target : ScenarioTarget,
) -> Bool {
match find_spec(matrix.specs, id) {
None => false
Some(spec) =>
match observation_for(matrix.observations, id, target) {
None => false
Some(observation) => observation_matches(spec, observation)
}
}
}
///|
fn find_spec(specs : Array[ScenarioSpec], id : String) -> ScenarioSpec? {
let mut index = 0
while index < specs.length() {
if specs[index].id == id {
return Some(specs[index])
}
index += 1
}
None
}
///|
fn scenario_case_key(id : String, target : ScenarioTarget) -> String {
id + "@" + target.name()
}
///|
fn diff_list(title : String, items : Array[String]) -> String {
let mut out = "## " + title + "\n\n"
if items.length() == 0 {
return out + "- None\n\n"
}
let mut index = 0
while index < items.length() {
out = out + "- `" + items[index] + "`\n"
index += 1
}
out + "\n"
}
///|
fn string_array_json(items : Array[String]) -> String {
let mut out = "["
let mut index = 0
while index < items.length() {
if index > 0 {
out = out + ","
}
out = out + "\"" + json_escape(items[index]) + "\""
index += 1
}
out + "]"
}