Skip to content

Commit

Permalink
Merge pull request #72 from managedcode/rybina/test_azure_stream
Browse files Browse the repository at this point in the history
Add tests for azure blob stream
  • Loading branch information
TRybina132 committed Oct 20, 2023
2 parents 1945489 + 292df32 commit 36730ab
Show file tree
Hide file tree
Showing 4 changed files with 222 additions and 6 deletions.
13 changes: 7 additions & 6 deletions ManagedCode.Storage.Azure/BlobStream.cs
Expand Up @@ -37,18 +37,19 @@ public override long Length
{
get
{
var realLength = 0L;
var metadata = _pageBlob.GetProperties().Value.Metadata;
var properties = _pageBlob.GetProperties();
var metadata = properties.Value.Metadata;
if (metadata.TryGetValue(MetadataLengthKey, out var length))
{
if (long.TryParse(length, out realLength))
if (long.TryParse(length, out var realLength))
{
return realLength;
}
}

SetLengthInternal(realLength);
return realLength;

var contentLenght = properties.Value.ContentLength;
SetLengthInternal(contentLenght);
return contentLenght;
}
}

Expand Down
28 changes: 28 additions & 0 deletions ManagedCode.Storage.Tests/Common/FileHelper.cs
Expand Up @@ -25,6 +25,34 @@ public static LocalFile GenerateLocalFile(string fileName, int byteSize)
return localFile;
}

public static LocalFile GenerateLocalFileWithData(LocalFile file, int sizeInBytes)
{
using (var fileStream = file.FileStream)
{
Random random = new Random();
byte[] buffer = new byte[1024]; // Buffer for writing in chunks

while (sizeInBytes > 0)
{
int bytesToWrite = (int) Math.Min(sizeInBytes, buffer.Length);

for (int i = 0; i < bytesToWrite; i++)
{
buffer[i] = (byte) random.Next(65, 91); // 'A' to 'Z'
if (random.Next(2) == 0)
{
buffer[i] = (byte) random.Next(97, 123); // 'a' to 'z'
}
}

fileStream.Write(buffer, 0, bytesToWrite);
sizeInBytes -= bytesToWrite;
}
}

return file;
}

