Merge pull request #1446 from pvieito/master

diff --git a/CoreFoundation/PlugIn.subproj/CFBundle_Executable.c b/CoreFoundation/PlugIn.subproj/CFBundle_Executable.c
index 64d0f05..568a6e4 100644
--- a/CoreFoundation/PlugIn.subproj/CFBundle_Executable.c
+++ b/CoreFoundation/PlugIn.subproj/CFBundle_Executable.c
@@ -207,13 +207,15 @@
             if (lookupMainExe && bundle && bundle->_isFHSInstalledBundle) {
                 // For a FHS installed bundle, the URL points to share/Bundle.resources, and the binary is in:
                 
-                CFURLRef prefix = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorSystemDefault, url);
-                
+                CFURLRef sharePath = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorSystemDefault, url);
+                CFURLRef prefixPath = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorSystemDefault, sharePath);
+                CFRelease(sharePath);
+
                 CFStringRef directories[] = { _CFBundleFHSDirectoriesInExecutableSearchOrder };
                 size_t directoriesCount = sizeof(directories) / sizeof(directories[0]);
                 
                 for (size_t i = 0; i < directoriesCount; i++) {
-                    CFURLRef where = CFURLCreateCopyAppendingPathComponent(kCFAllocatorSystemDefault, prefix, directories[i], true);
+                    CFURLRef where = CFURLCreateCopyAppendingPathComponent(kCFAllocatorSystemDefault, prefixPath, directories[i], true);
                     executableURL = _CFBundleCopyExecutableURLRaw(where, executableName);
                     CFRelease(where);
                     
@@ -223,7 +225,7 @@
                     }
                 }
                 
-                CFRelease(prefix);
+                CFRelease(prefixPath);
             }
 #endif // !DEPLOYMENT_RUNTIME_OBJC && !DEPLOYMENT_TARGET_WINDOWS
             
@@ -290,11 +292,7 @@
             if (lookupMainExe && !ignoreCache && bundle && executableURL) {
                 // We found it.  Cache the path.
                 CFURLRef absURL = CFURLCopyAbsoluteURL(executableURL);
-#if DEPLOYMENT_TARGET_WINDOWS
-                executablePath = CFURLCopyFileSystemPath(absURL, kCFURLWindowsPathStyle);
-#else
-                executablePath = CFURLCopyFileSystemPath(absURL, kCFURLPOSIXPathStyle);
-#endif
+                executablePath = CFURLCopyFileSystemPath(absURL, PLATFORM_PATH_STYLE);
                 CFRelease(absURL);
                 __CFLock(&bundle->_lock);
                 bundle->_executablePath = (CFStringRef)CFRetain(executablePath);
diff --git a/Foundation/Bundle.swift b/Foundation/Bundle.swift
index 5c66d37..921126a 100644
--- a/Foundation/Bundle.swift
+++ b/Foundation/Bundle.swift
@@ -115,8 +115,8 @@
         return CFBundleCopyExecutableURL(_bundle)?._swiftObject
     }
     
