Merge pull request #1303 from rudkx/fix-more-iuo-casts

Fix a couple more IUOs that were supposed to be banned by SE-0054.
diff --git a/CoreFoundation/Base.subproj/CFPlatform.c b/CoreFoundation/Base.subproj/CFPlatform.c
index 70597d1..5aefe20 100644
--- a/CoreFoundation/Base.subproj/CFPlatform.c
+++ b/CoreFoundation/Base.subproj/CFPlatform.c
@@ -1316,15 +1316,18 @@
     return thread;
 }
 
-CF_SWIFT_EXPORT void _CFThreadSetName(const char *_Nullable name) {
+CF_SWIFT_EXPORT int _CFThreadSetName(pthread_t thread, const char *_Nonnull name) {
 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
-    pthread_setname_np(name);
+    if (pthread_equal(pthread_self(), thread)) {
+        return pthread_setname_np(name);
+    }
+    return EINVAL;
 #elif DEPLOYMENT_TARGET_LINUX
-    pthread_setname_np(pthread_self(), name);
+    return pthread_setname_np(thread, name);
 #endif
 }
 
-CF_SWIFT_EXPORT int _CFThreadGetName(char *buf, int length) {
+CF_SWIFT_EXPORT int _CFThreadGetName(char *_Nonnull buf, int length) {
 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_EMBEDDED_MINI
     return pthread_getname_np(pthread_self(), buf, length);
 #elif DEPLOYMENT_TARGET_ANDROID
diff --git a/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h b/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h
index 2651cd8..57e2f12 100644
--- a/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h
+++ b/CoreFoundation/Base.subproj/ForSwiftFoundationOnly.h
@@ -316,8 +316,8 @@
 
 CF_EXPORT _CFThreadRef _CFThreadCreate(const _CFThreadAttributes attrs, void *_Nullable (* _Nonnull startfn)(void *_Nullable), void *restrict _Nullable context);
 
-CF_SWIFT_EXPORT void _CFThreadSetName(const char *_Nullable name);
-CF_SWIFT_EXPORT int _CFThreadGetName(char *buf, int length);
+CF_SWIFT_EXPORT int _CFThreadSetName(pthread_t thread, const char *_Nonnull name);
+CF_SWIFT_EXPORT int _CFThreadGetName(char *_Nonnull buf, int length);
 
 CF_EXPORT Boolean _CFCharacterSetIsLongCharacterMember(CFCharacterSetRef theSet, UTF32Char theChar);
 CF_EXPORT CFCharacterSetRef _CFCharacterSetCreateCopy(CFAllocatorRef alloc, CFCharacterSetRef theSet);
diff --git a/CoreFoundation/URL.subproj/CFURLComponents.c b/CoreFoundation/URL.subproj/CFURLComponents.c
index 5756ea8..86dd9f1 100644
--- a/CoreFoundation/URL.subproj/CFURLComponents.c
+++ b/CoreFoundation/URL.subproj/CFURLComponents.c
@@ -556,11 +556,11 @@
         components->_pathComponentValid = true;
     }
     if (!components->_pathComponent) {
-        result = CFSTR("");
+        result = CFStringCreateCopy(kCFAllocatorSystemDefault, CFSTR(""));
     } else {
         result = _CFStringCreateByRemovingPercentEncoding(kCFAllocatorSystemDefault, components->_pathComponent);
         if (!result) {
-            result = CFSTR("");
+            result = CFStringCreateCopy(kCFAllocatorSystemDefault, CFSTR(""));
         }
     }
     __CFUnlock(&components->_lock);
@@ -745,7 +745,7 @@
     result = components->_pathComponent ? CFRetain(components->_pathComponent) : NULL;
     __CFUnlock(&components->_lock);
     
-    if (!result) result = CFSTR("");
+    if (!result) result = CFStringCreateCopy(kCFAllocatorSystemDefault, CFSTR(""));
     
     return ( result );
 }
diff --git a/Foundation/NSKeyedArchiverHelpers.swift b/Foundation/NSKeyedArchiverHelpers.swift
index 6ecebcb..0bd8de6 100644
--- a/Foundation/NSKeyedArchiverHelpers.swift
+++ b/Foundation/NSKeyedArchiverHelpers.swift
@@ -29,7 +29,7 @@
     }
 
     open override var hash: Int {
-        return Int(bitPattern: CFHash(_cfObject as CFTypeRef!))
+        return Int(bitPattern: CFHash(_cfObject as CFTypeRef?))
     }
     
     open override func isEqual(_ object: Any?) -> Bool {
diff --git a/Foundation/Thread.swift b/Foundation/Thread.swift
index dae27cd..1489969 100644
--- a/Foundation/Thread.swift
+++ b/Foundation/Thread.swift
@@ -43,6 +43,9 @@
 private func NSThreadStart(_ context: UnsafeMutableRawPointer?) -> UnsafeMutableRawPointer? {
     let thread: Thread = NSObject.unretainedReference(context!)
     Thread._currentThread.set(thread)
+    if let name = thread.name {
+        _CFThreadSetName(pthread_self(), name)
+    }
     thread._status = .executing
     thread.main()
     thread._status = .finished
@@ -141,11 +144,12 @@
     }
 
     internal var _main: () -> Void = {}
-#if os(OSX) || os(iOS) || CYGWIN
-    private var _thread: pthread_t? = nil
-#elseif os(Linux) || os(Android)
+#if os(Android)
     private var _thread = pthread_t()
+#else
+    private var _thread: pthread_t? = nil
 #endif
+
 #if CYGWIN
     internal var _attr : pthread_attr_t? = nil
 #else
@@ -202,8 +206,8 @@
 
     open var name: String? {
         didSet {
-            if _thread == Thread.current._thread {
-                _CFThreadSetName(name)
+            if let thread = _thread {
+                _CFThreadSetName(thread, name ?? "" )
             }
         }
     }
diff --git a/Foundation/URLComponents.swift b/Foundation/URLComponents.swift
index 281865f..53f2384 100644
--- a/Foundation/URLComponents.swift
+++ b/Foundation/URLComponents.swift
@@ -107,8 +107,7 @@
     /// The getter for this property removes any percent encoding this component may have (if the component allows percent encoding). Setting this property assumes the subcomponent or component string is not percent encoded and will add percent encoding (if the component allows percent encoding).
     public var path: String {
         get {
-            guard let result = _handle.map({ $0.path }) else { return "" }
-            return result
+            return _handle.map { $0.path } ?? ""
         }
         set {
             _applyMutation { $0.path = newValue }
@@ -161,8 +160,7 @@
     /// The getter for this property retains any percent encoding this component may have. Setting this properties assumes the component string is already correctly percent encoded. Attempting to set an incorrectly percent encoded string will cause a `fatalError`. Although ';' is a legal path character, it is recommended that it be percent-encoded for best compatibility with `URL` (`String.addingPercentEncoding(withAllowedCharacters:)` will percent-encode any ';' characters if you pass `CharacterSet.urlPathAllowed`).
     public var percentEncodedPath: String {
         get {
-            guard let result = _handle.map({ $0.percentEncodedPath }) else { return "" }
-            return result
+            return _handle.map { $0.percentEncodedPath } ?? ""
         }
         set {
             _applyMutation { $0.percentEncodedPath = newValue }
@@ -456,3 +454,42 @@
         return result!
     }
 }
+
+extension URLComponents : Codable {
+    private enum CodingKeys : Int, CodingKey {
+        case scheme
+        case user
+        case password
+        case host
+        case port
+        case path
+        case query
+        case fragment
+    }
+
+    public init(from decoder: Decoder) throws {
+        self.init()
+
+        let container = try decoder.container(keyedBy: CodingKeys.self)
+        self.scheme = try container.decodeIfPresent(String.self, forKey: .scheme)
+        self.user = try container.decodeIfPresent(String.self, forKey: .user)
+        self.password = try container.decodeIfPresent(String.self, forKey: .password)
+        self.host = try container.decodeIfPresent(String.self, forKey: .host)
+        self.port = try container.decodeIfPresent(Int.self, forKey: .port)
+        self.path = try container.decode(String.self, forKey: .path)
+        self.query = try container.decodeIfPresent(String.self, forKey: .query)
+        self.fragment = try container.decodeIfPresent(String.self, forKey: .fragment)
+    }
+
+    public func encode(to encoder: Encoder) throws {
+        var container = encoder.container(keyedBy: CodingKeys.self)
+        try container.encodeIfPresent(self.scheme, forKey: .scheme)
+        try container.encodeIfPresent(self.user, forKey: .user)
+        try container.encodeIfPresent(self.password, forKey: .password)
+        try container.encodeIfPresent(self.host, forKey: .host)
+        try container.encodeIfPresent(self.port, forKey: .port)
+        try container.encode(self.path, forKey: .path)
+        try container.encodeIfPresent(self.query, forKey: .query)
+        try container.encodeIfPresent(self.fragment, forKey: .fragment)
+    }
+}
diff --git a/TestFoundation/TestCodable.swift b/TestFoundation/TestCodable.swift
index d616a95..63d8271 100644
--- a/TestFoundation/TestCodable.swift
+++ b/TestFoundation/TestCodable.swift
@@ -33,25 +33,17 @@
     return result
 }
 
-func expectRoundTripEquality<T : Codable>(of value: T, encode: (T) throws -> Data, decode: (Data) throws -> T) where T : Equatable {
-    let data: Data
+func expectRoundTripEquality<T : Codable>(of value: T, encode: (T) throws -> Data, decode: (Data) throws -> T) throws where T : Equatable  {
     do {
-        data = try encode(value)
-    } catch {
-        fatalError("Unable to encode \(T.self) <\(value)>: \(error)")
+        let data = try encode(value)
+        let decoded: T = try decode(data)
+        if value != decoded {
+            throw NSError(domain: "Decode mismatch", code: 0, userInfo: ["msg": "Decoded \(T.self) <\(decoded)> not equal to original <\(value)>"])
+        }
     }
-
-    let decoded: T
-    do {
-        decoded = try decode(data)
-    } catch {
-        fatalError("Unable to decode \(T.self) <\(value)>: \(error)")
-    }
-
-    XCTAssertEqual(value, decoded, "Decoded \(T.self) <\(decoded)> not equal to original <\(value)>")
 }
 
-func expectRoundTripEqualityThroughJSON<T : Codable>(for value: T) where T : Equatable {
+func expectRoundTripEqualityThroughJSON<T : Codable>(for value: T) throws where T : Equatable {
     let inf = "INF", negInf = "-INF", nan = "NaN"
     let encode = { (_ value: T) throws -> Data in
         let encoder = JSONEncoder()
@@ -69,7 +61,7 @@
         return try decoder.decode(T.self, from: data)
     }
 
-    expectRoundTripEquality(of: value, encode: encode, decode: decode)
+    try expectRoundTripEquality(of: value, encode: encode, decode: decode)
 }
 
 // MARK: - Helper Types
@@ -98,7 +90,11 @@
 
     func test_PersonNameComponents_JSON() {
         for components in personNameComponentsValues {
-            expectRoundTripEqualityThroughJSON(for: components)
+            do {
+                try expectRoundTripEqualityThroughJSON(for: components)
+            } catch let error {
+                XCTFail("\(error) for \(components)")
+            }
         }
     }
 
@@ -113,7 +109,11 @@
     func test_UUID_JSON() {
         for uuid in uuidValues {
             // We have to wrap the UUID since we cannot have a top-level string.
-            expectRoundTripEqualityThroughJSON(for: UUIDCodingWrapper(uuid))
+            do {
+                try expectRoundTripEqualityThroughJSON(for: UUIDCodingWrapper(uuid))
+            } catch let error {
+                XCTFail("\(error) for \(uuid)")
+            }
         }
     }
 
@@ -128,7 +128,11 @@
 
     func test_URL_JSON() {
         for url in urlValues {
-            expectRoundTripEqualityThroughJSON(for: url)
+            do {
+                try expectRoundTripEqualityThroughJSON(for: url)
+            } catch let error {
+                XCTFail("\(error) for \(url)")
+            }
         }
     }
 
@@ -141,7 +145,11 @@
 
     func test_NSRange_JSON() {
         for range in nsrangeValues {
-            expectRoundTripEqualityThroughJSON(for: range)
+            do {
+                try expectRoundTripEqualityThroughJSON(for: range)
+            } catch let error {
+                XCTFail("\(error) for \(range)")
+            }
         }
     }
 
@@ -159,7 +167,11 @@
 
     func test_Locale_JSON() {
         for locale in localeValues {
-            expectRoundTripEqualityThroughJSON(for: locale)
+            do {
+                try expectRoundTripEqualityThroughJSON(for: locale)
+            } catch let error {
+                XCTFail("\(error) for \(locale)")
+            }
         }
     }
 
@@ -172,7 +184,11 @@
 
     func test_IndexSet_JSON() {
         for indexSet in indexSetValues {
-            expectRoundTripEqualityThroughJSON(for: indexSet)
+            do {
+                try expectRoundTripEqualityThroughJSON(for: indexSet)
+            } catch let error {
+                XCTFail("\(error) for \(indexSet)")
+            }
         }
     }
 
@@ -186,7 +202,11 @@
 
     func test_IndexPath_JSON() {
         for indexPath in indexPathValues {
-            expectRoundTripEqualityThroughJSON(for: indexPath)
+            do {
+                try expectRoundTripEqualityThroughJSON(for: indexPath)
+            } catch let error {
+                XCTFail("\(error) for \(indexPath)")
+            }
         }
     }
 
@@ -210,7 +230,11 @@
 
     func test_AffineTransform_JSON() {
         for transform in affineTransformValues {
-            expectRoundTripEqualityThroughJSON(for: transform)
+            do {
+                try expectRoundTripEqualityThroughJSON(for: transform)
+            } catch let error {
+                XCTFail("\(error) for \(transform)")
+            }
         }
     }
 
@@ -226,7 +250,11 @@
 
     func test_Decimal_JSON() {
         for decimal in decimalValues {
-            expectRoundTripEqualityThroughJSON(for: decimal)
+            do {
+                try expectRoundTripEqualityThroughJSON(for: decimal)
+            } catch let error {
+                XCTFail("\(error) for \(decimal)")
+            }
         }
     }
     
@@ -242,7 +270,11 @@
     
     func test_CGPoint_JSON() {
         for point in cgpointValues {
-            expectRoundTripEqualityThroughJSON(for: point)
+            do {
+                try expectRoundTripEqualityThroughJSON(for: point)
+            } catch let error {
+                XCTFail("\(error) for \(point)")
+            }
         }
     }
     
@@ -258,7 +290,11 @@
     
     func test_CGSize_JSON() {
         for size in cgsizeValues {
-            expectRoundTripEqualityThroughJSON(for: size)
+            do {
+                try expectRoundTripEqualityThroughJSON(for: size)
+            } catch let error {
+                XCTFail("\(error) for \(size)")
+            }
         }
     }
     
@@ -275,7 +311,11 @@
     
     func test_CGRect_JSON() {
         for rect in cgrectValues {
-            expectRoundTripEqualityThroughJSON(for: rect)
+            do {
+                try expectRoundTripEqualityThroughJSON(for: rect)
+            } catch let error {
+                XCTFail("\(error) for \(rect)")
+            }
         }
     }
     
@@ -301,7 +341,11 @@
     
     func test_CharacterSet_JSON() {
         for characterSet in characterSetValues {
-            expectRoundTripEqualityThroughJSON(for: characterSet)
+            do {
+                try expectRoundTripEqualityThroughJSON(for: characterSet)
+            } catch let error {
+                XCTFail("\(error) for \(characterSet)")
+            }
         }
     }
 
@@ -330,7 +374,11 @@
 
     func test_TimeZone_JSON() {
         for timeZone in timeZoneValues {
-            expectRoundTripEqualityThroughJSON(for: timeZone)
+            do {
+                try expectRoundTripEqualityThroughJSON(for: timeZone)
+            } catch let error {
+                XCTFail("\(error) for \(timeZone)")
+            }
         }
     }
 
@@ -366,7 +414,11 @@
 
     func test_Calendar_JSON() {
         for calendar in calendarValues {
-            expectRoundTripEqualityThroughJSON(for: calendar)
+            do {
+                try expectRoundTripEqualityThroughJSON(for: calendar)
+            } catch let error {
+                XCTFail("\(error) for \(calendar)")
+            }
         }
     }
 
@@ -403,14 +455,119 @@
         #endif
 
         let components = calendar.dateComponents(dateComponents, from: Date(timeIntervalSince1970: 1501283776))
-        expectRoundTripEqualityThroughJSON(for: components)
+        do {
+            try expectRoundTripEqualityThroughJSON(for: components)
+        } catch let error {
+            XCTFail("\(error)")
+        }
     }
 
     // MARK: - Measurement
     func test_Measurement_JSON() {
-        expectRoundTripEqualityThroughJSON(for: Measurement(value: 42, unit: UnitAcceleration.metersPerSecondSquared))
-        expectRoundTripEqualityThroughJSON(for: Measurement(value: 42, unit: UnitMass.kilograms))
-        expectRoundTripEqualityThroughJSON(for: Measurement(value: 42, unit: UnitLength.miles))
+        do {
+            try expectRoundTripEqualityThroughJSON(for: Measurement(value: 42, unit: UnitAcceleration.metersPerSecondSquared))
+            try expectRoundTripEqualityThroughJSON(for: Measurement(value: 42, unit: UnitMass.kilograms))
+            try expectRoundTripEqualityThroughJSON(for: Measurement(value: 42, unit: UnitLength.miles))
+        } catch let error {
+            XCTFail("\(error)")
+        }
+    }
+
+    // MARK: - URLComponents
+    lazy var urlComponentsValues: [URLComponents] = [
+        URLComponents(),
+
+        URLComponents(string: "http://swift.org")!,
+        URLComponents(string: "http://swift.org:80")!,
+        URLComponents(string: "https://www.mywebsite.org/api/v42/something.php#param1=hi&param2=hello")!,
+        URLComponents(string: "ftp://johnny:apples@myftpserver.org:4242/some/path")!,
+
+        URLComponents(url: URL(string: "http://swift.org")!, resolvingAgainstBaseURL: false)!,
+        URLComponents(url: URL(string: "http://swift.org:80")!, resolvingAgainstBaseURL: false)!,
+        URLComponents(url: URL(string: "https://www.mywebsite.org/api/v42/something.php#param1=hi&param2=hello")!, resolvingAgainstBaseURL: false)!,
+        URLComponents(url: URL(string: "ftp://johnny:apples@myftpserver.org:4242/some/path")!, resolvingAgainstBaseURL: false)!,
+        URLComponents(url: URL(fileURLWithPath: NSTemporaryDirectory()), resolvingAgainstBaseURL: false)!,
+        URLComponents(url: URL(fileURLWithPath: "/"), resolvingAgainstBaseURL: false)!,
+        URLComponents(url: URL(string: "documentation", relativeTo: URL(string: "http://swift.org")!)!, resolvingAgainstBaseURL: false)!,
+
+        URLComponents(url: URL(string: "http://swift.org")!, resolvingAgainstBaseURL: true)!,
+        URLComponents(url: URL(string: "http://swift.org:80")!, resolvingAgainstBaseURL: true)!,
+        URLComponents(url: URL(string: "https://www.mywebsite.org/api/v42/something.php#param1=hi&param2=hello")!, resolvingAgainstBaseURL: true)!,
+        URLComponents(url: URL(string: "ftp://johnny:apples@myftpserver.org:4242/some/path")!, resolvingAgainstBaseURL: true)!,
+        URLComponents(url: URL(fileURLWithPath: NSTemporaryDirectory()), resolvingAgainstBaseURL: true)!,
+        URLComponents(url: URL(fileURLWithPath: "/"), resolvingAgainstBaseURL: true)!,
+        URLComponents(url: URL(string: "documentation", relativeTo: URL(string: "http://swift.org")!)!, resolvingAgainstBaseURL: true)!,
+
+        {
+            var components = URLComponents()
+            components.scheme = "https"
+            return components
+        }(),
+
+        {
+            var components = URLComponents()
+            components.user = "johnny"
+            return components
+        }(),
+
+        {
+            var components = URLComponents()
+            components.password = "apples"
+            return components
+        }(),
+
+        {
+            var components = URLComponents()
+            components.host = "0.0.0.0"
+            return components
+        }(),
+
+        {
+            var components = URLComponents()
+            components.port = 8080
+            return components
+        }(),
+
+        {
+            var components = URLComponents()
+            components.path = ".."
+            return components
+        }(),
+
+        {
+            var components = URLComponents()
+            components.query = "param1=hi&param2=there"
+            return components
+        }(),
+
+        {
+            var components = URLComponents()
+            components.fragment = "anchor"
+            return components
+        }(),
+
+        {
+            var components = URLComponents()
+            components.scheme = "ftp"
+            components.user = "johnny"
+            components.password = "apples"
+            components.host = "0.0.0.0"
+            components.port = 4242
+            components.path = "/some/file"
+            components.query = "utf8=✅"
+            components.fragment = "anchor"
+            return components
+        }()
+    ]
+
+    func test_URLComponents_JSON() {
+        for (components) in urlComponentsValues {
+            do {
+                try expectRoundTripEqualityThroughJSON(for: components)
+            } catch let error {
+                XCTFail("\(error)")
+            }
+        }
     }
 }
 
@@ -434,6 +591,7 @@
             ("test_Calendar_JSON", test_Calendar_JSON),
             ("test_DateComponents_JSON", test_DateComponents_JSON),
             ("test_Measurement_JSON", test_Measurement_JSON),
+            ("test_URLComponents_JSON", test_URLComponents_JSON),
         ]
     }
 }
