Merge pull request #1200 from ddunn2/formatterWork

diff --git a/Foundation/JSONSerialization.swift b/Foundation/JSONSerialization.swift
index a7b011f..f74932d 100644
--- a/Foundation/JSONSerialization.swift
+++ b/Foundation/JSONSerialization.swift
@@ -62,8 +62,9 @@
                 return true
             }
             
-            // object is Swift.String, NSNull, Int, Bool, or UInt
-            if obj is String || obj is NSNull || obj is Int || obj is Bool || obj is UInt {
+            if obj is String || obj is NSNull || obj is Int || obj is Bool || obj is UInt ||
+                obj is Int8 || obj is Int16 || obj is Int32 || obj is Int64 ||
+                obj is UInt8 || obj is UInt16 || obj is UInt32 || obj is UInt64 {
                 return true
             }
 
@@ -76,6 +77,10 @@
                 return number.isFinite
             }
 
+            if let number = obj as? Decimal {
+                return number.isFinite
+            }
+
             // object is Swift.Array
             if let array = obj as? [Any?] {
                 for element in array {
@@ -99,8 +104,13 @@
             // object is NSNumber and is not NaN or infinity
             // For better performance, this (most expensive) test should be last.
             if let number = _SwiftValue.store(obj) as? NSNumber {
-                let invalid = number.doubleValue.isInfinite || number.doubleValue.isNaN
-                return !invalid
+                if CFNumberIsFloatType(number._cfObject) {
+                    let dv = number.doubleValue
+                    let invalid = dv.isInfinite || dv.isNaN
+                    return !invalid
+                } else {
+                    return true
+                }
             }
 
             // invalid object
@@ -285,9 +295,7 @@
 
 //MARK: - JSONSerializer
 private struct JSONWriter {
-    
-    private let maxUIntLength = String(describing: UInt.max).count
-    private let maxIntLength = String(describing: Int.max).count
+
     var indent = 0
     let pretty: Bool
     let sortedKeys: Bool
@@ -320,13 +328,37 @@
         case let boolValue as Bool:
             serializeBool(boolValue)
         case let num as Int:
-            try serializeInt(value: num)
+            serializeInteger(value: num)
+        case let num as Int8:
+            serializeInteger(value: num)
+        case let num as Int16:
+            serializeInteger(value: num)
+        case let num as Int32:
+            serializeInteger(value: num)
+        case let num as Int64:
+            serializeInteger(value: num)
         case let num as UInt:
-            try serializeUInt(value: num)
+            serializeInteger(value: num)
+        case let num as UInt8:
+            serializeInteger(value: num)
+        case let num as UInt16:
+            serializeInteger(value: num)
+        case let num as UInt32:
+            serializeInteger(value: num)
+        case let num as UInt64:
+            serializeInteger(value: num)
         case let array as Array<Any?>:
             try serializeArray(array)
         case let dict as Dictionary<AnyHashable, Any?>:
             try serializeDictionary(dict)
+        case let num as Float:
+            try serializeNumber(NSNumber(value: num))
+        case let num as Double:
+            try serializeNumber(NSNumber(value: num))
+        case let num as Decimal:
+            writer(num.description)
+        case let num as NSDecimalNumber:
+            writer(num.description)
         case is NSNull:
             try serializeNull()
         case _ where _SwiftValue.store(obj) is NSNumber:
@@ -336,92 +368,33 @@
         }
     }
 
-    private func serializeUInt(value: UInt) throws {
-        if value == 0 {
-            writer("0")
-            return
-        }
-        var array: [UInt] = []
-        var stringResult = ""
-        //Maximum length of an UInt
-        array.reserveCapacity(maxUIntLength)
-        stringResult.reserveCapacity(maxUIntLength)
-        var number = value
-        
-        while number != 0 {
-            array.append(number % 10)
+    private func serializeInteger<T: UnsignedInteger>(value: T, isNegative: Bool = false) {
+        let maxIntLength = 22   // 20 digits in UInt64 + optional sign + trailing '\0'
+        let asciiZero: CChar = 0x30  // ASCII '0' == 0x30
+        let asciiMinus: CChar = 0x2d // ASCII '-' == 0x2d
+
+        var number = UInt64(value)
+        var buffer = Array<CChar>(repeating: 0, count: maxIntLength)
+        var pos = maxIntLength - 1
+
+        repeat {
+            pos -= 1
+            buffer[pos] = asciiZero + CChar(number % 10)
             number /= 10
+        } while number != 0
+
+        if isNegative {
+            pos -= 1
+            buffer[pos] = asciiMinus
         }
-        
-        /*
-         Step backwards through the array and append the values to the string. This way the values are appended in the correct order.
-         */
-        var counter = array.count
-        while counter > 0 {
-            counter -= 1
-            let digit: UInt = array[counter]
-            switch digit {
-            case 0: stringResult.append("0")
-            case 1: stringResult.append("1")
-            case 2: stringResult.append("2")
-            case 3: stringResult.append("3")
-            case 4: stringResult.append("4")
-            case 5: stringResult.append("5")
-            case 6: stringResult.append("6")
-            case 7: stringResult.append("7")
-            case 8: stringResult.append("8")
-            case 9: stringResult.append("9")
-            default: fatalError()
-            }
-        }
-        
-        writer(stringResult)
+        let output = String(cString: Array(buffer.suffix(from: pos)))
+        writer(output)
     }
-    
-    private func serializeInt(value: Int) throws {
-        if value == 0 {
-            writer("0")
-            return
-        }
-        var array: [Int] = []
-        var stringResult = ""
-        array.reserveCapacity(maxIntLength)
-        //Account for a negative sign
-        stringResult.reserveCapacity(maxIntLength + 1)
-        var number = value
-        
-        while number != 0 {
-            array.append(number % 10)
-            number /= 10
-        }
-        //If negative add minus sign before adding any values
-        if value < 0 {
-            stringResult.append("-")
-        }
-        /*
-         Step backwards through the array and append the values to the string. This way the values are appended in the correct order.
-         */
-        var counter = array.count
-        while counter > 0 {
-            counter -= 1
-            let digit = array[counter]
-            switch digit {
-            case 0: stringResult.append("0")
-            case 1, -1: stringResult.append("1")
-            case 2, -2: stringResult.append("2")
-            case 3, -3: stringResult.append("3")
-            case 4, -4: stringResult.append("4")
-            case 5, -5: stringResult.append("5")
-            case 6, -6: stringResult.append("6")
-            case 7, -7: stringResult.append("7")
-            case 8, -8: stringResult.append("8")
-            case 9, -9: stringResult.append("9")
-            default: fatalError()
-            }
-        }
-        writer(stringResult)
+
+    private func serializeInteger<T: SignedInteger>(value: T) {
+        serializeInteger(value: UInt64(value.magnitude), isNegative: value < 0)
     }
-    
+
     func serializeString(_ str: String) throws {
         writer("\"")
         for scalar in str.unicodeScalars {
@@ -462,15 +435,30 @@
     }
 
     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"])
-        }
-        
-        switch num._cfTypeID {
-        case CFBooleanGetTypeID():
-            serializeBool(num.boolValue)
-        default:
-            writer(_serializationString(for: num))
+        if CFNumberIsFloatType(num._cfObject) {
+            let dv = num.doubleValue
+            if !dv.isFinite {
+                let value: String
+                if dv.isNaN {
+                    value = "NaN"
+                } else if dv.isInfinite {
+                    value = "infinite"
+                } else {
+                    value = String(dv)
+                }
+
+                throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.propertyListReadCorrupt.rawValue, userInfo: ["NSDebugDescription" : "Invalid number value (\(value)) in JSON write"])
+            }
+
+            let string = CFNumberFormatterCreateStringWithNumber(nil, _numberformatter, num._cfObject)._swiftObject
+            writer(string)
+        } else {
+            switch num._cfTypeID {
+            case CFBooleanGetTypeID():
+                serializeBool(num.boolValue)
+            default:
+                writer(num.stringValue)
+            }
         }
     }
 
@@ -578,13 +566,6 @@
         }
     }
 
-    //[SR-2151] https://bugs.swift.org/browse/SR-2151
-    private mutating func _serializationString(for number: NSNumber) -> String {
-        if !CFNumberIsFloatType(number._cfObject) {
-            return number.stringValue
-        }
-        return CFNumberFormatterCreateStringWithNumber(nil, _numberformatter, number._cfObject)._swiftObject
-    }
 }
 
 //MARK: - JSONDeserializer
