@@ -27,6 +27,7 @@ class TestNSTask : XCTestCase {
27
27
( " test_pipe_stdin " , test_pipe_stdin) ,
28
28
( " test_pipe_stdout " , test_pipe_stdout) ,
29
29
( " test_pipe_stderr " , test_pipe_stderr) ,
30
+ ( " test_pipe_stdout_and_stderr_same_pipe " , test_pipe_stdout_and_stderr_same_pipe) ,
30
31
( " test_file_stdout " , test_file_stdout) ,
31
32
( " test_passthrough_environment " , test_passthrough_environment) ,
32
33
( " test_no_environment " , test_no_environment) ,
@@ -163,7 +164,29 @@ class TestNSTask : XCTestCase {
163
164
XCTFail ( " Could not read stdout " )
164
165
return
165
166
}
166
- XCTAssertEqual ( string, " cat: invalid_file_name: No such file or directory \n " )
167
+ XCTAssertEqual ( string, " /bin/cat: invalid_file_name: No such file or directory \n " )
168
+ }
169
+
170
+ func test_pipe_stdout_and_stderr_same_pipe( ) {
171
+ let task = NSTask ( )
172
+
173
+ task. launchPath = " /bin/cat "
174
+ task. arguments = [ " invalid_file_name " ]
175
+
176
+ let pipe = NSPipe ( )
177
+ task. standardOutput = pipe
178
+ task. standardError = pipe
179
+
180
+ task. launch ( )
181
+ task. waitUntilExit ( )
182
+ XCTAssertEqual ( task. terminationStatus, 1 )
183
+
184
+ let data = pipe. fileHandleForReading. availableData
185
+ guard let string = String ( data: data, encoding: NSASCIIStringEncoding) else {
186
+ XCTFail ( " Could not read stdout " )
187
+ return
188
+ }
189
+ XCTAssertEqual ( string, " /bin/cat: invalid_file_name: No such file or directory \n " )
167
190
}
168
191
169
192
func test_file_stdout( ) {
@@ -188,19 +211,36 @@ class TestNSTask : XCTestCase {
188
211
XCTAssertEqual ( string, " /usr/bin/which \n " )
189
212
}
190
213
}
191
-
214
+
192
215
func test_passthrough_environment( ) {
193
- XCTAssertGreaterThan ( env ( environment: nil ) . count, 0 )
216
+ do {
217
+ let output = try runTask ( [ " /usr/bin/env " ] , environment: nil )
218
+ let env = try parseEnv ( output)
219
+ XCTAssertGreaterThan ( env. count, 0 )
220
+ } catch let error {
221
+ XCTFail ( " Test failed: \( error) " )
222
+ }
194
223
}
195
224
196
225
func test_no_environment( ) {
197
- XCTAssertEqual ( env ( environment: [ : ] ) . count, 0 )
226
+ do {
227
+ let output = try runTask ( [ " /usr/bin/env " ] , environment: [ : ] )
228
+ let env = try parseEnv ( output)
229
+ XCTAssertEqual ( env. count, 0 )
230
+ } catch let error {
231
+ XCTFail ( " Test failed: \( error) " )
232
+ }
198
233
}
199
234
200
235
func test_custom_environment( ) {
201
- let input = [ " HELLO " : " WORLD " , " HOME " : " CUPERTINO " ]
202
- let output = env ( environment: input)
203
- XCTAssertEqual ( output, input)
236
+ do {
237
+ let input = [ " HELLO " : " WORLD " , " HOME " : " CUPERTINO " ]
238
+ let output = try runTask ( [ " /usr/bin/env " ] , environment: input)
239
+ let env = try parseEnv ( output)
240
+ XCTAssertEqual ( env, input)
241
+ } catch let error {
242
+ XCTFail ( " Test failed: \( error) " )
243
+ }
204
244
}
205
245
}
206
246
@@ -216,31 +256,47 @@ private func mkstemp(template: String, body: @noescape (NSFileHandle) throws ->
216
256
}
217
257
}
218
258
219
- private func env( environment: [ String : String ] ? ) -> [ String : String ] {
259
+ private enum Error : ErrorProtocol {
260
+ case TerminationStatus( Int32 )
261
+ case UnicodeDecodingError( NSData )
262
+ case InvalidEnvironmentVariable( String )
263
+ }
264
+
265
+ private func runTask( _ arguments: [ String ] , environment: [ String : String ] ? = nil ) throws -> String {
220
266
let task = NSTask ( )
221
- task. launchPath = " /usr/bin/env "
267
+
268
+ var arguments = arguments
269
+ task. launchPath = arguments. removeFirst ( )
270
+ task. arguments = arguments
222
271
task. environment = environment
223
272
224
273
let pipe = NSPipe ( )
225
274
task. standardOutput = pipe
226
-
275
+ task . standardError = pipe
227
276
task. launch ( )
228
277
task. waitUntilExit ( )
229
- XCTAssertEqual ( task. terminationStatus, 0 )
278
+
279
+ guard task. terminationStatus == 0 else {
280
+ throw Error . TerminationStatus ( task. terminationStatus)
281
+ }
230
282
231
283
let data = pipe. fileHandleForReading. availableData
232
- guard let string = String ( data: data, encoding: NSUTF8StringEncoding) else {
233
- XCTFail ( " Could not read stdout " )
234
- return [ : ]
284
+ guard let output = String ( data: data, encoding: NSUTF8StringEncoding) else {
285
+ throw Error . UnicodeDecodingError ( data)
235
286
}
236
287
288
+ return output
289
+ }
290
+
291
+ private func parseEnv( _ env: String ) throws -> [ String : String ] {
237
292
var result = [ String: String] ( )
238
- for variable in string. components ( separatedBy: " \n " ) where variable != " " {
239
- guard let range = variable. range ( of: " = " ) else {
240
- XCTFail ( " Could not parse environment variable: \" \( variable) \" " )
241
- continue
293
+ for line in env. components ( separatedBy: " \n " ) where line != " " {
294
+ guard let range = line. range ( of: " = " ) else {
295
+ throw Error . InvalidEnvironmentVariable ( line)
242
296
}
243
- result [ variable . substring ( to: range. lowerBound) ] = variable . substring ( from: range. upperBound)
297
+ result [ line . substring ( to: range. lowerBound) ] = line . substring ( from: range. upperBound)
244
298
}
245
299
return result
246
300
}
301
+
302
+
0 commit comments