diff --git a/TestFoundation/TestNSNumberBridging.swift b/TestFoundation/TestNSNumberBridging.swift
index 3edcbaf..118d3fa 100644
--- a/TestFoundation/TestNSNumberBridging.swift
+++ b/TestFoundation/TestNSNumberBridging.swift
@@ -242,13 +242,16 @@
                 XCTAssertEqual(Int(exactly: interestingValue), int)
                 let uint = UInt(exactly: number!)
                 XCTAssertEqual(UInt(exactly: interestingValue), uint)
+
                 let float = Float(exactly: number!)
                 let expectedFloat = Float(exactly: int32!)
-                // these are disabled because of https://bugs.swift.org/browse/SR-4634
-                if (int32! != Int32.min && int32! != Int32.max &&
-                    int32! != Int32.min + 1 && int32! != Int32.max - 1) {
+                if int32! != Int32.min + 1 && int32! < Int32.max - 1 {
                     testFloat(expectedFloat, float)
+                } else {
+                    XCTAssertNil(float)
+                    XCTAssertNil(expectedFloat)
                 }
+
                 let double = Double(exactly: number!)
                 let expectedDouble = Double(exactly: int32!)
                 testDouble(expectedDouble, double)
@@ -284,12 +287,16 @@
                 XCTAssertEqual(Int(exactly: interestingValue), int)
                 let uint = UInt(exactly: number!)
                 XCTAssertEqual(UInt(exactly: interestingValue), uint)
+
                 let float = Float(exactly: number!)
                 let expectedFloat = Float(exactly: uint32!)
-                // these are disabled because of https://bugs.swift.org/browse/SR-4634
-                if (uint32! != UInt32.max && uint32! != UInt32.max - 1) {
+                if uint32! < UInt32.max - 1 {
                     testFloat(expectedFloat, float)
+                } else {
+                    XCTAssertNil(float)
+                    XCTAssertNil(expectedFloat)
                 }
+
                 let double = Double(exactly: number!)
                 let expectedDouble = Double(exactly: uint32!)
                 testDouble(expectedDouble, double)
@@ -325,10 +332,17 @@
                 XCTAssertEqual(Int(exactly: interestingValue), int)
                 let uint = UInt(exactly: number!)
                 XCTAssertEqual(UInt(exactly: interestingValue), uint)
+
                 let float = Float(exactly: number!)
-                XCTAssertEqual(Float(interestingValue), float)
                 let double = Double(exactly: number!)
-                XCTAssertEqual(Double(interestingValue), double)
+                if int64! != Int64.min + 1 && int64! < Int64.max - 1 {
+                    // Note: Double/Float(exactly: Int64.min) != nil
+                    XCTAssertEqual(Float(interestingValue), float)
+                    XCTAssertEqual(Double(interestingValue), double)
+                } else {
+                    XCTAssertNil(float)
+                    XCTAssertNil(double)
+                }
             }
             let bridged = interestingValue._bridgeToObjectiveC()
             testNumber(bridged)
@@ -361,10 +375,16 @@
                 XCTAssertEqual(Int(exactly: interestingValue), int)
                 let uint = UInt(exactly: number!)
                 XCTAssertEqual(UInt(exactly: interestingValue), uint)
+
                 let float = Float(exactly: number!)
-                XCTAssertEqual(Float(interestingValue), float)
                 let double = Double(exactly: number!)
-                XCTAssertEqual(Double(interestingValue), double)
+                if uint64! < UInt64.max - 1 {
+                    XCTAssertEqual(Float(interestingValue), float)
+                    XCTAssertEqual(Double(interestingValue), double)
+                } else {
+                    XCTAssertNil(float)
+                    XCTAssertNil(double)
+                }
             }
             let bridged = interestingValue._bridgeToObjectiveC()
             testNumber(bridged)
