Skip to content

Commit 776d4e0

Browse files
committed
Add OpenReadAsync to ISimpleCloudBlob wrapper (#6758)
Progress on #6449
1 parent a49d5ec commit 776d4e0

3 files changed

Lines changed: 134 additions & 0 deletions

File tree

src/NuGetGallery.Core/Services/CloudBlobWrapper.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ public CloudBlobWrapper(CloudBlockBlob blob)
2929
_blob = blob;
3030
}
3131

32+
public async Task<Stream> OpenReadAsync(AccessCondition accessCondition)
33+
{
34+
return await _blob.OpenReadAsync(
35+
accessCondition: accessCondition,
36+
options: null,
37+
operationContext: null);
38+
}
39+
3240
public async Task DeleteIfExistsAsync()
3341
{
3442
await _blob.DeleteIfExistsAsync(

src/NuGetGallery.Core/Services/ISimpleCloudBlob.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ public interface ISimpleCloudBlob
2020
DateTime LastModifiedUtc { get; }
2121
string ETag { get; }
2222

23+
Task<Stream> OpenReadAsync(AccessCondition accessCondition);
24+
2325
Task DeleteIfExistsAsync();
2426
Task DownloadToStreamAsync(Stream target);
2527
Task DownloadToStreamAsync(Stream target, AccessCondition accessCondition);

tests/NuGetGallery.Core.Facts/Services/CloudBlobCoreFileStorageServiceIntegrationTests.cs

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System;
55
using System.Collections.Concurrent;
66
using System.IO;
7+
using System.Net;
78
using System.Text;
89
using System.Threading;
910
using System.Threading.Tasks;
@@ -58,6 +59,129 @@ public CloudBlobCoreFileStorageServiceIntegrationTests(BlobStorageFixture fixtur
5859
_targetB = new CloudBlobCoreFileStorageService(_clientB, Mock.Of<IDiagnosticsService>());
5960
}
6061

62+
[BlobStorageFact]
63+
public async Task OpenReadAsyncReturnsReadableStreamWhenBlobExistsAndPopulatesProperties()
64+
{
65+
// Arrange
66+
var folderName = CoreConstants.Folders.ValidationFolderName;
67+
var fileName = _prefixA;
68+
var expectedContent = "Hello, world.";
69+
70+
await _targetA.SaveFileAsync(
71+
folderName,
72+
fileName,
73+
new MemoryStream(Encoding.ASCII.GetBytes(expectedContent)),
74+
overwrite: false);
75+
76+
var container = _clientA.GetContainerReference(folderName);
77+
var file = container.GetBlobReference(fileName);
78+
79+
// Act
80+
using (var stream = await file.OpenReadAsync(accessCondition: null))
81+
using (var streamReader = new StreamReader(stream))
82+
{
83+
var actualContent = await streamReader.ReadToEndAsync();
84+
85+
// Assert
86+
Assert.Equal(expectedContent, actualContent);
87+
Assert.Equal(expectedContent.Length, file.Properties.Length);
88+
Assert.NotNull(file.ETag);
89+
}
90+
}
91+
92+
[BlobStorageFact]
93+
public async Task OpenReadAsyncThrowsNotFoundWhenBlobDoesNotExist()
94+
{
95+
// Arrange
96+
var folderName = CoreConstants.Folders.ValidationFolderName;
97+
var fileName = _prefixA;
98+
var exists = await _targetA.FileExistsAsync(folderName, fileName);
99+
var container = _clientA.GetContainerReference(folderName);
100+
var file = container.GetBlobReference(fileName);
101+
102+
// Act & Assert
103+
Assert.False(exists);
104+
var ex = await Assert.ThrowsAsync<StorageException>(
105+
() => file.OpenReadAsync(accessCondition: null));
106+
Assert.Equal(HttpStatusCode.NotFound, (HttpStatusCode)ex.RequestInformation.HttpStatusCode);
107+
}
108+
109+
[BlobStorageFact]
110+
public async Task OpenReadAsyncThrowsPreconditionFailedWhenIfMatchFails()
111+
{
112+
// Arrange
113+
var folderName = CoreConstants.Folders.ValidationFolderName;
114+
var fileName = _prefixA;
115+
116+
await _targetA.SaveFileAsync(
117+
folderName,
118+
fileName,
119+
new MemoryStream(Encoding.ASCII.GetBytes("Hello, world.")),
120+
overwrite: false);
121+
122+
var container = _clientA.GetContainerReference(folderName);
123+
var file = container.GetBlobReference(fileName);
124+
await file.FetchAttributesAsync();
125+
126+
// Act & Assert
127+
var ex = await Assert.ThrowsAsync<StorageException>(
128+
() => file.OpenReadAsync(accessCondition: AccessCondition.GenerateIfMatchCondition("WON'T MATCH")));
129+
Assert.Equal(HttpStatusCode.PreconditionFailed, (HttpStatusCode)ex.RequestInformation.HttpStatusCode);
130+
}
131+
132+
[BlobStorageFact]
133+
public async Task OpenReadAsyncThrowsNotModifiedWhenIfNoneMatchFails()
134+
{
135+
// Arrange
136+
var folderName = CoreConstants.Folders.ValidationFolderName;
137+
var fileName = _prefixA;
138+
139+
await _targetA.SaveFileAsync(
140+
folderName,
141+
fileName,
142+
new MemoryStream(Encoding.ASCII.GetBytes("Hello, world.")),
143+
overwrite: false);
144+
145+
var container = _clientA.GetContainerReference(folderName);
146+
var file = container.GetBlobReference(fileName);
147+
await file.FetchAttributesAsync();
148+
149+
// Act & Assert
150+
var ex = await Assert.ThrowsAsync<StorageException>(
151+
() => file.OpenReadAsync(accessCondition: AccessCondition.GenerateIfNoneMatchCondition(file.ETag)));
152+
Assert.Equal(HttpStatusCode.NotModified, (HttpStatusCode)ex.RequestInformation.HttpStatusCode);
153+
}
154+
155+
[BlobStorageFact]
156+
public async Task OpenReadAsyncReturnsContentWhenIfNoneMatchSucceeds()
157+
{
158+
// Arrange
159+
var folderName = CoreConstants.Folders.ValidationFolderName;
160+
var fileName = _prefixA;
161+
var expectedContent = "Hello, world.";
162+
163+
await _targetA.SaveFileAsync(
164+
folderName,
165+
fileName,
166+
new MemoryStream(Encoding.ASCII.GetBytes(expectedContent)),
167+
overwrite: false);
168+
169+
var container = _clientA.GetContainerReference(folderName);
170+
var file = container.GetBlobReference(fileName);
171+
172+
// Act
173+
using (var stream = await file.OpenReadAsync(accessCondition: AccessCondition.GenerateIfNoneMatchCondition("WON'T MATCH")))
174+
using (var streamReader = new StreamReader(stream))
175+
{
176+
var actualContent = await streamReader.ReadToEndAsync();
177+
178+
// Assert
179+
Assert.Equal(expectedContent, actualContent);
180+
Assert.Equal(expectedContent.Length, file.Properties.Length);
181+
Assert.NotNull(file.ETag);
182+
}
183+
}
184+
61185
[BlobStorageFact]
62186
public async Task ReturnsCurrentETagForIfMatch()
63187
{

0 commit comments

Comments
 (0)