From f480953fd32974b6583a9b8b070c8327b43ae64c Mon Sep 17 00:00:00 2001 From: Alexander Smarus Date: Tue, 26 May 2020 18:26:23 +0300 Subject: [PATCH] Add test for main dispatch queue processing in CFRunLoop This ensures CFRunLoop correctly serves main dispatch queue. Due to event specifics on Windows there was possibility to break RunLoop making it think that main queue always has pending work. The issue is adressed in https://github.com/apple/swift-corelibs-libdispatch/pull/542. --- Tests/Foundation/Tests/TestRunLoop.swift | 36 ++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/Tests/Foundation/Tests/TestRunLoop.swift b/Tests/Foundation/Tests/TestRunLoop.swift index 2613f96659..1797374ba9 100644 --- a/Tests/Foundation/Tests/TestRunLoop.swift +++ b/Tests/Foundation/Tests/TestRunLoop.swift @@ -125,6 +125,41 @@ class TestRunLoop : XCTestCase { XCTAssertTrue(didDeallocate) } + func test_mainDispatchQueueCallout() { + let runLoop = RunLoop.current + + var asyncExecuted = false + DispatchQueue.main.async { + asyncExecuted = true + } + + // RunLoop should service main queue + _ = runLoop.run(mode: .default, before: Date(timeIntervalSinceNow: 2)) + XCTAssertTrue(asyncExecuted, "Main queue async code should be executed") + + asyncExecuted = false + DispatchQueue.main.async { + asyncExecuted = true + } + + // Second run to be sure RunLoop will not stuck + _ = runLoop.run(mode: .default, before: Date(timeIntervalSinceNow: 2)) + XCTAssertTrue(asyncExecuted, "Main queue async code should be executed") + + var timerFired = false + let dummyTimer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false) { _ in + timerFired = true + } + runLoop.add(dummyTimer, forMode: .default) + + // At this moment RunLoop has no work to do except waiting for timer. + // But RunLoop will exit prematurely if event from previous async calls + // got stuck in wrong state. + _ = runLoop.run(mode: .default, before: Date(timeIntervalSinceNow: 2)) + + XCTAssertTrue(timerFired, "Time should fire already") + } + static var allTests : [(String, (TestRunLoop) -> () throws -> Void)] { return [ ("test_constants", test_constants), @@ -134,6 +169,7 @@ class TestRunLoop : XCTestCase { ("test_runLoopLimitDate", test_runLoopLimitDate), ("test_runLoopPoll", test_runLoopPoll), ("test_addingRemovingPorts", test_addingRemovingPorts), + ("test_mainDispatchQueueCallout", test_mainDispatchQueueCallout) ] } }