@@ -433,7 +433,7 @@ final class ServiceGroupTests: XCTestCase {
433433 ]
434434 )
435435
436- await withThrowingTaskGroup ( of: Void . self) { group in
436+ try await withThrowingTaskGroup ( of: Void . self) { group in
437437 group. addTask {
438438 try await serviceGroup. run ( )
439439 }
@@ -474,6 +474,71 @@ final class ServiceGroupTests: XCTestCase {
474474
475475 // Let's exit from the first service
476476 await service1. resumeRunContinuation ( with: . success( ( ) ) )
477+
478+ try await XCTAsyncAssertThrowsError ( await group. next ( ) ) {
479+ XCTAssertTrue ( $0 is ExampleError )
480+ }
481+ }
482+ }
483+
484+ func testRun_whenServiceThrows_andShutdownGracefully_andOtherServiceThrows( ) async throws {
485+ let service1 = MockService ( description: " Service1 " )
486+ let service2 = MockService ( description: " Service2 " )
487+ let service3 = MockService ( description: " Service3 " )
488+ let serviceGroup = self . makeServiceGroup (
489+ services: [
490+ . init( service: service1) ,
491+ . init( service: service2, failureTerminationBehavior: . gracefullyShutdownGroup) ,
492+ . init( service: service3) ,
493+ ]
494+ )
495+
496+ try await withThrowingTaskGroup ( of: Void . self) { group in
497+ group. addTask {
498+ try await serviceGroup. run ( )
499+ }
500+
501+ var eventIterator1 = service1. events. makeAsyncIterator ( )
502+ await XCTAsyncAssertEqual ( await eventIterator1. next ( ) , . run)
503+
504+ var eventIterator2 = service2. events. makeAsyncIterator ( )
505+ await XCTAsyncAssertEqual ( await eventIterator2. next ( ) , . run)
506+
507+ var eventIterator3 = service3. events. makeAsyncIterator ( )
508+ await XCTAsyncAssertEqual ( await eventIterator3. next ( ) , . run)
509+
510+ await service2. resumeRunContinuation ( with: . failure( ExampleError ( ) ) )
511+
512+ // The last service should receive the shutdown signal first
513+ await XCTAsyncAssertEqual ( await eventIterator3. next ( ) , . shutdownGracefully)
514+
515+ // Waiting to see that all two are still running
516+ service1. sendPing ( )
517+ service3. sendPing ( )
518+ await XCTAsyncAssertEqual ( await eventIterator1. next ( ) , . runPing)
519+ await XCTAsyncAssertEqual ( await eventIterator3. next ( ) , . runPing)
520+
521+ // Let's exit from the last service
522+ await service3. resumeRunContinuation ( with: . success( ( ) ) )
523+
524+ // Waiting to see that the remaining is still running
525+ service1. sendPing ( )
526+ await XCTAsyncAssertEqual ( await eventIterator1. next ( ) , . runPing)
527+
528+ // The first service should now receive the signal
529+ await XCTAsyncAssertEqual ( await eventIterator1. next ( ) , . shutdownGracefully)
530+
531+ // Waiting to see that the one remaining are still running
532+ service1. sendPing ( )
533+ await XCTAsyncAssertEqual ( await eventIterator1. next ( ) , . runPing)
534+
535+ // Let's throw from this service as well
536+ struct OtherError : Error { }
537+ await service1. resumeRunContinuation ( with: . failure( OtherError ( ) ) )
538+
539+ try await XCTAsyncAssertThrowsError ( await group. next ( ) ) {
540+ XCTAssertTrue ( $0 is ExampleError )
541+ }
477542 }
478543 }
479544
0 commit comments