diff --git a/Foundation/NSNumber.swift b/Foundation/NSNumber.swift
index 1759771..02429d2 100644
--- a/Foundation/NSNumber.swift
+++ b/Foundation/NSNumber.swift
@@ -226,7 +226,7 @@
         case let other as Bool:
             return boolValue == other
         case let other as NSNumber:
-            return CFEqual(_cfObject, other._cfObject)
+            return compare(other) == .orderedSame
         default:
             return false
         }
diff --git a/Foundation/URLSession/URLSessionTask.swift b/Foundation/URLSession/URLSessionTask.swift
index 6149f17..98ded2c 100644
--- a/Foundation/URLSession/URLSessionTask.swift
+++ b/Foundation/URLSession/URLSessionTask.swift
@@ -33,7 +33,7 @@
     internal var suspendCount = 1
     internal var session: URLSessionProtocol! //change to nil when task completes
     internal let body: _Body
-    fileprivate var _protocol: URLProtocol! = nil
+    fileprivate var _protocol: URLProtocol? = nil
     private let syncQ = DispatchQueue(label: "org.swift.URLSessionTask.SyncQ")
     
     /// All operations must run on this queue.
@@ -178,8 +178,8 @@
             self.workQueue.async {
                 let urlError = URLError(_nsError: NSError(domain: NSURLErrorDomain, code: NSURLErrorCancelled, userInfo: nil))
                 self.error = urlError
-                self._protocol.stopLoading()
-                self._protocol.client?.urlProtocol(self._protocol, didFailWithError: urlError)
+                self._protocol?.stopLoading()
+                self._protocol?.client?.urlProtocol(self._protocol!, didFailWithError: urlError)
             }
         }
     }
@@ -235,7 +235,7 @@
             
             if self.suspendCount == 1 {
                 self.workQueue.async {
-                    self._protocol.stopLoading()
+                    self._protocol?.stopLoading()
                 }
             }
         }
@@ -250,7 +250,21 @@
             self.updateTaskState()
             if self.suspendCount == 0 {
                 self.workQueue.async {
-                    self._protocol.startLoading()
+                    if let _protocol = self._protocol {
+                        _protocol.startLoading()
+                    }
+                    else if self.error == nil {
+                        var userInfo: [String: Any] = [NSLocalizedDescriptionKey: "unsupported URL"]
+                        if let url = self.originalRequest?.url {
+                            userInfo[NSURLErrorFailingURLErrorKey] = url
+                            userInfo[NSURLErrorFailingURLStringErrorKey] = url.absoluteString
+                        }
+                        let urlError = URLError(_nsError: NSError(domain: NSURLErrorDomain,
+                                                                  code: NSURLErrorUnsupportedURL,
+                                                                  userInfo: userInfo))
+                        self.error = urlError
+                        _ProtocolClient().urlProtocol(task: self, didFailWithError: urlError)
+                    }
                 }
             }
         }
@@ -547,6 +561,7 @@
                 session.taskRegistry.remove(task)
             }
         }
