Merge pull request #718 from djones6/json_dataperf
diff --git a/CoreFoundation/Locale.subproj/CFLocale.c b/CoreFoundation/Locale.subproj/CFLocale.c
index b502faf..69dda52 100644
--- a/CoreFoundation/Locale.subproj/CFLocale.c
+++ b/CoreFoundation/Locale.subproj/CFLocale.c
@@ -280,7 +280,12 @@
#if DEPLOYMENT_TARGET_MACOSX
+// Specify a default locale on Mac for Swift
+#if DEPLOYMENT_RUNTIME_SWIFT
+#define FALLBACK_LOCALE_NAME CFSTR("en_US")
+#else
#define FALLBACK_LOCALE_NAME CFSTR("")
+#endif /* DEPLOYMENT_RUNTIME_SWIFT */
#elif DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
#define FALLBACK_LOCALE_NAME CFSTR("en_US")
#elif DEPLOYMENT_TARGET_WINDOWS || DEPLOYMENT_TARGET_LINUX || DEPLOYMENT_TARGET_FREEBSD
diff --git a/Docs/Status.md b/Docs/Status.md
index 6c0eb68..e3b8d0b 100644
--- a/Docs/Status.md
+++ b/Docs/Status.md
@@ -53,10 +53,10 @@
| `URLProtectionSpace` | Unimplemented | None | |
| `URLProtocol` | Unimplemented | None | |
| `URLProtocolClient` | Unimplemented | None | |
- | `NSURLRequest` | Mostly Complete | Incomplete | `NSCoding` remains unimplemented |
- | `NSMutableURLRequest` | Mostly Complete | Incomplete | `NSCoding` remains unimplemented |
- | `URLResponse` | Mostly Complete | Incomplete | `NSCoding` remains unimplemented |
- | `NSHTTPURLResponse` | Mostly Complete | Substantial | `NSCoding` remains unimplemented |
+ | `NSURLRequest` | Mostly Complete | Incomplete | |
+ | `NSMutableURLRequest` | Mostly Complete | Incomplete | |
+ | `URLResponse` | Mostly Complete | Incomplete | |
+ | `NSHTTPURLResponse` | Mostly Complete | Substantial | |
| `NSURL` | Mostly Complete | Substantial | `NSCoding` with non-keyed-coding archivers, `checkResourceIsReachable()`, and resource values remain unimplemented |
| `NSURLQueryItem` | Mostly Complete | N/A | `NSCoding` remains unimplemented |
| `URLResourceKey` | Complete | N/A | |
diff --git a/Foundation/NSData.swift b/Foundation/NSData.swift
index 7c368a2..80a07fa 100644
--- a/Foundation/NSData.swift
+++ b/Foundation/NSData.swift
@@ -217,7 +217,12 @@
}
open var bytes: UnsafeRawPointer {
- return UnsafeRawPointer(CFDataGetBytePtr(_cfObject))
+ guard let bytePtr = CFDataGetBytePtr(_cfObject) else {
+ //This could occure on empty data being encoded.
+ //TODO: switch with nil when signature is fixed
+ return UnsafeRawPointer(bitPattern: 0xf00deadb0c0)! //would not result in 'nil unwrapped optional'
+ }
+ return UnsafeRawPointer(bytePtr)
}
diff --git a/Foundation/NSFileHandle.swift b/Foundation/NSFileHandle.swift
old mode 100644
new mode 100755
index 8596e66..dcc3e5d
--- a/Foundation/NSFileHandle.swift
+++ b/Foundation/NSFileHandle.swift
@@ -214,11 +214,49 @@
open class var standardError: FileHandle {
return _stderrFileHandle
}
-
+
+ internal static var _nulldeviceFileHandle: FileHandle = {
+ class NullDevice: FileHandle {
+ override var availableData: Data {
+ return Data()
+ }
+
+ override func readDataToEndOfFile() -> Data {
+ return Data()
+ }
+
+ override func readData(ofLength length: Int) -> Data {
+ return Data()
+ }
+
+ override func write(_ data: Data) {}
+
+ override var offsetInFile: UInt64 {
+ return 0
+ }
+
+ override func seekToEndOfFile() -> UInt64 {
+ return 0
+ }
+
+ override func seek(toFileOffset offset: UInt64) {}
+
+ override func truncateFile(atOffset offset: UInt64) {}
+
+ override func synchronizeFile() {}
+
+ override func closeFile() {}
+
+ deinit {}
+ }
+
+ return NullDevice(fileDescriptor: -1, closeOnDealloc: false)
+ }()
+
open class var nullDevice: FileHandle {
- NSUnimplemented()
+ return _nulldeviceFileHandle
}
-
+
public convenience init?(forReadingAtPath path: String) {
self.init(path: path, flags: O_RDONLY, createMode: 0)
}
diff --git a/Foundation/NSJSONSerialization.swift b/Foundation/NSJSONSerialization.swift
index f2ffeaa..cd4aed7 100644
--- a/Foundation/NSJSONSerialization.swift
+++ b/Foundation/NSJSONSerialization.swift
@@ -277,21 +277,21 @@
}
mutating func serializeJSON(_ obj: Any) throws {
-
- if let str = obj as? String {
+
+ switch (obj) {
+ case let str as String:
try serializeString(str)
- } else if let num = _SwiftValue.store(obj) as? NSNumber {
- try serializeNumber(num)
- } else if let array = obj as? Array<Any> {
+ case let boolValue as Bool:
+ serializeBool(boolValue)
+ case _ where _SwiftValue.store(obj) is NSNumber:
+ try serializeNumber(_SwiftValue.store(obj) as! NSNumber)
+ case let array as Array<Any>:
try serializeArray(array)
- } else if let dict = obj as? Dictionary<AnyHashable, Any> {
+ case let dict as Dictionary<AnyHashable, Any>:
try serializeDictionary(dict)
- } else if let null = obj as? NSNull {
+ case let null as NSNull:
try serializeNull(null)
- } else if let boolVal = obj as? Bool {
- try serializeNumber(NSNumber(value: boolVal))
- }
- else {
+ default:
throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.propertyListReadCorrupt.rawValue, userInfo: ["NSDebugDescription" : "Invalid object cannot be serialized"])
}
}
@@ -326,15 +326,26 @@
writer("\"")
}
+ func serializeBool(_ bool: Bool) {
+ switch bool {
+ case true:
+ writer("true")
+ case false:
+ writer("false")
+ }
+ }
+
mutating func serializeNumber(_ num: NSNumber) throws {
if num.doubleValue.isInfinite || num.doubleValue.isNaN {
throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.propertyListReadCorrupt.rawValue, userInfo: ["NSDebugDescription" : "Number cannot be infinity or NaN"])
}
- // Cannot detect type information (e.g. bool) as there is no objCType property on NSNumber in Swift
- // So, just print the number
-
- writer(_serializationString(for: num))
+ switch num._objCType {
+ case .Bool:
+ serializeBool(num.boolValue)
+ default:
+ writer(_serializationString(for: num))
+ }
}
mutating func serializeArray(_ array: [Any]) throws {
diff --git a/Foundation/NSNumber.swift b/Foundation/NSNumber.swift
index 14bec84..5f75de8 100644
--- a/Foundation/NSNumber.swift
+++ b/Foundation/NSNumber.swift
@@ -200,7 +200,9 @@
// This layout MUST be the same as CFNumber so that they are bridgeable
private var _base = _CFInfo(typeID: CFNumberGetTypeID())
private var _pad: UInt64 = 0
-
+
+ internal let _objCType: _NSSimpleObjCType
+
internal var _cfObject: CFType {
return unsafeBitCast(self, to: CFType.self)
}
@@ -221,77 +223,95 @@
}
return false
}
+
+ open override var objCType: UnsafePointer<Int8> {
+ return UnsafePointer<Int8>(bitPattern: UInt(_objCType.rawValue.value))!
+ }
deinit {
_CFDeinit(self)
}
public init(value: Int8) {
+ _objCType = .Char
super.init()
_CFNumberInitInt8(_cfObject, value)
}
public init(value: UInt8) {
+ _objCType = .UChar
super.init()
_CFNumberInitUInt8(_cfObject, value)
}
public init(value: Int16) {
+ _objCType = .Short
super.init()
_CFNumberInitInt16(_cfObject, value)
}
public init(value: UInt16) {
+ _objCType = .UShort
super.init()
_CFNumberInitUInt16(_cfObject, value)
}
public init(value: Int32) {
+ _objCType = .Long
super.init()
_CFNumberInitInt32(_cfObject, value)
}
public init(value: UInt32) {
+ _objCType = .ULong
super.init()
_CFNumberInitUInt32(_cfObject, value)
}
public init(value: Int) {
+ _objCType = .Int
super.init()
_CFNumberInitInt(_cfObject, value)
}
public init(value: UInt) {
+ _objCType = .UInt
super.init()
_CFNumberInitUInt(_cfObject, value)
}
public init(value: Int64) {
+ _objCType = .LongLong
super.init()
_CFNumberInitInt64(_cfObject, value)
}
public init(value: UInt64) {
+ _objCType = .ULongLong
super.init()
_CFNumberInitUInt64(_cfObject, value)
}
public init(value: Float) {
+ _objCType = .Float
super.init()
_CFNumberInitFloat(_cfObject, value)
}
public init(value: Double) {
+ _objCType = .Double
super.init()
_CFNumberInitDouble(_cfObject, value)
}
public init(value: Bool) {
+ _objCType = .Bool
super.init()
_CFNumberInitBool(_cfObject, value)
}
override internal init() {
+ _objCType = .Undef
super.init()
}
diff --git a/Foundation/NSNumberFormatter.swift b/Foundation/NSNumberFormatter.swift
index d0cf61e..fe319d1 100644
--- a/Foundation/NSNumberFormatter.swift
+++ b/Foundation/NSNumberFormatter.swift
@@ -70,6 +70,9 @@
let obj = CFNumberFormatterCreate(kCFAllocatorSystemDefault, locale._cfObject, numberStyle)!
_setFormatterAttributes(obj)
+ if let format = _format {
+ CFNumberFormatterSetFormat(obj, format._cfObject)
+ }
_currentCfFormatter = obj
return obj
}
@@ -99,12 +102,13 @@
open func number(from string: String) -> NSNumber? {
var range = CFRange(location: 0, length: string.length)
let number = withUnsafeMutablePointer(to: &range) { (rangePointer: UnsafeMutablePointer<CFRange>) -> NSNumber? in
-
+
#if os(OSX) || os(iOS)
- let result = CFNumberFormatterCreateNumberFromString(kCFAllocatorSystemDefault, _cfFormatter, string._cfObject, rangePointer, CFNumberFormatterOptionFlags.parseIntegersOnly.rawValue)
+ let parseOption = allowsFloats ? 0 : CFNumberFormatterOptionFlags.parseIntegersOnly.rawValue
#else
- let result = CFNumberFormatterCreateNumberFromString(kCFAllocatorSystemDefault, _cfFormatter, string._cfObject, rangePointer, CFOptionFlags(kCFNumberFormatterParseIntegersOnly))
+ let parseOption = allowsFloats ? 0 : CFOptionFlags(kCFNumberFormatterParseIntegersOnly)
#endif
+ let result = CFNumberFormatterCreateNumberFromString(kCFAllocatorSystemDefault, _cfFormatter, string._cfObject, rangePointer, parseOption)
return result?._nsObject
}
@@ -157,7 +161,7 @@
_setFormatterAttribute(formatter, attributeName: kCFNumberFormatterPerMillSymbol, value: _percentSymbol?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFNumberFormatterInternationalCurrencySymbol, value: _internationalCurrencySymbol?._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFNumberFormatterCurrencyGroupingSeparator, value: _currencyGroupingSeparator?._cfObject)
- _setFormatterAttribute(formatter, attributeName: kCFNumberFormatterIsLenient, value: kCFBooleanTrue)
+ _setFormatterAttribute(formatter, attributeName: kCFNumberFormatterIsLenient, value: _lenient._cfObject)
_setFormatterAttribute(formatter, attributeName: kCFNumberFormatterUseSignificantDigits, value: _usesSignificantDigits._cfObject)
if _usesSignificantDigits {
_setFormatterAttribute(formatter, attributeName: kCFNumberFormatterMinSignificantDigits, value: _minimumSignificantDigits._bridgeToObjectiveC()._cfObject)
@@ -182,7 +186,7 @@
switch newValue {
case .none, .ordinal, .spellOut:
_usesSignificantDigits = false
-
+
case .currency, .currencyPlural, .currencyISOCode, .currencyAccounting:
_usesSignificantDigits = false
_usesGroupingSeparator = true
@@ -838,10 +842,10 @@
//
- internal var _format: String = "#;0;#"
+ internal var _format: String?
open var format: String {
get {
- return _format
+ return _format ?? "#;0;#"
}
set {
_reset()
diff --git a/Foundation/NSPredicate.swift b/Foundation/NSPredicate.swift
index 083782b..3aada9c 100644
--- a/Foundation/NSPredicate.swift
+++ b/Foundation/NSPredicate.swift
@@ -15,8 +15,8 @@
private enum PredicateKind {
case boolean(Bool)
case block((Any?, [String : Any]?) -> Bool)
- // TODO: case for init(format:argumentArray:)
- // TODO: case for init(fromMetadataQueryString:)
+ case format(String)
+ case metadataQuery(String)
}
private let kind: PredicateKind
@@ -26,11 +26,33 @@
}
public required init?(coder aDecoder: NSCoder) {
- NSUnimplemented()
+ guard aDecoder.allowsKeyedCoding else {
+ preconditionFailure("Unkeyed coding is unsupported.")
+ }
+
+ let encodedBool = aDecoder.decodeBool(forKey: "NS.boolean.value")
+ self.kind = .boolean(encodedBool)
+
+ super.init()
}
open func encode(with aCoder: NSCoder) {
- NSUnimplemented()
+ guard aCoder.allowsKeyedCoding else {
+ preconditionFailure("Unkeyed coding is unsupported.")
+ }
+
+ //TODO: store kind key for .boolean, .format, .metadataQuery
+
+ switch self.kind {
+ case .boolean(let value):
+ aCoder.encode(value, forKey: "NS.boolean.value")
+ case .block:
+ preconditionFailure("NSBlockPredicate cannot be encoded or decoded.")
+ case .format:
+ NSUnimplemented()
+ case .metadataQuery:
+ NSUnimplemented()
+ }
}
open override func copy() -> Any {
@@ -38,7 +60,38 @@
}
open func copy(with zone: NSZone? = nil) -> Any {
- NSUnimplemented()
+ switch self.kind {
+ case .boolean(let value):
+ return NSPredicate(value: value)
+ case .block(let block):
+ return NSPredicate(block: block)
+ case .format:
+ NSUnimplemented()
+ case .metadataQuery:
+ NSUnimplemented()
+ }
+ }
+
+ open override func isEqual(_ object: Any?) -> Bool {
+ if let other = object as? NSPredicate {
+ if other === self {
+ return true
+ } else {
+ switch (other.kind, self.kind) {
+ case (.boolean(let otherBool), .boolean(let selfBool)):
+ return otherBool == selfBool
+ case (.format, .format):
+ NSUnimplemented()
+ case (.metadataQuery, .metadataQuery):
+ NSUnimplemented()
+ default:
+ // NSBlockPredicate returns false even for copy
+ return false
+ }
+ }
+ }
+
+ return false
}
// Parse predicateFormat and return an appropriate predicate
@@ -58,7 +111,21 @@
super.init()
}
- open var predicateFormat: String { NSUnimplemented() } // returns the format string of the predicate
+ open var predicateFormat: String {
+ switch self.kind {
+ case .boolean(let value):
+ return value ? "TRUEPREDICATE" : "FALSEPREDICATE"
+ case .block:
+ // TODO: Bring NSBlockPredicate's predicateFormat to macOS's Foundation version
+ // let address = unsafeBitCast(block, to: Int.self)
+ // return String(format:"BLOCKPREDICATE(%2X)", address)
+ return "BLOCKPREDICATE"
+ case .format:
+ NSUnimplemented()
+ case .metadataQuery:
+ NSUnimplemented()
+ }
+ }
open func withSubstitutionVariables(_ variables: [String : Any]) -> Self { NSUnimplemented() } // substitute constant values for variables
@@ -76,6 +143,10 @@
return value
case let .block(block):
return block(object, bindings)
+ case .format:
+ NSUnimplemented()
+ case .metadataQuery:
+ NSUnimplemented()
}
} // single pass evaluation substituting variables from the bindings dictionary for any variable expressions encountered
diff --git a/Foundation/NSPropertyList.swift b/Foundation/NSPropertyList.swift
index 7ea248a..5141c42 100644
--- a/Foundation/NSPropertyList.swift
+++ b/Foundation/NSPropertyList.swift
@@ -44,10 +44,11 @@
#else
let fmt = CFPropertyListFormat(format.rawValue)
#endif
- return CFPropertyListIsValid(unsafeBitCast(_SwiftValue.store(plist), to: CFPropertyList.self), fmt)
+ let plistObj = _SwiftValue.store(plist)
+ return CFPropertyListIsValid(plistObj, fmt)
}
-
- open class func data(fromPropertyList plist: AnyObject, format: PropertyListFormat, options opt: WriteOptions) throws -> Data {
+
+ open class func data(fromPropertyList plist: Any, format: PropertyListFormat, options opt: WriteOptions) throws -> Data {
var error: Unmanaged<CFError>? = nil
let result = withUnsafeMutablePointer(to: &error) { (outErr: UnsafeMutablePointer<Unmanaged<CFError>?>) -> CFData? in
#if os(OSX) || os(iOS)
@@ -56,7 +57,8 @@
let fmt = CFPropertyListFormat(format.rawValue)
#endif
let options = CFOptionFlags(opt)
- return CFPropertyListCreateData(kCFAllocatorSystemDefault, plist, fmt, options, outErr)
+ let plistObj = _SwiftValue.store(plist)
+ return CFPropertyListCreateData(kCFAllocatorSystemDefault, plistObj, fmt, options, outErr)
}
if let res = result {
return res._swiftObject
@@ -64,7 +66,7 @@
throw error!.takeRetainedValue()._nsObject
}
}
-
+
/// - Experiment: Note that the return type of this function is different than on Darwin Foundation (Any instead of AnyObject). This is likely to change once we have a more complete story for bridging in place.
open class func propertyList(from data: Data, options opt: ReadOptions = [], format: UnsafeMutablePointer<PropertyListFormat>?) throws -> Any {
var fmt = kCFPropertyListBinaryFormat_v1_0
diff --git a/Foundation/NSURLRequest.swift b/Foundation/NSURLRequest.swift
index 7081e0f..a044297 100644
--- a/Foundation/NSURLRequest.swift
+++ b/Foundation/NSURLRequest.swift
@@ -156,11 +156,101 @@
}
public required init?(coder aDecoder: NSCoder) {
- NSUnimplemented()
+ guard aDecoder.allowsKeyedCoding else {
+ preconditionFailure("Unkeyed coding is unsupported.")
+ }
+
+ if let encodedURL = aDecoder.decodeObject(forKey: "NS.url") as? NSURL {
+ self.url = encodedURL._swiftObject
+ }
+
+ if let encodedHeaders = aDecoder.decodeObject(forKey: "NS._allHTTPHeaderFields") as? NSDictionary {
+ self._allHTTPHeaderFields = encodedHeaders.reduce([String : String]()) { result, item in
+ var result = result
+ if let key = item.key as? NSString,
+ let value = item.value as? NSString {
+ result[key._swiftObject] = value._swiftObject
+ }
+ return result
+ }
+ }
+
+ if let encodedDocumentURL = aDecoder.decodeObject(forKey: "NS.mainDocumentURL") as? NSURL {
+ self.mainDocumentURL = encodedDocumentURL._swiftObject
+ }
+
+ if let encodedMethod = aDecoder.decodeObject(forKey: "NS.httpMethod") as? NSString {
+ self.httpMethod = encodedMethod._swiftObject
+ }
+
+ let encodedCachePolicy = aDecoder.decodeObject(forKey: "NS._cachePolicy") as! NSNumber
+ self._cachePolicy = CachePolicy(rawValue: encodedCachePolicy.uintValue)!
+
+ let encodedTimeout = aDecoder.decodeObject(forKey: "NS._timeoutInterval") as! NSNumber
+ self._timeoutInterval = encodedTimeout.doubleValue
+
+ let encodedHttpBody: Data? = aDecoder.withDecodedUnsafeBufferPointer(forKey: "NS.httpBody") {
+ guard let buffer = $0 else { return nil }
+ return Data(buffer: buffer)
+ }
+
+ if let encodedHttpBody = encodedHttpBody {
+ self._body = .data(encodedHttpBody)
+ }
+
+ let encodedNetworkServiceType = aDecoder.decodeObject(forKey: "NS._networkServiceType") as! NSNumber
+ self._networkServiceType = NetworkServiceType(rawValue: encodedNetworkServiceType.uintValue)!
+
+ let encodedCellularAccess = aDecoder.decodeObject(forKey: "NS._allowsCellularAccess") as! NSNumber
+ self._allowsCellularAccess = encodedCellularAccess.boolValue
+
+ let encodedHandleCookies = aDecoder.decodeObject(forKey: "NS._httpShouldHandleCookies") as! NSNumber
+ self._httpShouldHandleCookies = encodedHandleCookies.boolValue
+
+ let encodedUsePipelining = aDecoder.decodeObject(forKey: "NS._httpShouldUsePipelining") as! NSNumber
+ self._httpShouldUsePipelining = encodedUsePipelining.boolValue
}
open func encode(with aCoder: NSCoder) {
- NSUnimplemented()
+ guard aCoder.allowsKeyedCoding else {
+ preconditionFailure("Unkeyed coding is unsupported.")
+ }
+
+ aCoder.encode(self.url?._bridgeToObjectiveC(), forKey: "NS.url")
+ aCoder.encode(self._allHTTPHeaderFields?._bridgeToObjectiveC(), forKey: "NS._allHTTPHeaderFields")
+ aCoder.encode(self.mainDocumentURL?._bridgeToObjectiveC(), forKey: "NS.mainDocumentURL")
+ aCoder.encode(self.httpMethod?._bridgeToObjectiveC(), forKey: "NS.httpMethod")
+ aCoder.encode(self._cachePolicy.rawValue._bridgeToObjectiveC(), forKey: "NS._cachePolicy")
+ aCoder.encode(self._timeoutInterval._bridgeToObjectiveC(), forKey: "NS._timeoutInterval")
+ if let httpBody = self.httpBody?._bridgeToObjectiveC() {
+ let bytePtr = httpBody.bytes.bindMemory(to: UInt8.self, capacity: httpBody.length)
+ aCoder.encodeBytes(bytePtr, length: httpBody.length, forKey: "NS.httpBody")
+ }
+ //On macOS input stream is not encoded.
+ aCoder.encode(self._networkServiceType.rawValue._bridgeToObjectiveC(), forKey: "NS._networkServiceType")
+ aCoder.encode(self._allowsCellularAccess._bridgeToObjectiveC(), forKey: "NS._allowsCellularAccess")
+ aCoder.encode(self._httpShouldHandleCookies._bridgeToObjectiveC(), forKey: "NS._httpShouldHandleCookies")
+ aCoder.encode(self._httpShouldUsePipelining._bridgeToObjectiveC(), forKey: "NS._httpShouldUsePipelining")
+ }
+
+ open override func isEqual(_ object: Any?) -> Bool {
+ //On macOS this fields do not determine the result:
+ //allHTTPHeaderFields
+ //timeoutInterval
+ //httBody
+ //networkServiceType
+ //httpShouldUsePipelining
+ if let other = object as? NSURLRequest {
+ return other === self
+ || (other.url == self.url
+ && other.mainDocumentURL == self.mainDocumentURL
+ && other.httpMethod == self.httpMethod
+ && other._cachePolicy == self._cachePolicy
+ && other.httpBodyStream == self.httpBodyStream
+ && other._allowsCellularAccess == self._allowsCellularAccess
+ && other._httpShouldHandleCookies == self._httpShouldHandleCookies)
+ }
+ return false
}
/// Indicates that NSURLRequest implements the NSSecureCoding protocol.
@@ -289,7 +379,7 @@
/// example.
open class NSMutableURLRequest : NSURLRequest {
public required init?(coder aDecoder: NSCoder) {
- NSUnimplemented()
+ super.init(coder: aDecoder)
}
public convenience init(url: URL) {
diff --git a/Foundation/NSURLResponse.swift b/Foundation/NSURLResponse.swift
index e74f9f1..e39bfcf 100644
--- a/Foundation/NSURLResponse.swift
+++ b/Foundation/NSURLResponse.swift
@@ -23,11 +23,39 @@
}
public required init?(coder aDecoder: NSCoder) {
- NSUnimplemented()
+ guard aDecoder.allowsKeyedCoding else {
+ preconditionFailure("Unkeyed coding is unsupported.")
+ }
+
+ if let encodedUrl = aDecoder.decodeObject(forKey: "NS.url") as? NSURL {
+ self.url = encodedUrl._swiftObject
+ }
+
+ if let encodedMimeType = aDecoder.decodeObject(forKey: "NS.mimeType") as? NSString {
+ self.mimeType = encodedMimeType._swiftObject
+ }
+
+ self.expectedContentLength = aDecoder.decodeInt64(forKey: "NS.expectedContentLength")
+
+ if let encodedEncodingName = aDecoder.decodeObject(forKey: "NS.textEncodingName") as? NSString {
+ self.textEncodingName = encodedEncodingName._swiftObject
+ }
+
+ if let encodedFilename = aDecoder.decodeObject(forKey: "NS.suggestedFilename") as? NSString {
+ self.suggestedFilename = encodedFilename._swiftObject
+ }
}
open func encode(with aCoder: NSCoder) {
- NSUnimplemented()
+ guard aCoder.allowsKeyedCoding else {
+ preconditionFailure("Unkeyed coding is unsupported.")
+ }
+
+ aCoder.encode(self.url?._bridgeToObjectiveC(), forKey: "NS.url")
+ aCoder.encode(self.mimeType?._bridgeToObjectiveC(), forKey: "NS.mimeType")
+ aCoder.encode(self.expectedContentLength, forKey: "NS.expectedContentLength")
+ aCoder.encode(self.textEncodingName?._bridgeToObjectiveC(), forKey: "NS.textEncodingName")
+ aCoder.encode(self.suggestedFilename?._bridgeToObjectiveC(), forKey: "NS.suggestedFilename")
}
open override func copy() -> Any {
@@ -135,7 +163,27 @@
}
public required init?(coder aDecoder: NSCoder) {
- NSUnimplemented()
+ guard aDecoder.allowsKeyedCoding else {
+ preconditionFailure("Unkeyed coding is unsupported.")
+ }
+
+ self.statusCode = aDecoder.decodeInteger(forKey: "NS.statusCode")
+
+ if let encodedHeaders = aDecoder.decodeObject(forKey: "NS.allHeaderFields") as? NSDictionary {
+ self.allHeaderFields = encodedHeaders._swiftObject
+ } else {
+ self.allHeaderFields = [:]
+ }
+
+ super.init(coder: aDecoder)
+ }
+
+ open override func encode(with aCoder: NSCoder) {
+ super.encode(with: aCoder) //Will fail if .allowsKeyedCoding == false
+
+ aCoder.encode(self.statusCode, forKey: "NS.statusCode")
+ aCoder.encode(self.allHeaderFields._bridgeToObjectiveC(), forKey: "NS.allHeaderFields")
+
}
/// The HTTP status code of the receiver.
diff --git a/TestFoundation/TestNSArray.swift b/TestFoundation/TestNSArray.swift
index 132747b..c905e52 100644
--- a/TestFoundation/TestNSArray.swift
+++ b/TestFoundation/TestNSArray.swift
@@ -500,7 +500,7 @@
}
private func createTestFile(_ path: String, _contents: Data) -> String? {
- let tempDir = "/tmp/TestFoundation_Playground_" + NSUUID().uuidString + "/"
+ let tempDir = NSTemporaryDirectory() + "TestFoundation_Playground_" + NSUUID().uuidString + "/"
do {
try FileManager.default.createDirectory(atPath: tempDir, withIntermediateDirectories: false, attributes: nil)
if FileManager.default.createFile(atPath: tempDir + "/" + path, contents: _contents, attributes: nil) {
diff --git a/TestFoundation/TestNSBundle.swift b/TestFoundation/TestNSBundle.swift
index e427992..8e40179 100644
--- a/TestFoundation/TestNSBundle.swift
+++ b/TestFoundation/TestNSBundle.swift
@@ -108,7 +108,7 @@
private func _setupPlayground() -> String? {
// Make sure the directory is uniquely named
- let tempDir = "/tmp/TestFoundation_Playground_" + NSUUID().uuidString + "/"
+ let tempDir = NSTemporaryDirectory() + "TestFoundation_Playground_" + NSUUID().uuidString + "/"
do {
try FileManager.default.createDirectory(atPath: tempDir, withIntermediateDirectories: false, attributes: nil)
@@ -179,7 +179,7 @@
}
func test_bundleWithInvalidPath(){
- let bundleInvalid = Bundle(path: "/tmp/test.playground")
+ let bundleInvalid = Bundle(path: NSTemporaryDirectory() + "test.playground")
XCTAssertNil(bundleInvalid)
}
diff --git a/TestFoundation/TestNSDictionary.swift b/TestFoundation/TestNSDictionary.swift
index 002a119..ff415ef 100644
--- a/TestFoundation/TestNSDictionary.swift
+++ b/TestFoundation/TestNSDictionary.swift
@@ -205,7 +205,7 @@
}
private func createTestFile(_ path: String, _contents: Data) -> String? {
- let tempDir = "/tmp/TestFoundation_Playground_" + NSUUID().uuidString + "/"
+ let tempDir = NSTemporaryDirectory() + "TestFoundation_Playground_" + NSUUID().uuidString + "/"
do {
try FileManager.default.createDirectory(atPath: tempDir, withIntermediateDirectories: false, attributes: nil)
if FileManager.default.createFile(atPath: tempDir + "/" + path, contents: _contents,
diff --git a/TestFoundation/TestNSFileHandle.swift b/TestFoundation/TestNSFileHandle.swift
old mode 100644
new mode 100755
index 69a74cc..93357ff
--- a/TestFoundation/TestNSFileHandle.swift
+++ b/TestFoundation/TestNSFileHandle.swift
@@ -19,6 +19,7 @@
static var allTests : [(String, (TestNSFileHandle) -> () throws -> ())] {
return [
("test_pipe", test_pipe),
+ ("test_nullDevice", test_nullDevice),
]
}
@@ -38,4 +39,23 @@
XCTAssertEqual(output, input)
}
}
+
+ func test_nullDevice() {
+ let fh = FileHandle.nullDevice
+
+ XCTAssertEqual(fh.fileDescriptor, -1)
+ fh.closeFile()
+ fh.seek(toFileOffset: 10)
+ XCTAssertEqual(fh.offsetInFile, 0)
+ XCTAssertEqual(fh.seekToEndOfFile(), 0)
+ XCTAssertEqual(fh.readData(ofLength: 15).count, 0)
+ fh.synchronizeFile()
+
+ fh.write(Data(bytes: [1,2]))
+ fh.seek(toFileOffset: 0)
+ XCTAssertEqual(fh.availableData.count, 0)
+ fh.write(Data(bytes: [1,2]))
+ fh.seek(toFileOffset: 0)
+ XCTAssertEqual(fh.readDataToEndOfFile().count, 0)
+ }
}
diff --git a/TestFoundation/TestNSFileManager.swift b/TestFoundation/TestNSFileManager.swift
index b0c9afd..1bdffd3 100644
--- a/TestFoundation/TestNSFileManager.swift
+++ b/TestFoundation/TestNSFileManager.swift
@@ -38,7 +38,7 @@
func test_createDirectory() {
let fm = FileManager.default
- let path = "/tmp/testdir\(NSUUID().uuidString)"
+ let path = NSTemporaryDirectory() + "testdir\(NSUUID().uuidString)"
ignoreError { try fm.removeItem(atPath: path) }
@@ -63,7 +63,7 @@
func test_createFile() {
let fm = FileManager.default
- let path = "/tmp/testfile\(NSUUID().uuidString)"
+ let path = NSTemporaryDirectory() + "testfile\(NSUUID().uuidString)"
ignoreError { try fm.removeItem(atPath: path) }
@@ -83,8 +83,8 @@
func test_moveFile() {
let fm = FileManager.default
- let path = "/tmp/testfile\(NSUUID().uuidString)"
- let path2 = "/tmp/testfile2\(NSUUID().uuidString)"
+ let path = NSTemporaryDirectory() + "testfile\(NSUUID().uuidString)"
+ let path2 = NSTemporaryDirectory() + "testfile2\(NSUUID().uuidString)"
func cleanup() {
ignoreError { try fm.removeItem(atPath: path) }
@@ -114,7 +114,7 @@
func test_fileAttributes() {
let fm = FileManager.default
- let path = "/tmp/test_fileAttributes\(NSUUID().uuidString)"
+ let path = NSTemporaryDirectory() + "test_fileAttributes\(NSUUID().uuidString)"
ignoreError { try fm.removeItem(atPath: path) }
@@ -161,7 +161,7 @@
}
func test_setFileAttributes() {
- let path = "/tmp/test_setFileAttributes\(NSUUID().uuidString)"
+ let path = NSTemporaryDirectory() + "test_setFileAttributes\(NSUUID().uuidString)"
let fm = FileManager.default
ignoreError { try fm.removeItem(atPath: path) }
@@ -189,10 +189,10 @@
func test_pathEnumerator() {
let fm = FileManager.default
let testDirName = "testdir\(NSUUID().uuidString)"
- let basePath = "/tmp/\(testDirName)"
- let itemPath = "/tmp/\(testDirName)/item"
- let basePath2 = "/tmp/\(testDirName)/path2"
- let itemPath2 = "/tmp/\(testDirName)/path2/item"
+ let basePath = NSTemporaryDirectory() + "\(testDirName)"
+ let itemPath = NSTemporaryDirectory() + "\(testDirName)/item"
+ let basePath2 = NSTemporaryDirectory() + "\(testDirName)/path2"
+ let itemPath2 = NSTemporaryDirectory() + "\(testDirName)/path2/item"
ignoreError { try fm.removeItem(atPath: basePath) }
@@ -222,8 +222,8 @@
func test_directoryEnumerator() {
let fm = FileManager.default
let testDirName = "testdir\(NSUUID().uuidString)"
- let path = "/tmp/\(testDirName)"
- let itemPath = "/tmp/\(testDirName)/item"
+ let path = NSTemporaryDirectory() + "\(testDirName)"
+ let itemPath = NSTemporaryDirectory() + "\(testDirName)/item"
ignoreError { try fm.removeItem(atPath: path) }
@@ -244,8 +244,8 @@
XCTFail()
}
- let subDirPath = "/tmp/\(testDirName)/testdir2"
- let subDirItemPath = "/tmp/\(testDirName)/testdir2/item"
+ let subDirPath = NSTemporaryDirectory() + "\(testDirName)/testdir2"
+ let subDirItemPath = NSTemporaryDirectory() + "\(testDirName)/testdir2/item"
do {
try fm.createDirectory(atPath: subDirPath, withIntermediateDirectories: false, attributes: nil)
let _ = fm.createFile(atPath: subDirItemPath, contents: Data(), attributes: nil)
@@ -320,9 +320,9 @@
func test_contentsOfDirectoryAtPath() {
let fm = FileManager.default
let testDirName = "testdir\(NSUUID().uuidString)"
- let path = "/tmp/\(testDirName)"
- let itemPath1 = "/tmp/\(testDirName)/item"
- let itemPath2 = "/tmp/\(testDirName)/item2"
+ let path = NSTemporaryDirectory() + "\(testDirName)"
+ let itemPath1 = NSTemporaryDirectory() + "\(testDirName)/item"
+ let itemPath2 = NSTemporaryDirectory() + "\(testDirName)/item2"
ignoreError { try fm.removeItem(atPath: path) }
@@ -363,11 +363,11 @@
func test_subpathsOfDirectoryAtPath() {
let fm = FileManager.default
- let path = "/tmp/testdir"
- let path2 = "/tmp/testdir/sub"
- let itemPath1 = "/tmp/testdir/item"
- let itemPath2 = "/tmp/testdir/item2"
- let itemPath3 = "/tmp/testdir/sub/item3"
+ let path = NSTemporaryDirectory() + "testdir"
+ let path2 = NSTemporaryDirectory() + "testdir/sub"
+ let itemPath1 = NSTemporaryDirectory() + "testdir/item"
+ let itemPath2 = NSTemporaryDirectory() + "testdir/item2"
+ let itemPath3 = NSTemporaryDirectory() + "testdir/sub/item3"
ignoreError { try fm.removeItem(atPath: path) }
diff --git a/TestFoundation/TestNSJSONSerialization.swift b/TestFoundation/TestNSJSONSerialization.swift
index d40a1c0..3ce12e8 100644
--- a/TestFoundation/TestNSJSONSerialization.swift
+++ b/TestFoundation/TestNSJSONSerialization.swift
@@ -777,7 +777,7 @@
// Cannot generate "true"/"false" currently
json = [NSNumber(value:false),NSNumber(value:true)]
- XCTAssertEqual(try trySerialize(json), "[0,1]")
+ XCTAssertEqual(try trySerialize(json), "[false,true]")
}
func test_serialize_stringEscaping() {
@@ -931,16 +931,18 @@
func test_booleanJSONObject() {
do {
- let mydata = try JSONSerialization.data(withJSONObject: [true])
- XCTAssertEqual(String(data: mydata, encoding: String.Encoding.utf8), "[1]")
+ let objectLikeBoolArray = try JSONSerialization.data(withJSONObject: [true, NSNumber(value: false), NSNumber(value: true)] as Array<Any>)
+ XCTAssertEqual(String(data: objectLikeBoolArray, encoding: .utf8), "[true,false,true]")
+ let valueLikeBoolArray = try JSONSerialization.data(withJSONObject: [false, true, false])
+ XCTAssertEqual(String(data: valueLikeBoolArray, encoding: .utf8), "[false,true,false]")
} catch {
XCTFail("Failed during serialization")
}
- XCTAssertTrue(JSONSerialization.isValidJSONObject([1]))
+ XCTAssertTrue(JSONSerialization.isValidJSONObject([true]))
}
private func createTestFile(_ path: String,_contents: Data) -> String? {
- let tempDir = "/tmp/TestFoundation_Playground_" + NSUUID().uuidString + "/"
+ let tempDir = NSTemporaryDirectory() + "TestFoundation_Playground_" + NSUUID().uuidString + "/"
do {
try FileManager.default.createDirectory(atPath: tempDir, withIntermediateDirectories: false, attributes: nil)
if FileManager.default.createFile(atPath: tempDir + "/" + path, contents: _contents,
diff --git a/TestFoundation/TestNSLocale.swift b/TestFoundation/TestNSLocale.swift
index 3d18791..f83edf3 100644
--- a/TestFoundation/TestNSLocale.swift
+++ b/TestFoundation/TestNSLocale.swift
@@ -19,9 +19,24 @@
static var allTests: [(String, (TestNSLocale) -> () throws -> Void)] {
return [
("test_constants", test_constants),
+ ("test_Identifier", test_Identifier),
("test_copy", test_copy)
]
}
+
+ func test_Identifier() {
+ // Current locale identifier should not be empty
+ // Or things like NSNumberFormatter spellOut style won't work
+ XCTAssertFalse(Locale.current.identifier.isEmpty)
+
+ let enUSID = "en_US"
+ let locale = Locale(identifier: enUSID)
+ XCTAssertEqual(enUSID, locale.identifier)
+
+ let deDEID = "de_DE"
+ let germanLocale = Locale(identifier: deDEID)
+ XCTAssertEqual(deDEID, germanLocale.identifier)
+ }
func test_constants() {
XCTAssertEqual(NSCurrentLocaleDidChangeNotification, "kCFLocaleCurrentLocaleDidChangeNotification",
diff --git a/TestFoundation/TestNSNumberFormatter.swift b/TestFoundation/TestNSNumberFormatter.swift
index 9511770..222b3d2 100644
--- a/TestFoundation/TestNSNumberFormatter.swift
+++ b/TestFoundation/TestNSNumberFormatter.swift
@@ -53,7 +53,9 @@
("test_lenient", test_lenient),
("test_minimumSignificantDigits", test_minimumSignificantDigits),
("test_maximumSignificantDigits", test_maximumSignificantDigits),
- ("test_stringFor", test_stringFor)
+ ("test_stringFor", test_stringFor),
+ ("test_numberFrom", test_numberFrom),
+ //("test_en_US_initialValues", test_en_US_initialValues)
]
}
@@ -68,11 +70,15 @@
XCTAssertEqual(formattedString, "T 42_00")
*/
}
-
+
func test_decimalSeparator() {
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .decimal
- numberFormatter.decimalSeparator = "-"
+
+ let separator = "-"
+ numberFormatter.decimalSeparator = separator
+ XCTAssertEqual(numberFormatter.decimalSeparator, separator)
+
let formattedString = numberFormatter.string(from: 42.42)
XCTAssertEqual(formattedString, "42-42")
}
@@ -147,14 +153,28 @@
}
func test_plusSignSymbol() {
- //FIXME: How do we show the plus sign from a NSNumberFormatter?
+ // ex. 1.0E+1 in scientific notation
+ let numberFormatter = NumberFormatter()
+ let format = "#E+0"
+ numberFormatter.format = format
+ XCTAssertEqual(numberFormatter.format, format)
-// let numberFormatter = NumberFormatter()
-// numberFormatter.plusSign = "π"
-// let formattedString = numberFormatter.stringFromNumber(42)
-// XCTAssertEqual(formattedString, "π42")
+ let sign = "π"
+ numberFormatter.plusSign = sign
+ XCTAssertEqual(numberFormatter.plusSign, sign)
+
+ let formattedString = numberFormatter.string(from: 420000000000000000)
+ XCTAssertNotNil(formattedString)
+ XCTAssertEqual(formattedString, "4.2Eπ17")
+
+ // Verify a negative exponent does not have the π
+ let noPlusString = numberFormatter.string(from: -0.420)
+ XCTAssertNotNil(noPlusString)
+ if let fmt = noPlusString {
+ XCTAssertFalse(fmt.contains(sign), "Expected format of -0.420 (-4.2E-1) shouldn't have a plus sign which was set as \(sign)")
+ }
}
-
+
func test_currencySymbol() {
// Disabled due to [SR-250]
/*
@@ -316,14 +336,30 @@
*/
}
- //FIXME: Something is wrong with numberFromString implementation, I don't know exactly why, but it's not working.
func test_lenient() {
-// let numberFormatter = NumberFormatter()
-// numberFormatter.numberStyle = .CurrencyStyle
-// let nilNumberBeforeLenient = numberFormatter.numberFromString("42")
+ let numberFormatter = NumberFormatter()
+ // Not lenient by default
+ XCTAssertFalse(numberFormatter.isLenient)
+
+ // Lenient allows wrong style -- not lenient here
+ numberFormatter.numberStyle = .spellOut
+ XCTAssertEqual(numberFormatter.numberStyle, .spellOut)
+// let nilNumber = numberFormatter.number(from: "2.22")
+ // FIXME: Not nil on Linux?
+ //XCTAssertNil(nilNumber)
+ // Lenient allows wrong style
+ numberFormatter.isLenient = true
+ XCTAssertTrue(numberFormatter.isLenient)
+ let number = numberFormatter.number(from: "2.22")
+ XCTAssertEqual(number, 2.22)
+
+ // TODO: Add some tests with currency after [SR-250] resolved
+// numberFormatter.numberStyle = .currency
+// let nilNumberBeforeLenient = numberFormatter.number(from: "42")
+//
// XCTAssertNil(nilNumberBeforeLenient)
-// numberFormatter.lenient = true
-// let numberAfterLenient = numberFormatter.numberFromString("42.42")
+// numberFormatter.isLenient = true
+// let numberAfterLenient = numberFormatter.number(from: "42.42")
// XCTAssertEqual(numberAfterLenient, 42.42)
}
@@ -353,7 +389,76 @@
XCTAssertEqual(numberFormatter.string(for: NSNumber(value: 99.1))!, "99")
XCTAssertNil(numberFormatter.string(for: "NaN"))
XCTAssertNil(numberFormatter.string(for: NSString(string: "NaN")))
+
+ numberFormatter.numberStyle = .spellOut
+ XCTAssertEqual(numberFormatter.string(for: 234), "two hundred thirty-four")
+ XCTAssertEqual(numberFormatter.string(for: 2007), "two thousand seven")
+ XCTAssertEqual(numberFormatter.string(for: 3), "three")
+ XCTAssertEqual(numberFormatter.string(for: 0.3), "zero point three")
+
+ numberFormatter.locale = Locale(identifier: "zh_CN")
+ numberFormatter.numberStyle = .spellOut
+ XCTAssertEqual(numberFormatter.string(from: 11.4), "εδΈηΉε")
+
+ numberFormatter.locale = Locale(identifier: "fr_FR")
+ numberFormatter.numberStyle = .spellOut
+ XCTAssertEqual(numberFormatter.string(from: 11.4), "onze virgule quatre")
+
}
-
+
+ func test_numberFrom() {
+ let numberFormatter = NumberFormatter()
+ XCTAssertEqual(numberFormatter.number(from: "10"), 10)
+ XCTAssertEqual(numberFormatter.number(from: "3.14"), 3.14)
+ XCTAssertEqual(numberFormatter.number(from: "0.01"), 0.01)
+ XCTAssertEqual(numberFormatter.number(from: ".01"), 0.01)
+
+ // These don't work unless lenient/style set
+ numberFormatter.numberStyle = .decimal
+ XCTAssertEqual(numberFormatter.number(from: "1,001"), 1001)
+ XCTAssertEqual(numberFormatter.number(from: "1,050,001"), 1050001)
+
+ numberFormatter.numberStyle = .spellOut
+ XCTAssertEqual(numberFormatter.number(from: "two thousand and seven"), 2007)
+ XCTAssertEqual(numberFormatter.number(from: "one point zero"), 1.0)
+ XCTAssertEqual(numberFormatter.number(from: "one hundred million"), 1E8)
+
+ numberFormatter.locale = Locale(identifier: "zh_CN")
+ numberFormatter.numberStyle = .spellOut
+ XCTAssertEqual(numberFormatter.number(from: "εδΈηΉε"), 11.4)
+
+ numberFormatter.locale = Locale(identifier: "fr_FR")
+ numberFormatter.numberStyle = .spellOut
+ XCTAssertEqual(numberFormatter.number(from: "onze virgule quatre"), 11.4)
+ }
+
+ func test_en_US_initialValues() {
+ // Symbols should be extractable
+ // At one point, none of this passed!
+
+ let numberFormatter = NumberFormatter();
+ numberFormatter.locale = Locale(identifier: "en_US")
+
+ // TODO: Check if this is true for all versions...
+ XCTAssertEqual(numberFormatter.format, "#;0;#")
+
+ XCTAssertEqual(numberFormatter.plusSign, "+")
+ XCTAssertEqual(numberFormatter.minusSign, "-")
+ XCTAssertEqual(numberFormatter.decimalSeparator, ".")
+ XCTAssertEqual(numberFormatter.groupingSeparator, ",")
+ XCTAssertEqual(numberFormatter.nilSymbol, "")
+ XCTAssertEqual(numberFormatter.notANumberSymbol, "NaN")
+ XCTAssertEqual(numberFormatter.positiveInfinitySymbol, "+∞")
+ XCTAssertEqual(numberFormatter.negativeInfinitySymbol, "-∞")
+ XCTAssertEqual(numberFormatter.positivePrefix, "")
+ XCTAssertEqual(numberFormatter.negativePrefix, "-")
+ XCTAssertEqual(numberFormatter.positiveSuffix, "")
+ XCTAssertEqual(numberFormatter.negativeSuffix, "")
+ XCTAssertEqual(numberFormatter.percentSymbol, "%")
+ XCTAssertEqual(numberFormatter.perMillSymbol, "‰")
+ XCTAssertEqual(numberFormatter.exponentSymbol, "E")
+ XCTAssertEqual(numberFormatter.groupingSeparator, ",")
+ XCTAssertEqual(numberFormatter.paddingCharacter, "*")
+ }
}
diff --git a/TestFoundation/TestNSPredicate.swift b/TestFoundation/TestNSPredicate.swift
index 4275d9a..641d605 100644
--- a/TestFoundation/TestNSPredicate.swift
+++ b/TestFoundation/TestNSPredicate.swift
@@ -27,6 +27,8 @@
("test_filterNSMutableSet", test_filterNSMutableSet),
("test_filterNSOrderedSet", test_filterNSOrderedSet),
("test_filterNSMutableOrderedSet", test_filterNSMutableOrderedSet),
+ ("test_NSCoding", test_NSCoding),
+ ("test_copy", test_copy),
]
}
@@ -94,4 +96,15 @@
expectedOrderedSet.addObjects(from: expectedArray)
XCTAssertEqual(expectedOrderedSet, orderedSet)
}
+
+ func test_NSCoding() {
+ let predicateA = NSPredicate(value: true)
+ let predicateB = NSKeyedUnarchiver.unarchiveObject(with: NSKeyedArchiver.archivedData(withRootObject: predicateA)) as! NSPredicate
+ XCTAssertEqual(predicateA, predicateB, "Archived then unarchived uuid must be equal.")
+ }
+
+ func test_copy() {
+ let predicate = NSPredicate(value: true)
+ XCTAssert(predicate.isEqual(predicate.copy()))
+ }
}
diff --git a/TestFoundation/TestNSStream.swift b/TestFoundation/TestNSStream.swift
index f2daf43..8bb4c5c 100644
--- a/TestFoundation/TestNSStream.swift
+++ b/TestFoundation/TestNSStream.swift
@@ -118,7 +118,7 @@
}
func test_InputStreamInvalidPath() {
- let fileStream: InputStream = InputStream(fileAtPath: "/tmp/file.txt")!
+ let fileStream: InputStream = InputStream(fileAtPath: NSTemporaryDirectory() + "file.txt")!
XCTAssertEqual(Stream.Status.notOpen, fileStream.streamStatus)
fileStream.open()
XCTAssertEqual(Stream.Status.error, fileStream.streamStatus)
@@ -217,7 +217,7 @@
}
private func createTestFile(_ path: String, _contents: Data) -> String? {
- let tempDir = "/tmp/TestFoundation_Playground_" + NSUUID().uuidString + "/"
+ let tempDir = NSTemporaryDirectory() + "TestFoundation_Playground_" + NSUUID().uuidString + "/"
do {
try FileManager.default.createDirectory(atPath: tempDir, withIntermediateDirectories: false, attributes: nil)
if FileManager.default.createFile(atPath: tempDir + "/" + path, contents: _contents,
diff --git a/TestFoundation/TestNSString.swift b/TestFoundation/TestNSString.swift
index ebb8fab..362e075 100644
--- a/TestFoundation/TestNSString.swift
+++ b/TestFoundation/TestNSString.swift
@@ -419,11 +419,11 @@
func test_completePathIntoString() {
let fileNames = [
- "/tmp/Test_completePathIntoString_01",
- "/tmp/test_completePathIntoString_02",
- "/tmp/test_completePathIntoString_01.txt",
- "/tmp/test_completePathIntoString_01.dat",
- "/tmp/test_completePathIntoString_03.DAT"
+ NSTemporaryDirectory() + "Test_completePathIntoString_01",
+ NSTemporaryDirectory() + "test_completePathIntoString_02",
+ NSTemporaryDirectory() + "test_completePathIntoString_01.txt",
+ NSTemporaryDirectory() + "test_completePathIntoString_01.dat",
+ NSTemporaryDirectory() + "test_completePathIntoString_03.DAT"
]
guard ensureFiles(fileNames) else {
@@ -432,7 +432,7 @@
}
let tmpPath = { (path: String) -> String in
- return "/tmp/\(path)"
+ return NSTemporaryDirectory() + "\(path)"
}
do {
@@ -463,9 +463,9 @@
}
let fileNames2 = [
- "/tmp/ABC/",
- "/tmp/ABCD/",
- "/tmp/abcde"
+ NSTemporaryDirectory() + "ABC/",
+ NSTemporaryDirectory() + "ABCD/",
+ NSTemporaryDirectory() + "abcde"
]
guard ensureFiles(fileNames2) else {
@@ -571,7 +571,7 @@
// Next check has no sense on Linux due to case sensitive file system.
#if os(OSX)
- guard ensureFiles(["/tmp/ABC/temp.txt"]) else {
+ guard ensureFiles([NSTemporaryDirectory() + "ABC/temp.txt"]) else {
XCTAssert(false, "Could not create temp files for testing.")
return
}
diff --git a/TestFoundation/TestNSURL.swift b/TestFoundation/TestNSURL.swift
index 87409b5..b174390 100644
--- a/TestFoundation/TestNSURL.swift
+++ b/TestFoundation/TestNSURL.swift
@@ -352,7 +352,7 @@
func test_URLByResolvingSymlinksInPath() {
let files = [
- "/tmp/ABC/test_URLByResolvingSymlinksInPath"
+ NSTemporaryDirectory() + "ABC/test_URLByResolvingSymlinksInPath"
]
guard ensureFiles(files) else {
diff --git a/TestFoundation/TestNSURLRequest.swift b/TestFoundation/TestNSURLRequest.swift
index 5dde4ef..b9b0353 100644
--- a/TestFoundation/TestNSURLRequest.swift
+++ b/TestFoundation/TestNSURLRequest.swift
@@ -27,6 +27,9 @@
("test_mutableCopy_1", test_mutableCopy_1),
("test_mutableCopy_2", test_mutableCopy_2),
("test_mutableCopy_3", test_mutableCopy_3),
+ ("test_NSCoding_1", test_NSCoding_1),
+ ("test_NSCoding_2", test_NSCoding_2),
+ ("test_NSCoding_3", test_NSCoding_3)
]
}
@@ -203,4 +206,38 @@
XCTAssertEqual(originalRequest.url, urlA)
XCTAssertNil(originalRequest.allHTTPHeaderFields)
}
+
+ func test_NSCoding_1() {
+ let url = URL(string: "https://apple.com")!
+ let requestA = NSURLRequest(url: url)
+ let requestB = NSKeyedUnarchiver.unarchiveObject(with: NSKeyedArchiver.archivedData(withRootObject: requestA)) as! NSURLRequest
+ XCTAssertEqual(requestA, requestB, "Archived then unarchived url request must be equal.")
+ }
+
+ func test_NSCoding_2() {
+ let url = URL(string: "https://apple.com")!
+ let requestA = NSMutableURLRequest(url: url)
+ //Also checks crash on NSData.bytes
+ requestA.httpBody = Data()
+ let requestB = NSKeyedUnarchiver.unarchiveObject(with: NSKeyedArchiver.archivedData(withRootObject: requestA)) as! NSURLRequest
+ XCTAssertEqual(requestA, requestB, "Archived then unarchived url request must be equal.")
+ //Check `.httpBody` as it is not checked in `isEqual(_:)`
+ XCTAssertEqual(requestB.httpBody, requestA.httpBody)
+ }
+
+ func test_NSCoding_3() {
+ let url = URL(string: "https://apple.com")!
+ let urlForDocument = URL(string: "http://ibm.com")!
+
+ let requestA = NSMutableURLRequest(url: url)
+ requestA.mainDocumentURL = urlForDocument
+ //Also checks crash on NSData.bytes
+ requestA.httpBody = Data(bytes: [1, 2, 3])
+ let requestB = NSKeyedUnarchiver.unarchiveObject(with: NSKeyedArchiver.archivedData(withRootObject: requestA)) as! NSURLRequest
+ XCTAssertEqual(requestA, requestB, "Archived then unarchived url request must be equal.")
+ //Check `.httpBody` as it is not checked in `isEqual(_:)`
+ XCTAssertNotNil(requestB.httpBody)
+ XCTAssertEqual(3, requestB.httpBody!.count)
+ XCTAssertEqual(requestB.httpBody, requestA.httpBody)
+ }
}
diff --git a/TestFoundation/TestNSURLResponse.swift b/TestFoundation/TestNSURLResponse.swift
index 9e67ffa..dfece22 100644
--- a/TestFoundation/TestNSURLResponse.swift
+++ b/TestFoundation/TestNSURLResponse.swift
@@ -29,6 +29,7 @@
("test_suggestedFilename_2", test_suggestedFilename_2),
("test_suggestedFilename_3", test_suggestedFilename_3),
("test_copywithzone", test_copyWithZone),
+ ("test_NSCoding", test_NSCoding),
]
}
@@ -91,6 +92,19 @@
let res = URLResponse(url: url, mimeType: "txt", expectedContentLength: 0, textEncodingName: nil)
XCTAssertTrue(res.isEqual(res.copy() as! NSObject))
}
+
+ func test_NSCoding() {
+ let url = URL(string: "https://apple.com")!
+ let responseA = URLResponse(url: url, mimeType: "txt", expectedContentLength: 0, textEncodingName: nil)
+ let responseB = NSKeyedUnarchiver.unarchiveObject(with: NSKeyedArchiver.archivedData(withRootObject: responseA)) as! URLResponse
+
+ //On macOS unarchived Archived then unarchived `URLResponse` is not equal.
+ XCTAssertEqual(responseA.url, responseB.url, "Archived then unarchived url response must be equal.")
+ XCTAssertEqual(responseA.mimeType, responseB.mimeType, "Archived then unarchived url response must be equal.")
+ XCTAssertEqual(responseA.expectedContentLength, responseB.expectedContentLength, "Archived then unarchived url response must be equal.")
+ XCTAssertEqual(responseA.textEncodingName, responseB.textEncodingName, "Archived then unarchived url response must be equal.")
+ XCTAssertEqual(responseA.suggestedFilename, responseB.suggestedFilename, "Archived then unarchived url response must be equal.")
+ }
}
@@ -127,6 +141,8 @@
("test_MIMETypeAndCharacterEncoding_1", test_MIMETypeAndCharacterEncoding_1),
("test_MIMETypeAndCharacterEncoding_2", test_MIMETypeAndCharacterEncoding_2),
("test_MIMETypeAndCharacterEncoding_3", test_MIMETypeAndCharacterEncoding_3),
+
+ ("test_NSCoding", test_NSCoding),
]
}
@@ -292,4 +308,28 @@
XCTAssertEqual(sut?.mimeType, "text/html")
XCTAssertEqual(sut?.textEncodingName, "iso-8859-4")
}
+
+ // NSCoding
+
+ func test_NSCoding() {
+ let url = URL(string: "https://apple.com")!
+ let f = ["Content-Type": "text/HTML; charset=ISO-8859-4"]
+
+ let responseA = HTTPURLResponse(url: url, statusCode: 200, httpVersion: "HTTP/1.1", headerFields: f)!
+ let responseB = NSKeyedUnarchiver.unarchiveObject(with: NSKeyedArchiver.archivedData(withRootObject: responseA)) as! HTTPURLResponse
+
+ //On macOS unarchived Archived then unarchived `URLResponse` is not equal.
+ XCTAssertEqual(responseA.statusCode, responseB.statusCode, "Archived then unarchived http url response must be equal.")
+ XCTAssertEqual(Array(responseA.allHeaderFields.keys), Array(responseB.allHeaderFields.keys), "Archived then unarchived http url response must be equal.")
+
+ for key in responseA.allHeaderFields.keys {
+ XCTAssertEqual(responseA.allHeaderFields[key] as? String, responseB.allHeaderFields[key] as? String, "Archived then unarchived http url response must be equal.")
+ }
+
+ XCTAssertEqual(responseA.url, responseB.url, "Archived then unarchived http url response must be equal.")
+ XCTAssertEqual(responseA.mimeType, responseB.mimeType, "Archived then unarchived http url response must be equal.")
+ XCTAssertEqual(responseA.expectedContentLength, responseB.expectedContentLength, "Archived then unarchived http url response must be equal.")
+ XCTAssertEqual(responseA.textEncodingName, responseB.textEncodingName, "Archived then unarchived http url response must be equal.")
+ XCTAssertEqual(responseA.suggestedFilename, responseB.suggestedFilename, "Archived then unarchived http url response must be equal.")
+ }
}