Files
swift-nio/Tests/NIOFoundationCompatTests/WaitSpinningRunLoopTests.swift
Johannes Weiss 2a8811acd6 EventLoopFuture.waitSpinningRunLoop() (#2985)
### Motivation:

In some (probably niche) scenarios, especially in pre-Concurrency UI
applications on Darwin, it can be useful to wait for an a value whilst
still running the current `RunLoop`. That allows the UI and other things
to work whilst we're waiting for a future to complete.

### Modifications:

- Add `NIOFoundationCompat.EventLoopFuture.waitSpinningRunLoop()`.

### Result:

Better compatibility with Cocoa.
2024-11-21 18:22:42 +00:00

65 lines
2.1 KiB
Swift

//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftNIO open source project
//
// Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//
import NIO
import NIOFoundationCompat
import XCTest
final class WaitSpinningRunLoopTests: XCTestCase {
private let loop = MultiThreadedEventLoopGroup.singleton.any()
func testPreFailedWorks() {
struct Dummy: Error {}
let future: EventLoopFuture<Never> = self.loop.makeFailedFuture(Dummy())
XCTAssertThrowsError(try future.waitSpinningRunLoop()) { error in
XCTAssert(error is Dummy)
}
}
func testPreSucceededWorks() {
let future = self.loop.makeSucceededFuture("hello")
XCTAssertEqual("hello", try future.waitSpinningRunLoop())
}
func testFailingAfterALittleWhileWorks() {
struct Dummy: Error {}
let future: EventLoopFuture<Never> = self.loop.scheduleTask(in: .milliseconds(10)) {
throw Dummy()
}.futureResult
XCTAssertThrowsError(try future.waitSpinningRunLoop()) { error in
XCTAssert(error is Dummy)
}
}
func testSucceedingAfterALittleWhileWorks() {
let future = self.loop.scheduleTask(in: .milliseconds(10)) {
"hello"
}.futureResult
XCTAssertEqual("hello", try future.waitSpinningRunLoop())
}
func testWeCanStillUseOurRunLoopWhilstBlocking() {
let promise = self.loop.makePromise(of: String.self)
let myRunLoop = RunLoop.current
let timer = Timer(timeInterval: 0.1, repeats: false) { [loop = self.loop] _ in
loop.scheduleTask(in: .microseconds(10)) {
promise.succeed("hello")
}
}
myRunLoop.add(timer, forMode: .default)
XCTAssertEqual("hello", try promise.futureResult.waitSpinningRunLoop())
}
}