@@ -397,10 +417,17 @@
                 XCTAssertEqual(Int(exactly: interestingValue), int)
                 let uint = UInt(exactly: number!)
                 XCTAssertEqual(UInt(exactly: interestingValue), uint)
+
                 let float = Float(exactly: number!)
-                XCTAssertEqual(Float(interestingValue), float)
                 let double = Double(exactly: number!)
-                XCTAssertEqual(Double(interestingValue), double)
+                if int! != Int.min + 1 && int! < Int.max - 1 {
+                    // Double/Float(exactly: Int.min) != nil
+                    XCTAssertEqual(Float(interestingValue), float)
+                    XCTAssertEqual(Double(interestingValue), double)
+                } else {
+                    XCTAssertNil(float)
+                    XCTAssertNil(double)
+                }
             }
             let bridged = interestingValue._bridgeToObjectiveC()
             testNumber(bridged)
@@ -433,10 +460,16 @@
                 XCTAssertEqual(Int(exactly: interestingValue), int)
                 let uint = UInt(exactly: number!)
                 XCTAssertEqual(UInt(exactly: interestingValue), uint)
+
                 let float = Float(exactly: number!)
-                XCTAssertEqual(Float(interestingValue), float)
                 let double = Double(exactly: number!)
-                XCTAssertEqual(Double(interestingValue), double)
+                if uint! < UInt.max - 1 {
+                    XCTAssertEqual(Float(interestingValue), float)
+                    XCTAssertEqual(Double(interestingValue), double)
+                } else {
+                    XCTAssertNil(float)
+                    XCTAssertNil(double)
+                }
             }
             let bridged = interestingValue._bridgeToObjectiveC()
             testNumber(bridged)
