mirror of
https://github.com/samsonjs/AsyncMonitor.git
synced 2026-03-25 08:25:47 +00:00
111 lines
3.5 KiB
Swift
111 lines
3.5 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))
|
|
}
|
|
|
|
@Test func equatable() throws {
|
|
let subject = AsyncMonitor(sequence: AsyncStream.just(42)) { _ in }
|
|
#expect(subject == subject)
|
|
#expect(subject != AsyncMonitor(sequence: AsyncStream.just(42)) { _ in })
|
|
}
|
|
|
|
@Test func hashable() throws {
|
|
let subjects = (1...100).map { _ in
|
|
AsyncMonitor(sequence: AsyncStream.just(42)) { _ in }
|
|
}
|
|
var hashValues: Set<Int> = []
|
|
for subject in subjects {
|
|
hashValues.insert(subject.hashValue)
|
|
}
|
|
#expect(hashValues.count == subjects.count)
|
|
}
|
|
}
|