mirror of
https://github.com/pointfreeco/swift-composable-architecture.git
synced 2025-12-24 12:14:25 +01:00
Fix ordering of simultaneous work in test scheduler. (#94)
* Fix ordering of simultaneous work in test scheduler. * clean up * clean up * UInt
This commit is contained in:
@@ -5,9 +5,10 @@ import Foundation
|
||||
public final class TestScheduler<SchedulerTimeType, SchedulerOptions>: Scheduler
|
||||
where SchedulerTimeType: Strideable, SchedulerTimeType.Stride: SchedulerTimeIntervalConvertible {
|
||||
|
||||
private var lastId: UInt = 0
|
||||
public let minimumTolerance: SchedulerTimeType.Stride = .zero
|
||||
public private(set) var now: SchedulerTimeType
|
||||
private var scheduled: [(id: UUID, date: SchedulerTimeType, action: () -> Void)] = []
|
||||
private var scheduled: [(id: UInt, date: SchedulerTimeType, action: () -> Void)] = []
|
||||
|
||||
/// Creates a test scheduler with the given date.
|
||||
///
|
||||
@@ -20,11 +21,7 @@ where SchedulerTimeType: Strideable, SchedulerTimeType.Stride: SchedulerTimeInte
|
||||
///
|
||||
/// - Parameter stride: A stride.
|
||||
public func advance(by stride: SchedulerTimeType.Stride = .zero) {
|
||||
self.scheduled = self.scheduled
|
||||
// NB: Stabilizes sort via offset.
|
||||
.enumerated()
|
||||
.sorted(by: { $0.element.date < $1.element.date || $0.offset < $1.offset })
|
||||
.map { $0.element }
|
||||
self.scheduled.sort { $0.date < $1.date || $0.id < $1.id }
|
||||
|
||||
guard
|
||||
let nextDate = self.scheduled.first?.date,
|
||||
@@ -59,17 +56,17 @@ where SchedulerTimeType: Strideable, SchedulerTimeType.Stride: SchedulerTimeInte
|
||||
options _: SchedulerOptions?,
|
||||
_ action: @escaping () -> Void
|
||||
) -> Cancellable {
|
||||
let id = self.nextId()
|
||||
|
||||
let id = UUID()
|
||||
|
||||
func scheduleAction(_ date: SchedulerTimeType) -> () -> Void {
|
||||
func scheduleAction(for date: SchedulerTimeType) -> () -> Void {
|
||||
return { [weak self] in
|
||||
action()
|
||||
self?.scheduled.append((id, date, scheduleAction(date.advanced(by: interval))))
|
||||
let nextDate = date.advanced(by: interval)
|
||||
self?.scheduled.append((id, nextDate, scheduleAction(for: nextDate)))
|
||||
}
|
||||
}
|
||||
|
||||
self.scheduled.append((id, date, scheduleAction(date.advanced(by: interval))))
|
||||
self.scheduled.append((id, date, scheduleAction(for: date)))
|
||||
|
||||
return AnyCancellable { [weak self] in
|
||||
self?.scheduled.removeAll(where: { $0.id == id })
|
||||
@@ -82,11 +79,16 @@ where SchedulerTimeType: Strideable, SchedulerTimeType.Stride: SchedulerTimeInte
|
||||
options _: SchedulerOptions?,
|
||||
_ action: @escaping () -> Void
|
||||
) {
|
||||
self.scheduled.append((UUID(), date, action))
|
||||
self.scheduled.append((self.nextId(), date, action))
|
||||
}
|
||||
|
||||
public func schedule(options _: SchedulerOptions?, _ action: @escaping () -> Void) {
|
||||
self.scheduled.append((UUID(), self.now, action))
|
||||
self.scheduled.append((self.nextId(), self.now, action))
|
||||
}
|
||||
|
||||
private func nextId() -> UInt {
|
||||
self.lastId += 1
|
||||
return self.lastId
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ import ComposableArchitecture
|
||||
import XCTest
|
||||
|
||||
final class ComposableArchitectureTests: XCTestCase {
|
||||
var cancellables: Set<AnyCancellable> = []
|
||||
|
||||
func testScheduling() {
|
||||
enum CounterAction: Equatable {
|
||||
case incrAndSquareLater
|
||||
@@ -60,6 +62,24 @@ final class ComposableArchitectureTests: XCTestCase {
|
||||
)
|
||||
}
|
||||
|
||||
func testSimultaneousWorkOrdering() {
|
||||
let testScheduler = TestScheduler<DispatchQueue.SchedulerTimeType, DispatchQueue.SchedulerOptions>(
|
||||
now: .init(.init(uptimeNanoseconds: 1))
|
||||
)
|
||||
|
||||
var values: [Int] = []
|
||||
testScheduler.schedule(after: testScheduler.now, interval: 1) { values.append(1) }
|
||||
.store(in: &self.cancellables)
|
||||
testScheduler.schedule(after: testScheduler.now, interval: 2) { values.append(42) }
|
||||
.store(in: &self.cancellables)
|
||||
|
||||
XCTAssertEqual(values, [])
|
||||
testScheduler.advance()
|
||||
XCTAssertEqual(values, [1, 42])
|
||||
testScheduler.advance(by: 2)
|
||||
XCTAssertEqual(values, [1, 42, 1, 1, 42])
|
||||
}
|
||||
|
||||
func testLongLivingEffects() {
|
||||
typealias Environment = (
|
||||
startEffect: Effect<Void, Never>,
|
||||
|
||||
@@ -103,8 +103,8 @@ final class TimerTests: XCTestCase {
|
||||
|
||||
scheduler.run()
|
||||
|
||||
XCTAssertEqual(count2, 14)
|
||||
XCTAssertEqual(count3, 9)
|
||||
XCTAssertEqual(count2, 15)
|
||||
XCTAssertEqual(count3, 10)
|
||||
}
|
||||
|
||||
func testTimerCompletion() {
|
||||
|
||||
Reference in New Issue
Block a user