@@ -474,9 +507,12 @@
                 let expectedFloat = interestingValue
                 testFloat(expectedFloat, float)
 
-                let double = Double(truncating: number!)
-                let expectedDouble = Double(reasonably: interestingValue)
-                testDouble(expectedDouble, double)
+                // FIXME: Double.nan doesn't round-trip through NSNumber
+                if !interestingValue.isNaN {
+                  let double = Double(exactly: number!)
+                  let expectedDouble = Double(exactly: interestingValue)
+                  testDouble(expectedDouble, double)
+                }
             }
             let bridged = interestingValue._bridgeToObjectiveC()
             testNumber(bridged)
@@ -514,9 +550,12 @@
                 let expectedFloat = Float(reasonably: interestingValue)
                 testFloat(expectedFloat, float)
 
-                let double = Double(exactly: number!)
-                let expectedDouble = interestingValue
-                testDouble(expectedDouble, double)
+                // FIXME: Double.nan doesn't round-trip through NSNumber
+                if !interestingValue.isNaN {
+                  let double = Double(exactly: number!)
+                  let expectedDouble = Double(exactly: interestingValue)
+                  testDouble(expectedDouble, double)
+                }
             }
             let bridged = interestingValue._bridgeToObjectiveC()
             testNumber(bridged)
