// RUN: %target-run-simple-swift // REQUIRES: executable_test // REQUIRES: libdispatch import Dispatch import StdlibUnittest defer { runAllTests() } var DispatchAPI = TestSuite("DispatchAPI") DispatchAPI.test("constants") { expectEqual(2147483648, DispatchSource.ProcessEvent.exit.rawValue) expectEqual(0, DispatchData.empty.endIndex) // This is a lousy test, but really we just care that // DISPATCH_QUEUE_CONCURRENT comes through at all. _ = DispatchQueue.Attributes.concurrent } DispatchAPI.test("OS_OBJECT support") { let mainQueue = DispatchQueue.main as AnyObject expectTrue(mainQueue is DispatchQueue) // This should not be optimized out, and should succeed. expectNotNil(mainQueue as? DispatchQueue) } DispatchAPI.test("DispatchGroup creation") { let group = DispatchGroup() expectNotNil(group) } DispatchAPI.test("Dispatch sync return value") { let value = 24 let q = DispatchQueue(label: "Test") let result = q.sync() { return 24 } expectEqual(value, result) } DispatchAPI.test("dispatch_block_t conversions") { var counter = 0 let closure = { () -> Void in counter += 1 } typealias Block = @convention(block) () -> () let block = closure as Block block() expectEqual(1, counter) let closureAgain = block as () -> Void closureAgain() expectEqual(2, counter) } if #available(OSX 10.10, iOS 8.0, *) { DispatchAPI.test("dispatch_block_t identity") { let block = DispatchWorkItem(flags: .inheritQoS) { _ = 1 } DispatchQueue.main.async(execute: block) // This will trap if the block's pointer identity is not preserved. block.cancel() } } DispatchAPI.test("DispatchTime comparisons") { do { let now = DispatchTime.now() checkComparable([now, now + .milliseconds(1), .distantFuture], oracle: { return $0 < $1 ? .lt : $0 == $1 ? .eq : .gt }) } do { let now = DispatchWallTime.now() checkComparable([now, now + .milliseconds(1), .distantFuture], oracle: { return $0 < $1 ? .lt : $0 == $1 ? .eq : .gt }) } } DispatchAPI.test("DispatchTime.create") { var info = mach_timebase_info_data_t(numer: 1, denom: 1) mach_timebase_info(&info) let scales = info.numer != info.denom // Simple tests for non-overflow behavior var time = DispatchTime(uptimeNanoseconds: 0) expectEqual(time.uptimeNanoseconds, 0) time = DispatchTime(uptimeNanoseconds: 15 * NSEC_PER_SEC) expectEqual(time.uptimeNanoseconds, 15 * NSEC_PER_SEC) // On platforms where the timebase scale is not 1, the next two cases // overflow and become DISPATCH_TIME_FOREVER (UInt64.max) instead of trapping. time = DispatchTime(uptimeNanoseconds: UInt64.max - 1) expectEqual(time.uptimeNanoseconds, scales ? UInt64.max : UInt64.max - UInt64(1)) time = DispatchTime(uptimeNanoseconds: UInt64.max / 2) expectEqual(time.uptimeNanoseconds, scales ? UInt64.max : UInt64.max / 2) // UInt64.max must always be returned as UInt64.max. time = DispatchTime(uptimeNanoseconds: UInt64.max) expectEqual(time.uptimeNanoseconds, UInt64.max) } DispatchAPI.test("DispatchTime.addSubtract") { var then = DispatchTime.now() + Double.infinity expectEqual(DispatchTime.distantFuture, then) then = DispatchTime.now() + Double.nan expectEqual(DispatchTime.distantFuture, then) then = DispatchTime.now() - Double.infinity expectEqual(DispatchTime(uptimeNanoseconds: 1), then) then = DispatchTime.now() - Double.nan expectEqual(DispatchTime.distantFuture, then) } DispatchAPI.test("DispatchWallTime.addSubtract") { let distantPastRawValue = DispatchWallTime.distantFuture.rawValue - UInt64(1) var then = DispatchWallTime.now() + Double.infinity expectEqual(DispatchWallTime.distantFuture, then) then = DispatchWallTime.now() + Double.nan expectEqual(DispatchWallTime.distantFuture, then) then = DispatchWallTime.now() - Double.infinity expectEqual(distantPastRawValue, then.rawValue) then = DispatchWallTime.now() - Double.nan expectEqual(DispatchWallTime.distantFuture, then) } DispatchAPI.test("DispatchTime.uptimeNanos") { let seconds = 1 let nowMach = DispatchTime.now() let oneSecondFromNowMach = nowMach + .seconds(seconds) let nowNanos = nowMach.uptimeNanoseconds let oneSecondFromNowNanos = oneSecondFromNowMach.uptimeNanoseconds let diffNanos = oneSecondFromNowNanos - nowNanos expectEqual(NSEC_PER_SEC, diffNanos) } DispatchAPI.test("DispatchIO.initRelativePath") { let q = DispatchQueue(label: "initRelativePath queue") let chan = DispatchIO(type: .random, path: "_REL_PATH_", oflag: O_RDONLY, mode: 0, queue: q, cleanupHandler: { (error) in }) expectEqual(chan, nil) } if #available(OSX 10.13, iOS 11.0, watchOS 4.0, tvOS 11.0, *) { var block = DispatchWorkItem(qos: .unspecified, flags: .assignCurrentContext) {} DispatchAPI.test("DispatchSource.replace") { let g = DispatchGroup() let q = DispatchQueue(label: "q") let ds = DispatchSource.makeUserDataReplaceSource(queue: q) var lastValue = UInt(0) var nextValue = UInt(1) let maxValue = UInt(1 << 24) ds.setEventHandler() { let value = ds.data; expectTrue(value > lastValue) // Values must increase expectTrue((value & (value - 1)) == 0) // Must be power of two lastValue = value if value == maxValue { g.leave() } } ds.activate() g.enter() block = DispatchWorkItem(qos: .unspecified, flags: .assignCurrentContext) { ds.replace(data: nextValue) nextValue <<= 1 if nextValue <= maxValue { q.asyncAfter( deadline: DispatchTime.now() + DispatchTimeInterval.milliseconds(1), execute: block) } } q.asyncAfter( deadline: DispatchTime.now() + DispatchTimeInterval.milliseconds(1), execute: block) let result = g.wait(timeout: DispatchTime.now() + .seconds(30)) expectTrue(result == .success) } } DispatchAPI.test("DispatchTimeInterval") { // Basic tests that the correct value is stored and the == method works for i in stride(from:1, through: 100, by: 5) { expectEqual(DispatchTimeInterval.seconds(i), DispatchTimeInterval.milliseconds(i * 1000)) expectEqual(DispatchTimeInterval.milliseconds(i), DispatchTimeInterval.microseconds(i * 1000)) expectEqual(DispatchTimeInterval.microseconds(i), DispatchTimeInterval.nanoseconds(i * 1000)) } // Check some cases that used to cause arithmetic overflow when evaluating the rawValue for == var t = DispatchTimeInterval.seconds(Int.max) expectTrue(t == t) // This would crash. t = DispatchTimeInterval.seconds(-Int.max) expectTrue(t == t) // This would crash. t = DispatchTimeInterval.milliseconds(Int.max) expectTrue(t == t) // This would crash. t = DispatchTimeInterval.milliseconds(-Int.max) expectTrue(t == t) // This would crash. t = DispatchTimeInterval.microseconds(Int.max) expectTrue(t == t) // This would crash. t = DispatchTimeInterval.microseconds(-Int.max) expectTrue(t == t) // This would crash. } DispatchAPI.test("DispatchTimeInterval.never.equals") { expectTrue(DispatchTimeInterval.never == DispatchTimeInterval.never) expectTrue(DispatchTimeInterval.seconds(10) != DispatchTimeInterval.never); expectTrue(DispatchTimeInterval.never != DispatchTimeInterval.seconds(10)); expectTrue(DispatchTimeInterval.seconds(10) == DispatchTimeInterval.seconds(10)); }