import Foundation import Testing @testable import Workouts /// Pins the live-mirror staleness ordering (`LiveProgress.isNewer`): the shared per-run /// version sequence decides, and the phase anchor breaks ties. The tie-break exists /// because the sequence isn't collision-free — each side catches its counter up only from /// frames it *receives*, so after a lost frame both devices can mint the same version /// independently, and the later wall-clock action must win. Equal version *and* equal /// anchor is the same frame redelivered, which must NOT rank as newer (a redelivery would /// otherwise re-jump the follower's page). struct LiveProgressOrderingTests { private static let t0 = Date(timeIntervalSince1970: 1_700_000_000) private func frame(version: Int, start: Date) -> LiveProgress { LiveProgress(workoutID: "W", logID: "L", exerciseName: "Bench", phase: .work, setIndex: 0, setCount: 3, detail: "8 reps", phaseStart: start, phaseEnd: nil, version: version) } @Test func higherVersionWinsRegardlessOfAnchor() { let older = frame(version: 3, start: Self.t0.addingTimeInterval(10)) let newer = frame(version: 4, start: Self.t0) // earlier anchor, higher version #expect(newer.isNewer(than: older)) #expect(!older.isNewer(than: newer)) } @Test func collidedVersionsTieBreakOnAnchor() { let phoneFrame = frame(version: 4, start: Self.t0) let watchFrame = frame(version: 4, start: Self.t0.addingTimeInterval(2)) #expect(watchFrame.isNewer(than: phoneFrame)) #expect(!phoneFrame.isNewer(than: watchFrame)) } @Test func redeliveryIsNotNewer() { let sent = frame(version: 4, start: Self.t0) #expect(!sent.isNewer(than: sent)) } @Test func versionAndStartOverloadMatchesFrameOverload() { let f = frame(version: 4, start: Self.t0) #expect(f.isNewer(thanVersion: 3, start: Self.t0.addingTimeInterval(99))) #expect(f.isNewer(thanVersion: 4, start: Self.t0.addingTimeInterval(-1))) #expect(!f.isNewer(thanVersion: 4, start: Self.t0)) #expect(!f.isNewer(thanVersion: 5, start: .distantPast)) } }