AsyncMonitor/Tests/AsyncMonitorTests/AsyncMonitorTests.swift

86 lines
2.7 KiB
Swift

import Foundation
import Testing
@testable import AsyncMonitor
class AsyncMonitorTests {
let center = NotificationCenter()
let name = Notification.Name("a random notification")
private var subject: AsyncMonitor?
@Test func callsBlockWhenNotificationsArePosted() async throws {
await withCheckedContinuation { [center, name] continuation in
subject = center.notifications(named: name).map(\.name).monitor { receivedName in
#expect(name == receivedName)
continuation.resume()
}
Task {
center.post(name: name, object: nil)
}
}
}
@Test func doesNotCallBlockWhenOtherNotificationsArePosted() async throws {
subject = center.notifications(named: name).map(\.name).monitor { receivedName in
Issue.record("Called for irrelevant notification \(receivedName)")
}
Task { [center] in
center.post(name: Notification.Name("something else"), object: nil)
}
try await Task.sleep(for: .milliseconds(10))
}
@Test @MainActor func stopsCallingBlockWhenDeallocated() async throws {
subject = center.notifications(named: name).map(\.name).monitor { _ in
Issue.record("Called after deallocation")
}
Task { @MainActor in
subject = nil
center.post(name: name, object: nil)
}
try await Task.sleep(for: .milliseconds(10))
}
class Owner {
let deinitHook: () -> Void
private var cancellable: (any AsyncCancellable)?
init(center: NotificationCenter, deinitHook: @escaping () -> Void) {
self.deinitHook = deinitHook
let name = Notification.Name("irrelevant name")
cancellable = center.notifications(named: name).map(\.name)
.monitor(context: self) { _, _ in }
}
deinit {
deinitHook()
}
}
private var owner: Owner?
@Test(.timeLimit(.minutes(1))) func doesNotCreateReferenceCyclesWithContext() async throws {
await withCheckedContinuation { continuation in
self.owner = Owner(center: center) {
continuation.resume()
}
self.owner = nil
}
}
@Test func stopsCallingBlockWhenContextIsDeallocated() async throws {
var context: NSObject? = NSObject()
subject = center.notifications(named: name).map(\.name)
.monitor(context: context!) { context, receivedName in
Issue.record("Called after context was deallocated")
}
context = nil
Task { [center, name] in
center.post(name: name, object: nil)
}
try await Task.sleep(for: .milliseconds(10))
}
}