@@ -28,13 +28,11 @@ class TestProcess : XCTestCase {
28
28
( " test_pipe_stdout " , test_pipe_stdout) ,
29
29
( " test_pipe_stderr " , test_pipe_stderr) ,
30
30
( " test_current_working_directory " , test_current_working_directory) ,
31
- // disabled for now
32
- // ("test_pipe_stdout_and_stderr_same_pipe", test_pipe_stdout_and_stderr_same_pipe),
31
+ ( " test_pipe_stdout_and_stderr_same_pipe " , test_pipe_stdout_and_stderr_same_pipe) ,
33
32
( " test_file_stdout " , test_file_stdout) ,
34
- // disabled for now
35
- // ("test_passthrough_environment", test_passthrough_environment),
36
- // ("test_no_environment", test_no_environment),
37
- // ("test_custom_environment", test_custom_environment),
33
+ ( " test_passthrough_environment " , test_passthrough_environment) ,
34
+ ( " test_no_environment " , test_no_environment) ,
35
+ ( " test_custom_environment " , test_custom_environment) ,
38
36
]
39
37
}
40
38
@@ -183,7 +181,7 @@ class TestProcess : XCTestCase {
183
181
XCTFail ( " Could not read stdout " )
184
182
return
185
183
}
186
- // testing the return value of an external process is does not port well, and may change.
184
+ // testing the return value of an external process does not port well, and may change.
187
185
// XCTAssertEqual(string, "/bin/cat: invalid_file_name: No such file or directory\n")
188
186
}
189
187
@@ -197,6 +195,9 @@ class TestProcess : XCTestCase {
197
195
process. standardOutput = pipe
198
196
process. standardError = pipe
199
197
198
+ // Clear the environment to stop the malloc debug flags used in Xcode debug being
199
+ // set in the subprocess.
200
+ process. environment = [ : ]
200
201
process. launch ( )
201
202
process. waitUntilExit ( )
202
203
XCTAssertEqual ( process. terminationStatus, 1 )
@@ -206,7 +207,12 @@ class TestProcess : XCTestCase {
206
207
XCTFail ( " Could not read stdout " )
207
208
return
208
209
}
209
- XCTAssertEqual ( string, " /bin/cat: invalid_file_name: No such file or directory \n " )
210
+
211
+ // Remove the leading '/bin/' since on macOS '/bin/cat' just outputs 'cat:'
212
+ let searchStr = " /bin/ "
213
+ let errMsg = string. replacingOccurrences ( of: searchStr, with: " " , options: [ . literal, . anchored] ,
214
+ range: searchStr. startIndex..< searchStr. endIndex)
215
+ XCTAssertEqual ( errMsg, " cat: invalid_file_name: No such file or directory \n " )
210
216
}
211
217
212
218
func test_file_stdout( ) {
@@ -234,7 +240,7 @@ class TestProcess : XCTestCase {
234
240
235
241
func test_passthrough_environment( ) {
236
242
do {
237
- let output = try runTask ( [ " /usr/bin/env " ] , environment: nil )
243
+ let ( output, _ ) = try runTask ( [ " /usr/bin/env " ] , environment: nil )
238
244
let env = try parseEnv ( output)
239
245
XCTAssertGreaterThan ( env. count, 0 )
240
246
} catch let error {
@@ -244,7 +250,7 @@ class TestProcess : XCTestCase {
244
250
245
251
func test_no_environment( ) {
246
252
do {
247
- let output = try runTask ( [ " /usr/bin/env " ] , environment: [ : ] )
253
+ let ( output, _ ) = try runTask ( [ " /usr/bin/env " ] , environment: [ : ] )
248
254
let env = try parseEnv ( output)
249
255
XCTAssertEqual ( env. count, 0 )
250
256
} catch let error {
@@ -255,7 +261,7 @@ class TestProcess : XCTestCase {
255
261
func test_custom_environment( ) {
256
262
do {
257
263
let input = [ " HELLO " : " WORLD " , " HOME " : " CUPERTINO " ]
258
- let output = try runTask ( [ " /usr/bin/env " ] , environment: input)
264
+ let ( output, _ ) = try runTask ( [ " /usr/bin/env " ] , environment: input)
259
265
let env = try parseEnv ( output)
260
266
XCTAssertEqual ( env, input)
261
267
} catch let error {
@@ -267,9 +273,9 @@ class TestProcess : XCTestCase {
267
273
do {
268
274
let previousWorkingDirectory = FileManager . default. currentDirectoryPath
269
275
270
- // `bash` will not be found if the current working directory is not set correctly.
271
- let _ = try runTask ( [ " bash " , " -c " , " exit 0 " ] , currentDirectoryPath: " /bin " )
272
-
276
+ // Darwin Foundation requires the full path to the executable (.launchPath)
277
+ let ( output , _ ) = try runTask ( [ " /bin/ bash" , " -c " , " pwd " ] , currentDirectoryPath: " /bin " )
278
+ XCTAssertEqual ( output . trimmingCharacters ( in : . newlines ) , " /bin " )
273
279
XCTAssertEqual ( previousWorkingDirectory, FileManager . default. currentDirectoryPath)
274
280
} catch let error {
275
281
XCTFail ( " Test failed: \( error) " )
@@ -297,34 +303,44 @@ private enum Error: Swift.Error {
297
303
case InvalidEnvironmentVariable( String )
298
304
}
299
305
300
- private func runTask( _ arguments: [ String ] , environment: [ String : String ] ? = nil , currentDirectoryPath: String ? = nil ) throws -> String {
306
+ private func runTask( _ arguments: [ String ] , environment: [ String : String ] ? = nil , currentDirectoryPath: String ? = nil ) throws -> ( String , String ) {
301
307
let process = Process ( )
302
308
303
309
var arguments = arguments
304
310
process. launchPath = arguments. removeFirst ( )
305
311
process. arguments = arguments
306
- process. environment = environment
312
+ // Darwin Foundation doesnt allow .environment to be set to nil although the documentation
313
+ // says it is an optional. https://developer.apple.com/documentation/foundation/process/1409412-environment
314
+ if let e = environment {
315
+ process. environment = e
316
+ }
307
317
308
318
if let directoryPath = currentDirectoryPath {
309
319
process. currentDirectoryPath = directoryPath
310
320
}
311
321
312
- let pipe = Pipe ( )
313
- process. standardOutput = pipe
314
- process. standardError = pipe
322
+ let stdoutPipe = Pipe ( )
323
+ let stderrPipe = Pipe ( )
324
+ process. standardOutput = stdoutPipe
325
+ process. standardError = stderrPipe
315
326
process. launch ( )
316
327
process. waitUntilExit ( )
317
328
318
329
guard process. terminationStatus == 0 else {
319
330
throw Error . TerminationStatus ( process. terminationStatus)
320
331
}
321
332
322
- let data = pipe. fileHandleForReading. availableData
323
- guard let output = String ( data: data, encoding: . utf8) else {
324
- throw Error . UnicodeDecodingError ( data)
333
+ let stdoutData = stdoutPipe. fileHandleForReading. availableData
334
+ guard let stdout = String ( data: stdoutData, encoding: . utf8) else {
335
+ throw Error . UnicodeDecodingError ( stdoutData)
336
+ }
337
+
338
+ let stderrData = stderrPipe. fileHandleForReading. availableData
339
+ guard let stderr = String ( data: stderrData, encoding: . utf8) else {
340
+ throw Error . UnicodeDecodingError ( stderrData)
325
341
}
326
342
327
- return output
343
+ return ( stdout , stderr )
328
344
}
329
345
330
346
private func parseEnv( _ env: String ) throws -> [ String : String ] {
0 commit comments