Merge pull request #917 from KingOfBrian/bugfix/SR-1762-Remove-Final-In-Protocol-Extensions
Remove final from vars in error related protocol extensions
diff --git a/CoreFoundation/Base.subproj/CFRuntime.c b/CoreFoundation/Base.subproj/CFRuntime.c
index 2672704..8a01c0f 100644
--- a/CoreFoundation/Base.subproj/CFRuntime.c
+++ b/CoreFoundation/Base.subproj/CFRuntime.c
@@ -999,9 +999,9 @@
#ifndef __CFSwiftGetBaseClass
#if TARGET_OS_LINUX
-#define __CFSwiftGetBaseClass _TF10Foundation21__CFSwiftGetBaseClassFT_PMPs9AnyObject_
+#define __CFSwiftGetBaseClass _T010Foundation21__CFSwiftGetBaseClasss9AnyObject_pXpyF
#elif TARGET_OS_MAC
-#define __CFSwiftGetBaseClass _TF15SwiftFoundation21__CFSwiftGetBaseClassFT_PMPs9AnyObject_
+#define __CFSwiftGetBaseClass _T015SwiftFoundation21__CFSwiftGetBaseClasss9AnyObject_pXpyF
#endif
#endif
extern uintptr_t __CFSwiftGetBaseClass();
@@ -1108,9 +1108,9 @@
#if DEPLOYMENT_RUNTIME_SWIFT
#ifndef __CFInitializeSwift
#if TARGET_OS_LINUX
-#define __CFInitializeSwift _TF10Foundation19__CFInitializeSwiftFT_T_
+#define __CFInitializeSwift _T010Foundation19__CFInitializeSwiftyyF
#elif TARGET_OS_MAC
-#define __CFInitializeSwift _TF15SwiftFoundation19__CFInitializeSwiftFT_T_
+#define __CFInitializeSwift _T015SwiftFoundation014__CFInitializeA0yyF
#endif
#endif
extern void __CFInitializeSwift();
diff --git a/Foundation/NSJSONSerialization.swift b/Foundation/NSJSONSerialization.swift
index 8b97994..36120e3 100644
--- a/Foundation/NSJSONSerialization.swift
+++ b/Foundation/NSJSONSerialization.swift
@@ -202,8 +202,22 @@
/* Create a JSON object from JSON data stream. The stream should be opened and configured. All other behavior of this method is the same as the JSONObjectWithData:options:error: method.
*/
- open class func jsonObject(with stream: InputStream, options opt: ReadingOptions = []) throws -> AnyObject {
- NSUnimplemented()
+ open class func jsonObject(with stream: InputStream, options opt: ReadingOptions = []) throws -> Any {
+ var data = Data()
+ guard stream.streamStatus == .open || stream.streamStatus == .reading else {
+ fatalError("Stream is not available for reading")
+ }
+ repeat {
+ var buffer = [UInt8](repeating: 0, count: 1024)
+ var bytesRead: Int = 0
+ bytesRead = stream.read(&buffer, maxLength: buffer.count)
+ if bytesRead < 0 {
+ throw stream.streamError!
+ } else {
+ data.append(&buffer, count: bytesRead)
+ }
+ } while stream.hasBytesAvailable
+ return try jsonObject(with: data, options: opt)
}
}
@@ -702,22 +716,25 @@
defer { intEndPointer.deallocate(capacity: 1) }
let doubleEndPointer = UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>.allocate(capacity: 1)
defer { doubleEndPointer.deallocate(capacity: 1) }
-
let intResult = strtol(startPointer, intEndPointer, 10)
let intDistance = startPointer.distance(to: intEndPointer[0]!)
let doubleResult = strtod(startPointer, doubleEndPointer)
let doubleDistance = startPointer.distance(to: doubleEndPointer[0]!)
-
+
guard intDistance > 0 || doubleDistance > 0 else {
return nil
}
-
+
if intDistance == doubleDistance {
return (intResult, intDistance)
}
guard doubleDistance > 0 else {
return nil
}
+
+ if doubleResult == doubleResult.rounded() {
+ return (Int(doubleResult), doubleDistance)
+ }
return (doubleResult, doubleDistance)
}
}
diff --git a/Foundation/NSKeyedArchiver.swift b/Foundation/NSKeyedArchiver.swift
index 782c261..ccf7ad8 100644
--- a/Foundation/NSKeyedArchiver.swift
+++ b/Foundation/NSKeyedArchiver.swift
@@ -159,13 +159,13 @@
return false
}
+ defer { CFWriteStreamClose(writeStream) }
+
let keyedArchiver = NSKeyedArchiver(output: writeStream)
keyedArchiver.encode(rootObject, forKey: NSKeyedArchiveRootObjectKey)
keyedArchiver.finishEncoding()
finishedEncoding = keyedArchiver._flags.contains(ArchiverFlags.finishedEncoding)
-
- CFWriteStreamClose(writeStream)
return finishedEncoding
}
diff --git a/Foundation/NSKeyedUnarchiver.swift b/Foundation/NSKeyedUnarchiver.swift
index ff185b9..e29bed7 100644
--- a/Foundation/NSKeyedUnarchiver.swift
+++ b/Foundation/NSKeyedUnarchiver.swift
@@ -74,6 +74,8 @@
return nil
}
+ defer { CFReadStreamClose(readStream) }
+
let keyedUnarchiver = NSKeyedUnarchiver(stream: Stream.stream(readStream))
do {
try root = keyedUnarchiver.decodeTopLevelObject(forKey: NSKeyedArchiveRootObjectKey)
@@ -81,8 +83,6 @@
} catch {
}
- CFReadStreamClose(readStream)
-
return root
}
diff --git a/Foundation/NSOperation.swift b/Foundation/NSOperation.swift
index fcc9b38..988aef8 100644
--- a/Foundation/NSOperation.swift
+++ b/Foundation/NSOperation.swift
@@ -47,7 +47,6 @@
#endif
}
- /// - Note: Operations that are asynchronous from the execution of the operation queue itself are not supported since there is no KVO to trigger the finish.
open func start() {
main()
finish()
@@ -159,6 +158,24 @@
}
}
+/// The following two methods are added to provide support for Operations which
+/// are asynchronous from the execution of the operation queue itself. On Darwin,
+/// this is supported via KVO notifications. In the absence of KVO on non-Darwin
+/// platforms, these two methods (which are defined in NSObject on Darwin) are
+/// temporarily added here. They should be removed once a permanent solution is
+/// found.
+extension Operation {
+ public func willChangeValue(forKey key: String) {
+ // do nothing
+ }
+
+ public func didChangeValue(forKey key: String) {
+ if key == "isFinished" && isFinished {
+ finish()
+ }
+ }
+}
+
extension Operation {
public enum QueuePriority : Int {
case veryLow
diff --git a/Foundation/NSOrderedSet.swift b/Foundation/NSOrderedSet.swift
index 33b5f4e..9f85df1 100644
--- a/Foundation/NSOrderedSet.swift
+++ b/Foundation/NSOrderedSet.swift
@@ -391,6 +391,16 @@
_storage.remove(value)
_orderedStorage.remove(at: index(of: object))
}
+
+ open override subscript(idx: Int) -> Any {
+ get {
+ return object(at: idx)
+ }
+ set {
+ replaceObject(at: idx, with: newValue)
+ }
+ }
+
}
extension NSMutableOrderedSet {
diff --git a/Foundation/NSRegularExpression.swift b/Foundation/NSRegularExpression.swift
index 0d1a289..ec4a88e 100644
--- a/Foundation/NSRegularExpression.swift
+++ b/Foundation/NSRegularExpression.swift
@@ -75,7 +75,7 @@
/* An instance of NSRegularExpression is created from a regular expression pattern and a set of options. If the pattern is invalid, nil will be returned and an NSError will be returned by reference. The pattern syntax currently supported is that specified by ICU.
*/
- public init(pattern: String, options: Options) throws {
+ public init(pattern: String, options: Options = []) throws {
var error: Unmanaged<CFError>?
#if os(OSX) || os(iOS)
let opt = _CFRegularExpressionOptions(rawValue: options.rawValue)
@@ -277,12 +277,12 @@
var count = 0
var offset = 0
for result in results {
- var currentRnage = result.range
+ var currentRange = result.range
let replacement = replacementString(for: result, in: string._swiftObject, offset: offset, template: templ)
- currentRnage.location += offset
+ currentRange.location += offset
- string.replaceCharacters(in: currentRnage, with: replacement)
- offset += replacement.length - currentRnage.length
+ string.replaceCharacters(in: currentRange, with: replacement)
+ offset += replacement.length - currentRange.length
count += 1
}
return count
diff --git a/Foundation/NSString.swift b/Foundation/NSString.swift
index de75c17..7f2d181 100644
--- a/Foundation/NSString.swift
+++ b/Foundation/NSString.swift
@@ -1298,7 +1298,33 @@
}
public convenience init(contentsOf url: URL, usedEncoding enc: UnsafeMutablePointer<UInt>?) throws {
- NSUnimplemented()
+ let readResult = try NSData(contentsOf: url, options:[])
+
+ let bytePtr = readResult.bytes.bindMemory(to: UInt8.self, capacity:readResult.length)
+ if readResult.length >= 2 && bytePtr[0] == 254 && bytePtr[1] == 255 {
+ enc?.pointee = String.Encoding.utf16BigEndian.rawValue
+ }
+ else if readResult.length >= 2 && bytePtr[0] == 255 && bytePtr[1] == 254 {
+ enc?.pointee = String.Encoding.utf16LittleEndian.rawValue
+ }
+ else {
+ //Need to work on more conditions. This should be the default
+ enc?.pointee = String.Encoding.utf8.rawValue
+ }
+
+ guard let enc = enc, let cf = CFStringCreateWithBytes(kCFAllocatorDefault, bytePtr, readResult.length, CFStringConvertNSStringEncodingToEncoding(enc.pointee), true) else {
+ throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.fileReadInapplicableStringEncoding.rawValue, userInfo: [
+ "NSDebugDescription" : "Unable to create a string using the specified encoding."
+ ])
+ }
+ var str: String?
+ if String._conditionallyBridgeFromObjectiveC(cf._nsObject, result: &str) {
+ self.init(str!)
+ } else {
+ throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.fileReadInapplicableStringEncoding.rawValue, userInfo: [
+ "NSDebugDescription" : "Unable to bridge CFString to String."
+ ])
+ }
}
public convenience init(contentsOfFile path: String, usedEncoding enc: UnsafeMutablePointer<UInt>?) throws {
diff --git a/Foundation/NSURLSession/EasyHandle.swift b/Foundation/NSURLSession/EasyHandle.swift
index e3782e9..9588676 100644
--- a/Foundation/NSURLSession/EasyHandle.swift
+++ b/Foundation/NSURLSession/EasyHandle.swift
@@ -56,6 +56,8 @@
fileprivate var headerList: _CurlStringList?
fileprivate var pauseState: _PauseState = []
internal var fileLength: Int64 = 0
+ internal var timeoutTimer: _TimeoutSource!
+
init(delegate: _EasyHandleDelegate) {
self.delegate = delegate
setupCallbacks()
@@ -387,6 +389,13 @@
}
fileprivate extension _EasyHandle {
+
+ func resetTimer() {
+ //simply create a new timer with the same queue, timeout and handler
+ //this must cancel the old handler and reset the timer
+ timeoutTimer = _TimeoutSource(queue: timeoutTimer.queue, milliseconds: timeoutTimer.milliseconds, handler: timeoutTimer.handler)
+ }
+
/// Forward the libcurl callbacks into Swift methods
func setupCallbacks() {
// write
@@ -394,24 +403,33 @@
try! CFURLSession_easy_setopt_wc(rawHandle, CFURLSessionOptionWRITEFUNCTION) { (data: UnsafeMutablePointer<Int8>, size: Int, nmemb: Int, userdata: UnsafeMutableRawPointer?) -> Int in
guard let handle = _EasyHandle.from(callbackUserData: userdata) else { return 0 }
+ defer {
+ handle.resetTimer()
+ }
return handle.didReceive(data: data, size: size, nmemb: nmemb)
- }.asError()
+ }.asError()
// read
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionREADDATA, UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())).asError()
try! CFURLSession_easy_setopt_wc(rawHandle, CFURLSessionOptionREADFUNCTION) { (data: UnsafeMutablePointer<Int8>, size: Int, nmemb: Int, userdata: UnsafeMutableRawPointer?) -> Int in
guard let handle = _EasyHandle.from(callbackUserData: userdata) else { return 0 }
+ defer {
+ handle.resetTimer()
+ }
return handle.fill(writeBuffer: data, size: size, nmemb: nmemb)
- }.asError()
+ }.asError()
// header
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionHEADERDATA, UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())).asError()
try! CFURLSession_easy_setopt_wc(rawHandle, CFURLSessionOptionHEADERFUNCTION) { (data: UnsafeMutablePointer<Int8>, size: Int, nmemb: Int, userdata: UnsafeMutableRawPointer?) -> Int in
guard let handle = _EasyHandle.from(callbackUserData: userdata) else { return 0 }
+ defer {
+ handle.resetTimer()
+ }
var length = Double()
try! CFURLSession_easy_getinfo_double(handle.rawHandle, CFURLSessionInfoCONTENT_LENGTH_DOWNLOAD, &length).asError()
return handle.didReceive(headerData: data, size: size, nmemb: nmemb, fileLength: length)
- }.asError()
+ }.asError()
// socket options
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionSOCKOPTDATA, UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())).asError()
@@ -424,7 +442,7 @@
} catch {
return 1
}
- }.asError()
+ }.asError()
// seeking in input stream
try! CFURLSession_easy_setopt_ptr(rawHandle, CFURLSessionOptionSEEKDATA, UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())).asError()
try! CFURLSession_easy_setopt_seek(rawHandle, CFURLSessionOptionSEEKFUNCTION, { (userdata, offset, origin) -> Int32 in
diff --git a/Foundation/NSURLSession/MultiHandle.swift b/Foundation/NSURLSession/MultiHandle.swift
index b6d5008..215fc6a 100644
--- a/Foundation/NSURLSession/MultiHandle.swift
+++ b/Foundation/NSURLSession/MultiHandle.swift
@@ -300,11 +300,15 @@
/// A helper class that wraps a libdispatch timer.
///
-/// Used to implement the timeout of `URLSession.MultiHandle`.
-fileprivate class _TimeoutSource {
+/// Used to implement the timeout of `URLSession.MultiHandle` and `URLSession.EasyHandle`
+class _TimeoutSource {
let rawSource: DispatchSource
let milliseconds: Int
+ let queue: DispatchQueue //needed to restart the timer for EasyHandles
+ let handler: DispatchWorkItem //needed to restart the timer for EasyHandles
init(queue: DispatchQueue, milliseconds: Int, handler: DispatchWorkItem) {
+ self.queue = queue
+ self.handler = handler
self.milliseconds = milliseconds
self.rawSource = DispatchSource.makeTimerSource(queue: queue) as! DispatchSource
diff --git a/Foundation/NSURLSession/NSURLSessionTask.swift b/Foundation/NSURLSession/NSURLSessionTask.swift
index da2df5e..e44fb9d 100644
--- a/Foundation/NSURLSession/NSURLSessionTask.swift
+++ b/Foundation/NSURLSession/NSURLSessionTask.swift
@@ -554,7 +554,16 @@
// HTTP Options:
easyHandle.set(followLocation: false)
- easyHandle.set(customHeaders: curlHeaders(for: request))
+
+ let customHeaders: [String]
+ let headersForRequest = curlHeaders(for: request)
+ if ((request.httpMethod == "POST") && (request.value(forHTTPHeaderField: "Content-Type") == nil)) {
+ customHeaders = headersForRequest + ["Content-Type:application/x-www-form-urlencoded"]
+ } else {
+ customHeaders = headersForRequest
+ }
+
+ easyHandle.set(customHeaders: customHeaders)
//TODO: The CURLOPT_PIPEDWAIT option is unavailable on Ubuntu 14.04 (libcurl 7.36)
//TODO: Introduce something like an #if, if we want to set them here
@@ -562,14 +571,19 @@
//set the request timeout
//TODO: the timeout value needs to be reset on every data transfer
let s = session as! URLSession
- easyHandle.set(timeout: Int(s.configuration.timeoutIntervalForRequest))
+ let timeoutInterval = Int(s.configuration.timeoutIntervalForRequest) * 1000
+ let timeoutHandler = DispatchWorkItem { [weak self] in
+ guard let currentTask = self else { fatalError("Timeout on a task that doesn't exist") } //this guard must always pass
+ currentTask.internalState = .transferFailed
+ let urlError = URLError(_nsError: NSError(domain: NSURLErrorDomain, code: NSURLErrorTimedOut, userInfo: nil))
+ currentTask.completeTask(withError: urlError)
+ }
+ easyHandle.timeoutTimer = _TimeoutSource(queue: workQueue, milliseconds: timeoutInterval, handler: timeoutHandler)
easyHandle.set(automaticBodyDecompression: true)
easyHandle.set(requestMethod: request.httpMethod ?? "GET")
if request.httpMethod == "HEAD" {
easyHandle.set(noBody: true)
- } else if ((request.httpMethod == "POST") && (request.value(forHTTPHeaderField: "Content-Type") == nil)) {
- easyHandle.set(customHeaders: ["Content-Type:application/x-www-form-urlencoded"])
}
}
}
@@ -823,6 +837,9 @@
}
self.response = response
+ //We don't want a timeout to be triggered after this. The timeout timer needs to be cancelled.
+ easyHandle.timeoutTimer = nil
+
//because we deregister the task with the session on internalState being set to taskCompleted
//we need to do the latter after the delegate/handler was notified/invoked
switch session.behaviour(for: self) {
@@ -874,6 +891,10 @@
guard case .transferFailed = internalState else {
fatalError("Trying to complete the task, but its transfer isn't complete / failed.")
}
+
+ //We don't want a timeout to be triggered after this. The timeout timer needs to be cancelled.
+ easyHandle.timeoutTimer = nil
+
switch session.behaviour(for: self) {
case .taskDelegate(let delegate):
guard let s = session as? URLSession else { fatalError() }
diff --git a/Foundation/NSXMLParser.swift b/Foundation/NSXMLParser.swift
index 2825558..58e5b14 100644
--- a/Foundation/NSXMLParser.swift
+++ b/Foundation/NSXMLParser.swift
@@ -559,9 +559,12 @@
internal func parseFromStream() -> Bool {
var result = true
XMLParser.setCurrentParser(self)
+ defer { XMLParser.setCurrentParser(nil) }
if let stream = _stream {
stream.open()
+ defer { stream.close() }
let buffer = malloc(_chunkSize)!.bindMemory(to: UInt8.self, capacity: _chunkSize)
+ defer { free(buffer) }
var len = stream.read(buffer, maxLength: _chunkSize)
if len != -1 {
while len > 0 {
@@ -572,10 +575,9 @@
} else {
result = false
}
- free(buffer)
- stream.close()
} else if let data = _data {
let buffer = malloc(_chunkSize)!.bindMemory(to: UInt8.self, capacity: _chunkSize)
+ defer { free(buffer) }
var range = NSMakeRange(0, min(_chunkSize, data.count))
while result {
let chunk = data.withUnsafeBytes { (buffer: UnsafePointer<UInt8>) -> Data in
@@ -588,11 +590,9 @@
}
range = NSMakeRange(range.location + range.length, min(_chunkSize, data.count - (range.location + range.length)))
}
- free(buffer)
} else {
result = false
}
- XMLParser.setCurrentParser(nil)
return result
}
diff --git a/Foundation/Progress.swift b/Foundation/Progress.swift
index 3f16c2a..08c3e30 100644
--- a/Foundation/Progress.swift
+++ b/Foundation/Progress.swift
@@ -292,8 +292,8 @@
open var pausingHandler: (() -> Void)? {
didSet {
guard let handler = pausingHandler else { return }
- // If we're already cancelled, then invoke it - asynchronously
- if isCancelled {
+ // If we're already paused, then invoke it - asynchronously
+ if isPaused {
DispatchQueue.global().async {
handler()
}
diff --git a/TestFoundation/HTTPServer.swift b/TestFoundation/HTTPServer.swift
index 5b032a2..4070399 100644
--- a/TestFoundation/HTTPServer.swift
+++ b/TestFoundation/HTTPServer.swift
@@ -77,6 +77,7 @@
return sockaddr_in(sin_len: 0, sin_family: sa_family_t(AF_INET), sin_port: CFSwapInt16HostToBig(port), sin_addr: in_addr(s_addr: INADDR_ANY), sin_zero: (0,0,0,0,0,0,0,0) )
#endif
}
+
func acceptConnection(notify: ServerSemaphore) throws {
_ = try attempt("listen", valid: isZero, listen(listenSocket, SOMAXCONN))
try socketAddress.withMemoryRebound(to: sockaddr.self, capacity: MemoryLayout<sockaddr>.size, {
@@ -92,10 +93,32 @@
_ = try attempt("read", valid: isNotNegative, CInt(read(connectionSocket, &buffer, 4096)))
return String(cString: &buffer)
}
+
+ func split(_ str: String, _ count: Int) -> [String] {
+ return stride(from: 0, to: str.characters.count, by: count).map { i -> String in
+ let startIndex = str.index(str.startIndex, offsetBy: i)
+ let endIndex = str.index(startIndex, offsetBy: count, limitedBy: str.endIndex) ?? str.endIndex
+ return str[startIndex..<endIndex]
+ }
+ }
- func writeData(data: String) throws {
- var bytes = Array(data.utf8)
- _ = try attempt("write", valid: isNotNegative, CInt(write(connectionSocket, &bytes, data.utf8.count)))
+ func writeData(header: String, body: String, sendDelay: TimeInterval? = nil, bodyChunks: Int? = nil) throws {
+ var header = Array(header.utf8)
+ _ = try attempt("write", valid: isNotNegative, CInt(write(connectionSocket, &header, header.count)))
+
+ if let sendDelay = sendDelay, let bodyChunks = bodyChunks {
+ let count = max(1, Int(Double(body.utf8.count) / Double(bodyChunks)))
+ let texts = split(body, count)
+
+ for item in texts {
+ sleep(UInt32(sendDelay))
+ var bytes = Array(item.utf8)
+ _ = try attempt("write", valid: isNotNegative, CInt(write(connectionSocket, &bytes, bytes.count)))
+ }
+ } else {
+ var bytes = Array(body.utf8)
+ _ = try attempt("write", valid: isNotNegative, CInt(write(connectionSocket, &bytes, bytes.count)))
+ }
}
func shutdown() {
@@ -128,8 +151,24 @@
return _HTTPRequest(request: try socket.readData())
}
- public func respond(with response: _HTTPResponse) throws {
- try socket.writeData(data: response.description)
+ public func respond(with response: _HTTPResponse, startDelay: TimeInterval? = nil, sendDelay: TimeInterval? = nil, bodyChunks: Int? = nil) throws {
+ let semaphore = DispatchSemaphore(value: 0)
+ let deadlineTime: DispatchTime
+
+ if let startDelay = startDelay {
+ deadlineTime = .now() + .seconds(Int(startDelay))
+ } else {
+ deadlineTime = .now()
+ }
+
+ DispatchQueue.main.asyncAfter(deadline: deadlineTime) {
+ do {
+ try self.socket.writeData(header: response.header, body: response.body, sendDelay: sendDelay, bodyChunks: bodyChunks)
+ semaphore.signal()
+ } catch { }
+ }
+ semaphore.wait()
+
}
}
@@ -152,6 +191,14 @@
body = lines.last!
}
+ public func getCommaSeparatedHeaders() -> String {
+ var allHeaders = ""
+ for header in headers {
+ allHeaders += header + ","
+ }
+ return allHeaders
+ }
+
}
struct _HTTPResponse {
@@ -160,7 +207,7 @@
}
private let responseCode: Response
private let headers: String
- private let body: String
+ public let body: String
public init(response: Response, headers: String = _HTTPUtils.EMPTY, body: String) {
self.responseCode = response
@@ -168,9 +215,9 @@
self.body = body
}
- public var description: String {
+ public var header: String {
let statusLine = _HTTPUtils.VERSION + _HTTPUtils.SPACE + "\(responseCode.rawValue)" + _HTTPUtils.SPACE + "\(responseCode)"
- return statusLine + (headers != _HTTPUtils.EMPTY ? _HTTPUtils.CRLF + headers : _HTTPUtils.EMPTY) + _HTTPUtils.CRLF2 + body
+ return statusLine + (headers != _HTTPUtils.EMPTY ? _HTTPUtils.CRLF + headers : _HTTPUtils.EMPTY) + _HTTPUtils.CRLF2
}
}
@@ -181,9 +228,15 @@
"USA":"Washington, D.C.",
"country.txt": "A country is a region that is identified as a distinct national entity in political geography"]
let httpServer: _HTTPServer
+ let startDelay: TimeInterval?
+ let sendDelay: TimeInterval?
+ let bodyChunks: Int?
- public init (port: UInt16) throws {
+ public init (port: UInt16, startDelay: TimeInterval? = nil, sendDelay: TimeInterval? = nil, bodyChunks: Int? = nil) throws {
httpServer = try _HTTPServer.create(port: port)
+ self.startDelay = startDelay
+ self.sendDelay = sendDelay
+ self.bodyChunks = bodyChunks
}
public func start(started: ServerSemaphore) throws {
started.signal()
@@ -191,22 +244,28 @@
}
public func readAndRespond() throws {
- try httpServer.respond(with: process(request: httpServer.request()))
- }
+ try httpServer.respond(with: process(request: httpServer.request()), startDelay: self.startDelay, sendDelay: self.sendDelay, bodyChunks: self.bodyChunks)
+ }
func process(request: _HTTPRequest) -> _HTTPResponse {
- if request.method == .GET {
- return getResponse(uri: request.uri)
+ if request.method == .GET || request.method == .POST {
+ return getResponse(request: request)
} else {
fatalError("Unsupported method!")
}
}
- func getResponse(uri: String) -> _HTTPResponse {
+ func getResponse(request: _HTTPRequest) -> _HTTPResponse {
+ let uri = request.uri
if uri == "/country.txt" {
let text = capitals[String(uri.characters.dropFirst())]!
return _HTTPResponse(response: .OK, headers: "Content-Length: \(text.characters.count)", body: text)
}
+
+ if uri == "/requestHeaders" {
+ let text = request.getCommaSeparatedHeaders()
+ return _HTTPResponse(response: .OK, headers: "Content-Length: \(text.characters.count)", body: text)
+ }
return _HTTPResponse(response: .OK, body: capitals[String(uri.characters.dropFirst())]!)
}
diff --git a/TestFoundation/Resources/NSString-UTF16-BE-data.txt b/TestFoundation/Resources/NSString-UTF16-BE-data.txt
new file mode 100644
index 0000000..b28d473
--- /dev/null
+++ b/TestFoundation/Resources/NSString-UTF16-BE-data.txt
Binary files differ
diff --git a/TestFoundation/Resources/NSString-UTF16-LE-data.txt b/TestFoundation/Resources/NSString-UTF16-LE-data.txt
new file mode 100644
index 0000000..d9f85ab
--- /dev/null
+++ b/TestFoundation/Resources/NSString-UTF16-LE-data.txt
Binary files differ
diff --git a/TestFoundation/TestNSJSONSerialization.swift b/TestFoundation/TestNSJSONSerialization.swift
index 3ce12e8..0e4e09f 100644
--- a/TestFoundation/TestNSJSONSerialization.swift
+++ b/TestFoundation/TestNSJSONSerialization.swift
@@ -87,58 +87,266 @@
//MARK: - JSONDeserialization
extension TestNSJSONSerialization {
-
+
+ enum ObjectType {
+ case data
+ case stream
+ }
+ static var objectType = ObjectType.data
+
class var deserializationTests: [(String, (TestNSJSONSerialization) -> () throws -> Void)] {
return [
- ("test_deserialize_emptyObject", test_deserialize_emptyObject),
- ("test_deserialize_multiStringObject", test_deserialize_multiStringObject),
-
- ("test_deserialize_emptyArray", test_deserialize_emptyArray),
- ("test_deserialize_multiStringArray", test_deserialize_multiStringArray),
- ("test_deserialize_unicodeString", test_deserialize_unicodeString),
- ("test_deserialize_stringWithSpacesAtStart", test_deserialize_stringWithSpacesAtStart),
-
-
- ("test_deserialize_values", test_deserialize_values),
- ("test_deserialize_numbers", test_deserialize_numbers),
-
- ("test_deserialize_simpleEscapeSequences", test_deserialize_simpleEscapeSequences),
- ("test_deserialize_unicodeEscapeSequence", test_deserialize_unicodeEscapeSequence),
- ("test_deserialize_unicodeSurrogatePairEscapeSequence", test_deserialize_unicodeSurrogatePairEscapeSequence),
- // Disabled due to uninitialized memory SR-606
- // ("test_deserialize_allowFragments", test_deserialize_allowFragments),
-
- ("test_deserialize_unterminatedObjectString", test_deserialize_unterminatedObjectString),
- ("test_deserialize_missingObjectKey", test_deserialize_missingObjectKey),
- ("test_deserialize_unexpectedEndOfFile", test_deserialize_unexpectedEndOfFile),
- ("test_deserialize_invalidValueInObject", test_deserialize_invalidValueInObject),
- ("test_deserialize_invalidValueIncorrectSeparatorInObject", test_deserialize_invalidValueIncorrectSeparatorInObject),
- ("test_deserialize_invalidValueInArray", test_deserialize_invalidValueInArray),
- ("test_deserialize_badlyFormedArray", test_deserialize_badlyFormedArray),
- ("test_deserialize_invalidEscapeSequence", test_deserialize_invalidEscapeSequence),
- ("test_deserialize_unicodeMissingTrailingSurrogate", test_deserialize_unicodeMissingTrailingSurrogate),
- ("test_serialize_dictionaryWithDecimal", test_serialize_dictionaryWithDecimal),
+ //Deserialization with Data
+ ("test_deserialize_emptyObject_withData", test_deserialize_emptyObject_withData),
+ ("test_deserialize_multiStringObject_withData", test_deserialize_multiStringObject_withData),
+ ("test_deserialize_emptyArray_withData", test_deserialize_emptyArray_withData),
+ ("test_deserialize_multiStringArray_withData", test_deserialize_multiStringArray_withData),
+ ("test_deserialize_unicodeString_withData", test_deserialize_unicodeString_withData),
+ ("test_deserialize_stringWithSpacesAtStart_withData", test_deserialize_stringWithSpacesAtStart_withData),
+
+
+ ("test_deserialize_values_withData", test_deserialize_values_withData),
+ ("test_deserialize_numbers_withData", test_deserialize_numbers_withData),
+
+ ("test_deserialize_simpleEscapeSequences_withData", test_deserialize_simpleEscapeSequences_withData),
+ ("test_deserialize_unicodeEscapeSequence_withData", test_deserialize_unicodeEscapeSequence_withData),
+ ("test_deserialize_unicodeSurrogatePairEscapeSequence_withData", test_deserialize_unicodeSurrogatePairEscapeSequence_withData),
+ // Disabled due to uninitialized memory SR-606
+ // ("test_deserialize_allowFragments_withData", test_deserialize_allowFragments_withData),
+
+ ("test_deserialize_unterminatedObjectString_withData", test_deserialize_unterminatedObjectString_withData),
+ ("test_deserialize_missingObjectKey_withData", test_deserialize_missingObjectKey_withData),
+ ("test_deserialize_unexpectedEndOfFile_withData", test_deserialize_unexpectedEndOfFile_withData),
+ ("test_deserialize_invalidValueInObject_withData", test_deserialize_invalidValueInObject_withData),
+ ("test_deserialize_invalidValueIncorrectSeparatorInObject_withData", test_deserialize_invalidValueIncorrectSeparatorInObject_withData),
+ ("test_deserialize_invalidValueInArray_withData", test_deserialize_invalidValueInArray_withData),
+ ("test_deserialize_badlyFormedArray_withData", test_deserialize_badlyFormedArray_withData),
+ ("test_deserialize_invalidEscapeSequence_withData", test_deserialize_invalidEscapeSequence_withData),
+ ("test_deserialize_unicodeMissingTrailingSurrogate_withData", test_deserialize_unicodeMissingTrailingSurrogate_withData),
+
+ //Deserialization with Stream
+ ("test_deserialize_emptyObject_withStream", test_deserialize_emptyObject_withStream),
+ ("test_deserialize_multiStringObject_withStream", test_deserialize_multiStringObject_withStream),
+
+ ("test_deserialize_emptyArray_withStream", test_deserialize_emptyArray_withStream),
+ ("test_deserialize_multiStringArray_withStream", test_deserialize_multiStringArray_withStream),
+ ("test_deserialize_unicodeString_withStream", test_deserialize_unicodeString_withStream),
+ ("test_deserialize_stringWithSpacesAtStart_withStream", test_deserialize_stringWithSpacesAtStart_withStream),
+
+
+ ("test_deserialize_values_withStream", test_deserialize_values_withStream),
+ ("test_deserialize_numbers_withStream", test_deserialize_numbers_withStream),
+
+ ("test_deserialize_simpleEscapeSequences_withStream", test_deserialize_simpleEscapeSequences_withStream),
+ ("test_deserialize_unicodeEscapeSequence_withStream", test_deserialize_unicodeEscapeSequence_withStream),
+ ("test_deserialize_unicodeSurrogatePairEscapeSequence_withStream", test_deserialize_unicodeSurrogatePairEscapeSequence_withStream),
+ // Disabled due to uninitialized memory SR-606
+ // ("test_deserialize_allowFragments_withStream", test_deserialize_allowFragments_withStream),
+
+ ("test_deserialize_unterminatedObjectString_withStream", test_deserialize_unterminatedObjectString_withStream),
+ ("test_deserialize_missingObjectKey_withStream", test_deserialize_missingObjectKey_withStream),
+ ("test_deserialize_unexpectedEndOfFile_withStream", test_deserialize_unexpectedEndOfFile_withStream),
+ ("test_deserialize_invalidValueInObject_withStream", test_deserialize_invalidValueInObject_withStream),
+ ("test_deserialize_invalidValueIncorrectSeparatorInObject_withStream", test_deserialize_invalidValueIncorrectSeparatorInObject_withStream),
+ ("test_deserialize_invalidValueInArray_withStream", test_deserialize_invalidValueInArray_withStream),
+ ("test_deserialize_badlyFormedArray_withStream", test_deserialize_badlyFormedArray_withStream),
+ ("test_deserialize_invalidEscapeSequence_withStream", test_deserialize_invalidEscapeSequence_withStream),
+ ("test_deserialize_unicodeMissingTrailingSurrogate_withStream", test_deserialize_unicodeMissingTrailingSurrogate_withStream),
+ ("test_JSONObjectWithStream_withFile", test_JSONObjectWithStream_withFile),
+ ("test_JSONObjectWithStream_withURL", test_JSONObjectWithStream_withURL),
]
}
-
+
+ func test_deserialize_emptyObject_withData() {
+ deserialize_emptyObject(objectType: .data)
+ }
+
+ func test_deserialize_multiStringObject_withData() {
+ deserialize_multiStringObject(objectType: .data)
+ }
+
+ func test_deserialize_emptyArray_withData() {
+ deserialize_emptyArray(objectType: .data)
+ }
+
+ func test_deserialize_multiStringArray_withData() {
+ deserialize_multiStringArray(objectType: .data)
+ }
+
+
+ func test_deserialize_unicodeString_withData() {
+ deserialize_unicodeString(objectType: .data)
+ }
+
+ func test_deserialize_stringWithSpacesAtStart_withData() {
+ deserialize_stringWithSpacesAtStart(objectType: .data)
+ }
+
+ func test_deserialize_values_withData() {
+ deserialize_values(objectType: .data)
+ }
+
+ func test_deserialize_numbers_withData() {
+ deserialize_numbers(objectType: .data)
+ }
+
+ func test_deserialize_simpleEscapeSequences_withData() {
+ deserialize_simpleEscapeSequences(objectType: .data)
+ }
+
+ func test_deserialize_unicodeEscapeSequence_withData() {
+ deserialize_unicodeEscapeSequence(objectType: .data)
+ }
+
+ func test_deserialize_unicodeSurrogatePairEscapeSequence_withData() {
+ deserialize_unicodeSurrogatePairEscapeSequence(objectType: .data)
+ }
+
+ // Disabled due to uninitialized memory SR-606
+ // func test_deserialize_allowFragments_withData() {
+ // deserialize_allowFragments(objectType: .data)
+ // }
+
+ func test_deserialize_unterminatedObjectString_withData() {
+ deserialize_unterminatedObjectString(objectType: .data)
+ }
+
+ func test_deserialize_missingObjectKey_withData() {
+ deserialize_missingObjectKey(objectType: .data)
+ }
+
+ func test_deserialize_unexpectedEndOfFile_withData() {
+ deserialize_unexpectedEndOfFile(objectType: .data)
+ }
+
+ func test_deserialize_invalidValueInObject_withData() {
+ deserialize_invalidValueInObject(objectType: .data)
+ }
+
+ func test_deserialize_invalidValueIncorrectSeparatorInObject_withData() {
+ deserialize_invalidValueIncorrectSeparatorInObject(objectType: .data)
+ }
+
+ func test_deserialize_invalidValueInArray_withData() {
+ deserialize_invalidValueInArray(objectType: .data)
+ }
+
+ func test_deserialize_badlyFormedArray_withData() {
+ deserialize_badlyFormedArray(objectType: .data)
+ }
+
+ func test_deserialize_invalidEscapeSequence_withData() {
+ deserialize_invalidEscapeSequence(objectType: .data)
+ }
+
+ func test_deserialize_unicodeMissingTrailingSurrogate_withData() {
+ deserialize_unicodeMissingTrailingSurrogate(objectType: .data)
+ }
+
+ func test_deserialize_emptyObject_withStream() {
+ deserialize_emptyObject(objectType: .stream)
+ }
+
+ func test_deserialize_multiStringObject_withStream() {
+ deserialize_multiStringObject(objectType: .stream)
+ }
+
+ func test_deserialize_emptyArray_withStream() {
+ deserialize_emptyArray(objectType: .stream)
+ }
+
+ func test_deserialize_multiStringArray_withStream() {
+ deserialize_multiStringArray(objectType: .stream)
+ }
+
+
+ func test_deserialize_unicodeString_withStream() {
+ deserialize_unicodeString(objectType: .stream)
+ }
+
+ func test_deserialize_stringWithSpacesAtStart_withStream() {
+ deserialize_stringWithSpacesAtStart(objectType: .stream)
+ }
+
+ func test_deserialize_values_withStream() {
+ deserialize_values(objectType: .stream)
+ }
+
+ func test_deserialize_numbers_withStream() {
+ deserialize_numbers(objectType: .stream)
+ }
+
+ func test_deserialize_simpleEscapeSequences_withStream() {
+ deserialize_simpleEscapeSequences(objectType: .stream)
+ }
+
+ func test_deserialize_unicodeEscapeSequence_withStream() {
+ deserialize_unicodeEscapeSequence(objectType: .stream)
+ }
+
+ func test_deserialize_unicodeSurrogatePairEscapeSequence_withStream() {
+ deserialize_unicodeSurrogatePairEscapeSequence(objectType: .stream)
+ }
+
+ // Disabled due to uninitialized memory SR-606
+ // func test_deserialize_allowFragments_withStream() {
+ // deserialize_allowFragments(objectType: .stream)
+ // }
+
+ func test_deserialize_unterminatedObjectString_withStream() {
+ deserialize_unterminatedObjectString(objectType: .stream)
+ }
+
+ func test_deserialize_missingObjectKey_withStream() {
+ deserialize_missingObjectKey(objectType: .stream)
+ }
+
+ func test_deserialize_unexpectedEndOfFile_withStream() {
+ deserialize_unexpectedEndOfFile(objectType: .stream)
+ }
+
+ func test_deserialize_invalidValueInObject_withStream() {
+ deserialize_invalidValueInObject(objectType: .stream)
+ }
+
+ func test_deserialize_invalidValueIncorrectSeparatorInObject_withStream() {
+ deserialize_invalidValueIncorrectSeparatorInObject(objectType: .stream)
+ }
+
+ func test_deserialize_invalidValueInArray_withStream() {
+ deserialize_invalidValueInArray(objectType: .stream)
+ }
+
+ func test_deserialize_badlyFormedArray_withStream() {
+ deserialize_badlyFormedArray(objectType: .stream)
+ }
+
+ func test_deserialize_invalidEscapeSequence_withStream() {
+ deserialize_invalidEscapeSequence(objectType: .stream)
+ }
+
+ func test_deserialize_unicodeMissingTrailingSurrogate_withStream() {
+ deserialize_unicodeMissingTrailingSurrogate(objectType: .stream)
+ }
+
//MARK: - Object Deserialization
- func test_deserialize_emptyObject() {
+ func deserialize_emptyObject(objectType: ObjectType) {
let subject = "{}"
do {
guard let data = subject.data(using: .utf8) else {
XCTFail("Unable to convert string to data")
return
}
- let t = try JSONSerialization.jsonObject(with: data, options: [])
- let result = t as? [String: Any]
+ let result = try getjsonObjectResult(data, objectType) as? [String: Any]
+
XCTAssertEqual(result?.count, 0)
} catch {
XCTFail("Error thrown: \(error)")
}
}
-
- func test_deserialize_multiStringObject() {
+
+ func deserialize_multiStringObject(objectType: ObjectType) {
let subject = "{ \"hello\": \"world\", \"swift\": \"rocks\" }"
do {
for encoding in [String.Encoding.utf8, String.Encoding.utf16BigEndian] {
@@ -146,7 +354,7 @@
XCTFail("Unable to convert string to data")
return
}
- let result = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
+ let result = try getjsonObjectResult(data, objectType) as? [String: Any]
XCTAssertEqual(result?["hello"] as? String, "world")
XCTAssertEqual(result?["swift"] as? String, "rocks")
}
@@ -154,50 +362,47 @@
XCTFail("Error thrown: \(error)")
}
}
-
- func test_deserialize_stringWithSpacesAtStart(){
-
+
+ func deserialize_stringWithSpacesAtStart(objectType: ObjectType) {
let subject = "{\"title\" : \" hello world!!\" }"
do {
guard let data = subject.data(using: .utf8) else {
XCTFail("Unable to convert string to data")
return
}
- let result = try JSONSerialization.jsonObject(with: data, options: []) as? [String : Any]
+ let result = try getjsonObjectResult(data, objectType) as? [String: Any]
XCTAssertEqual(result?["title"] as? String, " hello world!!")
} catch{
XCTFail("Error thrown: \(error)")
}
-
-
}
-
+
//MARK: - Array Deserialization
- func test_deserialize_emptyArray() {
+ func deserialize_emptyArray(objectType: ObjectType) {
let subject = "[]"
-
+
do {
guard let data = subject.data(using: .utf8) else {
XCTFail("Unable to convert string to data")
return
}
- let result = try JSONSerialization.jsonObject(with: data, options: []) as? [Any]
+ let result = try getjsonObjectResult(data, objectType) as? [Any]
XCTAssertEqual(result?.count, 0)
} catch {
XCTFail("Unexpected error: \(error)")
}
}
-
- func test_deserialize_multiStringArray() {
+
+ func deserialize_multiStringArray(objectType: ObjectType) {
let subject = "[\"hello\", \"swift⚡️\"]"
-
+
do {
for encoding in [String.Encoding.utf8, String.Encoding.utf16BigEndian] {
guard let data = subject.data(using: encoding) else {
XCTFail("Unable to convert string to data")
return
}
- let result = try JSONSerialization.jsonObject(with: data, options: []) as? [Any]
+ let result = try getjsonObjectResult(data, objectType) as? [Any]
XCTAssertEqual(result?[0] as? String, "hello")
XCTAssertEqual(result?[1] as? String, "swift⚡️")
}
@@ -205,18 +410,17 @@
XCTFail("Unexpected error: \(error)")
}
}
-
- func test_deserialize_unicodeString() {
+
+ func deserialize_unicodeString(objectType: ObjectType) {
/// Ģ has the same LSB as quotation mark " (U+0022) so test guarding against this case
let subject = "[\"unicode\", \"Ģ\", \"😢\"]"
-
do {
for encoding in [String.Encoding.utf16LittleEndian, String.Encoding.utf16BigEndian, String.Encoding.utf32LittleEndian, String.Encoding.utf32BigEndian] {
guard let data = subject.data(using: encoding) else {
XCTFail("Unable to convert string to data")
return
}
- let result = try JSONSerialization.jsonObject(with: data, options: []) as? [Any]
+ let result = try getjsonObjectResult(data, objectType) as? [Any]
XCTAssertEqual(result?[0] as? String, "unicode")
XCTAssertEqual(result?[1] as? String, "Ģ")
XCTAssertEqual(result?[2] as? String, "😢")
@@ -225,18 +429,18 @@
XCTFail("Unexpected error: \(error)")
}
}
-
+
//MARK: - Value parsing
- func test_deserialize_values() {
+ func deserialize_values(objectType: ObjectType) {
let subject = "[true, false, \"hello\", null, {}, []]"
-
+
do {
for encoding in supportedEncodings {
guard let data = subject.data(using: encoding) else {
XCTFail("Unable to convert string to data")
return
}
- let result = try JSONSerialization.jsonObject(with: data, options: []) as? [Any]
+ let result = try getjsonObjectResult(data, objectType) as? [Any]
XCTAssertEqual(result?[0] as? Bool, true)
XCTAssertEqual(result?[1] as? Bool, false)
XCTAssertEqual(result?[2] as? String, "hello")
@@ -248,39 +452,39 @@
XCTFail("Unexpected error: \(error)")
}
}
-
+
//MARK: - Number parsing
- func test_deserialize_numbers() {
+ func deserialize_numbers(objectType: ObjectType) {
let subject = "[1, -1, 1.3, -1.3, 1e3, 1E-3]"
-
+
do {
for encoding in supportedEncodings {
guard let data = subject.data(using: encoding) else {
XCTFail("Unable to convert string to data")
return
}
- let result = try JSONSerialization.jsonObject(with: data, options: []) as? [Any]
+ let result = try getjsonObjectResult(data, objectType) as? [Any]
XCTAssertEqual(result?[0] as? Int, 1)
XCTAssertEqual(result?[1] as? Int, -1)
XCTAssertEqual(result?[2] as? Double, 1.3)
XCTAssertEqual(result?[3] as? Double, -1.3)
- XCTAssertEqual(result?[4] as? Double, 1000)
+ XCTAssertEqual(result?[4] as? Int, 1000)
XCTAssertEqual(result?[5] as? Double, 0.001)
}
} catch {
XCTFail("Unexpected error: \(error)")
}
}
-
+
//MARK: - Escape Sequences
- func test_deserialize_simpleEscapeSequences() {
+ func deserialize_simpleEscapeSequences(objectType: ObjectType) {
let subject = "[\"\\\"\", \"\\\\\", \"\\/\", \"\\b\", \"\\f\", \"\\n\", \"\\r\", \"\\t\"]"
do {
guard let data = subject.data(using: .utf8) else {
XCTFail("Unable to convert string to data")
return
}
- let res = try JSONSerialization.jsonObject(with: data, options: []) as? [Any]
+ let res = try getjsonObjectResult(data, objectType) as? [Any]
let result = res?.flatMap { $0 as? String }
XCTAssertEqual(result?[0], "\"")
XCTAssertEqual(result?[1], "\\")
@@ -294,15 +498,15 @@
XCTFail("Unexpected error: \(error)")
}
}
-
- func test_deserialize_unicodeEscapeSequence() {
+
+ func deserialize_unicodeEscapeSequence(objectType: ObjectType) {
let subject = "[\"\\u2728\"]"
do {
guard let data = subject.data(using: .utf8) else {
XCTFail("Unable to convert string to data")
return
}
- let result = try JSONSerialization.jsonObject(with: data, options: []) as? [Any]
+ let result = try getjsonObjectResult(data, objectType) as? [Any]
// result?[0] as? String returns an Optional<String> and RHS is promoted
// to Optional<String>
XCTAssertEqual(result?[0] as? String, "✨")
@@ -310,15 +514,15 @@
XCTFail("Unexpected error: \(error)")
}
}
-
- func test_deserialize_unicodeSurrogatePairEscapeSequence() {
+
+ func deserialize_unicodeSurrogatePairEscapeSequence(objectType: ObjectType) {
let subject = "[\"\\uD834\\udd1E\"]"
do {
guard let data = subject.data(using: .utf8) else {
XCTFail("Unable to convert string to data")
return
}
- let result = try JSONSerialization.jsonObject(with: data, options: []) as? [Any]
+ let result = try getjsonObjectResult(data, objectType) as? [Any]
// result?[0] as? String returns an Optional<String> and RHS is promoted
// to Optional<String>
XCTAssertEqual(result?[0] as? String, "\u{1D11E}")
@@ -326,159 +530,227 @@
XCTFail("Unexpected error: \(error)")
}
}
-
- func test_deserialize_allowFragments() {
+
+ func deserialize_allowFragments(objectType: ObjectType) {
let subject = "3"
-
+
do {
for encoding in supportedEncodings {
guard let data = subject.data(using: encoding) else {
XCTFail("Unable to convert string to data")
return
}
- let result = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? Int
+ let result = try getjsonObjectResult(data, objectType) as? Int
XCTAssertEqual(result, 3)
}
} catch {
XCTFail("Unexpected error: \(error)")
}
}
-
+
//MARK: - Parsing Errors
- func test_deserialize_unterminatedObjectString() {
+ func deserialize_unterminatedObjectString(objectType: ObjectType) {
let subject = "{\"}"
-
+
do {
guard let data = subject.data(using: .utf8) else {
XCTFail("Unable to convert string to data")
return
}
- let _ = try JSONSerialization.jsonObject(with: data, options: [])
+ let _ = try getjsonObjectResult(data, objectType)
XCTFail("Expected error: UnterminatedString")
} catch {
// Passing case; the object as unterminated
}
}
-
- func test_deserialize_missingObjectKey() {
+
+ func deserialize_missingObjectKey(objectType: ObjectType) {
let subject = "{3}"
-
+
do {
guard let data = subject.data(using: .utf8) else {
XCTFail("Unable to convert string to data")
return
}
- let _ = try JSONSerialization.jsonObject(with: data, options: [])
+ let _ = try getjsonObjectResult(data, objectType)
XCTFail("Expected error: Missing key for value")
} catch {
// Passing case; the key was missing for a value
}
}
-
- func test_deserialize_unexpectedEndOfFile() {
+
+ func deserialize_unexpectedEndOfFile(objectType: ObjectType) {
let subject = "{"
-
+
do {
guard let data = subject.data(using: .utf8) else {
XCTFail("Unable to convert string to data")
return
}
- let _ = try JSONSerialization.jsonObject(with: data, options: [])
+ let _ = try getjsonObjectResult(data, objectType)
XCTFail("Expected error: Unexpected end of file")
} catch {
// Success
}
}
-
- func test_deserialize_invalidValueInObject() {
+
+ func deserialize_invalidValueInObject(objectType: ObjectType) {
let subject = "{\"error\":}"
-
+
do {
guard let data = subject.data(using: .utf8) else {
XCTFail("Unable to convert string to data")
return
}
- let _ = try JSONSerialization.jsonObject(with: data, options: [])
+ let _ = try getjsonObjectResult(data, objectType)
XCTFail("Expected error: Invalid value")
} catch {
// Passing case; the value is invalid
}
}
-
- func test_deserialize_invalidValueIncorrectSeparatorInObject() {
+
+ func deserialize_invalidValueIncorrectSeparatorInObject(objectType: ObjectType) {
let subject = "{\"missing\";}"
-
+
do {
guard let data = subject.data(using: .utf8) else {
XCTFail("Unable to convert string to data")
return
}
- let _ = try JSONSerialization.jsonObject(with: data, options: [])
+ let _ = try getjsonObjectResult(data, objectType)
XCTFail("Expected error: Invalid value")
} catch {
// passing case the value is invalid
}
}
-
- func test_deserialize_invalidValueInArray() {
+
+ func deserialize_invalidValueInArray(objectType: ObjectType) {
let subject = "[,"
-
+
do {
guard let data = subject.data(using: .utf8) else {
XCTFail("Unable to convert string to data")
return
}
- let _ = try JSONSerialization.jsonObject(with: data, options: [])
+ let _ = try getjsonObjectResult(data, objectType)
XCTFail("Expected error: Invalid value")
} catch {
// Passing case; the element in the array is missing
}
}
-
- func test_deserialize_badlyFormedArray() {
+
+ func deserialize_badlyFormedArray(objectType: ObjectType) {
let subject = "[2b4]"
-
+
do {
guard let data = subject.data(using: .utf8) else {
XCTFail("Unable to convert string to data")
return
}
- let _ = try JSONSerialization.jsonObject(with: data, options: [])
+ let _ = try getjsonObjectResult(data, objectType)
XCTFail("Expected error: Badly formed array")
} catch {
// Passing case; the array is malformed
}
}
-
- func test_deserialize_invalidEscapeSequence() {
+
+ func deserialize_invalidEscapeSequence(objectType: ObjectType) {
let subject = "[\"\\e\"]"
-
+
do {
guard let data = subject.data(using: .utf8) else {
XCTFail("Unable to convert string to data")
return
}
- let _ = try JSONSerialization.jsonObject(with: data, options: [])
+ let _ = try getjsonObjectResult(data, objectType)
XCTFail("Expected error: Invalid escape sequence")
} catch {
// Passing case; the escape sequence is invalid
}
}
-
- func test_deserialize_unicodeMissingTrailingSurrogate() {
+
+ func deserialize_unicodeMissingTrailingSurrogate(objectType: ObjectType) {
let subject = "[\"\\uD834\"]"
do {
guard let data = subject.data(using: .utf8) else {
XCTFail("Unable to convert string to data")
return
}
- let _ = try JSONSerialization.jsonObject(with: data, options: []) as? [String]
+ let _ = try getjsonObjectResult(data, objectType) as? [String]
XCTFail("Expected error: Missing Trailing Surrogate")
} catch {
// Passing case; the unicode character is malformed
}
}
+ func test_JSONObjectWithStream_withFile() {
+ let subject = "{}"
+ do {
+ guard let data = subject.data(using: .utf8) else {
+ XCTFail("Unable to convert string to data")
+ return
+ }
+ let filePath = createTestFile("TestJSON.txt",_contents: data)
+ if filePath != nil {
+ let fileStream: InputStream = InputStream(fileAtPath: filePath!)!
+ fileStream.open()
+ let resultRead = try JSONSerialization.jsonObject(with: fileStream, options: [])
+ let result = resultRead as? [String: Any]
+ XCTAssertEqual(result?.count, 0)
+ fileStream.close()
+ removeTestFile(filePath!)
+ }
+ } catch {
+ XCTFail("Error thrown: \(error)")
+ }
+ }
+
+ func test_JSONObjectWithStream_withURL() {
+ let subject = "[true, false, \"hello\", null, {}, []]"
+ do {
+ for encoding in supportedEncodings {
+ guard let data = subject.data(using: encoding) else {
+ XCTFail("Unable to convert string to data")
+ return
+ }
+ let filePath = createTestFile("TestJSON.txt",_contents: data)
+ if filePath != nil {
+ let url = URL(fileURLWithPath: filePath!)
+ let inputStream: InputStream = InputStream(url: url)!
+ inputStream.open()
+ let result = try JSONSerialization.jsonObject(with: inputStream, options: []) as? [Any]
+ inputStream.close()
+ removeTestFile(filePath!)
+ XCTAssertEqual(result?[0] as? Bool, true)
+ XCTAssertEqual(result?[1] as? Bool, false)
+ XCTAssertEqual(result?[2] as? String, "hello")
+ XCTAssertNotNil(result?[3] as? NSNull)
+ XCTAssertNotNil(result?[4] as? [String:Any])
+ XCTAssertNotNil(result?[5] as? [Any])
+ }
+ }
+ } catch {
+ XCTFail("Unexpected error: \(error)")
+ }
+ }
+
+
+ private func getjsonObjectResult(_ data: Data,_ objectType: ObjectType) throws -> Any {
+ var result: Any
+ switch objectType {
+ case .data:
+ //Test with Data
+ result = try JSONSerialization.jsonObject(with: data, options: [])
+ case .stream:
+ //Test with stream
+ let stream: InputStream = InputStream(data: data)
+ stream.open()
+ result = try JSONSerialization.jsonObject(with: stream, options: [])
+ stream.close()
+ }
+ return result
+ }
+
}
// MARK: - isValidJSONObjectTests
@@ -596,8 +868,10 @@
("test_jsonObjectToOutputStreamBuffer", test_jsonObjectToOutputStreamBuffer),
("test_jsonObjectToOutputStreamFile", test_jsonObjectToOutputStreamFile),
("test_invalidJsonObjectToStreamBuffer", test_invalidJsonObjectToStreamBuffer),
- ("test_jsonObjectToOutputStreamInsufficeintBuffer", test_jsonObjectToOutputStreamInsufficeintBuffer),
+ ("test_jsonObjectToOutputStreamInsufficientBuffer", test_jsonObjectToOutputStreamInsufficientBuffer),
("test_booleanJSONObject", test_booleanJSONObject),
+ ("test_serialize_dictionaryWithDecimal", test_serialize_dictionaryWithDecimal),
+ ("test_serializeDecimalNumberJSONObject", test_serializeDecimalNumberJSONObject),
]
}
@@ -905,7 +1179,7 @@
}
}
- func test_jsonObjectToOutputStreamInsufficeintBuffer() {
+ func test_jsonObjectToOutputStreamInsufficientBuffer() {
let dict = ["a":["b":1]]
let buffer = Array<UInt8>(repeating: 0, count: 10)
let outputStream = OutputStream(toBuffer: UnsafeMutablePointer(mutating: buffer), capacity: buffer.count)
@@ -941,7 +1215,23 @@
XCTAssertTrue(JSONSerialization.isValidJSONObject([true]))
}
- private func createTestFile(_ path: String,_contents: Data) -> String? {
+ func test_serializeDecimalNumberJSONObject() {
+ let decimalArray = "[12.1,10.0,0.0,0.0001,20,\(Int.max)]"
+ do {
+ let data = decimalArray.data(using: String.Encoding.utf8)
+ let result = try JSONSerialization.jsonObject(with: data!, options: []) as? [Any]
+ XCTAssertEqual(result?[0] as! Double, 12.1)
+ XCTAssertEqual(result?[1] as! Int, 10)
+ XCTAssertEqual(result?[2] as! Int, 0)
+ XCTAssertEqual(result?[3] as! Double, 0.0001)
+ XCTAssertEqual(result?[4] as! Int, 20)
+ XCTAssertEqual(result?[5] as! Int, Int.max)
+ } catch {
+ XCTFail("Failed during serialization")
+ }
+ }
+
+ fileprivate func createTestFile(_ path: String,_contents: Data) -> String? {
let tempDir = NSTemporaryDirectory() + "TestFoundation_Playground_" + NSUUID().uuidString + "/"
do {
try FileManager.default.createDirectory(atPath: tempDir, withIntermediateDirectories: false, attributes: nil)
@@ -956,7 +1246,7 @@
}
}
- private func removeTestFile(_ location: String) {
+ fileprivate func removeTestFile(_ location: String) {
do {
try FileManager.default.removeItem(atPath: location)
} catch _ {
diff --git a/TestFoundation/TestNSNotificationQueue.swift b/TestFoundation/TestNSNotificationQueue.swift
index 30a6645..2cea068 100644
--- a/TestFoundation/TestNSNotificationQueue.swift
+++ b/TestFoundation/TestNSNotificationQueue.swift
@@ -19,6 +19,9 @@
class TestNSNotificationQueue : XCTestCase {
static var allTests : [(String, (TestNSNotificationQueue) -> () throws -> Void)] {
return [
+/*
+FIXME SR-4280 timeouts in TestNSNotificationQueue tests
+
("test_defaultQueue", test_defaultQueue),
("test_postNowToDefaultQueueWithoutCoalescing", test_postNowToDefaultQueueWithoutCoalescing),
("test_postNowToDefaultQueueWithCoalescing", test_postNowToDefaultQueueWithCoalescing),
@@ -29,6 +32,7 @@
("test_postAsapToDefaultQueueWithCoalescingOnNameAndSender", test_postAsapToDefaultQueueWithCoalescingOnNameAndSender),
("test_postAsapToDefaultQueueWithCoalescingOnNameOrSender", test_postAsapToDefaultQueueWithCoalescingOnNameOrSender),
("test_postIdleToDefaultQueue", test_postIdleToDefaultQueue),
+*/
]
}
diff --git a/TestFoundation/TestNSOperationQueue.swift b/TestFoundation/TestNSOperationQueue.swift
index cc74b86..783115f 100644
--- a/TestFoundation/TestNSOperationQueue.swift
+++ b/TestFoundation/TestNSOperationQueue.swift
@@ -16,12 +16,14 @@
import SwiftFoundation
import SwiftXCTest
#endif
+import Dispatch
class TestNSOperationQueue : XCTestCase {
static var allTests: [(String, (TestNSOperationQueue) -> () throws -> Void)] {
return [
("test_OperationPriorities", test_OperationPriorities),
- ("test_OperationCount", test_OperationCount)
+ ("test_OperationCount", test_OperationCount),
+ ("test_AsyncOperation", test_AsyncOperation)
]
}
@@ -65,4 +67,76 @@
XCTAssertEqual(msgOperations[2], "Operation2 executed")
XCTAssertEqual(msgOperations[3], "Operation4 executed")
}
+
+ func test_AsyncOperation() {
+ let operation = AsyncOperation()
+ XCTAssertFalse(operation.isExecuting)
+ XCTAssertFalse(operation.isFinished)
+
+ operation.start()
+
+ while !operation.isFinished {
+ // do nothing
+ }
+
+ XCTAssertFalse(operation.isExecuting)
+ XCTAssertTrue(operation.isFinished)
+ }
+}
+
+class AsyncOperation: Operation {
+
+ private let queue = DispatchQueue(label: "async.operation.queue")
+ private let lock = NSLock()
+
+ private var _executing = false
+ private var _finished = false
+
+ override internal(set) var isExecuting: Bool {
+ get {
+ return _executing
+ }
+ set {
+ if _executing != newValue {
+ willChangeValue(forKey: "isExecuting")
+ _executing = newValue
+ didChangeValue(forKey: "isExecuting")
+ }
+ }
+ }
+
+ override internal(set) var isFinished: Bool {
+ get {
+ return _finished
+ }
+ set {
+ if _finished != newValue {
+ willChangeValue(forKey: "isFinished")
+ _finished = newValue
+ didChangeValue(forKey: "isFinished")
+ }
+ }
+ }
+
+ override var isAsynchronous: Bool {
+ return true
+ }
+
+ override func start() {
+ if isCancelled {
+ isFinished = true
+ return
+ }
+
+ isExecuting = true
+
+ queue.async {
+ sleep(1)
+ self.lock.lock()
+ self.isExecuting = false
+ self.isFinished = true
+ self.lock.unlock()
+ }
+ }
+
}
diff --git a/TestFoundation/TestNSOrderedSet.swift b/TestFoundation/TestNSOrderedSet.swift
index d043824..10761b3 100644
--- a/TestFoundation/TestNSOrderedSet.swift
+++ b/TestFoundation/TestNSOrderedSet.swift
@@ -207,10 +207,11 @@
func test_ReplaceObject() {
let set = NSMutableOrderedSet(arrayLiteral: "foo", "bar", "baz")
set.replaceObject(at: 1, with: "123")
+ set[2] = "456"
XCTAssertEqual(set.count, 3)
XCTAssertEqual(set[0] as? String, "foo")
XCTAssertEqual(set[1] as? String, "123")
- XCTAssertEqual(set[2] as? String, "baz")
+ XCTAssertEqual(set[2] as? String, "456")
}
func test_ExchangeObjects() {
diff --git a/TestFoundation/TestNSRegularExpression.swift b/TestFoundation/TestNSRegularExpression.swift
index 5e5eb77..8b115cc 100644
--- a/TestFoundation/TestNSRegularExpression.swift
+++ b/TestFoundation/TestNSRegularExpression.swift
@@ -35,7 +35,7 @@
do {
let str = NSString(string: searchString)
var range = NSMakeRange(0, str.length)
- let regex = try NSRegularExpression(pattern: patternString, options: [])
+ let regex = try NSRegularExpression(pattern: patternString)
do {
let lookingRange = regex.rangeOfFirstMatch(in: searchString, options: .anchored, range: range)
let matchRange = regex.rangeOfFirstMatch(in: searchString, options: [], range: range)
diff --git a/TestFoundation/TestNSString.swift b/TestFoundation/TestNSString.swift
index 86e5daa..58a1c8a 100644
--- a/TestFoundation/TestNSString.swift
+++ b/TestFoundation/TestNSString.swift
@@ -66,6 +66,8 @@
("test_rangeOfCharacterFromSet", test_rangeOfCharacterFromSet ),
("test_CFStringCreateMutableCopy", test_CFStringCreateMutableCopy),
("test_FromContentsOfURL",test_FromContentsOfURL),
+ ("test_FromContentsOfURLUsedEncodingUTF16BE", test_FromContentsOfURLUsedEncodingUTF16BE),
+ ("test_FromContentsOfURLUsedEncodingUTF16LE", test_FromContentsOfURLUsedEncodingUTF16LE),
("test_FromContentOfFile",test_FromContentOfFile),
("test_swiftStringUTF16", test_swiftStringUTF16),
// This test takes forever on build servers; it has been seen up to 1852.084 seconds
@@ -300,6 +302,38 @@
}
}
+ func test_FromContentsOfURLUsedEncodingUTF16BE() {
+ guard let testFileURL = testBundle().url(forResource: "NSString-UTF16-BE-data", withExtension: "txt") else {
+ XCTFail("URL for NSString-UTF16-BE-data.txt is nil")
+ return
+ }
+
+ do {
+ var encoding: UInt = 0
+ let string = try NSString(contentsOf: testFileURL, usedEncoding: &encoding)
+ XCTAssertEqual(string, "NSString fromURL usedEncoding test with UTF16 BE file", "Wrong result when reading UTF16BE file")
+ XCTAssertEqual(encoding, String.Encoding.utf16BigEndian.rawValue, "Wrong encoding detected from UTF16BE file")
+ } catch {
+ XCTFail("Unable to init NSString from contentsOf:usedEncoding:")
+ }
+ }
+
+ func test_FromContentsOfURLUsedEncodingUTF16LE() {
+ guard let testFileURL = testBundle().url(forResource: "NSString-UTF16-LE-data", withExtension: "txt") else {
+ XCTFail("URL for NSString-UTF16-LE-data.txt is nil")
+ return
+ }
+
+ do {
+ var encoding: UInt = 0
+ let string = try NSString(contentsOf: testFileURL, usedEncoding: &encoding)
+ XCTAssertEqual(string, "NSString fromURL usedEncoding test with UTF16 LE file", "Wrong result when reading UTF16LE file")
+ XCTAssertEqual(encoding, String.Encoding.utf16LittleEndian.rawValue, "Wrong encoding detected from UTF16LE file")
+ } catch {
+ XCTFail("Unable to init NSString from contentOf:usedEncoding:")
+ }
+ }
+
func test_FromContentOfFile() {
let testFilePath = testBundle().path(forResource: "NSStringTestData", ofType: "txt")
XCTAssertNotNil(testFilePath)
diff --git a/TestFoundation/TestNSURLSession.swift b/TestFoundation/TestNSURLSession.swift
index cce1508..022c601 100644
--- a/TestFoundation/TestNSURLSession.swift
+++ b/TestFoundation/TestNSURLSession.swift
@@ -33,20 +33,22 @@
("test_taskError", test_taskError),
("test_taskCopy", test_taskCopy),
("test_cancelTask", test_cancelTask),
+ ("test_taskTimeout", test_taskTimeout),
+ ("test_verifyRequestHeaders", test_verifyRequestHeaders),
]
}
- private func runServer(with condition: ServerSemaphore) throws {
+ private func runServer(with condition: ServerSemaphore, startDelay: TimeInterval? = nil, sendDelay: TimeInterval? = nil, bodyChunks: Int? = nil) throws {
let start = 21961
for port in start...(start+100) { //we must find at least one port to bind
do {
serverPort = port
- let test = try TestURLSessionServer(port: UInt16(port))
+ let test = try TestURLSessionServer(port: UInt16(port), startDelay: startDelay, sendDelay: sendDelay, bodyChunks: bodyChunks)
try test.start(started: condition)
try test.readAndRespond()
test.stop()
} catch let e as ServerError {
- if e.operation != "bind" { continue }
+ if e.operation == "bind" { continue }
throw e
}
}
@@ -65,14 +67,14 @@
serverReady.wait()
let urlString = "http://127.0.0.1:\(serverPort)/Nepal"
let url = URL(string: urlString)!
- let d = DataTask(with: expectation(description: "data task"))
+ let d = DataTask(with: expectation(description: "data task"))
d.run(with: url)
waitForExpectations(timeout: 12)
if !d.error {
XCTAssertEqual(d.capital, "Kathmandu", "test_dataTaskWithURLRequest returned an unexpected result")
}
}
-
+
func test_dataTaskWithURLCompletionHandler() {
let serverReady = ServerSemaphore()
globalDispatchQueue.async {
@@ -80,7 +82,7 @@
try self.runServer(with: serverReady)
} catch {
XCTAssertTrue(true)
- return
+ return
}
}
serverReady.wait()
@@ -99,7 +101,7 @@
}
let httpResponse = response as! HTTPURLResponse?
- XCTAssertEqual(200, httpResponse!.statusCode, "HTTP response code is not 200")
+ XCTAssertEqual(200, httpResponse!.statusCode, "HTTP response code is not 200")
expectedResult = String(data: data!, encoding: String.Encoding.utf8)!
XCTAssertEqual("Washington, D.C.", expectedResult, "Did not receive expected value")
expect.fulfill()
@@ -121,7 +123,7 @@
serverReady.wait()
let urlString = "http://127.0.0.1:\(serverPort)/Peru"
let urlRequest = URLRequest(url: URL(string: urlString)!)
- let d = DataTask(with: expectation(description: "data task"))
+ let d = DataTask(with: expectation(description: "data task"))
d.run(with: urlRequest)
waitForExpectations(timeout: 12)
if !d.error {
@@ -175,7 +177,7 @@
}
serverReady.wait()
let urlString = "http://127.0.0.1:\(serverPort)/country.txt"
- let url = URL(string: urlString)!
+ let url = URL(string: urlString)!
let d = DownloadTask(with: expectation(description: "download task with delegate"))
d.run(with: url)
waitForExpectations(timeout: 12)
@@ -250,7 +252,7 @@
task.resume()
waitForExpectations(timeout: 12)
}
-
+
func test_finishTasksAndInvalidate() {
let invalidateExpectation = expectation(description: "URLSession wasn't invalidated")
let delegate = SessionDelegate(invalidateExpectation: invalidateExpectation)
@@ -265,7 +267,7 @@
session.finishTasksAndInvalidate()
waitForExpectations(timeout: 12)
}
-
+
func test_taskError() {
let url = URL(string: "http://127.0.0.1:\(serverPort)/Nepal")!
let session = URLSession(configuration: URLSessionConfiguration.default,
@@ -280,22 +282,22 @@
}
//should result in Bad URL error
task.resume()
-
+
waitForExpectations(timeout: 5) { error in
XCTAssertNil(error)
-
+
XCTAssertNotNil(task.error)
XCTAssertEqual((task.error as? URLError)?.code, .badURL)
}
}
-
+
func test_taskCopy() {
let url = URL(string: "http://127.0.0.1:\(serverPort)/Nepal")!
let session = URLSession(configuration: URLSessionConfiguration.default,
delegate: nil,
delegateQueue: nil)
let task = session.dataTask(with: url)
-
+
XCTAssert(task.isEqual(task.copy()))
}
@@ -318,6 +320,59 @@
waitForExpectations(timeout: 12)
}
+ func test_verifyRequestHeaders() {
+ let serverReady = ServerSemaphore()
+ globalDispatchQueue.async {
+ do {
+ try self.runServer(with: serverReady)
+ } catch {
+ XCTAssertTrue(true)
+ return
+ }
+ }
+ serverReady.wait()
+ let config = URLSessionConfiguration.default
+ config.timeoutIntervalForRequest = 5
+ let session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
+ var expect = expectation(description: "download task with handler")
+ var req = URLRequest(url: URL(string: "http://127.0.0.1:\(serverPort)/requestHeaders")!)
+ let headers = ["header1": "value1"]
+ req.httpMethod = "POST"
+ req.allHTTPHeaderFields = headers
+ var task = session.dataTask(with: req) { (data, _, error) -> Void in
+ defer { expect.fulfill() }
+ let headers = String(data: data!, encoding: String.Encoding.utf8)!
+ XCTAssertNotNil(headers.range(of: "header1: value1"))
+ }
+ task.resume()
+
+ waitForExpectations(timeout: 30)
+ }
+
+ func test_taskTimeout() {
+ let serverReady = ServerSemaphore()
+ globalDispatchQueue.async {
+ do {
+ try self.runServer(with: serverReady, startDelay: 3, sendDelay: 3, bodyChunks: 3)
+ } catch {
+ XCTAssertTrue(true)
+ return
+ }
+ }
+ serverReady.wait()
+ let config = URLSessionConfiguration.default
+ config.timeoutIntervalForRequest = 5
+ let session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
+ var expect = expectation(description: "download task with handler")
+ let req = URLRequest(url: URL(string: "http://127.0.0.1:\(serverPort)/Peru")!)
+ var task = session.dataTask(with: req) { (data, _, error) -> Void in
+ defer { expect.fulfill() }
+ XCTAssertNil(error)
+ }
+ task.resume()
+
+ waitForExpectations(timeout: 30)
+ }
}
class SessionDelegate: NSObject, URLSessionDelegate {
@@ -340,7 +395,7 @@
public var error = false
init(with expectation: XCTestExpectation) {
- dataTaskExpectation = expectation
+ dataTaskExpectation = expectation
}
func run(with request: URLRequest) {
@@ -350,7 +405,7 @@
task = session.dataTask(with: request)
task.resume()
}
-
+
func run(with url: URL) {
let config = URLSessionConfiguration.default
config.timeoutIntervalForRequest = 8
@@ -380,7 +435,7 @@
}
self.error = true
}
-}
+}
class DownloadTask : NSObject {
var totalBytesWritten: Int64 = 0
@@ -410,12 +465,12 @@
}
extension DownloadTask : URLSessionDownloadDelegate {
-
+
public func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64,
totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) -> Void {
self.totalBytesWritten = totalBytesWritten
}
-
+
public func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
do {
let attr = try FileManager.default.attributesOfItem(atPath: location.path)
diff --git a/build.py b/build.py
index 4f9d9e9..625b17c 100644
--- a/build.py
+++ b/build.py
@@ -16,7 +16,7 @@
swift_cflags = ['-DDEPLOYMENT_RUNTIME_SWIFT']
if Configuration.current.target.sdk == OSType.Linux:
foundation.CFLAGS = '-DDEPLOYMENT_TARGET_LINUX -D_GNU_SOURCE -DCF_CHARACTERSET_DATA_DIR="CoreFoundation/CharacterSets"'
- foundation.LDFLAGS = '${SWIFT_USE_LINKER} -Wl,@./CoreFoundation/linux.ld -lswiftGlibc `${PKG_CONFIG} icu-uc icu-i18n --libs` -Wl,-defsym,__CFConstantStringClassReference=_TMC10Foundation19_NSCFConstantString -Wl,-Bsymbolic '
+ foundation.LDFLAGS = '${SWIFT_USE_LINKER} -Wl,@./CoreFoundation/linux.ld -lswiftGlibc `${PKG_CONFIG} icu-uc icu-i18n --libs` -Wl,-defsym,__CFConstantStringClassReference=_T010Foundation19_NSCFConstantStringCN -Wl,-Bsymbolic '
Configuration.current.requires_pkg_config = True
elif Configuration.current.target.sdk == OSType.FreeBSD:
foundation.CFLAGS = '-DDEPLOYMENT_TARGET_FREEBSD -I/usr/local/include -I/usr/local/include/libxml2 -I/usr/local/include/curl '
@@ -26,7 +26,7 @@
foundation.LDFLAGS = '-licucore -twolevel_namespace -Wl,-alias_list,CoreFoundation/Base.subproj/DarwinSymbolAliases -sectcreate __UNICODE __csbitmaps CoreFoundation/CharacterSets/CFCharacterSetBitmaps.bitmap -sectcreate __UNICODE __properties CoreFoundation/CharacterSets/CFUniCharPropertyDatabase.data -sectcreate __UNICODE __data CoreFoundation/CharacterSets/CFUnicodeData-L.mapping -segprot __UNICODE r r '
elif Configuration.current.target.sdk == OSType.Win32 and Configuration.current.target.environ == EnvironmentType.Cygnus:
foundation.CFLAGS = '-DDEPLOYMENT_TARGET_LINUX -D_GNU_SOURCE -mcmodel=large '
- foundation.LDFLAGS = '${SWIFT_USE_LINKER} -lswiftGlibc `icu-config --ldflags` -Wl,-defsym,__CFConstantStringClassReference=_TMC10Foundation19_NSCFConstantString,--allow-multiple-definition '
+ foundation.LDFLAGS = '${SWIFT_USE_LINKER} -lswiftGlibc `icu-config --ldflags` -Wl,-defsym,__CFConstantStringClassReference=_T010Foundation19_NSCFConstantStringCN,--allow-multiple-definition '
swift_cflags += ['-DCYGWIN']
if Configuration.current.build_mode == Configuration.Debug:
@@ -460,6 +460,8 @@
'TestFoundation/Resources/NSURLTestData.plist',
'TestFoundation/Resources/Test.plist',
'TestFoundation/Resources/NSStringTestData.txt',
+ 'TestFoundation/Resources/NSString-UTF16-BE-data.txt',
+ 'TestFoundation/Resources/NSString-UTF16-LE-data.txt',
'TestFoundation/Resources/NSXMLDocumentTestData.xml',
'TestFoundation/Resources/PropertyList-1.0.dtd',
'TestFoundation/Resources/NSXMLDTDTestData.xml',