diff --git a/Aaru.Tests/Images/A2R.cs b/Aaru.Tests/Images/A2R.cs new file mode 100644 index 000000000..04ee7f0be --- /dev/null +++ b/Aaru.Tests/Images/A2R.cs @@ -0,0 +1,202 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : A2R.cs +// Author(s) : Rebecca Wallander +// +// Component : Aaru unit testing. +// +// --[ License ] -------------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2026 Rebecca Wallander +// ****************************************************************************/ + +using System.IO; +using Aaru.CommonTypes.Interfaces; +using NUnit.Framework; + +namespace Aaru.Tests.Images; + +[TestFixture] +public class A2R : FluxMediaImageTest +{ + public override string DataFolder => Path.Combine(Consts.TestFilesRoot, "Media image formats", "A2R"); + public override IMediaImage Plugin => new Aaru.Images.A2R(); + + public override FluxImageTestExpected[] Tests => + [ + new() + { + TestFile = "The Quest.a2r", + FluxCaptureCount = 162, + FluxCaptures = [ + new FluxCaptureTestExpected + { + Head = 0, + Track = 0, + SubTrack = 0, + CaptureIndex = 0, + IndexResolution = 62500, + DataResolution = 62500 + }, + new FluxCaptureTestExpected + { + Head = 0, + Track = 0, + SubTrack = 0, + CaptureIndex = 1, + IndexResolution = 62500, + DataResolution = 62500 + }, + new FluxCaptureTestExpected + { + Head = 0, + Track = 1, + SubTrack = 0, + CaptureIndex = 0, + IndexResolution = 62500, + DataResolution = 62500 + }, + new FluxCaptureTestExpected + { + Head = 0, + Track = 1, + SubTrack = 0, + CaptureIndex = 1, + IndexResolution = 62500, + DataResolution = 62500 + }, + new FluxCaptureTestExpected + { + Head = 0, + Track = 1, + SubTrack = 0, + CaptureIndex = 2, + IndexResolution = 62500, + DataResolution = 62500 + }, + new FluxCaptureTestExpected + { + Head = 0, + Track = 1, + SubTrack = 0, + CaptureIndex = 3, + IndexResolution = 62500, + DataResolution = 62500 + }, + ] + }, + new() + { + TestFile = "Lotus 1-2-3 v2 - Utility Disk.a2r", + FluxCaptureCount = 320, + FluxCaptures = [ + new FluxCaptureTestExpected + { + Head = 0, + Track = 0, + SubTrack = 0, + CaptureIndex = 0, + IndexResolution = 62500, + DataResolution = 62500 + }, + new FluxCaptureTestExpected + { + Head = 0, + Track = 0, + SubTrack = 0, + CaptureIndex = 1, + IndexResolution = 62500, + DataResolution = 62500 + }, + new FluxCaptureTestExpected + { + Head = 0, + Track = 0, + SubTrack = 0, + CaptureIndex = 2, + IndexResolution = 62500, + DataResolution = 62500 + }, + new FluxCaptureTestExpected + { + Head = 1, + Track = 0, + SubTrack = 0, + CaptureIndex = 0, + IndexResolution = 62500, + DataResolution = 62500 + }, + new FluxCaptureTestExpected + { + Head = 1, + Track = 0, + SubTrack = 0, + CaptureIndex = 1, + IndexResolution = 62500, + DataResolution = 62500 + }, + new FluxCaptureTestExpected + { + Head = 1, + Track = 0, + SubTrack = 0, + CaptureIndex = 2, + IndexResolution = 62500, + DataResolution = 62500 + }, + new FluxCaptureTestExpected + { + Head = 1, + Track = 1, + SubTrack = 0, + CaptureIndex = 0, + IndexResolution = 62500, + DataResolution = 62500 + }, + new FluxCaptureTestExpected + { + Head = 0, + Track = 2, + SubTrack = 0, + CaptureIndex = 0, + IndexResolution = 62500, + DataResolution = 62500 + }, + new FluxCaptureTestExpected + { + Head = 0, + Track = 2, + SubTrack = 0, + CaptureIndex = 1, + IndexResolution = 62500, + DataResolution = 62500 + }, + new FluxCaptureTestExpected + { + Head = 0, + Track = 2, + SubTrack = 0, + CaptureIndex = 2, + IndexResolution = 62500, + DataResolution = 62500 + }, + ] + }, + ]; +} diff --git a/Aaru.Tests/Images/AaruFormat/V2Flux.cs b/Aaru.Tests/Images/AaruFormat/V2Flux.cs new file mode 100644 index 000000000..2c284e4d4 --- /dev/null +++ b/Aaru.Tests/Images/AaruFormat/V2Flux.cs @@ -0,0 +1,105 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : V2Flux.cs +// Author(s) : Rebecca Wallander +// +// Component : Aaru unit testing. +// +// --[ License ] -------------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2026 Rebecca Wallander +// ****************************************************************************/ + +using System.IO; +using Aaru.CommonTypes.Interfaces; +using NUnit.Framework; + +namespace Aaru.Tests.Images.AaruFormat; + +[TestFixture] +public class V2Flux : FluxMediaImageTest +{ + public override string DataFolder => Path.Combine(Consts.TestFilesRoot, "Media image formats", "AaruFormat", "V2", "Flux"); + public override IMediaImage Plugin => new Aaru.Images.AaruFormat(); + + public override FluxImageTestExpected[] Tests => + [ + new() + { + TestFile = "dos_1.25_release_a - Disk 1.aif", + FluxCaptureCount = 320, + FluxCaptures = [ + new FluxCaptureTestExpected + { + Head = 0, + Track = 0, + SubTrack = 0, + CaptureIndex = 0, + IndexResolution = 125000, + DataResolution = 125000 + }, + new FluxCaptureTestExpected + { + Head = 0, + Track = 0, + SubTrack = 0, + CaptureIndex = 1, + IndexResolution = 125000, + DataResolution = 125000 + }, + new FluxCaptureTestExpected + { + Head = 0, + Track = 0, + SubTrack = 0, + CaptureIndex = 2, + IndexResolution = 125000, + DataResolution = 125000 + }, + new FluxCaptureTestExpected + { + Head = 1, + Track = 0, + SubTrack = 0, + CaptureIndex = 0, + IndexResolution = 125000, + DataResolution = 125000 + }, + new FluxCaptureTestExpected + { + Head = 1, + Track = 0, + SubTrack = 0, + CaptureIndex = 1, + IndexResolution = 125000, + DataResolution = 125000 + }, + new FluxCaptureTestExpected + { + Head = 1, + Track = 0, + SubTrack = 0, + CaptureIndex = 2, + IndexResolution = 125000, + DataResolution = 125000 + }, + ] + } + ]; +} \ No newline at end of file diff --git a/Aaru.Tests/Images/FluxMediaImageTest.cs b/Aaru.Tests/Images/FluxMediaImageTest.cs new file mode 100644 index 000000000..af898c68c --- /dev/null +++ b/Aaru.Tests/Images/FluxMediaImageTest.cs @@ -0,0 +1,188 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : FluxMediaImageTest.cs +// Author(s) : Rebecca Wallander +// +// Component : Aaru unit testing. +// +// --[ License ] -------------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2026 Rebecca Wallander +// ****************************************************************************/ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Aaru.CommonTypes; +using Aaru.CommonTypes.Enums; +using Aaru.CommonTypes.Interfaces; +using Aaru.CommonTypes.Structs; +using Aaru.Core; +using FluentAssertions; +using NUnit.Framework; + +namespace Aaru.Tests.Images; + +public abstract class FluxMediaImageTest : BaseMediaImageTest +{ + public abstract FluxImageTestExpected[] Tests { get; } + + [OneTimeSetUp] + public void InitTest() => PluginBase.Init(); + + [Test] + public void Info() + { + Environment.CurrentDirectory = DataFolder; + + Assert.Multiple(() => + { + foreach(FluxImageTestExpected test in Tests) + { + string testFile = test.TestFile; + + bool exists = File.Exists(testFile); + Assert.That(exists, string.Format(Localization._0_not_found, testFile)); + + // ReSharper disable once ConditionIsAlwaysTrueOrFalse + // It arrives here... + if(!exists) continue; + + IFilter filter = PluginRegister.Singleton.GetFilter(testFile); + filter.Open(testFile); + + var image = Activator.CreateInstance(Plugin.GetType()) as IMediaImage; + + Assert.That(image, + Is.Not.Null, + string.Format(Localization.Could_not_instantiate_filesystem_for_0, testFile)); + + ErrorNumber opened = image.Open(filter); + Assert.That(opened, Is.EqualTo(ErrorNumber.NoError), string.Format(Localization.Open_0, testFile)); + + if(opened != ErrorNumber.NoError) continue; + + if(image is not IFluxImage fluxImage) + { + Assert.Fail($"Image {testFile} does not implement IFluxImage"); + continue; + } + + ErrorNumber error = fluxImage.GetAllFluxCaptures(out List captures); + + Assert.That(error, Is.EqualTo(ErrorNumber.NoError), $"GetAllFluxCaptures failed with {error}"); + Assert.That(captures, Is.Not.Null, "GetAllFluxCaptures returned null"); + Assert.That(captures, Is.Not.Empty, "GetAllFluxCaptures returned empty list"); + + Assert.That(captures.Count, + Is.EqualTo(test.FluxCaptureCount), + $"Expected {test.FluxCaptureCount} flux captures, got {captures.Count}"); + + captures.Should().NotBeEmpty("Flux captures list should not be empty"); + + foreach(FluxCapture capture in captures) + { + // Verify each capture has valid properties + capture.IndexResolution.Should().BeGreaterThan(0, "IndexResolution should be greater than 0"); + capture.DataResolution.Should().BeGreaterThan(0, "DataResolution should be greater than 0"); + } + } + }); + } + + [Test] + public void Contents() + { + Environment.CurrentDirectory = DataFolder; + + Assert.Multiple(() => + { + foreach(FluxImageTestExpected test in Tests) + { + string testFile = test.TestFile; + + bool exists = File.Exists(testFile); + Assert.That(exists, string.Format(Localization._0_not_found, testFile)); + + // ReSharper disable once ConditionIsAlwaysTrueOrFalse + // It arrives here... + if(!exists) continue; + + IFilter filter = PluginRegister.Singleton.GetFilter(testFile); + filter.Open(testFile); + + var image = Activator.CreateInstance(Plugin.GetType()) as IMediaImage; + + Assert.That(image, + Is.Not.Null, + string.Format(Localization.Could_not_instantiate_filesystem_for_0, testFile)); + + ErrorNumber opened = image.Open(filter); + Assert.That(opened, Is.EqualTo(ErrorNumber.NoError), string.Format(Localization.Open_0, testFile)); + + if(opened != ErrorNumber.NoError) continue; + + if(image is not IFluxImage fluxImage) + { + Assert.Fail($"Image {testFile} does not implement IFluxImage"); + continue; + } + + ErrorNumber error = fluxImage.GetAllFluxCaptures(out List captures); + + Assert.That(error, Is.EqualTo(ErrorNumber.NoError), "GetAllFluxCaptures should succeed"); + Assert.That(captures, Is.Not.Null.And.Not.Empty, "Should have at least one flux capture"); + Assert.That(captures.Count, + Is.EqualTo(test.FluxCaptureCount), + $"Expected {test.FluxCaptureCount} flux captures, got {captures.Count}"); + + // If FluxCaptures array is provided, validate those captures + if(test.FluxCaptures != null && test.FluxCaptures.Length > 0) + { + Assert.That(captures.Count, + Is.GreaterThanOrEqualTo(test.FluxCaptures.Length), + $"Image has {captures.Count} captures, but {test.FluxCaptures.Length} expected captures specified"); + + foreach(FluxCaptureTestExpected expectedCapture in test.FluxCaptures) + { + FluxCapture actualCapture = captures.Find(c => c.Head == expectedCapture.Head && + c.Track == expectedCapture.Track && + c.SubTrack == expectedCapture.SubTrack && + c.CaptureIndex == expectedCapture.CaptureIndex); + + Assert.That(actualCapture, + Is.Not.Null, + $"Flux capture not found: head={expectedCapture.Head}, track={expectedCapture.Track}, subTrack={expectedCapture.SubTrack}, captureIndex={expectedCapture.CaptureIndex}"); + + if(actualCapture != null) + { + Assert.That(actualCapture.IndexResolution, + Is.EqualTo(expectedCapture.IndexResolution), + $"IndexResolution mismatch for head={expectedCapture.Head}, track={expectedCapture.Track}, subTrack={expectedCapture.SubTrack}, captureIndex={expectedCapture.CaptureIndex}"); + Assert.That(actualCapture.DataResolution, + Is.EqualTo(expectedCapture.DataResolution), + $"DataResolution mismatch for head={expectedCapture.Head}, track={expectedCapture.Track}, subTrack={expectedCapture.SubTrack}, captureIndex={expectedCapture.CaptureIndex}"); + } + } + } + } + }); + } +} diff --git a/Aaru.Tests/Images/SuperCardPro.cs b/Aaru.Tests/Images/SuperCardPro.cs new file mode 100644 index 000000000..a4a57b174 --- /dev/null +++ b/Aaru.Tests/Images/SuperCardPro.cs @@ -0,0 +1,105 @@ +// /*************************************************************************** +// Aaru Data Preservation Suite +// ---------------------------------------------------------------------------- +// +// Filename : SuperCardPro.cs +// Author(s) : Rebecca Wallander +// +// Component : Aaru unit testing. +// +// --[ License ] -------------------------------------------------------------- +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// ---------------------------------------------------------------------------- +// Copyright © 2011-2026 Rebecca Wallander +// ****************************************************************************/ + +using System.IO; +using Aaru.CommonTypes.Interfaces; +using NUnit.Framework; + +namespace Aaru.Tests.Images; + +[TestFixture] +public class SuperCardPro : FluxMediaImageTest +{ + public override string DataFolder => Path.Combine(Consts.TestFilesRoot, "Media image formats", "SuperCardPro"); + public override IMediaImage Plugin => new Aaru.Images.SuperCardPro(); + + public override FluxImageTestExpected[] Tests => + [ + new() + { + TestFile = "Go Simulator (1992)(Infogrames).scp", + FluxCaptureCount = 160, + FluxCaptures = [ + new FluxCaptureTestExpected + { + Head = 0, + Track = 0, + SubTrack = 0, + CaptureIndex = 0, + IndexResolution = 25000, + DataResolution = 25000 + }, + new FluxCaptureTestExpected + { + Head = 1, + Track = 0, + SubTrack = 0, + CaptureIndex = 0, + IndexResolution = 25000, + DataResolution = 25000 + }, + new FluxCaptureTestExpected + { + Head = 0, + Track = 1, + SubTrack = 0, + CaptureIndex = 0, + IndexResolution = 25000, + DataResolution = 25000 + }, + new FluxCaptureTestExpected + { + Head = 1, + Track = 1, + SubTrack = 0, + CaptureIndex = 0, + IndexResolution = 25000, + DataResolution = 25000 + }, + new FluxCaptureTestExpected + { + Head = 0, + Track = 2, + SubTrack = 0, + CaptureIndex = 0, + IndexResolution = 25000, + DataResolution = 25000 + }, + new FluxCaptureTestExpected + { + Head = 1, + Track = 2, + SubTrack = 0, + CaptureIndex = 0, + IndexResolution = 25000, + DataResolution = 25000 + }, + ] + }, + ]; +} diff --git a/Aaru.Tests/Structs.cs b/Aaru.Tests/Structs.cs index 83d149c98..e3aa1eb97 100644 --- a/Aaru.Tests/Structs.cs +++ b/Aaru.Tests/Structs.cs @@ -76,6 +76,30 @@ public class TapeImageTestExpected : BlockImageTestExpected public new TapePartition[] Partitions; } +public class FluxCaptureTestExpected +{ + /// Physical head (0-based) + public uint Head; + /// Physical track (0-based) + public ushort Track; + /// Physical sub-track (0-based, e.g. half-track) + public byte SubTrack; + /// Capture index for this head/track/subTrack combination + public uint CaptureIndex; + /// Expected index resolution in picoseconds + public ulong IndexResolution; + /// Expected data resolution in picoseconds + public ulong DataResolution; +} + +public class FluxImageTestExpected : BlockImageTestExpected +{ + /// Expected number of flux captures in the image + public uint FluxCaptureCount; + /// Expected flux captures to validate + public FluxCaptureTestExpected[] FluxCaptures; +} + public class PartitionTest { public Partition[] Partitions;