@@ -859,9 +859,10 @@ public async Task StartDownloadsAsync_MultipartDownload_DoesNotCallWaitForCapaci
859859 }
860860
861861 [ TestMethod ]
862- public async Task StartDownloadsAsync_BackgroundTask_PreAcquiresCapacityBeforeCreatingTasks ( )
862+ public async Task StartDownloadsAsync_BackgroundTask_InterleavesCapacityAcquisitionWithTaskCreation ( )
863863 {
864- // Arrange - Test that background task pre-acquires all capacity before creating download tasks
864+ // Arrange - Test that background task interleaves capacity acquisition with task creation
865+ // This ensures sequential ordering: capacity(2) → task(2) → capacity(3) → task(3)
865866 var totalParts = 3 ;
866867 var partSize = 8 * 1024 * 1024 ;
867868 var totalObjectSize = totalParts * partSize ;
@@ -879,7 +880,8 @@ public async Task StartDownloadsAsync_BackgroundTask_PreAcquiresCapacityBeforeCr
879880 {
880881 lock ( lockObject )
881882 {
882- var partNum = operationOrder . Count ( o => o . operation == "capacity" ) + 2 ; // Parts 2, 3
883+ // Capacity is now acquired for Parts 1, 2, 3 (Part 1 during discovery)
884+ var partNum = operationOrder . Count ( o => o . operation == "capacity" ) + 1 ;
883885 operationOrder . Add ( ( "capacity" , partNum , operationCounter ++ ) ) ;
884886 }
885887 return Task . CompletedTask ;
@@ -919,27 +921,56 @@ public async Task StartDownloadsAsync_BackgroundTask_PreAcquiresCapacityBeforeCr
919921 var capacityOps = operationOrder . Where ( o => o . operation == "capacity" ) . ToList ( ) ;
920922 var taskOps = operationOrder . Where ( o => o . operation == "task" ) . ToList ( ) ;
921923
922- Assert . AreEqual ( 3 , capacityOps . Count , "Should acquire capacity discovery part 1 and for parts 2-3 " ) ;
924+ Assert . AreEqual ( 3 , capacityOps . Count , "Should acquire capacity for parts 1 (discovery), 2, 3 (background) " ) ;
923925 Assert . AreEqual ( 3 , taskOps . Count , "Should create tasks for parts 1-3" ) ;
924926
925- // Verify all capacity acquisitions happened before any task creation
926- // Find the highest sequence number among capacity operations
927- var lastCapacitySequence = capacityOps . Max ( o => o . sequence ) ;
927+ // Verify Part 1: capacity → task (during discovery)
928+ var part1Capacity = capacityOps . FirstOrDefault ( o => o . partNum == 1 ) ;
929+ var part1Task = taskOps . FirstOrDefault ( o => o . partNum == 1 ) ;
930+ Assert . IsNotNull ( part1Capacity , "Part 1 capacity should be acquired during discovery" ) ;
931+ Assert . IsNotNull ( part1Task , "Part 1 should be processed" ) ;
932+ Assert . IsTrue ( part1Capacity . sequence < part1Task . sequence ,
933+ "Part 1 capacity should be acquired before Part 1 task" ) ;
928934
929- // Find the lowest sequence number among task operations
930- var firstTaskSequence = taskOps . Min ( o => o . sequence ) ;
935+ // Verify interleaved pattern for background parts (2, 3)
936+ // For each background part: capacity(N) → task(N) → capacity(N+1) → task(N+1)
937+ for ( int partNum = 2 ; partNum <= totalParts ; partNum ++ )
938+ {
939+ var capacity = capacityOps . FirstOrDefault ( o => o . partNum == partNum ) ;
940+ var task = taskOps . FirstOrDefault ( o => o . partNum == partNum ) ;
941+
942+ Assert . IsNotNull ( capacity , $ "Part { partNum } capacity should be acquired") ;
943+ Assert . IsNotNull ( task , $ "Part { partNum } task should be created") ;
944+
945+ // Verify capacity comes before task for this part
946+ Assert . IsTrue ( capacity . sequence < task . sequence ,
947+ $ "Part { partNum } capacity (seq={ capacity . sequence } ) should come before task (seq={ task . sequence } )") ;
948+
949+ // Verify interleaving: task(N) should come before capacity(N+1)
950+ if ( partNum < totalParts )
951+ {
952+ var nextCapacity = capacityOps . FirstOrDefault ( o => o . partNum == partNum + 1 ) ;
953+ Assert . IsNotNull ( nextCapacity , $ "Part { partNum + 1 } capacity should exist") ;
954+ Assert . IsTrue ( task . sequence < nextCapacity . sequence ,
955+ $ "Part { partNum } task (seq={ task . sequence } ) should come before Part { partNum + 1 } capacity (seq={ nextCapacity . sequence } )") ;
956+ }
957+ }
931958
932- // All capacity must be acquired (have lower sequence numbers) before tasks start
933- Assert . IsTrue ( lastCapacitySequence < firstTaskSequence ,
934- $ "All capacity acquisitions must complete before task creation. " +
935- $ "Last capacity sequence: { lastCapacitySequence } , First task sequence: { firstTaskSequence } . " +
936- $ "Operations: { string . Join ( ", " , operationOrder . Select ( o => $ "{ o . operation } ({ o . partNum } )={ o . sequence } ") ) } ") ;
959+ // Verify overall sequential pattern: capacity(1) → task(1) → capacity(2) → task(2) → capacity(3) → task(3)
960+ var expectedPattern = new [ ]
961+ {
962+ ( "capacity" , 1 ) , ( "task" , 1 ) ,
963+ ( "capacity" , 2 ) , ( "task" , 2 ) ,
964+ ( "capacity" , 3 ) , ( "task" , 3 )
965+ } ;
937966
938- // Additional verification: Part 1 should be first task (processed during StartDownloadsAsync)
939- var part1Task = taskOps . FirstOrDefault ( o => o . partNum == 1 ) ;
940- Assert . IsNotNull ( part1Task , "Part 1 should be processed" ) ;
941- Assert . IsTrue ( part1Task . sequence < lastCapacitySequence ,
942- "Part 1 should be processed before capacity acquisition for background parts" ) ;
967+ for ( int i = 0 ; i < expectedPattern . Length ; i ++ )
968+ {
969+ Assert . AreEqual ( expectedPattern [ i ] . Item1 , operationOrder [ i ] . operation ,
970+ $ "Operation { i } should be { expectedPattern [ i ] . Item1 } ") ;
971+ Assert . AreEqual ( expectedPattern [ i ] . Item2 , operationOrder [ i ] . partNum ,
972+ $ "Operation { i } should be for part { expectedPattern [ i ] . Item2 } ") ;
973+ }
943974 }
944975 }
945976
0 commit comments