+        task._protocol = nil
     }
 
     func urlProtocol(_ protocol: URLProtocol, didCancel challenge: URLAuthenticationChallenge) {
@@ -574,6 +589,10 @@
 
     func urlProtocol(_ protocol: URLProtocol, didFailWithError error: Error) {
         guard let task = `protocol`.task else { fatalError() }
+        urlProtocol(task: task, didFailWithError: error)
+    }
+
+    func urlProtocol(task: URLSessionTask, didFailWithError error: Error) {
         guard let session = task.session as? URLSession else { fatalError() }
         switch session.behaviour(for: task) {
         case .taskDelegate(let delegate):
@@ -602,6 +621,7 @@
                 session.taskRegistry.remove(task)
             }
         }
+        task._protocol = nil
     }
 
     func urlProtocol(_ protocol: URLProtocol, cachedResponseIsValid cachedResponse: CachedURLResponse) {
diff --git a/Foundation/URLSession/http/HTTPURLProtocol.swift b/Foundation/URLSession/http/HTTPURLProtocol.swift
index 307a64f..78aff84 100644
--- a/Foundation/URLSession/http/HTTPURLProtocol.swift
+++ b/Foundation/URLSession/http/HTTPURLProtocol.swift
@@ -13,13 +13,14 @@
 internal class _HTTPURLProtocol: URLProtocol {
 
     fileprivate var easyHandle: _EasyHandle!
-    fileprivate var tempFileURL: URL
+    fileprivate lazy var tempFileURL: URL = {
+        let fileName = NSTemporaryDirectory() + NSUUID().uuidString + ".tmp"
+        _ = FileManager.default.createFile(atPath: fileName, contents: nil)
+        return URL(fileURLWithPath: fileName)
+    }()
 
     public required init(task: URLSessionTask, cachedResponse: CachedURLResponse?, client: URLProtocolClient?) {
         self.internalState = _InternalState.initial
-        let fileName = NSTemporaryDirectory() + NSUUID().uuidString + ".tmp"
-        _ = FileManager.default.createFile(atPath: fileName, contents: nil)
-        self.tempFileURL = URL(fileURLWithPath: fileName)
         super.init(request: task.originalRequest!, cachedResponse: cachedResponse, client: client)
         self.task = task
         self.easyHandle = _EasyHandle(delegate: self)
@@ -27,9 +28,6 @@
 
     public required init(request: URLRequest, cachedResponse: CachedURLResponse?, client: URLProtocolClient?) {
         self.internalState = _InternalState.initial
-        let fileName = NSTemporaryDirectory() + NSUUID().uuidString + ".tmp"
-        _ = FileManager.default.createFile(atPath: fileName, contents: nil)
-        self.tempFileURL = URL(fileURLWithPath: fileName)
         super.init(request: request, cachedResponse: cachedResponse, client: client)
         self.easyHandle = _EasyHandle(delegate: self)
     }
diff --git a/Foundation/URLSession/http/MultiHandle.swift b/Foundation/URLSession/http/MultiHandle.swift
index bb2acaf..506c9a9 100644
--- a/Foundation/URLSession/http/MultiHandle.swift
+++ b/Foundation/URLSession/http/MultiHandle.swift
@@ -39,11 +39,7 @@
         let group = DispatchGroup()
         fileprivate var easyHandles: [_EasyHandle] = []
         fileprivate var timeoutSource: _TimeoutSource? = nil
-
-        //SR-4567: we need to synchronize the register/unregister commands to the epoll machinery in libdispatch
-        fileprivate let commandQueue: DispatchQueue = DispatchQueue(label: "Register-unregister synchronization")
-        fileprivate var cancelInProgress: DispatchSemaphore? = nil
-
+        
         init(configuration: URLSession._Configuration, workQueue: DispatchQueue) {
             queue = DispatchQueue(label: "MultiHandle.isolation", target: workQueue)
             setupCallbacks()
@@ -103,33 +99,25 @@
         // through libdispatch (DispatchSource) and store the source(s) inside
         // a `SocketSources` which we in turn store inside libcurl's multi handle
         // by means of curl_multi_assign() -- we retain the object fist.
-        commandQueue.async {
-            self.cancelInProgress?.wait()
-            self.cancelInProgress = nil
-
-            let action = _SocketRegisterAction(rawValue: CFURLSessionPoll(value: what))
-            var socketSources = _SocketSources.from(socketSourcePtr: socketSourcePtr)
-            if socketSources == nil && action.needsSource {
-                let s = _SocketSources()
-                let p = Unmanaged.passRetained(s).toOpaque()
-                CFURLSessionMultiHandleAssign(self.rawHandle, socket, UnsafeMutableRawPointer(p))
-                socketSources = s
-            } else if socketSources != nil && action == .unregister {
-                //the beginning of an unregister operation
-                self.cancelInProgress = DispatchSemaphore(value: 0)
-                // We need to release the stored pointer:
-                if let opaque = socketSourcePtr {
-                    Unmanaged<_SocketSources>.fromOpaque(opaque).release()
-                }
-                socketSources?.tearDown(self.cancelInProgress)
-                socketSources = nil
+        let action = _SocketRegisterAction(rawValue: CFURLSessionPoll(value: what))
+        var socketSources = _SocketSources.from(socketSourcePtr: socketSourcePtr)
+        if socketSources == nil && action.needsSource {
+            let s = _SocketSources()
+            let p = Unmanaged.passRetained(s).toOpaque()
+            CFURLSessionMultiHandleAssign(rawHandle, socket, UnsafeMutableRawPointer(p))
+            socketSources = s
+        } else if socketSources != nil && action == .unregister {
+            // We need to release the stored pointer:
+            if let opaque = socketSourcePtr {
+                Unmanaged<_SocketSources>.fromOpaque(opaque).release()
             }
-            if let ss = socketSources {
-                let handler = DispatchWorkItem { [weak self] in
-                    self?.performAction(for: socket)
-                }
-                ss.createSources(with: action, fileDescriptor: Int(socket), queue: self.queue, handler: handler)
+            socketSources = nil
+        }
+        if let ss = socketSources {
+            let handler = DispatchWorkItem { [weak self] in
+                self?.performAction(for: socket)
             }
+            ss.createSources(with: action, fileDescriptor: Int(socket), queue: queue, handler: handler)
         }
         return 0
     }
@@ -411,18 +399,12 @@
         s.resume()
     }
 
-    func tearDown(_ cancelInProgress: DispatchSemaphore?) {
-        let cancelHandler = DispatchWorkItem {
-            //the real end of an unregister operation!
-            cancelInProgress?.signal()
-        }
+    func tearDown() {
         if let s = readSource {
-            s.setCancelHandler(handler: cancelHandler)
             s.cancel()
         }
         readSource = nil
         if let s = writeSource {
-            s.setCancelHandler(handler: cancelHandler)
             s.cancel()
         }
         writeSource = nil
diff --git a/TestFoundation/HTTPServer.swift b/TestFoundation/HTTPServer.swift
index 14823d5..f52b771 100644
--- a/TestFoundation/HTTPServer.swift
+++ b/TestFoundation/HTTPServer.swift
@@ -37,6 +37,12 @@
     static let EMPTY = ""
 }
 
+extension UInt16 {
+    public init(networkByteOrder input: UInt16) {
+        self.init(bigEndian: input)
+    }
+}
+
 class _TCPSocket {
   
     private var listenSocket: Int32!
@@ -57,12 +63,15 @@
         return r
     }
 
-    init(port: UInt16) throws {
+    public private(set) var port: UInt16
+
+    init(port: UInt16?) throws {
         #if os(Linux)
             let SOCKSTREAM = Int32(SOCK_STREAM.rawValue)
         #else
             let SOCKSTREAM = SOCK_STREAM
         #endif
+        self.port = port ?? 0
         listenSocket = try attempt("socket", valid: isNotNegative, socket(AF_INET, SOCKSTREAM, Int32(IPPROTO_TCP)))
         var on: Int = 1
         _ = try attempt("setsockopt", valid: isZero, setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &on, socklen_t(MemoryLayout<Int>.size)))
@@ -72,16 +81,26 @@
             let addr = UnsafePointer<sockaddr>($0)
             _ = try attempt("bind", valid: isZero, bind(listenSocket, addr, socklen_t(MemoryLayout<sockaddr>.size)))
         })
+
+        var actualSA = sockaddr_in()
+        withUnsafeMutablePointer(to: &actualSA) { ptr in
+            ptr.withMemoryRebound(to: sockaddr.self, capacity: 1) { (ptr: UnsafeMutablePointer<sockaddr>) in
+                var len = socklen_t(MemoryLayout<sockaddr>.size)
+                getsockname(listenSocket, ptr, &len)
+            }
+        }
+
+        self.port = UInt16(networkByteOrder: actualSA.sin_port)
     }
 
-    private func createSockaddr(_ port: UInt16) -> sockaddr_in {
+    private func createSockaddr(_ port: UInt16?) -> sockaddr_in {
         // Listen on the loopback address so that OSX doesnt pop up a dialog
         // asking to accept incoming connections if the firewall is enabled.
         let addr = UInt32(INADDR_LOOPBACK).bigEndian
         #if os(Linux)
-            return sockaddr_in(sin_family: sa_family_t(AF_INET), sin_port: htons(port), sin_addr: in_addr(s_addr: addr), sin_zero: (0,0,0,0,0,0,0,0))
+            return sockaddr_in(sin_family: sa_family_t(AF_INET), sin_port: htons(port ?? 0), sin_addr: in_addr(s_addr: addr), sin_zero: (0,0,0,0,0,0,0,0))
         #else
-            return sockaddr_in(sin_len: 0, sin_family: sa_family_t(AF_INET), sin_port: CFSwapInt16HostToBig(port), sin_addr: in_addr(s_addr: addr), sin_zero: (0,0,0,0,0,0,0,0))
+            return sockaddr_in(sin_len: 0, sin_family: sa_family_t(AF_INET), sin_port: CFSwapInt16HostToBig(port ?? 0), sin_addr: in_addr(s_addr: addr), sin_zero: (0,0,0,0,0,0,0,0))
         #endif
     }
 
@@ -135,20 +154,27 @@
     }
 
     func shutdown() {
-        close(connectionSocket)
+        if let connectionSocket = self.connectionSocket {
+            close(connectionSocket)
+        }
         close(listenSocket)
     }
 }
 
 class _HTTPServer {
 
-    let socket: _TCPSocket 
+    let socket: _TCPSocket
+    var port: UInt16 {
+        get {
+            return self.socket.port
+        }
+    }
     
-    init(port: UInt16) throws {
+    init(port: UInt16?) throws {
         socket = try _TCPSocket(port: port)
     }
 
-    public class func create(port: UInt16) throws -> _HTTPServer {
+    public class func create(port: UInt16?) throws -> _HTTPServer {
         return try _HTTPServer(port: port)
     }
 
@@ -161,7 +187,7 @@
     }
    
     public func request() throws -> _HTTPRequest {
-       return _HTTPRequest(request: try socket.readData()) 
+       return try _HTTPRequest(request: socket.readData())
     }
 
     public func respond(with response: _HTTPResponse, startDelay: TimeInterval? = nil, sendDelay: TimeInterval? = nil, bodyChunks: Int? = nil) throws {
@@ -309,8 +335,13 @@
     let startDelay: TimeInterval?
     let sendDelay: TimeInterval?
     let bodyChunks: Int?
+    var port: UInt16 {
+        get {
+            return self.httpServer.port
+        }
+    }
     
-    public init (port: UInt16, startDelay: TimeInterval? = nil, sendDelay: TimeInterval? = nil, bodyChunks: Int? = nil) 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
@@ -406,23 +437,28 @@
 }
 
 class LoopbackServerTest : XCTestCase {
-    static var serverPort: Int = -1
+    private static let staticSyncQ = DispatchQueue(label: "org.swift.TestFoundation.HTTPServer.StaticSyncQ")
+
+    private static var _serverPort: Int = -1
+    static var serverPort: Int {
+        get {
+            return staticSyncQ.sync { _serverPort }
+        }
+        set {
+            staticSyncQ.sync { _serverPort = newValue }
+        }
+    }
 
     override class func setUp() {
         super.setUp()
         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), 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 }
-                    throw e
-                }
+            while true {
+                let test = try TestURLSessionServer(port: nil, startDelay: startDelay, sendDelay: sendDelay, bodyChunks: bodyChunks)
+                serverPort = Int(test.port)
+                try test.start(started: condition)
+                try test.readAndRespond()
+                serverPort = -2
+                test.stop()
             }
         }
 
diff --git a/TestFoundation/TestJSONEncoder.swift b/TestFoundation/TestJSONEncoder.swift
index 6444296..842eb52 100644
--- a/TestFoundation/TestJSONEncoder.swift
+++ b/TestFoundation/TestJSONEncoder.swift
@@ -405,23 +405,13 @@
     // UInt and Int
     func test_codingOfUIntMinMax() {
 
-        let encoder = JSONEncoder()
-
         struct MyValue: Codable {
-            let intMin:Int = Int.min
-            let intMax:Int = Int.max
-            let uintMin:UInt = UInt.min
-            let uintMax:UInt = UInt.max
+            let int64Min = Int64.min
+            let int64Max = Int64.max
+            let uint64Min = UInt64.min
+            let uint64Max = UInt64.max
         }
 
-        let myValue = MyValue()
-        let myDictI: [String:Any] = ["intMin": myValue.intMin, "intMax": myValue.intMax]
-        let myDictU: [String:Any] = ["uintMin": myValue.uintMin, "uintMax": myValue.uintMax]
-        let myDict1: [String:Any] = ["intMin": myValue.intMin]
-        let myDict2: [String:Any] = ["intMax": myValue.intMax]
-        let myDict3: [String:Any] = ["uintMin": myValue.uintMin]
-        let myDict4: [String:Any] = ["uintMax": myValue.uintMax]
-
         func compareJSON(_ s1: String, _ s2: String) {
             let ss1 = s1.trimmingCharacters(in: CharacterSet(charactersIn: "{}")).split(separator: Character(",")).sorted()
             let ss2 = s2.trimmingCharacters(in: CharacterSet(charactersIn: "{}")).split(separator: Character(",")).sorted()
@@ -429,40 +419,16 @@
         }
 
         do {
+            let encoder = JSONEncoder()
+            let myValue = MyValue()
             let result = try encoder.encode(myValue)
             let r = String(data: result, encoding: .utf8) ?? "nil"
-            compareJSON(r, "{\"uintMin\":0,\"uintMax\":18446744073709551615,\"intMin\":-9223372036854775808,\"intMax\":9223372036854775807}")
-
-            let resultI = try JSONSerialization.data(withJSONObject: myDictI)
-            let rI = String(data: resultI, encoding: .utf8) ?? "nil"
-            compareJSON(rI, "{\"intMin\":-9223372036854775808,\"intMax\":9223372036854775807}")
-
-            let resultU = try JSONSerialization.data(withJSONObject: myDictU)
-            let rU = String(data: resultU, encoding: .utf8) ?? "nil"
-            compareJSON(rU, "{\"uintMax\":18446744073709551615,\"uintMin\":0}")
-
-            let result1 = try JSONSerialization.data(withJSONObject: myDict1)
-            let r1 = String(data: result1, encoding: .utf8) ?? "nil"
-            XCTAssertEqual(r1, "{\"intMin\":-9223372036854775808}")
-
-            let result2 = try JSONSerialization.data(withJSONObject: myDict2)
-            let r2 = String(data: result2, encoding: .utf8) ?? "nil"
-            XCTAssertEqual(r2, "{\"intMax\":9223372036854775807}")
-
-            let result3 = try JSONSerialization.data(withJSONObject: myDict3)
-            let r3 = String(data: result3, encoding: .utf8) ?? "nil"
-            XCTAssertEqual(r3, "{\"uintMin\":0}")
-
-            let result4 = try JSONSerialization.data(withJSONObject: myDict4)
-            let r4 = String(data: result4, encoding: .utf8) ?? "nil"
-            XCTAssertEqual(r4, "{\"uintMax\":18446744073709551615}")
+            compareJSON(r, "{\"uint64Min\":0,\"uint64Max\":18446744073709551615,\"int64Min\":-9223372036854775808,\"int64Max\":9223372036854775807}")
         } catch {
             XCTFail(String(describing: error))
         }
     }
 
-
-
     // MARK: - Helper Functions
     private var _jsonEmptyDictionary: Data {
         return "{}".data(using: .utf8)!
diff --git a/TestFoundation/TestJSONSerialization.swift b/TestFoundation/TestJSONSerialization.swift
index 61e23c1..a07eba4 100644
--- a/TestFoundation/TestJSONSerialization.swift
+++ b/TestFoundation/TestJSONSerialization.swift
@@ -829,6 +829,7 @@
         return [
             ("test_isValidJSONObjectTrue", test_isValidJSONObjectTrue),
             ("test_isValidJSONObjectFalse", test_isValidJSONObjectFalse),
+            ("test_validNumericJSONObjects", test_validNumericJSONObjects)
         ]
     }
 
@@ -924,6 +925,36 @@
         }
     }
 
+    func test_validNumericJSONObjects() {
+        // All of the numeric types supported by JSONSerialization
+        XCTAssertTrue(JSONSerialization.isValidJSONObject([nil, NSNull()]))
+        XCTAssertTrue(JSONSerialization.isValidJSONObject([true, false]))
+        XCTAssertTrue(JSONSerialization.isValidJSONObject([Int.min, Int8.min, Int16.min, Int32.min, Int64.min]))
+        XCTAssertTrue(JSONSerialization.isValidJSONObject([UInt.min, UInt8.min, UInt16.min, UInt32.min, UInt64.min]))
+        XCTAssertTrue(JSONSerialization.isValidJSONObject([Float.leastNonzeroMagnitude, Double.leastNonzeroMagnitude]))
+
+        XCTAssertTrue(JSONSerialization.isValidJSONObject([NSNumber(value: true), NSNumber(value: Float.greatestFiniteMagnitude), NSNumber(value: Double.greatestFiniteMagnitude)]))
+        XCTAssertTrue(JSONSerialization.isValidJSONObject([NSNumber(value: Int.max), NSNumber(value: Int8.max), NSNumber(value: Int16.max), NSNumber(value: Int32.max), NSNumber(value: Int64.max)]))
+        XCTAssertTrue(JSONSerialization.isValidJSONObject([NSNumber(value: UInt.max), NSNumber(value: UInt8.max), NSNumber(value: UInt16.max), NSNumber(value: UInt32.max), NSNumber(value: UInt64.max)]))
+        XCTAssertTrue(JSONSerialization.isValidJSONObject([NSDecimalNumber(booleanLiteral: true), NSDecimalNumber(decimal: Decimal.greatestFiniteMagnitude), NSDecimalNumber(floatLiteral: Double.greatestFiniteMagnitude), NSDecimalNumber(integerLiteral: Int.min)]))
+        XCTAssertTrue(JSONSerialization.isValidJSONObject([Decimal(123), Decimal(Double.leastNonzeroMagnitude)]))
+
+        XCTAssertFalse(JSONSerialization.isValidJSONObject(Float.nan))
+        XCTAssertFalse(JSONSerialization.isValidJSONObject(Float.infinity))
+        XCTAssertFalse(JSONSerialization.isValidJSONObject(-Float.infinity))
+        XCTAssertFalse(JSONSerialization.isValidJSONObject(NSNumber(value: Float.nan)))
+        XCTAssertFalse(JSONSerialization.isValidJSONObject(NSNumber(value: Float.infinity)))
+        XCTAssertFalse(JSONSerialization.isValidJSONObject(NSNumber(value: -Float.infinity)))
+
+        XCTAssertFalse(JSONSerialization.isValidJSONObject(Double.nan))
+        XCTAssertFalse(JSONSerialization.isValidJSONObject(Double.infinity))
+        XCTAssertFalse(JSONSerialization.isValidJSONObject(-Double.infinity))
+        XCTAssertFalse(JSONSerialization.isValidJSONObject(NSNumber(value: Double.nan)))
+        XCTAssertFalse(JSONSerialization.isValidJSONObject(NSNumber(value: Double.infinity)))
+        XCTAssertFalse(JSONSerialization.isValidJSONObject(NSNumber(value: -Double.infinity)))
+
+        XCTAssertFalse(JSONSerialization.isValidJSONObject(NSDecimalNumber(decimal: Decimal(floatLiteral: Double.nan))))
+    }
 }
 
 // MARK: - serializationTests
