Files
Jot/Carthage/Checkouts/PromiseKit/Tests/A+/0.0.0.swift
James Griffin be7b6b5881 Add PromiseKit dependency
- Added PromiseKit dependency
2018-11-15 22:12:39 -04:00

186 lines
5.6 KiB
Swift

import PromiseKit
import Dispatch
import XCTest
enum Error: Swift.Error {
case dummy // we reject with this when we don't intend to test against it
case sentinel(UInt32)
}
private let timeout: TimeInterval = 10
extension XCTestCase {
func describe(_ description: String, file: StaticString = #file, line: UInt = #line, body: () throws -> Void) {
PromiseKit.conf.Q.map = .main
do {
try body()
} catch {
XCTFail(description, file: file, line: line)
}
}
func specify(_ description: String, file: StaticString = #file, line: UInt = #line, body: ((promise: Promise<Void>, fulfill: () -> Void, reject: (Error) -> Void), XCTestExpectation) throws -> Void) {
let expectation = self.expectation(description: description)
let (pending, seal) = Promise<Void>.pending()
do {
try body((pending, { seal.fulfill(()) }, seal.reject), expectation)
waitForExpectations(timeout: timeout) { err in
if let _ = err {
XCTFail("wait failed: \(description)", file: file, line: line)
}
}
} catch {
XCTFail(description, file: file, line: line)
}
}
func testFulfilled(file: StaticString = #file, line: UInt = #line, body: @escaping (Promise<UInt32>, XCTestExpectation, UInt32) -> Void) {
testFulfilled(withExpectationCount: 1, file: file, line: line) {
body($0, $1.first!, $2)
}
}
func testRejected(file: StaticString = #file, line: UInt = #line, body: @escaping (Promise<UInt32>, XCTestExpectation, UInt32) -> Void) {
testRejected(withExpectationCount: 1, file: file, line: line) {
body($0, $1.first!, $2)
}
}
func testFulfilled(withExpectationCount: Int, file: StaticString = #file, line: UInt = #line, body: @escaping (Promise<UInt32>, [XCTestExpectation], UInt32) -> Void) {
let specify = mkspecify(withExpectationCount, file: file, line: line, body: body)
specify("already-fulfilled") { value in
return (.value(value), {})
}
specify("immediately-fulfilled") { value in
let (promise, seal) = Promise<UInt32>.pending()
return (promise, {
seal.fulfill(value)
})
}
specify("eventually-fulfilled") { value in
let (promise, seal) = Promise<UInt32>.pending()
return (promise, {
after(ticks: 5) {
seal.fulfill(value)
}
})
}
}
func testRejected(withExpectationCount: Int, file: StaticString = #file, line: UInt = #line, body: @escaping (Promise<UInt32>, [XCTestExpectation], UInt32) -> Void) {
let specify = mkspecify(withExpectationCount, file: file, line: line, body: body)
specify("already-rejected") { sentinel in
return (Promise(error: Error.sentinel(sentinel)), {})
}
specify("immediately-rejected") { sentinel in
let (promise, seal) = Promise<UInt32>.pending()
return (promise, {
seal.reject(Error.sentinel(sentinel))
})
}
specify("eventually-rejected") { sentinel in
let (promise, seal) = Promise<UInt32>.pending()
return (promise, {
after(ticks: 50) {
seal.reject(Error.sentinel(sentinel))
}
})
}
}
/////////////////////////////////////////////////////////////////////////
private func mkspecify(_ numberOfExpectations: Int, file: StaticString, line: UInt, body: @escaping (Promise<UInt32>, [XCTestExpectation], UInt32) -> Void) -> (String, _ feed: (UInt32) -> (Promise<UInt32>, () -> Void)) -> Void {
return { desc, feed in
let value = arc4random()
let (promise, executeAfter) = feed(value)
let expectations = (1...numberOfExpectations).map {
self.expectation(description: "\(desc) (\($0))")
}
body(promise, expectations, value)
executeAfter()
self.waitForExpectations(timeout: timeout) { err in
if let _ = err {
XCTFail("timed out: \(desc)", file: file, line: line)
}
}
}
}
func mkex() -> XCTestExpectation {
return expectation(description: "")
}
}
func after(ticks: Int, execute body: @escaping () -> Void) {
precondition(ticks > 0)
var ticks = ticks
func f() {
DispatchQueue.main.async {
ticks -= 1
if ticks == 0 {
body()
} else {
f()
}
}
}
f()
}
extension Promise {
func test(onFulfilled: @escaping () -> Void, onRejected: @escaping () -> Void) {
tap { result in
switch result {
case .fulfilled:
onFulfilled()
case .rejected:
onRejected()
}
}.silenceWarning()
}
}
prefix func ++(a: inout Int) -> Int {
a += 1
return a
}
extension Promise {
func silenceWarning() {}
}
#if os(Linux)
import func Glibc.random
func arc4random() -> UInt32 {
return UInt32(random())
}
extension XCTestExpectation {
func fulfill() {
fulfill(#file, line: #line)
}
}
extension XCTestCase {
func wait(for: [XCTestExpectation], timeout: TimeInterval, file: StaticString = #file, line: UInt = #line) {
#if !(swift(>=4.0) && !swift(>=4.1))
let line = Int(line)
#endif
waitForExpectations(timeout: timeout, file: file, line: line)
}
}
#endif