Skip to content

Adding New Isolated Timeout Test Class #45202

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 28 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
b8f6ed8
potential fault injection fix
ibrandes May 5, 2025
54ad6a8
removing redundant class
ibrandes May 5, 2025
1765519
removing timeout from args to align with other tests that use this api
ibrandes May 5, 2025
25e44cc
making supplier match sync test, which does not have flakiness problems
ibrandes May 5, 2025
10cb93b
increasing response and read timeout again
ibrandes May 5, 2025
da074f5
wip
ibrandes May 5, 2025
703b608
Merge branch 'main' of https://github.com/Azure/azure-sdk-for-java in…
ibrandes May 5, 2025
e9adf59
removing management plane interaction and replacing with data plane i…
ibrandes May 5, 2025
5c98dad
changing seconds to days to match uploadFromUrlDestinationRequestCond…
ibrandes May 6, 2025
fbf8977
making root tests playback only to resolve race conditions due to par…
ibrandes May 6, 2025
36604c8
removing a test that was literally never used
ibrandes May 6, 2025
57938d7
adding mocking to list resource tests
ibrandes May 12, 2025
1e1d1ff
adding recordings
ibrandes May 12, 2025
fd928ed
increasing timeouts for sync tests
ibrandes May 12, 2025
ac9451e
fixing timeout mistake in ternary operator
ibrandes May 12, 2025
e6ba874
moving timeout tests to an isolated test file
ibrandes May 13, 2025
3bb234f
removing timeout difference between sync and async
ibrandes May 13, 2025
611cfb7
removing unused method and moving variables
ibrandes May 13, 2025
e2e987f
removing another unused method, changing util method names, and reduc…
ibrandes May 14, 2025
6fb2c69
removing everything besides timeout test changes to put into another PR
ibrandes May 15, 2025
8140f2e
format fix
ibrandes May 15, 2025
6f97482
spotless
ibrandes May 15, 2025
271417a
changing assets tag back to what it was before
ibrandes May 15, 2025
8742e8d
fixing sync timeout
ibrandes May 21, 2025
2eba4e7
Merge branch 'main' of https://github.com/Azure/azure-sdk-for-java in…
ibrandes May 21, 2025
5ec3162
refactoring timeout test class helper method
ibrandes Jun 1, 2025
66e1c22
style
ibrandes Jun 1, 2025
5ad4052
style
ibrandes Jun 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -1070,40 +1069,6 @@ public void listBlobsFlatError() {
assertThrows(BlobStorageException.class, () -> cc.listBlobs().iterator().hasNext());
}

@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))
.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());
}