@@ -941,6 +972,14 @@
             ("test_serialize_IntMin", test_serialize_IntMin),
             ("test_serialize_UIntMax", test_serialize_UIntMax),
             ("test_serialize_UIntMin", test_serialize_UIntMin),
+            ("test_serialize_8BitSizes", test_serialize_8BitSizes),
+            ("test_serialize_16BitSizes", test_serialize_16BitSizes),
+            ("test_serialize_32BitSizes", test_serialize_32BitSizes),
+            ("test_serialize_64BitSizes", test_serialize_64BitSizes),
+            ("test_serialize_Float", test_serialize_Float),
+            ("test_serialize_Double", test_serialize_Double),
+            ("test_serialize_Decimal", test_serialize_Decimal),
+            ("test_serialize_NSDecimalNumber", test_serialize_NSDecimalNumber),
             ("test_serialize_stringEscaping", test_serialize_stringEscaping),
             ("test_jsonReadingOffTheEndOfBuffers", test_jsonReadingOffTheEndOfBuffers),
             ("test_jsonObjectToOutputStreamBuffer", test_jsonObjectToOutputStreamBuffer),
@@ -1172,7 +1211,80 @@
         let json: [Any] = [UInt.min]
         XCTAssertEqual(try trySerialize(json), "[\(UInt.min)]")
     }
