Files
gronodandDevin <158243242+devin-ai-integration[bot]@users.noreply.github.com> ef56cdd7d4 Fix M5 regressions and Stage 3 chartread prompt delivery (#50, #52).
Hardens ProcessManager finalisation, ensures stdout/stderr pipe write-ends
close after spawn, sets termination handlers before run(), and fixes the
runCaptured continuation hand-off for fast exits. Resolves the Stage 3
prompt stream being dropped and the handheld fixture UI not advancing,
unskips and repairs the handheld UI test, and fixes averaging panel
accessibility. Includes the selected #52 profile, verification, and
artefact-gating fixes.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-09 13:25:39 +01:00

106 lines
3.3 KiB
Swift

import Foundation
import Testing
@testable import ICCeryCore
@Suite("DriftAlert")
struct DriftAlertTests {
@Test("No alert with fewer than two poor results")
func notEnough() {
let records = [
record(avg: 4.0, at: 1000)
]
#expect(DriftAlert.compute(from: records) == nil)
}
@Test("Alert on two poor results one hour apart")
func oneHourApart() {
let records = [
record(avg: 4.0, at: 1000),
record(avg: 5.0, at: 4600)
]
#expect(DriftAlert.compute(from: records) != nil)
}
@Test("No alert if same day and under one hour")
func sameDayUnderHour() {
let records = [
record(avg: 4.0, at: 1000),
record(avg: 5.0, at: 2000)
]
#expect(DriftAlert.compute(from: records) == nil)
}
@Test("Alert on distinct days")
func distinctDays() {
let day1 = record(avg: 4.0, at: 0)
let day2 = record(avg: 5.0, at: 86400 + 1000)
#expect(DriftAlert.compute(from: [day1, day2]) != nil)
}
@Test("Non-poor records do not trigger")
func nonPoor() {
let records = [
record(avg: 1.0, at: 0),
record(avg: 1.5, at: 86400)
]
#expect(DriftAlert.compute(from: records) == nil)
}
@Test("Non-poor records break the consecutive poor run")
func nonPoorBreaksRun() {
let records = [
record(avg: 4.0, at: 0), // poor
record(avg: 4.5, at: 86400), // poor, far apart
record(avg: 1.0, at: 90000), // good — breaks the run
record(avg: 4.0, at: 92000) // poor, recent but close to previous poor
]
#expect(DriftAlert.compute(from: records) == nil)
}
@Test("Only the final consecutive poor run is considered")
func onlySuffixRun() {
let records = [
record(avg: 4.0, at: 0), // poor
record(avg: 4.5, at: 18000), // poor, > 1h from first
record(avg: 1.0, at: 20000), // good — breaks the run
record(avg: 4.0, at: 25000), // poor
record(avg: 4.5, at: 26000) // poor, < 1h and same day
]
#expect(DriftAlert.compute(from: records) == nil)
}
@Test("Final consecutive poor run alerts when far apart")
func suffixRunAlerts() {
let records = [
record(avg: 1.0, at: 0), // good
record(avg: 4.0, at: 1000), // poor
record(avg: 4.5, at: 4600) // poor, 1h after previous
]
#expect(DriftAlert.compute(from: records) != nil)
}
@Test("A single final poor record after good records does not alert")
func singleFinalPoor() {
let records = [
record(avg: 1.0, at: 0),
record(avg: 4.0, at: 86400)
]
#expect(DriftAlert.compute(from: records) == nil)
}
private func record(avg: Double, at offset: TimeInterval) -> VerificationRecord {
VerificationRecord(
id: "vr-\(Int(offset))",
profileName: "p",
printerName: "",
avgDE: avg,
maxDE: avg,
rmsDE: avg,
patchCount: 1,
status: VerificationStatus.from(avgDE: avg),
timestamp: Date(timeIntervalSince1970: offset)
)
}
}