429 lines
14 KiB
C#
429 lines
14 KiB
C#
using Minio;
|
|
using RobotNet10.StorageManager;
|
|
using Xunit;
|
|
|
|
namespace RobotNet10.StorageManager.Test;
|
|
|
|
public class StorageManagerTests
|
|
{
|
|
private readonly string _testFolder = Path.Combine(Path.GetTempPath(), "StorageManagerTests");
|
|
|
|
public StorageManagerTests()
|
|
{
|
|
// Clean up test folder before each test
|
|
if (Directory.Exists(_testFolder))
|
|
{
|
|
Directory.Delete(_testFolder, true);
|
|
}
|
|
Directory.CreateDirectory(_testFolder);
|
|
}
|
|
|
|
[Fact]
|
|
public void Constructor_WithNullConfig_ThrowsArgumentNullException()
|
|
{
|
|
// Act & Assert
|
|
Assert.Throws<ArgumentNullException>(() => new StorageManager(null!));
|
|
}
|
|
|
|
[Fact]
|
|
public void Constructor_WithMinioButNoConfig_ThrowsArgumentException()
|
|
{
|
|
// Arrange
|
|
var config = new StorageConfig
|
|
{
|
|
UsingLocal = false,
|
|
MinioConfig = null
|
|
};
|
|
|
|
// Act & Assert
|
|
var ex = Assert.Throws<ArgumentException>(() => new StorageManager(config));
|
|
Assert.Contains("MinioConfig is required", ex.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void Constructor_WithMinioButEmptyEndpoint_ThrowsArgumentException()
|
|
{
|
|
// Arrange
|
|
var config = new StorageConfig
|
|
{
|
|
UsingLocal = false,
|
|
MinioConfig = new MinioConfig { Endpoint = string.Empty },
|
|
Bucket = "test-bucket"
|
|
};
|
|
|
|
// Act & Assert
|
|
var ex = Assert.Throws<ArgumentException>(() => new StorageManager(config));
|
|
Assert.Contains("Endpoint", ex.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public void Constructor_WithMinioButEmptyBucket_ThrowsArgumentException()
|
|
{
|
|
// Arrange
|
|
var config = new StorageConfig
|
|
{
|
|
UsingLocal = false,
|
|
MinioConfig = new MinioConfig { Endpoint = "localhost:9000" },
|
|
Bucket = string.Empty
|
|
};
|
|
|
|
// Act & Assert
|
|
var ex = Assert.Throws<ArgumentException>(() => new StorageManager(config));
|
|
Assert.Contains("Bucket", ex.Message);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task UploadAsync_WithNullPath_ThrowsArgumentException()
|
|
{
|
|
// Arrange
|
|
var config = new StorageConfig { UsingLocal = true, LocalFolder = _testFolder };
|
|
var manager = new StorageManager(config);
|
|
var data = new MemoryStream(new byte[] { 1, 2, 3 });
|
|
|
|
// Act & Assert
|
|
await Assert.ThrowsAsync<ArgumentException>(() =>
|
|
manager.UploadAsync(null!, "test", data, 3, "image/png", CancellationToken.None));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task UploadAsync_WithPathContainingDotDot_ThrowsArgumentException()
|
|
{
|
|
// Arrange
|
|
var config = new StorageConfig { UsingLocal = true, LocalFolder = _testFolder };
|
|
var manager = new StorageManager(config);
|
|
var data = new MemoryStream(new byte[] { 1, 2, 3 });
|
|
|
|
// Act & Assert
|
|
await Assert.ThrowsAsync<ArgumentException>(() =>
|
|
manager.UploadAsync("../test", "test", data, 3, "image/png", CancellationToken.None));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task UploadAsync_WithNullData_ThrowsArgumentNullException()
|
|
{
|
|
// Arrange
|
|
var config = new StorageConfig { UsingLocal = true, LocalFolder = _testFolder };
|
|
var manager = new StorageManager(config);
|
|
|
|
// Act & Assert
|
|
await Assert.ThrowsAsync<ArgumentNullException>(() =>
|
|
manager.UploadAsync("test", "test", null!, 3, "image/png", CancellationToken.None));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task UploadAsync_WithNegativeSize_ThrowsArgumentException()
|
|
{
|
|
// Arrange
|
|
var config = new StorageConfig { UsingLocal = true, LocalFolder = _testFolder };
|
|
var manager = new StorageManager(config);
|
|
var data = new MemoryStream(new byte[] { 1, 2, 3 });
|
|
|
|
// Act & Assert
|
|
await Assert.ThrowsAsync<ArgumentException>(() =>
|
|
manager.UploadAsync("test", "test", data, -1, "image/png", CancellationToken.None));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task UploadAsync_Local_WithPngContentType_CreatesPngFile()
|
|
{
|
|
// Arrange
|
|
var config = new StorageConfig { UsingLocal = true, LocalFolder = _testFolder };
|
|
var manager = new StorageManager(config);
|
|
var data = new MemoryStream(new byte[] { 1, 2, 3 });
|
|
var path = "test";
|
|
var objectName = "image";
|
|
|
|
// Act
|
|
await manager.UploadAsync(path, objectName, data, 3, "image/png", CancellationToken.None);
|
|
|
|
// Assert
|
|
var expectedPath = Path.Combine(_testFolder, path, $"{objectName}.png");
|
|
Assert.True(File.Exists(expectedPath));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task UploadAsync_Local_WithJpegContentType_CreatesJpgFile()
|
|
{
|
|
// Arrange
|
|
var config = new StorageConfig { UsingLocal = true, LocalFolder = _testFolder };
|
|
var manager = new StorageManager(config);
|
|
var data = new MemoryStream(new byte[] { 1, 2, 3 });
|
|
var path = "test";
|
|
var objectName = "image";
|
|
|
|
// Act
|
|
await manager.UploadAsync(path, objectName, data, 3, "image/jpeg", CancellationToken.None);
|
|
|
|
// Assert
|
|
var expectedPath = Path.Combine(_testFolder, path, $"{objectName}.jpg");
|
|
Assert.True(File.Exists(expectedPath));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task UploadAsync_Local_WithPdfContentType_CreatesPdfFile()
|
|
{
|
|
// Arrange
|
|
var config = new StorageConfig { UsingLocal = true, LocalFolder = _testFolder };
|
|
var manager = new StorageManager(config);
|
|
var data = new MemoryStream(new byte[] { 1, 2, 3 });
|
|
var path = "test";
|
|
var objectName = "document";
|
|
|
|
// Act
|
|
await manager.UploadAsync(path, objectName, data, 3, "application/pdf", CancellationToken.None);
|
|
|
|
// Assert
|
|
var expectedPath = Path.Combine(_testFolder, path, $"{objectName}.pdf");
|
|
Assert.True(File.Exists(expectedPath));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task UploadAsync_Local_CreatesBackupFile()
|
|
{
|
|
// Arrange
|
|
var config = new StorageConfig { UsingLocal = true, LocalFolder = _testFolder };
|
|
var manager = new StorageManager(config);
|
|
var data1 = new MemoryStream(new byte[] { 1, 2, 3 });
|
|
var data2 = new MemoryStream(new byte[] { 4, 5, 6 });
|
|
var path = "test";
|
|
var objectName = "image";
|
|
|
|
// Act - Upload first time
|
|
await manager.UploadAsync(path, objectName, data1, 3, "image/png", CancellationToken.None);
|
|
var filePath = Path.Combine(_testFolder, path, $"{objectName}.png");
|
|
Assert.True(File.Exists(filePath));
|
|
|
|
// Upload second time - should create backup
|
|
await manager.UploadAsync(path, objectName, data2, 3, "image/png", CancellationToken.None);
|
|
|
|
// Assert
|
|
Assert.True(File.Exists(filePath));
|
|
var backupPath = $"{filePath}.bk";
|
|
Assert.True(File.Exists(backupPath));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetUrlAsync_Local_WithExistingFile_ReturnsPath()
|
|
{
|
|
// Arrange
|
|
var config = new StorageConfig { UsingLocal = true, LocalFolder = _testFolder };
|
|
var manager = new StorageManager(config);
|
|
var path = "test";
|
|
var objectName = "image";
|
|
var filePath = Path.Combine(_testFolder, path, $"{objectName}.png");
|
|
Directory.CreateDirectory(Path.GetDirectoryName(filePath)!);
|
|
File.WriteAllBytes(filePath, new byte[] { 1, 2, 3 });
|
|
|
|
// Act
|
|
var url = await manager.GetUrlAsync(path, objectName, CancellationToken.None);
|
|
|
|
// Assert
|
|
Assert.Equal(filePath, url);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetUrlAsync_Local_WithNonExistingFile_ReturnsEmpty()
|
|
{
|
|
// Arrange
|
|
var config = new StorageConfig { UsingLocal = true, LocalFolder = _testFolder };
|
|
var manager = new StorageManager(config);
|
|
|
|
// Act
|
|
var url = await manager.GetUrlAsync("test", "nonexistent", CancellationToken.None);
|
|
|
|
// Assert
|
|
Assert.Equal(string.Empty, url);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task DeleteAsync_Local_DeletesFile()
|
|
{
|
|
// Arrange
|
|
var config = new StorageConfig { UsingLocal = true, LocalFolder = _testFolder };
|
|
var manager = new StorageManager(config);
|
|
var path = "test";
|
|
var objectName = "image";
|
|
var filePath = Path.Combine(_testFolder, path, $"{objectName}.png");
|
|
Directory.CreateDirectory(Path.GetDirectoryName(filePath)!);
|
|
File.WriteAllBytes(filePath, new byte[] { 1, 2, 3 });
|
|
|
|
// Act
|
|
await manager.DeleteAsync(path, objectName, CancellationToken.None);
|
|
|
|
// Assert
|
|
Assert.False(File.Exists(filePath));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ExistsAsync_Local_WithExistingFile_ReturnsTrue()
|
|
{
|
|
// Arrange
|
|
var config = new StorageConfig { UsingLocal = true, LocalFolder = _testFolder };
|
|
var manager = new StorageManager(config);
|
|
var path = "test";
|
|
var objectName = "image";
|
|
var filePath = Path.Combine(_testFolder, path, $"{objectName}.png");
|
|
Directory.CreateDirectory(Path.GetDirectoryName(filePath)!);
|
|
File.WriteAllBytes(filePath, new byte[] { 1, 2, 3 });
|
|
|
|
// Act
|
|
var exists = await manager.ExistsAsync(path, objectName, CancellationToken.None);
|
|
|
|
// Assert
|
|
Assert.True(exists);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ExistsAsync_Local_WithNonExistingFile_ReturnsFalse()
|
|
{
|
|
// Arrange
|
|
var config = new StorageConfig { UsingLocal = true, LocalFolder = _testFolder };
|
|
var manager = new StorageManager(config);
|
|
|
|
// Act
|
|
var exists = await manager.ExistsAsync("test", "nonexistent", CancellationToken.None);
|
|
|
|
// Assert
|
|
Assert.False(exists);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ListAsync_Local_NonRecursive_ReturnsFilesInPath()
|
|
{
|
|
// Arrange
|
|
var config = new StorageConfig { UsingLocal = true, LocalFolder = _testFolder };
|
|
var manager = new StorageManager(config);
|
|
var path = "test";
|
|
var folderPath = Path.Combine(_testFolder, path);
|
|
Directory.CreateDirectory(folderPath);
|
|
File.WriteAllBytes(Path.Combine(folderPath, "file1.png"), new byte[] { 1 });
|
|
File.WriteAllBytes(Path.Combine(folderPath, "file2.jpg"), new byte[] { 2 });
|
|
|
|
// Act
|
|
var files = await manager.ListAsync(path, false, CancellationToken.None);
|
|
|
|
// Assert
|
|
Assert.Equal(2, files.Count);
|
|
Assert.Contains("file1.png", files);
|
|
Assert.Contains("file2.jpg", files);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task ListAsync_Local_Recursive_ReturnsAllFiles()
|
|
{
|
|
// Arrange
|
|
var config = new StorageConfig { UsingLocal = true, LocalFolder = _testFolder };
|
|
var manager = new StorageManager(config);
|
|
var path = "test";
|
|
var folderPath = Path.Combine(_testFolder, path);
|
|
Directory.CreateDirectory(folderPath);
|
|
var subFolder = Path.Combine(folderPath, "sub");
|
|
Directory.CreateDirectory(subFolder);
|
|
File.WriteAllBytes(Path.Combine(folderPath, "file1.png"), new byte[] { 1 });
|
|
File.WriteAllBytes(Path.Combine(subFolder, "file2.jpg"), new byte[] { 2 });
|
|
|
|
// Act
|
|
var files = await manager.ListAsync(path, true, CancellationToken.None);
|
|
|
|
// Assert
|
|
Assert.Equal(2, files.Count);
|
|
Assert.Contains("file1.png", files);
|
|
Assert.Contains("sub/file2.jpg", files);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task CopyAsync_Local_CopiesFile()
|
|
{
|
|
// Arrange
|
|
var config = new StorageConfig { UsingLocal = true, LocalFolder = _testFolder };
|
|
var manager = new StorageManager(config);
|
|
var sourcePath = "source";
|
|
var destPath = "dest";
|
|
var objectName = "file";
|
|
var sourceFile = Path.Combine(_testFolder, sourcePath, $"{objectName}.png");
|
|
Directory.CreateDirectory(Path.GetDirectoryName(sourceFile)!);
|
|
File.WriteAllBytes(sourceFile, new byte[] { 1, 2, 3 });
|
|
|
|
// Act
|
|
await manager.CopyAsync(sourcePath, destPath, objectName, CancellationToken.None);
|
|
|
|
// Assert
|
|
var destFile = Path.Combine(_testFolder, destPath, $"{objectName}.png");
|
|
Assert.True(File.Exists(destFile));
|
|
Assert.True(File.Exists(sourceFile)); // Source should still exist
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetMetadataAsync_Local_ReturnsMetadata()
|
|
{
|
|
// Arrange
|
|
var config = new StorageConfig { UsingLocal = true, LocalFolder = _testFolder };
|
|
var manager = new StorageManager(config);
|
|
var path = "test";
|
|
var objectName = "image";
|
|
var filePath = Path.Combine(_testFolder, path, $"{objectName}.png");
|
|
Directory.CreateDirectory(Path.GetDirectoryName(filePath)!);
|
|
var fileData = new byte[] { 1, 2, 3, 4, 5 };
|
|
File.WriteAllBytes(filePath, fileData);
|
|
|
|
// Act
|
|
var metadata = await manager.GetMetadataAsync(path, objectName, CancellationToken.None);
|
|
|
|
// Assert
|
|
Assert.Equal(path, metadata.Path);
|
|
Assert.Equal(objectName, metadata.ObjectName);
|
|
Assert.Equal(fileData.Length, metadata.Size);
|
|
Assert.Equal("image/png", metadata.ContentType);
|
|
Assert.NotNull(metadata.LastModified);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetMetadataAsync_Local_WithNonExistingFile_ThrowsFileNotFoundException()
|
|
{
|
|
// Arrange
|
|
var config = new StorageConfig { UsingLocal = true, LocalFolder = _testFolder };
|
|
var manager = new StorageManager(config);
|
|
|
|
// Act & Assert
|
|
await Assert.ThrowsAsync<FileNotFoundException>(() =>
|
|
manager.GetMetadataAsync("test", "nonexistent", CancellationToken.None));
|
|
}
|
|
|
|
[Fact]
|
|
public void Dispose_DisposesMinioClient()
|
|
{
|
|
// Arrange
|
|
var config = new StorageConfig
|
|
{
|
|
UsingLocal = false,
|
|
MinioConfig = new MinioConfig
|
|
{
|
|
Endpoint = "localhost:9000",
|
|
User = "minioadmin",
|
|
Password = "minioadmin"
|
|
},
|
|
Bucket = "test-bucket"
|
|
};
|
|
var manager = new StorageManager(config);
|
|
|
|
// Act
|
|
manager.Dispose();
|
|
|
|
// Assert - Should not throw
|
|
Assert.True(true);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|