-    
+
+    func test_serialize_8BitSizes() {
+        let json1 = [Int8.min, Int8(-1), Int8(0), Int8(1), Int8.max]
+        XCTAssertEqual(try trySerialize(json1), "[-128,-1,0,1,127]")
+        let json2 = [UInt8.min, UInt8(0), UInt8(1), UInt8.max]
+        XCTAssertEqual(try trySerialize(json2), "[0,0,1,255]")
+    }
+
+    func test_serialize_16BitSizes() {
+        let json1 = [Int16.min, Int16(-1), Int16(0), Int16(1), Int16.max]
+        XCTAssertEqual(try trySerialize(json1), "[-32768,-1,0,1,32767]")
+        let json2 = [UInt16.min, UInt16(0), UInt16(1), UInt16.max]
+        XCTAssertEqual(try trySerialize(json2), "[0,0,1,65535]")
+    }
+
+    func test_serialize_32BitSizes() {
+        let json1 = [Int32.min, Int32(-1), Int32(0), Int32(1), Int32.max]
+        XCTAssertEqual(try trySerialize(json1), "[-2147483648,-1,0,1,2147483647]")
+        let json2 = [UInt32.min, UInt32(0), UInt32(1), UInt32.max]
+        XCTAssertEqual(try trySerialize(json2), "[0,0,1,4294967295]")
+    }
+
+    func test_serialize_64BitSizes() {
+        let json1 = [Int64.min, Int64(-1), Int64(0), Int64(1), Int64.max]
+        XCTAssertEqual(try trySerialize(json1), "[-9223372036854775808,-1,0,1,9223372036854775807]")
+        let json2 = [UInt64.min, UInt64(0), UInt64(1), UInt64.max]
+        XCTAssertEqual(try trySerialize(json2), "[0,0,1,18446744073709551615]")
+    }
+
+    func test_serialize_Float() {
+        XCTAssertEqual(try trySerialize([-Float.leastNonzeroMagnitude, Float.leastNonzeroMagnitude]), "[-0,0]")
+        XCTAssertEqual(try trySerialize([-Float.greatestFiniteMagnitude]), "[-340282346638529000000000000000000000000]")
+        XCTAssertEqual(try trySerialize([Float.greatestFiniteMagnitude]), "[340282346638529000000000000000000000000]")
+        XCTAssertEqual(try trySerialize([Float(-1), Float.leastNonzeroMagnitude, Float(1)]), "[-1,0,1]")
+    }
+
+    func test_serialize_Double() {
+        XCTAssertEqual(try trySerialize([-Double.leastNonzeroMagnitude, Double.leastNonzeroMagnitude]), "[-0,0]")
+        XCTAssertEqual(try trySerialize([-Double.leastNormalMagnitude, Double.leastNormalMagnitude]), "[-0,0]")
+        XCTAssertEqual(try trySerialize([-Double.greatestFiniteMagnitude]), "[-179769313486232000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000]")
+        XCTAssertEqual(try trySerialize([Double.greatestFiniteMagnitude]), "[179769313486232000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000]")
+        XCTAssertEqual(try trySerialize([Double(-1.0),  Double(1.0)]), "[-1,1]")
+    }
+
+    func test_serialize_Decimal() {
+        XCTAssertEqual(try trySerialize([-Decimal.leastFiniteMagnitude]), "[3402823669209384634633746074317682114550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000]")
+        XCTAssertEqual(try trySerialize([Decimal.leastFiniteMagnitude]), "[-3402823669209384634633746074317682114550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000]")
+        XCTAssertEqual(try trySerialize([-Decimal.leastNonzeroMagnitude]), "[-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001]")
+        XCTAssertEqual(try trySerialize([Decimal.leastNonzeroMagnitude]), "[0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001]")
+        XCTAssertEqual(try trySerialize([-Decimal.greatestFiniteMagnitude]), "[-3402823669209384634633746074317682114550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000]")
+        XCTAssertEqual(try trySerialize([Decimal.greatestFiniteMagnitude]), "[3402823669209384634633746074317682114550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000]")
+        XCTAssertEqual(try trySerialize([Decimal(Int8.min), Decimal(Int8(0)), Decimal(Int8.max)]), "[-128,0,127]")
+        XCTAssertEqual(try trySerialize([Decimal(string: "-0.0"), Decimal(string: "0.000"), Decimal(string: "1.0000")]), "[0,0,1]")
+    }
+
+    func test_serialize_NSDecimalNumber() {
+        let dn0: [Any] = [NSDecimalNumber(floatLiteral: -Double.leastNonzeroMagnitude)]
+        let dn1: [Any] = [NSDecimalNumber(floatLiteral: Double.leastNonzeroMagnitude)]
+        let dn2: [Any] = [NSDecimalNumber(floatLiteral: -Double.leastNormalMagnitude)]
+        let dn3: [Any] = [NSDecimalNumber(floatLiteral: Double.leastNormalMagnitude)]
+        let dn4: [Any] = [NSDecimalNumber(floatLiteral: -Double.greatestFiniteMagnitude)]
+        let dn5: [Any] = [NSDecimalNumber(floatLiteral: Double.greatestFiniteMagnitude)]
+
+        XCTAssertEqual(try trySerialize(dn0), "[-0.00000000000000000000000000000000000000000000000000000000000000000004940656458412464128]")
+        XCTAssertEqual(try trySerialize(dn1), "[0.00000000000000000000000000000000000000000000000000000000000000000004940656458412464128]")
+        XCTAssertEqual(try trySerialize(dn2), "[-0.0000000000000000000000000000000000000000000000000002225073858507201792]")
+        XCTAssertEqual(try trySerialize(dn3), "[0.0000000000000000000000000000000000000000000000000002225073858507201792]")
+        XCTAssertEqual(try trySerialize(dn4), "[-17976931348623167488000000000000000000000000000000000]")
+        XCTAssertEqual(try trySerialize(dn5), "[17976931348623167488000000000000000000000000000000000]")
+        XCTAssertEqual(try trySerialize([NSDecimalNumber(string: "0.0001"), NSDecimalNumber(string: "0.00"), NSDecimalNumber(string: "-0.0")]), "[0.0001,0,0]")
+        XCTAssertEqual(try trySerialize([NSDecimalNumber(integerLiteral: Int(Int16.min)), NSDecimalNumber(integerLiteral: 0), NSDecimalNumber(integerLiteral: Int(Int16.max))]), "[-32768,0,32767]")
+        XCTAssertEqual(try trySerialize([NSDecimalNumber(booleanLiteral: true), NSDecimalNumber(booleanLiteral: false)]), "[1,0]")
+    }
+
     func test_serialize_stringEscaping() {
         var json = ["foo"]
         XCTAssertEqual(try trySerialize(json), "[\"foo\"]")
diff --git a/TestFoundation/TestNSNumber.swift b/TestFoundation/TestNSNumber.swift
index 9d7fe2b..0e3ac08 100644
--- a/TestFoundation/TestNSNumber.swift
+++ b/TestFoundation/TestNSNumber.swift
@@ -44,6 +44,7 @@
             ("test_descriptionWithLocale", test_descriptionWithLocale ),
             ("test_objCType", test_objCType ),
             ("test_stringValue", test_stringValue),
+            ("test_Equals", test_Equals),
         ]
     }
     
