@@ -264,13 +264,7 @@ final class ServiceGroupTests: XCTestCase {
264
264
await service3. resumeRunContinuation ( with: . success( ( ) ) )
265
265
266
266
// 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
271
267
await XCTAsyncAssertEqual ( await eventIterator1. next ( ) , . shutdownGracefully)
272
-
273
- // Waiting to see that the one remaining are still running
274
268
service1. sendPing ( )
275
269
await XCTAsyncAssertEqual ( await eventIterator1. next ( ) , . runPing)
276
270
@@ -1472,6 +1466,72 @@ final class ServiceGroupTests: XCTestCase {
1472
1466
}
1473
1467
}
1474
1468
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
+
1475
1535
// MARK: - Helpers
1476
1536
1477
1537
private func makeServiceGroup(
0 commit comments