( match: RegExp, timeout = 30000, )
| 213 | } |
| 214 | |
| 215 | export async function waitForAnyProcessOutputToMatch( |
| 216 | match: RegExp, |
| 217 | timeout = 30000, |
| 218 | ): Promise<ProcessOutput> { |
| 219 | let timeoutId: ReturnType<typeof setTimeout> | null = null; |
| 220 | |
| 221 | // Race between _all_ processes, and the timeout. First one to resolve/reject wins. |
| 222 | const timeoutPromise: Promise<ProcessOutput> = new Promise((_resolve, reject) => { |
| 223 | // Wait for 30 seconds and timeout. |
| 224 | timeoutId = setTimeout(() => { |
| 225 | reject(new Error(`Waiting for ${match} timed out (timeout: ${timeout}msec)...`)); |
| 226 | }, timeout); |
| 227 | }); |
| 228 | |
| 229 | const matchPromises: Promise<ProcessOutput>[] = _processes.map( |
| 230 | (childProcess) => |
| 231 | new Promise((resolve) => { |
| 232 | let stdout = ''; |
| 233 | let stderr = ''; |
| 234 | |
| 235 | childProcess.stdout!.on('data', (data: Buffer) => { |
| 236 | stdout += data.toString(); |
| 237 | if (stripVTControlCharacters(stdout).match(match)) { |
| 238 | resolve({ stdout, stderr }); |
| 239 | } |
| 240 | }); |
| 241 | |
| 242 | childProcess.stderr!.on('data', (data: Buffer) => { |
| 243 | stderr += data.toString(); |
| 244 | if (stripVTControlCharacters(stderr).match(match)) { |
| 245 | resolve({ stdout, stderr }); |
| 246 | } |
| 247 | }); |
| 248 | }), |
| 249 | ); |
| 250 | |
| 251 | const matchingProcess = await Promise.race(matchPromises.concat([timeoutPromise])); |
| 252 | if (timeoutId !== null) { |
| 253 | clearTimeout(timeoutId); |
| 254 | } |
| 255 | return matchingProcess; |
| 256 | } |
| 257 | |
| 258 | /** |
| 259 | * Kills a process by PID |
no test coverage detected