diff --git a/Sources/Testing/ExitTests/SpawnProcess.swift b/Sources/Testing/ExitTests/SpawnProcess.swift index 50d78010a..c5d87e6f7 100644 --- a/Sources/Testing/ExitTests/SpawnProcess.swift +++ b/Sources/Testing/ExitTests/SpawnProcess.swift @@ -46,9 +46,9 @@ func spawnExecutable( ) throws -> ProcessID { // Darwin and Linux differ in their optionality for the posix_spawn types we // use, so use this typealias to paper over the differences. -#if SWT_TARGET_OS_APPLE +#if SWT_TARGET_OS_APPLE || os(FreeBSD) typealias P = T? -#elseif os(Linux) || os(FreeBSD) +#elseif os(Linux) typealias P = T #endif diff --git a/Sources/Testing/Support/Additions/CommandLineAdditions.swift b/Sources/Testing/Support/Additions/CommandLineAdditions.swift index c354e386a..762ab7290 100644 --- a/Sources/Testing/Support/Additions/CommandLineAdditions.swift +++ b/Sources/Testing/Support/Additions/CommandLineAdditions.swift @@ -16,16 +16,19 @@ extension CommandLine { get throws { #if os(macOS) var result: String? - var bufferCount = UInt32(1024) +#if DEBUG + var bufferCount = UInt32(1) // force looping +#else + var bufferCount = UInt32(PATH_MAX) +#endif while result == nil { - result = withUnsafeTemporaryAllocation(of: CChar.self, capacity: Int(bufferCount)) { buffer in + withUnsafeTemporaryAllocation(of: CChar.self, capacity: Int(bufferCount)) { buffer in // _NSGetExecutablePath returns 0 on success and -1 if bufferCount is // too small. If that occurs, we'll return nil here and loop with the // new value of bufferCount. if 0 == _NSGetExecutablePath(buffer.baseAddress, &bufferCount) { - return String(cString: buffer.baseAddress!) + result = String(cString: buffer.baseAddress!) } - return nil } } return result! @@ -40,7 +43,7 @@ extension CommandLine { } #elseif os(FreeBSD) var mib = [CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1] - try mib.withUnsafeMutableBufferPointer { mib in + return try mib.withUnsafeMutableBufferPointer { mib in var bufferCount = 0 guard 0 == sysctl(mib.baseAddress!, .init(mib.count), nil, &bufferCount, nil, 0) else { throw CError(rawValue: swt_errno()) @@ -53,15 +56,30 @@ extension CommandLine { } } #elseif os(Windows) - return try withUnsafeTemporaryAllocation(of: wchar_t.self, capacity: Int(MAX_PATH) * 2) { buffer in - guard 0 != GetModuleFileNameW(nil, buffer.baseAddress!, DWORD(buffer.count)) else { - throw Win32Error(rawValue: GetLastError()) - } - guard let path = String.decodeCString(buffer.baseAddress!, as: UTF16.self)?.result else { - throw Win32Error(rawValue: DWORD(ERROR_ILLEGAL_CHARACTER)) + var result: String? +#if DEBUG + var bufferCount = Int(1) // force looping +#else + var bufferCount = Int(MAX_PATH) +#endif + while result == nil { + try withUnsafeTemporaryAllocation(of: wchar_t.self, capacity: bufferCount) { buffer in + SetLastError(DWORD(ERROR_SUCCESS)) + _ = GetModuleFileNameW(nil, buffer.baseAddress!, DWORD(buffer.count)) + switch GetLastError() { + case DWORD(ERROR_SUCCESS): + result = String.decodeCString(buffer.baseAddress!, as: UTF16.self)?.result + if result == nil { + throw Win32Error(rawValue: DWORD(ERROR_ILLEGAL_CHARACTER)) + } + case DWORD(ERROR_INSUFFICIENT_BUFFER): + bufferCount += Int(MAX_PATH) + case let errorCode: + throw Win32Error(rawValue: errorCode) + } } - return path } + return result! #elseif os(WASI) // WASI does not really have the concept of a file system path to the main // executable, so simply return the first argument--presumably the program