@@ -155,6 +155,71 @@ extension IntegrationSuite {
155155 }
156156 }
157157
158+ func testMultipleConcurrentProcessesOutput( ) async throws {
159+ let id = " test-concurrent-processes-output "
160+
161+ let bs = try await bootstrap ( )
162+ let container = LinuxContainer (
163+ id,
164+ rootfs: bs. rootfs,
165+ vmm: bs. vmm
166+ )
167+ container. arguments = [ " /bin/sleep " , " 1000 " ]
168+
169+ do {
170+ try await container. create ( )
171+ try await container. start ( )
172+
173+ let execConfig = ContainerizationOCI . Process (
174+ args: [ " /bin/echo " , " hi " ] ,
175+ env: [ " PATH= \( LinuxContainer . defaultPath) " ]
176+ )
177+
178+ try await withThrowingTaskGroup ( of: Void . self) { group in
179+ for i in 0 ... 80 {
180+ let idx = i
181+ group. addTask {
182+ let buffer = BufferWriter ( )
183+
184+ var config = execConfig
185+ config. args [ 1 ] = " hi \( idx) "
186+
187+ let exec = try await container. exec (
188+ " exec- \( idx) " ,
189+ configuration: config,
190+ stdout: buffer,
191+ )
192+ try await exec. start ( )
193+
194+ let status = try await exec. wait ( )
195+ if status != 0 {
196+ throw IntegrationError . assert ( msg: " process status \( status) != 0 " )
197+ }
198+
199+ let output = String ( data: buffer. data, encoding: . utf8)
200+ guard output == " hi \( idx) \n " else {
201+ throw IntegrationError . assert (
202+ msg: " process should have returned on stdout 'hi \( idx) ' != ' \( output!) ) " )
203+ }
204+ try await exec. delete ( )
205+ }
206+ }
207+
208+ // wait for all the exec'd processes.
209+ try await group. waitForAll ( )
210+ print ( " all group processes exit " )
211+
212+ // kill the init process.
213+ try await container. kill ( SIGKILL)
214+ let status = try await container. wait ( )
215+ try await container. stop ( )
216+ print ( " \( status) " )
217+ }
218+ } catch {
219+ throw error
220+ }
221+ }
222+
158223 func testProcessUser( ) async throws {
159224 let id = " test-process-user "
160225
0 commit comments