@@ -1087,4 +1088,50 @@
         XCTAssertEqual(NSNumber(value: Int64.max).stringValue, "9223372036854775807")
         XCTAssertEqual(NSNumber(value: Int64.max - 1).stringValue, "9223372036854775806")
     }
+
+    func test_Equals() {
+        // Booleans: false only equals 0, true only equals 1
+        XCTAssertTrue(NSNumber(value: true) == NSNumber(value: true))
+        XCTAssertTrue(NSNumber(value: true) == NSNumber(value: 1))
+        XCTAssertTrue(NSNumber(value: true) == NSNumber(value: Float(1)))
+        XCTAssertTrue(NSNumber(value: true) == NSNumber(value: Double(1)))
+        XCTAssertTrue(NSNumber(value: true) == NSNumber(value: Int8(1)))
+        XCTAssertTrue(NSNumber(value: true) != NSNumber(value: false))
+        XCTAssertTrue(NSNumber(value: true) != NSNumber(value: Int8(-1)))
+        XCTAssertTrue(NSNumber(value: true) != NSNumber(value: Float(1.01)))
+        XCTAssertTrue(NSNumber(value: true) != NSNumber(value: Double(1234.56)))
+        XCTAssertTrue(NSNumber(value: true) != NSNumber(value: 2))
+        XCTAssertTrue(NSNumber(value: true) != NSNumber(value: Int.max))
+        XCTAssertTrue(NSNumber(value: false) == NSNumber(value: false))
+        XCTAssertTrue(NSNumber(value: false) == NSNumber(value: 0))
+        XCTAssertTrue(NSNumber(value: false) == NSNumber(value: Float(0)))
+        XCTAssertTrue(NSNumber(value: false) == NSNumber(value: Double(0)))
+        XCTAssertTrue(NSNumber(value: false) == NSNumber(value: Int8(0)))
+        XCTAssertTrue(NSNumber(value: false) == NSNumber(value: UInt64(0)))
+        XCTAssertTrue(NSNumber(value: false) != NSNumber(value: 1))
+        XCTAssertTrue(NSNumber(value: false) != NSNumber(value: 2))
+        XCTAssertTrue(NSNumber(value: false) != NSNumber(value: Int.max))
+
+        XCTAssertTrue(NSNumber(value: Int8(-1)) == NSNumber(value: Int16(-1)))
+        XCTAssertTrue(NSNumber(value: Int16(-1)) == NSNumber(value: Int32(-1)))
+        XCTAssertTrue(NSNumber(value: Int32(-1)) == NSNumber(value: Int64(-1)))
+        XCTAssertTrue(NSNumber(value: Int8.max) != NSNumber(value: Int16.max))
+        XCTAssertTrue(NSNumber(value: Int16.max) != NSNumber(value: Int32.max))
+        XCTAssertTrue(NSNumber(value: Int32.max) != NSNumber(value: Int64.max))
+        XCTAssertTrue(NSNumber(value: UInt8.min) == NSNumber(value: UInt16.min))
+        XCTAssertTrue(NSNumber(value: UInt16.min) == NSNumber(value: UInt32.min))
+        XCTAssertTrue(NSNumber(value: UInt32.min) == NSNumber(value: UInt64.min))
+        XCTAssertTrue(NSNumber(value: UInt8.max) != NSNumber(value: UInt16.max))
+        XCTAssertTrue(NSNumber(value: UInt16.max) != NSNumber(value: UInt32.max))
+        XCTAssertTrue(NSNumber(value: UInt32.max) != NSNumber(value: UInt64.max))
+        XCTAssertTrue(NSNumber(value: Int8(0)) == NSNumber(value: UInt16(0)))
+        XCTAssertTrue(NSNumber(value: UInt16(0)) == NSNumber(value: Int32(0)))
+        XCTAssertTrue(NSNumber(value: Int32(0)) == NSNumber(value: UInt64(0)))
+        XCTAssertTrue(NSNumber(value: Int(0)) == NSNumber(value: UInt(0)))
+        XCTAssertTrue(NSNumber(value: Int8.min) == NSNumber(value: Float(-128)))
+        XCTAssertTrue(NSNumber(value: Int8.max) == NSNumber(value: Double(127)))
+        XCTAssertTrue(NSNumber(value: UInt16.min) == NSNumber(value: Float(0)))
+        XCTAssertTrue(NSNumber(value: UInt16.max) == NSNumber(value: Double(65535)))
+        XCTAssertTrue(NSNumber(value: 1.1) != NSNumber(value: Int64(1)))
+    }
 }
