blob: 99df736f1abaea9a5b5996188b9e1dfa277110b6 [file] [log] [blame]
// RUN: %target-run-simple-swift
// REQUIRES: executable_test
// REQUIRES: objc_interop
import StdlibUnittest
import Foundation
import CoreLocation
import Darwin
var ErrorTypeBridgingTests = TestSuite("ErrorTypeBridging")
var NoisyErrorLifeCount = 0
var NoisyErrorDeathCount = 0
var CanaryHandle = 0
protocol OtherProtocol {
var otherProperty: String { get }
}
protocol OtherClassProtocol : class {
var otherClassProperty: String { get }
}
class NoisyError : ErrorType, OtherProtocol, OtherClassProtocol {
init() { NoisyErrorLifeCount += 1 }
deinit { NoisyErrorDeathCount += 1 }
let _domain = "NoisyError"
let _code = 123
let otherProperty = "otherProperty"
let otherClassProperty = "otherClassProperty"
}
@objc enum EnumError : Int, ErrorType {
case BadError = 9000
case ReallyBadError = 9001
}
ErrorTypeBridgingTests.test("NSError") {
NoisyErrorLifeCount = 0
NoisyErrorDeathCount = 0
autoreleasepool {
let ns = NSError(domain: "SomeDomain", code: 321, userInfo: nil)
objc_setAssociatedObject(ns, &CanaryHandle, NoisyError(),
.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
let e: ErrorType = ns
expectEqual(e._domain, "SomeDomain")
expectEqual(e._code, 321)
let ns2 = e as NSError
expectTrue(ns === ns2)
expectEqual(ns2._domain, "SomeDomain")
expectEqual(ns2._code, 321)
}
expectEqual(NoisyErrorDeathCount, NoisyErrorLifeCount)
}
ErrorTypeBridgingTests.test("NSError-to-enum bridging") {
NoisyErrorLifeCount = 0
NoisyErrorDeathCount = 0
autoreleasepool {
let ns = NSError(domain: NSCocoaErrorDomain,
code: NSFileNoSuchFileError,
userInfo: nil)
objc_setAssociatedObject(ns, &CanaryHandle, NoisyError(),
.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
let e: ErrorType = ns
let cocoaCode: Int?
switch e {
case let x as NSCocoaError:
cocoaCode = x._code
expectTrue(x.isFileError)
expectEqual(x, NSCocoaError.FileNoSuchFileError)
expectEqual(x.hashValue, NSFileNoSuchFileError)
default:
cocoaCode = nil
}
expectEqual(cocoaCode, NSFileNoSuchFileError)
let cocoaCode2: Int? = (ns as? NSCocoaError)?._code
expectEqual(cocoaCode2, NSFileNoSuchFileError)
let isNoSuchFileError: Bool
switch e {
case NSCocoaError.FileNoSuchFileError:
isNoSuchFileError = true
default:
isNoSuchFileError = false
}
expectTrue(isNoSuchFileError)
// NSURLError domain
let nsURL = NSError(domain: NSURLErrorDomain,
code: NSURLErrorBadURL,
userInfo: nil)
let eURL: ErrorType = nsURL
let isBadURLError: Bool
switch eURL {
case NSURLError.BadURL:
isBadURLError = true
default:
isBadURLError = false
}
expectTrue(isBadURLError)
// CoreLocation error domain
let nsCL = NSError(domain: kCLErrorDomain,
code: CLError.HeadingFailure.rawValue,
userInfo: [:])
let eCL: ErrorType = nsCL
let isHeadingFailure: Bool
switch eCL {
case CLError.HeadingFailure:
isHeadingFailure = true
default:
isHeadingFailure = false
}
expectTrue(isHeadingFailure)
// NSPOSIXError domain
let nsPOSIX = NSError(domain: NSPOSIXErrorDomain,
code: Int(EDEADLK),
userInfo: [:])
let ePOSIX: ErrorType = nsPOSIX
let isDeadlock: Bool
switch ePOSIX {
case POSIXError.EDEADLK:
isDeadlock = true
default:
isDeadlock = false
}
expectTrue(isDeadlock)
// NSMachError domain
let nsMach = NSError(domain: NSMachErrorDomain,
code: Int(KERN_MEMORY_FAILURE),
userInfo: [:])
let eMach: ErrorType = nsMach
let isMemoryFailure: Bool
switch eMach {
case MachError.KERN_MEMORY_FAILURE:
isMemoryFailure = true
default:
isMemoryFailure = false
}
expectTrue(isMemoryFailure)
}
expectEqual(NoisyErrorDeathCount, NoisyErrorLifeCount)
}
func opaqueUpcastToAny<T>(x: T) -> Any {
return x
}
struct StructError: ErrorType {
var _domain: String { return "StructError" }
var _code: Int { return 4812 }
}
ErrorTypeBridgingTests.test("ErrorType-to-NSError bridging") {
NoisyErrorLifeCount = 0
NoisyErrorDeathCount = 0
autoreleasepool {
let e: ErrorType = NoisyError()
let ns = e as NSError
let ns2 = e as NSError
expectTrue(ns === ns2)
expectEqual(ns._domain, "NoisyError")
expectEqual(ns._code, 123)
let e3: ErrorType = ns
expectEqual(e3._domain, "NoisyError")
expectEqual(e3._code, 123)
let ns3 = e3 as NSError
expectTrue(ns === ns3)
let nativeNS = NSError(domain: NSCocoaErrorDomain,
code: NSFileNoSuchFileError,
userInfo: nil)
objc_setAssociatedObject(ns, &CanaryHandle, NoisyError(),
.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
let nativeE: ErrorType = nativeNS
let nativeNS2 = nativeE as NSError
expectTrue(nativeNS === nativeNS2)
expectEqual(nativeNS2._domain, NSCocoaErrorDomain)
expectEqual(nativeNS2._code, NSFileNoSuchFileError)
let any: Any = NoisyError()
let ns4 = any as! NSError
expectEqual(ns4._domain, "NoisyError")
expectEqual(ns4._code, 123)
let ao: AnyObject = NoisyError()
let ns5 = ao as! NSError
expectEqual(ns5._domain, "NoisyError")
expectEqual(ns5._code, 123)
let any2: Any = StructError()
let ns6 = any2 as! NSError
expectEqual(ns6._domain, "StructError")
expectEqual(ns6._code, 4812)
}
expectEqual(NoisyErrorDeathCount, NoisyErrorLifeCount)
}
ErrorTypeBridgingTests.test("enum-to-NSError round trip") {
autoreleasepool {
// Emulate throwing an error from Objective-C.
func throwNSError(error: EnumError) throws {
throw NSError(domain: "\(EnumError.self)", code: error.rawValue,
userInfo: [:])
}
var caughtError: Bool
caughtError = false
do {
try throwNSError(.BadError)
expectUnreachable()
} catch let error as EnumError {
expectEqual(.BadError, error)
caughtError = true
} catch _ {
expectUnreachable()
}
expectTrue(caughtError)
caughtError = false
do {
try throwNSError(.ReallyBadError)
expectUnreachable()
} catch EnumError.BadError {
expectUnreachable()
} catch EnumError.ReallyBadError {
caughtError = true
} catch _ {
expectUnreachable()
}
expectTrue(caughtError)
}
}
class SomeNSErrorSubclass: NSError {}
ErrorTypeBridgingTests.test("Thrown NSError identity is preserved") {
do {
let e = NSError(domain: "ClericalError", code: 219,
userInfo: ["yeah": "yeah"])
do {
throw e
} catch let e2 as NSError {
expectTrue(e === e2)
expectTrue(e2.userInfo["yeah"] as? String == "yeah")
} catch {
expectUnreachable()
}
}
do {
let f = SomeNSErrorSubclass(domain: "ClericalError", code: 219,
userInfo: ["yeah": "yeah"])
do {
throw f
} catch let f2 as NSError {
expectTrue(f === f2)
expectTrue(f2.userInfo["yeah"] as? String == "yeah")
} catch {
expectUnreachable()
}
}
}
runAllTests()