import Testing import Foundation @testable import FlixyPlayback @Suite("Rückler-Buchführung") struct StallLedgerTests { /// Der Fall, wegen dem es den Typ gibt. /// /// Zehn Rückler à dreißig Sekunden lösten beim alten Wachhund nichts aus, /// weil er sich bei jedem Erholen zurücksetzte. Hier muss sichtbar /// werden, dass die Wiedergabe unbrauchbar ist. @Test("Viele kurze Rückler bleiben sichtbar") func manyShortStallsAreVisible() { var ledger = StallLedger(window: .seconds(180)) // Alle 20 s ein Rückler von 5 s, drei Minuten lang. for step in 1...9 { ledger.record(.init(endedAt: .seconds(step * 20), length: .seconds(5))) } let now = Duration.seconds(180) #expect(ledger.count(at: now) == 9) // 45 s Warten in 180 s Fenster. #expect(ledger.share(at: now) > 0.2) #expect(ledger.share(at: now) < 0.3) } @Test("Was aus dem Fenster fällt, zählt nicht mehr") func oldEpisodesFallOut() { var ledger = StallLedger(window: .seconds(180)) ledger.record(.init(endedAt: .seconds(10), length: .seconds(30))) #expect(ledger.count(at: .seconds(60)) == 1) // Weit hinter dem Fenster: vergessen. #expect(ledger.count(at: .seconds(300)) == 0) #expect(ledger.share(at: .seconds(300)) == 0) } /// Am Anfang ist das Fenster noch nicht voll — dann gegen die tatsächlich /// vergangene Zeit rechnen, sonst sieht ein früher Rückler harmlos aus. @Test("Früh im Film zählt die vergangene Zeit, nicht das ganze Fenster") func earlyStallsAreNotDiluted() { var ledger = StallLedger(window: .seconds(180)) ledger.record(.init(endedAt: .seconds(20), length: .seconds(5))) let share = ledger.share(at: .seconds(20)) // 5 s von 20 s, nicht 5 s von 180 s. #expect(share > 0.2) #expect(share < 0.3) } @Test("Der laufende Rückler zählt mit") func ongoingStallCounts() { var ledger = StallLedger(window: .seconds(180)) ledger.record(.init(endedAt: .seconds(60), length: .seconds(10))) let without = ledger.share(at: .seconds(180)) let with = ledger.share(at: .seconds(180), ongoing: .seconds(20)) #expect(with > without) } /// Ein einzelner langer Rückler ist eine andere Aussage als viele kurze. @Test("Der längste Einzelfall lässt sich getrennt ablesen") func longestIsSeparate() { var ledger = StallLedger(window: .seconds(180)) ledger.record(.init(endedAt: .seconds(30), length: .seconds(2))) ledger.record(.init(endedAt: .seconds(60), length: .seconds(18))) ledger.record(.init(endedAt: .seconds(90), length: .seconds(3))) #expect(ledger.longest(at: .seconds(120)) == .seconds(18)) #expect(ledger.count(at: .seconds(120)) == 3) } @Test("Eine ruhige Wiedergabe meldet nichts") func quietPlaybackIsQuiet() { let ledger = StallLedger() #expect(ledger.count(at: .seconds(600)) == 0) #expect(ledger.share(at: .seconds(600)) == 0) #expect(ledger.longest(at: .seconds(600)) == .zero) } @Test("Der Anteil übersteigt nie eins") func shareIsBounded() { var ledger = StallLedger(window: .seconds(60)) // Absurd: mehr Wartezeit als Fenster. ledger.record(.init(endedAt: .seconds(30), length: .seconds(200))) #expect(ledger.share(at: .seconds(60)) == 1) } }