diff --git a/TestFoundation/TestThread.swift b/TestFoundation/TestThread.swift
index f5b224b..6f09c8d 100644
--- a/TestFoundation/TestThread.swift
+++ b/TestFoundation/TestThread.swift
@@ -59,34 +59,70 @@
     }
     
     func test_threadName() {
-        let thread = Thread()
-        XCTAssertNil(thread.name)
 
-        func getPThreadName() -> String? {
-            var buf = [Int8](repeating: 0, count: 16)
+        // Compare the name set in pthreads()
+        func compareThreadName(to name: String) {
+            var buf = [Int8](repeating: 0, count: 128)
+#if os(OSX) || os(iOS)
+            // Dont use _CF functions on macOS as it will break testing with Darwin's native Foundation.
+            let r = pthread_getname_np(pthread_self(), &buf, buf.count)
+#else
             let r = _CFThreadGetName(&buf, Int32(buf.count))
-
-            guard r == 0 else {
-                return nil
+#endif
+            if r == 0 {
+                XCTAssertEqual(String(cString: buf), name)
+            } else {
+                XCTFail("Cant get thread name")
             }
-            return String(cString: buf)
         }
 
+        // No name is set initially
+        XCTAssertNil(Thread.current.name)
+
+#if os(Linux) // Linux sets the initial thread name to the process name.
+        compareThreadName(to: "TestFoundation")
+#else
+        compareThreadName(to: "")
+#endif
+        Thread.current.name = "mainThread"
+        XCTAssertEqual(Thread.mainThread.name, "mainThread")
+
+        let condition = NSCondition()
+        condition.lock()
+
         let thread2 = Thread() {
-            Thread.current.name = "Thread2"
-            XCTAssertEqual(Thread.current.name, "Thread2")
-            XCTAssertEqual(Thread.current.name, getPThreadName())
-        }
+            XCTAssertEqual(Thread.current.name, "Thread2-1")
+            compareThreadName(to: "Thread2-1")
 
+            Thread.current.name = "Thread2-2"
+            XCTAssertEqual(Thread.current.name, "Thread2-2")
+            compareThreadName(to: "Thread2-2")
+
+            Thread.current.name = "12345678901234567890"
+            XCTAssertEqual(Thread.current.name, "12345678901234567890")
+#if os(OSX) || os(iOS)
+            compareThreadName(to: "12345678901234567890")
+#elseif os(Linux)
+            // pthread_setname_np() only allows 15 characters on Linux, so setting it fails
+            // and the previous name will still be there.
+            compareThreadName(to: "Thread2-2")
+#endif
+            condition.lock()
+            condition.signal()
+            condition.unlock()
+        }
+        thread2.name = "Thread2-1"
         thread2.start()
 
-        Thread.current.name = "CurrentThread"
-        XCTAssertEqual(Thread.current.name, getPThreadName())
+        // Allow 1 second for thread2 to finish
+        XCTAssertTrue(condition.wait(until: Date(timeIntervalSinceNow: 1)))
+        condition.unlock()
 
+        XCTAssertEqual(Thread.current.name, "mainThread")
+        XCTAssertEqual(Thread.mainThread.name, "mainThread")
         let thread3 = Thread()
         thread3.name = "Thread3"
         XCTAssertEqual(thread3.name, "Thread3")
-        XCTAssertNotEqual(thread3.name, getPThreadName())
     }
 
     func test_mainThread() {
diff --git a/TestFoundation/TestURL.swift b/TestFoundation/TestURL.swift
index 0a9b652..f84f06c 100644
--- a/TestFoundation/TestURL.swift
+++ b/TestFoundation/TestURL.swift
@@ -523,7 +523,9 @@
             ("test_port", test_portSetter),
             ("test_url", test_url),
             ("test_copy", test_copy),
-            ("test_createURLWithComponents", test_createURLWithComponents)
+            ("test_createURLWithComponents", test_createURLWithComponents),
+            ("test_path", test_path),
+            ("test_percentEncodedPath", test_percentEncodedPath),
         ]
     }
     
