177 lines
5.8 KiB
C#
177 lines
5.8 KiB
C#
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Options;
|
|
using RobotNet10.FleetManager.Services;
|
|
using RobotNet10.StorageManager;
|
|
using System.Text;
|
|
|
|
namespace RobotNet10.RobotManager.Test.Services;
|
|
|
|
/// <summary>
|
|
/// Unit tests for RobotModelImageStorageService
|
|
/// </summary>
|
|
[TestFixture]
|
|
public class RobotModelImageStorageServiceTests
|
|
{
|
|
private string _testDirectory = null!;
|
|
private RobotModelImageStorageService _service = null!;
|
|
private IOptionsMonitor<StorageConfig> _optionsMonitor = null!;
|
|
|
|
[SetUp]
|
|
public void Setup()
|
|
{
|
|
// Create a temporary test directory
|
|
_testDirectory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
|
Directory.CreateDirectory(_testDirectory);
|
|
|
|
// Create StorageConfig for local storage
|
|
var storageConfig = new StorageConfig
|
|
{
|
|
UsingLocal = true,
|
|
LocalFolder = _testDirectory,
|
|
RetryCount = 3
|
|
};
|
|
|
|
// Mock IOptionsMonitor<StorageConfig>
|
|
var mockOptionsMonitor = new Moq.Mock<IOptionsMonitor<StorageConfig>>();
|
|
mockOptionsMonitor.Setup(m => m.Get("RobotModelImages")).Returns(storageConfig);
|
|
|
|
_optionsMonitor = mockOptionsMonitor.Object;
|
|
var logger = new LoggerFactory().CreateLogger<RobotModelImageStorageService>();
|
|
_service = new RobotModelImageStorageService(_optionsMonitor, logger);
|
|
}
|
|
|
|
[TearDown]
|
|
public void TearDown()
|
|
{
|
|
// Dispose service to clean up StorageManager
|
|
_service?.Dispose();
|
|
|
|
// Clean up test directory
|
|
if (Directory.Exists(_testDirectory))
|
|
{
|
|
Directory.Delete(_testDirectory, true);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public async Task SaveImageAsync_ValidImage_SavesToFileSystem()
|
|
{
|
|
// Arrange
|
|
var robotModelId = Guid.NewGuid();
|
|
var imageBytes = Encoding.UTF8.GetBytes("Fake PNG image data");
|
|
using var imageStream = new MemoryStream(imageBytes);
|
|
|
|
// Act
|
|
await _service.SaveImageAsync(robotModelId, imageStream);
|
|
|
|
// Assert
|
|
// StorageManager stores files in path "robotModelImages" with objectName = robotModelId
|
|
var expectedPath = Path.Combine(_testDirectory, "robotModelImages", $"{robotModelId}.png");
|
|
Assert.That(File.Exists(expectedPath), Is.True);
|
|
}
|
|
|
|
[Test]
|
|
public async Task GetImageAsync_ExistingImage_ReturnsStream()
|
|
{
|
|
// Arrange
|
|
var robotModelId = Guid.NewGuid();
|
|
var imageBytes = Encoding.UTF8.GetBytes("Fake PNG image data");
|
|
using var saveStream = new MemoryStream(imageBytes);
|
|
await _service.SaveImageAsync(robotModelId, saveStream);
|
|
|
|
// Act
|
|
using var result = await _service.GetImageAsync(robotModelId);
|
|
|
|
// Assert
|
|
Assert.That(result, Is.Not.Null);
|
|
Assert.That(result, Is.InstanceOf<Stream>());
|
|
Assert.That(result!.Length, Is.GreaterThan(0));
|
|
}
|
|
|
|
[Test]
|
|
public async Task GetImageAsync_NonExistentImage_ReturnsNull()
|
|
{
|
|
// Arrange
|
|
var nonExistentId = Guid.NewGuid();
|
|
|
|
// Act
|
|
var result = await _service.GetImageAsync(nonExistentId);
|
|
|
|
// Assert
|
|
Assert.That(result, Is.Null);
|
|
}
|
|
|
|
[Test]
|
|
public async Task DeleteImageAsync_ExistingImage_DeletesFile()
|
|
{
|
|
// Arrange
|
|
var robotModelId = Guid.NewGuid();
|
|
var imageBytes = Encoding.UTF8.GetBytes("Fake PNG image data");
|
|
using var saveStream = new MemoryStream(imageBytes);
|
|
await _service.SaveImageAsync(robotModelId, saveStream);
|
|
|
|
// Act
|
|
await _service.DeleteImageAsync(robotModelId);
|
|
|
|
// Assert
|
|
// StorageManager stores files in path "robotModelImages" with objectName = robotModelId
|
|
var expectedPath = Path.Combine(_testDirectory, "robotModelImages", $"{robotModelId}.png");
|
|
Assert.That(File.Exists(expectedPath), Is.False);
|
|
}
|
|
|
|
[Test]
|
|
public async Task DeleteImageAsync_NonExistentImage_DoesNotThrow()
|
|
{
|
|
// Arrange
|
|
var nonExistentId = Guid.NewGuid();
|
|
|
|
// Act & Assert - Should not throw
|
|
Assert.DoesNotThrowAsync(async () => await _service.DeleteImageAsync(nonExistentId));
|
|
}
|
|
|
|
[Test]
|
|
public async Task ImageExistsAsync_ExistingImage_ReturnsTrue()
|
|
{
|
|
// Arrange
|
|
var robotModelId = Guid.NewGuid();
|
|
var imageBytes = Encoding.UTF8.GetBytes("Fake PNG image data");
|
|
using var saveStream = new MemoryStream(imageBytes);
|
|
await _service.SaveImageAsync(robotModelId, saveStream);
|
|
|
|
// Act
|
|
var result = await _service.ImageExistsAsync(robotModelId);
|
|
|
|
// Assert
|
|
Assert.That(result, Is.True);
|
|
}
|
|
|
|
[Test]
|
|
public async Task ImageExistsAsync_NonExistentImage_ReturnsFalse()
|
|
{
|
|
// Arrange
|
|
var nonExistentId = Guid.NewGuid();
|
|
|
|
// Act
|
|
var result = await _service.ImageExistsAsync(nonExistentId);
|
|
|
|
// Assert
|
|
Assert.That(result, Is.False);
|
|
}
|
|
|
|
[Test]
|
|
public async Task GetImageDimensionsAsync_InvalidImageStream_ThrowsException()
|
|
{
|
|
// Arrange
|
|
// Note: This test uses invalid image data to verify error handling
|
|
var imageBytes = Encoding.UTF8.GetBytes("Invalid image data");
|
|
using var imageStream = new MemoryStream(imageBytes);
|
|
|
|
// Act & Assert
|
|
// Since we're using invalid image data, this should throw InvalidOperationException
|
|
// (which wraps UnknownImageFormatException from ImageSharp)
|
|
var ex = Assert.ThrowsAsync<InvalidOperationException>(async () =>
|
|
await _service.GetImageDimensionsAsync(imageStream));
|
|
Assert.That(ex!.Message, Does.Contain("Invalid image format or corrupted file"));
|
|
}
|
|
}
|