/*
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.
Expand Down Expand Up @@ -1656,28 +1621,6 @@ public void findBlobsError() {
assertThrows(BlobStorageException.class, () -> cc.findBlobsByTags("garbageTag").streamByPage().count());
}

@SuppressWarnings("deprecation")
@RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2021-04-10")
@Test
public void findBlobsWithTimeoutStillBackedByPagedStream() {
int numBlobs = 5;
int pageResults = 3;
Map<String, String> 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());
}

@ParameterizedTest
@ValueSource(strings = { "中文", "az[]", "hello world", "hello/world", "hello&world", "!*'();:@&=+/$,/?#[]" })
public void createURLSpecialChars(String name) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1122,42 +1122,6 @@ public void listBlobsFlatError() {
StepVerifier.create(ccAsync.listBlobs()).verifyError(BlobStorageException.class);
}

@Test
public void listBlobsFlatWithTimeoutStillBackedByPagedFlux() {
int numBlobs = 5;
int pageResults = 3;

Mono<List<BlockBlobItem>> createBlob = Flux.range(0, numBlobs).flatMap(i -> {
BlockBlobAsyncClient blob = ccAsync.getBlobAsyncClient(generateBlobName()).getBlockBlobAsyncClient();
return blob.upload(DATA.getDefaultFlux(), DATA.getDefaultDataSize());
}).collectList();

// when: "Consume results by page, then still have paging functionality"
StepVerifier
.create(createBlob
.thenMany(ccAsync.listBlobs(new ListBlobsOptions().setMaxResultsPerPage(pageResults)).byPage()))
.expectNextCount(2)
.verifyComplete();
}

@Test
public void listBlobsHierWithTimeoutStillBackedByPagedFlux() {
int numBlobs = 5;
int pageResults = 3;

Mono<List<BlockBlobItem>> createBlob = Flux.range(0, numBlobs).flatMap(i -> {
BlockBlobAsyncClient blob = ccAsync.getBlobAsyncClient(generateBlobName()).getBlockBlobAsyncClient();
return blob.upload(DATA.getDefaultFlux(), DATA.getDefaultDataSize());
}).collectList();

// when: "Consume results by page, then still have paging functionality"
StepVerifier
.create(createBlob.thenMany(
ccAsync.listBlobsByHierarchy("/", new ListBlobsOptions().setMaxResultsPerPage(pageResults)).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.
Expand Down Expand Up @@ -1776,35 +1740,6 @@ public void findBlobsError() {
StepVerifier.create(ccAsync.findBlobsByTags("garbageTag").byPage()).verifyError(BlobStorageException.class);
}

@SuppressWarnings("deprecation")
@RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2021-04-10")
@Test
public void findBlobsWithTimeoutStillBackedByPagedFlux() {
int numBlobs = 5;
int pageResults = 3;
Map<String, String> tags = Collections.singletonMap(tagKey, tagValue);

Mono<List<Response<BlockBlobItem>>> uploadBlob = Flux.range(0, numBlobs)
.flatMap(i -> ccAsync.getBlobAsyncClient(generateBlobName())
.uploadWithResponse(
new BlobParallelUploadOptions(DATA.getDefaultInputStream(), DATA.getDefaultDataSize())
.setTags(tags)))
.collectList();

// 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();
}

@ParameterizedTest
@ValueSource(strings = { "中文", "az[]", "hello world", "hello/world", "hello&world", "!*'();:@&=+/$,/?#[]" })
public void createURLSpecialChars(String name) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,30 +289,6 @@ public void listContainersAnonymous() {
assertThrows(IllegalStateException.class, () -> anonymousClient.listBlobContainers().iterator());
}

@Test
public void listContainersWithTimeoutStillBackedByPagedStream() {
int numContainers = 5;
int pageResults = 3;

List<BlobContainerClient> 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))
.streamByPage()
.count());

// cleanup:
for (BlobContainerClient container : containers) {
container.delete();
}
}

@RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2020-10-02")
@Test
@ResourceLock("ServiceProperties")
Expand Down Expand Up @@ -525,32 +501,6 @@ public void findBlobsAnonymous() {

}

@SuppressWarnings("deprecation")
@RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2019-12-12")
@Test
public void findBlobsWithTimeoutStillBackedByPagedStream() {
int numBlobs = 5;
int pageResults = 3;
BlobContainerClient cc = primaryBlobServiceClient.createBlobContainer(generateContainerName());
Map<String, String> 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());

// cleanup:
cc.delete();
}

private static void validatePropsSet(BlobServiceProperties sent, BlobServiceProperties received) {
assertEquals(sent.getLogging().isRead(), received.getLogging().isRead());
assertEquals(sent.getLogging().isWrite(), received.getLogging().isWrite());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -285,22 +285,6 @@ public void listContainersAnonymous() {
StepVerifier.create(anonymousClient.listBlobContainers()).verifyError(IllegalStateException.class);
}

@Test
public void listContainersWithTimeoutStillBackedByPagedFlux() {
int numContainers = 5;
int pageResults = 3;

Mono<List<BlobContainerAsyncClient>> containersMono = Flux.range(0, numContainers)
.flatMap(i -> primaryBlobServiceAsyncClient.createBlobContainer(generateContainerName()))
.collectList();

StepVerifier.create(containersMono.flatMapMany(containers -> primaryBlobServiceAsyncClient
.listBlobContainersWithOptionalTimeout(new ListBlobContainersOptions().setMaxResultsPerPage(pageResults),
Duration.ofSeconds(10))
.byPage()
.count())).expectNextCount(1).verifyComplete();
}

@RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2020-10-02")
@Test
@ResourceLock("ServiceProperties")
Expand Down Expand Up @@ -500,30 +484,6 @@ public void findBlobsAnonymous() {
StepVerifier.create(anonymousClient.findBlobsByTags("foo=bar")).verifyError(IllegalStateException.class);
}

@SuppressWarnings("deprecation")
@RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2019-12-12")
@Test
public void findBlobsWithTimeoutStillBackedByPagedFlux() {
int numBlobs = 5;
int pageResults = 3;
Map<String, String> tags = Collections.singletonMap(tagKey, tagValue);

Mono<Long> response = primaryBlobServiceAsyncClient.createBlobContainer(generateContainerName()).flatMap(cc -> {
Flux<Response<BlockBlobItem>> 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());
});

StepVerifier.create(response).expectNextCount(1).verifyComplete();
}

private static void validatePropsSet(BlobServiceProperties sent, BlobServiceProperties received) {
assertEquals(sent.getLogging().isRead(), received.getLogging().isRead());
assertEquals(sent.getLogging().isWrite(), received.getLogging().isWrite());
Expand Down
Original file line number Diff line number Diff line change
@@ -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())
.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())
.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())
.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())
.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())
.buildAsyncClient();

StepVerifier.create(serviceClient.findBlobsByTags(
new FindBlobsOptions(String.format("\"%s\"='%s'", "dummyKey", "dummyValue")).setMaxResultsPerPage(3),
Duration.ofSeconds(6), Context.NONE).byPage()).expectNextCount(2).verifyComplete();
}

}
Loading
Loading