From b8f6ed8aceae1724d0f2ce589b2ef8fb429894c4 Mon Sep 17 00:00:00 2001 From: Isabelle Date: Mon, 5 May 2025 14:49:18 -0700 Subject: [PATCH 01/16] potential fault injection fix --- .../storage/blob/specialized/HttpFaultInjectingTests.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/HttpFaultInjectingTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/HttpFaultInjectingTests.java index 565a9b7e44e2..271791ad3773 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/HttpFaultInjectingTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/HttpFaultInjectingTests.java @@ -155,7 +155,8 @@ public void downloadToFileWithFaultInjection() throws IOException, InterruptedEx countDownLatch.await(10, TimeUnit.MINUTES); - assertTrue(successCount.get() >= 450); + assertTrue(successCount.get() >= 450, + () -> "Expected over 450 successes, actual success count was: " + successCount.get()); // cleanup files.forEach(it -> { try { @@ -170,8 +171,8 @@ public void downloadToFileWithFaultInjection() throws IOException, InterruptedEx private HttpClient getFaultInjectingWrappedHttpClient() { switch (ENVIRONMENT.getHttpClientType()) { case NETTY: - return HttpClient.createDefault(new HttpClientOptions().readTimeout(Duration.ofSeconds(2)) - .responseTimeout(Duration.ofSeconds(2)) + return HttpClient.createDefault(new HttpClientOptions().readTimeout(Duration.ofSeconds(4)) + .responseTimeout(Duration.ofSeconds(4)) .setHttpClientProvider(NettyAsyncHttpClientProvider.class)); case OK_HTTP: From 54ad6a8db2e33719b25c572a5a629fff6dfe88f5 Mon Sep 17 00:00:00 2001 From: Isabelle Date: Mon, 5 May 2025 15:07:24 -0700 Subject: [PATCH 02/16] removing redundant class --- .../specialized/HttpFaultInjectingTests.java | 98 +------------------ 1 file changed, 2 insertions(+), 96 deletions(-) diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/HttpFaultInjectingTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/HttpFaultInjectingTests.java index 271791ad3773..3f240b1cd00d 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/HttpFaultInjectingTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/HttpFaultInjectingTests.java @@ -6,8 +6,6 @@ import com.azure.core.http.HttpClient; import com.azure.core.http.HttpClientProvider; import com.azure.core.http.HttpHeaderName; -import com.azure.core.http.HttpRequest; -import com.azure.core.http.HttpResponse; import com.azure.core.http.netty.NettyAsyncHttpClientProvider; import com.azure.core.http.okhttp.OkHttpAsyncClientProvider; import com.azure.core.test.TestMode; @@ -17,7 +15,6 @@ import com.azure.core.util.CoreUtils; import com.azure.core.util.HttpClientOptions; import com.azure.core.util.SharedExecutorService; -import com.azure.core.util.UrlBuilder; import com.azure.core.util.logging.ClientLogger; import com.azure.storage.blob.BlobClient; import com.azure.storage.blob.BlobClientBuilder; @@ -33,12 +30,9 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIf; -import reactor.core.publisher.Mono; import java.io.File; import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; import java.nio.file.Files; import java.nio.file.OpenOption; import java.nio.file.StandardOpenOption; @@ -56,6 +50,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; +import static com.azure.core.test.utils.TestUtils.getFaultInjectingHttpClient; import static com.azure.storage.blob.BlobTestBase.ENVIRONMENT; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -112,7 +107,7 @@ public void downloadToFileWithFaultInjection() throws IOException, InterruptedEx .containerName(containerClient.getBlobContainerName()) .blobName(containerClient.getBlobContainerName()) .credential(ENVIRONMENT.getPrimaryAccount().getCredential()) - .httpClient(new HttpFaultInjectingHttpClient(getFaultInjectingWrappedHttpClient())) + .httpClient(getFaultInjectingHttpClient(getFaultInjectingWrappedHttpClient(), false)) .retryOptions(new RequestRetryOptions(RetryPolicyType.FIXED, 4, null, 10L, 10L, null)) .buildClient(); @@ -217,95 +212,6 @@ private static Class getVertxClientProviderReflect return (Class) clazz; } - // For now a local implementation is here in azure-storage-blob until this is released in azure-core-test. - // Since this is a local definition with a clear set of configurations everything is simplified. - private static final class HttpFaultInjectingHttpClient implements HttpClient { - private final HttpClient wrappedHttpClient; - - HttpFaultInjectingHttpClient(HttpClient wrappedHttpClient) { - this.wrappedHttpClient = wrappedHttpClient; - } - - @Override - public Mono send(HttpRequest request) { - return send(request, Context.NONE); - } - - @Override - public Mono send(HttpRequest request, Context context) { - URL originalUrl = request.getUrl(); - request.setHeader(UPSTREAM_URI_HEADER, originalUrl.toString()).setUrl(rewriteUrl(originalUrl)); - String faultType = faultInjectorHandling(); - request.setHeader(HTTP_FAULT_INJECTOR_RESPONSE_HEADER, faultType); - - return wrappedHttpClient.send(request, context).map(response -> { - HttpRequest request1 = response.getRequest(); - request1.getHeaders().remove(UPSTREAM_URI_HEADER); - request1.setUrl(originalUrl); - - return response; - }); - } - - @Override - public HttpResponse sendSync(HttpRequest request, Context context) { - URL originalUrl = request.getUrl(); - request.setHeader(UPSTREAM_URI_HEADER, originalUrl.toString()).setUrl(rewriteUrl(originalUrl)); - String faultType = faultInjectorHandling(); - request.setHeader(HTTP_FAULT_INJECTOR_RESPONSE_HEADER, faultType); - - HttpResponse response = wrappedHttpClient.sendSync(request, context); - response.getRequest().setUrl(originalUrl); - response.getRequest().getHeaders().remove(UPSTREAM_URI_HEADER); - - return response; - } - - private static URL rewriteUrl(URL originalUrl) { - try { - return UrlBuilder.parse(originalUrl).setScheme("http").setHost("localhost").setPort(7777).toUrl(); - } catch (MalformedURLException e) { - throw new RuntimeException(e); - } - } - - private static String faultInjectorHandling() { - // f: Full response - // p: Partial Response (full headers, 50% of body), then wait indefinitely - // pc: Partial Response (full headers, 50% of body), then close (TCP FIN) - // pa: Partial Response (full headers, 50% of body), then abort (TCP RST) - // pn: Partial Response (full headers, 50% of body), then finish normally - // n: No response, then wait indefinitely - // nc: No response, then close (TCP FIN) - // na: No response, then abort (TCP RST) - double random = ThreadLocalRandom.current().nextDouble(); - int choice = (int) (random * 100); - - if (choice >= 25) { - // 75% of requests complete without error. - return "f"; - } else if (choice >= 1) { - if (random <= 0.34D) { - return "n"; - } else if (random <= 0.67D) { - return "nc"; - } else { - return "na"; - } - } else { - if (random <= 0.25D) { - return "p"; - } else if (random <= 0.50D) { - return "pc"; - } else if (random <= 0.75D) { - return "pa"; - } else { - return "pn"; - } - } - } - } - private static boolean shouldRun() { String osName = System.getProperty("os.name").toLowerCase(Locale.ROOT); From 17655196bcb4f7d0651951182e07028f40d56c7e Mon Sep 17 00:00:00 2001 From: Isabelle Date: Mon, 5 May 2025 15:21:24 -0700 Subject: [PATCH 03/16] removing timeout from args to align with other tests that use this api --- .../src/test/java/com/azure/storage/blob/ServiceApiTests.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceApiTests.java index bec72862df0c..ff8c77650fb2 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceApiTests.java @@ -1021,8 +1021,8 @@ public void restoreContainerWithResponse() { sleepIfRunningAgainstService(30000); Response response = primaryBlobServiceClient.undeleteBlobContainerWithResponse( - new UndeleteBlobContainerOptions(blobContainerItem.getName(), blobContainerItem.getVersion()), - Duration.ofMinutes(1), Context.NONE); + new UndeleteBlobContainerOptions(blobContainerItem.getName(), blobContainerItem.getVersion()), null, + Context.NONE); BlobContainerClient restoredContainerClient = response.getValue(); assertNotNull(response); From 25e44cc96662160fe74a7c9d3f3303b59a454ff6 Mon Sep 17 00:00:00 2001 From: Isabelle Date: Mon, 5 May 2025 15:27:58 -0700 Subject: [PATCH 04/16] making supplier match sync test, which does not have flakiness problems --- .../storage/blob/specialized/BlockBlobAsyncApiTests.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobAsyncApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobAsyncApiTests.java index 88fef0b12c91..f829193e9a6f 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobAsyncApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobAsyncApiTests.java @@ -434,9 +434,9 @@ public void stageBlockFromUrl() { @Test public void stageBlockFromUrlSourceErrorAndStatusCode() { BlockBlobAsyncClient destBlob = ccAsync.getBlobAsyncClient(generateBlobName()).getBlockBlobAsyncClient(); - + String blockID = getBlockID(); - + StepVerifier.create(destBlob.stageBlockFromUrl(blockID, blockBlobAsyncClient.getBlobUrl(), new BlobRange(0, (long) PageBlobClient.PAGE_BYTES))) .verifyErrorSatisfies(r -> { BlobStorageException e = assertInstanceOf(BlobStorageException.class, r); @@ -2393,7 +2393,7 @@ public void uploadFromUrlMin() { @Test public void uploadFromUrlSourceErrorAndStatusCode() { BlockBlobAsyncClient destBlob = ccAsync.getBlobAsyncClient(generateBlobName()).getBlockBlobAsyncClient(); - + StepVerifier.create(destBlob.uploadFromUrl(blockBlobAsyncClient.getBlobUrl())) .verifyErrorSatisfies(r -> { BlobStorageException e = assertInstanceOf(BlobStorageException.class, r); @@ -2541,7 +2541,7 @@ public void uploadFromUrlSourceRequestConditions(BlobRequestConditions requestCo private static Stream uploadFromUrlSourceRequestConditionsSupplier() { return Stream.of( Arguments.of(new BlobRequestConditions().setIfMatch("dummy"), BlobErrorCode.SOURCE_CONDITION_NOT_MET), - Arguments.of(new BlobRequestConditions().setIfModifiedSince(OffsetDateTime.now().plusSeconds(10)), + Arguments.of(new BlobRequestConditions().setIfModifiedSince(OffsetDateTime.now().plusSeconds(20)), BlobErrorCode.CANNOT_VERIFY_COPY_SOURCE), Arguments.of(new BlobRequestConditions().setIfUnmodifiedSince(OffsetDateTime.now().minusDays(1)), BlobErrorCode.CANNOT_VERIFY_COPY_SOURCE)); From 10cb93b38dc37208225b06514c821007fbba366a Mon Sep 17 00:00:00 2001 From: Isabelle Date: Mon, 5 May 2025 15:29:21 -0700 Subject: [PATCH 05/16] increasing response and read timeout again --- .../storage/blob/specialized/HttpFaultInjectingTests.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/HttpFaultInjectingTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/HttpFaultInjectingTests.java index 3f240b1cd00d..11c9afd38598 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/HttpFaultInjectingTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/HttpFaultInjectingTests.java @@ -166,8 +166,8 @@ public void downloadToFileWithFaultInjection() throws IOException, InterruptedEx private HttpClient getFaultInjectingWrappedHttpClient() { switch (ENVIRONMENT.getHttpClientType()) { case NETTY: - return HttpClient.createDefault(new HttpClientOptions().readTimeout(Duration.ofSeconds(4)) - .responseTimeout(Duration.ofSeconds(4)) + return HttpClient.createDefault(new HttpClientOptions().readTimeout(Duration.ofSeconds(5)) + .responseTimeout(Duration.ofSeconds(5)) .setHttpClientProvider(NettyAsyncHttpClientProvider.class)); case OK_HTTP: From da074f5608d3abb5dd5217db9fa90c31708d619e Mon Sep 17 00:00:00 2001 From: Isabelle Date: Mon, 5 May 2025 16:22:29 -0700 Subject: [PATCH 06/16] wip --- .../azure/storage/blob/ServiceApiTests.java | 2 +- .../blob/specialized/BlockBlobApiTests.java | 18 +++++++++--------- .../specialized/BlockBlobAsyncApiTests.java | 9 ++++++--- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceApiTests.java index ff8c77650fb2..aad6eecbe076 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceApiTests.java @@ -45,6 +45,7 @@ import com.azure.storage.common.test.shared.extensions.PlaybackOnly; import com.azure.storage.common.test.shared.extensions.RequiredServiceVersion; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.parallel.ResourceLock; import org.junit.jupiter.params.ParameterizedTest; @@ -298,7 +299,6 @@ public void listContainersWithTimeoutStillBackedByPagedStream() { for (int i = 0; i < numContainers; i++) { containers.add(primaryBlobServiceClient.createBlobContainer(generateContainerName())); } - // when: "Consume results by page, then should still have paging functionality"" assertDoesNotThrow( () -> primaryBlobServiceClient diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobApiTests.java index ea3afd3a19be..fae9f5976c4e 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobApiTests.java @@ -372,11 +372,11 @@ public void stageBlockFromUrl() { @Test public void stageBlockFromUrlSourceErrorAndStatusCode() { BlockBlobClient destBlob = cc.getBlobClient(generateBlobName()).getBlockBlobClient(); - + String blockID = getBlockID(); - + BlobStorageException e = assertThrows(BlobStorageException.class, () -> destBlob.stageBlockFromUrl(blockID, blockBlobClient.getBlobUrl(), new BlobRange(0, (long) PageBlobClient.PAGE_BYTES))); - + assertTrue(e.getStatusCode() == 409); assertTrue(e.getServiceMessage().contains("PublicAccessNotPermitted")); assertTrue(e.getServiceMessage().contains("Public access is not permitted on this storage account.")); @@ -1308,13 +1308,13 @@ private static Stream bufferedUploadSyncHandlePathingWithTransientFai def numBlocks = data.remaining() / BlockBlobURL.MAX_STAGE_BLOCK_BYTES long prevCount = 0 def mockReceiver = Mock(IProgressReceiver) - - + + when: TransferManager.uploadFromNonReplayableFlowable(Flowable.just(data), bu, BlockBlobURL.MAX_STAGE_BLOCK_BYTES, 10, new TransferManagerUploadToBlockBlobOptions(mockReceiver, null, null, null, 20)).blockingGet() data.position(0) - + then: // We should receive exactly one notification of the completed progress. 1 * mockReceiver.reportProgress(data.remaining()) */ @@ -1331,7 +1331,7 @@ private static Stream bufferedUploadSyncHandlePathingWithTransientFai prevCount = bytesTransferred } } - + // We should receive no notifications that report more progress than the size of the file. 0 * mockReceiver.reportProgress({ it > data.remaining() }) notThrown(IllegalArgumentException) @@ -1448,9 +1448,9 @@ public void uploadFromUrlMin() { @Test public void uploadFromUrlSourceErrorAndStatusCode() { BlockBlobClient destBlob = cc.getBlobClient(generateBlobName()).getBlockBlobClient(); - + BlobStorageException e = assertThrows(BlobStorageException.class, () -> destBlob.uploadFromUrl(blockBlobClient.getBlobUrl())); - + assertTrue(e.getStatusCode() == 409); assertTrue(e.getServiceMessage().contains("PublicAccessNotPermitted")); assertTrue(e.getServiceMessage().contains("Public access is not permitted on this storage account.")); diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobAsyncApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobAsyncApiTests.java index f829193e9a6f..26a09b7f13a0 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobAsyncApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobAsyncApiTests.java @@ -2526,10 +2526,13 @@ public void uploadFromUrlSourceRequestConditions(BlobRequestConditions requestCo Mono> response = sourceBlob.upload(DATA.getDefaultFlux(), null).flatMap(r -> { String sas = sourceBlob.generateSas(new BlobServiceSasSignatureValues(testResourceNamer.now().plusDays(1), new BlobContainerSasPermission().setReadPermission(true))); - BlobUploadFromUrlOptions options = new BlobUploadFromUrlOptions(sourceBlob.getBlobUrl() + "?" + sas) - .setSourceRequestConditions(requestConditions); + return blockBlobAsyncClient.upload(Flux.just(ByteBuffer.wrap(new byte[0])), 0, true) - .then(blockBlobAsyncClient.uploadFromUrlWithResponse(options)); + .flatMap(r2 -> { + BlobUploadFromUrlOptions options = new BlobUploadFromUrlOptions(sourceBlob.getBlobUrl() + "?" + sas) + .setSourceRequestConditions(requestConditions); + return blockBlobAsyncClient.uploadFromUrlWithResponse(options); + }); }); StepVerifier.create(response).verifyErrorSatisfies(r -> { From e9adf597ab882585f58c06b32ed4a00c04fae586 Mon Sep 17 00:00:00 2001 From: Isabelle Date: Mon, 5 May 2025 16:56:44 -0700 Subject: [PATCH 07/16] removing management plane interaction and replacing with data plane interaction so it doesnt explode with 429s --- .../com/azure/storage/blob/BlobTestBase.java | 69 ++++++------------- .../blob/specialized/BlockBlobApiTests.java | 18 ++--- .../specialized/BlockBlobAsyncApiTests.java | 17 +++-- 3 files changed, 37 insertions(+), 67 deletions(-) diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobTestBase.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobTestBase.java index 51abad78209e..3f0888b5d22e 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobTestBase.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobTestBase.java @@ -37,7 +37,6 @@ import com.azure.identity.ChainedTokenCredentialBuilder; import com.azure.identity.DefaultAzureCredentialBuilder; import com.azure.identity.EnvironmentCredentialBuilder; -import com.azure.json.JsonProviders; import com.azure.json.JsonSerializable; import com.azure.json.JsonWriter; import com.azure.storage.blob.models.BlobContainerItem; @@ -68,7 +67,6 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; -import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -879,6 +877,9 @@ protected String generateShareName() { return generateResourceName(entityNo++); } + private HttpPipeline dataPlanePipeline; + private HttpHeaders genericHeaders; + protected String createFileAndDirectoryWithoutFileShareDependency(byte[] data, String shareName) throws IOException { String accountName = ENVIRONMENT.getPrimaryAccount().getName(); @@ -886,11 +887,8 @@ protected String createFileAndDirectoryWithoutFileShareDependency(byte[] data, S BearerTokenAuthenticationPolicy credentialPolicyDataPlane = new BearerTokenAuthenticationPolicy( getTokenCredential(ENVIRONMENT.getTestMode()), Constants.STORAGE_SCOPE); - //create share through management plane - createFileShareWithoutDependency(shareName); - //setup headers that will be used in every request - HttpHeaders genericHeaders = new HttpHeaders().set(X_MS_VERSION, "2025-07-05") + genericHeaders = new HttpHeaders().set(X_MS_VERSION, "2025-07-05") .set(HttpHeaderName.ACCEPT, "application/xml") .set(HttpHeaderName.HOST, accountName + ".file.core.windows.net") .set(HttpHeaderName.CONTENT_LENGTH, "0") @@ -904,8 +902,15 @@ protected String createFileAndDirectoryWithoutFileShareDependency(byte[] data, S policies.add(new RequestIdPolicy()); // create data plane pipeline - HttpPipeline dataPlanePipeline - = new HttpPipelineBuilder().policies(policies.toArray(new HttpPipelinePolicy[0])).build(); + dataPlanePipeline = new HttpPipelineBuilder().policies(policies.toArray(new HttpPipelinePolicy[0])).build(); + + // create share through data plane pipeline + String shareUrl = String.format("https://%s.file.core.windows.net/%s?restype=share", accountName, shareName); + + HttpResponse shareCreateResponse + = dataPlanePipeline.send(new HttpRequest(HttpMethod.PUT, new URL(shareUrl), genericHeaders)).block(); + assertNotNull(shareCreateResponse); + assertEquals(201, shareCreateResponse.getStatusCode()); // create directory String directoryName = generateBlobName(); @@ -945,48 +950,14 @@ protected String createFileAndDirectoryWithoutFileShareDependency(byte[] data, S return fileUrl; } - protected void createFileShareWithoutDependency(String shareName) throws IOException { - String shareID = getFileShareID(shareName); - Body shareBody = new Body(); - shareBody.setId(shareID); - shareBody.setName(shareName); - shareBody.setType("Microsoft.Storage/storageAccounts/fileServices/shares"); - - ByteArrayOutputStream shareJson = new ByteArrayOutputStream(); - try (JsonWriter jsonWriter = JsonProviders.createWriter(shareJson)) { - shareBody.toJson(jsonWriter); - } - HttpResponse response - = getManagementPlanePipeline().send(new HttpRequest(HttpMethod.PUT, new URL(getFileShareUri(shareID)), - new HttpHeaders(), Flux.just(ByteBuffer.wrap(shareJson.toByteArray())))).block(); - assertNotNull(response); - assertEquals(201, response.getStatusCode()); - } - protected void deleteFileShareWithoutDependency(String shareName) throws IOException { - String shareID = getFileShareID(shareName); - HttpResponse response = getManagementPlanePipeline() - .send(new HttpRequest(HttpMethod.DELETE, new URL(getFileShareUri(shareID)), new HttpHeaders())) - .block(); - assertNotNull(response); - assertEquals(200, response.getStatusCode()); - } - - protected HttpPipeline getManagementPlanePipeline() { - BearerTokenAuthenticationPolicy credentialPolicyManagementPlane = new BearerTokenAuthenticationPolicy( - getTokenCredential(ENVIRONMENT.getTestMode()), "https://management.azure.com/.default"); - return new HttpPipelineBuilder().policies(credentialPolicyManagementPlane).build(); - } - - protected String getFileShareID(String shareName) { - return String.format( - "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Storage/storageAccounts/" - + "%s/fileServices/default/shares/%s", - SUBSCRIPTION_ID, RESOURCE_GROUP_NAME, ENVIRONMENT.getPrimaryAccount().getName(), shareName); - } + String shareUrl = String.format("https://%s.file.core.windows.net/%s?restype=share", + ENVIRONMENT.getPrimaryAccount().getName(), shareName); - protected String getFileShareUri(String fileShareID) { - return "https://management.azure.com" + fileShareID + "?api-version=2024-01-01"; + HttpResponse shareDeleteResponse + = dataPlanePipeline.send(new HttpRequest(HttpMethod.DELETE, new URL(shareUrl), genericHeaders)).block(); + assertNotNull(shareDeleteResponse); + assertEquals(202, shareDeleteResponse.getStatusCode()); } public static final class Body implements JsonSerializable { @@ -1073,7 +1044,7 @@ public JsonWriter toJson(JsonWriter jsonWriter) throws IOException { } } - //todo: change the copy of this method in StorageCommonTestUtils to take in TestMode instead of interception manager + //todo isbr: change the copy of this method in StorageCommonTestUtils to take in TestMode instead of interception manager protected static TokenCredential getTokenCredential(TestMode testMode) { if (testMode == TestMode.RECORD) { return new DefaultAzureCredentialBuilder().build(); diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobApiTests.java index 9945ba179238..7a00b9697dbc 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobApiTests.java @@ -377,11 +377,11 @@ public void stageBlockFromUrl() { @Test public void stageBlockFromUrlSourceErrorAndStatusCode() { BlockBlobClient destBlob = cc.getBlobClient(generateBlobName()).getBlockBlobClient(); - + String blockID = getBlockID(); - + BlobStorageException e = assertThrows(BlobStorageException.class, () -> destBlob.stageBlockFromUrl(blockID, blockBlobClient.getBlobUrl(), new BlobRange(0, (long) PageBlobClient.PAGE_BYTES))); - + assertTrue(e.getStatusCode() == 409); assertTrue(e.getServiceMessage().contains("PublicAccessNotPermitted")); assertTrue(e.getServiceMessage().contains("Public access is not permitted on this storage account.")); @@ -1313,13 +1313,13 @@ private static Stream bufferedUploadSyncHandlePathingWithTransientFai def numBlocks = data.remaining() / BlockBlobURL.MAX_STAGE_BLOCK_BYTES long prevCount = 0 def mockReceiver = Mock(IProgressReceiver) - - + + when: TransferManager.uploadFromNonReplayableFlowable(Flowable.just(data), bu, BlockBlobURL.MAX_STAGE_BLOCK_BYTES, 10, new TransferManagerUploadToBlockBlobOptions(mockReceiver, null, null, null, 20)).blockingGet() data.position(0) - + then: // We should receive exactly one notification of the completed progress. 1 * mockReceiver.reportProgress(data.remaining()) */ @@ -1336,7 +1336,7 @@ private static Stream bufferedUploadSyncHandlePathingWithTransientFai prevCount = bytesTransferred } } - + // We should receive no notifications that report more progress than the size of the file. 0 * mockReceiver.reportProgress({ it > data.remaining() }) notThrown(IllegalArgumentException) @@ -1453,9 +1453,9 @@ public void uploadFromUrlMin() { @Test public void uploadFromUrlSourceErrorAndStatusCode() { BlockBlobClient destBlob = cc.getBlobClient(generateBlobName()).getBlockBlobClient(); - + BlobStorageException e = assertThrows(BlobStorageException.class, () -> destBlob.uploadFromUrl(blockBlobClient.getBlobUrl())); - + assertTrue(e.getStatusCode() == 409); assertTrue(e.getServiceMessage().contains("PublicAccessNotPermitted")); assertTrue(e.getServiceMessage().contains("Public access is not permitted on this storage account.")); diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobAsyncApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobAsyncApiTests.java index 7a46fd49e2b3..0c69b5eea581 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobAsyncApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobAsyncApiTests.java @@ -439,9 +439,9 @@ public void stageBlockFromUrl() { @Test public void stageBlockFromUrlSourceErrorAndStatusCode() { BlockBlobAsyncClient destBlob = ccAsync.getBlobAsyncClient(generateBlobName()).getBlockBlobAsyncClient(); - + String blockID = getBlockID(); - + StepVerifier.create(destBlob.stageBlockFromUrl(blockID, blockBlobAsyncClient.getBlobUrl(), new BlobRange(0, (long) PageBlobClient.PAGE_BYTES))) .verifyErrorSatisfies(r -> { BlobStorageException e = assertInstanceOf(BlobStorageException.class, r); @@ -2398,7 +2398,7 @@ public void uploadFromUrlMin() { @Test public void uploadFromUrlSourceErrorAndStatusCode() { BlockBlobAsyncClient destBlob = ccAsync.getBlobAsyncClient(generateBlobName()).getBlockBlobAsyncClient(); - + StepVerifier.create(destBlob.uploadFromUrl(blockBlobAsyncClient.getBlobUrl())) .verifyErrorSatisfies(r -> { BlobStorageException e = assertInstanceOf(BlobStorageException.class, r); @@ -2532,12 +2532,11 @@ public void uploadFromUrlSourceRequestConditions(BlobRequestConditions requestCo String sas = sourceBlob.generateSas(new BlobServiceSasSignatureValues(testResourceNamer.now().plusDays(1), new BlobContainerSasPermission().setReadPermission(true))); - return blockBlobAsyncClient.upload(Flux.just(ByteBuffer.wrap(new byte[0])), 0, true) - .flatMap(r2 -> { - BlobUploadFromUrlOptions options = new BlobUploadFromUrlOptions(sourceBlob.getBlobUrl() + "?" + sas) - .setSourceRequestConditions(requestConditions); - return blockBlobAsyncClient.uploadFromUrlWithResponse(options); - }); + return blockBlobAsyncClient.upload(Flux.just(ByteBuffer.wrap(new byte[0])), 0, true).flatMap(r2 -> { + BlobUploadFromUrlOptions options = new BlobUploadFromUrlOptions(sourceBlob.getBlobUrl() + "?" + sas) + .setSourceRequestConditions(requestConditions); + return blockBlobAsyncClient.uploadFromUrlWithResponse(options); + }); }); StepVerifier.create(response).verifyErrorSatisfies(r -> { From 5c98dad71c958f9b32a2f42483b263444bde6881 Mon Sep 17 00:00:00 2001 From: Isabelle Date: Tue, 6 May 2025 10:57:11 -0700 Subject: [PATCH 08/16] changing seconds to days to match uploadFromUrlDestinationRequestConditionsSupplier --- .../blob/specialized/BlockBlobApiTests.java | 20 +++++++++---------- .../specialized/BlockBlobAsyncApiTests.java | 8 ++++---- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobApiTests.java index 7a00b9697dbc..feeded664384 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobApiTests.java @@ -377,11 +377,11 @@ public void stageBlockFromUrl() { @Test public void stageBlockFromUrlSourceErrorAndStatusCode() { BlockBlobClient destBlob = cc.getBlobClient(generateBlobName()).getBlockBlobClient(); - + String blockID = getBlockID(); - + BlobStorageException e = assertThrows(BlobStorageException.class, () -> destBlob.stageBlockFromUrl(blockID, blockBlobClient.getBlobUrl(), new BlobRange(0, (long) PageBlobClient.PAGE_BYTES))); - + assertTrue(e.getStatusCode() == 409); assertTrue(e.getServiceMessage().contains("PublicAccessNotPermitted")); assertTrue(e.getServiceMessage().contains("Public access is not permitted on this storage account.")); @@ -1313,13 +1313,13 @@ private static Stream bufferedUploadSyncHandlePathingWithTransientFai def numBlocks = data.remaining() / BlockBlobURL.MAX_STAGE_BLOCK_BYTES long prevCount = 0 def mockReceiver = Mock(IProgressReceiver) - - + + when: TransferManager.uploadFromNonReplayableFlowable(Flowable.just(data), bu, BlockBlobURL.MAX_STAGE_BLOCK_BYTES, 10, new TransferManagerUploadToBlockBlobOptions(mockReceiver, null, null, null, 20)).blockingGet() data.position(0) - + then: // We should receive exactly one notification of the completed progress. 1 * mockReceiver.reportProgress(data.remaining()) */ @@ -1336,7 +1336,7 @@ private static Stream bufferedUploadSyncHandlePathingWithTransientFai prevCount = bytesTransferred } } - + // We should receive no notifications that report more progress than the size of the file. 0 * mockReceiver.reportProgress({ it > data.remaining() }) notThrown(IllegalArgumentException) @@ -1453,9 +1453,9 @@ public void uploadFromUrlMin() { @Test public void uploadFromUrlSourceErrorAndStatusCode() { BlockBlobClient destBlob = cc.getBlobClient(generateBlobName()).getBlockBlobClient(); - + BlobStorageException e = assertThrows(BlobStorageException.class, () -> destBlob.uploadFromUrl(blockBlobClient.getBlobUrl())); - + assertTrue(e.getStatusCode() == 409); assertTrue(e.getServiceMessage().contains("PublicAccessNotPermitted")); assertTrue(e.getServiceMessage().contains("Public access is not permitted on this storage account.")); @@ -1581,7 +1581,7 @@ public void uploadFromUrlSourceRequestConditions(BlobRequestConditions requestCo private static Stream uploadFromUrlSourceRequestConditionsSupplier() { return Stream.of( Arguments.of(new BlobRequestConditions().setIfMatch("dummy"), BlobErrorCode.SOURCE_CONDITION_NOT_MET), - Arguments.of(new BlobRequestConditions().setIfModifiedSince(OffsetDateTime.now().plusSeconds(20)), + Arguments.of(new BlobRequestConditions().setIfModifiedSince(OffsetDateTime.now().plusDays(10)), BlobErrorCode.CANNOT_VERIFY_COPY_SOURCE), Arguments.of(new BlobRequestConditions().setIfUnmodifiedSince(OffsetDateTime.now().minusDays(1)), BlobErrorCode.CANNOT_VERIFY_COPY_SOURCE)); diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobAsyncApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobAsyncApiTests.java index 0c69b5eea581..9ee81c9bd76b 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobAsyncApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobAsyncApiTests.java @@ -439,9 +439,9 @@ public void stageBlockFromUrl() { @Test public void stageBlockFromUrlSourceErrorAndStatusCode() { BlockBlobAsyncClient destBlob = ccAsync.getBlobAsyncClient(generateBlobName()).getBlockBlobAsyncClient(); - + String blockID = getBlockID(); - + StepVerifier.create(destBlob.stageBlockFromUrl(blockID, blockBlobAsyncClient.getBlobUrl(), new BlobRange(0, (long) PageBlobClient.PAGE_BYTES))) .verifyErrorSatisfies(r -> { BlobStorageException e = assertInstanceOf(BlobStorageException.class, r); @@ -2398,7 +2398,7 @@ public void uploadFromUrlMin() { @Test public void uploadFromUrlSourceErrorAndStatusCode() { BlockBlobAsyncClient destBlob = ccAsync.getBlobAsyncClient(generateBlobName()).getBlockBlobAsyncClient(); - + StepVerifier.create(destBlob.uploadFromUrl(blockBlobAsyncClient.getBlobUrl())) .verifyErrorSatisfies(r -> { BlobStorageException e = assertInstanceOf(BlobStorageException.class, r); @@ -2548,7 +2548,7 @@ public void uploadFromUrlSourceRequestConditions(BlobRequestConditions requestCo private static Stream uploadFromUrlSourceRequestConditionsSupplier() { return Stream.of( Arguments.of(new BlobRequestConditions().setIfMatch("dummy"), BlobErrorCode.SOURCE_CONDITION_NOT_MET), - Arguments.of(new BlobRequestConditions().setIfModifiedSince(OffsetDateTime.now().plusSeconds(20)), + Arguments.of(new BlobRequestConditions().setIfModifiedSince(OffsetDateTime.now().plusDays(10)), BlobErrorCode.CANNOT_VERIFY_COPY_SOURCE), Arguments.of(new BlobRequestConditions().setIfUnmodifiedSince(OffsetDateTime.now().minusDays(1)), BlobErrorCode.CANNOT_VERIFY_COPY_SOURCE)); From fbf897702a1f82415b44f34caae319992c648de5 Mon Sep 17 00:00:00 2001 From: Isabelle Date: Tue, 6 May 2025 15:20:50 -0700 Subject: [PATCH 09/16] making root tests playback only to resolve race conditions due to parallelism --- .../azure/storage/blob/ContainerApiTests.java | 12 ++++++++---- .../storage/blob/ContainerAsyncApiTests.java | 12 ++++++++---- .../blob/specialized/BlockBlobApiTests.java | 18 +++++++++--------- .../specialized/BlockBlobAsyncApiTests.java | 6 +++--- 4 files changed, 28 insertions(+), 20 deletions(-) diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerApiTests.java index 83828fdd7f8d..0f47b86c66b4 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerApiTests.java @@ -1760,6 +1760,7 @@ public void createURLSpecialCharsDecoded(String name) { } @Test + @PlaybackOnly public void rootExplicit() { cc = primaryBlobServiceClient.getBlobContainerClient(BlobContainerClient.ROOT_CONTAINER_NAME); // create root container if not exist. @@ -1771,6 +1772,7 @@ public void rootExplicit() { } @Test + @PlaybackOnly public void rootExplicitInEndpoint() { cc = primaryBlobServiceClient.getBlobContainerClient(BlobContainerClient.ROOT_CONTAINER_NAME); // create root container if not exist. @@ -1788,6 +1790,7 @@ public void rootExplicitInEndpoint() { } @Test + @PlaybackOnly public void blobClientBuilderRootImplicit() { cc = primaryBlobServiceClient.getBlobContainerClient(BlobContainerClient.ROOT_CONTAINER_NAME); // createroot container if not exist. @@ -1810,6 +1813,7 @@ public void blobClientBuilderRootImplicit() { } @Test + @PlaybackOnly public void containerClientBuilderRootImplicit() { cc = primaryBlobServiceClient.getBlobContainerClient(BlobContainerClient.ROOT_CONTAINER_NAME); // create root container if not exist. @@ -1832,10 +1836,10 @@ public void containerClientBuilderRootImplicit() { @Test public void serviceClientImplicitRoot() { - assertEquals(primaryBlobServiceClient.getBlobContainerClient(null).getBlobContainerName(), - BlobContainerAsyncClient.ROOT_CONTAINER_NAME); - assertEquals(primaryBlobServiceClient.getBlobContainerClient("").getBlobContainerName(), - BlobContainerAsyncClient.ROOT_CONTAINER_NAME); + assertEquals(BlobContainerAsyncClient.ROOT_CONTAINER_NAME, + primaryBlobServiceClient.getBlobContainerClient(null).getBlobContainerName()); + assertEquals(BlobContainerAsyncClient.ROOT_CONTAINER_NAME, + primaryBlobServiceClient.getBlobContainerClient("").getBlobContainerName()); } @Test diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerAsyncApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerAsyncApiTests.java index 3bb26f5c4741..bb703086e294 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerAsyncApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerAsyncApiTests.java @@ -1859,6 +1859,7 @@ public void createURLSpecialCharsEncoded(String name) { } @Test + @PlaybackOnly public void rootExplicit() { ccAsync = primaryBlobServiceAsyncClient.getBlobContainerAsyncClient(BlobContainerClient.ROOT_CONTAINER_NAME); // create root container if not exist. @@ -1874,6 +1875,7 @@ public void rootExplicit() { } @Test + @PlaybackOnly public void rootExplicitInEndpoint() { ccAsync = primaryBlobServiceAsyncClient.getBlobContainerAsyncClient(BlobContainerClient.ROOT_CONTAINER_NAME); // create root container if not exist. @@ -1893,6 +1895,7 @@ public void rootExplicitInEndpoint() { } @Test + @PlaybackOnly public void blobClientBuilderRootImplicit() { ccAsync = primaryBlobServiceAsyncClient.getBlobContainerAsyncClient(BlobContainerClient.ROOT_CONTAINER_NAME); // createroot container if not exist. @@ -1917,6 +1920,7 @@ public void blobClientBuilderRootImplicit() { } @Test + @PlaybackOnly public void containerClientBuilderRootImplicit() { ccAsync = primaryBlobServiceAsyncClient.getBlobContainerAsyncClient(BlobContainerClient.ROOT_CONTAINER_NAME); // create root container if not exist. @@ -1945,10 +1949,10 @@ public void containerClientBuilderRootImplicit() { @Test public void serviceClientImplicitRoot() { - assertEquals(primaryBlobServiceAsyncClient.getBlobContainerAsyncClient(null).getBlobContainerName(), - BlobContainerAsyncClient.ROOT_CONTAINER_NAME); - assertEquals(primaryBlobServiceAsyncClient.getBlobContainerAsyncClient("").getBlobContainerName(), - BlobContainerAsyncClient.ROOT_CONTAINER_NAME); + assertEquals(BlobContainerAsyncClient.ROOT_CONTAINER_NAME, + primaryBlobServiceAsyncClient.getBlobContainerAsyncClient(null).getBlobContainerName()); + assertEquals(BlobContainerAsyncClient.ROOT_CONTAINER_NAME, + primaryBlobServiceAsyncClient.getBlobContainerAsyncClient("").getBlobContainerName()); } @Test diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobApiTests.java index feeded664384..915941177e57 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobApiTests.java @@ -377,11 +377,11 @@ public void stageBlockFromUrl() { @Test public void stageBlockFromUrlSourceErrorAndStatusCode() { BlockBlobClient destBlob = cc.getBlobClient(generateBlobName()).getBlockBlobClient(); - + String blockID = getBlockID(); - + BlobStorageException e = assertThrows(BlobStorageException.class, () -> destBlob.stageBlockFromUrl(blockID, blockBlobClient.getBlobUrl(), new BlobRange(0, (long) PageBlobClient.PAGE_BYTES))); - + assertTrue(e.getStatusCode() == 409); assertTrue(e.getServiceMessage().contains("PublicAccessNotPermitted")); assertTrue(e.getServiceMessage().contains("Public access is not permitted on this storage account.")); @@ -1313,13 +1313,13 @@ private static Stream bufferedUploadSyncHandlePathingWithTransientFai def numBlocks = data.remaining() / BlockBlobURL.MAX_STAGE_BLOCK_BYTES long prevCount = 0 def mockReceiver = Mock(IProgressReceiver) - - + + when: TransferManager.uploadFromNonReplayableFlowable(Flowable.just(data), bu, BlockBlobURL.MAX_STAGE_BLOCK_BYTES, 10, new TransferManagerUploadToBlockBlobOptions(mockReceiver, null, null, null, 20)).blockingGet() data.position(0) - + then: // We should receive exactly one notification of the completed progress. 1 * mockReceiver.reportProgress(data.remaining()) */ @@ -1336,7 +1336,7 @@ private static Stream bufferedUploadSyncHandlePathingWithTransientFai prevCount = bytesTransferred } } - + // We should receive no notifications that report more progress than the size of the file. 0 * mockReceiver.reportProgress({ it > data.remaining() }) notThrown(IllegalArgumentException) @@ -1453,9 +1453,9 @@ public void uploadFromUrlMin() { @Test public void uploadFromUrlSourceErrorAndStatusCode() { BlockBlobClient destBlob = cc.getBlobClient(generateBlobName()).getBlockBlobClient(); - + BlobStorageException e = assertThrows(BlobStorageException.class, () -> destBlob.uploadFromUrl(blockBlobClient.getBlobUrl())); - + assertTrue(e.getStatusCode() == 409); assertTrue(e.getServiceMessage().contains("PublicAccessNotPermitted")); assertTrue(e.getServiceMessage().contains("Public access is not permitted on this storage account.")); diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobAsyncApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobAsyncApiTests.java index 9ee81c9bd76b..eeec87686794 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobAsyncApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobAsyncApiTests.java @@ -439,9 +439,9 @@ public void stageBlockFromUrl() { @Test public void stageBlockFromUrlSourceErrorAndStatusCode() { BlockBlobAsyncClient destBlob = ccAsync.getBlobAsyncClient(generateBlobName()).getBlockBlobAsyncClient(); - + String blockID = getBlockID(); - + StepVerifier.create(destBlob.stageBlockFromUrl(blockID, blockBlobAsyncClient.getBlobUrl(), new BlobRange(0, (long) PageBlobClient.PAGE_BYTES))) .verifyErrorSatisfies(r -> { BlobStorageException e = assertInstanceOf(BlobStorageException.class, r); @@ -2398,7 +2398,7 @@ public void uploadFromUrlMin() { @Test public void uploadFromUrlSourceErrorAndStatusCode() { BlockBlobAsyncClient destBlob = ccAsync.getBlobAsyncClient(generateBlobName()).getBlockBlobAsyncClient(); - + StepVerifier.create(destBlob.uploadFromUrl(blockBlobAsyncClient.getBlobUrl())) .verifyErrorSatisfies(r -> { BlobStorageException e = assertInstanceOf(BlobStorageException.class, r); From 36604c8b5b62133ed90111acb7eabf1e13de5cbc Mon Sep 17 00:00:00 2001 From: Isabelle Date: Tue, 6 May 2025 15:22:51 -0700 Subject: [PATCH 10/16] removing a test that was literally never used --- .../blob/specialized/BlockBlobApiTests.java | 46 ++----------------- 1 file changed, 5 insertions(+), 41 deletions(-) diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobApiTests.java index 915941177e57..bf377ebe06c6 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobApiTests.java @@ -377,11 +377,11 @@ public void stageBlockFromUrl() { @Test public void stageBlockFromUrlSourceErrorAndStatusCode() { BlockBlobClient destBlob = cc.getBlobClient(generateBlobName()).getBlockBlobClient(); - + String blockID = getBlockID(); - + BlobStorageException e = assertThrows(BlobStorageException.class, () -> destBlob.stageBlockFromUrl(blockID, blockBlobClient.getBlobUrl(), new BlobRange(0, (long) PageBlobClient.PAGE_BYTES))); - + assertTrue(e.getStatusCode() == 409); assertTrue(e.getServiceMessage().contains("PublicAccessNotPermitted")); assertTrue(e.getServiceMessage().contains("Public access is not permitted on this storage account.")); @@ -1306,42 +1306,6 @@ private static Stream bufferedUploadSyncHandlePathingWithTransientFai return Stream.of(Arguments.of(11110, 0), Arguments.of(2 * Constants.MB + 11, 2)); } - /* - def "Upload NRF progress"() { - setup: - def data = getRandomData(BlockBlobURL.MAX_UPLOAD_BLOB_BYTES + 1) - def numBlocks = data.remaining() / BlockBlobURL.MAX_STAGE_BLOCK_BYTES - long prevCount = 0 - def mockReceiver = Mock(IProgressReceiver) - - - when: - TransferManager.uploadFromNonReplayableFlowable(Flowable.just(data), bu, BlockBlobURL.MAX_STAGE_BLOCK_BYTES, 10, - new TransferManagerUploadToBlockBlobOptions(mockReceiver, null, null, null, 20)).blockingGet() - data.position(0) - - then: - // We should receive exactly one notification of the completed progress. - 1 * mockReceiver.reportProgress(data.remaining()) */ - - /* - We should receive at least one notification reporting an intermediary value per block, but possibly more - notifications will be received depending on the implementation. We specify numBlocks - 1 because the last block - will be the total size as above. Finally, we assert that the number reported monotonically increases. - */ - /*(numBlocks - 1.._) * mockReceiver.reportProgress(!data.remaining()) >> { long bytesTransferred -> - if (!(bytesTransferred > prevCount)) { - throw new IllegalArgumentException("Reported progress should monotonically increase") - } else { - prevCount = bytesTransferred - } - } - - // We should receive no notifications that report more progress than the size of the file. - 0 * mockReceiver.reportProgress({ it > data.remaining() }) - notThrown(IllegalArgumentException) - }*/ - @LiveOnly @Test public void bufferedUploadOverwrite() throws IOException { @@ -1453,9 +1417,9 @@ public void uploadFromUrlMin() { @Test public void uploadFromUrlSourceErrorAndStatusCode() { BlockBlobClient destBlob = cc.getBlobClient(generateBlobName()).getBlockBlobClient(); - + BlobStorageException e = assertThrows(BlobStorageException.class, () -> destBlob.uploadFromUrl(blockBlobClient.getBlobUrl())); - + assertTrue(e.getStatusCode() == 409); assertTrue(e.getServiceMessage().contains("PublicAccessNotPermitted")); assertTrue(e.getServiceMessage().contains("Public access is not permitted on this storage account.")); From 57938d767398c4a493cf0db8a1a81864df32f713 Mon Sep 17 00:00:00 2001 From: Isabelle Date: Mon, 12 May 2025 13:15:55 -0700 Subject: [PATCH 11/16] adding mocking to list resource tests --- .../com/azure/storage/blob/BlobTestBase.java | 151 ++++++++++++++++++ .../azure/storage/blob/ContainerApiTests.java | 89 ++++++----- .../storage/blob/ContainerAsyncApiTests.java | 88 +++++----- .../azure/storage/blob/ServiceApiTests.java | 62 +++---- .../storage/blob/ServiceAsyncApiTests.java | 58 +++---- .../blob/specialized/BlockBlobApiTests.java | 10 +- 6 files changed, 304 insertions(+), 154 deletions(-) diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobTestBase.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobTestBase.java index 3f0888b5d22e..8539ce65b02c 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobTestBase.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobTestBase.java @@ -22,6 +22,7 @@ import com.azure.core.http.rest.Response; import com.azure.core.test.TestMode; import com.azure.core.test.TestProxyTestBase; +import com.azure.core.test.http.MockHttpResponse; import com.azure.core.test.models.CustomMatcher; import com.azure.core.test.models.TestProxySanitizer; import com.azure.core.test.models.TestProxySanitizerType; @@ -1080,4 +1081,154 @@ protected static TokenCredential getTokenCredential(TestMode testMode) { return new MockTokenCredential(); } } + + protected static final class ListBlobsWithTimeoutTestClient implements HttpClient { + + private HttpResponse response(HttpRequest request, String xml) { + HttpHeaders headers = new HttpHeaders().set(HttpHeaderName.CONTENT_TYPE, "application/xml"); + return new MockHttpResponse(request, 200, headers, xml.getBytes(StandardCharsets.UTF_8)); + } + + private String buildFirstRequest(Boolean useDelimiter) { + String delimiterString = useDelimiter ? "/" : ""; + + return "" + + "" + + "3" + delimiterString + "" + "" + "blob1" + + "" + "" + "blob2" + "" + "" + "blob3" + "" + + "" + "MARKER--" + ""; + } + + private String buildSecondRequest(Boolean useDelimiter) { + String delimiterString = useDelimiter ? "/" : ""; + + return "" + + "" + + "MARKER--" + "3" + delimiterString + "" + "" + + "blob4" + "" + "" + "blob5" + "" + "" + + "" + ""; + } + + @Override + public Mono send(HttpRequest request) { + String url = request.getUrl().toString(); + HttpResponse response; + + if (url.contains("?restype=container&comp=list&maxresults=")) { + // flat first request + response = response(request, buildFirstRequest(false)); + } else if (url.contains("?restype=container&comp=list&marker=")) { + // flat second request + response = response(request, buildSecondRequest(false)); + } else if (url.contains("?restype=container&comp=list&delimiter=/&maxresults=")) { + // hierarchy first request + response = response(request, buildFirstRequest(true)); + } else if (url.contains("?restype=container&comp=list&delimiter=/&marker=")) { + // hierarchy second request + response = response(request, buildSecondRequest(true)); + } else { + // fallback + return Mono.just(new MockHttpResponse(request, 404)); + } + + return Mono.delay(Duration.ofSeconds(4)).then(Mono.just(response)); + } + } + + protected static final class FindBlobsWithTimeoutClient implements HttpClient { + + private HttpResponse response(HttpRequest request, String xml) { + HttpHeaders headers = new HttpHeaders().set(HttpHeaderName.CONTENT_TYPE, "application/xml"); + return new MockHttpResponse(request, 200, headers, xml.getBytes(StandardCharsets.UTF_8)); + } + + private String buildFirstRequest() { + return "" + + "" + + ""dummyKey"='dummyValue'" + "3" + + "" + "" + "blob1" + "foo" + "" + + "" + "" + "dummyKey" + "dummyValue" + "" + "" + + "" + "" + "" + "blob2" + "foo" + + "" + "" + "" + "dummyKey" + "dummyValue" + "" + + "" + "" + "" + "" + "blob3" + + "foo" + "" + "" + "" + "dummyKey" + + "dummyValue" + "" + "" + "" + "" + "" + + "MARKER-" + ""; + } + + private String buildSecondRequest() { + return "" + + "" + + "MARKER-" + ""dummyKey"='dummyValue'" + + "3" + "" + "" + "blob4" + + "foo" + "" + "" + "" + "dummyKey" + + "dummyValue" + "" + "" + "" + "" + "" + + "blob5" + "foo" + "" + "" + "" + + "dummyKey" + "dummyValue" + "" + "" + "" + "" + + "" + "" + ""; + } + + @Override + public Mono send(HttpRequest request) { + String url = request.getUrl().toString(); + HttpResponse response; + + if (url.contains("marker")) { + // second request + response = response(request, buildSecondRequest()); + } else if (url.contains("?comp=blobs&where=%") || url.contains("?restype=container&comp=blobs&where=%")) { + // first request + response = response(request, buildFirstRequest()); + } else { + // fallback + return Mono.just(new MockHttpResponse(request, 404)); + } + + return Mono.delay(Duration.ofSeconds(4)).then(Mono.just(response)); + } + } + + protected static final class ListContainersWithTimeoutTestClient implements HttpClient { + + private HttpResponse response(HttpRequest request, String xml) { + HttpHeaders headers = new HttpHeaders().set(HttpHeaderName.CONTENT_TYPE, "application/xml"); + return new MockHttpResponse(request, 200, headers, xml.getBytes(StandardCharsets.UTF_8)); + } + + private String buildFirstRequest() { + return "" + + "" + + "3" + "" + "" + "container1" + + "" + "" + "container2" + "" + "" + + "container3" + "" + "" + + "/marker/marker" + ""; + } + + private String buildSecondRequest() { + return "" + + "" + + "/marker/marker" + "3" + "" + "" + + "container4" + "" + "" + "container5" + + "" + "" + "" + ""; + } + + @Override + public Mono send(HttpRequest request) { + String url = request.getUrl().toString(); + HttpResponse response; + + if (url.contains("?comp=list&maxresults=")) { + // flat first request + response = response(request, buildFirstRequest()); + } else if (url.contains("?comp=list&marker=")) { + // flat second request + response = response(request, buildSecondRequest()); + } else { + // fallback + return Mono.just(new MockHttpResponse(request, 404)); + } + + return Mono.delay(Duration.ofSeconds(4)).then(Mono.just(response)); + } + } } diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerApiTests.java index 0f47b86c66b4..4bd6062c9e5f 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerApiTests.java @@ -1070,38 +1070,43 @@ public void listBlobsFlatError() { assertThrows(BlobStorageException.class, () -> cc.listBlobs().iterator().hasNext()); } + /* + * For listBlobsFlatWithTimeoutStillBackedByPagedStream and listBlobsHierWithTimeoutStillBackedByPagedStream: + * The custom http client returns a generic xml list of 5 blobs total. + * The api call should return 2 pages, one page of 3 blobs and one page of 2 blobs. + * Although each page is set to take 4 seconds to return, the timeout being set to 6 seconds should not cause the test to fail, + * as the timeout is only on the page request and not the entire stream of pages. + */ + @Test public void listBlobsFlatWithTimeoutStillBackedByPagedStream() { - int numBlobs = 5; - int pageResults = 3; - - for (int i = 0; i < numBlobs; i++) { - BlockBlobClient blob = cc.getBlobClient(generateBlobName()).getBlockBlobClient(); - blob.upload(DATA.getDefaultInputStream(), DATA.getDefaultDataSize()); - } - - // when: "Consume results by page, then still have paging functionality" - assertDoesNotThrow( - () -> cc.listBlobs(new ListBlobsOptions().setMaxResultsPerPage(pageResults), Duration.ofSeconds(10)) + BlobContainerClient containerClient + = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") + .credential(new MockTokenCredential()) + .containerName("foo") + .httpClient(new ListBlobsWithTimeoutTestClient()) + .buildClient(); + + assertEquals(2, + containerClient.listBlobs(new ListBlobsOptions().setMaxResultsPerPage(3), Duration.ofSeconds(6)) .streamByPage() .count()); } @Test public void listBlobsHierWithTimeoutStillBackedByPagedStream() { - int numBlobs = 5; - int pageResults = 3; - - for (int i = 0; i < numBlobs; i++) { - BlockBlobClient blob = cc.getBlobClient(generateBlobName()).getBlockBlobClient(); - blob.upload(DATA.getDefaultInputStream(), DATA.getDefaultDataSize()); - } - - // when: "Consume results by page, then still have paging functionality" - assertDoesNotThrow(() -> cc - .listBlobsByHierarchy("/", new ListBlobsOptions().setMaxResultsPerPage(pageResults), Duration.ofSeconds(10)) - .streamByPage() - .count()); + BlobContainerClient containerClient + = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") + .credential(new MockTokenCredential()) + .containerName("foo") + .httpClient(new ListBlobsWithTimeoutTestClient()) + .buildClient(); + + assertEquals(2, + containerClient + .listBlobsByHierarchy("/", new ListBlobsOptions().setMaxResultsPerPage(3), Duration.ofSeconds(6)) + .streamByPage() + .count()); } /* @@ -1656,26 +1661,28 @@ public void findBlobsError() { assertThrows(BlobStorageException.class, () -> cc.findBlobsByTags("garbageTag").streamByPage().count()); } - @SuppressWarnings("deprecation") + /* + * For findBlobsWithTimeoutStillBackedByPagedStream: + * The custom http client returns a generic xml list of 5 blobs total. + * The api call should return 2 pages, one page of 3 blobs and one page of 2 blobs. + * Although each page is set to take 4 seconds to return, the timeout being set to 6 seconds should not cause the test to fail, + * as the timeout is only on the page request and not the entire stream of pages. + */ + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2021-04-10") @Test public void findBlobsWithTimeoutStillBackedByPagedStream() { - int numBlobs = 5; - int pageResults = 3; - Map tags = Collections.singletonMap(tagKey, tagValue); - - for (int i = 0; i < numBlobs; i++) { - cc.getBlobClient(generateBlobName()) - .uploadWithResponse( - new BlobParallelUploadOptions(DATA.getDefaultInputStream(), DATA.getDefaultDataSize()) - .setTags(tags), - null, null); - } - - // when: "Consume results by page, still have paging functionality" - assertDoesNotThrow(() -> cc.findBlobsByTags( - new FindBlobsOptions(String.format("\"%s\"='%s'", tagKey, tagValue)).setMaxResultsPerPage(pageResults), - Duration.ofSeconds(10), Context.NONE).streamByPage().count()); + BlobContainerClient containerClient + = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") + .credential(new MockTokenCredential()) + .containerName("foo") + .httpClient(new FindBlobsWithTimeoutClient()) + .buildClient(); + + assertEquals(2, + containerClient.findBlobsByTags( + new FindBlobsOptions(String.format("\"%s\"='%s'", "dummyKey", "dummyValue")).setMaxResultsPerPage(3), + Duration.ofSeconds(6), Context.NONE).streamByPage().count()); } @ParameterizedTest diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerAsyncApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerAsyncApiTests.java index bb703086e294..df6570b41b5c 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerAsyncApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerAsyncApiTests.java @@ -1122,38 +1122,46 @@ public void listBlobsFlatError() { StepVerifier.create(ccAsync.listBlobs()).verifyError(BlobStorageException.class); } + /* + * For listBlobsFlatWithTimeoutStillBackedByPagedFlux and listBlobsHierWithTimeoutStillBackedByPagedFlux: + * The custom http client returns a generic xml list of 5 blobs total. + * The api call should return 2 pages, one page of 3 blobs and one page of 2 blobs. + * Although each page is set to take 4 seconds to return, the timeout being set to 6 seconds should not cause the test to fail, + * as the timeout is only on the page request and not the entire stream of pages. + */ @Test public void listBlobsFlatWithTimeoutStillBackedByPagedFlux() { - int numBlobs = 5; - int pageResults = 3; - - Mono> createBlob = Flux.range(0, numBlobs).flatMap(i -> { - BlockBlobAsyncClient blob = ccAsync.getBlobAsyncClient(generateBlobName()).getBlockBlobAsyncClient(); - return blob.upload(DATA.getDefaultFlux(), DATA.getDefaultDataSize()); - }).collectList(); + BlobContainerAsyncClient containerClient + = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") + .credential(new MockTokenCredential()) + .containerName("foo") + .httpClient(new ListBlobsWithTimeoutTestClient()) + .buildAsyncClient(); - // when: "Consume results by page, then still have paging functionality" StepVerifier - .create(createBlob - .thenMany(ccAsync.listBlobs(new ListBlobsOptions().setMaxResultsPerPage(pageResults)).byPage())) + .create( + containerClient + .listBlobsFlatWithOptionalTimeout(new ListBlobsOptions().setMaxResultsPerPage(3), null, + Duration.ofSeconds(6)) + .byPage()) .expectNextCount(2) .verifyComplete(); } @Test public void listBlobsHierWithTimeoutStillBackedByPagedFlux() { - int numBlobs = 5; - int pageResults = 3; - - Mono> createBlob = Flux.range(0, numBlobs).flatMap(i -> { - BlockBlobAsyncClient blob = ccAsync.getBlobAsyncClient(generateBlobName()).getBlockBlobAsyncClient(); - return blob.upload(DATA.getDefaultFlux(), DATA.getDefaultDataSize()); - }).collectList(); + BlobContainerAsyncClient containerClient + = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") + .credential(new MockTokenCredential()) + .containerName("foo") + .httpClient(new ListBlobsWithTimeoutTestClient()) + .buildAsyncClient(); - // when: "Consume results by page, then still have paging functionality" StepVerifier - .create(createBlob.thenMany( - ccAsync.listBlobsByHierarchy("/", new ListBlobsOptions().setMaxResultsPerPage(pageResults)).byPage())) + .create(containerClient + .listBlobsHierarchyWithOptionalTimeout("/", new ListBlobsOptions().setMaxResultsPerPage(3), + Duration.ofSeconds(6)) + .byPage()) .expectNextCount(2) .verifyComplete(); } @@ -1776,33 +1784,27 @@ public void findBlobsError() { StepVerifier.create(ccAsync.findBlobsByTags("garbageTag").byPage()).verifyError(BlobStorageException.class); } - @SuppressWarnings("deprecation") + /* + * For findBlobsWithTimeoutStillBackedByPagedFlux: + * The custom http client returns a generic xml list of 5 blobs total. + * The api call should return 2 pages, one page of 3 blobs and one page of 2 blobs. + * Although each page is set to take 4 seconds to return, the timeout being set to 6 seconds should not cause the test to fail, + * as the timeout is only on the page request and not the entire stream of pages. + */ + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2021-04-10") @Test public void findBlobsWithTimeoutStillBackedByPagedFlux() { - int numBlobs = 5; - int pageResults = 3; - Map tags = Collections.singletonMap(tagKey, tagValue); - - Mono>> uploadBlob = Flux.range(0, numBlobs) - .flatMap(i -> ccAsync.getBlobAsyncClient(generateBlobName()) - .uploadWithResponse( - new BlobParallelUploadOptions(DATA.getDefaultInputStream(), DATA.getDefaultDataSize()) - .setTags(tags))) - .collectList(); + BlobContainerAsyncClient containerClient + = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") + .credential(new MockTokenCredential()) + .containerName("foo") + .httpClient(new FindBlobsWithTimeoutClient()) + .buildAsyncClient(); - // when: "Consume results by page, still have paging functionality" - StepVerifier - .create( - uploadBlob - .thenMany( - ccAsync - .findBlobsByTags(new FindBlobsOptions(String.format("\"%s\"='%s'", tagKey, tagValue)) - .setMaxResultsPerPage(pageResults), Duration.ofSeconds(10), Context.NONE) - .byPage() - .count())) - .expectNextCount(1) - .verifyComplete(); + StepVerifier.create(containerClient.findBlobsByTags( + new FindBlobsOptions(String.format("\"%s\"='%s'", "dummyKey", "dummyValue")).setMaxResultsPerPage(3), + Duration.ofSeconds(6), Context.NONE).byPage()).expectNextCount(2).verifyComplete(); } @ParameterizedTest diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceApiTests.java index aad6eecbe076..60146450b42b 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceApiTests.java @@ -9,6 +9,7 @@ import com.azure.core.http.rest.PagedResponse; import com.azure.core.http.rest.Response; import com.azure.core.test.http.NoOpHttpClient; +import com.azure.core.test.utils.MockTokenCredential; import com.azure.core.util.Context; import com.azure.identity.DefaultAzureCredentialBuilder; import com.azure.storage.blob.models.BlobAnalyticsLogging; @@ -45,7 +46,6 @@ import com.azure.storage.common.test.shared.extensions.PlaybackOnly; import com.azure.storage.common.test.shared.extensions.RequiredServiceVersion; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.parallel.ResourceLock; import org.junit.jupiter.params.ParameterizedTest; @@ -292,25 +292,18 @@ public void listContainersAnonymous() { @Test public void listContainersWithTimeoutStillBackedByPagedStream() { - int numContainers = 5; - int pageResults = 3; + BlobServiceClient serviceClient + = new BlobServiceClientBuilder().endpoint("https://account.blob.core.windows.net/") + .credential(new MockTokenCredential()) + .httpClient(new ListContainersWithTimeoutTestClient()) + .buildClient(); - List containers = new ArrayList<>(); - for (int i = 0; i < numContainers; i++) { - containers.add(primaryBlobServiceClient.createBlobContainer(generateContainerName())); - } - // when: "Consume results by page, then should still have paging functionality"" - assertDoesNotThrow( - () -> primaryBlobServiceClient - .listBlobContainers(new ListBlobContainersOptions().setMaxResultsPerPage(pageResults), - Duration.ofSeconds(10)) + assertEquals(2, + serviceClient + .listBlobContainers(new ListBlobContainersOptions().setMaxResultsPerPage(3), Duration.ofSeconds(6)) .streamByPage() .count()); - // cleanup: - for (BlobContainerClient container : containers) { - container.delete(); - } } @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2020-10-02") @@ -525,30 +518,27 @@ public void findBlobsAnonymous() { } - @SuppressWarnings("deprecation") + /* + * For findBlobsWithTimeoutStillBackedByPagedStream: + * The custom http client returns a generic xml list of 5 blobs total. + * The api call should return 2 pages, one page of 3 blobs and one page of 2 blobs. + * Although each page is set to take 4 seconds to return, the timeout being set to 6 seconds should not cause the test to fail, + * as the timeout is only on the page request and not the entire stream of pages. + */ + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2019-12-12") @Test public void findBlobsWithTimeoutStillBackedByPagedStream() { - int numBlobs = 5; - int pageResults = 3; - BlobContainerClient cc = primaryBlobServiceClient.createBlobContainer(generateContainerName()); - Map tags = Collections.singletonMap(tagKey, tagValue); - - for (int i = 0; i < numBlobs; i++) { - cc.getBlobClient(generateBlobName()) - .uploadWithResponse( - new BlobParallelUploadOptions(DATA.getDefaultInputStream(), DATA.getDefaultDataSize()) - .setTags(tags), - null, null); - } - - // when: "Consume results by page, then still have paging functionality" - assertDoesNotThrow(() -> primaryBlobServiceClient.findBlobsByTags( - new FindBlobsOptions(String.format("\"%s\"='%s'", tagKey, tagValue)).setMaxResultsPerPage(pageResults), - Duration.ofSeconds(10), Context.NONE).streamByPage().count()); + BlobServiceClient serviceClient + = new BlobServiceClientBuilder().endpoint("https://account.blob.core.windows.net/") + .credential(new MockTokenCredential()) + .httpClient(new FindBlobsWithTimeoutClient()) + .buildClient(); - // cleanup: - cc.delete(); + assertEquals(2, + serviceClient.findBlobsByTags( + new FindBlobsOptions(String.format("\"%s\"='%s'", "dummyKey", "dummyValue")).setMaxResultsPerPage(3), + Duration.ofSeconds(6), Context.NONE).streamByPage().count()); } private static void validatePropsSet(BlobServiceProperties sent, BlobServiceProperties received) { diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceAsyncApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceAsyncApiTests.java index 55d8bd119202..2474d7e25d4d 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceAsyncApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceAsyncApiTests.java @@ -8,6 +8,7 @@ import com.azure.core.http.rest.Response; import com.azure.core.test.TestMode; import com.azure.core.test.http.NoOpHttpClient; +import com.azure.core.test.utils.MockTokenCredential; import com.azure.core.util.Context; import com.azure.core.util.paging.ContinuablePage; import com.azure.identity.DefaultAzureCredentialBuilder; @@ -287,18 +288,19 @@ public void listContainersAnonymous() { @Test public void listContainersWithTimeoutStillBackedByPagedFlux() { - int numContainers = 5; - int pageResults = 3; - - Mono> containersMono = Flux.range(0, numContainers) - .flatMap(i -> primaryBlobServiceAsyncClient.createBlobContainer(generateContainerName())) - .collectList(); + BlobServiceAsyncClient serviceClient + = new BlobServiceClientBuilder().endpoint("https://account.blob.core.windows.net/") + .credential(new MockTokenCredential()) + .httpClient(new ListContainersWithTimeoutTestClient()) + .buildAsyncClient(); - StepVerifier.create(containersMono.flatMapMany(containers -> primaryBlobServiceAsyncClient - .listBlobContainersWithOptionalTimeout(new ListBlobContainersOptions().setMaxResultsPerPage(pageResults), - Duration.ofSeconds(10)) - .byPage() - .count())).expectNextCount(1).verifyComplete(); + StepVerifier + .create(serviceClient + .listBlobContainersWithOptionalTimeout(new ListBlobContainersOptions().setMaxResultsPerPage(3), + Duration.ofSeconds(6)) + .byPage()) + .expectNextCount(2) + .verifyComplete(); } @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2020-10-02") @@ -500,28 +502,26 @@ public void findBlobsAnonymous() { StepVerifier.create(anonymousClient.findBlobsByTags("foo=bar")).verifyError(IllegalStateException.class); } - @SuppressWarnings("deprecation") + /* + * For findBlobsWithTimeoutStillBackedByPagedFlux: + * The custom http client returns a generic xml list of 5 blobs total. + * The api call should return 2 pages, one page of 3 blobs and one page of 2 blobs. + * Although each page is set to take 4 seconds to return, the timeout being set to 6 seconds should not cause the test to fail, + * as the timeout is only on the page request and not the entire stream of pages. + */ + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2019-12-12") @Test public void findBlobsWithTimeoutStillBackedByPagedFlux() { - int numBlobs = 5; - int pageResults = 3; - Map tags = Collections.singletonMap(tagKey, tagValue); - - Mono response = primaryBlobServiceAsyncClient.createBlobContainer(generateContainerName()).flatMap(cc -> { - Flux> upload = Flux.range(0, numBlobs) - .flatMap(i -> cc.getBlobAsyncClient(generateBlobName()) - .uploadWithResponse( - new BlobParallelUploadOptions(DATA.getDefaultInputStream(), DATA.getDefaultDataSize()) - .setTags(tags))); - // when: "Consume results by page, then still have paging functionality" - return upload.then(primaryBlobServiceAsyncClient.findBlobsByTags( - new FindBlobsOptions(String.format("\"%s\"='%s'", tagKey, tagValue)).setMaxResultsPerPage(pageResults)) - .byPage() - .count()); - }); + BlobServiceAsyncClient serviceClient + = new BlobServiceClientBuilder().endpoint("https://account.blob.core.windows.net/") + .credential(new MockTokenCredential()) + .httpClient(new FindBlobsWithTimeoutClient()) + .buildAsyncClient(); - StepVerifier.create(response).expectNextCount(1).verifyComplete(); + StepVerifier.create(serviceClient.findBlobsByTags( + new FindBlobsOptions(String.format("\"%s\"='%s'", "dummyKey", "dummyValue")).setMaxResultsPerPage(3), + Duration.ofSeconds(6), Context.NONE).byPage()).expectNextCount(2).verifyComplete(); } private static void validatePropsSet(BlobServiceProperties sent, BlobServiceProperties received) { diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobApiTests.java index bf377ebe06c6..7a4d162c7d85 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/BlockBlobApiTests.java @@ -377,11 +377,11 @@ public void stageBlockFromUrl() { @Test public void stageBlockFromUrlSourceErrorAndStatusCode() { BlockBlobClient destBlob = cc.getBlobClient(generateBlobName()).getBlockBlobClient(); - + String blockID = getBlockID(); - + BlobStorageException e = assertThrows(BlobStorageException.class, () -> destBlob.stageBlockFromUrl(blockID, blockBlobClient.getBlobUrl(), new BlobRange(0, (long) PageBlobClient.PAGE_BYTES))); - + assertTrue(e.getStatusCode() == 409); assertTrue(e.getServiceMessage().contains("PublicAccessNotPermitted")); assertTrue(e.getServiceMessage().contains("Public access is not permitted on this storage account.")); @@ -1417,9 +1417,9 @@ public void uploadFromUrlMin() { @Test public void uploadFromUrlSourceErrorAndStatusCode() { BlockBlobClient destBlob = cc.getBlobClient(generateBlobName()).getBlockBlobClient(); - + BlobStorageException e = assertThrows(BlobStorageException.class, () -> destBlob.uploadFromUrl(blockBlobClient.getBlobUrl())); - + assertTrue(e.getStatusCode() == 409); assertTrue(e.getServiceMessage().contains("PublicAccessNotPermitted")); assertTrue(e.getServiceMessage().contains("Public access is not permitted on this storage account.")); From 1e1d1ffef2a4a8fffe1a78e58e674671d1453853 Mon Sep 17 00:00:00 2001 From: Isabelle Date: Mon, 12 May 2025 13:34:09 -0700 Subject: [PATCH 12/16] adding recordings --- sdk/storage/azure-storage-blob/assets.json | 2 +- .../test/java/com/azure/storage/blob/ServiceApiTests.java | 8 ++++++++ .../java/com/azure/storage/blob/ServiceAsyncApiTests.java | 8 ++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/sdk/storage/azure-storage-blob/assets.json b/sdk/storage/azure-storage-blob/assets.json index e8388dbaa150..7aed1248ffa7 100644 --- a/sdk/storage/azure-storage-blob/assets.json +++ b/sdk/storage/azure-storage-blob/assets.json @@ -2,5 +2,5 @@ "AssetsRepo": "Azure/azure-sdk-assets", "AssetsRepoPrefixPath": "java", "TagPrefix": "java/storage/azure-storage-blob", - "Tag": "java/storage/azure-storage-blob_e4ae407bc2" + "Tag": "java/storage/azure-storage-blob_0c7e10b175" } diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceApiTests.java index 60146450b42b..bd09aa03f3d4 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceApiTests.java @@ -290,6 +290,14 @@ public void listContainersAnonymous() { assertThrows(IllegalStateException.class, () -> anonymousClient.listBlobContainers().iterator()); } + /* + * For listContainersWithTimeoutStillBackedByPagedStream: + * The custom http client returns a generic xml list of 5 blobs total. + * The api call should return 2 pages, one page of 3 blobs and one page of 2 blobs. + * Although each page is set to take 4 seconds to return, the timeout being set to 6 seconds should not cause the test to fail, + * as the timeout is only on the page request and not the entire stream of pages. + */ + @Test public void listContainersWithTimeoutStillBackedByPagedStream() { BlobServiceClient serviceClient diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceAsyncApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceAsyncApiTests.java index 2474d7e25d4d..9a1d686308ab 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceAsyncApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceAsyncApiTests.java @@ -286,6 +286,14 @@ public void listContainersAnonymous() { StepVerifier.create(anonymousClient.listBlobContainers()).verifyError(IllegalStateException.class); } + /* + * For listContainersWithTimeoutStillBackedByPagedFlux: + * The custom http client returns a generic xml list of 5 blobs total. + * The api call should return 2 pages, one page of 3 blobs and one page of 2 blobs. + * Although each page is set to take 4 seconds to return, the timeout being set to 6 seconds should not cause the test to fail, + * as the timeout is only on the page request and not the entire stream of pages. + */ + @Test public void listContainersWithTimeoutStillBackedByPagedFlux() { BlobServiceAsyncClient serviceClient From fd928ed455461475f1da58f1cfae03181f8b5286 Mon Sep 17 00:00:00 2001 From: Isabelle Date: Mon, 12 May 2025 14:28:09 -0700 Subject: [PATCH 13/16] increasing timeouts for sync tests --- .../com/azure/storage/blob/BlobTestBase.java | 24 ++++++++++++++++--- .../azure/storage/blob/ContainerApiTests.java | 12 +++++----- .../storage/blob/ContainerAsyncApiTests.java | 6 ++--- .../azure/storage/blob/ServiceApiTests.java | 8 +++---- .../storage/blob/ServiceAsyncApiTests.java | 4 ++-- 5 files changed, 36 insertions(+), 18 deletions(-) diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobTestBase.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobTestBase.java index 8539ce65b02c..2d41bf3f890e 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobTestBase.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobTestBase.java @@ -1083,6 +1083,11 @@ protected static TokenCredential getTokenCredential(TestMode testMode) { } protected static final class ListBlobsWithTimeoutTestClient implements HttpClient { + private final boolean isAsync; + + ListBlobsWithTimeoutTestClient(Boolean isAsync) { + this.isAsync = isAsync; + } private HttpResponse response(HttpRequest request, String xml) { HttpHeaders headers = new HttpHeaders().set(HttpHeaderName.CONTENT_TYPE, "application/xml"); @@ -1113,6 +1118,7 @@ private String buildSecondRequest(Boolean useDelimiter) { public Mono send(HttpRequest request) { String url = request.getUrl().toString(); HttpResponse response; + int delay = isAsync ? 8 : 4; if (url.contains("?restype=container&comp=list&maxresults=")) { // flat first request @@ -1131,11 +1137,16 @@ public Mono send(HttpRequest request) { return Mono.just(new MockHttpResponse(request, 404)); } - return Mono.delay(Duration.ofSeconds(4)).then(Mono.just(response)); + return Mono.delay(Duration.ofSeconds(delay)).then(Mono.just(response)); } } protected static final class FindBlobsWithTimeoutClient implements HttpClient { + private final boolean isAsync; + + FindBlobsWithTimeoutClient(Boolean isAsync) { + this.isAsync = isAsync; + } private HttpResponse response(HttpRequest request, String xml) { HttpHeaders headers = new HttpHeaders().set(HttpHeaderName.CONTENT_TYPE, "application/xml"); @@ -1172,6 +1183,7 @@ private String buildSecondRequest() { public Mono send(HttpRequest request) { String url = request.getUrl().toString(); HttpResponse response; + int delay = isAsync ? 8 : 4; if (url.contains("marker")) { // second request @@ -1184,11 +1196,16 @@ public Mono send(HttpRequest request) { return Mono.just(new MockHttpResponse(request, 404)); } - return Mono.delay(Duration.ofSeconds(4)).then(Mono.just(response)); + return Mono.delay(Duration.ofSeconds(delay)).then(Mono.just(response)); } } protected static final class ListContainersWithTimeoutTestClient implements HttpClient { + private final boolean isAsync; + + ListContainersWithTimeoutTestClient(Boolean isAsync) { + this.isAsync = isAsync; + } private HttpResponse response(HttpRequest request, String xml) { HttpHeaders headers = new HttpHeaders().set(HttpHeaderName.CONTENT_TYPE, "application/xml"); @@ -1216,6 +1233,7 @@ private String buildSecondRequest() { public Mono send(HttpRequest request) { String url = request.getUrl().toString(); HttpResponse response; + int delay = isAsync ? 8 : 4; if (url.contains("?comp=list&maxresults=")) { // flat first request @@ -1228,7 +1246,7 @@ public Mono send(HttpRequest request) { return Mono.just(new MockHttpResponse(request, 404)); } - return Mono.delay(Duration.ofSeconds(4)).then(Mono.just(response)); + return Mono.delay(Duration.ofSeconds(delay)).then(Mono.just(response)); } } } diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerApiTests.java index 4bd6062c9e5f..1f3ea9d5bf0f 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerApiTests.java @@ -1084,11 +1084,11 @@ public void listBlobsFlatWithTimeoutStillBackedByPagedStream() { = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") .credential(new MockTokenCredential()) .containerName("foo") - .httpClient(new ListBlobsWithTimeoutTestClient()) + .httpClient(new ListBlobsWithTimeoutTestClient(false)) .buildClient(); assertEquals(2, - containerClient.listBlobs(new ListBlobsOptions().setMaxResultsPerPage(3), Duration.ofSeconds(6)) + containerClient.listBlobs(new ListBlobsOptions().setMaxResultsPerPage(3), Duration.ofSeconds(14)) .streamByPage() .count()); } @@ -1099,12 +1099,12 @@ public void listBlobsHierWithTimeoutStillBackedByPagedStream() { = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") .credential(new MockTokenCredential()) .containerName("foo") - .httpClient(new ListBlobsWithTimeoutTestClient()) + .httpClient(new ListBlobsWithTimeoutTestClient(false)) .buildClient(); assertEquals(2, containerClient - .listBlobsByHierarchy("/", new ListBlobsOptions().setMaxResultsPerPage(3), Duration.ofSeconds(6)) + .listBlobsByHierarchy("/", new ListBlobsOptions().setMaxResultsPerPage(3), Duration.ofSeconds(14)) .streamByPage() .count()); } @@ -1676,13 +1676,13 @@ public void findBlobsWithTimeoutStillBackedByPagedStream() { = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") .credential(new MockTokenCredential()) .containerName("foo") - .httpClient(new FindBlobsWithTimeoutClient()) + .httpClient(new FindBlobsWithTimeoutClient(false)) .buildClient(); assertEquals(2, containerClient.findBlobsByTags( new FindBlobsOptions(String.format("\"%s\"='%s'", "dummyKey", "dummyValue")).setMaxResultsPerPage(3), - Duration.ofSeconds(6), Context.NONE).streamByPage().count()); + Duration.ofSeconds(14), Context.NONE).streamByPage().count()); } @ParameterizedTest diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerAsyncApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerAsyncApiTests.java index df6570b41b5c..fee4ef24df05 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerAsyncApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerAsyncApiTests.java @@ -1135,7 +1135,7 @@ public void listBlobsFlatWithTimeoutStillBackedByPagedFlux() { = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") .credential(new MockTokenCredential()) .containerName("foo") - .httpClient(new ListBlobsWithTimeoutTestClient()) + .httpClient(new ListBlobsWithTimeoutTestClient(true)) .buildAsyncClient(); StepVerifier @@ -1154,7 +1154,7 @@ public void listBlobsHierWithTimeoutStillBackedByPagedFlux() { = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") .credential(new MockTokenCredential()) .containerName("foo") - .httpClient(new ListBlobsWithTimeoutTestClient()) + .httpClient(new ListBlobsWithTimeoutTestClient(true)) .buildAsyncClient(); StepVerifier @@ -1799,7 +1799,7 @@ public void findBlobsWithTimeoutStillBackedByPagedFlux() { = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") .credential(new MockTokenCredential()) .containerName("foo") - .httpClient(new FindBlobsWithTimeoutClient()) + .httpClient(new FindBlobsWithTimeoutClient(true)) .buildAsyncClient(); StepVerifier.create(containerClient.findBlobsByTags( diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceApiTests.java index bd09aa03f3d4..8fda9fd9cbd0 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceApiTests.java @@ -303,12 +303,12 @@ public void listContainersWithTimeoutStillBackedByPagedStream() { BlobServiceClient serviceClient = new BlobServiceClientBuilder().endpoint("https://account.blob.core.windows.net/") .credential(new MockTokenCredential()) - .httpClient(new ListContainersWithTimeoutTestClient()) + .httpClient(new ListContainersWithTimeoutTestClient(false)) .buildClient(); assertEquals(2, serviceClient - .listBlobContainers(new ListBlobContainersOptions().setMaxResultsPerPage(3), Duration.ofSeconds(6)) + .listBlobContainers(new ListBlobContainersOptions().setMaxResultsPerPage(3), Duration.ofSeconds(14)) .streamByPage() .count()); @@ -540,13 +540,13 @@ public void findBlobsWithTimeoutStillBackedByPagedStream() { BlobServiceClient serviceClient = new BlobServiceClientBuilder().endpoint("https://account.blob.core.windows.net/") .credential(new MockTokenCredential()) - .httpClient(new FindBlobsWithTimeoutClient()) + .httpClient(new FindBlobsWithTimeoutClient(false)) .buildClient(); assertEquals(2, serviceClient.findBlobsByTags( new FindBlobsOptions(String.format("\"%s\"='%s'", "dummyKey", "dummyValue")).setMaxResultsPerPage(3), - Duration.ofSeconds(6), Context.NONE).streamByPage().count()); + Duration.ofSeconds(14), Context.NONE).streamByPage().count()); } private static void validatePropsSet(BlobServiceProperties sent, BlobServiceProperties received) { diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceAsyncApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceAsyncApiTests.java index 9a1d686308ab..8c679a5d2753 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceAsyncApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceAsyncApiTests.java @@ -299,7 +299,7 @@ public void listContainersWithTimeoutStillBackedByPagedFlux() { BlobServiceAsyncClient serviceClient = new BlobServiceClientBuilder().endpoint("https://account.blob.core.windows.net/") .credential(new MockTokenCredential()) - .httpClient(new ListContainersWithTimeoutTestClient()) + .httpClient(new ListContainersWithTimeoutTestClient(true)) .buildAsyncClient(); StepVerifier @@ -524,7 +524,7 @@ public void findBlobsWithTimeoutStillBackedByPagedFlux() { BlobServiceAsyncClient serviceClient = new BlobServiceClientBuilder().endpoint("https://account.blob.core.windows.net/") .credential(new MockTokenCredential()) - .httpClient(new FindBlobsWithTimeoutClient()) + .httpClient(new FindBlobsWithTimeoutClient(true)) .buildAsyncClient(); StepVerifier.create(serviceClient.findBlobsByTags( From ac9451eb1209f893ab0f89bc04162abbd42ac641 Mon Sep 17 00:00:00 2001 From: Isabelle Date: Mon, 12 May 2025 15:00:06 -0700 Subject: [PATCH 14/16] fixing timeout mistake in ternary operator --- .../src/test/java/com/azure/storage/blob/BlobTestBase.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobTestBase.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobTestBase.java index 2d41bf3f890e..1af61ef87f7f 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobTestBase.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobTestBase.java @@ -1118,7 +1118,7 @@ private String buildSecondRequest(Boolean useDelimiter) { public Mono send(HttpRequest request) { String url = request.getUrl().toString(); HttpResponse response; - int delay = isAsync ? 8 : 4; + int delay = isAsync ? 4 : 8; if (url.contains("?restype=container&comp=list&maxresults=")) { // flat first request @@ -1183,7 +1183,7 @@ private String buildSecondRequest() { public Mono send(HttpRequest request) { String url = request.getUrl().toString(); HttpResponse response; - int delay = isAsync ? 8 : 4; + int delay = isAsync ? 4 : 8; if (url.contains("marker")) { // second request @@ -1233,7 +1233,7 @@ private String buildSecondRequest() { public Mono send(HttpRequest request) { String url = request.getUrl().toString(); HttpResponse response; - int delay = isAsync ? 8 : 4; + int delay = isAsync ? 4 : 8; if (url.contains("?comp=list&maxresults=")) { // flat first request From e6ba8743dcef6a191212491c294f1986508d19a0 Mon Sep 17 00:00:00 2001 From: Isabelle Date: Tue, 13 May 2025 11:44:45 -0700 Subject: [PATCH 15/16] moving timeout tests to an isolated test file --- .../com/azure/storage/blob/BlobTestBase.java | 168 ---------- .../azure/storage/blob/ContainerApiTests.java | 64 ---- .../storage/blob/ContainerAsyncApiTests.java | 67 ---- .../azure/storage/blob/ServiceApiTests.java | 48 --- .../storage/blob/ServiceAsyncApiTests.java | 48 --- .../azure/storage/blob/TimeoutAsyncTests.java | 112 +++++++ .../com/azure/storage/blob/TimeoutTests.java | 288 ++++++++++++++++++ .../specialized/HttpFaultInjectingTests.java | 3 + 8 files changed, 403 insertions(+), 395 deletions(-) create mode 100644 sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/TimeoutAsyncTests.java create mode 100644 sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/TimeoutTests.java diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobTestBase.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobTestBase.java index 1af61ef87f7f..fe6a011b8ee9 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobTestBase.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobTestBase.java @@ -22,7 +22,6 @@ import com.azure.core.http.rest.Response; import com.azure.core.test.TestMode; import com.azure.core.test.TestProxyTestBase; -import com.azure.core.test.http.MockHttpResponse; import com.azure.core.test.models.CustomMatcher; import com.azure.core.test.models.TestProxySanitizer; import com.azure.core.test.models.TestProxySanitizerType; @@ -1082,171 +1081,4 @@ protected static TokenCredential getTokenCredential(TestMode testMode) { } } - protected static final class ListBlobsWithTimeoutTestClient implements HttpClient { - private final boolean isAsync; - - ListBlobsWithTimeoutTestClient(Boolean isAsync) { - this.isAsync = isAsync; - } - - private HttpResponse response(HttpRequest request, String xml) { - HttpHeaders headers = new HttpHeaders().set(HttpHeaderName.CONTENT_TYPE, "application/xml"); - return new MockHttpResponse(request, 200, headers, xml.getBytes(StandardCharsets.UTF_8)); - } - - private String buildFirstRequest(Boolean useDelimiter) { - String delimiterString = useDelimiter ? "/" : ""; - - return "" - + "" - + "3" + delimiterString + "" + "" + "blob1" - + "" + "" + "blob2" + "" + "" + "blob3" + "" - + "" + "MARKER--" + ""; - } - - private String buildSecondRequest(Boolean useDelimiter) { - String delimiterString = useDelimiter ? "/" : ""; - - return "" - + "" - + "MARKER--" + "3" + delimiterString + "" + "" - + "blob4" + "" + "" + "blob5" + "" + "" - + "" + ""; - } - - @Override - public Mono send(HttpRequest request) { - String url = request.getUrl().toString(); - HttpResponse response; - int delay = isAsync ? 4 : 8; - - if (url.contains("?restype=container&comp=list&maxresults=")) { - // flat first request - response = response(request, buildFirstRequest(false)); - } else if (url.contains("?restype=container&comp=list&marker=")) { - // flat second request - response = response(request, buildSecondRequest(false)); - } else if (url.contains("?restype=container&comp=list&delimiter=/&maxresults=")) { - // hierarchy first request - response = response(request, buildFirstRequest(true)); - } else if (url.contains("?restype=container&comp=list&delimiter=/&marker=")) { - // hierarchy second request - response = response(request, buildSecondRequest(true)); - } else { - // fallback - return Mono.just(new MockHttpResponse(request, 404)); - } - - return Mono.delay(Duration.ofSeconds(delay)).then(Mono.just(response)); - } - } - - protected static final class FindBlobsWithTimeoutClient implements HttpClient { - private final boolean isAsync; - - FindBlobsWithTimeoutClient(Boolean isAsync) { - this.isAsync = isAsync; - } - - private HttpResponse response(HttpRequest request, String xml) { - HttpHeaders headers = new HttpHeaders().set(HttpHeaderName.CONTENT_TYPE, "application/xml"); - return new MockHttpResponse(request, 200, headers, xml.getBytes(StandardCharsets.UTF_8)); - } - - private String buildFirstRequest() { - return "" - + "" - + ""dummyKey"='dummyValue'" + "3" - + "" + "" + "blob1" + "foo" + "" - + "" + "" + "dummyKey" + "dummyValue" + "" + "" - + "" + "" + "" + "blob2" + "foo" - + "" + "" + "" + "dummyKey" + "dummyValue" + "" - + "" + "" + "" + "" + "blob3" - + "foo" + "" + "" + "" + "dummyKey" - + "dummyValue" + "" + "" + "" + "" + "" - + "MARKER-" + ""; - } - - private String buildSecondRequest() { - return "" - + "" - + "MARKER-" + ""dummyKey"='dummyValue'" - + "3" + "" + "" + "blob4" - + "foo" + "" + "" + "" + "dummyKey" - + "dummyValue" + "" + "" + "" + "" + "" - + "blob5" + "foo" + "" + "" + "" - + "dummyKey" + "dummyValue" + "" + "" + "" + "" - + "" + "" + ""; - } - - @Override - public Mono send(HttpRequest request) { - String url = request.getUrl().toString(); - HttpResponse response; - int delay = isAsync ? 4 : 8; - - if (url.contains("marker")) { - // second request - response = response(request, buildSecondRequest()); - } else if (url.contains("?comp=blobs&where=%") || url.contains("?restype=container&comp=blobs&where=%")) { - // first request - response = response(request, buildFirstRequest()); - } else { - // fallback - return Mono.just(new MockHttpResponse(request, 404)); - } - - return Mono.delay(Duration.ofSeconds(delay)).then(Mono.just(response)); - } - } - - protected static final class ListContainersWithTimeoutTestClient implements HttpClient { - private final boolean isAsync; - - ListContainersWithTimeoutTestClient(Boolean isAsync) { - this.isAsync = isAsync; - } - - private HttpResponse response(HttpRequest request, String xml) { - HttpHeaders headers = new HttpHeaders().set(HttpHeaderName.CONTENT_TYPE, "application/xml"); - return new MockHttpResponse(request, 200, headers, xml.getBytes(StandardCharsets.UTF_8)); - } - - private String buildFirstRequest() { - return "" - + "" - + "3" + "" + "" + "container1" - + "" + "" + "container2" + "" + "" - + "container3" + "" + "" - + "/marker/marker" + ""; - } - - private String buildSecondRequest() { - return "" - + "" - + "/marker/marker" + "3" + "" + "" - + "container4" + "" + "" + "container5" - + "" + "" + "" + ""; - } - - @Override - public Mono send(HttpRequest request) { - String url = request.getUrl().toString(); - HttpResponse response; - int delay = isAsync ? 4 : 8; - - if (url.contains("?comp=list&maxresults=")) { - // flat first request - response = response(request, buildFirstRequest()); - } else if (url.contains("?comp=list&marker=")) { - // flat second request - response = response(request, buildSecondRequest()); - } else { - // fallback - return Mono.just(new MockHttpResponse(request, 404)); - } - - return Mono.delay(Duration.ofSeconds(delay)).then(Mono.just(response)); - } - } } diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerApiTests.java index 1f3ea9d5bf0f..f8fab37840a7 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerApiTests.java @@ -59,7 +59,6 @@ import java.io.ByteArrayInputStream; import java.net.URL; -import java.time.Duration; import java.time.OffsetDateTime; import java.util.Arrays; import java.util.Base64; @@ -1070,45 +1069,6 @@ public void listBlobsFlatError() { assertThrows(BlobStorageException.class, () -> cc.listBlobs().iterator().hasNext()); } - /* - * For listBlobsFlatWithTimeoutStillBackedByPagedStream and listBlobsHierWithTimeoutStillBackedByPagedStream: - * The custom http client returns a generic xml list of 5 blobs total. - * The api call should return 2 pages, one page of 3 blobs and one page of 2 blobs. - * Although each page is set to take 4 seconds to return, the timeout being set to 6 seconds should not cause the test to fail, - * as the timeout is only on the page request and not the entire stream of pages. - */ - - @Test - public void listBlobsFlatWithTimeoutStillBackedByPagedStream() { - BlobContainerClient containerClient - = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") - .credential(new MockTokenCredential()) - .containerName("foo") - .httpClient(new ListBlobsWithTimeoutTestClient(false)) - .buildClient(); - - assertEquals(2, - containerClient.listBlobs(new ListBlobsOptions().setMaxResultsPerPage(3), Duration.ofSeconds(14)) - .streamByPage() - .count()); - } - - @Test - public void listBlobsHierWithTimeoutStillBackedByPagedStream() { - BlobContainerClient containerClient - = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") - .credential(new MockTokenCredential()) - .containerName("foo") - .httpClient(new ListBlobsWithTimeoutTestClient(false)) - .buildClient(); - - assertEquals(2, - containerClient - .listBlobsByHierarchy("/", new ListBlobsOptions().setMaxResultsPerPage(3), Duration.ofSeconds(14)) - .streamByPage() - .count()); - } - /* This test requires two accounts that are configured in a very specific way. It is not feasible to setup that relationship programmatically, so we have recorded a successful interaction and only test recordings. @@ -1661,30 +1621,6 @@ public void findBlobsError() { assertThrows(BlobStorageException.class, () -> cc.findBlobsByTags("garbageTag").streamByPage().count()); } - /* - * For findBlobsWithTimeoutStillBackedByPagedStream: - * The custom http client returns a generic xml list of 5 blobs total. - * The api call should return 2 pages, one page of 3 blobs and one page of 2 blobs. - * Although each page is set to take 4 seconds to return, the timeout being set to 6 seconds should not cause the test to fail, - * as the timeout is only on the page request and not the entire stream of pages. - */ - - @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2021-04-10") - @Test - public void findBlobsWithTimeoutStillBackedByPagedStream() { - BlobContainerClient containerClient - = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") - .credential(new MockTokenCredential()) - .containerName("foo") - .httpClient(new FindBlobsWithTimeoutClient(false)) - .buildClient(); - - assertEquals(2, - containerClient.findBlobsByTags( - new FindBlobsOptions(String.format("\"%s\"='%s'", "dummyKey", "dummyValue")).setMaxResultsPerPage(3), - Duration.ofSeconds(14), Context.NONE).streamByPage().count()); - } - @ParameterizedTest @ValueSource(strings = { "中文", "az[]", "hello world", "hello/world", "hello&world", "!*'();:@&=+/$,/?#[]" }) public void createURLSpecialChars(String name) { diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerAsyncApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerAsyncApiTests.java index fee4ef24df05..e07cf26b6e84 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerAsyncApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ContainerAsyncApiTests.java @@ -1122,50 +1122,6 @@ public void listBlobsFlatError() { StepVerifier.create(ccAsync.listBlobs()).verifyError(BlobStorageException.class); } - /* - * For listBlobsFlatWithTimeoutStillBackedByPagedFlux and listBlobsHierWithTimeoutStillBackedByPagedFlux: - * The custom http client returns a generic xml list of 5 blobs total. - * The api call should return 2 pages, one page of 3 blobs and one page of 2 blobs. - * Although each page is set to take 4 seconds to return, the timeout being set to 6 seconds should not cause the test to fail, - * as the timeout is only on the page request and not the entire stream of pages. - */ - @Test - public void listBlobsFlatWithTimeoutStillBackedByPagedFlux() { - BlobContainerAsyncClient containerClient - = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") - .credential(new MockTokenCredential()) - .containerName("foo") - .httpClient(new ListBlobsWithTimeoutTestClient(true)) - .buildAsyncClient(); - - StepVerifier - .create( - containerClient - .listBlobsFlatWithOptionalTimeout(new ListBlobsOptions().setMaxResultsPerPage(3), null, - Duration.ofSeconds(6)) - .byPage()) - .expectNextCount(2) - .verifyComplete(); - } - - @Test - public void listBlobsHierWithTimeoutStillBackedByPagedFlux() { - BlobContainerAsyncClient containerClient - = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") - .credential(new MockTokenCredential()) - .containerName("foo") - .httpClient(new ListBlobsWithTimeoutTestClient(true)) - .buildAsyncClient(); - - StepVerifier - .create(containerClient - .listBlobsHierarchyWithOptionalTimeout("/", new ListBlobsOptions().setMaxResultsPerPage(3), - Duration.ofSeconds(6)) - .byPage()) - .expectNextCount(2) - .verifyComplete(); - } - /* This test requires two accounts that are configured in a very specific way. It is not feasible to setup that relationship programmatically, so we have recorded a successful interaction and only test recordings. @@ -1784,29 +1740,6 @@ public void findBlobsError() { StepVerifier.create(ccAsync.findBlobsByTags("garbageTag").byPage()).verifyError(BlobStorageException.class); } - /* - * For findBlobsWithTimeoutStillBackedByPagedFlux: - * The custom http client returns a generic xml list of 5 blobs total. - * The api call should return 2 pages, one page of 3 blobs and one page of 2 blobs. - * Although each page is set to take 4 seconds to return, the timeout being set to 6 seconds should not cause the test to fail, - * as the timeout is only on the page request and not the entire stream of pages. - */ - - @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2021-04-10") - @Test - public void findBlobsWithTimeoutStillBackedByPagedFlux() { - BlobContainerAsyncClient containerClient - = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") - .credential(new MockTokenCredential()) - .containerName("foo") - .httpClient(new FindBlobsWithTimeoutClient(true)) - .buildAsyncClient(); - - StepVerifier.create(containerClient.findBlobsByTags( - new FindBlobsOptions(String.format("\"%s\"='%s'", "dummyKey", "dummyValue")).setMaxResultsPerPage(3), - Duration.ofSeconds(6), Context.NONE).byPage()).expectNextCount(2).verifyComplete(); - } - @ParameterizedTest @ValueSource(strings = { "中文", "az[]", "hello world", "hello/world", "hello&world", "!*'();:@&=+/$,/?#[]" }) public void createURLSpecialChars(String name) { diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceApiTests.java index 8fda9fd9cbd0..86da4b6d98b0 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceApiTests.java @@ -9,7 +9,6 @@ import com.azure.core.http.rest.PagedResponse; import com.azure.core.http.rest.Response; import com.azure.core.test.http.NoOpHttpClient; -import com.azure.core.test.utils.MockTokenCredential; import com.azure.core.util.Context; import com.azure.identity.DefaultAzureCredentialBuilder; import com.azure.storage.blob.models.BlobAnalyticsLogging; @@ -290,30 +289,6 @@ public void listContainersAnonymous() { assertThrows(IllegalStateException.class, () -> anonymousClient.listBlobContainers().iterator()); } - /* - * For listContainersWithTimeoutStillBackedByPagedStream: - * The custom http client returns a generic xml list of 5 blobs total. - * The api call should return 2 pages, one page of 3 blobs and one page of 2 blobs. - * Although each page is set to take 4 seconds to return, the timeout being set to 6 seconds should not cause the test to fail, - * as the timeout is only on the page request and not the entire stream of pages. - */ - - @Test - public void listContainersWithTimeoutStillBackedByPagedStream() { - BlobServiceClient serviceClient - = new BlobServiceClientBuilder().endpoint("https://account.blob.core.windows.net/") - .credential(new MockTokenCredential()) - .httpClient(new ListContainersWithTimeoutTestClient(false)) - .buildClient(); - - assertEquals(2, - serviceClient - .listBlobContainers(new ListBlobContainersOptions().setMaxResultsPerPage(3), Duration.ofSeconds(14)) - .streamByPage() - .count()); - - } - @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2020-10-02") @Test @ResourceLock("ServiceProperties") @@ -526,29 +501,6 @@ public void findBlobsAnonymous() { } - /* - * For findBlobsWithTimeoutStillBackedByPagedStream: - * The custom http client returns a generic xml list of 5 blobs total. - * The api call should return 2 pages, one page of 3 blobs and one page of 2 blobs. - * Although each page is set to take 4 seconds to return, the timeout being set to 6 seconds should not cause the test to fail, - * as the timeout is only on the page request and not the entire stream of pages. - */ - - @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2019-12-12") - @Test - public void findBlobsWithTimeoutStillBackedByPagedStream() { - BlobServiceClient serviceClient - = new BlobServiceClientBuilder().endpoint("https://account.blob.core.windows.net/") - .credential(new MockTokenCredential()) - .httpClient(new FindBlobsWithTimeoutClient(false)) - .buildClient(); - - assertEquals(2, - serviceClient.findBlobsByTags( - new FindBlobsOptions(String.format("\"%s\"='%s'", "dummyKey", "dummyValue")).setMaxResultsPerPage(3), - Duration.ofSeconds(14), Context.NONE).streamByPage().count()); - } - private static void validatePropsSet(BlobServiceProperties sent, BlobServiceProperties received) { assertEquals(sent.getLogging().isRead(), received.getLogging().isRead()); assertEquals(sent.getLogging().isWrite(), received.getLogging().isWrite()); diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceAsyncApiTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceAsyncApiTests.java index 8c679a5d2753..af576303551d 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceAsyncApiTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceAsyncApiTests.java @@ -8,7 +8,6 @@ import com.azure.core.http.rest.Response; import com.azure.core.test.TestMode; import com.azure.core.test.http.NoOpHttpClient; -import com.azure.core.test.utils.MockTokenCredential; import com.azure.core.util.Context; import com.azure.core.util.paging.ContinuablePage; import com.azure.identity.DefaultAzureCredentialBuilder; @@ -286,31 +285,6 @@ public void listContainersAnonymous() { StepVerifier.create(anonymousClient.listBlobContainers()).verifyError(IllegalStateException.class); } - /* - * For listContainersWithTimeoutStillBackedByPagedFlux: - * The custom http client returns a generic xml list of 5 blobs total. - * The api call should return 2 pages, one page of 3 blobs and one page of 2 blobs. - * Although each page is set to take 4 seconds to return, the timeout being set to 6 seconds should not cause the test to fail, - * as the timeout is only on the page request and not the entire stream of pages. - */ - - @Test - public void listContainersWithTimeoutStillBackedByPagedFlux() { - BlobServiceAsyncClient serviceClient - = new BlobServiceClientBuilder().endpoint("https://account.blob.core.windows.net/") - .credential(new MockTokenCredential()) - .httpClient(new ListContainersWithTimeoutTestClient(true)) - .buildAsyncClient(); - - StepVerifier - .create(serviceClient - .listBlobContainersWithOptionalTimeout(new ListBlobContainersOptions().setMaxResultsPerPage(3), - Duration.ofSeconds(6)) - .byPage()) - .expectNextCount(2) - .verifyComplete(); - } - @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2020-10-02") @Test @ResourceLock("ServiceProperties") @@ -510,28 +484,6 @@ public void findBlobsAnonymous() { StepVerifier.create(anonymousClient.findBlobsByTags("foo=bar")).verifyError(IllegalStateException.class); } - /* - * For findBlobsWithTimeoutStillBackedByPagedFlux: - * The custom http client returns a generic xml list of 5 blobs total. - * The api call should return 2 pages, one page of 3 blobs and one page of 2 blobs. - * Although each page is set to take 4 seconds to return, the timeout being set to 6 seconds should not cause the test to fail, - * as the timeout is only on the page request and not the entire stream of pages. - */ - - @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2019-12-12") - @Test - public void findBlobsWithTimeoutStillBackedByPagedFlux() { - BlobServiceAsyncClient serviceClient - = new BlobServiceClientBuilder().endpoint("https://account.blob.core.windows.net/") - .credential(new MockTokenCredential()) - .httpClient(new FindBlobsWithTimeoutClient(true)) - .buildAsyncClient(); - - StepVerifier.create(serviceClient.findBlobsByTags( - new FindBlobsOptions(String.format("\"%s\"='%s'", "dummyKey", "dummyValue")).setMaxResultsPerPage(3), - Duration.ofSeconds(6), Context.NONE).byPage()).expectNextCount(2).verifyComplete(); - } - private static void validatePropsSet(BlobServiceProperties sent, BlobServiceProperties received) { assertEquals(sent.getLogging().isRead(), received.getLogging().isRead()); assertEquals(sent.getLogging().isWrite(), received.getLogging().isWrite()); diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/TimeoutAsyncTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/TimeoutAsyncTests.java new file mode 100644 index 000000000000..f267e908d608 --- /dev/null +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/TimeoutAsyncTests.java @@ -0,0 +1,112 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.storage.blob; + +import com.azure.core.test.utils.MockTokenCredential; +import com.azure.core.util.Context; +import com.azure.storage.blob.models.ListBlobContainersOptions; +import com.azure.storage.blob.models.ListBlobsOptions; +import com.azure.storage.blob.options.FindBlobsOptions; +import com.azure.storage.common.test.shared.extensions.RequiredServiceVersion; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.parallel.Isolated; +import reactor.test.StepVerifier; + +import java.time.Duration; + +@Isolated +public class TimeoutAsyncTests { + /* + * This test class is marked as isolated to ensure that resource related issues do not interfere with the timeouts being tested. + * + * The custom http clients return a generic xml list of 5 blobs total. + * The api call should return 2 pages, one page of 3 blobs and one page of 2 blobs. + * Although each page is set to take 4 seconds to return, the timeout being set to 6 seconds should not cause the test to fail, + * as the timeout is only on the page request and not the entire stream of pages. + */ + + @Test + public void listBlobsFlatWithTimeoutStillBackedByPagedFlux() { + BlobContainerAsyncClient containerClient + = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") + .credential(new MockTokenCredential()) + .containerName("foo") + .httpClient(new TimeoutTests.ListBlobsWithTimeoutTestClient(true)) + .buildAsyncClient(); + + StepVerifier + .create( + containerClient + .listBlobsFlatWithOptionalTimeout(new ListBlobsOptions().setMaxResultsPerPage(3), null, + Duration.ofSeconds(6)) + .byPage()) + .expectNextCount(2) + .verifyComplete(); + } + + @Test + public void listBlobsHierWithTimeoutStillBackedByPagedFlux() { + BlobContainerAsyncClient containerClient + = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") + .credential(new MockTokenCredential()) + .containerName("foo") + .httpClient(new TimeoutTests.ListBlobsWithTimeoutTestClient(true)) + .buildAsyncClient(); + + StepVerifier + .create(containerClient + .listBlobsHierarchyWithOptionalTimeout("/", new ListBlobsOptions().setMaxResultsPerPage(3), + Duration.ofSeconds(6)) + .byPage()) + .expectNextCount(2) + .verifyComplete(); + } + + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2021-04-10") + @Test + public void findBlobsInContainerWithTimeoutStillBackedByPagedFlux() { + BlobContainerAsyncClient containerClient + = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") + .credential(new MockTokenCredential()) + .containerName("foo") + .httpClient(new TimeoutTests.FindBlobsWithTimeoutClient(true)) + .buildAsyncClient(); + + StepVerifier.create(containerClient.findBlobsByTags( + new FindBlobsOptions(String.format("\"%s\"='%s'", "dummyKey", "dummyValue")).setMaxResultsPerPage(3), + Duration.ofSeconds(6), Context.NONE).byPage()).expectNextCount(2).verifyComplete(); + } + + @Test + public void listContainersWithTimeoutStillBackedByPagedFlux() { + BlobServiceAsyncClient serviceClient + = new BlobServiceClientBuilder().endpoint("https://account.blob.core.windows.net/") + .credential(new MockTokenCredential()) + .httpClient(new TimeoutTests.ListContainersWithTimeoutTestClient(true)) + .buildAsyncClient(); + + StepVerifier + .create(serviceClient + .listBlobContainersWithOptionalTimeout(new ListBlobContainersOptions().setMaxResultsPerPage(3), + Duration.ofSeconds(6)) + .byPage()) + .expectNextCount(2) + .verifyComplete(); + } + + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2019-12-12") + @Test + public void findBlobsWithTimeoutStillBackedByPagedFlux() { + BlobServiceAsyncClient serviceClient + = new BlobServiceClientBuilder().endpoint("https://account.blob.core.windows.net/") + .credential(new MockTokenCredential()) + .httpClient(new TimeoutTests.FindBlobsWithTimeoutClient(true)) + .buildAsyncClient(); + + StepVerifier.create(serviceClient.findBlobsByTags( + new FindBlobsOptions(String.format("\"%s\"='%s'", "dummyKey", "dummyValue")).setMaxResultsPerPage(3), + Duration.ofSeconds(6), Context.NONE).byPage()).expectNextCount(2).verifyComplete(); + } + +} diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/TimeoutTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/TimeoutTests.java new file mode 100644 index 000000000000..7d38f2185550 --- /dev/null +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/TimeoutTests.java @@ -0,0 +1,288 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.storage.blob; + +import com.azure.core.http.HttpClient; +import com.azure.core.http.HttpHeaderName; +import com.azure.core.http.HttpHeaders; +import com.azure.core.http.HttpRequest; +import com.azure.core.http.HttpResponse; +import com.azure.core.test.http.MockHttpResponse; +import com.azure.core.test.utils.MockTokenCredential; +import com.azure.core.util.Context; +import com.azure.storage.blob.models.ListBlobContainersOptions; +import com.azure.storage.blob.models.ListBlobsOptions; +import com.azure.storage.blob.options.FindBlobsOptions; +import com.azure.storage.common.test.shared.extensions.RequiredServiceVersion; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.parallel.Isolated; +import reactor.core.publisher.Mono; + +import java.nio.charset.StandardCharsets; +import java.time.Duration; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@Isolated +public class TimeoutTests { + /* + * This test class is marked as isolated to ensure that resource related issues do not interfere with the timeouts being tested. + * + * The custom http clients return a generic xml list of 5 blobs total. + * The api call should return 2 pages, one page of 3 blobs and one page of 2 blobs. + * Although each page is set to take 4 seconds to return, the timeout being set to 6 seconds should not cause the test to fail, + * as the timeout should only be on the page request and not the entire stream of pages. + */ + + @Test + public void listBlobsFlatWithTimeoutStillBackedByPagedStream() { + BlobContainerClient containerClient + = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") + .credential(new MockTokenCredential()) + .containerName("foo") + .httpClient(new ListBlobsWithTimeoutTestClient(false)) + .buildClient(); + + assertEquals(2, + containerClient.listBlobs(new ListBlobsOptions().setMaxResultsPerPage(3), Duration.ofSeconds(14)) + .streamByPage() + .count()); + } + + @Test + public void listBlobsHierWithTimeoutStillBackedByPagedStream() { + BlobContainerClient containerClient + = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") + .credential(new MockTokenCredential()) + .containerName("foo") + .httpClient(new ListBlobsWithTimeoutTestClient(false)) + .buildClient(); + + assertEquals(2, + containerClient + .listBlobsByHierarchy("/", new ListBlobsOptions().setMaxResultsPerPage(3), Duration.ofSeconds(14)) + .streamByPage() + .count()); + } + + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2021-04-10") + @Test + public void findBlobsInContainerWithTimeoutStillBackedByPagedStream() { + BlobContainerClient containerClient + = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") + .credential(new MockTokenCredential()) + .containerName("foo") + .httpClient(new FindBlobsWithTimeoutClient(false)) + .buildClient(); + + assertEquals(2, + containerClient.findBlobsByTags( + new FindBlobsOptions(String.format("\"%s\"='%s'", "dummyKey", "dummyValue")).setMaxResultsPerPage(3), + Duration.ofSeconds(14), Context.NONE).streamByPage().count()); + } + + @Test + public void listContainersWithTimeoutStillBackedByPagedStream() { + BlobServiceClient serviceClient + = new BlobServiceClientBuilder().endpoint("https://account.blob.core.windows.net/") + .credential(new MockTokenCredential()) + .httpClient(new ListContainersWithTimeoutTestClient(false)) + .buildClient(); + + assertEquals(2, + serviceClient + .listBlobContainers(new ListBlobContainersOptions().setMaxResultsPerPage(3), Duration.ofSeconds(14)) + .streamByPage() + .count()); + + } + + @RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2019-12-12") + @Test + public void findBlobsWithTimeoutStillBackedByPagedStream() { + BlobServiceClient serviceClient + = new BlobServiceClientBuilder().endpoint("https://account.blob.core.windows.net/") + .credential(new MockTokenCredential()) + .httpClient(new FindBlobsWithTimeoutClient(false)) + .buildClient(); + + assertEquals(2, + serviceClient.findBlobsByTags( + new FindBlobsOptions(String.format("\"%s\"='%s'", "dummyKey", "dummyValue")).setMaxResultsPerPage(3), + Duration.ofSeconds(14), Context.NONE).streamByPage().count()); + } + + /* + * Used for sync and async tests + */ + + protected static final class ListBlobsWithTimeoutTestClient implements HttpClient { + private final boolean isAsync; + + ListBlobsWithTimeoutTestClient(Boolean isAsync) { + this.isAsync = isAsync; + } + + private HttpResponse response(HttpRequest request, String xml) { + HttpHeaders headers = new HttpHeaders().set(HttpHeaderName.CONTENT_TYPE, "application/xml"); + return new MockHttpResponse(request, 200, headers, xml.getBytes(StandardCharsets.UTF_8)); + } + + private String buildFirstRequest(Boolean useDelimiter) { + String delimiterString = useDelimiter ? "/" : ""; + + return "" + + "" + + "3" + delimiterString + "" + "" + "blob1" + + "" + "" + "blob2" + "" + "" + "blob3" + "" + + "" + "MARKER--" + ""; + } + + private String buildSecondRequest(Boolean useDelimiter) { + String delimiterString = useDelimiter ? "/" : ""; + + return "" + + "" + + "MARKER--" + "3" + delimiterString + "" + "" + + "blob4" + "" + "" + "blob5" + "" + "" + + "" + ""; + } + + @Override + public Mono send(HttpRequest request) { + String url = request.getUrl().toString(); + HttpResponse response; + int delay = isAsync ? 4 : 8; + + if (url.contains("?restype=container&comp=list&maxresults=")) { + // flat first request + response = response(request, buildFirstRequest(false)); + } else if (url.contains("?restype=container&comp=list&marker=")) { + // flat second request + response = response(request, buildSecondRequest(false)); + } else if (url.contains("?restype=container&comp=list&delimiter=/&maxresults=")) { + // hierarchy first request + response = response(request, buildFirstRequest(true)); + } else if (url.contains("?restype=container&comp=list&delimiter=/&marker=")) { + // hierarchy second request + response = response(request, buildSecondRequest(true)); + } else { + // fallback + return Mono.just(new MockHttpResponse(request, 404)); + } + + return Mono.delay(Duration.ofSeconds(delay)).then(Mono.just(response)); + } + } + + protected static final class FindBlobsWithTimeoutClient implements HttpClient { + private final boolean isAsync; + + FindBlobsWithTimeoutClient(Boolean isAsync) { + this.isAsync = isAsync; + } + + private HttpResponse response(HttpRequest request, String xml) { + HttpHeaders headers = new HttpHeaders().set(HttpHeaderName.CONTENT_TYPE, "application/xml"); + return new MockHttpResponse(request, 200, headers, xml.getBytes(StandardCharsets.UTF_8)); + } + + private String buildFirstRequest() { + return "" + + "" + + ""dummyKey"='dummyValue'" + "3" + + "" + "" + "blob1" + "foo" + "" + + "" + "" + "dummyKey" + "dummyValue" + "" + "" + + "" + "" + "" + "blob2" + "foo" + + "" + "" + "" + "dummyKey" + "dummyValue" + "" + + "" + "" + "" + "" + "blob3" + + "foo" + "" + "" + "" + "dummyKey" + + "dummyValue" + "" + "" + "" + "" + "" + + "MARKER-" + ""; + } + + private String buildSecondRequest() { + return "" + + "" + + "MARKER-" + ""dummyKey"='dummyValue'" + + "3" + "" + "" + "blob4" + + "foo" + "" + "" + "" + "dummyKey" + + "dummyValue" + "" + "" + "" + "" + "" + + "blob5" + "foo" + "" + "" + "" + + "dummyKey" + "dummyValue" + "" + "" + "" + "" + + "" + "" + ""; + } + + @Override + public Mono send(HttpRequest request) { + String url = request.getUrl().toString(); + HttpResponse response; + int delay = isAsync ? 4 : 8; + + if (url.contains("marker")) { + // second request + response = response(request, buildSecondRequest()); + } else if (url.contains("?comp=blobs&where=%") || url.contains("?restype=container&comp=blobs&where=%")) { + // first request + response = response(request, buildFirstRequest()); + } else { + // fallback + return Mono.just(new MockHttpResponse(request, 404)); + } + + return Mono.delay(Duration.ofSeconds(delay)).then(Mono.just(response)); + } + } + + protected static final class ListContainersWithTimeoutTestClient implements HttpClient { + private final boolean isAsync; + + ListContainersWithTimeoutTestClient(Boolean isAsync) { + this.isAsync = isAsync; + } + + private HttpResponse response(HttpRequest request, String xml) { + HttpHeaders headers = new HttpHeaders().set(HttpHeaderName.CONTENT_TYPE, "application/xml"); + return new MockHttpResponse(request, 200, headers, xml.getBytes(StandardCharsets.UTF_8)); + } + + private String buildFirstRequest() { + return "" + + "" + + "3" + "" + "" + "container1" + + "" + "" + "container2" + "" + "" + + "container3" + "" + "" + + "/marker/marker" + ""; + } + + private String buildSecondRequest() { + return "" + + "" + + "/marker/marker" + "3" + "" + "" + + "container4" + "" + "" + "container5" + + "" + "" + "" + ""; + } + + @Override + public Mono send(HttpRequest request) { + String url = request.getUrl().toString(); + HttpResponse response; + int delay = isAsync ? 4 : 8; + + if (url.contains("?comp=list&maxresults=")) { + // flat first request + response = response(request, buildFirstRequest()); + } else if (url.contains("?comp=list&marker=")) { + // flat second request + response = response(request, buildSecondRequest()); + } else { + // fallback + return Mono.just(new MockHttpResponse(request, 404)); + } + + return Mono.delay(Duration.ofSeconds(delay)).then(Mono.just(response)); + } + } + +} diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/HttpFaultInjectingTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/HttpFaultInjectingTests.java index 11c9afd38598..b86435cedcb8 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/HttpFaultInjectingTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/specialized/HttpFaultInjectingTests.java @@ -30,6 +30,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledIf; +import org.junit.jupiter.api.parallel.Isolated; import java.io.File; import java.io.IOException; @@ -56,8 +57,10 @@ /** * Set of tests that use HTTP fault injecting to simulate scenarios where the network has random errors. + * Isolated is used to ensure that timeouts caused by resource related issues are not mistaken for fault injections. */ @EnabledIf("shouldRun") +@Isolated public class HttpFaultInjectingTests { private static final ClientLogger LOGGER = new ClientLogger(HttpFaultInjectingTests.class); private static final HttpHeaderName UPSTREAM_URI_HEADER = HttpHeaderName.fromString("X-Upstream-Base-Uri"); From 3bb234fdd491d80c5060a105c77b9416e9ebe1bc Mon Sep 17 00:00:00 2001 From: Isabelle Date: Tue, 13 May 2025 11:51:25 -0700 Subject: [PATCH 16/16] removing timeout difference between sync and async --- .../azure/storage/blob/TimeoutAsyncTests.java | 10 +++--- .../com/azure/storage/blob/TimeoutTests.java | 34 +++++-------------- 2 files changed, 13 insertions(+), 31 deletions(-) diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/TimeoutAsyncTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/TimeoutAsyncTests.java index f267e908d608..c6b6ab0eef4b 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/TimeoutAsyncTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/TimeoutAsyncTests.java @@ -32,7 +32,7 @@ public void listBlobsFlatWithTimeoutStillBackedByPagedFlux() { = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") .credential(new MockTokenCredential()) .containerName("foo") - .httpClient(new TimeoutTests.ListBlobsWithTimeoutTestClient(true)) + .httpClient(new TimeoutTests.ListBlobsWithTimeoutTestClient()) .buildAsyncClient(); StepVerifier @@ -51,7 +51,7 @@ public void listBlobsHierWithTimeoutStillBackedByPagedFlux() { = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") .credential(new MockTokenCredential()) .containerName("foo") - .httpClient(new TimeoutTests.ListBlobsWithTimeoutTestClient(true)) + .httpClient(new TimeoutTests.ListBlobsWithTimeoutTestClient()) .buildAsyncClient(); StepVerifier @@ -70,7 +70,7 @@ public void findBlobsInContainerWithTimeoutStillBackedByPagedFlux() { = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") .credential(new MockTokenCredential()) .containerName("foo") - .httpClient(new TimeoutTests.FindBlobsWithTimeoutClient(true)) + .httpClient(new TimeoutTests.FindBlobsWithTimeoutClient()) .buildAsyncClient(); StepVerifier.create(containerClient.findBlobsByTags( @@ -83,7 +83,7 @@ public void listContainersWithTimeoutStillBackedByPagedFlux() { BlobServiceAsyncClient serviceClient = new BlobServiceClientBuilder().endpoint("https://account.blob.core.windows.net/") .credential(new MockTokenCredential()) - .httpClient(new TimeoutTests.ListContainersWithTimeoutTestClient(true)) + .httpClient(new TimeoutTests.ListContainersWithTimeoutTestClient()) .buildAsyncClient(); StepVerifier @@ -101,7 +101,7 @@ public void findBlobsWithTimeoutStillBackedByPagedFlux() { BlobServiceAsyncClient serviceClient = new BlobServiceClientBuilder().endpoint("https://account.blob.core.windows.net/") .credential(new MockTokenCredential()) - .httpClient(new TimeoutTests.FindBlobsWithTimeoutClient(true)) + .httpClient(new TimeoutTests.FindBlobsWithTimeoutClient()) .buildAsyncClient(); StepVerifier.create(serviceClient.findBlobsByTags( diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/TimeoutTests.java b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/TimeoutTests.java index 7d38f2185550..13b65110e2b2 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/TimeoutTests.java +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/TimeoutTests.java @@ -41,7 +41,7 @@ public void listBlobsFlatWithTimeoutStillBackedByPagedStream() { = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") .credential(new MockTokenCredential()) .containerName("foo") - .httpClient(new ListBlobsWithTimeoutTestClient(false)) + .httpClient(new ListBlobsWithTimeoutTestClient()) .buildClient(); assertEquals(2, @@ -56,7 +56,7 @@ public void listBlobsHierWithTimeoutStillBackedByPagedStream() { = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") .credential(new MockTokenCredential()) .containerName("foo") - .httpClient(new ListBlobsWithTimeoutTestClient(false)) + .httpClient(new ListBlobsWithTimeoutTestClient()) .buildClient(); assertEquals(2, @@ -73,7 +73,7 @@ public void findBlobsInContainerWithTimeoutStillBackedByPagedStream() { = new BlobContainerClientBuilder().endpoint("https://account.blob.core.windows.net/") .credential(new MockTokenCredential()) .containerName("foo") - .httpClient(new FindBlobsWithTimeoutClient(false)) + .httpClient(new FindBlobsWithTimeoutClient()) .buildClient(); assertEquals(2, @@ -87,7 +87,7 @@ public void listContainersWithTimeoutStillBackedByPagedStream() { BlobServiceClient serviceClient = new BlobServiceClientBuilder().endpoint("https://account.blob.core.windows.net/") .credential(new MockTokenCredential()) - .httpClient(new ListContainersWithTimeoutTestClient(false)) + .httpClient(new ListContainersWithTimeoutTestClient()) .buildClient(); assertEquals(2, @@ -104,7 +104,7 @@ public void findBlobsWithTimeoutStillBackedByPagedStream() { BlobServiceClient serviceClient = new BlobServiceClientBuilder().endpoint("https://account.blob.core.windows.net/") .credential(new MockTokenCredential()) - .httpClient(new FindBlobsWithTimeoutClient(false)) + .httpClient(new FindBlobsWithTimeoutClient()) .buildClient(); assertEquals(2, @@ -118,12 +118,6 @@ public void findBlobsWithTimeoutStillBackedByPagedStream() { */ protected static final class ListBlobsWithTimeoutTestClient implements HttpClient { - private final boolean isAsync; - - ListBlobsWithTimeoutTestClient(Boolean isAsync) { - this.isAsync = isAsync; - } - private HttpResponse response(HttpRequest request, String xml) { HttpHeaders headers = new HttpHeaders().set(HttpHeaderName.CONTENT_TYPE, "application/xml"); return new MockHttpResponse(request, 200, headers, xml.getBytes(StandardCharsets.UTF_8)); @@ -153,7 +147,7 @@ private String buildSecondRequest(Boolean useDelimiter) { public Mono send(HttpRequest request) { String url = request.getUrl().toString(); HttpResponse response; - int delay = isAsync ? 4 : 8; + int delay = 4; if (url.contains("?restype=container&comp=list&maxresults=")) { // flat first request @@ -177,12 +171,6 @@ public Mono send(HttpRequest request) { } protected static final class FindBlobsWithTimeoutClient implements HttpClient { - private final boolean isAsync; - - FindBlobsWithTimeoutClient(Boolean isAsync) { - this.isAsync = isAsync; - } - private HttpResponse response(HttpRequest request, String xml) { HttpHeaders headers = new HttpHeaders().set(HttpHeaderName.CONTENT_TYPE, "application/xml"); return new MockHttpResponse(request, 200, headers, xml.getBytes(StandardCharsets.UTF_8)); @@ -218,7 +206,7 @@ private String buildSecondRequest() { public Mono send(HttpRequest request) { String url = request.getUrl().toString(); HttpResponse response; - int delay = isAsync ? 4 : 8; + int delay = 4; if (url.contains("marker")) { // second request @@ -236,12 +224,6 @@ public Mono send(HttpRequest request) { } protected static final class ListContainersWithTimeoutTestClient implements HttpClient { - private final boolean isAsync; - - ListContainersWithTimeoutTestClient(Boolean isAsync) { - this.isAsync = isAsync; - } - private HttpResponse response(HttpRequest request, String xml) { HttpHeaders headers = new HttpHeaders().set(HttpHeaderName.CONTENT_TYPE, "application/xml"); return new MockHttpResponse(request, 200, headers, xml.getBytes(StandardCharsets.UTF_8)); @@ -268,7 +250,7 @@ private String buildSecondRequest() { public Mono send(HttpRequest request) { String url = request.getUrl().toString(); HttpResponse response; - int delay = isAsync ? 4 : 8; + int delay = 4; if (url.contains("?comp=list&maxresults=")) { // flat first request