Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Fix getblocks long #19078

Merged
merged 12 commits into from
Mar 1, 2021
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,9 @@ internal BlobAppendInfo() { }
private readonly object _dummy;
private readonly int _dummyPrimitive;
public string Name { get { throw null; } }
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
public int Size { get { throw null; } }
public long SizeLong { get { throw null; } }
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
public bool Equals(Azure.Storage.Blobs.Models.BlobBlock other) { throw null; }
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
Expand Down Expand Up @@ -839,7 +841,9 @@ public static partial class BlobsModelFactory
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
public static Azure.Storage.Blobs.Models.BlobAppendInfo BlobAppendInfo(Azure.ETag eTag, System.DateTimeOffset lastModified, byte[] contentHash, byte[] contentCrc64, string blobAppendOffset, int blobCommittedBlockCount, bool isServerEncrypted, string encryptionKeySha256) { throw null; }
public static Azure.Storage.Blobs.Models.BlobAppendInfo BlobAppendInfo(Azure.ETag eTag, System.DateTimeOffset lastModified, byte[] contentHash, byte[] contentCrc64, string blobAppendOffset, int blobCommittedBlockCount, bool isServerEncrypted, string encryptionKeySha256, string encryptionScope) { throw null; }
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
public static Azure.Storage.Blobs.Models.BlobBlock BlobBlock(string name, int size) { throw null; }
public static Azure.Storage.Blobs.Models.BlobBlock BlobBlock(string name, long size) { throw null; }
public static Azure.Storage.Blobs.Models.BlobContainerAccessPolicy BlobContainerAccessPolicy(Azure.Storage.Blobs.Models.PublicAccessType blobPublicAccess, Azure.ETag eTag, System.DateTimeOffset lastModified, System.Collections.Generic.IEnumerable<Azure.Storage.Blobs.Models.BlobSignedIdentifier> signedIdentifiers) { throw null; }
public static Azure.Storage.Blobs.Models.BlobContainerInfo BlobContainerInfo(Azure.ETag eTag, System.DateTimeOffset lastModified) { throw null; }
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 23 additions & 0 deletions sdk/storage/Azure.Storage.Blobs/src/Models/BlobBlock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT License.

using System;
using System.ComponentModel;
using Azure.Core;

namespace Azure.Storage.Blobs.Models
Expand All @@ -12,6 +13,28 @@ namespace Azure.Storage.Blobs.Models
[CodeGenModel("Block")]
public readonly partial struct BlobBlock : IEquatable<BlobBlock>
{
// All properties are rebuilt by hand in this class to avoid compile error CS0282

/// <summary>
/// The block size in bytes.
/// </summary>
[CodeGenMember("Size")]
public long SizeLong { get; }

/// <summary>
/// This property is a backwards-compatible facade for <see cref="SizeLong"/>,
/// which supports long values. Use <see cref="SizeLong"/> for full access of
/// supported values.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public int Size => checked((int)SizeLong);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does checked do? Ensure we didn’t wrap around?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. Without this, the extra bits are just discarded. Here, we actually throw the OverflowException.


/// <summary>
/// The base64 encoded block ID.
/// </summary>
[CodeGenMember("Name")]
public string Name { get; }

/// <summary>
/// Check if two BlobBlock instances are equal.
/// </summary>
Expand Down
11 changes: 11 additions & 0 deletions sdk/storage/Azure.Storage.Blobs/src/Models/BlobsModelFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1416,12 +1416,23 @@ public static PageBlobInfo PageBlobInfo(
/// <summary>
/// Creates a new BlobBlock instance for mocking.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public static BlobBlock BlobBlock(
string name,
int size)
{
return new BlobBlock(name, size);
}

/// <summary>
/// Creates a new BlobBlock instance for mocking.
/// </summary>
public static BlobBlock BlobBlock(
string name,
long size)
{
return new BlobBlock(name, size);
}
#endregion

#region BlobGeoReplication
Expand Down
2 changes: 1 addition & 1 deletion sdk/storage/Azure.Storage.Blobs/src/autorest.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Run `dotnet build /t:GenerateCode` to generate code.

``` yaml
input-file:
- https://raw.githubusercontent.com/Azure/azure-rest-api-specs/011761be1285d14feb41796b5d97df1126495c5c/specification/storage/data-plane/Microsoft.BlobStorage/preview/2020-06-12/blob.json
- https://raw.githubusercontent.com/Azure/azure-rest-api-specs/blob/8c1f9b739165035d9ced32761cebb19125bce233/specification/storage/data-plane/Microsoft.BlobStorage/preview/2020-06-12/blob.json
```

### Move path parameters to constructor.
Expand Down
45 changes: 45 additions & 0 deletions sdk/storage/Azure.Storage.Blobs/tests/BlockBlobClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using Azure.Storage.Test.Shared;
using Moq;
using NUnit.Framework;
using static Azure.Storage.Blobs.BlobClientOptions;
using Metadata = System.Collections.Generic.IDictionary<string, string>;
using Tags = System.Collections.Generic.IDictionary<string, string>;

Expand Down Expand Up @@ -1513,6 +1514,50 @@ public async Task GetBlockListAsync()
Assert.AreEqual(blockId1, response.Value.UncommittedBlocks.First().Name);
}

[Test]
[LiveOnly]
[ServiceVersion(Min = ServiceVersion.V2019_12_12)]
[Ignore("https://github.com/Azure/azure-sdk-for-net/issues/12312")]
public async Task GetBlockListAsync_LongBlock()
{
const long bigBlockSize = int.MaxValue + 1024L;
await using DisposingContainer test = await GetTestContainerAsync();

// Arrange
BlockBlobClient blob = InstrumentClient(test.Container.GetBlockBlobClient(GetNewBlobName()));
var data = GetRandomBuffer(Size);

// Upload to blockBlobUri, so it exists
using (var stream = new MemoryStream(data))
{
await blob.UploadAsync(stream);
}

var blockId0 = ToBase64(GetNewBlockName());
using (var stream = new Storage.Tests.Shared.PredictableStream(length: bigBlockSize))
{
await blob.StageBlockAsync(blockId0, stream);
}
await blob.CommitBlockListAsync(new string[] { blockId0 });

var blockId1 = ToBase64(GetNewBlobName());
using (var stream = new MemoryStream(data))
{
await blob.StageBlockAsync(blockId1, stream);
}

// Act
Response<BlockList> response = await blob.GetBlockListAsync();

// Assert
Assert.AreEqual(1, response.Value.CommittedBlocks.Count());
Assert.AreEqual(blockId0, response.Value.CommittedBlocks.First().Name);
Assert.AreEqual(1, response.Value.UncommittedBlocks.Count());
Assert.AreEqual(blockId1, response.Value.UncommittedBlocks.First().Name);
Assert.AreEqual(bigBlockSize, response.Value.CommittedBlocks.First().SizeLong);
Assert.Throws<OverflowException>(() => _ = response.Value.CommittedBlocks.First().Size); // if no overflow then we didn't actually test handling of long lengths
}

[Test]
public async Task GetBlockListAsync_Type()
{
Expand Down