Skip to content

Commit b739c0a

Browse files
authored
make testSignals more robust (#196)
1 parent 0054181 commit b739c0a

File tree

1 file changed

+60
-39
lines changed

1 file changed

+60
-39
lines changed

Tests/TSCBasicTests/ProcessTests.swift

Lines changed: 60 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -116,51 +116,72 @@ class ProcessTests: XCTestCase {
116116

117117
#if !os(Windows) // Signals are not supported in Windows
118118
func testSignals() throws {
119+
let group = DispatchGroup()
119120

120-
// Test sigint terminates the script.
121-
try testWithTemporaryDirectory { tmpdir in
122-
let file = tmpdir.appending(component: "pidfile")
123-
let waitFile = tmpdir.appending(component: "waitFile")
124-
let process = Process(args: script("print-pid"), file.pathString, waitFile.pathString)
125-
try process.launch()
126-
guard waitForFile(waitFile) else {
127-
return XCTFail("Couldn't launch the process")
121+
DispatchQueue.global().async(group: group) {
122+
do {
123+
// Test sigint terminates the script.
124+
try testWithTemporaryDirectory { tmpdir in
125+
let file = tmpdir.appending(component: "pidfile")
126+
let waitFile = tmpdir.appending(component: "waitFile")
127+
let process = Process(args: self.script("print-pid"), file.pathString, waitFile.pathString)
128+
try process.launch()
129+
guard waitForFile(waitFile) else {
130+
return XCTFail("Couldn't launch the process")
131+
}
132+
// Ensure process has started running.
133+
guard try Process.running(process.processID) else {
134+
return XCTFail("Couldn't launch the process")
135+
}
136+
process.signal(SIGINT)
137+
try process.waitUntilExit()
138+
// Ensure the process's pid was written.
139+
let contents = try localFileSystem.readFileContents(file).description
140+
XCTAssertEqual("\(process.processID)", contents)
141+
XCTAssertFalse(try Process.running(process.processID))
142+
}
143+
} catch {
144+
XCTFail("\(error)")
128145
}
129-
// Ensure process has started running.
130-
XCTAssertTrue(try Process.running(process.processID))
131-
process.signal(SIGINT)
132-
try process.waitUntilExit()
133-
// Ensure the process's pid was written.
134-
let contents = try localFileSystem.readFileContents(file).description
135-
XCTAssertEqual("\(process.processID)", contents)
136-
XCTAssertFalse(try Process.running(process.processID))
137146
}
138147

139148
// Test SIGKILL terminates the subprocess and any of its subprocess.
140-
try testWithTemporaryDirectory { tmpdir in
141-
let file = tmpdir.appending(component: "pidfile")
142-
let waitFile = tmpdir.appending(component: "waitFile")
143-
let process = Process(args: script("subprocess"), file.pathString, waitFile.pathString)
144-
try process.launch()
145-
guard waitForFile(waitFile) else {
146-
return XCTFail("Couldn't launch the process")
147-
}
148-
// Ensure process has started running.
149-
XCTAssertTrue(try Process.running(process.processID))
150-
process.signal(SIGKILL)
151-
let result = try process.waitUntilExit()
152-
XCTAssertEqual(result.exitStatus, .signalled(signal: SIGKILL))
153-
let json = try JSON(bytes: localFileSystem.readFileContents(file))
154-
guard case let .dictionary(dict) = json,
155-
case let .int(parent)? = dict["parent"],
156-
case let .int(child)? = dict["child"] else {
157-
return XCTFail("Couldn't launch the process")
149+
DispatchQueue.global().async(group: group) {
150+
do {
151+
try testWithTemporaryDirectory { tmpdir in
152+
let file = tmpdir.appending(component: "pidfile")
153+
let waitFile = tmpdir.appending(component: "waitFile")
154+
let process = Process(args: self.script("subprocess"), file.pathString, waitFile.pathString)
155+
try process.launch()
156+
guard waitForFile(waitFile) else {
157+
return XCTFail("Couldn't launch the process")
158+
}
159+
// Ensure process has started running.
160+
guard try Process.running(process.processID) else {
161+
return XCTFail("Couldn't launch the process")
162+
}
163+
process.signal(SIGKILL)
164+
let result = try process.waitUntilExit()
165+
XCTAssertEqual(result.exitStatus, .signalled(signal: SIGKILL))
166+
let json = try JSON(bytes: localFileSystem.readFileContents(file))
167+
guard case let .dictionary(dict) = json,
168+
case let .int(parent)? = dict["parent"],
169+
case let .int(child)? = dict["child"] else {
170+
return XCTFail("Couldn't launch the process")
171+
}
172+
XCTAssertEqual(process.processID, ProcessID(parent))
173+
// We should have killed the process and any subprocess spawned by it.
174+
XCTAssertFalse(try Process.running(ProcessID(parent)))
175+
// FIXME: The child process becomes defunct when executing the tests using docker directly without entering the bash.
176+
XCTAssertFalse(try Process.running(ProcessID(child), orDefunct: true))
177+
}
178+
} catch {
179+
XCTFail("\(error)")
158180
}
159-
XCTAssertEqual(process.processID, ProcessID(parent))
160-
// We should have killed the process and any subprocess spawned by it.
161-
XCTAssertFalse(try Process.running(ProcessID(parent)))
162-
// FIXME: The child process becomes defunct when executing the tests using docker directly without entering the bash.
163-
XCTAssertFalse(try Process.running(ProcessID(child), orDefunct: true))
181+
}
182+
183+
if case .timedOut = group.wait(timeout: .now() + 1) {
184+
XCTFail("timeout waiting for signals to be processed")
164185
}
165186
}
166187
#endif

0 commit comments

Comments
 (0)