@@ -2284,7 +2284,7 @@ public async Task HttpSemaphore_RangeStrategy_HeldThroughProcessPartAsync()
22842284 #region Semaphore Release Error Path Tests
22852285
22862286 [ TestMethod ]
2287- public async Task StartDownloadAsync_WaitForCapacityFails_DoesNotReleaseHttpSemaphore ( )
2287+ public async Task Discovery_WaitForCapacityFails_DoesNotReleaseHttpSemaphore ( )
22882288 {
22892289 // Arrange - Test that semaphore is NOT released when it was never acquired
22902290 var httpThrottler = new SemaphoreSlim ( 2 , 2 ) ;
@@ -2323,8 +2323,9 @@ public async Task StartDownloadAsync_WaitForCapacityFails_DoesNotReleaseHttpSema
23232323 }
23242324
23252325
2326+
23262327 [ TestMethod ]
2327- public async Task Discovery_WaitForCapacityFails_DoesNotReleaseHttpSemaphore ( )
2328+ public async Task StartDownloadAsync_WaitForCapacityFails_DoesNotReleaseHttpSemaphore ( )
23282329 {
23292330 // Arrange - Test that semaphore is NOT released when it was never acquired
23302331 var httpThrottler = new SemaphoreSlim ( 2 , 2 ) ;
@@ -2362,8 +2363,6 @@ public async Task Discovery_WaitForCapacityFails_DoesNotReleaseHttpSemaphore()
23622363 httpThrottler . Dispose ( ) ;
23632364 }
23642365
2365-
2366-
23672366 [ TestMethod ]
23682367 public async Task Discovery_HttpRequestAfterCapacityFails_ReleasesHttpSemaphore ( )
23692368 {
@@ -2460,53 +2459,6 @@ public async Task StartDownloadAsync_PrepareAsyncFails_ReleasesHttpSemaphore()
24602459 httpThrottler . Dispose ( ) ;
24612460 }
24622461
2463- [ TestMethod ]
2464- public async Task StartDownloadAsync_Part1ProcessingFails_ReleasesHttpSemaphore ( )
2465- {
2466- // Arrange - Test that HTTP semaphore is released when Part 1 processing fails during discovery
2467- var httpThrottler = new SemaphoreSlim ( 2 , 2 ) ;
2468- var initialCount = httpThrottler . CurrentCount ;
2469-
2470- var mockDataHandler = new Mock < IPartDataHandler > ( ) ;
2471-
2472- // WaitForCapacityAsync succeeds
2473- mockDataHandler
2474- . Setup ( x => x . WaitForCapacityAsync ( It . IsAny < CancellationToken > ( ) ) )
2475- . Returns ( Task . CompletedTask ) ;
2476-
2477- // Part 1 ProcessPartAsync FAILS (during discovery phase of StartDownloadAsync)
2478- mockDataHandler
2479- . Setup ( x => x . ProcessPartAsync ( 1 , It . IsAny < GetObjectResponse > ( ) , It . IsAny < CancellationToken > ( ) ) )
2480- . ThrowsAsync ( new InvalidOperationException ( "Simulated Part 1 processing failure" ) ) ;
2481-
2482- var mockClient = MultipartDownloadTestHelpers . CreateMockS3ClientForMultipart (
2483- 2 , 8 * 1024 * 1024 , 16 * 1024 * 1024 , "test-etag" , usePartStrategy : true ) ;
2484-
2485- var request = MultipartDownloadTestHelpers . CreateOpenStreamRequest (
2486- downloadType : MultipartDownloadType . PART ) ;
2487- var config = MultipartDownloadTestHelpers . CreateBufferedDownloadConfiguration ( ) ;
2488- var coordinator = new MultipartDownloadManager (
2489- mockClient . Object , request , config , mockDataHandler . Object , null , httpThrottler ) ;
2490-
2491- // Act & Assert
2492- try
2493- {
2494- await coordinator . StartDownloadAsync ( null , CancellationToken . None ) ;
2495- Assert . Fail ( "Expected InvalidOperationException to be thrown" ) ;
2496- }
2497- catch ( InvalidOperationException ex )
2498- {
2499- Assert . AreEqual ( "Simulated Part 1 processing failure" , ex . Message ) ;
2500- }
2501-
2502- // Assert - HTTP semaphore should be released when Part 1 processing fails
2503- Assert . AreEqual ( initialCount , httpThrottler . CurrentCount ,
2504- "HTTP semaphore should be released when Part 1 processing fails during discovery" ) ;
2505-
2506- // Cleanup
2507- httpThrottler . Dispose ( ) ;
2508- }
2509-
25102462 [ TestMethod ]
25112463 public async Task StartDownloadAsync_BackgroundPartHttpFails_ReleasesHttpSemaphore ( )
25122464 {
@@ -2573,6 +2525,53 @@ public async Task StartDownloadAsync_BackgroundPartHttpFails_ReleasesHttpSemapho
25732525 httpThrottler . Dispose ( ) ;
25742526 }
25752527
2528+ [ TestMethod ]
2529+ public async Task StartDownloadAsync_Part1ProcessingFails_ReleasesHttpSemaphore ( )
2530+ {
2531+ // Arrange - Test that HTTP semaphore is released when Part 1 processing fails during discovery
2532+ var httpThrottler = new SemaphoreSlim ( 2 , 2 ) ;
2533+ var initialCount = httpThrottler . CurrentCount ;
2534+
2535+ var mockDataHandler = new Mock < IPartDataHandler > ( ) ;
2536+
2537+ // WaitForCapacityAsync succeeds
2538+ mockDataHandler
2539+ . Setup ( x => x . WaitForCapacityAsync ( It . IsAny < CancellationToken > ( ) ) )
2540+ . Returns ( Task . CompletedTask ) ;
2541+
2542+ // Part 1 ProcessPartAsync FAILS (during discovery phase of StartDownloadAsync)
2543+ mockDataHandler
2544+ . Setup ( x => x . ProcessPartAsync ( 1 , It . IsAny < GetObjectResponse > ( ) , It . IsAny < CancellationToken > ( ) ) )
2545+ . ThrowsAsync ( new InvalidOperationException ( "Simulated Part 1 processing failure" ) ) ;
2546+
2547+ var mockClient = MultipartDownloadTestHelpers . CreateMockS3ClientForMultipart (
2548+ 2 , 8 * 1024 * 1024 , 16 * 1024 * 1024 , "test-etag" , usePartStrategy : true ) ;
2549+
2550+ var request = MultipartDownloadTestHelpers . CreateOpenStreamRequest (
2551+ downloadType : MultipartDownloadType . PART ) ;
2552+ var config = MultipartDownloadTestHelpers . CreateBufferedDownloadConfiguration ( ) ;
2553+ var coordinator = new MultipartDownloadManager (
2554+ mockClient . Object , request , config , mockDataHandler . Object , null , httpThrottler ) ;
2555+
2556+ // Act & Assert
2557+ try
2558+ {
2559+ await coordinator . StartDownloadAsync ( null , CancellationToken . None ) ;
2560+ Assert . Fail ( "Expected InvalidOperationException to be thrown" ) ;
2561+ }
2562+ catch ( InvalidOperationException ex )
2563+ {
2564+ Assert . AreEqual ( "Simulated Part 1 processing failure" , ex . Message ) ;
2565+ }
2566+
2567+ // Assert - HTTP semaphore should be released when Part 1 processing fails
2568+ Assert . AreEqual ( initialCount , httpThrottler . CurrentCount ,
2569+ "HTTP semaphore should be released when Part 1 processing fails during discovery" ) ;
2570+
2571+ // Cleanup
2572+ httpThrottler . Dispose ( ) ;
2573+ }
2574+
25762575 [ TestMethod ]
25772576 public async Task StartDownloadAsync_BackgroundPartProcessingFails_ReleasesHttpSemaphore ( )
25782577 {
0 commit comments