diff --git a/TestFoundation/TestURLSession.swift b/TestFoundation/TestURLSession.swift
index 68339fc..c941f1c 100644
--- a/TestFoundation/TestURLSession.swift
+++ b/TestFoundation/TestURLSession.swift
@@ -36,7 +36,7 @@
             ("test_verifyHttpAdditionalHeaders", test_verifyHttpAdditionalHeaders),
             ("test_timeoutInterval", test_timeoutInterval),
             ("test_httpRedirection", test_httpRedirection),
-            ("test_httpRedirectionTimeout", test_httpRedirectionTimeout),
+            //("test_httpRedirectionTimeout", test_httpRedirectionTimeout), /* temporarily disabled (https://bugs.swift.org/browse/SR-5751) */
             ("test_http0_9SimpleResponses", test_http0_9SimpleResponses),
             ("test_outOfRangeButCorrectlyFormattedHTTPCode", test_outOfRangeButCorrectlyFormattedHTTPCode),
             ("test_missingContentLengthButStillABody", test_missingContentLengthButStillABody),
@@ -313,6 +313,8 @@
         waitForExpectations(timeout: 12)
     }
 
+    /*
+     // temporarily disabled (https://bugs.swift.org/browse/SR-5751)
     func test_httpRedirectionTimeout() {
         let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/UnitedStates"
         var req = URLRequest(url: URL(string: urlString)!)
@@ -325,11 +327,14 @@
             if let e = error as? URLError {
                 XCTAssertEqual(e.code, .timedOut, "Unexpected error code")
                 return
+            } else {
+                XCTFail("test unexpectedly succeeded (response=\(response.debugDescription))")
             }
         }
         task.resume()
         waitForExpectations(timeout: 12)
     }
+    */
 
     func test_http0_9SimpleResponses() {
         for brokenCity in ["Pompeii", "Sodom"] {