@@ -617,4 +619,43 @@
         XCTAssertEqual(urlComponents.queryItems?.count, 4)
     }
 
+    func test_path() {
+        let c1 = URLComponents()
+        XCTAssertEqual(c1.path, "")
+
+        let c2 = URLComponents(string: "http://swift.org")
+        XCTAssertEqual(c2?.path, "")
+
+        let c3 = URLComponents(string: "http://swift.org/")
+        XCTAssertEqual(c3?.path, "/")
+
+        let c4 = URLComponents(string: "http://swift.org/foo/bar")
+        XCTAssertEqual(c4?.path, "/foo/bar")
+
+        let c5 = URLComponents(string: "http://swift.org:80/foo/bar")
+        XCTAssertEqual(c5?.path, "/foo/bar")
+
+        let c6 = URLComponents(string: "http://swift.org:80/foo/b%20r")
+        XCTAssertEqual(c6?.path, "/foo/b r")
+    }
+
+    func test_percentEncodedPath() {
+        let c1 = URLComponents()
+        XCTAssertEqual(c1.percentEncodedPath, "")
+
+        let c2 = URLComponents(string: "http://swift.org")
+        XCTAssertEqual(c2?.percentEncodedPath, "")
+
+        let c3 = URLComponents(string: "http://swift.org/")
+        XCTAssertEqual(c3?.percentEncodedPath, "/")
+
+        let c4 = URLComponents(string: "http://swift.org/foo/bar")
+        XCTAssertEqual(c4?.percentEncodedPath, "/foo/bar")
+
+        let c5 = URLComponents(string: "http://swift.org:80/foo/bar")
+        XCTAssertEqual(c5?.percentEncodedPath, "/foo/bar")
+
+        let c6 = URLComponents(string: "http://swift.org:80/foo/b%20r")
+        XCTAssertEqual(c6?.percentEncodedPath, "/foo/b%20r")
+    }
 }