blob: 50dfc968b3f6e23f33062d0b887512c7ffc82ebd [file] [log] [blame]
// RUN: %target-run-simple-swift
// REQUIRES: executable_test
// REQUIRES: objc_interop
import Foundation
import StdlibUnittest
// rdar://problem/18884272
// Make sure that NSObject conforms to NSObjectProtocol. This
// particular bug is ridiculously hard to trigger without a complete
// SDK, so it sits here.
let objcProtocol: NSObjectProtocol = NSObject()
var FoundationTestSuite = TestSuite("Foundation")
func asNSString(_ s: String) -> NSString { return s as NSString }
func asString(_ ns: NSString) -> String { return ns as String }
//===----------------------------------------------------------------------===//
// Strings
//===----------------------------------------------------------------------===//
FoundationTestSuite.test("NSString") {
var str = "Hello"
var nsStr = str as NSString
assert(nsStr.compare(str).rawValue == ComparisonResult.orderedSame.rawValue)
assert(nsStr.compare(str) == ComparisonResult.orderedSame)
nsStr = "World"
str = nsStr as String
// FIXME: Shouldn't need coercion here to resolve ambiguity. <rdar://problem/14637688>
assert(str == asString(nsStr))
}
//===----------------------------------------------------------------------===//
// Numbers
//===----------------------------------------------------------------------===//
FoundationTestSuite.test("NSNumber") {
var i = 17
var d = 3.14159
var b = true
// Implicit boxing/explicit unboxing
var nsNum: NSNumber = i as NSNumber
expectEqual(i, Int(nsNum))
nsNum = d as NSNumber
expectEqual(d, Double(nsNum))
nsNum = b as NSNumber
expectEqual(b, Bool(nsNum))
// Literals
nsNum = 42
expectEqual(42, Int(nsNum))
nsNum = 3.14159
expectEqual(3.14159, Double(nsNum))
nsNum = false
expectEqual(false, Bool(nsNum))
}
//===----------------------------------------------------------------------===//
// Arrays
//===----------------------------------------------------------------------===//
FoundationTestSuite.test("NSArray") {
// Literals
var nsArr: NSArray = [1, 2.5, "Hello"]
assert(nsArr.count == 3)
// Subscripting
expectEqual(1, Int(nsArr[0] as! NSNumber))
expectEqual(2.5, Double(nsArr[1] as! NSNumber))
expectTrue((nsArr[2] as! NSString).isEqual("Hello"))
// Iteration
var result = [String]()
for x: Any in nsArr {
result.append((x as! NSObject).description)
}
expectEqualSequence(["1", "2.5", "Hello"], result)
}
FoundationTestSuite.test("NSMutableArray") {
let nsMutableArr: NSMutableArray = ["Constant", "Moon"]
nsMutableArr[0] = "Inconstant"
expectEqual(2, nsMutableArr.count)
expectEqual("Inconstant", nsMutableArr[0] as! NSString)
expectEqual("Moon", nsMutableArr[1] as! NSString)
}
FoundationTestSuite.test("NSArrayVariadicInit") {
let variadicArray = NSArray(objects: "A", "B", "C")
expectEqual(3, variadicArray.count)
}
FoundationTestSuite.test("arrayConversions") {
var nsa = NSArray()
var aoa: Array<AnyObject> = []
nsa as Array<AnyObject>
var nsa2 = NSArray()
var aoa2 = nsa2 as Array<AnyObject>
var nsaoa = aoa as NSArray
func nsArrayToAnyObjectArray(_ nsa: NSArray) -> [AnyObject] {
return nsa as [AnyObject]
}
nsArrayToAnyObjectArray(nsa)
nsArrayToAnyObjectArray(aoa as NSArray)
}
//===----------------------------------------------------------------------===//
// Dictionaries
//===----------------------------------------------------------------------===//
FoundationTestSuite.test("NSDictionary") {
var nsDict : NSDictionary = [1 : "Hello", 2 : "World"]
assert((nsDict[1]! as! NSString).isEqual("Hello"))
assert((nsDict[2]! as! NSString).isEqual("World"))
let nsMutableDict: NSMutableDictionary = ["Hello" : 1, "World" : 2 as NSNumber]
assert((nsMutableDict["Hello"]! as AnyObject).isEqual(1))
assert((nsMutableDict["World"]! as AnyObject).isEqual(2))
}
//===----------------------------------------------------------------------===//
// Ranges
//===----------------------------------------------------------------------===//
FoundationTestSuite.test("NSRange") {
let nsRange = NSRange(1..<5)
expectEqual("{1, 4}", String(NSStringFromRange(nsRange)))
}
FoundationTestSuite.test("RangeConversion") {
let i: Int8 = 10
let j: Int8 = 20
let nsrFromInt8 = NSRange(i..<j)
expectEqual(nsrFromInt8, NSRange(location: 10, length: 10))
var r = Range(nsrFromInt8)
expectNotNil(r)
expectEqual(r!.lowerBound, 10)
expectEqual(r!.upperBound, 20)
expectType(Optional<Range<Int>>.self, &r)
var r8 = Range<Int8>(nsrFromInt8)
expectNotNil(r8 != nil)
expectEqual(r8?.lowerBound, 10)
expectEqual(r8?.upperBound, 20)
expectType(Optional<Range<Int8>>.self, &r8)
var nsrFromPartial = NSRange(..<5)
expectEqual("{0, 5}", NSStringFromRange(nsrFromPartial))
let s = "Hello, 🌎!"
let b = s.index(of: ",")!
let e = s.index(of: "!")!
let nsr = NSRange(b..<e, in: s)
expectEqual(nsr.location, 5)
expectEqual(nsr.length, 4)
let rs = Range(nsr, in: s)!
expectEqual(s[rs], ", 🌎")
let nsrTo = NSRange(..<b, in: s)
expectEqual(nsrTo.location, 0)
expectEqual(nsrTo.length, 5)
let nsrFrom = NSRange(b..., in: s)
expectEqual(nsrFrom.location,5)
expectEqual(nsrFrom.length, 5)
expectNil(Range(NSRange(location: 100, length: 0), in: s))
expectNil(Range(NSRange(location: 0, length: 100), in: s))
let empty = ""
expectNil(Range(NSRange(location: 1, length: 0), in: empty))
expectNil(Range(NSRange(location: 0, length: 1), in: empty))
expectNotNil(Range(NSRange(location: 0, length: 0), in: empty))
// FIXME: enable once indices conform to RangeExpression
// let nsrFull = NSRange(s.indices, in: s)
// expectEqual(nsrFull.location, 0)
// expectEqual(nsrFull.length, 10)
}
//===----------------------------------------------------------------------===//
// URLs
//===----------------------------------------------------------------------===//
FoundationTestSuite.test("NSURL") {
let nsURL = NSURL(string: "http://llvm.org")!
expectEqual("http://llvm.org", nsURL.description)
}
//===----------------------------------------------------------------------===//
// Pattern-matching
//===----------------------------------------------------------------------===//
func matchesEither(_ input: NSNumber, _ a: NSNumber, _ b: NSNumber) -> Bool {
switch input {
case a, b:
return true
default:
return false
}
}
FoundationTestSuite.test("patternMatching") {
var one, two, three, oneAgain : NSNumber
one = NSNumber(value: 1)
two = NSNumber(value: 2)
three = NSNumber(value: 3)
oneAgain = NSNumber(value: 1)
expectFalse(matchesEither(one, two, three))
expectTrue(matchesEither(one, oneAgain, three))
expectTrue(matchesEither(one, two, oneAgain))
}
//===----------------------------------------------------------------------===//
// Miscellaneous
//===----------------------------------------------------------------------===//
// <rdar://problem/14474701>
// Type checker used to crash on this.
class ClassWithDtor : NSObject {
deinit {
let noteCenter = NotificationCenter.default
noteCenter.removeObserver(self, name: Notification.Name(rawValue: "ReceivedContentNotification"), object: nil)
}
}
FoundationTestSuite.test("rdar://17584531") {
// <rdar://problem/17584531>
// Type checker used to be confused by this.
var dict: NSDictionary = ["status": 200, "people": [["id": 255, "name": ["first": "John", "last": "Appleseed"] as NSDictionary] as NSDictionary] as NSArray]
var dict2 = dict["people"].flatMap { $0 as? NSArray }?[0] as! NSDictionary
expectEqual("Optional(255)", String(describing: dict2["id" as NSString]))
}
FoundationTestSuite.test("DarwinBoolean smoke test") {
expectFalse(CFEqual("abc" as NSString as CFString, "def" as NSString as CFString))
let _: CFArrayEqualCallBack = { DarwinBoolean($0 == $1) }
}
#if os(OSX)
FoundationTestSuite.test("NSRectEdge/constants") {
// Check that the following constants have the correct type and value.
//
// It is valid to hardcode the value in the test. The way they are currently
// defined in the SDK makes them ABI for Objective-C code.
expectEqual(0, CGRectEdge(rectEdge: NSRectEdge.minX).rawValue)
expectEqual(0, NSRectEdge(rectEdge: CGRectEdge.minXEdge).rawValue)
expectEqual(1, CGRectEdge(rectEdge: NSRectEdge.minY).rawValue)
expectEqual(1, NSRectEdge(rectEdge: CGRectEdge.minYEdge).rawValue)
expectEqual(2, CGRectEdge(rectEdge: NSRectEdge.maxX).rawValue)
expectEqual(2, NSRectEdge(rectEdge: CGRectEdge.maxXEdge).rawValue)
expectEqual(3, CGRectEdge(rectEdge: NSRectEdge.maxY).rawValue)
expectEqual(3, NSRectEdge(rectEdge: CGRectEdge.maxYEdge).rawValue)
}
#endif
if #available(OSX 10.11, iOS 9.0, *) {
FoundationTestSuite.test("UndoManager/ObjCClass") {
let UM = UndoManager()
// Confirm with an ObjC class.
class ObjCClass : NSObject {
var someProperty: String = ""
}
let f = ObjCClass()
UM.registerUndo(withTarget: f) { target in
target.someProperty = "expected"
}
UM.undo()
expectEqual(f.someProperty, "expected")
}
FoundationTestSuite.test("UndoManager/SwiftClass") {
let UM = UndoManager()
// Confirm with a Swift class.
class SwiftClass {
var someOtherProperty: String = ""
}
var b = SwiftClass()
UM.registerUndo(withTarget:b) { target in
target.someOtherProperty = "expected"
}
UM.undo()
expectEqual(b.someOtherProperty, "expected")
}
}
private let KEY = "some-key"
private func createTestArchive() -> NSData {
let mutableData = NSMutableData()
let KA = NSKeyedArchiver(forWritingWith: mutableData)
// Set up some fake data.
let obj = NSPredicate(value: true)
KA.encode(obj, forKey: KEY)
KA.encode(obj, forKey: NSKeyedArchiveRootObjectKey)
KA.finishEncoding()
return mutableData
}
FoundationTestSuite.test("NSKeyedUnarchiver/decodeObjectOfClass(_:forKey:)") {
let obj = NSPredicate(value: true)
let data = createTestArchive()
var KU = NSKeyedUnarchiver(forReadingWith: data as Data)
var missing = KU.decodeObject(of: NSPredicate.self, forKey: "Not there")
expectNil(missing)
expectType((NSPredicate?).self, &missing)
var decoded = KU.decodeObject(of: NSPredicate.self, forKey: KEY)
expectNotNil(decoded)
expectType((NSPredicate?).self, &decoded)
var wrongType = KU.decodeObject(of: DateFormatter.self, forKey: KEY)
expectNil(missing)
KU.finishDecoding()
}
if #available(OSX 10.11, iOS 9.0, *) {
FoundationTestSuite.test("NSKeyedUnarchiver/decodeTopLevel*") {
let obj = NSPredicate(value: true)
let data = createTestArchive()
// first confirm .decodeObjectWithClasses overlay requires an array of classes
var KU = NSKeyedUnarchiver(forReadingWith: data as Data)
var nonTopLevelResult = KU.decodeObject(of: [NSPredicate.self], forKey: KEY)
expectTrue(nonTopLevelResult != nil)
KU.finishDecoding()
KU = NSKeyedUnarchiver(forReadingWith: data as Data)
do {
// decodeObjectForKey(_:) throws
let decoded1 = try KU.decodeTopLevelObject(forKey: KEY) as? NSPredicate
let missing1 = try KU.decodeTopLevelObject(forKey:"Not there")
expectTrue(decoded1 != nil)
expectEqual(obj, decoded1)
expectTrue(missing1 == nil)
KU.finishDecoding()
// recreate so we can do the rest securely
KU = NSKeyedUnarchiver(forReadingWith: data as Data)
KU.requiresSecureCoding = true
// decodeObjectOfClass(_:,forKey:) throws
let decoded2 = try KU.decodeTopLevelObject(of: NSPredicate.self, forKey: KEY)
let missing2 = try KU.decodeTopLevelObject(of: NSPredicate.self, forKey: "Not there")
expectTrue(decoded2 != nil)
expectEqual(obj, decoded2)
expectTrue(missing2 == nil)
let classes: [AnyClass] = [NSPredicate.self]
let decoded3 = try KU.decodeTopLevelObject(of: classes, forKey: KEY) as? NSPredicate
let missing3 = try KU.decodeTopLevelObject(of: classes, forKey: "Not there")
expectTrue(decoded3 != nil)
expectEqual(obj, decoded3)
expectTrue(missing3 == nil)
}
catch {
expectTrue(false) // should have no errors
}
KU.finishDecoding()
KU = NSKeyedUnarchiver(forReadingWith: data as Data)
KU.requiresSecureCoding = true
do {
// recreate so we avoid caches from above
let wrong = try KU.decodeTopLevelObject(of: DateFormatter.self, forKey: KEY)
expectUnreachable() // should have error
}
catch {
// expected
}
KU.finishDecoding()
KU = NSKeyedUnarchiver(forReadingWith: data as Data)
KU.requiresSecureCoding = true
do {
let wrongClasses: [AnyClass] = [DateFormatter.self]
let wrong = try KU.decodeTopLevelObject(of: wrongClasses, forKey: KEY)
expectUnreachable() // should have error
}
catch {
// expected
}
KU.finishDecoding()
// confirm the that class function works
do {
let decoded = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? NSPredicate
expectEqual(obj, decoded)
}
catch {
expectUnreachableCatch(error)
}
}
FoundationTestSuite.test("NSKeyedUnarchiver/decodeTopLevelObjectOfClass(_:forKey:)/trap") {
let obj = NSPredicate(value: true)
let data = createTestArchive()
var KU = NSKeyedUnarchiver(forReadingWith: data as Data)
// Even though we're doing non-secure coding, this should still be checked
// in Swift.
do {
var wrongType = try KU.decodeTopLevelObject(of: DateFormatter.self, forKey: KEY)
expectType((DateFormatter?).self, &wrongType)
} catch {
expectUnreachableCatch(error)
}
KU.finishDecoding()
}
}
FoundationTestSuite.test("NotificationCenter/addObserver(_:selector:name:object:)") {
let obj: AnyObject = "Hello" as NSString
NotificationCenter.default.addObserver(obj, selector: Selector("blah:"),
name: nil, object: nil)
let name = "hello"
NotificationCenter.default.addObserver(obj, selector: Selector("blarg:"),
name: Notification.Name(name),
object: nil)
}
runAllTests()