From cf8cd77cbc0d885be160be3ecc1f60882f3a5c82 Mon Sep 17 00:00:00 2001 From: gapra Date: Thu, 24 Jun 2021 12:39:57 -0700 Subject: [PATCH 1/9] Added support for file share reliable download --- .../com/azure/storage/blob/APISpec.groovy | 14 - .../com/azure/storage/blob/BlobAPITest.groovy | 3 +- .../policy/MockRetryRangeResponsePolicy.java | 34 ++ .../storage/file/datalake/APISpec.groovy | 14 - .../storage/file/datalake/FileAPITest.groovy | 3 +- .../azure-storage-file-share/CHANGELOG.md | 2 +- .../file/share/ShareFileAsyncClient.java | 120 ++++++- .../storage/file/share/ShareFileClient.java | 31 +- .../implementation/util/ModelHelper.java | 7 + .../share/models/DownloadRetryOptions.java | 56 ++++ .../options/ShareFileDownloadOptions.java | 85 +++++ .../ShareFileAsyncJavaDocCodeSamples.java | 23 ++ .../share/ShareFileJavaDocCodeSamples.java | 29 ++ .../storage/file/share/FileAPITests.groovy | 93 ++++++ .../FileAPITestsDownloadAllNull.json | 114 +++++++ .../FileAPITestsDownloadEmptyFile.json | 90 ++++++ .../FileAPITestsDownloadRetryDefault.json | 294 ++++++++++++++++++ .../FileAPITestsDownloadWithRetryRange.json | 222 +++++++++++++ 18 files changed, 1187 insertions(+), 47 deletions(-) create mode 100644 sdk/storage/azure-storage-common/src/test-shared/java/com/azure/storage/common/test/shared/policy/MockRetryRangeResponsePolicy.java create mode 100644 sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/models/DownloadRetryOptions.java create mode 100644 sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/options/ShareFileDownloadOptions.java create mode 100644 sdk/storage/azure-storage-file-share/src/test/resources/session-records/FileAPITestsDownloadAllNull.json create mode 100644 sdk/storage/azure-storage-file-share/src/test/resources/session-records/FileAPITestsDownloadEmptyFile.json create mode 100644 sdk/storage/azure-storage-file-share/src/test/resources/session-records/FileAPITestsDownloadRetryDefault.json create mode 100644 sdk/storage/azure-storage-file-share/src/test/resources/session-records/FileAPITestsDownloadWithRetryRange.json diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/APISpec.groovy b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/APISpec.groovy index ffd6c72815b7b..4e89458a5b627 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/APISpec.groovy +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/APISpec.groovy @@ -671,20 +671,6 @@ class APISpec extends StorageSpec { } } - class MockRetryRangeResponsePolicy implements HttpPipelinePolicy { - @Override - Mono process(HttpPipelineCallContext context, HttpPipelineNextPolicy next) { - return next.process().flatMap { HttpResponse response -> - if (response.getRequest().getHeaders().getValue("x-ms-range") != "bytes=2-6") { - return Mono. error(new IllegalArgumentException("The range header was not set correctly on retry.")) - } else { - // ETag can be a dummy value. It's not validated, but DownloadResponse requires one - return Mono. just(new MockDownloadHttpResponse(response, 206, Flux.error(new IOException()))) - } - } - } - } - /** * Injects one retry-able IOException failure per url. */ diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobAPITest.groovy b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobAPITest.groovy index 1c116b95b5b87..43c1c1cea40f4 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobAPITest.groovy +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobAPITest.groovy @@ -50,6 +50,7 @@ import com.azure.storage.common.test.shared.extensions.LiveOnly import com.azure.storage.common.test.shared.extensions.PlaybackOnly import com.azure.storage.common.test.shared.extensions.RequiredServiceVersion import com.azure.storage.common.test.shared.policy.MockFailureResponsePolicy +import com.azure.storage.common.test.shared.policy.MockRetryRangeResponsePolicy import reactor.core.Exceptions import reactor.core.publisher.Flux import reactor.core.publisher.Hooks @@ -377,7 +378,7 @@ class BlobAPITest extends APISpec { constructed in BlobClient.download(). */ setup: - def bu2 = getBlobClient(env.primaryAccount.credential, bc.getBlobUrl(), new MockRetryRangeResponsePolicy()) + def bu2 = getBlobClient(env.primaryAccount.credential, bc.getBlobUrl(), new MockRetryRangeResponsePolicy("bytes=2-6")) when: def range = new BlobRange(2, 5L) diff --git a/sdk/storage/azure-storage-common/src/test-shared/java/com/azure/storage/common/test/shared/policy/MockRetryRangeResponsePolicy.java b/sdk/storage/azure-storage-common/src/test-shared/java/com/azure/storage/common/test/shared/policy/MockRetryRangeResponsePolicy.java new file mode 100644 index 0000000000000..2d7e5a2213cfc --- /dev/null +++ b/sdk/storage/azure-storage-common/src/test-shared/java/com/azure/storage/common/test/shared/policy/MockRetryRangeResponsePolicy.java @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.storage.common.test.shared.policy; + +import com.azure.core.http.HttpPipelineCallContext; +import com.azure.core.http.HttpPipelineNextPolicy; +import com.azure.core.http.HttpResponse; +import com.azure.core.http.policy.HttpPipelinePolicy; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.io.IOException; + +public class MockRetryRangeResponsePolicy implements HttpPipelinePolicy { + + private final String rangeMatch; + + public MockRetryRangeResponsePolicy(String rangeMatch) { + this.rangeMatch = rangeMatch; + } + + @Override + public Mono process(HttpPipelineCallContext context, HttpPipelineNextPolicy next) { + return next.process().flatMap( response -> { + if (!response.getRequest().getHeaders().getValue("x-ms-range").equals(rangeMatch)) { + return Mono.error(new IllegalArgumentException("The range header was not set correctly on retry.")); + } else { + // ETag can be a dummy value. It's not validated, but DownloadResponse requires one + return Mono.just(new MockDownloadHttpResponse(response, 206, Flux.error(new IOException()))); + } + }); + } +} diff --git a/sdk/storage/azure-storage-file-datalake/src/test/java/com/azure/storage/file/datalake/APISpec.groovy b/sdk/storage/azure-storage-file-datalake/src/test/java/com/azure/storage/file/datalake/APISpec.groovy index 9c904b723028e..59b62a4b26319 100644 --- a/sdk/storage/azure-storage-file-datalake/src/test/java/com/azure/storage/file/datalake/APISpec.groovy +++ b/sdk/storage/azure-storage-file-datalake/src/test/java/com/azure/storage/file/datalake/APISpec.groovy @@ -485,20 +485,6 @@ class APISpec extends StorageSpec { } } - class MockRetryRangeResponsePolicy implements HttpPipelinePolicy { - @Override - Mono process(HttpPipelineCallContext context, HttpPipelineNextPolicy next) { - return next.process().flatMap { HttpResponse response -> - if (response.getRequest().getHeaders().getValue("x-ms-range") != "bytes=2-6") { - return Mono. error(new IllegalArgumentException("The range header was not set correctly on retry.")) - } else { - // ETag can be a dummy value. It's not validated, but DownloadResponse requires one - return Mono. just(new MockDownloadHttpResponse(response, 206, Flux.error(new IOException()))) - } - } - } - } - def getMockRequest() { HttpHeaders headers = new HttpHeaders() headers.put(Constants.HeaderConstants.CONTENT_ENCODING, "en-US") diff --git a/sdk/storage/azure-storage-file-datalake/src/test/java/com/azure/storage/file/datalake/FileAPITest.groovy b/sdk/storage/azure-storage-file-datalake/src/test/java/com/azure/storage/file/datalake/FileAPITest.groovy index bee47bb2e361a..5f51f8192e047 100644 --- a/sdk/storage/azure-storage-file-datalake/src/test/java/com/azure/storage/file/datalake/FileAPITest.groovy +++ b/sdk/storage/azure-storage-file-datalake/src/test/java/com/azure/storage/file/datalake/FileAPITest.groovy @@ -15,6 +15,7 @@ import com.azure.storage.blob.models.BlockListType import com.azure.storage.common.test.shared.extensions.LiveOnly import com.azure.storage.common.test.shared.extensions.RequiredServiceVersion import com.azure.storage.common.test.shared.policy.MockFailureResponsePolicy +import com.azure.storage.common.test.shared.policy.MockRetryRangeResponsePolicy import com.azure.storage.file.datalake.models.DownloadRetryOptions import com.azure.storage.file.datalake.models.AccessTier import com.azure.storage.file.datalake.models.DataLakeRequestConditions @@ -979,7 +980,7 @@ class FileAPITest extends APISpec { constructed in BlobClient.download(). */ setup: - def fileClient = getFileClient(env.dataLakeAccount.credential, fc.getPathUrl(), new MockRetryRangeResponsePolicy()) + def fileClient = getFileClient(env.dataLakeAccount.credential, fc.getPathUrl(), new MockRetryRangeResponsePolicy("bytes=2-6")) fc.append(new ByteArrayInputStream(data.defaultBytes), 0, data.defaultDataSize) fc.flush(data.defaultDataSize) diff --git a/sdk/storage/azure-storage-file-share/CHANGELOG.md b/sdk/storage/azure-storage-file-share/CHANGELOG.md index 09b66dafcbc3a..4893d92241e95 100644 --- a/sdk/storage/azure-storage-file-share/CHANGELOG.md +++ b/sdk/storage/azure-storage-file-share/CHANGELOG.md @@ -1,7 +1,7 @@ # Release History ## 12.11.0-beta.1 (Unreleased) - +- Added support to reliably download a file. ## 12.10.0 (2021-06-09) - GA release diff --git a/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/ShareFileAsyncClient.java b/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/ShareFileAsyncClient.java index 192be52e0bc24..1dddf2f8e2891 100644 --- a/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/ShareFileAsyncClient.java +++ b/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/ShareFileAsyncClient.java @@ -14,6 +14,7 @@ import com.azure.core.http.rest.PagedResponseBase; import com.azure.core.http.rest.Response; import com.azure.core.http.rest.SimpleResponse; +import com.azure.core.http.rest.StreamResponse; import com.azure.core.util.Context; import com.azure.core.util.CoreUtils; import com.azure.core.util.FluxUtil; @@ -48,6 +49,7 @@ import com.azure.storage.file.share.implementation.util.ShareSasImplUtil; import com.azure.storage.file.share.models.CloseHandlesInfo; import com.azure.storage.file.share.models.CopyStatusType; +import com.azure.storage.file.share.models.DownloadRetryOptions; import com.azure.storage.file.share.models.HandleItem; import com.azure.storage.file.share.models.LeaseDurationType; import com.azure.storage.file.share.models.LeaseStateType; @@ -58,6 +60,7 @@ import com.azure.storage.file.share.models.ShareErrorCode; import com.azure.storage.file.share.models.ShareFileCopyInfo; import com.azure.storage.file.share.models.ShareFileDownloadAsyncResponse; +import com.azure.storage.file.share.models.ShareFileDownloadHeaders; import com.azure.storage.file.share.models.ShareFileHttpHeaders; import com.azure.storage.file.share.models.ShareFileInfo; import com.azure.storage.file.share.models.ShareFileMetadataInfo; @@ -70,6 +73,7 @@ import com.azure.storage.file.share.models.ShareFileUploadRangeFromUrlInfo; import com.azure.storage.file.share.models.ShareRequestConditions; import com.azure.storage.file.share.models.ShareStorageException; +import com.azure.storage.file.share.options.ShareFileDownloadOptions; import com.azure.storage.file.share.options.ShareFileListRangesDiffOptions; import com.azure.storage.file.share.sas.ShareServiceSasSignatureValues; import reactor.core.Exceptions; @@ -93,6 +97,7 @@ import java.time.OffsetDateTime; import java.util.ArrayList; import java.util.Collections; +import java.util.ConcurrentModificationException; import java.util.List; import java.util.Map; import java.util.Objects; @@ -134,6 +139,7 @@ public class ShareFileAsyncClient { static final long FILE_DEFAULT_BLOCK_SIZE = 4 * 1024 * 1024L; static final long FILE_MAX_PUT_RANGE_SIZE = 4 * Constants.MB; private static final long DOWNLOAD_UPLOAD_CHUNK_TIMEOUT = 300; + private static final Duration TIMEOUT_VALUE = Duration.ofSeconds(60); private final AzureFileStorageImpl azureFileStorageClient; private final String shareName; @@ -734,7 +740,8 @@ private Mono> downloadResponseInChunk(Response - downloadWithResponse(chunk, false, requestConditions, context) + downloadWithResponse(new ShareFileDownloadOptions().setRange(chunk).setRangeContentMd5(false) + .setRequestConditions(requestConditions), context) .map(ShareFileDownloadAsyncResponse::getValue) .subscribeOn(Schedulers.elastic()) .flatMap(fbb -> FluxUtil @@ -778,8 +785,7 @@ private void channelCleanUp(AsynchronousFileChannel channel) { */ public Flux download() { try { - return downloadWithResponse(null, null).flatMapMany( - ShareFileDownloadAsyncResponse::getValue); + return downloadWithResponse(null).flatMapMany(ShareFileDownloadAsyncResponse::getValue); } catch (RuntimeException ex) { return fluxError(logger, ex); } @@ -826,25 +832,111 @@ public Mono downloadWithResponse(ShareFileRange */ public Mono downloadWithResponse(ShareFileRange range, Boolean rangeGetContentMD5, ShareRequestConditions requestConditions) { + return downloadWithResponse(new ShareFileDownloadOptions().setRange(range) + .setRangeContentMd5(rangeGetContentMD5).setRequestConditions(requestConditions)); + } + + /** + * Downloads a file from the system, including its metadata and properties + * + *

Code Samples

+ * + *

Download the file from 1024 to 2048 bytes with its metadata and properties and without the contentMD5.

+ * + * {@codesnippet com.azure.storage.file.share.ShareFileAsyncClient.downloadWithResponse#ShareFileDownloadOptions} + * + *

For more information, see the + * Azure Docs.

+ * + * @param options {@link ShareFileDownloadOptions} + * true, as long as the range is less than or equal to 4 MB in size. + * @return A reactive response containing response data and the file data. + */ + public Mono downloadWithResponse(ShareFileDownloadOptions options) { try { - return withContext(context -> downloadWithResponse(range, rangeGetContentMD5, - requestConditions, context)); + return withContext(context -> downloadWithResponse(options, context)); } catch (RuntimeException ex) { return monoError(logger, ex); } } - Mono downloadWithResponse(ShareFileRange range, Boolean rangeGetContentMD5, + Mono downloadWithResponse(ShareFileDownloadOptions options, Context context) { + options = options == null ? new ShareFileDownloadOptions() : options; + ShareFileRange range = options.getRange() == null ? new ShareFileRange(0) : options.getRange(); + ShareRequestConditions requestConditions = options.getRequestConditions() == null + ? new ShareRequestConditions() : options.getRequestConditions(); + DownloadRetryOptions retryOptions = options.getRetryOptions() == null ? new DownloadRetryOptions() + : options.getRetryOptions(); + Boolean getRangeContentMd5 = options.getRangeContentMd5(); + + return downloadRange(range, getRangeContentMd5, requestConditions, context) + .map(response -> { + String eTag = ModelHelper.getETag(response.getHeaders()); + ShareFileDownloadHeaders headers = ModelHelper.transformFileDownloadHeaders(response.getHeaders()); + + long finalEnd; + if (range.getEnd() == null) { + finalEnd = headers.getContentRange() == null ? headers.getContentLength() + : Long.parseLong(headers.getContentRange().split("/")[1]); + } else { + finalEnd = range.getEnd(); + } + + Flux bufferFlux = FluxUtil.createRetriableDownloadFlux( + () -> response.getValue().timeout(TIMEOUT_VALUE), + (throwable, offset) -> { + if (!(throwable instanceof IOException || throwable instanceof TimeoutException)) { + return Flux.error(throwable); + } + + long newCount = finalEnd - (offset - range.getStart()); + + /* + It is possible that the network stream will throw an error after emitting all data but before + completing. Issuing a retry at this stage would leave the download in a bad state with incorrect count + and offset values. Because we have read the intended amount of data, we can ignore the error at the end + of the stream. + */ + if (newCount == 0) { + logger.warning("Exception encountered in ReliableDownload after all data read from the network but " + + "but before stream signaled completion. Returning success as all data was downloaded. " + + "Exception message: " + throwable.getMessage()); + return Flux.empty(); + } + + try { + return downloadRange( + new ShareFileRange(offset, range.getEnd()), getRangeContentMd5, + requestConditions, context).flatMapMany(r -> { + String receivedETag = ModelHelper.getETag(r.getHeaders()); + if ((eTag == null && receivedETag == null) + || (eTag != null && eTag.equals(receivedETag))) { + return r.getValue().timeout(TIMEOUT_VALUE); + } else { + return Flux.error( + new ConcurrentModificationException(String.format("File has been modified " + + "concurrently. Expected eTag: %s, Received eTag: %s", eTag, + receivedETag))); + } + }); + } catch (Exception e) { + return Flux.error(e); + } + }, + retryOptions.getMaxRetryRequests(), + range.getStart() + ).switchIfEmpty(Flux.just(ByteBuffer.wrap(new byte[0]))); + + return new ShareFileDownloadAsyncResponse(response.getRequest(), response.getStatusCode(), + response.getHeaders(), bufferFlux, headers); + }); + } + + private Mono downloadRange(ShareFileRange range, Boolean rangeGetContentMD5, ShareRequestConditions requestConditions, Context context) { - requestConditions = requestConditions == null ? new ShareRequestConditions() : requestConditions; String rangeString = range == null ? null : range.toString(); - - return azureFileStorageClient.getFiles() - .downloadWithResponseAsync(shareName, filePath, null, rangeString, rangeGetContentMD5, - requestConditions.getLeaseId(), context) - .map(response -> new ShareFileDownloadAsyncResponse(response.getRequest(), response.getStatusCode(), - response.getHeaders(), response.getValue(), - ModelHelper.transformFileDownloadHeaders(response.getHeaders()))); + return azureFileStorageClient.getFiles().downloadWithResponseAsync(shareName, filePath, null, + rangeString, rangeGetContentMD5, requestConditions.getLeaseId(), context); } /** diff --git a/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/ShareFileClient.java b/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/ShareFileClient.java index 4c03c1ce26f78..1945df2087e0b 100644 --- a/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/ShareFileClient.java +++ b/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/ShareFileClient.java @@ -33,6 +33,7 @@ import com.azure.storage.file.share.models.ShareFileUploadRangeOptions; import com.azure.storage.file.share.models.ShareRequestConditions; import com.azure.storage.file.share.models.ShareStorageException; +import com.azure.storage.file.share.options.ShareFileDownloadOptions; import com.azure.storage.file.share.options.ShareFileListRangesDiffOptions; import com.azure.storage.file.share.sas.ShareServiceSasSignatureValues; import reactor.core.Exceptions; @@ -561,10 +562,36 @@ public ShareFileDownloadResponse downloadWithResponse(OutputStream stream, Share */ public ShareFileDownloadResponse downloadWithResponse(OutputStream stream, ShareFileRange range, Boolean rangeGetContentMD5, ShareRequestConditions requestConditions, Duration timeout, Context context) { + return downloadWithResponse(stream, new ShareFileDownloadOptions().setRange(range) + .setRangeContentMd5(rangeGetContentMD5).setRequestConditions(requestConditions), timeout, context); + } + + /** + * Downloads a file from the system, including its metadata and properties + * + *

Code Samples

+ * + *

Download the file from 1024 to 2048 bytes with its metadata and properties and without the contentMD5.

+ * + * {@codesnippet com.azure.storage.file.share.ShareFileClient.downloadWithResponse#OutputStream-ShareFileDownloadOptions-Duration-Context} + * + *

For more information, see the + * Azure Docs.

+ * + * @param stream A non-null {@link OutputStream} where the downloaded data will be written. + * @param options {@link ShareFileDownloadOptions} + * @param timeout An optional timeout applied to the operation. If a response is not returned before the timeout + * concludes a {@link RuntimeException} will be thrown. + * @param context Additional context that is passed through the Http pipeline during the service call. + * @return A response containing the headers and response status code + * @throws NullPointerException If {@code stream} is {@code null}. + * @throws RuntimeException if the operation doesn't complete before the timeout concludes. + */ + public ShareFileDownloadResponse downloadWithResponse(OutputStream stream, ShareFileDownloadOptions options, + Duration timeout, Context context) { Objects.requireNonNull(stream, "'stream' cannot be null."); - Mono download = shareFileAsyncClient.downloadWithResponse(range, rangeGetContentMD5, - requestConditions, context) + Mono download = shareFileAsyncClient.downloadWithResponse(options, context) .flatMap(response -> response.getValue().reduce(stream, (outputStream, buffer) -> { try { outputStream.write(FluxUtil.byteBufferToArray(buffer)); diff --git a/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/implementation/util/ModelHelper.java b/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/implementation/util/ModelHelper.java index 5d53544ca68f4..7687aff6db258 100644 --- a/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/implementation/util/ModelHelper.java +++ b/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/implementation/util/ModelHelper.java @@ -188,4 +188,11 @@ public static ShareFileDownloadHeaders transformFileDownloadHeaders(HttpHeaders throw LOGGER.logExceptionAsError(new RuntimeException(e)); } } + + public static String getETag(HttpHeaders headers) { + if (headers == null) { + return null; + } + return headers.getValue("ETag"); + } } diff --git a/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/models/DownloadRetryOptions.java b/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/models/DownloadRetryOptions.java new file mode 100644 index 0000000000000..22abdb12dcdaa --- /dev/null +++ b/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/models/DownloadRetryOptions.java @@ -0,0 +1,56 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.storage.file.share.models; + +import com.azure.core.annotation.Fluent; +import com.azure.core.util.logging.ClientLogger; + +import java.util.Locale; + +/** + * This class contains the configuration options used to download from the file share service using smart retries, + * starting from a checkpoint, rather than starting over from the beginning. + */ +@Fluent +public final class DownloadRetryOptions { + private static final String PARAMETER_NOT_IN_RANGE = "The value of the parameter '%s' should be between %s and %s."; + + private final ClientLogger logger = new ClientLogger(DownloadRetryOptions.class); + + /* + We use "retry" here because by the time the user passes this type, the initial request, or try, has already been + issued and returned. This is in contrast to the retry policy options, which includes the initial try in its count, + thus the difference in verbiage. + */ + private int maxRetryRequests = 5; + + /** + * Specifies the maximum number of additional HTTP Get requests that will be made while reading the data from a + * response body. + * + * @return the maximum number of retries to attempt before the request finally fails + */ + public int getMaxRetryRequests() { + return maxRetryRequests; + } + + /** + * Specifies the maximum number of additional HTTP Get requests that will be made while reading the data from a + * response body. + * + * @param maxRetryRequests The number of retries to attempt before the request finally fails + * @return the updated DownloadRetryOptions object + * @throws IllegalArgumentException If {@code maxRetryRequests} is less than 0 + */ + public DownloadRetryOptions setMaxRetryRequests(int maxRetryRequests) { + if (maxRetryRequests < 0) { + throw logger.logExceptionAsError( + new IllegalArgumentException(String.format(Locale.ROOT, PARAMETER_NOT_IN_RANGE, + "options.maxRetryRequests", 0, Integer.MAX_VALUE))); + } + + this.maxRetryRequests = maxRetryRequests; + return this; + } +} diff --git a/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/options/ShareFileDownloadOptions.java b/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/options/ShareFileDownloadOptions.java new file mode 100644 index 0000000000000..3d4d592509d29 --- /dev/null +++ b/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/options/ShareFileDownloadOptions.java @@ -0,0 +1,85 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.storage.file.share.options; + +import com.azure.core.annotation.Fluent; +import com.azure.storage.file.share.models.DownloadRetryOptions; +import com.azure.storage.file.share.models.ShareFileRange; +import com.azure.storage.file.share.models.ShareRequestConditions; + +/** + * Extended options that may be passed when downloading a File. + */ +@Fluent +public class ShareFileDownloadOptions { + + private ShareFileRange range; + private Boolean getRangeContentMd5; + private ShareRequestConditions requestConditions; + private DownloadRetryOptions retryOptions; + + /** + * @return The range of bytes over which to list ranges, inclusively. + */ + public ShareFileRange getRange() { + return range; + } + + /** + * @param range The range of bytes over which to list ranges, inclusively. + * @return The updated options. + */ + public ShareFileDownloadOptions setRange(ShareFileRange range) { + this.range = range; + return this; + } + + /** + * @return Whether or not the service returns the MD5 hash for the range. + */ + public Boolean getRangeContentMd5() { + return getRangeContentMd5; + } + + /** + * @param getRangeContentMd5 Whether or not the service returns the MD5 hash for the range. + * @return The updated options. + */ + public ShareFileDownloadOptions setRangeContentMd5(Boolean getRangeContentMd5) { + this.getRangeContentMd5 = getRangeContentMd5; + return this; + } + + /** + * @return {@link ShareRequestConditions} + */ + public ShareRequestConditions getRequestConditions() { + return requestConditions; + } + + /** + * @param requestConditions {@link ShareRequestConditions} for the file. + * @return The updated options. + */ + public ShareFileDownloadOptions setRequestConditions(ShareRequestConditions requestConditions) { + this.requestConditions = requestConditions; + return this; + } + + /** + * @return {@link DownloadRetryOptions} + */ + public DownloadRetryOptions getRetryOptions() { + return retryOptions; + } + + /** + * @param retryOptions {@link DownloadRetryOptions} + * @return The updated options. + */ + public ShareFileDownloadOptions setRetryOptions(DownloadRetryOptions retryOptions) { + this.retryOptions = retryOptions; + return this; + } +} diff --git a/sdk/storage/azure-storage-file-share/src/samples/java/com/azure/storage/file/share/ShareFileAsyncJavaDocCodeSamples.java b/sdk/storage/azure-storage-file-share/src/samples/java/com/azure/storage/file/share/ShareFileAsyncJavaDocCodeSamples.java index b6971b03ac384..2e81f41250a82 100644 --- a/sdk/storage/azure-storage-file-share/src/samples/java/com/azure/storage/file/share/ShareFileAsyncJavaDocCodeSamples.java +++ b/sdk/storage/azure-storage-file-share/src/samples/java/com/azure/storage/file/share/ShareFileAsyncJavaDocCodeSamples.java @@ -5,6 +5,7 @@ import com.azure.core.util.Context; import com.azure.core.util.polling.PollerFlux; import com.azure.storage.common.StorageSharedKeyCredential; +import com.azure.storage.file.share.models.DownloadRetryOptions; import com.azure.storage.file.share.models.FileRange; import com.azure.storage.file.share.models.PermissionCopyModeType; import com.azure.storage.file.share.models.ShareFileCopyInfo; @@ -15,6 +16,7 @@ import com.azure.storage.file.share.models.ShareFileUploadOptions; import com.azure.storage.file.share.models.ShareFileUploadRangeOptions; import com.azure.storage.file.share.models.ShareRequestConditions; +import com.azure.storage.file.share.options.ShareFileDownloadOptions; import com.azure.storage.file.share.options.ShareFileListRangesDiffOptions; import com.azure.storage.file.share.sas.ShareFileSasPermission; import com.azure.storage.file.share.sas.ShareServiceSasSignatureValues; @@ -537,6 +539,27 @@ public void downloadWithLease() { // END: com.azure.storage.file.share.ShareFileAsyncClient.downloadWithResponse#ShareFileRange-Boolean-ShareRequestConditions } + /** + * Generates a code sample for using {@link ShareFileAsyncClient#downloadWithResponse(ShareFileDownloadOptions)} + */ + public void downloadWithOptions() { + ShareFileAsyncClient shareFileAsyncClient = createAsyncClientWithSASToken(); + // BEGIN: com.azure.storage.file.share.ShareFileAsyncClient.downloadWithResponse#ShareFileDownloadOptions + ShareRequestConditions requestConditions = new ShareRequestConditions().setLeaseId(leaseId); + ShareFileRange range = new ShareFileRange(1024, 2047L); + DownloadRetryOptions retryOptions = new DownloadRetryOptions().setMaxRetryRequests(3); + ShareFileDownloadOptions options = new ShareFileDownloadOptions().setRange(range) + .setRequestConditions(requestConditions) + .setRangeContentMd5(false) + .setRetryOptions(retryOptions); + shareFileAsyncClient.downloadWithResponse(options) + .subscribe(response -> + System.out.printf("Complete downloading the data with status code %d%n", response.getStatusCode()), + error -> System.err.println(error.getMessage()) + ); + // END: com.azure.storage.file.share.ShareFileAsyncClient.downloadWithResponse#ShareFileDownloadOptions + } + /** * Generates a code sample for using {@link ShareFileAsyncClient#downloadToFile(String)} diff --git a/sdk/storage/azure-storage-file-share/src/samples/java/com/azure/storage/file/share/ShareFileJavaDocCodeSamples.java b/sdk/storage/azure-storage-file-share/src/samples/java/com/azure/storage/file/share/ShareFileJavaDocCodeSamples.java index e01a7fc83c2f0..517b8c8ae799c 100644 --- a/sdk/storage/azure-storage-file-share/src/samples/java/com/azure/storage/file/share/ShareFileJavaDocCodeSamples.java +++ b/sdk/storage/azure-storage-file-share/src/samples/java/com/azure/storage/file/share/ShareFileJavaDocCodeSamples.java @@ -8,6 +8,7 @@ import com.azure.core.util.polling.SyncPoller; import com.azure.storage.common.StorageSharedKeyCredential; import com.azure.storage.file.share.models.CloseHandlesInfo; +import com.azure.storage.file.share.models.DownloadRetryOptions; import com.azure.storage.file.share.models.FileRange; import com.azure.storage.file.share.models.PermissionCopyModeType; import com.azure.storage.file.share.models.ShareFileCopyInfo; @@ -23,6 +24,7 @@ import com.azure.storage.file.share.models.NtfsFileAttributes; import com.azure.storage.file.share.models.ShareFileUploadRangeOptions; import com.azure.storage.file.share.models.ShareRequestConditions; +import com.azure.storage.file.share.options.ShareFileDownloadOptions; import com.azure.storage.file.share.options.ShareFileListRangesDiffOptions; import com.azure.storage.file.share.sas.ShareFileSasPermission; import com.azure.storage.file.share.sas.ShareServiceSasSignatureValues; @@ -505,6 +507,33 @@ public void downloadWithPropertiesWithLease() { // END: com.azure.storage.file.share.ShareFileClient.downloadWithResponse#OutputStream-ShareFileRange-Boolean-ShareRequestConditions-Duration-Context } + /** + * Generates a code sample for using {@link ShareFileClient#downloadWithResponse(OutputStream, ShareFileDownloadOptions, Duration, Context)} + */ + public void downloadWithOptions() { + ShareFileClient fileClient = createClientWithSASToken(); + // BEGIN: com.azure.storage.file.share.ShareFileClient.downloadWithResponse#OutputStream-ShareFileDownloadOptions-Duration-Context + try { + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + ShareRequestConditions requestConditions = new ShareRequestConditions().setLeaseId(leaseId); + ShareFileRange range = new ShareFileRange(1024, 2047L); + DownloadRetryOptions retryOptions = new DownloadRetryOptions().setMaxRetryRequests(3); + ShareFileDownloadOptions options = new ShareFileDownloadOptions().setRange(range) + .setRequestConditions(requestConditions) + .setRangeContentMd5(false) + .setRetryOptions(retryOptions); + Response response = fileClient.downloadWithResponse(stream, options, Duration.ofSeconds(30), + new Context(key1, value1)); + + System.out.printf("Completed downloading file with status code %d%n", response.getStatusCode()); + System.out.printf("Content of the file is: %n%s%n", + new String(stream.toByteArray(), StandardCharsets.UTF_8)); + } catch (Throwable throwable) { + System.err.printf("Downloading failed with exception. Message: %s%n", throwable.getMessage()); + } + // END: com.azure.storage.file.share.ShareFileClient.downloadWithResponse#OutputStream-ShareFileDownloadOptions-Duration-Context + } + /** * Generates a code sample for using {@link ShareFileClient#downloadToFile(String)} */ diff --git a/sdk/storage/azure-storage-file-share/src/test/java/com/azure/storage/file/share/FileAPITests.groovy b/sdk/storage/azure-storage-file-share/src/test/java/com/azure/storage/file/share/FileAPITests.groovy index 78d38db60c3eb..3f67e56519662 100644 --- a/sdk/storage/azure-storage-file-share/src/test/java/com/azure/storage/file/share/FileAPITests.groovy +++ b/sdk/storage/azure-storage-file-share/src/test/java/com/azure/storage/file/share/FileAPITests.groovy @@ -5,12 +5,16 @@ package com.azure.storage.file.share import com.azure.core.exception.UnexpectedLengthException import com.azure.core.util.Context +import com.azure.core.util.CoreUtils import com.azure.core.util.polling.SyncPoller import com.azure.storage.common.ParallelTransferOptions import com.azure.storage.common.StorageSharedKeyCredential import com.azure.storage.common.implementation.Constants import com.azure.storage.common.test.shared.extensions.LiveOnly import com.azure.storage.common.test.shared.extensions.RequiredServiceVersion +import com.azure.storage.common.test.shared.policy.MockFailureResponsePolicy +import com.azure.storage.common.test.shared.policy.MockRetryRangeResponsePolicy +import com.azure.storage.file.share.models.DownloadRetryOptions import com.azure.storage.file.share.models.NtfsFileAttributes import com.azure.storage.file.share.models.PermissionCopyModeType import com.azure.storage.file.share.models.ShareErrorCode @@ -22,6 +26,7 @@ import com.azure.storage.file.share.models.ShareFileUploadRangeOptions import com.azure.storage.file.share.models.ShareRequestConditions import com.azure.storage.file.share.models.ShareSnapshotInfo import com.azure.storage.file.share.models.ShareStorageException +import com.azure.storage.file.share.options.ShareFileDownloadOptions import com.azure.storage.file.share.options.ShareFileListRangesDiffOptions import com.azure.storage.file.share.sas.ShareFileSasPermission import com.azure.storage.file.share.sas.ShareServiceSasSignatureValues @@ -29,6 +34,7 @@ import spock.lang.Ignore import spock.lang.Requires import spock.lang.Unroll +import java.nio.ByteBuffer import java.nio.charset.StandardCharsets import java.nio.file.FileAlreadyExistsException import java.nio.file.NoSuchFileException @@ -348,6 +354,93 @@ class FileAPITests extends APISpec { data.defaultBytes == stream.toByteArray() } + def "Download all null"() { + given: + primaryFileClient.create(data.defaultDataSizeLong) + primaryFileClient.upload(data.defaultInputStream, data.defaultDataSizeLong) + + when: + def stream = new ByteArrayOutputStream() + def response = primaryFileClient.downloadWithResponse(stream, null, null, null) + def body = stream.toByteArray() + def headers = response.getDeserializedHeaders() + + then: + body == data.defaultBytes + CoreUtils.isNullOrEmpty(headers.getMetadata()) + headers.getContentLength() != null + headers.getContentType() != null + headers.getContentRange() != null + headers.getContentMd5() == null + headers.getContentEncoding() == null + headers.getCacheControl() == null + headers.getContentDisposition() == null + headers.getContentLanguage() == null + } + + def "Download empty file"() { + setup: + primaryFileClient.create(1) + + when: + def outStream = new ByteArrayOutputStream() + primaryFileClient.download(outStream) + def result = outStream.toByteArray() + + then: + notThrown(ShareStorageException) + result.length == 1 + !result[0] + } + + /* + This is to test the appropriate integration of DownloadResponse, including setting the correct range values on + HttpGetterInfo. + */ + + def "Download with retry range"() { + /* + We are going to make a request for some range on a blob. The Flux returned will throw an exception, forcing + a retry per the DownloadRetryOptions. The next request should have the same range header, which was generated + from the count and offset values in HttpGetterInfo that was constructed on the initial call to download. We + don't need to check the data here, but we want to ensure that the correct range is set each time. This will + test the correction of a bug that was found which caused HttpGetterInfo to have an incorrect offset when it was + constructed in FileClient.download(). + */ + setup: + primaryFileClient.create(data.defaultDataSizeLong) + primaryFileClient.upload(data.defaultInputStream, data.defaultDataSizeLong) + def fc2 = getFileClient(env.primaryAccount.credential, primaryFileClient.getFileUrl(), new MockRetryRangeResponsePolicy("bytes=2-6")) + + when: + def range = new ShareFileRange(2, 6L) + def options = new DownloadRetryOptions().setMaxRetryRequests(3) + fc2.downloadWithResponse(new ByteArrayOutputStream(), new ShareFileDownloadOptions().setRange(range).setRetryOptions(options), null, null) + + then: + /* + Because the dummy Flux always throws an error. This will also validate that an IllegalArgumentException is + NOT thrown because the types would not match. + */ + def e = thrown(RuntimeException) + e.getCause() instanceof IOException + } + + def "Download retry default"() { + setup: + primaryFileClient.create(data.defaultDataSizeLong) + primaryFileClient.upload(data.defaultInputStream, data.defaultDataSizeLong) + def failureClient = getFileClient(env.primaryAccount.credential, primaryFileClient.getFileUrl(), new MockFailureResponsePolicy(5)) + + when: + def outStream = new ByteArrayOutputStream() + failureClient.download(outStream) + String bodyStr = outStream.toString() + + then: + bodyStr == data.defaultText + } + @RequiredServiceVersion(clazz = ShareServiceVersion.class, min = "V2020_02_10") def "Upload Range 4TB"() { given: diff --git a/sdk/storage/azure-storage-file-share/src/test/resources/session-records/FileAPITestsDownloadAllNull.json b/sdk/storage/azure-storage-file-share/src/test/resources/session-records/FileAPITestsDownloadAllNull.json new file mode 100644 index 0000000000000..d952e35c6e75f --- /dev/null +++ b/sdk/storage/azure-storage-file-share/src/test/resources/session-records/FileAPITestsDownloadAllNull.json @@ -0,0 +1,114 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://REDACTED.file.core.windows.net/3243218e3243218e53694335db3b1be80202449a97?restype=share", + "Headers" : { + "x-ms-version" : "2020-08-04", + "User-Agent" : "azsdk-java-azure-storage-file-share/12.11.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "382a788f-80e3-401b-b189-a4cba648baec" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2020-08-04", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "eTag" : "0x8D936ABC67836E4", + "Last-Modified" : "Thu, 24 Jun 2021 01:02:44 GMT", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "b081bddd-801a-0046-0494-683dd8000000", + "x-ms-client-request-id" : "382a788f-80e3-401b-b189-a4cba648baec", + "Date" : "Thu, 24 Jun 2021 01:02:44 GMT" + }, + "Exception" : null + }, { + "Method" : "PUT", + "Uri" : "https://REDACTED.file.core.windows.net/3243218e3243218e53694335db3b1be80202449a97/3243218e3243218e53660163e69e73c7ce45433390", + "Headers" : { + "x-ms-version" : "2020-08-04", + "User-Agent" : "azsdk-java-azure-storage-file-share/12.11.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "72fc2a2c-9bcc-4e51-920a-4ee33b4d6cdc" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2020-08-04", + "x-ms-file-permission-key" : "2559623233989293371*10026547158748585397", + "x-ms-file-id" : "13835128424026341376", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-file-creation-time" : "2021-06-24T01:02:44.9657932Z", + "Last-Modified" : "Thu, 24 Jun 2021 01:02:44 GMT", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-server-encrypted" : "true", + "Date" : "Thu, 24 Jun 2021 01:02:44 GMT", + "x-ms-file-attributes" : "Archive", + "x-ms-file-change-time" : "2021-06-24T01:02:44.9657932Z", + "x-ms-file-parent-id" : "0", + "eTag" : "0x8D936ABC6A5304C", + "x-ms-request-id" : "b081bde0-801a-0046-0594-683dd8000000", + "x-ms-client-request-id" : "72fc2a2c-9bcc-4e51-920a-4ee33b4d6cdc", + "x-ms-file-last-write-time" : "2021-06-24T01:02:44.9657932Z" + }, + "Exception" : null + }, { + "Method" : "PUT", + "Uri" : "https://REDACTED.file.core.windows.net/3243218e3243218e53694335db3b1be80202449a97/3243218e3243218e53660163e69e73c7ce45433390?comp=range", + "Headers" : { + "x-ms-version" : "2020-08-04", + "User-Agent" : "azsdk-java-azure-storage-file-share/12.11.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "9ec78499-7af8-443c-820d-880b8e6857ab", + "Content-Type" : "application/octet-stream" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2020-08-04", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "eTag" : "0x8D936ABC6C2CFD3", + "Last-Modified" : "Thu, 24 Jun 2021 01:02:45 GMT", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "b081bde1-801a-0046-0694-683dd8000000", + "x-ms-request-server-encrypted" : "true", + "x-ms-client-request-id" : "9ec78499-7af8-443c-820d-880b8e6857ab", + "Date" : "Thu, 24 Jun 2021 01:02:44 GMT", + "Content-MD5" : "wh+Wm18D0z1D4E+PE252gg==" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.file.core.windows.net/3243218e3243218e53694335db3b1be80202449a97/3243218e3243218e53660163e69e73c7ce45433390", + "Headers" : { + "x-ms-version" : "2020-08-04", + "User-Agent" : "azsdk-java-azure-storage-file-share/12.11.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "0657ca2d-f5c1-4a97-a70c-a37ddee1d3cd" + }, + "Response" : { + "content-length" : "7", + "x-ms-lease-status" : "unlocked", + "x-ms-file-id" : "13835128424026341376", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-file-creation-time" : "2021-06-24T01:02:44.9657932Z", + "Content-Range" : "bytes 0-6/7", + "x-ms-lease-state" : "available", + "Last-Modified" : "Thu, 24 Jun 2021 01:02:45 GMT", + "retry-after" : "0", + "StatusCode" : "206", + "x-ms-file-attributes" : "Archive", + "eTag" : "0x8D936ABC6C2CFD3", + "x-ms-request-id" : "b081bde2-801a-0046-0794-683dd8000000", + "Body" : "ZGVmYXVsdA==", + "Content-Type" : "application/octet-stream", + "x-ms-version" : "2020-08-04", + "x-ms-file-permission-key" : "2559623233989293371*10026547158748585397", + "Date" : "Thu, 24 Jun 2021 01:02:44 GMT", + "Accept-Ranges" : "bytes", + "x-ms-server-encrypted" : "true", + "x-ms-type" : "File", + "x-ms-file-change-time" : "2021-06-24T01:02:44.9657932Z", + "x-ms-file-parent-id" : "0", + "x-ms-client-request-id" : "0657ca2d-f5c1-4a97-a70c-a37ddee1d3cd", + "x-ms-file-last-write-time" : "2021-06-24T01:02:44.9657932Z" + }, + "Exception" : null + } ], + "variables" : [ "3243218e3243218e53694335db3b1be80202449a97", "3243218e3243218e53660163e69e73c7ce45433390" ] +} \ No newline at end of file diff --git a/sdk/storage/azure-storage-file-share/src/test/resources/session-records/FileAPITestsDownloadEmptyFile.json b/sdk/storage/azure-storage-file-share/src/test/resources/session-records/FileAPITestsDownloadEmptyFile.json new file mode 100644 index 0000000000000..83ca2fb71d9c1 --- /dev/null +++ b/sdk/storage/azure-storage-file-share/src/test/resources/session-records/FileAPITestsDownloadEmptyFile.json @@ -0,0 +1,90 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://REDACTED.file.core.windows.net/c44dd708c44dd70852c42552e52ea596dcea470a82?restype=share", + "Headers" : { + "x-ms-version" : "2020-08-04", + "User-Agent" : "azsdk-java-azure-storage-file-share/12.11.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "e8148acd-0429-4573-a731-7a81a4ec3798" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2020-08-04", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "eTag" : "0x8D936ABFFE1E21B", + "Last-Modified" : "Thu, 24 Jun 2021 01:04:20 GMT", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "3749d34f-d01a-0055-0d94-680839000000", + "x-ms-client-request-id" : "e8148acd-0429-4573-a731-7a81a4ec3798", + "Date" : "Thu, 24 Jun 2021 01:04:20 GMT" + }, + "Exception" : null + }, { + "Method" : "PUT", + "Uri" : "https://REDACTED.file.core.windows.net/c44dd708c44dd70852c42552e52ea596dcea470a82/c44dd708c44dd70852c0117536c599920f1a4b4aa6", + "Headers" : { + "x-ms-version" : "2020-08-04", + "User-Agent" : "azsdk-java-azure-storage-file-share/12.11.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "39bdd492-3082-46cf-97b3-f68a850fdf5e" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2020-08-04", + "x-ms-file-permission-key" : "2559623233989293371*10026547158748585397", + "x-ms-file-id" : "13835128424026341376", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-file-creation-time" : "2021-06-24T01:04:21.2902256Z", + "Last-Modified" : "Thu, 24 Jun 2021 01:04:21 GMT", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-server-encrypted" : "true", + "Date" : "Thu, 24 Jun 2021 01:04:20 GMT", + "x-ms-file-attributes" : "Archive", + "x-ms-file-change-time" : "2021-06-24T01:04:21.2902256Z", + "x-ms-file-parent-id" : "0", + "eTag" : "0x8D936AC000F2170", + "x-ms-request-id" : "3749d363-d01a-0055-1b94-680839000000", + "x-ms-client-request-id" : "39bdd492-3082-46cf-97b3-f68a850fdf5e", + "x-ms-file-last-write-time" : "2021-06-24T01:04:21.2902256Z" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.file.core.windows.net/c44dd708c44dd70852c42552e52ea596dcea470a82/c44dd708c44dd70852c0117536c599920f1a4b4aa6", + "Headers" : { + "x-ms-version" : "2020-08-04", + "User-Agent" : "azsdk-java-azure-storage-file-share/12.11.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "5562ecb1-7e1b-4a0f-afc2-17b1138381fc" + }, + "Response" : { + "content-length" : "1", + "x-ms-lease-status" : "unlocked", + "x-ms-file-id" : "13835128424026341376", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-file-creation-time" : "2021-06-24T01:04:21.2902256Z", + "Content-Range" : "bytes 0-0/1", + "x-ms-lease-state" : "available", + "Last-Modified" : "Thu, 24 Jun 2021 01:04:21 GMT", + "retry-after" : "0", + "StatusCode" : "206", + "x-ms-file-attributes" : "Archive", + "eTag" : "0x8D936AC000F2170", + "x-ms-request-id" : "3749d368-d01a-0055-1f94-680839000000", + "Body" : "AA==", + "Content-Type" : "application/octet-stream", + "x-ms-version" : "2020-08-04", + "x-ms-file-permission-key" : "2559623233989293371*10026547158748585397", + "Date" : "Thu, 24 Jun 2021 01:04:21 GMT", + "Accept-Ranges" : "bytes", + "x-ms-server-encrypted" : "true", + "x-ms-type" : "File", + "x-ms-file-change-time" : "2021-06-24T01:04:21.2902256Z", + "x-ms-file-parent-id" : "0", + "x-ms-client-request-id" : "5562ecb1-7e1b-4a0f-afc2-17b1138381fc", + "x-ms-file-last-write-time" : "2021-06-24T01:04:21.2902256Z" + }, + "Exception" : null + } ], + "variables" : [ "c44dd708c44dd70852c42552e52ea596dcea470a82", "c44dd708c44dd70852c0117536c599920f1a4b4aa6" ] +} \ No newline at end of file diff --git a/sdk/storage/azure-storage-file-share/src/test/resources/session-records/FileAPITestsDownloadRetryDefault.json b/sdk/storage/azure-storage-file-share/src/test/resources/session-records/FileAPITestsDownloadRetryDefault.json new file mode 100644 index 0000000000000..0e1ebc5294145 --- /dev/null +++ b/sdk/storage/azure-storage-file-share/src/test/resources/session-records/FileAPITestsDownloadRetryDefault.json @@ -0,0 +1,294 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://REDACTED.file.core.windows.net/6661bfcc6661bfcced45901141e1ecc5cb904e5fb7?restype=share", + "Headers" : { + "x-ms-version" : "2020-08-04", + "User-Agent" : "azsdk-java-azure-storage-file-share/12.11.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "4742eabc-d0fb-44b9-9824-b1e3e6baf52b" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2020-08-04", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "eTag" : "0x8D937476B68BA73", + "Last-Modified" : "Thu, 24 Jun 2021 19:36:53 GMT", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "02b41c9a-f01a-00c1-3030-6968f7000000", + "x-ms-client-request-id" : "4742eabc-d0fb-44b9-9824-b1e3e6baf52b", + "Date" : "Thu, 24 Jun 2021 19:36:52 GMT" + }, + "Exception" : null + }, { + "Method" : "PUT", + "Uri" : "https://REDACTED.file.core.windows.net/6661bfcc6661bfcced45901141e1ecc5cb904e5fb7/6661bfcc6661bfcced475304f9dc872bb07d42f3bb", + "Headers" : { + "x-ms-version" : "2020-08-04", + "User-Agent" : "azsdk-java-azure-storage-file-share/12.11.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "1c9fbed7-e339-47c7-9839-88c37a66da42" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2020-08-04", + "x-ms-file-permission-key" : "2559623233989293371*10026547158748585397", + "x-ms-file-id" : "13835128424026341376", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-file-creation-time" : "2021-06-24T19:36:53.7585176Z", + "Last-Modified" : "Thu, 24 Jun 2021 19:36:53 GMT", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-server-encrypted" : "true", + "Date" : "Thu, 24 Jun 2021 19:36:53 GMT", + "x-ms-file-attributes" : "Archive", + "x-ms-file-change-time" : "2021-06-24T19:36:53.7585176Z", + "x-ms-file-parent-id" : "0", + "eTag" : "0x8D937476BA17618", + "x-ms-request-id" : "02b41ca0-f01a-00c1-3230-6968f7000000", + "x-ms-client-request-id" : "1c9fbed7-e339-47c7-9839-88c37a66da42", + "x-ms-file-last-write-time" : "2021-06-24T19:36:53.7585176Z" + }, + "Exception" : null + }, { + "Method" : "PUT", + "Uri" : "https://REDACTED.file.core.windows.net/6661bfcc6661bfcced45901141e1ecc5cb904e5fb7/6661bfcc6661bfcced475304f9dc872bb07d42f3bb?comp=range", + "Headers" : { + "x-ms-version" : "2020-08-04", + "User-Agent" : "azsdk-java-azure-storage-file-share/12.11.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "999f4807-e49c-40a4-8888-f79ec89e54d0", + "Content-Type" : "application/octet-stream" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2020-08-04", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "eTag" : "0x8D937476BB29030", + "Last-Modified" : "Thu, 24 Jun 2021 19:36:53 GMT", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "02b41ca1-f01a-00c1-3330-6968f7000000", + "x-ms-request-server-encrypted" : "true", + "x-ms-client-request-id" : "999f4807-e49c-40a4-8888-f79ec89e54d0", + "Date" : "Thu, 24 Jun 2021 19:36:53 GMT", + "Content-MD5" : "wh+Wm18D0z1D4E+PE252gg==" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.file.core.windows.net/6661bfcc6661bfcced45901141e1ecc5cb904e5fb7/6661bfcc6661bfcced475304f9dc872bb07d42f3bb", + "Headers" : { + "x-ms-version" : "2020-08-04", + "User-Agent" : "azsdk-java-azure-storage-file-share/12.11.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "d48fad92-3a61-48af-a8ed-39a80349e022" + }, + "Response" : { + "content-length" : "7", + "x-ms-lease-status" : "unlocked", + "x-ms-file-id" : "13835128424026341376", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-file-creation-time" : "2021-06-24T19:36:53.7585176Z", + "Content-Range" : "bytes 0-6/7", + "x-ms-lease-state" : "available", + "Last-Modified" : "Thu, 24 Jun 2021 19:36:53 GMT", + "retry-after" : "0", + "StatusCode" : "206", + "x-ms-file-attributes" : "Archive", + "eTag" : "0x8D937476BB29030", + "x-ms-request-id" : "02b41ca3-f01a-00c1-3530-6968f7000000", + "Body" : "ZGVmYXVsdA==", + "Content-Type" : "application/octet-stream", + "x-ms-version" : "2020-08-04", + "x-ms-file-permission-key" : "2559623233989293371*10026547158748585397", + "Date" : "Thu, 24 Jun 2021 19:36:53 GMT", + "Accept-Ranges" : "bytes", + "x-ms-server-encrypted" : "true", + "x-ms-type" : "File", + "x-ms-file-change-time" : "2021-06-24T19:36:53.7585176Z", + "x-ms-file-parent-id" : "0", + "x-ms-client-request-id" : "d48fad92-3a61-48af-a8ed-39a80349e022", + "x-ms-file-last-write-time" : "2021-06-24T19:36:53.7585176Z" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.file.core.windows.net/6661bfcc6661bfcced45901141e1ecc5cb904e5fb7/6661bfcc6661bfcced475304f9dc872bb07d42f3bb", + "Headers" : { + "x-ms-version" : "2020-08-04", + "User-Agent" : "azsdk-java-azure-storage-file-share/12.11.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "a92f9d97-23dd-4deb-a6b0-32d2bc0ccb10" + }, + "Response" : { + "content-length" : "7", + "x-ms-lease-status" : "unlocked", + "x-ms-file-id" : "13835128424026341376", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-file-creation-time" : "2021-06-24T19:36:53.7585176Z", + "Content-Range" : "bytes 0-6/7", + "x-ms-lease-state" : "available", + "Last-Modified" : "Thu, 24 Jun 2021 19:36:53 GMT", + "retry-after" : "0", + "StatusCode" : "206", + "x-ms-file-attributes" : "Archive", + "eTag" : "0x8D937476BB29030", + "x-ms-request-id" : "02b41ca4-f01a-00c1-3630-6968f7000000", + "Body" : "ZGVmYXVsdA==", + "Content-Type" : "application/octet-stream", + "x-ms-version" : "2020-08-04", + "x-ms-file-permission-key" : "2559623233989293371*10026547158748585397", + "Date" : "Thu, 24 Jun 2021 19:36:53 GMT", + "Accept-Ranges" : "bytes", + "x-ms-server-encrypted" : "true", + "x-ms-type" : "File", + "x-ms-file-change-time" : "2021-06-24T19:36:53.7585176Z", + "x-ms-file-parent-id" : "0", + "x-ms-client-request-id" : "a92f9d97-23dd-4deb-a6b0-32d2bc0ccb10", + "x-ms-file-last-write-time" : "2021-06-24T19:36:53.7585176Z" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.file.core.windows.net/6661bfcc6661bfcced45901141e1ecc5cb904e5fb7/6661bfcc6661bfcced475304f9dc872bb07d42f3bb", + "Headers" : { + "x-ms-version" : "2020-08-04", + "User-Agent" : "azsdk-java-azure-storage-file-share/12.11.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "e5d05f89-58c9-4aff-8172-9ba0be16ae3d" + }, + "Response" : { + "content-length" : "7", + "x-ms-lease-status" : "unlocked", + "x-ms-file-id" : "13835128424026341376", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-file-creation-time" : "2021-06-24T19:36:53.7585176Z", + "Content-Range" : "bytes 0-6/7", + "x-ms-lease-state" : "available", + "Last-Modified" : "Thu, 24 Jun 2021 19:36:53 GMT", + "retry-after" : "0", + "StatusCode" : "206", + "x-ms-file-attributes" : "Archive", + "eTag" : "0x8D937476BB29030", + "x-ms-request-id" : "02b41ca5-f01a-00c1-3730-6968f7000000", + "Body" : "ZGVmYXVsdA==", + "Content-Type" : "application/octet-stream", + "x-ms-version" : "2020-08-04", + "x-ms-file-permission-key" : "2559623233989293371*10026547158748585397", + "Date" : "Thu, 24 Jun 2021 19:36:53 GMT", + "Accept-Ranges" : "bytes", + "x-ms-server-encrypted" : "true", + "x-ms-type" : "File", + "x-ms-file-change-time" : "2021-06-24T19:36:53.7585176Z", + "x-ms-file-parent-id" : "0", + "x-ms-client-request-id" : "e5d05f89-58c9-4aff-8172-9ba0be16ae3d", + "x-ms-file-last-write-time" : "2021-06-24T19:36:53.7585176Z" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.file.core.windows.net/6661bfcc6661bfcced45901141e1ecc5cb904e5fb7/6661bfcc6661bfcced475304f9dc872bb07d42f3bb", + "Headers" : { + "x-ms-version" : "2020-08-04", + "User-Agent" : "azsdk-java-azure-storage-file-share/12.11.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "ec204d50-b542-4621-99de-b7ae7ceb0f39" + }, + "Response" : { + "content-length" : "7", + "x-ms-lease-status" : "unlocked", + "x-ms-file-id" : "13835128424026341376", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-file-creation-time" : "2021-06-24T19:36:53.7585176Z", + "Content-Range" : "bytes 0-6/7", + "x-ms-lease-state" : "available", + "Last-Modified" : "Thu, 24 Jun 2021 19:36:53 GMT", + "retry-after" : "0", + "StatusCode" : "206", + "x-ms-file-attributes" : "Archive", + "eTag" : "0x8D937476BB29030", + "x-ms-request-id" : "02b41ca6-f01a-00c1-3830-6968f7000000", + "Body" : "ZGVmYXVsdA==", + "Content-Type" : "application/octet-stream", + "x-ms-version" : "2020-08-04", + "x-ms-file-permission-key" : "2559623233989293371*10026547158748585397", + "Date" : "Thu, 24 Jun 2021 19:36:53 GMT", + "Accept-Ranges" : "bytes", + "x-ms-server-encrypted" : "true", + "x-ms-type" : "File", + "x-ms-file-change-time" : "2021-06-24T19:36:53.7585176Z", + "x-ms-file-parent-id" : "0", + "x-ms-client-request-id" : "ec204d50-b542-4621-99de-b7ae7ceb0f39", + "x-ms-file-last-write-time" : "2021-06-24T19:36:53.7585176Z" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.file.core.windows.net/6661bfcc6661bfcced45901141e1ecc5cb904e5fb7/6661bfcc6661bfcced475304f9dc872bb07d42f3bb", + "Headers" : { + "x-ms-version" : "2020-08-04", + "User-Agent" : "azsdk-java-azure-storage-file-share/12.11.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "cf32708e-ec8a-4ecf-8ffe-154a629d4361" + }, + "Response" : { + "content-length" : "7", + "x-ms-lease-status" : "unlocked", + "x-ms-file-id" : "13835128424026341376", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-file-creation-time" : "2021-06-24T19:36:53.7585176Z", + "Content-Range" : "bytes 0-6/7", + "x-ms-lease-state" : "available", + "Last-Modified" : "Thu, 24 Jun 2021 19:36:53 GMT", + "retry-after" : "0", + "StatusCode" : "206", + "x-ms-file-attributes" : "Archive", + "eTag" : "0x8D937476BB29030", + "x-ms-request-id" : "02b41ca7-f01a-00c1-3930-6968f7000000", + "Body" : "ZGVmYXVsdA==", + "Content-Type" : "application/octet-stream", + "x-ms-version" : "2020-08-04", + "x-ms-file-permission-key" : "2559623233989293371*10026547158748585397", + "Date" : "Thu, 24 Jun 2021 19:36:53 GMT", + "Accept-Ranges" : "bytes", + "x-ms-server-encrypted" : "true", + "x-ms-type" : "File", + "x-ms-file-change-time" : "2021-06-24T19:36:53.7585176Z", + "x-ms-file-parent-id" : "0", + "x-ms-client-request-id" : "cf32708e-ec8a-4ecf-8ffe-154a629d4361", + "x-ms-file-last-write-time" : "2021-06-24T19:36:53.7585176Z" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.file.core.windows.net/6661bfcc6661bfcced45901141e1ecc5cb904e5fb7/6661bfcc6661bfcced475304f9dc872bb07d42f3bb", + "Headers" : { + "x-ms-version" : "2020-08-04", + "User-Agent" : "azsdk-java-azure-storage-file-share/12.11.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "66eb0a1a-6d9d-4eea-ad2d-825240a511b2" + }, + "Response" : { + "content-length" : "7", + "x-ms-lease-status" : "unlocked", + "x-ms-file-id" : "13835128424026341376", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-file-creation-time" : "2021-06-24T19:36:53.7585176Z", + "Content-Range" : "bytes 0-6/7", + "x-ms-lease-state" : "available", + "Last-Modified" : "Thu, 24 Jun 2021 19:36:53 GMT", + "retry-after" : "0", + "StatusCode" : "206", + "x-ms-file-attributes" : "Archive", + "eTag" : "0x8D937476BB29030", + "x-ms-request-id" : "02b41ca8-f01a-00c1-3a30-6968f7000000", + "Body" : "ZGVmYXVsdA==", + "Content-Type" : "application/octet-stream", + "x-ms-version" : "2020-08-04", + "x-ms-file-permission-key" : "2559623233989293371*10026547158748585397", + "Date" : "Thu, 24 Jun 2021 19:36:53 GMT", + "Accept-Ranges" : "bytes", + "x-ms-server-encrypted" : "true", + "x-ms-type" : "File", + "x-ms-file-change-time" : "2021-06-24T19:36:53.7585176Z", + "x-ms-file-parent-id" : "0", + "x-ms-client-request-id" : "66eb0a1a-6d9d-4eea-ad2d-825240a511b2", + "x-ms-file-last-write-time" : "2021-06-24T19:36:53.7585176Z" + }, + "Exception" : null + } ], + "variables" : [ "6661bfcc6661bfcced45901141e1ecc5cb904e5fb7", "6661bfcc6661bfcced475304f9dc872bb07d42f3bb" ] +} \ No newline at end of file diff --git a/sdk/storage/azure-storage-file-share/src/test/resources/session-records/FileAPITestsDownloadWithRetryRange.json b/sdk/storage/azure-storage-file-share/src/test/resources/session-records/FileAPITestsDownloadWithRetryRange.json new file mode 100644 index 0000000000000..119b3538831dd --- /dev/null +++ b/sdk/storage/azure-storage-file-share/src/test/resources/session-records/FileAPITestsDownloadWithRetryRange.json @@ -0,0 +1,222 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://REDACTED.file.core.windows.net/46640b9946640b99558335126ab174aa329c42ad88?restype=share", + "Headers" : { + "x-ms-version" : "2020-08-04", + "User-Agent" : "azsdk-java-azure-storage-file-share/12.11.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "e02fcf77-dd58-4579-9f3f-9c9c7b972ed8" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2020-08-04", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "eTag" : "0x8D93744F21279BE", + "Last-Modified" : "Thu, 24 Jun 2021 19:19:10 GMT", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "15bdd339-301a-00d7-752d-69a969000000", + "x-ms-client-request-id" : "e02fcf77-dd58-4579-9f3f-9c9c7b972ed8", + "Date" : "Thu, 24 Jun 2021 19:19:09 GMT" + }, + "Exception" : null + }, { + "Method" : "PUT", + "Uri" : "https://REDACTED.file.core.windows.net/46640b9946640b99558335126ab174aa329c42ad88/46640b9946640b99558808139c3701a132bf44129d", + "Headers" : { + "x-ms-version" : "2020-08-04", + "User-Agent" : "azsdk-java-azure-storage-file-share/12.11.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "0871d106-e9e3-4df9-b4e2-3d7fbf4d62de" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2020-08-04", + "x-ms-file-permission-key" : "2559623233989293371*10026547158748585397", + "x-ms-file-id" : "13835128424026341376", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-file-creation-time" : "2021-06-24T19:19:12.4573506Z", + "Last-Modified" : "Thu, 24 Jun 2021 19:19:12 GMT", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-server-encrypted" : "true", + "Date" : "Thu, 24 Jun 2021 19:19:12 GMT", + "x-ms-file-attributes" : "Archive", + "x-ms-file-change-time" : "2021-06-24T19:19:12.4573506Z", + "x-ms-file-parent-id" : "0", + "eTag" : "0x8D93744F30BC142", + "x-ms-request-id" : "15bdd343-301a-00d7-782d-69a969000000", + "x-ms-client-request-id" : "0871d106-e9e3-4df9-b4e2-3d7fbf4d62de", + "x-ms-file-last-write-time" : "2021-06-24T19:19:12.4573506Z" + }, + "Exception" : null + }, { + "Method" : "PUT", + "Uri" : "https://REDACTED.file.core.windows.net/46640b9946640b99558335126ab174aa329c42ad88/46640b9946640b99558808139c3701a132bf44129d?comp=range", + "Headers" : { + "x-ms-version" : "2020-08-04", + "User-Agent" : "azsdk-java-azure-storage-file-share/12.11.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "35183239-9970-42b5-ae3e-440e20641e41", + "Content-Type" : "application/octet-stream" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2020-08-04", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "eTag" : "0x8D93744F341CF2D", + "Last-Modified" : "Thu, 24 Jun 2021 19:19:12 GMT", + "retry-after" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "15bdd344-301a-00d7-792d-69a969000000", + "x-ms-request-server-encrypted" : "true", + "x-ms-client-request-id" : "35183239-9970-42b5-ae3e-440e20641e41", + "Date" : "Thu, 24 Jun 2021 19:19:12 GMT", + "Content-MD5" : "wh+Wm18D0z1D4E+PE252gg==" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.file.core.windows.net/46640b9946640b99558335126ab174aa329c42ad88/46640b9946640b99558808139c3701a132bf44129d", + "Headers" : { + "x-ms-version" : "2020-08-04", + "User-Agent" : "azsdk-java-azure-storage-file-share/12.11.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "7a18200b-e0ae-4b92-adf8-9c18c0467672" + }, + "Response" : { + "content-length" : "5", + "x-ms-lease-status" : "unlocked", + "x-ms-file-id" : "13835128424026341376", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-file-creation-time" : "2021-06-24T19:19:12.4573506Z", + "Content-Range" : "bytes 2-6/7", + "x-ms-lease-state" : "available", + "Last-Modified" : "Thu, 24 Jun 2021 19:19:12 GMT", + "retry-after" : "0", + "StatusCode" : "206", + "x-ms-file-attributes" : "Archive", + "eTag" : "0x8D93744F341CF2D", + "x-ms-request-id" : "15bdd34c-301a-00d7-7d2d-69a969000000", + "Body" : "ZmF1bHQ=", + "Content-Type" : "application/octet-stream", + "x-ms-version" : "2020-08-04", + "x-ms-file-permission-key" : "2559623233989293371*10026547158748585397", + "Date" : "Thu, 24 Jun 2021 19:19:13 GMT", + "Accept-Ranges" : "bytes", + "x-ms-server-encrypted" : "true", + "x-ms-type" : "File", + "x-ms-file-change-time" : "2021-06-24T19:19:12.4573506Z", + "x-ms-file-parent-id" : "0", + "x-ms-client-request-id" : "7a18200b-e0ae-4b92-adf8-9c18c0467672", + "x-ms-file-last-write-time" : "2021-06-24T19:19:12.4573506Z" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.file.core.windows.net/46640b9946640b99558335126ab174aa329c42ad88/46640b9946640b99558808139c3701a132bf44129d", + "Headers" : { + "x-ms-version" : "2020-08-04", + "User-Agent" : "azsdk-java-azure-storage-file-share/12.11.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "bd690649-8ca3-4712-bff1-3c9807424fa0" + }, + "Response" : { + "content-length" : "5", + "x-ms-lease-status" : "unlocked", + "x-ms-file-id" : "13835128424026341376", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-file-creation-time" : "2021-06-24T19:19:12.4573506Z", + "Content-Range" : "bytes 2-6/7", + "x-ms-lease-state" : "available", + "Last-Modified" : "Thu, 24 Jun 2021 19:19:12 GMT", + "retry-after" : "0", + "StatusCode" : "206", + "x-ms-file-attributes" : "Archive", + "eTag" : "0x8D93744F341CF2D", + "x-ms-request-id" : "15bdd34d-301a-00d7-7e2d-69a969000000", + "Body" : "ZmF1bHQ=", + "Content-Type" : "application/octet-stream", + "x-ms-version" : "2020-08-04", + "x-ms-file-permission-key" : "2559623233989293371*10026547158748585397", + "Date" : "Thu, 24 Jun 2021 19:19:13 GMT", + "Accept-Ranges" : "bytes", + "x-ms-server-encrypted" : "true", + "x-ms-type" : "File", + "x-ms-file-change-time" : "2021-06-24T19:19:12.4573506Z", + "x-ms-file-parent-id" : "0", + "x-ms-client-request-id" : "bd690649-8ca3-4712-bff1-3c9807424fa0", + "x-ms-file-last-write-time" : "2021-06-24T19:19:12.4573506Z" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.file.core.windows.net/46640b9946640b99558335126ab174aa329c42ad88/46640b9946640b99558808139c3701a132bf44129d", + "Headers" : { + "x-ms-version" : "2020-08-04", + "User-Agent" : "azsdk-java-azure-storage-file-share/12.11.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "f8678f16-bc7a-4b47-8935-f5eee92b65e0" + }, + "Response" : { + "content-length" : "5", + "x-ms-lease-status" : "unlocked", + "x-ms-file-id" : "13835128424026341376", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-file-creation-time" : "2021-06-24T19:19:12.4573506Z", + "Content-Range" : "bytes 2-6/7", + "x-ms-lease-state" : "available", + "Last-Modified" : "Thu, 24 Jun 2021 19:19:12 GMT", + "retry-after" : "0", + "StatusCode" : "206", + "x-ms-file-attributes" : "Archive", + "eTag" : "0x8D93744F341CF2D", + "x-ms-request-id" : "15bdd34f-301a-00d7-802d-69a969000000", + "Body" : "ZmF1bHQ=", + "Content-Type" : "application/octet-stream", + "x-ms-version" : "2020-08-04", + "x-ms-file-permission-key" : "2559623233989293371*10026547158748585397", + "Date" : "Thu, 24 Jun 2021 19:19:13 GMT", + "Accept-Ranges" : "bytes", + "x-ms-server-encrypted" : "true", + "x-ms-type" : "File", + "x-ms-file-change-time" : "2021-06-24T19:19:12.4573506Z", + "x-ms-file-parent-id" : "0", + "x-ms-client-request-id" : "f8678f16-bc7a-4b47-8935-f5eee92b65e0", + "x-ms-file-last-write-time" : "2021-06-24T19:19:12.4573506Z" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.file.core.windows.net/46640b9946640b99558335126ab174aa329c42ad88/46640b9946640b99558808139c3701a132bf44129d", + "Headers" : { + "x-ms-version" : "2020-08-04", + "User-Agent" : "azsdk-java-azure-storage-file-share/12.11.0-beta.1 (11.0.7; Windows 10; 10.0)", + "x-ms-client-request-id" : "60da6018-b288-4108-b896-40b8e737c609" + }, + "Response" : { + "content-length" : "5", + "x-ms-lease-status" : "unlocked", + "x-ms-file-id" : "13835128424026341376", + "Server" : "Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0", + "x-ms-file-creation-time" : "2021-06-24T19:19:12.4573506Z", + "Content-Range" : "bytes 2-6/7", + "x-ms-lease-state" : "available", + "Last-Modified" : "Thu, 24 Jun 2021 19:19:12 GMT", + "retry-after" : "0", + "StatusCode" : "206", + "x-ms-file-attributes" : "Archive", + "eTag" : "0x8D93744F341CF2D", + "x-ms-request-id" : "15bdd350-301a-00d7-012d-69a969000000", + "Body" : "ZmF1bHQ=", + "Content-Type" : "application/octet-stream", + "x-ms-version" : "2020-08-04", + "x-ms-file-permission-key" : "2559623233989293371*10026547158748585397", + "Date" : "Thu, 24 Jun 2021 19:19:13 GMT", + "Accept-Ranges" : "bytes", + "x-ms-server-encrypted" : "true", + "x-ms-type" : "File", + "x-ms-file-change-time" : "2021-06-24T19:19:12.4573506Z", + "x-ms-file-parent-id" : "0", + "x-ms-client-request-id" : "60da6018-b288-4108-b896-40b8e737c609", + "x-ms-file-last-write-time" : "2021-06-24T19:19:12.4573506Z" + }, + "Exception" : null + } ], + "variables" : [ "46640b9946640b99558335126ab174aa329c42ad88", "46640b9946640b99558808139c3701a132bf44129d" ] +} \ No newline at end of file From 684844df9aae53f7d82708413aaf301418cd8d60 Mon Sep 17 00:00:00 2001 From: gapra Date: Fri, 25 Jun 2021 12:01:07 -0700 Subject: [PATCH 2/9] try to resolve test issue --- .../common/test/shared/policy/MockRetryRangeResponsePolicy.java | 2 +- .../java/com/azure/storage/file/share/FileAsyncAPITests.groovy | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/storage/azure-storage-common/src/test-shared/java/com/azure/storage/common/test/shared/policy/MockRetryRangeResponsePolicy.java b/sdk/storage/azure-storage-common/src/test-shared/java/com/azure/storage/common/test/shared/policy/MockRetryRangeResponsePolicy.java index 2d7e5a2213cfc..01f05c5ad5ed2 100644 --- a/sdk/storage/azure-storage-common/src/test-shared/java/com/azure/storage/common/test/shared/policy/MockRetryRangeResponsePolicy.java +++ b/sdk/storage/azure-storage-common/src/test-shared/java/com/azure/storage/common/test/shared/policy/MockRetryRangeResponsePolicy.java @@ -22,7 +22,7 @@ public MockRetryRangeResponsePolicy(String rangeMatch) { @Override public Mono process(HttpPipelineCallContext context, HttpPipelineNextPolicy next) { - return next.process().flatMap( response -> { + return next.process().flatMap(response -> { if (!response.getRequest().getHeaders().getValue("x-ms-range").equals(rangeMatch)) { return Mono.error(new IllegalArgumentException("The range header was not set correctly on retry.")); } else { diff --git a/sdk/storage/azure-storage-file-share/src/test/java/com/azure/storage/file/share/FileAsyncAPITests.groovy b/sdk/storage/azure-storage-file-share/src/test/java/com/azure/storage/file/share/FileAsyncAPITests.groovy index e0f812fb5e10f..6cbb4ad5b54a1 100644 --- a/sdk/storage/azure-storage-file-share/src/test/java/com/azure/storage/file/share/FileAsyncAPITests.groovy +++ b/sdk/storage/azure-storage-file-share/src/test/java/com/azure/storage/file/share/FileAsyncAPITests.groovy @@ -217,7 +217,7 @@ class FileAsyncAPITests extends APISpec { when: def uploadVerifier = StepVerifier.create(primaryFileAsyncClient.uploadWithResponse(data.defaultFlux, data.defaultDataSizeLong, 0L)) - def downloadVerifier = StepVerifier.create(primaryFileAsyncClient.downloadWithResponse(null, null)) + def downloadVerifier = StepVerifier.create(primaryFileAsyncClient.downloadWithResponse(null)) then: uploadVerifier.assertNext { From ec85a85c2b04d3746fb06ca4c112a3a20f4054b2 Mon Sep 17 00:00:00 2001 From: gapra Date: Tue, 29 Jun 2021 10:57:26 -0700 Subject: [PATCH 3/9] removed null check --- .../com/azure/storage/file/share/ShareFileAsyncClient.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/ShareFileAsyncClient.java b/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/ShareFileAsyncClient.java index 1dddf2f8e2891..359090413a926 100644 --- a/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/ShareFileAsyncClient.java +++ b/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/ShareFileAsyncClient.java @@ -909,8 +909,7 @@ Mono downloadWithResponse(ShareFileDownloadOptio new ShareFileRange(offset, range.getEnd()), getRangeContentMd5, requestConditions, context).flatMapMany(r -> { String receivedETag = ModelHelper.getETag(r.getHeaders()); - if ((eTag == null && receivedETag == null) - || (eTag != null && eTag.equals(receivedETag))) { + if (eTag != null && eTag.equals(receivedETag)) { return r.getValue().timeout(TIMEOUT_VALUE); } else { return Flux.error( From e78e23cc0d42ec01d1803583cd995607eaaf820b Mon Sep 17 00:00:00 2001 From: gapra Date: Tue, 29 Jun 2021 11:41:10 -0700 Subject: [PATCH 4/9] removed null check --- .../storage/file/share/implementation/util/ModelHelper.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/implementation/util/ModelHelper.java b/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/implementation/util/ModelHelper.java index c1f5a046d8449..37ccd4ee382a8 100644 --- a/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/implementation/util/ModelHelper.java +++ b/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/implementation/util/ModelHelper.java @@ -192,12 +192,9 @@ public static ShareFileDownloadHeaders transformFileDownloadHeaders(HttpHeaders } public static String getETag(HttpHeaders headers) { - if (headers == null) { - return null; - } return headers.getValue("ETag"); } - + public static ShareFileItemProperties transformFileProperty(FileProperty property) { if (property == null) { return null; From 8af9313d757487628c25657ecd5e10cb1a594330 Mon Sep 17 00:00:00 2001 From: gapra Date: Tue, 29 Jun 2021 13:37:14 -0700 Subject: [PATCH 5/9] file share exception annotation working --- .../models/CopyFileSmbInfo.java | 1 + .../share/models/ShareFileHttpHeaders.java | 1 + .../SourceModifiedAccessConditions.java | 1 + .../ShareStorageCustomization.java | 20 +++++++++---------- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/implementation/models/CopyFileSmbInfo.java b/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/implementation/models/CopyFileSmbInfo.java index 05ec8a65ba0fa..9e09cea0de92b 100644 --- a/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/implementation/models/CopyFileSmbInfo.java +++ b/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/implementation/models/CopyFileSmbInfo.java @@ -10,6 +10,7 @@ import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; /** Parameter group. */ +@JacksonXmlRootElement(localName = "CopyFileSmbInfo") @Fluent @JacksonXmlRootElement(localName = "copy-file-smb-info") public final class CopyFileSmbInfo { diff --git a/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/models/ShareFileHttpHeaders.java b/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/models/ShareFileHttpHeaders.java index b151fde5cd305..c8fdf0099f64a 100644 --- a/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/models/ShareFileHttpHeaders.java +++ b/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/models/ShareFileHttpHeaders.java @@ -10,6 +10,7 @@ import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; /** Parameter group. */ +@JacksonXmlRootElement(localName = "ShareFileHttpHeaders") @Fluent @JacksonXmlRootElement(localName = "share-file-http-headers") public final class ShareFileHttpHeaders { diff --git a/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/models/SourceModifiedAccessConditions.java b/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/models/SourceModifiedAccessConditions.java index f765020a2add6..1bcddfb17aa18 100644 --- a/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/models/SourceModifiedAccessConditions.java +++ b/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/models/SourceModifiedAccessConditions.java @@ -10,6 +10,7 @@ import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; /** Parameter group. */ +@JacksonXmlRootElement(localName = "SourceModifiedAccessConditions") @Fluent @JacksonXmlRootElement(localName = "source-modified-access-conditions") public final class SourceModifiedAccessConditions { diff --git a/sdk/storage/azure-storage-file-share/swagger/src/main/java/com/azure/storage/file/share/customization/ShareStorageCustomization.java b/sdk/storage/azure-storage-file-share/swagger/src/main/java/com/azure/storage/file/share/customization/ShareStorageCustomization.java index 65cc8d7a5251f..b0f6b773ea609 100644 --- a/sdk/storage/azure-storage-file-share/swagger/src/main/java/com/azure/storage/file/share/customization/ShareStorageCustomization.java +++ b/sdk/storage/azure-storage-file-share/swagger/src/main/java/com/azure/storage/file/share/customization/ShareStorageCustomization.java @@ -85,26 +85,26 @@ public void customize(LibraryCustomization customization, Logger logger) { // Replace JacksonXmlRootElement annotations that are causing a semantic breaking change. ClassCustomization shareFileHttpHeaders = models.getClass("ShareFileHttpHeaders"); - shareFileHttpHeaders.removeAnnotation("@JacksonXmlRootElement(localName = \"ShareFileHttpHeaders\")"); - shareFileHttpHeaders.addAnnotation("@JacksonXmlRootElement(localName = \"share-file-http-headers\")"); + shareFileHttpHeaders.removeAnnotation("@JacksonXmlRootElement(localName = \"ShareFileHttpHeaders\")") + .addAnnotation("@JacksonXmlRootElement(localName = \"share-file-http-headers\")"); ClassCustomization sourceModifiedAccessConditions = models.getClass("SourceModifiedAccessConditions"); - sourceModifiedAccessConditions.removeAnnotation("@JacksonXmlRootElement(localName = \"SourceModifiedAccessConditions\")"); - sourceModifiedAccessConditions.addAnnotation("@JacksonXmlRootElement(localName = \"source-modified-access-conditions\")"); + sourceModifiedAccessConditions.removeAnnotation("@JacksonXmlRootElement(localName = \"SourceModifiedAccessConditions\")") + .addAnnotation("@JacksonXmlRootElement(localName = \"source-modified-access-conditions\")"); // Update incorrect JsonProperty of Metrics ClassCustomization shareServiceProperties = models.getClass("ShareServiceProperties"); PropertyCustomization hourMetrics = shareServiceProperties.getProperty("hourMetrics"); - hourMetrics.removeAnnotation("@JsonProperty(value = \"Metrics\")"); - hourMetrics.addAnnotation("@JsonProperty(value = \"HourMetrics\")"); + hourMetrics.removeAnnotation("@JsonProperty(value = \"Metrics\")") + .addAnnotation("@JsonProperty(value = \"HourMetrics\")"); PropertyCustomization minuteMetrics = shareServiceProperties.getProperty("minuteMetrics"); - minuteMetrics.removeAnnotation("@JsonProperty(value = \"Metrics\")"); - minuteMetrics.addAnnotation("@JsonProperty(value = \"MinuteMetrics\")"); + minuteMetrics.removeAnnotation("@JsonProperty(value = \"Metrics\")") + .addAnnotation("@JsonProperty(value = \"MinuteMetrics\")"); } private void modifyUnexpectedResponseExceptionType(MethodCustomization method) { - method.removeAnnotation("@UnexpectedResponseExceptionType(StorageErrorException.class)"); - method.addAnnotation("@UnexpectedResponseExceptionType(com.azure.storage.file.share.models.ShareStorageException.class)"); + method.removeAnnotation("@UnexpectedResponseExceptionType(StorageErrorException.class)") + .addAnnotation("@UnexpectedResponseExceptionType(com.azure.storage.file.share.models.ShareStorageException.class)"); } } From 1a891f1396e515ceacdba8ddd694959bac2c3783 Mon Sep 17 00:00:00 2001 From: gapra Date: Tue, 29 Jun 2021 13:52:06 -0700 Subject: [PATCH 6/9] Changes for new swagger/autorest --- .../file/share/implementation/models/CopyFileSmbInfo.java | 1 - .../storage/file/share/models/ShareFileHttpHeaders.java | 1 - .../file/share/models/SourceModifiedAccessConditions.java | 1 - .../file/share/customization/ShareStorageCustomization.java | 6 +++--- 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/implementation/models/CopyFileSmbInfo.java b/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/implementation/models/CopyFileSmbInfo.java index 9e09cea0de92b..05ec8a65ba0fa 100644 --- a/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/implementation/models/CopyFileSmbInfo.java +++ b/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/implementation/models/CopyFileSmbInfo.java @@ -10,7 +10,6 @@ import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; /** Parameter group. */ -@JacksonXmlRootElement(localName = "CopyFileSmbInfo") @Fluent @JacksonXmlRootElement(localName = "copy-file-smb-info") public final class CopyFileSmbInfo { diff --git a/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/models/ShareFileHttpHeaders.java b/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/models/ShareFileHttpHeaders.java index c8fdf0099f64a..b151fde5cd305 100644 --- a/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/models/ShareFileHttpHeaders.java +++ b/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/models/ShareFileHttpHeaders.java @@ -10,7 +10,6 @@ import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; /** Parameter group. */ -@JacksonXmlRootElement(localName = "ShareFileHttpHeaders") @Fluent @JacksonXmlRootElement(localName = "share-file-http-headers") public final class ShareFileHttpHeaders { diff --git a/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/models/SourceModifiedAccessConditions.java b/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/models/SourceModifiedAccessConditions.java index 1bcddfb17aa18..f765020a2add6 100644 --- a/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/models/SourceModifiedAccessConditions.java +++ b/sdk/storage/azure-storage-file-share/src/main/java/com/azure/storage/file/share/models/SourceModifiedAccessConditions.java @@ -10,7 +10,6 @@ import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; /** Parameter group. */ -@JacksonXmlRootElement(localName = "SourceModifiedAccessConditions") @Fluent @JacksonXmlRootElement(localName = "source-modified-access-conditions") public final class SourceModifiedAccessConditions { diff --git a/sdk/storage/azure-storage-file-share/swagger/src/main/java/com/azure/storage/file/share/customization/ShareStorageCustomization.java b/sdk/storage/azure-storage-file-share/swagger/src/main/java/com/azure/storage/file/share/customization/ShareStorageCustomization.java index b0f6b773ea609..1b2067eb26e66 100644 --- a/sdk/storage/azure-storage-file-share/swagger/src/main/java/com/azure/storage/file/share/customization/ShareStorageCustomization.java +++ b/sdk/storage/azure-storage-file-share/swagger/src/main/java/com/azure/storage/file/share/customization/ShareStorageCustomization.java @@ -77,7 +77,7 @@ public void customize(LibraryCustomization customization, Logger logger) { PackageCustomization implementationModels = customization.getPackage("com.azure.storage.file.share.implementation.models"); implementationModels.getClass("FilesAndDirectoriesListSegment").addAnnotation("@JsonDeserialize(using = com.azure.storage.file.share.implementation.util.FilesAndDirectoriesListSegmentDeserializer.class)"); implementationModels.getClass("CopyFileSmbInfo") - .removeAnnotation("@JacksonXmlRootElement(localName = \"CopyFileSmbInfo\")") + .removeAnnotation("@JacksonXmlRootElement\\(localName = \"CopyFileSmbInfo\"\\)") .addAnnotation("@JacksonXmlRootElement(localName = \"copy-file-smb-info\")"); PackageCustomization models = customization.getPackage("com.azure.storage.file.share.models"); @@ -85,11 +85,11 @@ public void customize(LibraryCustomization customization, Logger logger) { // Replace JacksonXmlRootElement annotations that are causing a semantic breaking change. ClassCustomization shareFileHttpHeaders = models.getClass("ShareFileHttpHeaders"); - shareFileHttpHeaders.removeAnnotation("@JacksonXmlRootElement(localName = \"ShareFileHttpHeaders\")") + shareFileHttpHeaders.removeAnnotation("@JacksonXmlRootElement\\(localName = \"ShareFileHttpHeaders\"\\)") .addAnnotation("@JacksonXmlRootElement(localName = \"share-file-http-headers\")"); ClassCustomization sourceModifiedAccessConditions = models.getClass("SourceModifiedAccessConditions"); - sourceModifiedAccessConditions.removeAnnotation("@JacksonXmlRootElement(localName = \"SourceModifiedAccessConditions\")") + sourceModifiedAccessConditions.removeAnnotation("@JacksonXmlRootElement\\(localName = \"SourceModifiedAccessConditions\"\\)") .addAnnotation("@JacksonXmlRootElement(localName = \"source-modified-access-conditions\")"); // Update incorrect JsonProperty of Metrics From 700b961fb646b2c5246181981fd31b7e1b91b4c1 Mon Sep 17 00:00:00 2001 From: gapra Date: Tue, 29 Jun 2021 13:53:48 -0700 Subject: [PATCH 7/9] Revert "file share exception annotation working" This reverts commit 8af9313d757487628c25657ecd5e10cb1a594330. --- .../ShareStorageCustomization.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/sdk/storage/azure-storage-file-share/swagger/src/main/java/com/azure/storage/file/share/customization/ShareStorageCustomization.java b/sdk/storage/azure-storage-file-share/swagger/src/main/java/com/azure/storage/file/share/customization/ShareStorageCustomization.java index 1b2067eb26e66..9b225f39d0b5e 100644 --- a/sdk/storage/azure-storage-file-share/swagger/src/main/java/com/azure/storage/file/share/customization/ShareStorageCustomization.java +++ b/sdk/storage/azure-storage-file-share/swagger/src/main/java/com/azure/storage/file/share/customization/ShareStorageCustomization.java @@ -85,26 +85,27 @@ public void customize(LibraryCustomization customization, Logger logger) { // Replace JacksonXmlRootElement annotations that are causing a semantic breaking change. ClassCustomization shareFileHttpHeaders = models.getClass("ShareFileHttpHeaders"); - shareFileHttpHeaders.removeAnnotation("@JacksonXmlRootElement\\(localName = \"ShareFileHttpHeaders\"\\)") - .addAnnotation("@JacksonXmlRootElement(localName = \"share-file-http-headers\")"); + + shareFileHttpHeaders.removeAnnotation("@JacksonXmlRootElement(localName = \"ShareFileHttpHeaders\")"); + shareFileHttpHeaders.addAnnotation("@JacksonXmlRootElement(localName = \"share-file-http-headers\")"); ClassCustomization sourceModifiedAccessConditions = models.getClass("SourceModifiedAccessConditions"); - sourceModifiedAccessConditions.removeAnnotation("@JacksonXmlRootElement\\(localName = \"SourceModifiedAccessConditions\"\\)") - .addAnnotation("@JacksonXmlRootElement(localName = \"source-modified-access-conditions\")"); + sourceModifiedAccessConditions.removeAnnotation("@JacksonXmlRootElement(localName = \"SourceModifiedAccessConditions\")"); + sourceModifiedAccessConditions.addAnnotation("@JacksonXmlRootElement(localName = \"source-modified-access-conditions\")"); // Update incorrect JsonProperty of Metrics ClassCustomization shareServiceProperties = models.getClass("ShareServiceProperties"); PropertyCustomization hourMetrics = shareServiceProperties.getProperty("hourMetrics"); - hourMetrics.removeAnnotation("@JsonProperty(value = \"Metrics\")") - .addAnnotation("@JsonProperty(value = \"HourMetrics\")"); + hourMetrics.removeAnnotation("@JsonProperty(value = \"Metrics\")"); + hourMetrics.addAnnotation("@JsonProperty(value = \"HourMetrics\")"); PropertyCustomization minuteMetrics = shareServiceProperties.getProperty("minuteMetrics"); - minuteMetrics.removeAnnotation("@JsonProperty(value = \"Metrics\")") - .addAnnotation("@JsonProperty(value = \"MinuteMetrics\")"); + minuteMetrics.removeAnnotation("@JsonProperty(value = \"Metrics\")"); + minuteMetrics.addAnnotation("@JsonProperty(value = \"MinuteMetrics\")"); } private void modifyUnexpectedResponseExceptionType(MethodCustomization method) { - method.removeAnnotation("@UnexpectedResponseExceptionType(StorageErrorException.class)") - .addAnnotation("@UnexpectedResponseExceptionType(com.azure.storage.file.share.models.ShareStorageException.class)"); + method.removeAnnotation("@UnexpectedResponseExceptionType(StorageErrorException.class)"); + method.addAnnotation("@UnexpectedResponseExceptionType(com.azure.storage.file.share.models.ShareStorageException.class)"); } } From 41c328ba9ad5d160bcb52c8eeaf2c32ec005bb9f Mon Sep 17 00:00:00 2001 From: gapra Date: Tue, 29 Jun 2021 17:17:23 -0700 Subject: [PATCH 8/9] undo share customization change --- .../file/share/customization/ShareStorageCustomization.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sdk/storage/azure-storage-file-share/swagger/src/main/java/com/azure/storage/file/share/customization/ShareStorageCustomization.java b/sdk/storage/azure-storage-file-share/swagger/src/main/java/com/azure/storage/file/share/customization/ShareStorageCustomization.java index 9b225f39d0b5e..65cc8d7a5251f 100644 --- a/sdk/storage/azure-storage-file-share/swagger/src/main/java/com/azure/storage/file/share/customization/ShareStorageCustomization.java +++ b/sdk/storage/azure-storage-file-share/swagger/src/main/java/com/azure/storage/file/share/customization/ShareStorageCustomization.java @@ -77,7 +77,7 @@ public void customize(LibraryCustomization customization, Logger logger) { PackageCustomization implementationModels = customization.getPackage("com.azure.storage.file.share.implementation.models"); implementationModels.getClass("FilesAndDirectoriesListSegment").addAnnotation("@JsonDeserialize(using = com.azure.storage.file.share.implementation.util.FilesAndDirectoriesListSegmentDeserializer.class)"); implementationModels.getClass("CopyFileSmbInfo") - .removeAnnotation("@JacksonXmlRootElement\\(localName = \"CopyFileSmbInfo\"\\)") + .removeAnnotation("@JacksonXmlRootElement(localName = \"CopyFileSmbInfo\")") .addAnnotation("@JacksonXmlRootElement(localName = \"copy-file-smb-info\")"); PackageCustomization models = customization.getPackage("com.azure.storage.file.share.models"); @@ -85,7 +85,6 @@ public void customize(LibraryCustomization customization, Logger logger) { // Replace JacksonXmlRootElement annotations that are causing a semantic breaking change. ClassCustomization shareFileHttpHeaders = models.getClass("ShareFileHttpHeaders"); - shareFileHttpHeaders.removeAnnotation("@JacksonXmlRootElement(localName = \"ShareFileHttpHeaders\")"); shareFileHttpHeaders.addAnnotation("@JacksonXmlRootElement(localName = \"share-file-http-headers\")"); From 341bd4865c97e66bc1ee488db92aa233782d4862 Mon Sep 17 00:00:00 2001 From: gapra Date: Wed, 30 Jun 2021 17:33:44 -0700 Subject: [PATCH 9/9] file tests --- .../java/com/azure/storage/file/share/FileAPITests.groovy | 6 +++--- .../com/azure/storage/file/share/FileAsyncAPITests.groovy | 2 +- .../com/azure/storage/file/share/FileTestHelper.groovy | 8 ++++++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/sdk/storage/azure-storage-file-share/src/test/java/com/azure/storage/file/share/FileAPITests.groovy b/sdk/storage/azure-storage-file-share/src/test/java/com/azure/storage/file/share/FileAPITests.groovy index e61f07c6bf98e..29736378dda96 100644 --- a/sdk/storage/azure-storage-file-share/src/test/java/com/azure/storage/file/share/FileAPITests.groovy +++ b/sdk/storage/azure-storage-file-share/src/test/java/com/azure/storage/file/share/FileAPITests.groovy @@ -229,7 +229,7 @@ class FileAPITests extends APISpec { then: assertResponseStatusCode(uploadResponse, 201) - assertResponseStatusCode(downloadResponse, 200) + assertResponseStatusCode(downloadResponse, 200, 206) headers.getContentLength() == data.defaultDataSizeLong headers.getETag() headers.getLastModified() @@ -274,7 +274,7 @@ class FileAPITests extends APISpec { then: assertResponseStatusCode(uploadResponse, 201) - assertResponseStatusCode(downloadResponse, 200) + assertResponseStatusCode(downloadResponse, 200, 206) headers.getContentLength() == data.defaultDataSizeLong headers.getETag() headers.getLastModified() @@ -366,7 +366,7 @@ class FileAPITests extends APISpec { then: assertResponseStatusCode(uploadResponse, 201) - assertResponseStatusCode(downloadResponse, 200) + assertResponseStatusCode(downloadResponse, 200, 206) headers.getContentLength() == data.defaultDataSizeLong headers.getETag() headers.getLastModified() diff --git a/sdk/storage/azure-storage-file-share/src/test/java/com/azure/storage/file/share/FileAsyncAPITests.groovy b/sdk/storage/azure-storage-file-share/src/test/java/com/azure/storage/file/share/FileAsyncAPITests.groovy index 6cbb4ad5b54a1..133497a46ff33 100644 --- a/sdk/storage/azure-storage-file-share/src/test/java/com/azure/storage/file/share/FileAsyncAPITests.groovy +++ b/sdk/storage/azure-storage-file-share/src/test/java/com/azure/storage/file/share/FileAsyncAPITests.groovy @@ -225,7 +225,7 @@ class FileAsyncAPITests extends APISpec { }.verifyComplete() downloadVerifier.assertNext({ response -> - assert assertResponseStatusCode(response, 200) + assert assertResponseStatusCode(response, 200, 206) def headers = response.getDeserializedHeaders() assert headers.getContentLength() == data.defaultDataSizeLong assert headers.getETag() diff --git a/sdk/storage/azure-storage-file-share/src/test/java/com/azure/storage/file/share/FileTestHelper.groovy b/sdk/storage/azure-storage-file-share/src/test/java/com/azure/storage/file/share/FileTestHelper.groovy index 1f10a239dbc43..6ab3305488ed4 100644 --- a/sdk/storage/azure-storage-file-share/src/test/java/com/azure/storage/file/share/FileTestHelper.groovy +++ b/sdk/storage/azure-storage-file-share/src/test/java/com/azure/storage/file/share/FileTestHelper.groovy @@ -25,8 +25,12 @@ import java.nio.file.Paths class FileTestHelper { private static final ClientLogger logger = new ClientLogger(FileTestHelper.class) - static boolean assertResponseStatusCode(Response response, int expectedStatusCode) { - return expectedStatusCode == response.getStatusCode() + static boolean assertResponseStatusCode(Response response, int... expectedStatusCode) { + boolean result = false + for (int statusCode : expectedStatusCode) { + result |= statusCode == response.getStatusCode() + } + return result } static boolean assertExceptionStatusCodeAndMessage(T throwable, int expectedStatusCode, ShareErrorCode errMessage) {