@@ -707,7 +707,7 @@ final class ServiceGroupTests: XCTestCase {
707
707
gracefulShutdownSignals: [ . sigalrm]
708
708
)
709
709
710
- await withThrowingTaskGroup ( of: Void . self) { group in
710
+ try await withThrowingTaskGroup ( of: Void . self) { group in
711
711
group. addTask {
712
712
try await serviceGroup. run ( )
713
713
}
@@ -748,13 +748,85 @@ final class ServiceGroupTests: XCTestCase {
748
748
await XCTAsyncAssertEqual ( await eventIterator2. next ( ) , . runPing)
749
749
750
750
// Let's throw from the middle service
751
- await service2. resumeRunContinuation ( with: . failure( CancellationError ( ) ) )
751
+ await service2. resumeRunContinuation ( with: . failure( ExampleError ( ) ) )
752
752
753
753
// The first service should now receive a cancellation
754
754
await XCTAsyncAssertEqual ( await eventIterator1. next ( ) , . runCancelled)
755
755
756
756
// Let's exit from the first service
757
757
await service1. resumeRunContinuation ( with: . success( ( ) ) )
758
+
759
+ try await XCTAsyncAssertThrowsError ( await group. next ( ) ) {
760
+ XCTAssertTrue ( $0 is ExampleError )
761
+ }
762
+ }
763
+ }
764
+
765
+ func testGracefulShutdownOrdering_whenServiceThrows_andServiceGracefullyShutsdown( ) async throws {
766
+ let service1 = MockService ( description: " Service1 " )
767
+ let service2 = MockService ( description: " Service2 " )
768
+ let service3 = MockService ( description: " Service3 " )
769
+ let serviceGroup = self . makeServiceGroup (
770
+ services: [
771
+ . init( service: service1) ,
772
+ . init( service: service2, failureTerminationBehavior: . gracefullyShutdownGroup) ,
773
+ . init( service: service3)
774
+ ] ,
775
+ gracefulShutdownSignals: [ . sigalrm]
776
+ )
777
+
778
+ try await withThrowingTaskGroup ( of: Void . self) { group in
779
+ group. addTask {
780
+ try await serviceGroup. run ( )
781
+ }
782
+
783
+ var eventIterator1 = service1. events. makeAsyncIterator ( )
784
+ await XCTAsyncAssertEqual ( await eventIterator1. next ( ) , . run)
785
+
786
+ var eventIterator2 = service2. events. makeAsyncIterator ( )
787
+ await XCTAsyncAssertEqual ( await eventIterator2. next ( ) , . run)
788
+
789
+ var eventIterator3 = service3. events. makeAsyncIterator ( )
790
+ await XCTAsyncAssertEqual ( await eventIterator3. next ( ) , . run)
791
+
792
+ let pid = getpid ( )
793
+ kill ( pid, UnixSignal . sigalrm. rawValue)
794
+
795
+ // The last service should receive the shutdown signal first
796
+ await XCTAsyncAssertEqual ( await eventIterator3. next ( ) , . shutdownGracefully)
797
+
798
+ // Waiting to see that all three are still running
799
+ service1. sendPing ( )
800
+ service2. sendPing ( )
801
+ service3. sendPing ( )
802
+ await XCTAsyncAssertEqual ( await eventIterator1. next ( ) , . runPing)
803
+ await XCTAsyncAssertEqual ( await eventIterator2. next ( ) , . runPing)
804
+ await XCTAsyncAssertEqual ( await eventIterator3. next ( ) , . runPing)
805
+
806
+ // Let's exit from the last service
807
+ await service3. resumeRunContinuation ( with: . success( ( ) ) )
808
+
809
+ // The middle service should now receive the signal
810
+ await XCTAsyncAssertEqual ( await eventIterator2. next ( ) , . shutdownGracefully)
811
+
812
+ // Waiting to see that the two remaining are still running
813
+ service1. sendPing ( )
814
+ service2. sendPing ( )
815
+ await XCTAsyncAssertEqual ( await eventIterator1. next ( ) , . runPing)
816
+ await XCTAsyncAssertEqual ( await eventIterator2. next ( ) , . runPing)
817
+
818
+ // Let's throw from the middle service
819
+ await service2. resumeRunContinuation ( with: . failure( ExampleError ( ) ) )
820
+
821
+ // The first service should now receive a cancellation
822
+ await XCTAsyncAssertEqual ( await eventIterator1. next ( ) , . shutdownGracefully)
823
+
824
+ // Let's exit from the first service
825
+ await service1. resumeRunContinuation ( with: . success( ( ) ) )
826
+
827
+ try await XCTAsyncAssertThrowsError ( await group. next ( ) ) {
828
+ XCTAssertTrue ( $0 is ExampleError )
829
+ }
758
830
}
759
831
}
760
832
@@ -881,7 +953,9 @@ final class ServiceGroupTests: XCTestCase {
881
953
// Let's throw from the first service
882
954
await service1. resumeRunContinuation ( with: . failure( ExampleError ( ) ) )
883
955
884
- await XCTAsyncAssertNoThrow ( try await group. next ( ) )
956
+ try await XCTAsyncAssertThrowsError ( await group. next ( ) ) {
957
+ XCTAssertTrue ( $0 is ExampleError )
958
+ }
885
959
}
886
960
}
887
961
0 commit comments