diff --git a/Tests/SwiftModelTests/DriveQoSDiagnosticsTests.swift b/Tests/SwiftModelTests/DriveQoSDiagnosticsTests.swift new file mode 100644 index 0000000..68aada6 --- /dev/null +++ b/Tests/SwiftModelTests/DriveQoSDiagnosticsTests.swift @@ -0,0 +1,82 @@ +import Testing +import Foundation +import ConcurrencyExtras +@testable import SwiftModel + +#if canImport(Darwin) +import Dispatch + +// TEMPORARY DIAGNOSTIC — prints, for CI log comparison, where drive jobs and +// their yielded continuations actually run (QoS + dispatch queue label), and the +// timing of the settle() fixpoint relative to the children's completion. +// Same shape as ExecutorDrainSettleTests.settleIsLoadIndependentAcrossChildTasks. + +private struct Sample: Sendable, CustomStringConvertible { + let child: Int, step: String, qos: UInt32, queue: String, tNs: UInt64 + var description: String { "child\(child) \(step) qos=\(qos) queue=\(queue) t=\(tNs / 1000)µs" } +} +private let samples = LockIsolated<[Sample]>([]) +private let t0 = LockIsolated(0) +private func now() -> UInt64 { DispatchTime.now().uptimeNanoseconds &- t0.value } +private func record(_ child: Int, _ step: String) { + let label = String(cString: __dispatch_queue_get_label(nil)) + samples.withValue { $0.append(Sample(child: child, step: step, qos: qos_class_self().rawValue, queue: label, tNs: now())) } +} + +@Model private struct DiagItem: Sendable, Identifiable { + let id: Int + var done = false + func onActivate() { + node.task { + record(id, "start") + for i in 0..<6 { await Task.yield(); record(id, "yield\(i)") } + done = true + record(id, "done") + } + } +} +@Model private struct DiagParent: Sendable { + var items: [DiagItem] = [] +} + +@Sendable private func underCPULoad(_ body: () async -> T) async -> T { + let stop = NSLock() + nonisolated(unsafe) var running = true + for _ in 0..