using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using RobotNet10.FleetManager.Services; using RobotNet10.StorageManager; using System.Text; namespace RobotNet10.RobotManager.Test.Services; /// /// Unit tests for RobotModelImageStorageService /// [TestFixture] public class RobotModelImageStorageServiceTests { private string _testDirectory = null!; private RobotModelImageStorageService _service = null!; private IOptionsMonitor _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 var mockOptionsMonitor = new Moq.Mock>(); mockOptionsMonitor.Setup(m => m.Get("RobotModelImages")).Returns(storageConfig); _optionsMonitor = mockOptionsMonitor.Object; var logger = new LoggerFactory().CreateLogger(); _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()); 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(async () => await _service.GetImageDimensionsAsync(imageStream)); Assert.That(ex!.Message, Does.Contain("Invalid image format or corrupted file")); } }