11package com.azure.storage.blob.batch
22
3- import com.azure.core.http.HttpPipelineBuilder
4- import com.azure.core.http.policy.HttpPipelinePolicy
3+
54import com.azure.core.http.rest.Response
65import com.azure.core.test.TestMode
76import com.azure.core.util.Context
8- import com.azure.storage.blob.BlobServiceAsyncClient
97import com.azure.storage.blob.BlobServiceVersion
108import com.azure.storage.blob.batch.options.BlobBatchSetBlobAccessTierOptions
119import com.azure.storage.blob.models.AccessTier
1210import com.azure.storage.blob.models.BlobStorageException
1311import com.azure.storage.blob.models.DeleteSnapshotsOptionType
1412import com.azure.storage.blob.models.RehydratePriority
1513import com.azure.storage.blob.sas.BlobContainerSasPermission
16- import com.azure.storage.blob.sas.BlobSasPermission
1714import com.azure.storage.blob.sas.BlobServiceSasSignatureValues
1815import com.azure.storage.common.sas.AccountSasPermission
1916import com.azure.storage.common.sas.AccountSasResourceType
2017import com.azure.storage.common.sas.AccountSasService
2118import com.azure.storage.common.sas.AccountSasSignatureValues
22- import com.azure.storage.common.sas.SasIpRange
2319import com.azure.storage.common.sas.SasProtocol
2420import com.azure.storage.common.test.shared.extensions.RequiredServiceVersion
21+ import reactor.test.StepVerifier
2522import spock.lang.Unroll
2623
2724import java.nio.charset.StandardCharsets
25+ import java.time.Duration
26+ import java.util.stream.Collectors
2827
2928class BatchAPITest extends APISpec {
3029 /*
@@ -33,6 +32,7 @@ class BatchAPITest extends APISpec {
3332 * as these requests will be properly associated to the response by their `Content-ID` but this causes issues in
3433 * playback as we are using a static response that cannot handle changes in operation order.
3534 */
35+
3636 static def assertExpectedOrException (Response<?> response , int expectedStatusCode ) {
3737 try {
3838 def statusCode = response. getStatusCode()
@@ -45,10 +45,13 @@ class BatchAPITest extends APISpec {
4545 }
4646
4747 BlobBatchClient batchClient
48+ BlobBatchAsyncClient batchAsyncClient
4849 BlobBatchClient oauthBatchClient
4950
5051 def setup () {
51- batchClient = new BlobBatchClientBuilder (primaryBlobServiceClient). buildClient()
52+ def blobBatchClientBuilder = new BlobBatchClientBuilder (primaryBlobServiceAsyncClient)
53+ batchClient = blobBatchClientBuilder. buildClient()
54+ batchAsyncClient = blobBatchClientBuilder. buildAsyncClient()
5255 oauthBatchClient = new BlobBatchClientBuilder (getOAuthServiceClient()). buildClient()
5356 }
5457
@@ -189,9 +192,39 @@ class BatchAPITest extends APISpec {
189192 primaryBlobServiceClient. deleteBlobContainer(containerName)
190193
191194 where :
192- leaseId | tags
193- garbageLeaseID | null
194- null | " \" notfoo\" = 'notbar'"
195+ leaseId | tags
196+ garbageLeaseID | null
197+ null | " \" notfoo\" = 'notbar'"
198+ }
199+
200+ // Ensures errors in the batch using BlobBatchAsyncClient are emitted as onError and are not thrown.
201+ @Unroll
202+ def " Set tier AC fail async" () {
203+ setup :
204+ def containerName = generateContainerName()
205+ def blobName1 = generateBlobName()
206+ def batch = batchAsyncClient. getBlobBatch()
207+ def containerClient = primaryBlobServiceClient. createBlobContainer(containerName)
208+ def blobClient1 = containerClient. getBlobClient(blobName1)
209+ blobClient1. getBlockBlobClient(). upload(data. defaultInputStream, data. defaultDataSize)
210+
211+ when :
212+ batch. setBlobAccessTier(new BlobBatchSetBlobAccessTierOptions (blobClient1. getBlobUrl(), AccessTier . HOT )
213+ .setLeaseId(leaseId). setTagsConditions(tags))
214+ def request = batchAsyncClient. submitBatch(batch)
215+
216+ then :
217+ StepVerifier . create(request)
218+ .expectError(BlobBatchStorageException . class)
219+ .verify(Duration . ofSeconds(30 ))
220+
221+ cleanup :
222+ primaryBlobServiceClient. deleteBlobContainer(containerName)
223+
224+ where :
225+ leaseId | tags
226+ garbageLeaseID | null
227+ null | " \" notfoo\" = 'notbar'"
195228 }
196229
197230 def " Set tier some succeed throw on any error" () {
@@ -227,6 +260,41 @@ class BatchAPITest extends APISpec {
227260 primaryBlobServiceClient. deleteBlobContainer(containerName)
228261 }
229262
263+ def " Set tier some succeed throw on any error async" () {
264+ setup :
265+ def containerName = generateContainerName()
266+ def blobName1 = generateBlobName()
267+ def blobName2 = generateBlobName()
268+ def batch = batchAsyncClient. getBlobBatch()
269+ def containerClient = primaryBlobServiceClient. createBlobContainer(containerName)
270+ containerClient. getBlobClient(blobName1). getBlockBlobClient(). upload(data. defaultInputStream, data. defaultDataSize)
271+
272+ when :
273+ def response1 = batch. setBlobAccessTier(containerName, blobName1, AccessTier . HOT )
274+ def response2 = batch. setBlobAccessTier(containerName, blobName2, AccessTier . COOL )
275+ def request = batchAsyncClient. submitBatch(batch)
276+
277+ then :
278+ StepVerifier . create(request)
279+ .expectError(BlobBatchStorageException . class)
280+ .verify(Duration . ofSeconds(30 ))
281+
282+ // In PLAYBACK check responses in an order invariant fashion.
283+ if (env. testMode == TestMode . PLAYBACK ) {
284+ assert (assertExpectedOrException(response1, 200 ) + assertExpectedOrException(response2, 200 )) == 1
285+ } else {
286+ assert response1. getStatusCode() == 200
287+ try {
288+ response2. getStatusCode()
289+ } catch (def exception) {
290+ assert exception instanceof BlobStorageException
291+ }
292+ }
293+
294+ cleanup :
295+ primaryBlobServiceClient. deleteBlobContainer(containerName)
296+ }
297+
230298 def " Set tier some succeed do not throw on any error" () {
231299 setup :
232300 def containerName = generateContainerName()
@@ -507,7 +575,9 @@ class BatchAPITest extends APISpec {
507575 def responses = batchClient. deleteBlobs(blobUrls, DeleteSnapshotsOptionType . INCLUDE )
508576
509577 then :
510- for (def response : responses) {
578+ def responseList = responses. stream(). collect(Collectors . toList())
579+ assert responseList. size() == 10
580+ for (def response : responseList) {
511581 assert response. getStatusCode() == 202
512582 }
513583
@@ -530,7 +600,9 @@ class BatchAPITest extends APISpec {
530600 def responses = batchClient. setBlobsAccessTier(blobUrls, AccessTier . HOT )
531601
532602 then :
533- for (def response : responses) {
603+ def responseList = responses. stream(). collect(Collectors . toList())
604+ assert responseList. size() == 10
605+ for (def response : responseList) {
534606 assert response. getStatusCode() == 200
535607 }
536608
@@ -553,7 +625,9 @@ class BatchAPITest extends APISpec {
553625 def responses = batchClient. setBlobsAccessTier(blobUrls, AccessTier . HOT )
554626
555627 then :
556- for (def response : responses) {
628+ def responseList = responses. stream(). collect(Collectors . toList())
629+ assert responseList. size() == 1
630+ for (def response : responseList) {
557631 assert response. getStatusCode() == 200
558632 }
559633
@@ -579,7 +653,9 @@ class BatchAPITest extends APISpec {
579653 def responses = batchClient. setBlobsAccessTier(blobUrls, AccessTier . HOT )
580654
581655 then :
582- for (def response : responses) {
656+ def responseList = responses. stream(). collect(Collectors . toList())
657+ assert responseList. size() == 1
658+ for (def response : responseList) {
583659 assert response. getStatusCode() == 200
584660 }
585661
@@ -601,7 +677,8 @@ class BatchAPITest extends APISpec {
601677 batchClient. deleteBlobs(blobUrls, DeleteSnapshotsOptionType . INCLUDE ). iterator(). next()
602678
603679 then :
604- thrown(BlobStorageException )
680+ def ex = thrown(RuntimeException )
681+ assert ex instanceof BlobStorageException || ex. getCause() instanceof BlobStorageException
605682
606683 cleanup :
607684 primaryBlobServiceClient. deleteBlobContainer(containerName)
@@ -711,7 +788,7 @@ class BatchAPITest extends APISpec {
711788 def sas = primaryBlobServiceClient. generateAccountSas(sasValues)
712789
713790 def batchClient = new BlobBatchClientBuilder (getServiceClient(sas, primaryBlobServiceClient. getAccountUrl()))
714- .buildClient()
791+ .buildClient()
715792
716793 def batch = batchClient. getBlobBatch()
717794
0 commit comments