DeepDrftTests.csproj

- FileDatabase Tests
This commit is contained in:
daniel-c-harvey
2025-09-04 14:20:29 -04:00
parent c4c4662c67
commit e82366e47f
6 changed files with 876 additions and 0 deletions
+61
View File
@@ -10,31 +10,92 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeepDrftContent", "DeepDrft
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetBlocks", "C:\lib\NetBlocks\NetBlocks.csproj", "{EEB3A665-B8AD-4C00-A41E-B9D8AFE1BBA8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeepDrftTests", "DeepDrftTests\DeepDrftTests.csproj", "{47E99024-491B-47A6-BAF8-9E5814366DB2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7E629215-7EF7-465D-B7F2-2CED53C4BFEC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7E629215-7EF7-465D-B7F2-2CED53C4BFEC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7E629215-7EF7-465D-B7F2-2CED53C4BFEC}.Debug|x64.ActiveCfg = Debug|Any CPU
{7E629215-7EF7-465D-B7F2-2CED53C4BFEC}.Debug|x64.Build.0 = Debug|Any CPU
{7E629215-7EF7-465D-B7F2-2CED53C4BFEC}.Debug|x86.ActiveCfg = Debug|Any CPU
{7E629215-7EF7-465D-B7F2-2CED53C4BFEC}.Debug|x86.Build.0 = Debug|Any CPU
{7E629215-7EF7-465D-B7F2-2CED53C4BFEC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7E629215-7EF7-465D-B7F2-2CED53C4BFEC}.Release|Any CPU.Build.0 = Release|Any CPU
{7E629215-7EF7-465D-B7F2-2CED53C4BFEC}.Release|x64.ActiveCfg = Release|Any CPU
{7E629215-7EF7-465D-B7F2-2CED53C4BFEC}.Release|x64.Build.0 = Release|Any CPU
{7E629215-7EF7-465D-B7F2-2CED53C4BFEC}.Release|x86.ActiveCfg = Release|Any CPU
{7E629215-7EF7-465D-B7F2-2CED53C4BFEC}.Release|x86.Build.0 = Release|Any CPU
{E76D21B4-308B-487B-B8D6-59D6AE49F1F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E76D21B4-308B-487B-B8D6-59D6AE49F1F7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E76D21B4-308B-487B-B8D6-59D6AE49F1F7}.Debug|x64.ActiveCfg = Debug|Any CPU
{E76D21B4-308B-487B-B8D6-59D6AE49F1F7}.Debug|x64.Build.0 = Debug|Any CPU
{E76D21B4-308B-487B-B8D6-59D6AE49F1F7}.Debug|x86.ActiveCfg = Debug|Any CPU
{E76D21B4-308B-487B-B8D6-59D6AE49F1F7}.Debug|x86.Build.0 = Debug|Any CPU
{E76D21B4-308B-487B-B8D6-59D6AE49F1F7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E76D21B4-308B-487B-B8D6-59D6AE49F1F7}.Release|Any CPU.Build.0 = Release|Any CPU
{E76D21B4-308B-487B-B8D6-59D6AE49F1F7}.Release|x64.ActiveCfg = Release|Any CPU
{E76D21B4-308B-487B-B8D6-59D6AE49F1F7}.Release|x64.Build.0 = Release|Any CPU
{E76D21B4-308B-487B-B8D6-59D6AE49F1F7}.Release|x86.ActiveCfg = Release|Any CPU
{E76D21B4-308B-487B-B8D6-59D6AE49F1F7}.Release|x86.Build.0 = Release|Any CPU
{10CE5160-16C3-4CB1-9E2E-52467BA80B4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{10CE5160-16C3-4CB1-9E2E-52467BA80B4B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{10CE5160-16C3-4CB1-9E2E-52467BA80B4B}.Debug|x64.ActiveCfg = Debug|Any CPU
{10CE5160-16C3-4CB1-9E2E-52467BA80B4B}.Debug|x64.Build.0 = Debug|Any CPU
{10CE5160-16C3-4CB1-9E2E-52467BA80B4B}.Debug|x86.ActiveCfg = Debug|Any CPU
{10CE5160-16C3-4CB1-9E2E-52467BA80B4B}.Debug|x86.Build.0 = Debug|Any CPU
{10CE5160-16C3-4CB1-9E2E-52467BA80B4B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{10CE5160-16C3-4CB1-9E2E-52467BA80B4B}.Release|Any CPU.Build.0 = Release|Any CPU
{10CE5160-16C3-4CB1-9E2E-52467BA80B4B}.Release|x64.ActiveCfg = Release|Any CPU
{10CE5160-16C3-4CB1-9E2E-52467BA80B4B}.Release|x64.Build.0 = Release|Any CPU
{10CE5160-16C3-4CB1-9E2E-52467BA80B4B}.Release|x86.ActiveCfg = Release|Any CPU
{10CE5160-16C3-4CB1-9E2E-52467BA80B4B}.Release|x86.Build.0 = Release|Any CPU
{C79AFD08-02C0-45D2-A98A-FCDDFBEAE155}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C79AFD08-02C0-45D2-A98A-FCDDFBEAE155}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C79AFD08-02C0-45D2-A98A-FCDDFBEAE155}.Debug|x64.ActiveCfg = Debug|Any CPU
{C79AFD08-02C0-45D2-A98A-FCDDFBEAE155}.Debug|x64.Build.0 = Debug|Any CPU
{C79AFD08-02C0-45D2-A98A-FCDDFBEAE155}.Debug|x86.ActiveCfg = Debug|Any CPU
{C79AFD08-02C0-45D2-A98A-FCDDFBEAE155}.Debug|x86.Build.0 = Debug|Any CPU
{C79AFD08-02C0-45D2-A98A-FCDDFBEAE155}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C79AFD08-02C0-45D2-A98A-FCDDFBEAE155}.Release|Any CPU.Build.0 = Release|Any CPU
{C79AFD08-02C0-45D2-A98A-FCDDFBEAE155}.Release|x64.ActiveCfg = Release|Any CPU
{C79AFD08-02C0-45D2-A98A-FCDDFBEAE155}.Release|x64.Build.0 = Release|Any CPU
{C79AFD08-02C0-45D2-A98A-FCDDFBEAE155}.Release|x86.ActiveCfg = Release|Any CPU
{C79AFD08-02C0-45D2-A98A-FCDDFBEAE155}.Release|x86.Build.0 = Release|Any CPU
{EEB3A665-B8AD-4C00-A41E-B9D8AFE1BBA8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EEB3A665-B8AD-4C00-A41E-B9D8AFE1BBA8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EEB3A665-B8AD-4C00-A41E-B9D8AFE1BBA8}.Debug|x64.ActiveCfg = Debug|Any CPU
{EEB3A665-B8AD-4C00-A41E-B9D8AFE1BBA8}.Debug|x64.Build.0 = Debug|Any CPU
{EEB3A665-B8AD-4C00-A41E-B9D8AFE1BBA8}.Debug|x86.ActiveCfg = Debug|Any CPU
{EEB3A665-B8AD-4C00-A41E-B9D8AFE1BBA8}.Debug|x86.Build.0 = Debug|Any CPU
{EEB3A665-B8AD-4C00-A41E-B9D8AFE1BBA8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EEB3A665-B8AD-4C00-A41E-B9D8AFE1BBA8}.Release|Any CPU.Build.0 = Release|Any CPU
{EEB3A665-B8AD-4C00-A41E-B9D8AFE1BBA8}.Release|x64.ActiveCfg = Release|Any CPU
{EEB3A665-B8AD-4C00-A41E-B9D8AFE1BBA8}.Release|x64.Build.0 = Release|Any CPU
{EEB3A665-B8AD-4C00-A41E-B9D8AFE1BBA8}.Release|x86.ActiveCfg = Release|Any CPU
{EEB3A665-B8AD-4C00-A41E-B9D8AFE1BBA8}.Release|x86.Build.0 = Release|Any CPU
{47E99024-491B-47A6-BAF8-9E5814366DB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{47E99024-491B-47A6-BAF8-9E5814366DB2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{47E99024-491B-47A6-BAF8-9E5814366DB2}.Debug|x64.ActiveCfg = Debug|Any CPU
{47E99024-491B-47A6-BAF8-9E5814366DB2}.Debug|x64.Build.0 = Debug|Any CPU
{47E99024-491B-47A6-BAF8-9E5814366DB2}.Debug|x86.ActiveCfg = Debug|Any CPU
{47E99024-491B-47A6-BAF8-9E5814366DB2}.Debug|x86.Build.0 = Debug|Any CPU
{47E99024-491B-47A6-BAF8-9E5814366DB2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{47E99024-491B-47A6-BAF8-9E5814366DB2}.Release|Any CPU.Build.0 = Release|Any CPU
{47E99024-491B-47A6-BAF8-9E5814366DB2}.Release|x64.ActiveCfg = Release|Any CPU
{47E99024-491B-47A6-BAF8-9E5814366DB2}.Release|x64.Build.0 = Release|Any CPU
{47E99024-491B-47A6-BAF8-9E5814366DB2}.Release|x86.ActiveCfg = Release|Any CPU
{47E99024-491B-47A6-BAF8-9E5814366DB2}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
+27
View File
@@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="NUnit" Version="4.2.2" />
<PackageReference Include="NUnit.Analyzers" Version="4.4.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
</ItemGroup>
<ItemGroup>
<Using Include="NUnit.Framework" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\DeepDrftContent\DeepDrftContent.csproj" />
</ItemGroup>
</Project>
+229
View File
@@ -0,0 +1,229 @@
using DeepDrftContent.FileDatabase.Models;
using DeepDrftContent.FileDatabase.Services;
namespace DeepDrftTests;
/// <summary>
/// Tests for FileDatabase functionality, ported from TypeScript tests
/// </summary>
[TestFixture]
public class FileDatabaseTests
{
private string _testDatabasePath = null!;
private FileDatabase? _fileDatabase;
[SetUp]
public void SetUp()
{
// Create a unique test directory for each test
_testDatabasePath = Path.Combine(Path.GetTempPath(), "DeepDrftTests", Guid.NewGuid().ToString());
// Clean up any existing test directory
if (Directory.Exists(_testDatabasePath))
{
Directory.Delete(_testDatabasePath, true);
}
// Ensure the directory exists
Directory.CreateDirectory(_testDatabasePath);
}
[TearDown]
public void TearDown()
{
// Clean up test directory
if (Directory.Exists(_testDatabasePath))
{
try
{
Directory.Delete(_testDatabasePath, true);
}
catch
{
// Ignore cleanup errors
}
}
}
[Test]
public async Task FileDatabase_CanBeCreatedAtSpecifiedLocation()
{
// Act
_fileDatabase = await FileDatabase.FromAsync(_testDatabasePath);
// Assert
Assert.That(_fileDatabase, Is.Not.Null, "FileDatabase should not be null");
Assert.That(_fileDatabase.GetIndexSize(), Is.EqualTo(0), "Index should be empty initially");
}
[Test]
public async Task FileDatabase_CanAddNewVaultForImages()
{
// Arrange
_fileDatabase = await FileDatabase.FromAsync(_testDatabasePath);
Assert.That(_fileDatabase, Is.Not.Null);
// Act
await _fileDatabase.CreateVaultAsync(TestData.TestKeys.ImageVaultKey);
// Assert
Assert.That(_fileDatabase.GetIndexSize(), Is.EqualTo(1), "Index should contain one element");
var vaultDirectory = Path.Combine(_testDatabasePath, TestData.TestKeys.ImageVaultKey.Key);
Assert.That(Directory.Exists(vaultDirectory), Is.True, "Vault directory should exist");
}
[Test]
public async Task FileDatabase_CanAddNewMediaToImageVault()
{
// Arrange
_fileDatabase = await FileDatabase.FromAsync(_testDatabasePath);
Assert.That(_fileDatabase, Is.Not.Null);
await _fileDatabase.CreateVaultAsync(TestData.TestKeys.ImageVaultKey);
var testImage = TestData.CreateTestImageBinary(1.0);
// Act
await _fileDatabase.RegisterResourceAsync(
MediaVaultType.Image,
TestData.TestKeys.ImageVaultKey,
TestData.TestKeys.TestImageEntry,
testImage);
// Assert
var vault = _fileDatabase.GetVault(TestData.TestKeys.ImageVaultKey);
Assert.That(vault, Is.Not.Null, "Vault should not be null");
Assert.That(vault!.HasIndexEntry(TestData.TestKeys.TestImageEntry), Is.True,
"Added image should be in the index");
}
[Test]
public async Task FileDatabase_CanLoadValidResourceFromVault()
{
// Arrange
_fileDatabase = await FileDatabase.FromAsync(_testDatabasePath);
Assert.That(_fileDatabase, Is.Not.Null);
await _fileDatabase.CreateVaultAsync(TestData.TestKeys.ImageVaultKey);
var testImage = TestData.CreateTestImageBinary(1.0);
await _fileDatabase.RegisterResourceAsync(
MediaVaultType.Image,
TestData.TestKeys.ImageVaultKey,
TestData.TestKeys.TestImageEntry,
testImage);
// Act
var loadedMedia = await _fileDatabase.LoadResourceAsync<ImageBinary>(
MediaVaultType.Image,
TestData.TestKeys.ImageVaultKey,
TestData.TestKeys.TestImageEntry);
// Assert
Assert.That(loadedMedia, Is.Not.Null, "Loaded media should not be null");
AssertValidImageResource(loadedMedia!);
}
[Test]
public async Task FileDatabase_DeniesAccessToNonexistentVault()
{
// Arrange
_fileDatabase = await FileDatabase.FromAsync(_testDatabasePath);
Assert.That(_fileDatabase, Is.Not.Null);
// Act & Assert - Should not throw exception but return null/default
var vault = _fileDatabase.GetVault(TestData.TestKeys.NonExistentVaultKey);
Assert.That(vault, Is.Null, "Nonexistent vault should return null");
// Loading from nonexistent vault should not throw but handle gracefully
Assert.DoesNotThrowAsync(async () =>
{
await _fileDatabase.LoadResourceAsync<ImageBinary>(
MediaVaultType.Image,
TestData.TestKeys.NonExistentVaultKey,
TestData.TestKeys.NonExistentEntryKey);
}, "Should not throw exceptions when accessing nonexistent vault");
}
[Test]
public async Task FileDatabase_DeniesAccessToNonexistentResource()
{
// Arrange
_fileDatabase = await FileDatabase.FromAsync(_testDatabasePath);
Assert.That(_fileDatabase, Is.Not.Null);
await _fileDatabase.CreateVaultAsync(TestData.TestKeys.ImageVaultKey);
// Act & Assert - Should not throw exception when accessing nonexistent resource
Assert.DoesNotThrowAsync(async () =>
{
await _fileDatabase.LoadResourceAsync<ImageBinary>(
MediaVaultType.Image,
TestData.TestKeys.ImageVaultKey,
TestData.TestKeys.NonExistentEntryKey);
}, "Should not throw exceptions when accessing nonexistent resource");
}
[Test]
public async Task FileDatabase_CanBeReloadedFromSecondaryMemory()
{
// Arrange - Create and populate a database
_fileDatabase = await FileDatabase.FromAsync(_testDatabasePath);
Assert.That(_fileDatabase, Is.Not.Null);
await _fileDatabase.CreateVaultAsync(TestData.TestKeys.ImageVaultKey);
var testImage = TestData.CreateTestImageBinary(1.0);
await _fileDatabase.RegisterResourceAsync(
MediaVaultType.Image,
TestData.TestKeys.ImageVaultKey,
TestData.TestKeys.TestImageEntry,
testImage);
// Act - Reload the database from the same path
var reloadedDatabase = await FileDatabase.FromAsync(_testDatabasePath);
// Assert
Assert.That(reloadedDatabase, Is.Not.Null, "Reloaded database should not be null");
Assert.That(reloadedDatabase.GetIndexSize(), Is.EqualTo(1), "Index count should be 1");
// Verify vault exists
Assert.That(reloadedDatabase.HasIndexEntry(TestData.TestKeys.ImageVaultKey), Is.True,
"Vault should be present in index");
Assert.That(reloadedDatabase.HasVault(TestData.TestKeys.ImageVaultKey), Is.True,
"Vault should be present in vault collection");
var vault = reloadedDatabase.GetVault(TestData.TestKeys.ImageVaultKey);
Assert.That(vault, Is.Not.Null, "Vault should not be null");
// Verify resource can be loaded
var loadedMedia = await reloadedDatabase.LoadResourceAsync<ImageBinary>(
MediaVaultType.Image,
TestData.TestKeys.ImageVaultKey,
TestData.TestKeys.TestImageEntry);
Assert.That(loadedMedia, Is.Not.Null, "Loaded media should not be null");
AssertValidImageResource(loadedMedia!);
}
/// <summary>
/// Helper method to validate an ImageBinary resource matches test expectations
/// </summary>
private static void AssertValidImageResource(ImageBinary media)
{
Assert.That(media, Is.Not.Null, "Image package should not be null");
Assert.That(media.Size, Is.GreaterThan(0), "Image size should be greater than 0");
Assert.That(media.Buffer.Length, Is.EqualTo(TestData.TestPngBytes.Length),
"Number of bytes should match test data");
// Verify byte-by-byte equality
for (int i = 0; i < media.Buffer.Length; i++)
{
Assert.That(media.Buffer[i], Is.EqualTo(TestData.TestPngBytes[i]),
$"Byte at index {i} should be equal");
}
Assert.That(media.Extension, Is.EqualTo(".png"), "Extension should be .png");
Assert.That(media.AspectRatio, Is.EqualTo(1.0).Within(0.001), "Aspect ratio should be 1.0");
}
}
+255
View File
@@ -0,0 +1,255 @@
using DeepDrftContent.FileDatabase.Models;
namespace DeepDrftTests;
/// <summary>
/// Tests for model classes and data structures
/// </summary>
[TestFixture]
public class ModelTests
{
[TestFixture]
public class EntryKeyTests
{
[Test]
public void EntryKey_CanBeCreated()
{
// Arrange
var key = "test-key";
var type = MediaVaultType.Image;
// Act
var entryKey = new EntryKey(key, type);
// Assert
Assert.That(entryKey.Key, Is.EqualTo(key), "Key should match");
Assert.That(entryKey.Type, Is.EqualTo(type), "Type should match");
}
[Test]
public void EntryKey_SupportsStructuralEquality()
{
// Arrange
var key1 = new EntryKey("test", MediaVaultType.Image);
var key2 = new EntryKey("test", MediaVaultType.Image);
var key3 = new EntryKey("different", MediaVaultType.Image);
// Act & Assert
Assert.That(key1, Is.EqualTo(key2), "Structurally equal keys should be equal");
Assert.That(key1, Is.Not.EqualTo(key3), "Different keys should not be equal");
Assert.That(key1.GetHashCode(), Is.EqualTo(key2.GetHashCode()), "Equal keys should have same hash code");
}
}
[TestFixture]
public class MediaModelTests
{
[Test]
public void FileBinary_CanBeCreated()
{
// Arrange
var buffer = TestData.TestPngBytes;
var size = buffer.Length;
var parameters = new FileBinaryParams(buffer, size);
// Act
var fileBinary = new FileBinary(parameters);
// Assert
Assert.That(fileBinary.Buffer, Is.EqualTo(buffer), "Buffer should match");
Assert.That(fileBinary.Size, Is.EqualTo(size), "Size should match");
}
[Test]
public void FileBinary_CanBeCreatedFromDto()
{
// Arrange
var originalBuffer = TestData.TestPngBytes;
var base64Data = Convert.ToBase64String(originalBuffer);
var dto = new FileBinaryDto(base64Data, originalBuffer.Length);
// Act
var fileBinary = FileBinary.From(dto);
// Assert
Assert.That(fileBinary.Size, Is.EqualTo(originalBuffer.Length), "Size should match");
Assert.That(fileBinary.Buffer, Is.EqualTo(originalBuffer), "Buffer should match original");
}
[Test]
public void MediaBinary_CanBeCreated()
{
// Arrange
var buffer = TestData.TestPngBytes;
var size = buffer.Length;
var extension = ".png";
var parameters = new MediaBinaryParams(buffer, size, extension);
// Act
var mediaBinary = new MediaBinary(parameters);
// Assert
Assert.That(mediaBinary.Buffer, Is.EqualTo(buffer), "Buffer should match");
Assert.That(mediaBinary.Size, Is.EqualTo(size), "Size should match");
Assert.That(mediaBinary.Extension, Is.EqualTo(extension), "Extension should match");
}
[Test]
public void ImageBinary_CanBeCreated()
{
// Arrange
var buffer = TestData.TestPngBytes;
var size = buffer.Length;
var extension = ".png";
var aspectRatio = 1.5;
var parameters = new ImageBinaryParams(buffer, size, extension, aspectRatio);
// Act
var imageBinary = new ImageBinary(parameters);
// Assert
Assert.That(imageBinary.Buffer, Is.EqualTo(buffer), "Buffer should match");
Assert.That(imageBinary.Size, Is.EqualTo(size), "Size should match");
Assert.That(imageBinary.Extension, Is.EqualTo(extension), "Extension should match");
Assert.That(imageBinary.AspectRatio, Is.EqualTo(aspectRatio), "Aspect ratio should match");
}
[Test]
public void ImageBinary_CanBeCreatedFromDto()
{
// Arrange
var originalBuffer = TestData.TestPngBytes;
var base64Data = Convert.ToBase64String(originalBuffer);
var dto = new ImageBinaryDto(base64Data, originalBuffer.Length, "image/png", 1.0);
// Act
var imageBinary = ImageBinary.From(dto);
// Assert
Assert.That(imageBinary.Size, Is.EqualTo(originalBuffer.Length), "Size should match");
Assert.That(imageBinary.Buffer, Is.EqualTo(originalBuffer), "Buffer should match original");
Assert.That(imageBinary.Extension, Is.EqualTo(".png"), "Extension should match");
Assert.That(imageBinary.AspectRatio, Is.EqualTo(1.0), "Aspect ratio should match");
}
[Test]
public void ImageBinaryDto_CanBeCreatedFromImageBinary()
{
// Arrange
var imageBinary = TestData.CreateTestImageBinary(1.5);
// Act
var dto = new ImageBinaryDto(imageBinary);
// Assert
Assert.That(dto.Size, Is.EqualTo(imageBinary.Size), "Size should match");
Assert.That(dto.Mime, Is.EqualTo(MimeTypeExtensions.GetMimeType(imageBinary.Extension)), "MIME type should match");
Assert.That(dto.AspectRatio, Is.EqualTo(imageBinary.AspectRatio), "Aspect ratio should match");
// Verify base64 encoding
var decodedBuffer = Convert.FromBase64String(dto.Base64);
Assert.That(decodedBuffer, Is.EqualTo(imageBinary.Buffer), "Decoded buffer should match original");
}
}
[TestFixture]
public class MetaDataTests
{
[Test]
public void MetaData_CanBeCreated()
{
// Arrange
var key = "test-key";
var extension = ".png";
// Act
var metaData = new MetaData(key, extension);
// Assert
Assert.That(metaData.MediaKey, Is.EqualTo(key), "MediaKey should match");
Assert.That(metaData.Extension, Is.EqualTo(extension), "Extension should match");
}
[Test]
public void ImageMetaData_CanBeCreated()
{
// Arrange
var key = "test-image";
var extension = ".jpg";
var aspectRatio = 1.77;
// Act
var imageMetaData = new ImageMetaData(key, extension, aspectRatio);
// Assert
Assert.That(imageMetaData.MediaKey, Is.EqualTo(key), "MediaKey should match");
Assert.That(imageMetaData.Extension, Is.EqualTo(extension), "Extension should match");
Assert.That(imageMetaData.AspectRatio, Is.EqualTo(aspectRatio), "Aspect ratio should match");
}
[Test]
public void MetaDataFactory_CreatesCorrectTypes()
{
// Arrange
var key = "test";
var extension = ".png";
var aspectRatio = 2.0;
// Act
var mediaMetaData = MetaDataFactory.Create(MediaVaultType.Media, key, extension, 0.0);
var imageMetaData = MetaDataFactory.Create(MediaVaultType.Image, key, extension, aspectRatio);
// Assert
Assert.That(mediaMetaData, Is.TypeOf<MetaData>(), "Should create MetaData for Media type");
Assert.That(imageMetaData, Is.TypeOf<ImageMetaData>(), "Should create ImageMetaData for Image type");
var typedImageMetaData = (ImageMetaData)imageMetaData;
Assert.That(typedImageMetaData.AspectRatio, Is.EqualTo(aspectRatio), "Aspect ratio should be set");
}
}
[TestFixture]
public class MediaFactoryTests
{
[Test]
public void MediaBinaryFactory_CreatesCorrectTypes()
{
// Arrange
var buffer = TestData.TestPngBytes;
var size = buffer.Length;
var extension = ".png";
// Act
var mediaParams = new MediaBinaryParams(buffer, size, extension);
var imageParams = new ImageBinaryParams(buffer, size, extension, 1.0);
var mediaBinary = FileBinaryFactory.Create(MediaVaultType.Media, mediaParams);
var imageBinary = FileBinaryFactory.Create(MediaVaultType.Image, imageParams);
// Assert
Assert.That(mediaBinary, Is.TypeOf<MediaBinary>(), "Should create MediaBinary for Media type");
Assert.That(imageBinary, Is.TypeOf<ImageBinary>(), "Should create ImageBinary for Image type");
var typedImageBinary = (ImageBinary)imageBinary;
Assert.That(typedImageBinary.AspectRatio, Is.EqualTo(1.0), "Aspect ratio should be set");
}
[Test]
public void MediaBinaryFactory_ThrowsForInvalidType()
{
// Arrange
var buffer = TestData.TestPngBytes;
var size = buffer.Length;
var extension = ".png";
var invalidType = (MediaVaultType)999;
// Act & Assert
var invalidParams = new MediaBinaryParams(buffer, size, extension);
Assert.Throws<ArgumentException>(() =>
{
FileBinaryFactory.Create(invalidType, invalidParams);
}, "Should throw for invalid media vault type");
}
}
}
+52
View File
@@ -0,0 +1,52 @@
using DeepDrftContent.FileDatabase.Models;
namespace DeepDrftTests;
/// <summary>
/// Test data and helper methods for FileDatabase tests
/// </summary>
public static class TestData
{
/// <summary>
/// Test PNG image bytes (16x16 pixel test image)
/// </summary>
public static readonly byte[] TestPngBytes =
[
137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255,97,0,0,2,8,73,68,65,84,56,203,61,144,59,142,28,71,16,5,163,42,95,254,186,103,185,182,100,233,34,188,255,13,116,0,57,50,36,136,132,86,208,252,187,105,244,112,141,0,10,168,202,120,47,107,12,255,117,127,151,243,238,193,23,79,78,158,172,30,156,34,89,221,63,121,11,231,45,130,85,226,45,156,245,133,84,65,41,88,60,41,79,42,146,142,36,37,202,157,114,167,93,44,17,148,59,75,56,229,162,195,89,66,104,205,100,81,146,94,100,36,25,65,122,80,210,241,208,197,226,241,57,176,132,179,186,88,226,184,211,26,69,69,145,241,18,184,31,152,81,46,22,119,58,244,226,72,175,16,237,199,89,89,141,103,99,158,120,36,225,78,201,104,25,139,139,118,99,137,67,242,51,181,253,144,151,59,82,47,140,108,70,20,195,19,73,132,77,74,147,142,73,135,209,110,116,56,29,70,73,164,139,140,99,69,61,151,230,81,43,215,104,206,42,78,22,164,61,105,219,233,216,233,16,229,131,138,73,134,145,18,41,163,234,144,234,122,42,182,116,238,17,92,50,56,231,23,108,44,252,114,255,155,37,110,116,12,50,94,130,87,245,116,35,195,201,16,186,182,177,229,100,203,13,234,201,165,190,243,71,125,112,169,255,248,122,189,179,142,70,74,36,144,6,18,71,147,112,50,133,110,109,88,14,72,176,222,176,20,214,131,71,173,252,254,126,229,60,225,55,118,122,3,38,184,12,133,161,152,40,28,109,109,108,49,25,101,140,50,172,133,149,177,231,228,82,193,95,177,99,115,199,24,36,147,155,193,110,131,41,3,159,232,94,162,202,217,83,108,37,248,196,120,150,113,139,39,31,190,243,167,6,49,141,192,56,153,193,52,144,161,75,137,46,103,235,128,20,148,51,90,140,114,246,156,220,3,46,1,231,24,252,163,65,75,244,16,235,48,22,51,68,59,143,242,35,189,3,202,217,211,217,75,108,105,60,115,242,204,201,45,7,255,199,224,187,79,150,57,89,205,169,97,232,231,208,172,96,235,96,79,135,118,246,16,123,138,61,141,189,140,71,78,110,101,156,125,240,175,15,190,233,104,33,218,121,118,176,101,48,94,130,45,197,94,130,116,40,177,229,241,47,91,192,163,156,75,76,62,124,240,109,12,126,0,211,140,106,253,37,95,60,102,0,0,0,0,73,69,78,68,174,66,96,130
];
/// <summary>
/// Creates a test ImageBinary with the test PNG data
/// </summary>
/// <param name="aspectRatio">The aspect ratio for the image</param>
/// <returns>An ImageBinary instance with test data</returns>
public static ImageBinary CreateTestImageBinary(double aspectRatio = 1.0)
{
var parameters = new ImageBinaryParams(
Buffer: TestPngBytes,
Size: TestPngBytes.Length,
Extension: ".png",
AspectRatio: aspectRatio
);
return new ImageBinary(parameters);
}
/// <summary>
/// Test entry keys used across tests
/// </summary>
public static class TestKeys
{
public static readonly EntryKey TestImageEntry = new("test", MediaVaultType.Image);
public static readonly EntryKey ImageVaultKey = new("img", MediaVaultType.Image);
public static readonly EntryKey NonExistentVaultKey = new("i-do-not-exist", MediaVaultType.Image);
public static readonly EntryKey NonExistentEntryKey = new("i-do-not-exist", MediaVaultType.Image);
}
/// <summary>
/// Test file names
/// </summary>
public static class TestFiles
{
public const string TestPngName = "test.png";
}
}
+252
View File
@@ -0,0 +1,252 @@
using DeepDrftContent.FileDatabase.Models;
using DeepDrftContent.FileDatabase.Utils;
namespace DeepDrftTests;
/// <summary>
/// Tests for utility classes like StructuralMap and StructuralSet
/// </summary>
[TestFixture]
public class UtilityTests
{
[TestFixture]
public class StructuralMapTests
{
[Test]
public void StructuralMap_CanAddAndRetrieveEntries()
{
// Arrange
var map = new StructuralMap<EntryKey, string>();
var key = new EntryKey("test", MediaVaultType.Image);
var value = "test-value";
// Act
map.Set(key, value);
// Assert
Assert.That(map.Has(key), Is.True, "Map should contain the key");
Assert.That(map.Get(key), Is.EqualTo(value), "Retrieved value should match");
Assert.That(map.Size, Is.EqualTo(1), "Map should have one entry");
}
[Test]
public void StructuralMap_HandlesStructuralEquality()
{
// Arrange
var map = new StructuralMap<EntryKey, string>();
var key1 = new EntryKey("test", MediaVaultType.Image);
var key2 = new EntryKey("test", MediaVaultType.Image); // Same values, different instance
var value = "test-value";
// Act
map.Set(key1, value);
// Assert
Assert.That(map.Has(key2), Is.True, "Map should use structural equality");
Assert.That(map.Get(key2), Is.EqualTo(value), "Should retrieve value using structurally equal key");
}
[Test]
public void StructuralMap_CanRemoveEntries()
{
// Arrange
var map = new StructuralMap<EntryKey, string>();
var key = new EntryKey("test", MediaVaultType.Image);
var value = "test-value";
map.Set(key, value);
// Act
var removed = map.Delete(key);
// Assert
Assert.That(removed, Is.True, "Delete should return true");
Assert.That(map.Has(key), Is.False, "Map should not contain the key after removal");
Assert.That(map.Size, Is.EqualTo(0), "Map should be empty");
}
[Test]
public void StructuralMap_CanEnumerateEntries()
{
// Arrange
var map = new StructuralMap<EntryKey, string>();
var entries = new[]
{
(new EntryKey("key1", MediaVaultType.Image), "value1"),
(new EntryKey("key2", MediaVaultType.Media), "value2"),
(new EntryKey("key3", MediaVaultType.Image), "value3")
};
foreach (var (key, value) in entries)
{
map.Set(key, value);
}
// Act
var retrievedEntries = map.ToList();
// Assert
Assert.That(retrievedEntries.Count, Is.EqualTo(3), "Should enumerate all entries");
foreach (var (key, value) in entries)
{
Assert.That(retrievedEntries.Any(kvp => kvp.Key.Equals(key) && kvp.Value == value),
Is.True, $"Should contain entry ({key}, {value})");
}
}
}
[TestFixture]
public class StructuralSetTests
{
[Test]
public void StructuralSet_CanAddAndContainEntries()
{
// Arrange
var set = new StructuralSet<EntryKey>();
var key = new EntryKey("test", MediaVaultType.Image);
// Act
set.Add(key);
// Assert
Assert.That(set.Has(key), Is.True, "Set should contain the key");
Assert.That(set.Size, Is.EqualTo(1), "Set should have one entry");
}
[Test]
public void StructuralSet_HandlesStructuralEquality()
{
// Arrange
var set = new StructuralSet<EntryKey>();
var key1 = new EntryKey("test", MediaVaultType.Image);
var key2 = new EntryKey("test", MediaVaultType.Image); // Same values, different instance
// Act
set.Add(key1);
set.Add(key2);
// Assert
Assert.That(set.Has(key2), Is.True, "Should contain structurally equal key");
Assert.That(set.Size, Is.EqualTo(1), "Set should still have only one entry due to structural equality");
}
[Test]
public void StructuralSet_CanRemoveEntries()
{
// Arrange
var set = new StructuralSet<EntryKey>();
var key = new EntryKey("test", MediaVaultType.Image);
set.Add(key);
// Act
var removed = set.Delete(key);
// Assert
Assert.That(removed, Is.True, "Delete should return true");
Assert.That(set.Has(key), Is.False, "Set should not contain the key after removal");
Assert.That(set.Size, Is.EqualTo(0), "Set should be empty");
}
[Test]
public void StructuralSet_CanEnumerateEntries()
{
// Arrange
var set = new StructuralSet<EntryKey>();
var keys = new[]
{
new EntryKey("key1", MediaVaultType.Image),
new EntryKey("key2", MediaVaultType.Media),
new EntryKey("key3", MediaVaultType.Image)
};
foreach (var key in keys)
{
set.Add(key);
}
// Act
var retrievedKeys = set.ToList();
// Assert
Assert.That(retrievedKeys.Count, Is.EqualTo(3), "Should enumerate all entries");
foreach (var key in keys)
{
Assert.That(retrievedKeys.Contains(key), Is.True, $"Should contain key {key}");
}
}
}
[TestFixture]
public class FileUtilsTests
{
private string _testDirectory = null!;
[SetUp]
public void SetUp()
{
_testDirectory = Path.Combine(Path.GetTempPath(), "DeepDrftTests", "FileUtils", Guid.NewGuid().ToString());
Directory.CreateDirectory(_testDirectory);
}
[TearDown]
public void TearDown()
{
if (Directory.Exists(_testDirectory))
{
Directory.Delete(_testDirectory, true);
}
}
[Test]
public async Task FileUtils_CanWriteAndReadFile()
{
// Arrange
var testFile = Path.Combine(_testDirectory, "test.dat");
var testData = TestData.TestPngBytes;
// Act
await FileUtils.PutFileAsync(testFile, testData);
var fileBinary = await FileUtils.FetchFileAsync(testFile);
// Assert
Assert.That(File.Exists(testFile), Is.True, "File should exist after writing");
Assert.That(fileBinary, Is.Not.Null, "FileBinary should not be null");
Assert.That(fileBinary.Buffer.Length, Is.EqualTo(testData.Length), "Read data length should match");
for (int i = 0; i < testData.Length; i++)
{
Assert.That(fileBinary.Buffer[i], Is.EqualTo(testData[i]), $"Byte at index {i} should match");
}
}
[Test]
public async Task FileUtils_CanWriteAndReadJson()
{
// Arrange
var testFile = Path.Combine(_testDirectory, "test.json");
var testObject = new { Name = "Test", Value = 42, IsActive = true };
// Act
await FileUtils.PutObjectAsync(testFile, testObject);
var readObject = await FileUtils.FetchObjectAsync<dynamic>(testFile);
// Assert
Assert.That(File.Exists(testFile), Is.True, "JSON file should exist after writing");
Assert.That(readObject, Is.Not.Null, "Read object should not be null");
}
[Test]
public void FileUtils_HandlesNonExistentFile()
{
// Arrange
var nonExistentFile = Path.Combine(_testDirectory, "does-not-exist.dat");
// Act & Assert
Assert.ThrowsAsync<FileNotFoundException>(async () =>
{
await FileUtils.FetchFileAsync(nonExistentFile);
}, "Should throw FileNotFoundException for non-existent file");
}
}
}