-    open func url(forAuxiliaryExecutable executableName: String) -> NSURL? {
-        return CFBundleCopyAuxiliaryExecutableURL(_bundle, executableName._cfObject)?._nsObject
+    open func url(forAuxiliaryExecutable executableName: String) -> URL? {
+        return CFBundleCopyAuxiliaryExecutableURL(_bundle, executableName._cfObject)?._swiftObject
     }
     
     open var privateFrameworksURL: URL? {
diff --git a/TestFoundation/TestBundle.swift b/TestFoundation/TestBundle.swift
index 3db11bf..1b8cb7d 100644
--- a/TestFoundation/TestBundle.swift
+++ b/TestFoundation/TestBundle.swift
@@ -9,26 +9,26 @@
 
 
 #if DEPLOYMENT_RUNTIME_OBJC || os(Linux)
-    import Foundation
-    import XCTest
+import Foundation
+import XCTest
 #else
-    import SwiftFoundation
-    import SwiftXCTest
+import SwiftFoundation
+import SwiftXCTest
 #endif
 
 import CoreFoundation
 
 internal func testBundle() -> Bundle {
-#if DARWIN_COMPATIBILITY_TESTS
+    #if DARWIN_COMPATIBILITY_TESTS
     for bundle in Bundle.allBundles {
         if let bundleId = bundle.bundleIdentifier, bundleId == "org.swift.DarwinCompatibilityTests", bundle.resourcePath != nil {
             return bundle
         }
     }
     fatalError("Cant find test bundle")
-#else
+    #else
     return Bundle.main
-#endif
+    #endif
 }
 
 class BundlePlayground {
@@ -58,6 +58,7 @@
     }
     
     let bundleName: String
+    let bundleExtension: String
     let resourceFilenames: [String]
     let resourceSubdirectory: String
     let subdirectoryResourcesFilenames: [String]
@@ -68,12 +69,14 @@
     private var playgroundPath: String?
     
     init?(bundleName: String,
-         resourceFilenames: [String],
-         resourceSubdirectory: String,
-         subdirectoryResourcesFilenames: [String],
-         auxiliaryExecutableName: String,
-         layout: Layout) {
+          bundleExtension: String,
+          resourceFilenames: [String],
+          resourceSubdirectory: String,
+          subdirectoryResourcesFilenames: [String],
+          auxiliaryExecutableName: String,
+          layout: Layout) {
         self.bundleName = bundleName
+        self.bundleExtension = bundleExtension
         self.resourceFilenames = resourceFilenames
         self.resourceSubdirectory = resourceSubdirectory
         self.subdirectoryResourcesFilenames = subdirectoryResourcesFilenames
@@ -88,53 +91,55 @@
     
     private func _create() -> Bool {
         // Make sure the directory is uniquely named
-        let tempDir = NSTemporaryDirectory() + "TestFoundation_Playground_" + NSUUID().uuidString + "/"
+        
+        let temporaryDirectory = FileManager.default.temporaryDirectory.appendingPathComponent("TestFoundation_Playground_" + UUID().uuidString)
         
         switch (layout) {
         case .flat:
-        do {
-            try FileManager.default.createDirectory(atPath: tempDir, withIntermediateDirectories: false, attributes: nil)
-            
-            // Make a flat bundle in the playground
-            let bundlePath = tempDir + bundleName
-            try FileManager.default.createDirectory(atPath: bundlePath, withIntermediateDirectories: false, attributes: nil)
-            
-            // Make a main and an auxiliary executable:
-            guard FileManager.default.createFile(atPath: bundlePath + "/" + bundleName, contents: nil) else {
-                return false
-            }
-            guard FileManager.default.createFile(atPath: bundlePath + "/" + auxiliaryExecutableName, contents: nil) else {
+            do {
+                try FileManager.default.createDirectory(atPath: temporaryDirectory.path, withIntermediateDirectories: false, attributes: nil)
+                
+                // Make a flat bundle in the playground
+                let bundleURL = temporaryDirectory.appendingPathComponent(bundleName).appendingPathExtension(self.bundleExtension)
+                try FileManager.default.createDirectory(atPath: bundleURL.path, withIntermediateDirectories: false, attributes: nil)
+                
+                // Make a main and an auxiliary executable:
+                guard FileManager.default.createFile(atPath: bundleURL.appendingPathComponent(bundleName).path, contents: nil) else {
+                    return false
+                }
+                guard FileManager.default.createFile(atPath: bundleURL.appendingPathComponent(auxiliaryExecutableName).path, contents: nil) else {
+                    return false
+                }
+                
+                // Put some resources in the bundle
+                for resourceName in resourceFilenames {
+                    guard FileManager.default.createFile(atPath: bundleURL.appendingPathComponent(resourceName).path, contents: nil, attributes: nil) else {
+                        return false
+                    }
+                }
+                
+                // Add a resource into a subdirectory
+                let subdirectoryURL = bundleURL.appendingPathComponent(resourceSubdirectory)
+                try FileManager.default.createDirectory(atPath: subdirectoryURL.path, withIntermediateDirectories: false, attributes: nil)
+                
+                for resourceName in subdirectoryResourcesFilenames {
+                    guard FileManager.default.createFile(atPath: subdirectoryURL.appendingPathComponent(resourceName).path, contents: nil, attributes: nil) else {
+                        return false
+                    }
+                }
+                
+                self.bundlePath = bundleURL.path
+            } catch _ {
                 return false
             }
             
-            // Put some resources in the bundle
-            for n in resourceFilenames {
-                guard FileManager.default.createFile(atPath: bundlePath + "/" + n, contents: nil, attributes: nil) else {
-                    return false
-                }
-            }
-            // Add a resource into a subdirectory
-            let subDirPath = bundlePath + "/" + resourceSubdirectory
-            try FileManager.default.createDirectory(atPath: subDirPath, withIntermediateDirectories: false, attributes: nil)
-            for n in subdirectoryResourcesFilenames {
-                guard FileManager.default.createFile(atPath: subDirPath + "/" + n, contents: nil, attributes: nil) else {
-                    return false
-                }
-            }
-            
-            self.bundlePath = bundlePath
-        } catch _ {
-            return false
-        }
-        
         case .fhsInstalled:
             do {
-                let bundleName = URL(string:self.bundleName)!.deletingPathExtension().path
                 
                 // Create a FHS /usr/local-style hierarchy:
-                try FileManager.default.createDirectory(atPath: tempDir, withIntermediateDirectories: false, attributes: nil)
-                try FileManager.default.createDirectory(atPath: tempDir + "/share", withIntermediateDirectories: false, attributes: nil)
-                try FileManager.default.createDirectory(atPath: tempDir + "/lib", withIntermediateDirectories: false, attributes: nil)
+                try FileManager.default.createDirectory(atPath: temporaryDirectory.path, withIntermediateDirectories: false, attributes: nil)
+                try FileManager.default.createDirectory(atPath: temporaryDirectory.appendingPathComponent("share").path, withIntermediateDirectories: false, attributes: nil)
+                try FileManager.default.createDirectory(atPath: temporaryDirectory.appendingPathComponent("lib").path, withIntermediateDirectories: false, attributes: nil)
                 
                 // Make a main and an auxiliary executable:
                 #if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
@@ -143,28 +148,30 @@
                 let pathExtension = "so"
                 #endif
                 
-                guard FileManager.default.createFile(atPath: tempDir + "/lib/lib" + bundleName + ".\(pathExtension)", contents: nil) else { return false }
+                guard FileManager.default.createFile(atPath: temporaryDirectory.appendingPathComponent("lib").appendingPathComponent("lib\(bundleName).\(pathExtension)").path, contents: nil) else { return false }
                 
-                let executables = tempDir + "/libexec/" + bundleName + ".executables"
-                try FileManager.default.createDirectory(atPath: executables, withIntermediateDirectories: true, attributes: nil)
-                guard FileManager.default.createFile(atPath: executables + "/" + auxiliaryExecutableName, contents: nil) else { return false }
+                let executablesDirectory = temporaryDirectory.appendingPathComponent("libexec").appendingPathComponent("\(bundleName).executables")
+                try FileManager.default.createDirectory(atPath: executablesDirectory.path, withIntermediateDirectories: true, attributes: nil)
+                guard FileManager.default.createFile(atPath: executablesDirectory.appendingPathComponent(auxiliaryExecutableName).path, contents: nil) else { return false }
                 
                 // Make a .resources directory in …/share:
-                let resourcesPath = tempDir + "/share/" + bundleName + ".resources"
-                try FileManager.default.createDirectory(atPath: resourcesPath, withIntermediateDirectories: false, attributes: nil)
+                let resourcesDirectory = temporaryDirectory.appendingPathComponent("share").appendingPathComponent("\(bundleName).resources")
+                try FileManager.default.createDirectory(atPath: resourcesDirectory.path, withIntermediateDirectories: false, attributes: nil)
                 
                 // Put some resources in the bundle
-                for n in resourceFilenames {
-                    guard FileManager.default.createFile(atPath: resourcesPath + "/" + n, contents: nil, attributes: nil) else { return false }
-                }
-                // Add a resource into a subdirectory
-                let subDirPath = resourcesPath + "/" + resourceSubdirectory
-                try FileManager.default.createDirectory(atPath: subDirPath, withIntermediateDirectories: false, attributes: nil)
-                for n in subdirectoryResourcesFilenames {
-                    guard FileManager.default.createFile(atPath: subDirPath + "/" + n, contents: nil, attributes: nil) else { return false }
+                for resourceName in resourceFilenames {
+                    guard FileManager.default.createFile(atPath: resourcesDirectory.appendingPathComponent(resourceName).path, contents: nil, attributes: nil) else { return false }
                 }
                 
-                self.bundlePath = resourcesPath
+                // Add a resource into a subdirectory
+                let subdirectoryURL = resourcesDirectory.appendingPathComponent(resourceSubdirectory)
+                try FileManager.default.createDirectory(atPath: subdirectoryURL.path, withIntermediateDirectories: false, attributes: nil)
+                
+                for resourceName in subdirectoryResourcesFilenames {
+                    guard FileManager.default.createFile(atPath: subdirectoryURL.appendingPathComponent(resourceName).path, contents: nil, attributes: nil) else { return false }
+                }
+                
+                self.bundlePath = resourcesDirectory.path
             } catch _ {
                 return false
             }
@@ -173,36 +180,38 @@
             do {
                 let bundleName = URL(string:self.bundleName)!.deletingPathExtension().path
                 
-                try FileManager.default.createDirectory(atPath: tempDir, withIntermediateDirectories: false, attributes: nil)
+                try FileManager.default.createDirectory(atPath: temporaryDirectory.path, withIntermediateDirectories: false, attributes: nil)
                 
                 // Make a main executable:
-                guard FileManager.default.createFile(atPath: tempDir + "/" + bundleName, contents: nil) else { return false }
+                guard FileManager.default.createFile(atPath: temporaryDirectory.appendingPathComponent(bundleName).path, contents: nil) else { return false }
                 
                 // Make a .resources directory:
-                let resourcesPath = tempDir + "/" + bundleName + ".resources"
-                try FileManager.default.createDirectory(atPath: resourcesPath, withIntermediateDirectories: false, attributes: nil)
+                let resourcesDirectory = temporaryDirectory.appendingPathComponent("\(bundleName).resources")
+                try FileManager.default.createDirectory(atPath: resourcesDirectory.path, withIntermediateDirectories: false, attributes: nil)
                 
                 // Make an auxiliary executable:
-                guard FileManager.default.createFile(atPath: resourcesPath + "/" + auxiliaryExecutableName, contents: nil) else { return false }
+                guard FileManager.default.createFile(atPath: resourcesDirectory.appendingPathComponent(auxiliaryExecutableName).path, contents: nil) else { return false }
                 
                 // Put some resources in the bundle
-                for n in resourceFilenames {
-                    guard FileManager.default.createFile(atPath: resourcesPath + "/" + n, contents: nil, attributes: nil) else { return false }
-                }
-                // Add a resource into a subdirectory
-                let subDirPath = resourcesPath + "/" + resourceSubdirectory
-                try FileManager.default.createDirectory(atPath: subDirPath, withIntermediateDirectories: false, attributes: nil)
-                for n in subdirectoryResourcesFilenames {
-                    guard FileManager.default.createFile(atPath: subDirPath + "/" + n, contents: nil, attributes: nil) else { return false }
+                for resourceName in resourceFilenames {
+                    guard FileManager.default.createFile(atPath: resourcesDirectory.appendingPathComponent(resourceName).path, contents: nil, attributes: nil) else { return false }
                 }
                 
-                self.bundlePath = resourcesPath
+                // Add a resource into a subdirectory
+                let subdirectoryURL = resourcesDirectory.appendingPathComponent(resourceSubdirectory)
+                try FileManager.default.createDirectory(atPath: subdirectoryURL.path, withIntermediateDirectories: false, attributes: nil)
+                
+                for resourceName in subdirectoryResourcesFilenames {
+                    guard FileManager.default.createFile(atPath: subdirectoryURL.appendingPathComponent(resourceName).path, contents: nil, attributes: nil) else { return false }
+                }
+                
+                self.bundlePath = resourcesDirectory.path
             } catch _ {
                 return false
             }
         }
         
-        self.playgroundPath = tempDir
+        self.playgroundPath = temporaryDirectory.path
         return true
     }
     
@@ -235,40 +244,41 @@
             ("test_bundleLoadWithError", test_bundleLoadWithError),
             ("test_bundleWithInvalidPath", test_bundleWithInvalidPath),
             ("test_bundlePreflight", test_bundlePreflight),
+            ("test_bundleFindExecutable", test_bundleFindExecutable),
             ("test_bundleFindAuxiliaryExecutables", test_bundleFindAuxiliaryExecutables),
         ]
     }
     
     func test_paths() {
         let bundle = testBundle()
-
+        
         // bundlePath
         XCTAssert(!bundle.bundlePath.isEmpty)
         XCTAssertEqual(bundle.bundleURL.path, bundle.bundlePath)
         let path = bundle.bundlePath
-
+        
         // etc
         #if os(OSX)
         XCTAssertEqual("\(path)/Contents/Resources", bundle.resourcePath)
-#if DARWIN_COMPATIBILITY_TESTS
+        #if DARWIN_COMPATIBILITY_TESTS
         XCTAssertEqual("\(path)/Contents/MacOS/DarwinCompatibilityTests", bundle.executablePath)
-#else
+        #else
         XCTAssertEqual("\(path)/Contents/MacOS/TestFoundation", bundle.executablePath)
-#endif
+        #endif
         XCTAssertEqual("\(path)/Contents/Frameworks", bundle.privateFrameworksPath)
         XCTAssertEqual("\(path)/Contents/SharedFrameworks", bundle.sharedFrameworksPath)
         XCTAssertEqual("\(path)/Contents/SharedSupport", bundle.sharedSupportPath)
         #endif
         
         XCTAssertNil(bundle.path(forAuxiliaryExecutable: "no_such_file"))
-#if !DARWIN_COMPATIBILITY_TESTS
+        #if !DARWIN_COMPATIBILITY_TESTS
         XCTAssertNil(bundle.appStoreReceiptURL)
-#endif
+        #endif
     }
     
     func test_resources() {
         let bundle = testBundle()
-
+        
         // bad resources
         XCTAssertNil(bundle.url(forResource: nil, withExtension: nil, subdirectory: nil))
         XCTAssertNil(bundle.url(forResource: "", withExtension: "", subdirectory: nil))
@@ -290,37 +300,38 @@
         let bundle = testBundle()
         
         // bundleIdentifier
-#if DARWIN_COMPATIBILITY_TESTS
+        #if DARWIN_COMPATIBILITY_TESTS
         XCTAssertEqual("org.swift.DarwinCompatibilityTests", bundle.bundleIdentifier)
-#else
+        #else
         XCTAssertEqual("org.swift.TestFoundation", bundle.bundleIdentifier)
-#endif
-
+        #endif
+        
         // infoDictionary
         let info = bundle.infoDictionary
         XCTAssertNotNil(info)
-
-#if DARWIN_COMPATIBILITY_TESTS
+        
+        #if DARWIN_COMPATIBILITY_TESTS
         XCTAssert("DarwinCompatibilityTests" == info!["CFBundleName"] as! String)
         XCTAssert("org.swift.DarwinCompatibilityTests" == info!["CFBundleIdentifier"] as! String)
-#else
+        #else
         XCTAssert("TestFoundation" == info!["CFBundleName"] as! String)
         XCTAssert("org.swift.TestFoundation" == info!["CFBundleIdentifier"] as! String)
-#endif
-
+        #endif
+        
         // localizedInfoDictionary
         XCTAssertNil(bundle.localizedInfoDictionary) // FIXME: Add a localized Info.plist for testing
     }
     
     func test_localizations() {
         let bundle = testBundle()
-
+        
         XCTAssertEqual(["en"], bundle.localizations)
         XCTAssertEqual(["en"], bundle.preferredLocalizations)
         XCTAssertEqual(["en"], Bundle.preferredLocalizations(from: ["en", "pl", "es"]))
     }
     
-    private let _bundleName = "MyBundle.bundle"
+    private let _bundleName = "MyBundle"
+    private let _bundleExtension = "bundle"
     private let _bundleResourceNames = ["hello.world", "goodbye.world", "swift.org"]
     private let _subDirectory = "Sources"
     private let _main = "main"
@@ -329,6 +340,7 @@
     
     private func _setupPlayground(layout: BundlePlayground.Layout) -> BundlePlayground? {
         return BundlePlayground(bundleName: _bundleName,
+                                bundleExtension: _bundleExtension,
                                 resourceFilenames: _bundleResourceNames,
                                 resourceSubdirectory: _subDirectory,
                                 subdirectoryResourcesFilenames: [ "\(_main).\(_type)" ],
@@ -352,58 +364,67 @@
             // Oh well
         }
     }
-
+    
     func test_URLsForResourcesWithExtension() {
         _withEachPlaygroundLayout { (playground) in
-            let bundle = Bundle(path: playground.bundlePath)
+            let bundle = Bundle(path: playground.bundlePath)!
             XCTAssertNotNil(bundle)
             
-            let worldResources = bundle?.urls(forResourcesWithExtension: "world", subdirectory: nil)
+            let worldResources = bundle.urls(forResourcesWithExtension: "world", subdirectory: nil)
             XCTAssertNotNil(worldResources)
             XCTAssertEqual(worldResources?.count, 2)
             
-            let path = bundle?.path(forResource: _main, ofType: _type, inDirectory: _subDirectory)
+            let path = bundle.path(forResource: _main, ofType: _type, inDirectory: _subDirectory)
             XCTAssertNotNil(path)
         }
     }
     
-    func test_bundleLoad(){
+    func test_bundleLoad() {
         let bundle = testBundle()
         let _ = bundle.load()
         XCTAssertTrue(bundle.isLoaded)
     }
     
-    func test_bundleLoadWithError(){
+    func test_bundleLoadWithError() {
         let bundleValid = testBundle()
-        //test valid load using loadAndReturnError
-        do{
+        
+        // Test valid load using loadAndReturnError
+        do {
             try bundleValid.loadAndReturnError()
-        }catch{
+        }
+        catch{
             XCTFail("should not fail to load")
         }
-        // executable cannot be located
+        
+        // Executable cannot be located
         try! _withEachPlaygroundLayout { (playground) in
             let bundle = Bundle(path: playground.bundlePath)
             XCTAssertThrowsError(try bundle!.loadAndReturnError())
         }
     }
     
-    func test_bundleWithInvalidPath(){
+    func test_bundleWithInvalidPath() {
         let bundleInvalid = Bundle(path: NSTemporaryDirectory() + "test.playground")
         XCTAssertNil(bundleInvalid)
     }
     
-    func test_bundlePreflight(){
-        let bundleValid = testBundle()
-        do{
-            try bundleValid.preflight()
-        }catch{
-            XCTFail("should not fail to load")
-        }
-        // executable cannot be located ..preflight should report error
+    func test_bundlePreflight() {
+        XCTAssertNoThrow(try testBundle().preflight())
+        
         try! _withEachPlaygroundLayout { (playground) in
-            let bundle = Bundle(path: playground.bundlePath)
-            XCTAssertThrowsError(try bundle!.preflight())
+            let bundle = Bundle(path: playground.bundlePath)!
+            
+            // Must throw as the main executable is a dummy empty file.
+            XCTAssertThrowsError(try bundle.preflight())
+        }
+    }
+    
+    func test_bundleFindExecutable() {
+        XCTAssertNotNil(testBundle().executableURL)
+        
+        _withEachPlaygroundLayout { (playground) in
+            let bundle = Bundle(path: playground.bundlePath)!
+            XCTAssertNotNil(bundle.executableURL)
         }
     }