Initial commit
This commit is contained in:
@@ -0,0 +1,428 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user