diff --git a/sdk/storage/Azure.Storage.Blobs/CHANGELOG.md b/sdk/storage/Azure.Storage.Blobs/CHANGELOG.md index 532241965392e..c726c4f2f3e1c 100644 --- a/sdk/storage/Azure.Storage.Blobs/CHANGELOG.md +++ b/sdk/storage/Azure.Storage.Blobs/CHANGELOG.md @@ -2,6 +2,7 @@ ## 12.7.0-preview.1 (Unreleased) - Fixed bug where Stream returned from AppendBlobClient.OpenWrite(), BlockBlobClient.OpenWrite() and PageBlobClient.OpenWrite() did not flush while disposing preventing compatibility with using keyword. +- Fixed bug where Listing Blobs with BlobTraits.Metadata would return BlobItems with null metadata instead of an empty dictionary if no metadata was present. ## 12.6.0 (2020-08-31) - Fixed bug where BlobClient.Upload(), BlockBlobClient.Upload(), AppendBlobClient.AppendBlock(), and PageBlobClient.UploadPages() would deadlock if the content stream's position was not 0. diff --git a/sdk/storage/Azure.Storage.Blobs/src/BlobExtensions.cs b/sdk/storage/Azure.Storage.Blobs/src/BlobExtensions.cs index e932e2badc3a2..732f2f2f8e336 100644 --- a/sdk/storage/Azure.Storage.Blobs/src/BlobExtensions.cs +++ b/sdk/storage/Azure.Storage.Blobs/src/BlobExtensions.cs @@ -59,7 +59,7 @@ internal static BlobItem ToBlobItem(this BlobItemInternal blobItemInternal) IsLatestVersion = blobItemInternal.IsCurrentVersion, Metadata = blobItemInternal.Metadata?.Count > 0 ? blobItemInternal.Metadata - : null, + : new Dictionary(), Tags = blobItemInternal.BlobTags.ToTagDictionary(), ObjectReplicationSourceProperties = blobItemInternal.ObjectReplicationMetadata?.Count > 0 ? ParseObjectReplicationMetadata(blobItemInternal.ObjectReplicationMetadata) diff --git a/sdk/storage/Azure.Storage.Blobs/tests/ContainerClientTests.cs b/sdk/storage/Azure.Storage.Blobs/tests/ContainerClientTests.cs index 83a2e80f37ab1..fcc6bf86ef182 100644 --- a/sdk/storage/Azure.Storage.Blobs/tests/ContainerClientTests.cs +++ b/sdk/storage/Azure.Storage.Blobs/tests/ContainerClientTests.cs @@ -1779,7 +1779,7 @@ public async Task ListBlobsFlatSegmentAsync_MaxResults() // Assert Assert.AreEqual(2, page.Values.Count); - Assert.IsTrue(page.Values.All(b => b.Metadata == null)); + Assert.IsTrue(page.Values.All(b => b.Metadata.Count == 0)); } [Test] @@ -2107,6 +2107,23 @@ public async Task ListBlobsHierarchySegmentAsync_Metadata() AssertDictionaryEquality(metadata, item.Blob.Metadata); } + [Test] + public async Task ListBlobsHierarchySegmentAsync_Metadata_NoMetadata() + { + await using DisposingContainer test = await GetTestContainerAsync(); + + // Arrange + AppendBlobClient blob = InstrumentClient(test.Container.GetAppendBlobClient(GetNewBlobName())); + await blob.CreateAsync(); + + // Act + BlobHierarchyItem item = await test.Container.GetBlobsByHierarchyAsync(traits: BlobTraits.Metadata).FirstAsync(); + + // Assert + Assert.IsNotNull(item.Blob.Metadata); + Assert.AreEqual(0, item.Blob.Metadata.Count); + } + [Test] [ServiceVersion(Min = BlobClientOptions.ServiceVersion.V2019_07_07)] public async Task ListBlobsHierarchySegmentAsync_EncryptionScope() diff --git a/sdk/storage/Azure.Storage.Blobs/tests/SessionRecords/ContainerClientTests/ListBlobsHierarchySegmentAsync_Metadata_NoMetadata.json b/sdk/storage/Azure.Storage.Blobs/tests/SessionRecords/ContainerClientTests/ListBlobsHierarchySegmentAsync_Metadata_NoMetadata.json new file mode 100644 index 0000000000000..cd504128759a8 --- /dev/null +++ b/sdk/storage/Azure.Storage.Blobs/tests/SessionRecords/ContainerClientTests/ListBlobsHierarchySegmentAsync_Metadata_NoMetadata.json @@ -0,0 +1,136 @@ +{ + "Entries": [ + { + "RequestUri": "https://seanmcccanary3.blob.core.windows.net/test-container-d3fdff83-742a-3e2d-b67c-ca7fca1ced30?restype=container", + "RequestMethod": "PUT", + "RequestHeaders": { + "Authorization": "Sanitized", + "traceparent": "00-893f223fa655de46b4cab0db4f2d54fd-46d2e2b0e816f14d-00", + "User-Agent": [ + "azsdk-net-Storage.Blobs/12.7.0-alpha.20200903.1", + "(.NET Core 4.6.29017.01; Microsoft Windows 10.0.18362 )" + ], + "x-ms-blob-public-access": "container", + "x-ms-client-request-id": "faace94a-5f4f-7da6-76bb-9574690403c7", + "x-ms-date": "Thu, 03 Sep 2020 19:23:15 GMT", + "x-ms-return-client-request-id": "true", + "x-ms-version": "2019-12-12" + }, + "RequestBody": null, + "StatusCode": 201, + "ResponseHeaders": { + "Content-Length": "0", + "Date": "Thu, 03 Sep 2020 19:23:14 GMT", + "ETag": "\u00220x8D8503ECE49C8B4\u0022", + "Last-Modified": "Thu, 03 Sep 2020 19:23:15 GMT", + "Server": [ + "Windows-Azure-Blob/1.0", + "Microsoft-HTTPAPI/2.0" + ], + "x-ms-client-request-id": "faace94a-5f4f-7da6-76bb-9574690403c7", + "x-ms-request-id": "249c96d3-f01e-001f-6927-8269c6000000", + "x-ms-version": "2019-12-12" + }, + "ResponseBody": [] + }, + { + "RequestUri": "https://seanmcccanary3.blob.core.windows.net/test-container-d3fdff83-742a-3e2d-b67c-ca7fca1ced30/test-blob-05019481-0918-207d-ca32-e0468396ee1e", + "RequestMethod": "PUT", + "RequestHeaders": { + "Authorization": "Sanitized", + "Content-Length": "0", + "traceparent": "00-234d708028c01d418b28d2fe0c4d8df7-34fbce4b64654143-00", + "User-Agent": [ + "azsdk-net-Storage.Blobs/12.7.0-alpha.20200903.1", + "(.NET Core 4.6.29017.01; Microsoft Windows 10.0.18362 )" + ], + "x-ms-blob-type": "AppendBlob", + "x-ms-client-request-id": "bb1529e0-b097-415f-6c8b-2f1c7f5ffae0", + "x-ms-date": "Thu, 03 Sep 2020 19:23:16 GMT", + "x-ms-return-client-request-id": "true", + "x-ms-version": "2019-12-12" + }, + "RequestBody": null, + "StatusCode": 201, + "ResponseHeaders": { + "Content-Length": "0", + "Date": "Thu, 03 Sep 2020 19:23:14 GMT", + "ETag": "\u00220x8D8503ECE5A3C31\u0022", + "Last-Modified": "Thu, 03 Sep 2020 19:23:15 GMT", + "Server": [ + "Windows-Azure-Blob/1.0", + "Microsoft-HTTPAPI/2.0" + ], + "x-ms-client-request-id": "bb1529e0-b097-415f-6c8b-2f1c7f5ffae0", + "x-ms-request-id": "249c96ee-f01e-001f-7c27-8269c6000000", + "x-ms-request-server-encrypted": "true", + "x-ms-version": "2019-12-12" + }, + "ResponseBody": [] + }, + { + "RequestUri": "https://seanmcccanary3.blob.core.windows.net/test-container-d3fdff83-742a-3e2d-b67c-ca7fca1ced30?restype=container\u0026comp=list\u0026include=metadata", + "RequestMethod": "GET", + "RequestHeaders": { + "Authorization": "Sanitized", + "User-Agent": [ + "azsdk-net-Storage.Blobs/12.7.0-alpha.20200903.1", + "(.NET Core 4.6.29017.01; Microsoft Windows 10.0.18362 )" + ], + "x-ms-client-request-id": "5965f1d0-3281-1686-f2f3-74e4c3c4f6f5", + "x-ms-date": "Thu, 03 Sep 2020 19:23:16 GMT", + "x-ms-return-client-request-id": "true", + "x-ms-version": "2019-12-12" + }, + "RequestBody": null, + "StatusCode": 200, + "ResponseHeaders": { + "Content-Length": "854", + "Content-Type": "application/xml", + "Date": "Thu, 03 Sep 2020 19:23:14 GMT", + "Server": [ + "Windows-Azure-Blob/1.0", + "Microsoft-HTTPAPI/2.0" + ], + "x-ms-client-request-id": "5965f1d0-3281-1686-f2f3-74e4c3c4f6f5", + "x-ms-request-id": "249c96fc-f01e-001f-0727-8269c6000000", + "x-ms-version": "2019-12-12" + }, + "ResponseBody": "\uFEFF\u003C?xml version=\u00221.0\u0022 encoding=\u0022utf-8\u0022?\u003E\u003CEnumerationResults ServiceEndpoint=\u0022https://seanmcccanary3.blob.core.windows.net/\u0022 ContainerName=\u0022test-container-d3fdff83-742a-3e2d-b67c-ca7fca1ced30\u0022\u003E\u003CBlobs\u003E\u003CBlob\u003E\u003CName\u003Etest-blob-05019481-0918-207d-ca32-e0468396ee1e\u003C/Name\u003E\u003CProperties\u003E\u003CCreation-Time\u003EThu, 03 Sep 2020 19:23:15 GMT\u003C/Creation-Time\u003E\u003CLast-Modified\u003EThu, 03 Sep 2020 19:23:15 GMT\u003C/Last-Modified\u003E\u003CEtag\u003E0x8D8503ECE5A3C31\u003C/Etag\u003E\u003CContent-Length\u003E0\u003C/Content-Length\u003E\u003CContent-Type\u003Eapplication/octet-stream\u003C/Content-Type\u003E\u003CContent-Encoding /\u003E\u003CContent-Language /\u003E\u003CContent-CRC64 /\u003E\u003CContent-MD5 /\u003E\u003CCache-Control /\u003E\u003CContent-Disposition /\u003E\u003CBlobType\u003EAppendBlob\u003C/BlobType\u003E\u003CLeaseStatus\u003Eunlocked\u003C/LeaseStatus\u003E\u003CLeaseState\u003Eavailable\u003C/LeaseState\u003E\u003CServerEncrypted\u003Etrue\u003C/ServerEncrypted\u003E\u003C/Properties\u003E\u003CMetadata /\u003E\u003COrMetadata /\u003E\u003C/Blob\u003E\u003C/Blobs\u003E\u003CNextMarker /\u003E\u003C/EnumerationResults\u003E" + }, + { + "RequestUri": "https://seanmcccanary3.blob.core.windows.net/test-container-d3fdff83-742a-3e2d-b67c-ca7fca1ced30?restype=container", + "RequestMethod": "DELETE", + "RequestHeaders": { + "Authorization": "Sanitized", + "traceparent": "00-e3e2b2b1257a024ea90ea6f591949045-b79d1f11eba4ed4d-00", + "User-Agent": [ + "azsdk-net-Storage.Blobs/12.7.0-alpha.20200903.1", + "(.NET Core 4.6.29017.01; Microsoft Windows 10.0.18362 )" + ], + "x-ms-client-request-id": "8d4c2438-a0fa-9b5e-f096-25dcae73ccee", + "x-ms-date": "Thu, 03 Sep 2020 19:23:16 GMT", + "x-ms-return-client-request-id": "true", + "x-ms-version": "2019-12-12" + }, + "RequestBody": null, + "StatusCode": 202, + "ResponseHeaders": { + "Content-Length": "0", + "Date": "Thu, 03 Sep 2020 19:23:14 GMT", + "Server": [ + "Windows-Azure-Blob/1.0", + "Microsoft-HTTPAPI/2.0" + ], + "x-ms-client-request-id": "8d4c2438-a0fa-9b5e-f096-25dcae73ccee", + "x-ms-request-id": "249c9707-f01e-001f-0e27-8269c6000000", + "x-ms-version": "2019-12-12" + }, + "ResponseBody": [] + } + ], + "Variables": { + "RandomSeed": "1207041412", + "Storage_TestConfigDefault": "ProductionTenant\nseanmcccanary3\nU2FuaXRpemVk\nhttps://seanmcccanary3.blob.core.windows.net\nhttps://seanmcccanary3.file.core.windows.net\nhttps://seanmcccanary3.queue.core.windows.net\nhttps://seanmcccanary3.table.core.windows.net\n\n\n\n\nhttps://seanmcccanary3-secondary.blob.core.windows.net\nhttps://seanmcccanary3-secondary.file.core.windows.net\nhttps://seanmcccanary3-secondary.queue.core.windows.net\nhttps://seanmcccanary3-secondary.table.core.windows.net\n\nSanitized\n\n\nCloud\nBlobEndpoint=https://seanmcccanary3.blob.core.windows.net/;QueueEndpoint=https://seanmcccanary3.queue.core.windows.net/;FileEndpoint=https://seanmcccanary3.file.core.windows.net/;BlobSecondaryEndpoint=https://seanmcccanary3-secondary.blob.core.windows.net/;QueueSecondaryEndpoint=https://seanmcccanary3-secondary.queue.core.windows.net/;FileSecondaryEndpoint=https://seanmcccanary3-secondary.file.core.windows.net/;AccountName=seanmcccanary3;AccountKey=Kg==;\nseanscope1" + } +} \ No newline at end of file diff --git a/sdk/storage/Azure.Storage.Blobs/tests/SessionRecords/ContainerClientTests/ListBlobsHierarchySegmentAsync_Metadata_NoMetadataAsync.json b/sdk/storage/Azure.Storage.Blobs/tests/SessionRecords/ContainerClientTests/ListBlobsHierarchySegmentAsync_Metadata_NoMetadataAsync.json new file mode 100644 index 0000000000000..9e135e6ad4a94 --- /dev/null +++ b/sdk/storage/Azure.Storage.Blobs/tests/SessionRecords/ContainerClientTests/ListBlobsHierarchySegmentAsync_Metadata_NoMetadataAsync.json @@ -0,0 +1,136 @@ +{ + "Entries": [ + { + "RequestUri": "https://seanmcccanary3.blob.core.windows.net/test-container-fac230ef-737b-66a8-a34a-3cc30767c245?restype=container", + "RequestMethod": "PUT", + "RequestHeaders": { + "Authorization": "Sanitized", + "traceparent": "00-a1971a3552335c4c8b67c31e9d959f7a-5e8a4dc3197a444e-00", + "User-Agent": [ + "azsdk-net-Storage.Blobs/12.7.0-alpha.20200903.1", + "(.NET Core 4.6.29017.01; Microsoft Windows 10.0.18362 )" + ], + "x-ms-blob-public-access": "container", + "x-ms-client-request-id": "85226dd3-fb29-0663-8a17-31e3202fb396", + "x-ms-date": "Thu, 03 Sep 2020 19:23:16 GMT", + "x-ms-return-client-request-id": "true", + "x-ms-version": "2019-12-12" + }, + "RequestBody": null, + "StatusCode": 201, + "ResponseHeaders": { + "Content-Length": "0", + "Date": "Thu, 03 Sep 2020 19:23:15 GMT", + "ETag": "\u00220x8D8503ECEAB0742\u0022", + "Last-Modified": "Thu, 03 Sep 2020 19:23:15 GMT", + "Server": [ + "Windows-Azure-Blob/1.0", + "Microsoft-HTTPAPI/2.0" + ], + "x-ms-client-request-id": "85226dd3-fb29-0663-8a17-31e3202fb396", + "x-ms-request-id": "d77524e3-901e-0036-1327-8257b2000000", + "x-ms-version": "2019-12-12" + }, + "ResponseBody": [] + }, + { + "RequestUri": "https://seanmcccanary3.blob.core.windows.net/test-container-fac230ef-737b-66a8-a34a-3cc30767c245/test-blob-27032c7b-0af4-c303-96fa-dce3ef67de69", + "RequestMethod": "PUT", + "RequestHeaders": { + "Authorization": "Sanitized", + "Content-Length": "0", + "traceparent": "00-4d5ecdece332ca44bcf8cae64a95beeb-6dd752cb7db9f54e-00", + "User-Agent": [ + "azsdk-net-Storage.Blobs/12.7.0-alpha.20200903.1", + "(.NET Core 4.6.29017.01; Microsoft Windows 10.0.18362 )" + ], + "x-ms-blob-type": "AppendBlob", + "x-ms-client-request-id": "5ac5ece5-3c35-c9cd-6a5e-ee2f1f801622", + "x-ms-date": "Thu, 03 Sep 2020 19:23:17 GMT", + "x-ms-return-client-request-id": "true", + "x-ms-version": "2019-12-12" + }, + "RequestBody": null, + "StatusCode": 201, + "ResponseHeaders": { + "Content-Length": "0", + "Date": "Thu, 03 Sep 2020 19:23:15 GMT", + "ETag": "\u00220x8D8503ECEB368EC\u0022", + "Last-Modified": "Thu, 03 Sep 2020 19:23:15 GMT", + "Server": [ + "Windows-Azure-Blob/1.0", + "Microsoft-HTTPAPI/2.0" + ], + "x-ms-client-request-id": "5ac5ece5-3c35-c9cd-6a5e-ee2f1f801622", + "x-ms-request-id": "d77524ec-901e-0036-1927-8257b2000000", + "x-ms-request-server-encrypted": "true", + "x-ms-version": "2019-12-12" + }, + "ResponseBody": [] + }, + { + "RequestUri": "https://seanmcccanary3.blob.core.windows.net/test-container-fac230ef-737b-66a8-a34a-3cc30767c245?restype=container\u0026comp=list\u0026include=metadata", + "RequestMethod": "GET", + "RequestHeaders": { + "Authorization": "Sanitized", + "User-Agent": [ + "azsdk-net-Storage.Blobs/12.7.0-alpha.20200903.1", + "(.NET Core 4.6.29017.01; Microsoft Windows 10.0.18362 )" + ], + "x-ms-client-request-id": "03feed53-84a2-a834-ad26-2fe54fecc9a1", + "x-ms-date": "Thu, 03 Sep 2020 19:23:17 GMT", + "x-ms-return-client-request-id": "true", + "x-ms-version": "2019-12-12" + }, + "RequestBody": null, + "StatusCode": 200, + "ResponseHeaders": { + "Content-Length": "854", + "Content-Type": "application/xml", + "Date": "Thu, 03 Sep 2020 19:23:15 GMT", + "Server": [ + "Windows-Azure-Blob/1.0", + "Microsoft-HTTPAPI/2.0" + ], + "x-ms-client-request-id": "03feed53-84a2-a834-ad26-2fe54fecc9a1", + "x-ms-request-id": "d77524f5-901e-0036-2127-8257b2000000", + "x-ms-version": "2019-12-12" + }, + "ResponseBody": "\uFEFF\u003C?xml version=\u00221.0\u0022 encoding=\u0022utf-8\u0022?\u003E\u003CEnumerationResults ServiceEndpoint=\u0022https://seanmcccanary3.blob.core.windows.net/\u0022 ContainerName=\u0022test-container-fac230ef-737b-66a8-a34a-3cc30767c245\u0022\u003E\u003CBlobs\u003E\u003CBlob\u003E\u003CName\u003Etest-blob-27032c7b-0af4-c303-96fa-dce3ef67de69\u003C/Name\u003E\u003CProperties\u003E\u003CCreation-Time\u003EThu, 03 Sep 2020 19:23:15 GMT\u003C/Creation-Time\u003E\u003CLast-Modified\u003EThu, 03 Sep 2020 19:23:15 GMT\u003C/Last-Modified\u003E\u003CEtag\u003E0x8D8503ECEB368EC\u003C/Etag\u003E\u003CContent-Length\u003E0\u003C/Content-Length\u003E\u003CContent-Type\u003Eapplication/octet-stream\u003C/Content-Type\u003E\u003CContent-Encoding /\u003E\u003CContent-Language /\u003E\u003CContent-CRC64 /\u003E\u003CContent-MD5 /\u003E\u003CCache-Control /\u003E\u003CContent-Disposition /\u003E\u003CBlobType\u003EAppendBlob\u003C/BlobType\u003E\u003CLeaseStatus\u003Eunlocked\u003C/LeaseStatus\u003E\u003CLeaseState\u003Eavailable\u003C/LeaseState\u003E\u003CServerEncrypted\u003Etrue\u003C/ServerEncrypted\u003E\u003C/Properties\u003E\u003CMetadata /\u003E\u003COrMetadata /\u003E\u003C/Blob\u003E\u003C/Blobs\u003E\u003CNextMarker /\u003E\u003C/EnumerationResults\u003E" + }, + { + "RequestUri": "https://seanmcccanary3.blob.core.windows.net/test-container-fac230ef-737b-66a8-a34a-3cc30767c245?restype=container", + "RequestMethod": "DELETE", + "RequestHeaders": { + "Authorization": "Sanitized", + "traceparent": "00-4bd1c2ef19610d4aa23ab27271116f3d-ce434f72e0686c4d-00", + "User-Agent": [ + "azsdk-net-Storage.Blobs/12.7.0-alpha.20200903.1", + "(.NET Core 4.6.29017.01; Microsoft Windows 10.0.18362 )" + ], + "x-ms-client-request-id": "31dc0d95-1381-b480-9255-f719e96cee24", + "x-ms-date": "Thu, 03 Sep 2020 19:23:17 GMT", + "x-ms-return-client-request-id": "true", + "x-ms-version": "2019-12-12" + }, + "RequestBody": null, + "StatusCode": 202, + "ResponseHeaders": { + "Content-Length": "0", + "Date": "Thu, 03 Sep 2020 19:23:15 GMT", + "Server": [ + "Windows-Azure-Blob/1.0", + "Microsoft-HTTPAPI/2.0" + ], + "x-ms-client-request-id": "31dc0d95-1381-b480-9255-f719e96cee24", + "x-ms-request-id": "d7752507-901e-0036-3027-8257b2000000", + "x-ms-version": "2019-12-12" + }, + "ResponseBody": [] + } + ], + "Variables": { + "RandomSeed": "1811523451", + "Storage_TestConfigDefault": "ProductionTenant\nseanmcccanary3\nU2FuaXRpemVk\nhttps://seanmcccanary3.blob.core.windows.net\nhttps://seanmcccanary3.file.core.windows.net\nhttps://seanmcccanary3.queue.core.windows.net\nhttps://seanmcccanary3.table.core.windows.net\n\n\n\n\nhttps://seanmcccanary3-secondary.blob.core.windows.net\nhttps://seanmcccanary3-secondary.file.core.windows.net\nhttps://seanmcccanary3-secondary.queue.core.windows.net\nhttps://seanmcccanary3-secondary.table.core.windows.net\n\nSanitized\n\n\nCloud\nBlobEndpoint=https://seanmcccanary3.blob.core.windows.net/;QueueEndpoint=https://seanmcccanary3.queue.core.windows.net/;FileEndpoint=https://seanmcccanary3.file.core.windows.net/;BlobSecondaryEndpoint=https://seanmcccanary3-secondary.blob.core.windows.net/;QueueSecondaryEndpoint=https://seanmcccanary3-secondary.queue.core.windows.net/;FileSecondaryEndpoint=https://seanmcccanary3-secondary.file.core.windows.net/;AccountName=seanmcccanary3;AccountKey=Kg==;\nseanscope1" + } +} \ No newline at end of file