@@ -1558,6 +1558,118 @@ public async Task Should_Return_Report_That_Marks_Failed_Tasks_As_Failed()
15581558 Assert . Equal ( CakeTaskExecutionStatus . Delegated , report . First ( e => e . TaskName == "A" ) . ExecutionStatus ) ;
15591559 Assert . Equal ( CakeTaskExecutionStatus . Failed , report . First ( e => e . TaskName == "B" ) . ExecutionStatus ) ;
15601560 }
1561+
1562+ [ Fact ]
1563+ public async Task Should_Throw_Exception_For_Circular_Dependencies ( )
1564+ {
1565+ // Given
1566+ var fixture = new CakeEngineFixture ( ) ;
1567+ var settings = new ExecutionSettings ( ) . SetTarget ( "B" ) ;
1568+ var engine = fixture . CreateEngine ( ) ;
1569+ engine . RegisterTask ( "B" ) . IsDependentOn ( "C" ) ;
1570+ engine . RegisterTask ( "C" ) . IsDependentOn ( "D" ) ;
1571+ engine . RegisterTask ( "D" ) . IsDependentOn ( "B" ) ;
1572+
1573+ // When
1574+ var result = await Record . ExceptionAsync ( ( ) => engine . RunTargetAsync ( fixture . Context , fixture . ExecutionStrategy , settings ) ) ;
1575+
1576+ // Then
1577+ Assert . IsType < CakeException > ( result ) ;
1578+ Assert . Equal ( "Graph contains circular references." , result ? . Message ) ;
1579+ }
1580+
1581+ [ Fact ]
1582+ public async Task Should_Throw_Exception_For_Circular_Dependencies_In_Parallel ( )
1583+ {
1584+ // Given
1585+ var fixture = new CakeEngineFixture ( ) ;
1586+ var settings = new ExecutionSettings ( ) . SetTarget ( "B" ) . RunInParallel ( ) ;
1587+ var engine = fixture . CreateEngine ( ) ;
1588+ engine . RegisterTask ( "B" ) . IsDependentOn ( "C" ) ;
1589+ engine . RegisterTask ( "C" ) . IsDependentOn ( "D" ) ;
1590+ engine . RegisterTask ( "D" ) . IsDependentOn ( "B" ) ;
1591+
1592+ // When
1593+ var result = await Record . ExceptionAsync ( ( ) => engine . RunTargetAsync ( fixture . Context , fixture . ExecutionStrategy , settings ) ) ;
1594+
1595+ // Then
1596+ Assert . IsType < CakeException > ( result ) ;
1597+ Assert . Equal ( "Graph contains circular references." , result ? . Message ) ;
1598+ }
1599+
1600+ [ Fact ]
1601+ public async Task Should_Execute_Tasks_In_Order_In_Parallel ( )
1602+ {
1603+ // Given
1604+ var result = new List < string > ( ) ;
1605+ var fixture = new CakeEngineFixture ( ) ;
1606+ var settings = new ExecutionSettings ( ) . SetTarget ( "E" ) . RunInParallel ( ) ;
1607+ var engine = fixture . CreateEngine ( ) ;
1608+ engine . RegisterTask ( "A" ) . Does ( ( ) => result . Add ( "A" ) ) ;
1609+ engine . RegisterTask ( "B" ) . IsDependentOn ( "A" ) . Does ( ( ) => result . Add ( "B" ) ) ;
1610+ engine . RegisterTask ( "C" ) . IsDependentOn ( "B" ) . Does ( ( ) => result . Add ( "C" ) ) ;
1611+ engine . RegisterTask ( "D" ) . IsDependentOn ( "C" ) . IsDependeeOf ( "E" ) . Does ( ( ) => { result . Add ( "D" ) ; } ) ;
1612+ engine . RegisterTask ( "E" ) . Does ( ( ) => { result . Add ( "E" ) ; } ) ;
1613+
1614+ // When
1615+ await engine . RunTargetAsync ( fixture . Context , fixture . ExecutionStrategy , settings ) ;
1616+
1617+ // Then
1618+ Assert . Equal ( 5 , result . Count ) ;
1619+ Assert . Equal ( "A" , result [ 0 ] ) ;
1620+ Assert . Equal ( "B" , result [ 1 ] ) ;
1621+ Assert . Equal ( "C" , result [ 2 ] ) ;
1622+ Assert . Equal ( "D" , result [ 3 ] ) ;
1623+ Assert . Equal ( "E" , result [ 4 ] ) ;
1624+ }
1625+
1626+ [ Fact ]
1627+ public async Task Should_Execute_Tasks_In_Parallel ( )
1628+ {
1629+ // Given
1630+ var result = new List < string > ( ) ;
1631+ var fixture = new CakeEngineFixture ( ) ;
1632+ var settings = new ExecutionSettings ( ) . SetTarget ( "E" ) . RunInParallel ( ) ;
1633+ var engine = fixture . CreateEngine ( ) ;
1634+ engine . RegisterTask ( "A" ) . Does ( ( ) => result . Add ( "A" ) ) ;
1635+ engine . RegisterTask ( "B" ) . IsDependentOn ( "A" ) . Does ( async ( ) => { await Task . Delay ( 20 ) ; result . Add ( "B" ) ; } ) ;
1636+ engine . RegisterTask ( "C" ) . IsDependentOn ( "A" ) . Does ( async ( ) => { await Task . Delay ( 5 ) ; result . Add ( "C" ) ; } ) ;
1637+ engine . RegisterTask ( "D" ) . IsDependentOn ( "A" ) . Does ( ( ) => result . Add ( "D" ) ) ;
1638+ engine . RegisterTask ( "E" ) . IsDependentOn ( "B" ) . IsDependentOn ( "C" ) . IsDependentOn ( "D" ) . Does ( ( ) => result . Add ( "E" ) ) ;
1639+
1640+ // When
1641+ await engine . RunTargetAsync ( fixture . Context , fixture . ExecutionStrategy , settings ) ;
1642+
1643+ // Then
1644+ Assert . Equal ( 5 , result . Count ) ;
1645+ Assert . Equal ( "A" , result [ 0 ] ) ;
1646+ Assert . Equal ( "D" , result [ 1 ] ) ;
1647+ Assert . Equal ( "C" , result [ 2 ] ) ;
1648+ Assert . Equal ( "B" , result [ 3 ] ) ;
1649+ Assert . Equal ( "E" , result [ 4 ] ) ;
1650+ }
1651+
1652+ [ Fact ]
1653+ public async Task Should_Not_Catch_Exceptions_From_Task_If_ContinueOnError_Is_Not_Set_In_Parallel ( )
1654+ {
1655+ // Given
1656+ var fixture = new CakeEngineFixture ( ) ;
1657+ var settings = new ExecutionSettings ( ) . SetTarget ( "E" ) . RunInParallel ( ) ;
1658+ var engine = fixture . CreateEngine ( ) ;
1659+ engine . RegisterTask ( "A" ) ;
1660+ engine . RegisterTask ( "B" ) . IsDependentOn ( "A" ) ;
1661+ engine . RegisterTask ( "C" ) . IsDependentOn ( "A" ) . Does ( ( ) => throw new InvalidOperationException ( "Whoopsie" ) ) ;
1662+ engine . RegisterTask ( "D" ) . IsDependentOn ( "A" ) ;
1663+ engine . RegisterTask ( "E" ) . IsDependentOn ( "B" ) . IsDependentOn ( "C" ) . IsDependentOn ( "D" ) ;
1664+
1665+ // When
1666+ var result = await Record . ExceptionAsync ( ( ) =>
1667+ engine . RunTargetAsync ( fixture . Context , fixture . ExecutionStrategy , settings ) ) ;
1668+
1669+ // Then
1670+ Assert . IsType < InvalidOperationException > ( result ) ;
1671+ Assert . Equal ( "Whoopsie" , result ? . Message ) ;
1672+ }
15611673 }
15621674
15631675 public sealed class TheSetupEvent
0 commit comments