//===----------------------------------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// @_exported import XCTest // Clang module import CoreGraphics /// Returns the current test case, so we can use free functions instead of methods for the overlay. @_silgen_name("_XCTCurrentTestCaseBridge") func _XCTCurrentTestCaseBridge() -> XCTestCase // --- Failure Formatting --- /// Register the failure, expected or unexpected, of the current test case. func _XCTRegisterFailure(expected: Bool, _ condition: String, @autoclosure _ message: () -> String, _ file: StaticString, _ line: UInt) -> Void { // Call the real _XCTFailureHandler. let test = _XCTCurrentTestCaseBridge() _XCTPreformattedFailureHandler(test, expected, file.description, line, condition, message()) } /// Produce a failure description for the given assertion type. func _XCTFailureDescription(assertionType: _XCTAssertionType, _ formatIndex: UInt, _ expressionStrings: CVarArg...) -> String { // In order to avoid revlock/submission issues between XCTest and the Swift XCTest overlay, // we are using the convention with _XCTFailureFormat that (formatIndex >= 100) should be // treated just like (formatIndex - 100), but WITHOUT the expression strings. (Swift can't // stringify the expressions, only their values.) This way we don't have to introduce a new // BOOL parameter to this semi-internal function and coordinate that across builds. // // Since there's a single bottleneck in the overlay where we invoke _XCTFailureFormat, just // add the formatIndex adjustment there rather than in all of the individual calls to this // function. return String(format: _XCTFailureFormat(assertionType, formatIndex + 100), arguments: expressionStrings) } // --- Exception Support --- @_silgen_name("_XCTRunThrowableBlockBridge") func _XCTRunThrowableBlockBridge(@noescape _: @convention(block) () -> Void) -> NSDictionary /// The Swift-style result of evaluating a block which may throw an exception. enum _XCTThrowableBlockResult { case success case failedWithError(error: ErrorProtocol) case failedWithException(className: String, name: String, reason: String) case failedWithUnknownException } /// Asks some Objective-C code to evaluate a block which may throw an exception or error, /// and if it does consume the exception and return information about it. func _XCTRunThrowableBlock(@noescape block: () throws -> Void) -> _XCTThrowableBlockResult { var blockErrorOptional: ErrorProtocol? let d = _XCTRunThrowableBlockBridge({ do { try block() } catch { blockErrorOptional = error } }) if let blockError = blockErrorOptional { return .failedWithError(error: blockError) } else if d.count > 0 { let t: String = d["type"] as! String if t == "objc" { return .failedWithException( className: d["className"] as! String, name: d["name"] as! String, reason: d["reason"] as! String) } else { return .failedWithUnknownException } } else { return .success } } // --- Supported Assertions --- public func XCTFail(message: String = "", file: StaticString = #file, line: UInt = #line) -> Void { let assertionType = _XCTAssertionType.fail _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, "" as NSString), message, file, line) } public func XCTAssertNil(@autoclosure expression: () throws -> Any?, @autoclosure _ message: () -> String = "", file: StaticString = #file, line: UInt = #line) -> Void { let assertionType = _XCTAssertionType.`nil` // evaluate the expression exactly once var expressionValueOptional: Any? let result = _XCTRunThrowableBlock { expressionValueOptional = try expression() } switch result { case .success: // test both Optional and value to treat .none and nil as synonymous var passed: Bool var expressionValueStr: String = "nil" if let expressionValueUnwrapped = expressionValueOptional { passed = false expressionValueStr = "\(expressionValueUnwrapped)" } else { passed = true } if !passed { // TODO: @auto_string expression _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionValueStr as NSString), message, file, line) } case .failedWithError(let error): _XCTRegisterFailure(false, "XCTAssertNil failed: threw error \"\(error)\"", message, file, line) case .failedWithException(_, _, let reason): _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line) case .failedWithUnknownException: _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line) } } public func XCTAssertNotNil(@autoclosure expression: () throws -> Any?, @autoclosure _ message: () -> String = "", file: StaticString = #file, line: UInt = #line) -> Void { let assertionType = _XCTAssertionType.notNil // evaluate the expression exactly once var expressionValueOptional: Any? let result = _XCTRunThrowableBlock { expressionValueOptional = try expression() } switch result { case .success: // test both Optional and value to treat .none and nil as synonymous var passed: Bool var expressionValueStr: String = "nil" if let expressionValueUnwrapped = expressionValueOptional { passed = true expressionValueStr = "\(expressionValueUnwrapped)" } else { passed = false } if !passed { // TODO: @auto_string expression _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionValueStr as NSString), message, file, line) } case .failedWithError(let error): _XCTRegisterFailure(false, "XCTAssertNotNil failed: threw error \"\(error)\"", message, file, line) case .failedWithException(_, _, let reason): _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line) case .failedWithUnknownException: _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line) } } public func XCTAssert(@autoclosure expression: () throws -> Boolean, @autoclosure _ message: () -> String = "", file: StaticString = #file, line: UInt = #line) -> Void { // XCTAssert is just a cover for XCTAssertTrue. XCTAssertTrue(expression, message, file: file, line: line) } public func XCTAssertTrue(@autoclosure expression: () throws -> Boolean, @autoclosure _ message: () -> String = "", file: StaticString = #file, line: UInt = #line) -> Void { let assertionType = _XCTAssertionType.`true` // evaluate the expression exactly once var expressionValueOptional: Bool? let result = _XCTRunThrowableBlock { expressionValueOptional = try expression().boolValue } switch result { case .success: let expressionValue = expressionValueOptional! if !expressionValue { // TODO: @auto_string expression _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0), message, file, line) } case .failedWithError(let error): _XCTRegisterFailure(false, "XCTAssertTrue failed: threw error \"\(error)\"", message, file, line) case .failedWithException(_, _, let reason): _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line) case .failedWithUnknownException: _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line) } } public func XCTAssertFalse(@autoclosure expression: () throws -> Boolean, @autoclosure _ message: () -> String = "", file: StaticString = #file, line: UInt = #line) -> Void { let assertionType = _XCTAssertionType.`false` // evaluate the expression exactly once var expressionValueOptional: Bool? let result = _XCTRunThrowableBlock { expressionValueOptional = try expression().boolValue } switch result { case .success: let expressionValue = expressionValueOptional! if expressionValue { // TODO: @auto_string expression _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0), message, file, line) } case .failedWithError(let error): _XCTRegisterFailure(false, "XCTAssertFalse failed: threw error \"\(error)\"", message, file, line) case .failedWithException(_, _, let reason): _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line) case .failedWithUnknownException: _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line) } } public func XCTAssertEqual(@autoclosure expression1: () throws -> T?, @autoclosure _ expression2: () throws -> T?, @autoclosure _ message: () -> String = "", file: StaticString = #file, line: UInt = #line) -> Void { let assertionType = _XCTAssertionType.equal // evaluate each expression exactly once var expressionValue1Optional: T? var expressionValue2Optional: T? let result = _XCTRunThrowableBlock { expressionValue1Optional = try expression1() expressionValue2Optional = try expression2() } switch result { case .success: if expressionValue1Optional != expressionValue2Optional { // TODO: @auto_string expression1 // TODO: @auto_string expression2 let expressionValueStr1 = "\(expressionValue1Optional)" let expressionValueStr2 = "\(expressionValue2Optional)" _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionValueStr1 as NSString, expressionValueStr2 as NSString), message, file, line) } case .failedWithError(let error): _XCTRegisterFailure(false, "XCTAssertEqual failed: threw error \"\(error)\"", message, file, line) case .failedWithException(_, _, let reason): _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line) case .failedWithUnknownException: _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line) } } // FIXME: Due to we need overrides of XCTAssertEqual for: // ContiguousArray // ArraySlice // Array // Dictionary public func XCTAssertEqual(@autoclosure expression1: () throws -> ArraySlice, @autoclosure _ expression2: () throws -> ArraySlice, @autoclosure _ message: () -> String = "", file: StaticString = #file, line: UInt = #line) -> Void { let assertionType = _XCTAssertionType.equal // evaluate each expression exactly once var expressionValue1Optional: ArraySlice? var expressionValue2Optional: ArraySlice? let result = _XCTRunThrowableBlock { expressionValue1Optional = try expression1() expressionValue2Optional = try expression2() } switch result { case .success: let expressionValue1: ArraySlice = expressionValue1Optional! let expressionValue2: ArraySlice = expressionValue2Optional! if expressionValue1 != expressionValue2 { // TODO: @auto_string expression1 // TODO: @auto_string expression2 let expressionValueStr1 = "\(expressionValue1)" let expressionValueStr2 = "\(expressionValue2)" _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionValueStr1 as NSString, expressionValueStr2 as NSString), message, file, line) } case .failedWithError(let error): _XCTRegisterFailure(false, "XCTAssertEqual failed: threw error \"\(error)\"", message, file, line) case .failedWithException(_, _, let reason): _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line) case .failedWithUnknownException: _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line) } } public func XCTAssertEqual(@autoclosure expression1: () throws -> ContiguousArray, @autoclosure _ expression2: () throws -> ContiguousArray, @autoclosure _ message: () -> String = "", file: StaticString = #file, line: UInt = #line) -> Void { let assertionType = _XCTAssertionType.equal // evaluate each expression exactly once var expressionValue1Optional: ContiguousArray? var expressionValue2Optional: ContiguousArray? let result = _XCTRunThrowableBlock { expressionValue1Optional = try expression1() expressionValue2Optional = try expression2() } switch result { case .success: let expressionValue1: ContiguousArray = expressionValue1Optional! let expressionValue2: ContiguousArray = expressionValue2Optional! if expressionValue1 != expressionValue2 { // TODO: @auto_string expression1 // TODO: @auto_string expression2 let expressionValueStr1 = "\(expressionValue1)" let expressionValueStr2 = "\(expressionValue2)" _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionValueStr1 as NSString, expressionValueStr2 as NSString), message, file, line) } case .failedWithError(let error): _XCTRegisterFailure(false, "XCTAssertEqual failed: threw error \"\(error)\"", message, file, line) case .failedWithException(_, _, let reason): _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line) case .failedWithUnknownException: _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line) } } public func XCTAssertEqual(@autoclosure expression1: () throws -> [T], @autoclosure _ expression2: () throws -> [T], @autoclosure _ message: () -> String = "", file: StaticString = #file, line: UInt = #line) -> Void { let assertionType = _XCTAssertionType.equal // evaluate each expression exactly once var expressionValue1Optional: [T]? var expressionValue2Optional: [T]? let result = _XCTRunThrowableBlock { expressionValue1Optional = try expression1() expressionValue2Optional = try expression2() } switch result { case .success: let expressionValue1: [T] = expressionValue1Optional! let expressionValue2: [T] = expressionValue2Optional! if expressionValue1 != expressionValue2 { // TODO: @auto_string expression1 // TODO: @auto_string expression2 let expressionValueStr1 = "\(expressionValue1)" let expressionValueStr2 = "\(expressionValue2)" _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionValueStr1 as NSString, expressionValueStr2 as NSString), message, file, line) } case .failedWithError(let error): _XCTRegisterFailure(false, "XCTAssertEqual failed: threw error \"\(error)\"", message, file, line) case .failedWithException(_, _, let reason): _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line) case .failedWithUnknownException: _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line) } } public func XCTAssertEqual(@autoclosure expression1: () throws -> [T: U], @autoclosure _ expression2: () throws -> [T: U], @autoclosure _ message: () -> String = "", file: StaticString = #file, line: UInt = #line) -> Void { let assertionType = _XCTAssertionType.equal // evaluate each expression exactly once var expressionValue1Optional: [T: U]? var expressionValue2Optional: [T: U]? let result = _XCTRunThrowableBlock { expressionValue1Optional = try expression1() expressionValue2Optional = try expression2() } switch result { case .success: let expressionValue1: [T: U] = expressionValue1Optional! let expressionValue2: [T: U] = expressionValue2Optional! if expressionValue1 != expressionValue2 { // TODO: @auto_string expression1 // TODO: @auto_string expression2 let expressionValueStr1 = "\(expressionValue1)" let expressionValueStr2 = "\(expressionValue2)" _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionValueStr1 as NSString, expressionValueStr2 as NSString), message, file, line) } case .failedWithError(let error): _XCTRegisterFailure(false, "XCTAssertEqual failed: threw error \"\(error)\"", message, file, line) case .failedWithException(_, _, let reason): _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line) case .failedWithUnknownException: _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line) } } public func XCTAssertNotEqual(@autoclosure expression1: () throws -> T?, @autoclosure _ expression2: () throws -> T?, @autoclosure _ message: () -> String = "", file: StaticString = #file, line: UInt = #line) -> Void { let assertionType = _XCTAssertionType.notEqual // evaluate each expression exactly once var expressionValue1Optional: T? var expressionValue2Optional: T? let result = _XCTRunThrowableBlock { expressionValue1Optional = try expression1() expressionValue2Optional = try expression2() } switch result { case .success: if expressionValue1Optional == expressionValue2Optional { // TODO: @auto_string expression1 // TODO: @auto_string expression2 let expressionValueStr1 = "\(expressionValue1Optional)" let expressionValueStr2 = "\(expressionValue2Optional)" _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionValueStr1 as NSString, expressionValueStr2 as NSString), message, file, line) } case .failedWithError(let error): _XCTRegisterFailure(false, "XCTAssertNotEqual failed: threw error \"\(error)\"", message, file, line) case .failedWithException(_, _, let reason): _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line) case .failedWithUnknownException: _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line) } } // FIXME: Due to we need overrides of XCTAssertNotEqual for: // ContiguousArray // ArraySlice // Array // Dictionary public func XCTAssertNotEqual(@autoclosure expression1: () throws -> ContiguousArray, @autoclosure _ expression2: () throws -> ContiguousArray, @autoclosure _ message: () -> String = "", file: StaticString = #file, line: UInt = #line) -> Void { let assertionType = _XCTAssertionType.notEqual // evaluate each expression exactly once var expressionValue1Optional: ContiguousArray? var expressionValue2Optional: ContiguousArray? let result = _XCTRunThrowableBlock { expressionValue1Optional = try expression1() expressionValue2Optional = try expression2() } switch result { case .success: let expressionValue1: ContiguousArray = expressionValue1Optional! let expressionValue2: ContiguousArray = expressionValue2Optional! if expressionValue1 == expressionValue2 { // TODO: @auto_string expression1 // TODO: @auto_string expression2 let expressionValueStr1 = "\(expressionValue1)" let expressionValueStr2 = "\(expressionValue2)" _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionValueStr1 as NSString, expressionValueStr2 as NSString), message, file, line) } case .failedWithError(let error): _XCTRegisterFailure(false, "XCTAssertNotEqual failed: threw error \"\(error)\"", message, file, line) case .failedWithException(_, _, let reason): _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line) case .failedWithUnknownException: _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line) } } public func XCTAssertNotEqual(@autoclosure expression1: () throws -> ArraySlice, @autoclosure _ expression2: () throws -> ArraySlice, @autoclosure _ message: () -> String = "", file: StaticString = #file, line: UInt = #line) -> Void { let assertionType = _XCTAssertionType.notEqual // evaluate each expression exactly once var expressionValue1Optional: ArraySlice? var expressionValue2Optional: ArraySlice? let result = _XCTRunThrowableBlock { expressionValue1Optional = try expression1() expressionValue2Optional = try expression2() } switch result { case .success: let expressionValue1: ArraySlice = expressionValue1Optional! let expressionValue2: ArraySlice = expressionValue2Optional! if expressionValue1 == expressionValue2 { // TODO: @auto_string expression1 // TODO: @auto_string expression2 let expressionValueStr1 = "\(expressionValue1)" let expressionValueStr2 = "\(expressionValue2)" _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionValueStr1 as NSString, expressionValueStr2 as NSString), message, file, line) } case .failedWithError(let error): _XCTRegisterFailure(false, "XCTAssertNotEqual failed: threw error \"\(error)\"", message, file, line) case .failedWithException(_, _, let reason): _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line) case .failedWithUnknownException: _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line) } } public func XCTAssertNotEqual(@autoclosure expression1: () throws -> [T], @autoclosure _ expression2: () throws -> [T], @autoclosure _ message: () -> String = "", file: StaticString = #file, line: UInt = #line) -> Void { let assertionType = _XCTAssertionType.notEqual // evaluate each expression exactly once var expressionValue1Optional: [T]? var expressionValue2Optional: [T]? let result = _XCTRunThrowableBlock { expressionValue1Optional = try expression1() expressionValue2Optional = try expression2() } switch result { case .success: let expressionValue1: [T] = expressionValue1Optional! let expressionValue2: [T] = expressionValue2Optional! if expressionValue1 == expressionValue2 { // TODO: @auto_string expression1 // TODO: @auto_string expression2 let expressionValueStr1 = "\(expressionValue1)" let expressionValueStr2 = "\(expressionValue2)" _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionValueStr1 as NSString, expressionValueStr2 as NSString), message, file, line) } case .failedWithError(let error): _XCTRegisterFailure(false, "XCTAssertNotEqual failed: threw error \"\(error)\"", message, file, line) case .failedWithException(_, _, let reason): _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line) case .failedWithUnknownException: _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line) } } public func XCTAssertNotEqual(@autoclosure expression1: () throws -> [T: U], @autoclosure _ expression2: () throws -> [T: U], @autoclosure _ message: () -> String = "", file: StaticString = #file, line: UInt = #line) -> Void { let assertionType = _XCTAssertionType.notEqual // evaluate each expression exactly once var expressionValue1Optional: [T: U]? var expressionValue2Optional: [T: U]? let result = _XCTRunThrowableBlock { expressionValue1Optional = try expression1() expressionValue2Optional = try expression2() } switch result { case .success: let expressionValue1: [T: U] = expressionValue1Optional! let expressionValue2: [T: U] = expressionValue2Optional! if expressionValue1 == expressionValue2 { // TODO: @auto_string expression1 // TODO: @auto_string expression2 let expressionValueStr1 = "\(expressionValue1)" let expressionValueStr2 = "\(expressionValue2)" _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionValueStr1 as NSString, expressionValueStr2 as NSString), message, file, line) } case .failedWithError(let error): _XCTRegisterFailure(false, "XCTAssertNotEqual failed: threw error \"\(error)\"", message, file, line) case .failedWithException(_, _, let reason): _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line) case .failedWithUnknownException: _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line) } } func _XCTCheckEqualWithAccuracy_Double(value1: Double, _ value2: Double, _ accuracy: Double) -> Bool { return (!value1.isNaN && !value2.isNaN) && (abs(value1 - value2) <= accuracy) } func _XCTCheckEqualWithAccuracy_Float(value1: Float, _ value2: Float, _ accuracy: Float) -> Bool { return (!value1.isNaN && !value2.isNaN) && (abs(value1 - value2) <= accuracy) } func _XCTCheckEqualWithAccuracy_CGFloat(value1: CGFloat, _ value2: CGFloat, _ accuracy: CGFloat) -> Bool { return (!value1.isNaN && !value2.isNaN) && (abs(value1 - value2) <= accuracy) } public func XCTAssertEqualWithAccuracy(@autoclosure expression1: () throws -> T, @autoclosure _ expression2: () throws -> T, accuracy: T, @autoclosure _ message: () -> String = "", file: StaticString = #file, line: UInt = #line) -> Void { let assertionType = _XCTAssertionType.equalWithAccuracy // evaluate each expression exactly once var expressionValue1Optional: T? var expressionValue2Optional: T? let result = _XCTRunThrowableBlock { expressionValue1Optional = try expression1() expressionValue2Optional = try expression2() } switch result { case .success: let expressionValue1 = expressionValue1Optional! let expressionValue2 = expressionValue2Optional! var equalWithAccuracy: Bool = false switch (expressionValue1, expressionValue2, accuracy) { case let (expressionValue1Double as Double, expressionValue2Double as Double, accuracyDouble as Double): equalWithAccuracy = _XCTCheckEqualWithAccuracy_Double(expressionValue1Double, expressionValue2Double, accuracyDouble) case let (expressionValue1Float as Float, expressionValue2Float as Float, accuracyFloat as Float): equalWithAccuracy = _XCTCheckEqualWithAccuracy_Float(expressionValue1Float, expressionValue2Float, accuracyFloat) case let (expressionValue1CGFloat as CGFloat, expressionValue2CGFloat as CGFloat, accuracyCGFloat as CGFloat): equalWithAccuracy = _XCTCheckEqualWithAccuracy_CGFloat(expressionValue1CGFloat, expressionValue2CGFloat, accuracyCGFloat) default: // unknown type, fail with prejudice _preconditionFailure("unsupported floating-point type passed to XCTAssertEqualWithAccuracy") } if !equalWithAccuracy { // TODO: @auto_string expression1 // TODO: @auto_string expression2 let expressionValueStr1 = "\(expressionValue1)" let expressionValueStr2 = "\(expressionValue2)" let accuracyStr = "\(accuracy)" _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionValueStr1 as NSString, expressionValueStr2 as NSString, accuracyStr as NSString), message, file, line) } case .failedWithError(let error): _XCTRegisterFailure(false, "XCTAssertEqualWithAccuracy failed: threw error \"\(error)\"", message, file, line) case .failedWithException(_, _, let reason): _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line) case .failedWithUnknownException: _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line) } } func _XCTCheckNotEqualWithAccuracy_Double(value1: Double, _ value2: Double, _ accuracy: Double) -> Bool { return (value1.isNaN || value2.isNaN) || (abs(value1 - value2) > accuracy) } func _XCTCheckNotEqualWithAccuracy_Float(value1: Float, _ value2: Float, _ accuracy: Float) -> Bool { return (value1.isNaN || value2.isNaN) || (abs(value1 - value2) > accuracy) } func _XCTCheckNotEqualWithAccuracy_CGFloat(value1: CGFloat, _ value2: CGFloat, _ accuracy: CGFloat) -> Bool { return (value1.isNaN || value2.isNaN) || (abs(value1 - value2) > accuracy) } public func XCTAssertNotEqualWithAccuracy(@autoclosure expression1: () throws -> T, @autoclosure _ expression2: () throws -> T, _ accuracy: T, @autoclosure _ message: () -> String = "", file: StaticString = #file, line: UInt = #line) -> Void { let assertionType = _XCTAssertionType.notEqualWithAccuracy // evaluate each expression exactly once var expressionValue1Optional: T? var expressionValue2Optional: T? let result = _XCTRunThrowableBlock { expressionValue1Optional = try expression1() expressionValue2Optional = try expression2() } switch result { case .success: let expressionValue1 = expressionValue1Optional! let expressionValue2 = expressionValue2Optional! var notEqualWithAccuracy: Bool = false switch (expressionValue1, expressionValue2, accuracy) { case let (expressionValue1Double as Double, expressionValue2Double as Double, accuracyDouble as Double): notEqualWithAccuracy = _XCTCheckNotEqualWithAccuracy_Double(expressionValue1Double, expressionValue2Double, accuracyDouble) case let (expressionValue1Float as Float, expressionValue2Float as Float, accuracyFloat as Float): notEqualWithAccuracy = _XCTCheckNotEqualWithAccuracy_Float(expressionValue1Float, expressionValue2Float, accuracyFloat) case let (expressionValue1CGFloat as CGFloat, expressionValue2CGFloat as CGFloat, accuracyCGFloat as CGFloat): notEqualWithAccuracy = _XCTCheckNotEqualWithAccuracy_CGFloat(expressionValue1CGFloat, expressionValue2CGFloat, accuracyCGFloat) default: // unknown type, fail with prejudice _preconditionFailure("unsupported floating-point type passed to XCTAssertNotEqualWithAccuracy") } if !notEqualWithAccuracy { // TODO: @auto_string expression1 // TODO: @auto_string expression2 let expressionValueStr1 = "\(expressionValue1)" let expressionValueStr2 = "\(expressionValue2)" let accuracyStr = "\(accuracy)" _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionValueStr1 as NSString, expressionValueStr2 as NSString, accuracyStr as NSString), message, file, line) } case .failedWithError(let error): _XCTRegisterFailure(false, "XCTAssertNotEqualWithAccuracy failed: threw error \"\(error)\"", message, file, line) case .failedWithException(_, _, let reason): _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line) case .failedWithUnknownException: _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line) } } public func XCTAssertGreaterThan(@autoclosure expression1: () throws -> T, @autoclosure _ expression2: () throws -> T, @autoclosure _ message: () -> String = "", file: StaticString = #file, line: UInt = #line) -> Void { let assertionType = _XCTAssertionType.greaterThan // evaluate each expression exactly once var expressionValue1Optional: T? var expressionValue2Optional: T? let result = _XCTRunThrowableBlock { expressionValue1Optional = try expression1() expressionValue2Optional = try expression2() } switch result { case .success: let expressionValue1 = expressionValue1Optional! let expressionValue2 = expressionValue2Optional! if !(expressionValue1 > expressionValue2) { // TODO: @auto_string expression1 // TODO: @auto_string expression2 let expressionValueStr1 = "\(expressionValue1)" let expressionValueStr2 = "\(expressionValue2)" _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionValueStr1 as NSString, expressionValueStr2 as NSString), message, file, line) } case .failedWithError(let error): _XCTRegisterFailure(false, "XCTAssertGreaterThan failed: threw error \"\(error)\"", message, file, line) case .failedWithException(_, _, let reason): _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line) case .failedWithUnknownException: _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line) } } public func XCTAssertGreaterThanOrEqual(@autoclosure expression1: () throws -> T, @autoclosure _ expression2: () throws -> T, @autoclosure _ message: () -> String = "", file: StaticString = #file, line: UInt = #line) { let assertionType = _XCTAssertionType.greaterThanOrEqual // evaluate each expression exactly once var expressionValue1Optional: T? var expressionValue2Optional: T? let result = _XCTRunThrowableBlock { expressionValue1Optional = try expression1() expressionValue2Optional = try expression2() } switch result { case .success: let expressionValue1 = expressionValue1Optional! let expressionValue2 = expressionValue2Optional! if !(expressionValue1 >= expressionValue2) { // TODO: @auto_string expression1 // TODO: @auto_string expression2 let expressionValueStr1 = "\(expressionValue1)" let expressionValueStr2 = "\(expressionValue2)" _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionValueStr1 as NSString, expressionValueStr2 as NSString), message, file, line) } case .failedWithError(let error): _XCTRegisterFailure(false, "XCTAssertGreaterThanOrEqual failed: threw error \"\(error)\"", message, file, line) case .failedWithException(_, _, let reason): _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line) case .failedWithUnknownException: _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line) } } public func XCTAssertLessThan(@autoclosure expression1: () throws -> T, @autoclosure _ expression2: () throws -> T, @autoclosure _ message: () -> String = "", file: StaticString = #file, line: UInt = #line) -> Void { let assertionType = _XCTAssertionType.lessThan // evaluate each expression exactly once var expressionValue1Optional: T? var expressionValue2Optional: T? let result = _XCTRunThrowableBlock { expressionValue1Optional = try expression1() expressionValue2Optional = try expression2() } switch result { case .success: let expressionValue1 = expressionValue1Optional! let expressionValue2 = expressionValue2Optional! if !(expressionValue1 < expressionValue2) { // TODO: @auto_string expression1 // TODO: @auto_string expression2 let expressionValueStr1 = "\(expressionValue1)" let expressionValueStr2 = "\(expressionValue2)" _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionValueStr1 as NSString, expressionValueStr2 as NSString), message, file, line) } case .failedWithError(let error): _XCTRegisterFailure(false, "XCTAssertLessThan failed: threw error \"\(error)\"", message, file, line) case .failedWithException(_, _, let reason): _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line) case .failedWithUnknownException: _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line) } } public func XCTAssertLessThanOrEqual(@autoclosure expression1: () throws -> T, @autoclosure _ expression2: () throws -> T, @autoclosure _ message: () -> String = "", file: StaticString = #file, line: UInt = #line) { let assertionType = _XCTAssertionType.lessThanOrEqual // evaluate each expression exactly once var expressionValue1Optional: T? var expressionValue2Optional: T? let result = _XCTRunThrowableBlock { expressionValue1Optional = try expression1() expressionValue2Optional = try expression2() } switch result { case .success: let expressionValue1 = expressionValue1Optional! let expressionValue2 = expressionValue2Optional! if !(expressionValue1 <= expressionValue2) { // TODO: @auto_string expression1 // TODO: @auto_string expression2 let expressionValueStr1 = "\(expressionValue1)" let expressionValueStr2 = "\(expressionValue2)" _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionValueStr1 as NSString, expressionValueStr2 as NSString), message, file, line) } case .failedWithError(let error): _XCTRegisterFailure(false, "XCTAssertLessThanOrEqual failed: threw error \"\(error)\"", message, file, line) case .failedWithException(_, _, let reason): _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line) case .failedWithUnknownException: _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line) } } public func XCTAssertThrowsError(@autoclosure expression: () throws -> T, @autoclosure _ message: () -> String = "", file: StaticString = #file, line: UInt = #line, _ errorHandler: (error: ErrorProtocol) -> Void = { _ in }) -> Void { // evaluate expression exactly once var caughtErrorOptional: ErrorProtocol? let result = _XCTRunThrowableBlock { do { _ = try expression() } catch { caughtErrorOptional = error } } switch result { case .success: if let caughtError = caughtErrorOptional { errorHandler(error: caughtError) } else { _XCTRegisterFailure(true, "XCTAssertThrowsError failed: did not throw an error", message, file, line) } case .failedWithError(let error): _XCTRegisterFailure(false, "XCTAssertLessThanOrEqual failed: threw error \"\(error)\"", message, file, line) case .failedWithException(_, _, let reason): _XCTRegisterFailure(true, "XCTAssertThrowsError failed: throwing \(reason)", message, file, line) case .failedWithUnknownException: _XCTRegisterFailure(true, "XCTAssertThrowsError failed: throwing an unknown exception", message, file, line) } } #if XCTEST_ENABLE_EXCEPTION_ASSERTIONS // --- Currently-Unsupported Assertions --- public func XCTAssertThrows(@autoclosure expression: () -> Any?, @autoclosure _ message: () -> String = "", file: StaticString = #file, line: UInt = #line) -> Void { let assertionType = _XCTAssertionType.assertion_Throws // FIXME: Unsupported } public func XCTAssertThrowsSpecific(@autoclosure expression: () -> Any?, _ exception: Any, @autoclosure _ message: () -> String = "", file: StaticString = #file, line: UInt = #line) -> Void { let assertionType = _XCTAssertionType.assertion_ThrowsSpecific // FIXME: Unsupported } public func XCTAssertThrowsSpecificNamed(@autoclosure expression: () -> Any?, _ exception: Any, _ name: String, @autoclosure _ message: () -> String = "", file: StaticString = #file, line: UInt = #line) -> Void { let assertionType = _XCTAssertionType.assertion_ThrowsSpecificNamed // FIXME: Unsupported } public func XCTAssertNoThrow(@autoclosure expression: () -> Any?, @autoclosure _ message: () -> String = "", file: StaticString = #file, line: UInt = #line) -> Void { let assertionType = _XCTAssertionType.assertion_NoThrow // FIXME: Unsupported } public func XCTAssertNoThrowSpecific(@autoclosure expression: () -> Any?, _ exception: Any, @autoclosure _ message: () -> String = "", file: StaticString = #file, line: UInt = #line) -> Void { let assertionType = _XCTAssertionType.assertion_NoThrowSpecific // FIXME: Unsupported } public func XCTAssertNoThrowSpecificNamed(@autoclosure expression: () -> Any?, _ exception: Any, _ name: String, @autoclosure _ message: () -> String = "", file: StaticString = #file, line: UInt = #line) -> Void { let assertionType = _XCTAssertionType.assertion_NoThrowSpecificNamed // FIXME: Unsupported } #endif