///|
/// Kind of deterministic replay mismatch.
pub(all) enum ReplayIssueKind {
PartIdentifier
StepCount
FeatureIdentifier
DeviceIdentifier
Strategy
Direction
Uncertainty
Coverage
Capability
} derive(Eq, Debug)
///|
/// One replay mismatch with an index and stable message.
pub(all) struct ReplayIssue {
kind : ReplayIssueKind
index : Int
message : String
}
///|
/// Result of comparing an expected and actual plan.
pub(all) struct ReplayResult {
expected_part_id : String
actual_part_id : String
expected_steps : Int
actual_steps : Int
matches : Bool
issues : Array[ReplayIssue]
}
///|
/// Compare two plans field by field.
pub fn compare_plans(
expected : MeasurementPlan,
actual : MeasurementPlan,
) -> ReplayResult {
let issues = []
if expected.part_id != actual.part_id {
issues.push({
kind: ReplayIssueKind::PartIdentifier,
index: -1,
message: "part identifier differs",
})
}
if expected.steps.length() != actual.steps.length() {
issues.push({
kind: ReplayIssueKind::StepCount,
index: -1,
message: "step count differs",
})
}
let common = if expected.steps.length() < actual.steps.length() {
expected.steps.length()
} else {
actual.steps.length()
}
for i in 0.. ReplayResult {
let rebuilt = MeasurementPlan::{
part_id: plan.part_id,
steps: plan.steps,
summary: plan.summary,
}
compare_plans(plan, rebuilt)
}
///|
/// Return the number of replay issues.
pub fn replay_issue_count(result : ReplayResult) -> Int {
result.issues.length()
}
///|
/// Return whether a replay has no differences.
pub fn replay_is_idempotent(plan : MeasurementPlan) -> Bool {
replay_plan(plan).matches
}
///|
/// Return whether a replay contains a given issue kind.
pub fn replay_has_issue(result : ReplayResult, kind : ReplayIssueKind) -> Bool {
let mut found = false
for issue in result.issues {
if issue.kind == kind {
found = true
}
}
found
}
///|
/// Return stable labels for replay issue kinds.
pub fn replay_issue_kind_text(kind : ReplayIssueKind) -> String {
match kind {
PartIdentifier => "part-id"
StepCount => "step-count"
FeatureIdentifier => "feature-id"
DeviceIdentifier => "device-id"
Strategy => "strategy"
Direction => "direction"
Uncertainty => "uncertainty"
Coverage => "coverage"
Capability => "capability"
}
}
///|
/// Render replay issues as stable text.
pub fn render_replay_issues(result : ReplayResult) -> String {
let mut output = ""
for issue in result.issues {
output = output +
replay_issue_kind_text(issue.kind) +
"[" +
issue.index.to_string() +
"] " +
issue.message +
"\n"
}
output
}