public static IFormFile GenerateFormFile(string fileName, int byteSize)
{
var localFile = GenerateLocalFile(fileName, byteSize);
Expand Down
175 changes: 175 additions & 0 deletions ManagedCode.Storage.Tests/Storages/Azure/AzureBlobStreamTests.cs
@@ -0,0 +1,175 @@
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using FluentAssertions;
using ManagedCode.Storage.Azure;
using ManagedCode.Storage.Core.Models;
using ManagedCode.Storage.Tests.Common;
using Microsoft.Extensions.DependencyInjection;
using Testcontainers.Azurite;
using Xunit;

namespace ManagedCode.Storage.Tests.Storages.Azure;

public class AzureBlobStreamTests : StreamTests<AzuriteContainer>
{
protected override AzuriteContainer Build()
{
return new AzuriteBuilder()
.WithImage("mcr.microsoft.com/azure-storage/azurite:3.26.0")
.Build();
}

protected override ServiceProvider ConfigureServices()
{
return AzureConfigurator.ConfigureServices(Container.GetConnectionString());
}

[Fact]
public async Task ReadStreamWithStreamReader_WhenFileExists_ReturnData()
{
// Arrange
var directory = "test-directory";
var fileSizeInBytes = 10;
await using var localFile = LocalFile.FromRandomNameWithExtension(".txt");
FileHelper.GenerateLocalFileWithData(localFile, fileSizeInBytes);
var storage = (IAzureStorage) Storage;

UploadOptions options = new() { FileName = localFile.Name, Directory = directory };
await using var localFileStream = localFile.FileInfo.OpenRead();
var result = await storage.UploadAsync(localFileStream, options);

await using var blobStream = storage.GetBlobStream(result.Value.FullName);

// Act
using var streamReader = new StreamReader(blobStream);
var content = await streamReader.ReadToEndAsync();

// Assert
await using var fileStream = localFile.FileInfo.OpenRead();
using var fileReader = new StreamReader(fileStream);
var fileContent = await fileReader.ReadToEndAsync();
content.Should().NotBeNullOrEmpty();
fileContent.Should().NotBeNullOrEmpty();
content.Should().Be(fileContent);
}

[Fact]
public async Task ReadStream_WhenFileExists_ReturnData()
{
// Arrange
var directory = "test-directory";
var fileSizeInBytes = 10;
await using var localFile = LocalFile.FromRandomNameWithExtension(".txt");
FileHelper.GenerateLocalFileWithData(localFile, fileSizeInBytes);
var storage = (IAzureStorage) Storage;

UploadOptions options = new() { FileName = localFile.Name, Directory = directory };
await using var fileStream = localFile.FileInfo.OpenRead();
var result = await storage.UploadAsync(fileStream, options);

await using var blobStream = storage.GetBlobStream(result.Value.FullName);

var chunkSize = (int) blobStream.Length / 2;
var chunk1 = new byte[chunkSize];
var chunk2 = new byte[chunkSize];

// Act
var bytesReadForChunk1 = await blobStream.ReadAsync(chunk1, 0, chunkSize);
var bytesReadForChunk2 = await blobStream.ReadAsync(chunk2, 0, chunkSize);

// Assert
bytesReadForChunk1.Should().Be(chunkSize);
bytesReadForChunk2.Should().Be(chunkSize);
chunk1.Should().NotBeNullOrEmpty().And.HaveCount(chunkSize);
chunk2.Should().NotBeNullOrEmpty().And.HaveCount(chunkSize);
}

[Fact]
public async Task ReadStream_WhenFileDoesNotExists_ReturnNoData()
{
// Arrange
var directory = "test-directory";
var storage = (IAzureStorage) Storage;
await storage.CreateContainerAsync();
var fullFileName = $"{directory}/{Guid.NewGuid()}.txt";

await using var blobStream = storage.GetBlobStream(fullFileName);
var chunk = new byte[4];

// Act
var bytesRead = await blobStream.ReadAsync(chunk, 0, 4);

// Assert
bytesRead.Should().Be(0);
chunk.Should().NotBeNullOrEmpty();
chunk.Should().AllBeEquivalentTo(0);
}

[Fact]
public async Task WriteStreamWithStreamWriter_SaveData()
{
// Arrange
var directory = "test-directory";
await using var localFile = LocalFile.FromRandomNameWithExtension(".txt");
var fileSizeInBytes = 10;
FileHelper.GenerateLocalFileWithData(localFile, fileSizeInBytes);
var fullFileName = $"{directory}/{localFile.FileInfo.FullName}";

var storage = (IAzureStorage) Storage;

await storage.CreateContainerAsync();

// Act
await using (var blobStream = storage.GetBlobStream(fullFileName))
{
await using (var localFileStream = localFile.FileStream)
{
await localFileStream.CopyToAsync(blobStream);
}
}

// Assert
var fileResult = await storage.DownloadAsync(fullFileName);
fileResult.IsSuccess.Should().BeTrue();
fileResult.Value.Should().NotBeNull();
await using var fileStream = fileResult.Value.FileStream;
using var streamReader = new StreamReader(fileStream);
var fileContent = await streamReader.ReadLineAsync();
fileContent.Should().NotBeNullOrEmpty();
}

[Fact]
public async Task Seek_WhenFileExists_ReturnData()
{
// Arrange
var directory = "test-directory";
var fileSizeInBytes = 10;
await using var localFile = LocalFile.FromRandomNameWithExtension(".txt");
FileHelper.GenerateLocalFileWithData(localFile, fileSizeInBytes);
var storage = (IAzureStorage) Storage;

UploadOptions options = new() { FileName = localFile.Name, Directory = directory };
await using var localFileStream = localFile.FileInfo.OpenRead();
var result = await storage.UploadAsync(localFileStream, options);

await using var blobStream = storage.GetBlobStream(result.Value.FullName);

// Act
var seekInPosition = fileSizeInBytes / 2;
blobStream.Seek(seekInPosition, SeekOrigin.Current);
var buffer = new byte[seekInPosition];
var bytesRead = await blobStream.ReadAsync(buffer);

// Assert
bytesRead.Should().Be(seekInPosition);
await using var fileStream = localFile.FileInfo.OpenRead();
using var fileReader = new StreamReader(fileStream);
var fileContent = await fileReader.ReadToEndAsync();
var content = Encoding.UTF8.GetString(buffer);
content.Should().NotBeNullOrEmpty();
var trimmedFileContent = fileContent.Remove(0, seekInPosition);
content.Should().Be(trimmedFileContent);
}
}
12 changes: 12 additions & 0 deletions ManagedCode.Storage.Tests/Storages/StreamTests.cs
@@ -0,0 +1,12 @@
using System.Threading.Tasks;
using DotNet.Testcontainers.Containers;
using ManagedCode.Storage.Tests.Common;
using Xunit;

namespace ManagedCode.Storage.Tests.Storages;

public abstract class StreamTests<T> : BaseContainer<T>
where T : IContainer
{

}

0 comments on commit 36730ab

Please sign in to comment.