@@ -1866,6 +1866,97 @@ public async Task StartDownloadsAsync_SinglePart_ReturnsImmediatelyWithoutBackgr
18661866
18671867 #region Capacity Checking Tests
18681868
1869+ [ TestMethod ]
1870+ public async Task Discovery_PartStrategy_CallsWaitForCapacityAsync ( )
1871+ {
1872+ // Arrange - PART strategy should check capacity during discovery
1873+ var capacityCallCount = 0 ;
1874+ var mockDataHandler = new Mock < IPartDataHandler > ( ) ;
1875+
1876+ mockDataHandler
1877+ . Setup ( x => x . WaitForCapacityAsync ( It . IsAny < CancellationToken > ( ) ) )
1878+ . Returns ( ( ) =>
1879+ {
1880+ Interlocked . Increment ( ref capacityCallCount ) ;
1881+ return Task . CompletedTask ;
1882+ } ) ;
1883+
1884+ mockDataHandler
1885+ . Setup ( x => x . ProcessPartAsync ( It . IsAny < int > ( ) , It . IsAny < GetObjectResponse > ( ) , It . IsAny < CancellationToken > ( ) ) )
1886+ . Returns ( Task . CompletedTask ) ;
1887+
1888+ var totalObjectSize = 24 * 1024 * 1024 ; // 24MB -> 3 parts @ 8MB
1889+ var partSize = 8 * 1024 * 1024 ; // 8MB
1890+ var totalParts = 3 ;
1891+
1892+ var mockResponse = MultipartDownloadTestHelpers . CreateMultipartFirstPartResponse (
1893+ partSize , totalParts , totalObjectSize , "test-etag" ) ;
1894+
1895+ var mockClient = MultipartDownloadTestHelpers . CreateMockS3Client (
1896+ ( req , ct ) => Task . FromResult ( mockResponse ) ) ;
1897+
1898+ var request = MultipartDownloadTestHelpers . CreateOpenStreamRequest (
1899+ downloadType : MultipartDownloadType . PART ) ;
1900+ var config = MultipartDownloadTestHelpers . CreateBufferedDownloadConfiguration ( ) ;
1901+ var coordinator = new MultipartDownloadManager (
1902+ mockClient . Object , request , config , mockDataHandler . Object ) ;
1903+
1904+ // Act
1905+ var result = await coordinator . StartDownloadAsync ( null , CancellationToken . None ) ;
1906+
1907+ // Assert
1908+ Assert . IsNotNull ( result ) ;
1909+ Assert . AreEqual ( 3 , result . TotalParts ) ;
1910+ Assert . AreEqual ( 1 , capacityCallCount ,
1911+ "PART strategy should call WaitForCapacityAsync during Part 1 discovery" ) ;
1912+ }
1913+
1914+
1915+ [ TestMethod ]
1916+ public async Task Discovery_RangeStrategy_CallsWaitForCapacityAsync ( )
1917+ {
1918+ // Arrange - RANGE strategy should also check capacity during discovery
1919+ var capacityCallCount = 0 ;
1920+ var mockDataHandler = new Mock < IPartDataHandler > ( ) ;
1921+
1922+ mockDataHandler
1923+ . Setup ( x => x . WaitForCapacityAsync ( It . IsAny < CancellationToken > ( ) ) )
1924+ . Returns ( ( ) =>
1925+ {
1926+ Interlocked . Increment ( ref capacityCallCount ) ;
1927+ return Task . CompletedTask ;
1928+ } ) ;
1929+
1930+ mockDataHandler
1931+ . Setup ( x => x . ProcessPartAsync ( It . IsAny < int > ( ) , It . IsAny < GetObjectResponse > ( ) , It . IsAny < CancellationToken > ( ) ) )
1932+ . Returns ( Task . CompletedTask ) ;
1933+
1934+ var totalObjectSize = 17 * 1024 * 1024 ; // 17MB -> 3 parts @ 8MB
1935+ var partSize = 8 * 1024 * 1024 ; // 8MB
1936+
1937+ var mockResponse = MultipartDownloadTestHelpers . CreateRangeResponse (
1938+ 0 , partSize - 1 , totalObjectSize , "test-etag" ) ;
1939+
1940+ var mockClient = MultipartDownloadTestHelpers . CreateMockS3Client (
1941+ ( req , ct ) => Task . FromResult ( mockResponse ) ) ;
1942+
1943+ var request = MultipartDownloadTestHelpers . CreateOpenStreamRequest (
1944+ partSize : partSize ,
1945+ downloadType : MultipartDownloadType . RANGE ) ;
1946+ var config = MultipartDownloadTestHelpers . CreateBufferedDownloadConfiguration ( ) ;
1947+ var coordinator = new MultipartDownloadManager (
1948+ mockClient . Object , request , config , mockDataHandler . Object ) ;
1949+
1950+ // Act
1951+ var result = await coordinator . StartDownloadAsync ( null , CancellationToken . None ) ;
1952+
1953+ // Assert
1954+ Assert . IsNotNull ( result ) ;
1955+ Assert . AreEqual ( 3 , result . TotalParts ) ; // 17MB / 8MB = 3 parts (ceiling)
1956+ Assert . AreEqual ( 1 , capacityCallCount ,
1957+ "RANGE strategy should call WaitForCapacityAsync during Part 1 discovery" ) ;
1958+ }
1959+
18691960 [ TestMethod ]
18701961 public async Task MultipleDownloads_WithSharedHttpThrottler_RespectsLimits ( )
18711962 {
@@ -2077,50 +2168,6 @@ public async Task Discovery_SinglePart_StillCallsCapacityCheck()
20772168 "Even single-part downloads should call WaitForCapacityAsync during discovery" ) ;
20782169 }
20792170
2080- [ TestMethod ]
2081- public async Task Discovery_RangeStrategy_CallsWaitForCapacityAsync ( )
2082- {
2083- // Arrange - RANGE strategy should also check capacity during discovery
2084- var capacityCallCount = 0 ;
2085- var mockDataHandler = new Mock < IPartDataHandler > ( ) ;
2086-
2087- mockDataHandler
2088- . Setup ( x => x . WaitForCapacityAsync ( It . IsAny < CancellationToken > ( ) ) )
2089- . Returns ( ( ) =>
2090- {
2091- Interlocked . Increment ( ref capacityCallCount ) ;
2092- return Task . CompletedTask ;
2093- } ) ;
2094-
2095- mockDataHandler
2096- . Setup ( x => x . ProcessPartAsync ( It . IsAny < int > ( ) , It . IsAny < GetObjectResponse > ( ) , It . IsAny < CancellationToken > ( ) ) )
2097- . Returns ( Task . CompletedTask ) ;
2098-
2099- var totalObjectSize = 17 * 1024 * 1024 ; // 17MB -> 3 parts @ 8MB
2100- var partSize = 8 * 1024 * 1024 ; // 8MB
2101-
2102- var mockResponse = MultipartDownloadTestHelpers . CreateRangeResponse (
2103- 0 , partSize - 1 , totalObjectSize , "test-etag" ) ;
2104-
2105- var mockClient = MultipartDownloadTestHelpers . CreateMockS3Client (
2106- ( req , ct ) => Task . FromResult ( mockResponse ) ) ;
2107-
2108- var request = MultipartDownloadTestHelpers . CreateOpenStreamRequest (
2109- partSize : partSize ,
2110- downloadType : MultipartDownloadType . RANGE ) ;
2111- var config = MultipartDownloadTestHelpers . CreateBufferedDownloadConfiguration ( ) ;
2112- var coordinator = new MultipartDownloadManager (
2113- mockClient . Object , request , config , mockDataHandler . Object ) ;
2114-
2115- // Act
2116- var result = await coordinator . StartDownloadAsync ( null , CancellationToken . None ) ;
2117-
2118- // Assert
2119- Assert . IsNotNull ( result ) ;
2120- Assert . AreEqual ( 3 , result . TotalParts ) ; // 17MB / 8MB = 3 parts (ceiling)
2121- Assert . AreEqual ( 1 , capacityCallCount ,
2122- "RANGE strategy should call WaitForCapacityAsync during Part 1 discovery" ) ;
2123- }
21242171
21252172 #endregion
21262173
0 commit comments