@@ -264,13 +264,7 @@ final class ServiceGroupTests: XCTestCase {
264264 await service3. resumeRunContinuation ( with: . success( ( ) ) )
265265
266266 // Waiting to see that the remaining is still running
267- service1. sendPing ( )
268- await XCTAsyncAssertEqual ( await eventIterator1. next ( ) , . runPing)
269-
270- // The first service should now receive the signal
271267 await XCTAsyncAssertEqual ( await eventIterator1. next ( ) , . shutdownGracefully)
272-
273- // Waiting to see that the one remaining are still running
274268 service1. sendPing ( )
275269 await XCTAsyncAssertEqual ( await eventIterator1. next ( ) , . runPing)
276270
@@ -1472,6 +1466,72 @@ final class ServiceGroupTests: XCTestCase {
14721466 }
14731467 }
14741468
1469+ func testTriggerGracefulShutdown_whenNestedGroup( ) async throws {
1470+ let service1 = MockService ( description: " Service1 " )
1471+ let service2 = MockService ( description: " Service2 " )
1472+ let service3 = MockService ( description: " Service3 " )
1473+ let innerServiceGroup = self . makeServiceGroup (
1474+ services: [ . init( service: service1) , . init( service: service2) , . init( service: service3) ]
1475+ )
1476+
1477+ var logger = Logger ( label: " Tests " )
1478+ logger. logLevel = . debug
1479+
1480+ let outerServiceGroup = ServiceGroup (
1481+ services: [ innerServiceGroup] ,
1482+ logger: logger
1483+ )
1484+
1485+ await withThrowingTaskGroup ( of: Void . self) { group in
1486+ group. addTask {
1487+ try await outerServiceGroup. run ( )
1488+ }
1489+
1490+ var eventIterator1 = service1. events. makeAsyncIterator ( )
1491+ await XCTAsyncAssertEqual ( await eventIterator1. next ( ) , . run)
1492+
1493+ var eventIterator2 = service2. events. makeAsyncIterator ( )
1494+ await XCTAsyncAssertEqual ( await eventIterator2. next ( ) , . run)
1495+
1496+ var eventIterator3 = service3. events. makeAsyncIterator ( )
1497+ await XCTAsyncAssertEqual ( await eventIterator3. next ( ) , . run)
1498+
1499+ await outerServiceGroup. triggerGracefulShutdown ( )
1500+
1501+ // The last service should receive the shutdown signal first
1502+ await XCTAsyncAssertEqual ( await eventIterator3. next ( ) , . shutdownGracefully)
1503+
1504+ // Waiting to see that all three are still running
1505+ service1. sendPing ( )
1506+ service2. sendPing ( )
1507+ service3. sendPing ( )
1508+ await XCTAsyncAssertEqual ( await eventIterator1. next ( ) , . runPing)
1509+ await XCTAsyncAssertEqual ( await eventIterator2. next ( ) , . runPing)
1510+ await XCTAsyncAssertEqual ( await eventIterator3. next ( ) , . runPing)
1511+
1512+ // Let's exit from the last service
1513+ await service3. resumeRunContinuation ( with: . success( ( ) ) )
1514+
1515+ // The middle service should now receive the signal
1516+ await XCTAsyncAssertEqual ( await eventIterator2. next ( ) , . shutdownGracefully)
1517+
1518+ // Waiting to see that the two remaining are still running
1519+ service1. sendPing ( )
1520+ service2. sendPing ( )
1521+ await XCTAsyncAssertEqual ( await eventIterator1. next ( ) , . runPing)
1522+ await XCTAsyncAssertEqual ( await eventIterator2. next ( ) , . runPing)
1523+
1524+ // Let's exit from the first service
1525+ await service1. resumeRunContinuation ( with: . success( ( ) ) )
1526+
1527+ // The middle service should now receive a cancellation
1528+ await XCTAsyncAssertEqual ( await eventIterator2. next ( ) , . runCancelled)
1529+
1530+ // Let's exit from the first service
1531+ await service2. resumeRunContinuation ( with: . success( ( ) ) )
1532+ }
1533+ }
1534+
14751535 // MARK: - Helpers
14761536
14771537 private func makeServiceGroup(
0 commit comments