using SSPCTester.Devices.Interfaces; using SSPCTester.Logic.Models; using SSPCTester.Logic.Report; using SSPCTester.Logic.Storage; namespace SSPCTester.Tests; public sealed class WaveformStoreTests { [Fact] public async Task SaveThenLoad_RestoresCurveDataAndChannels() { string folder = Path.Combine(Path.GetTempPath(), "SSPCTester-waveform-" + Guid.NewGuid().ToString("N")); try { var project = new Project { FolderPath = folder }; var curve = new CurveData { SampleRateHz = 100_000, TriggerSampleIndex = 2, TriggerTimeSec = 0.00002, Voltage = new[] { 0.0, 3.5, 10.0, 22.0 }, Current = new[] { 0.0, 0.1, 0.4, 0.8 }, EngineeringChannels = new[] { new CurveChannelData(0, DaqChannelRole.OutputVoltage, "Vout", "V", 2, 0, new[] { 0.0, 3.5, 10.0, 22.0 }), new CurveChannelData(1, DaqChannelRole.OutputCurrent, "Iout", "A", 1, 0, new[] { 0.0, 0.1, 0.4, 0.8 }) } }; string? path = await WaveformStore.SaveAsync(project, 1, "on", curve); var loaded = await WaveformStore.LoadAsync(project, path); Assert.NotNull(path); Assert.NotNull(loaded); Assert.Equal(curve.SampleRateHz, loaded.SampleRateHz); Assert.Equal(curve.TriggerSampleIndex, loaded.TriggerSampleIndex); Assert.Equal(curve.TriggerTimeSec, loaded.TriggerTimeSec, 8); Assert.Equal(curve.Voltage, loaded.Voltage, new ApproximateDoubleComparer()); Assert.Equal(curve.Current!, loaded.Current!, new ApproximateDoubleComparer()); Assert.Contains(loaded.EngineeringChannels, x => x.Role == DaqChannelRole.OutputVoltage); Assert.Contains(loaded.EngineeringChannels, x => x.Role == DaqChannelRole.OutputCurrent); } finally { if (Directory.Exists(folder)) Directory.Delete(folder, true); } } [Fact] public async Task Load_ReturnsNull_WhenPathIsMissing() { var project = new Project { FolderPath = Path.GetTempPath() }; var loaded = await WaveformStore.LoadAsync(project, "curves/missing.json"); Assert.Null(loaded); } [Fact] public void CurveImageRenderer_RendersPngFromLoadedCurves() { var rising = MakeCurve(true); var falling = MakeCurve(false); byte[] png = CurveImageRenderer.RenderChannel(3, rising, falling); Assert.True(png.Length > 1_000); Assert.Equal(new byte[] { 0x89, 0x50, 0x4E, 0x47 }, png[..4]); } private static CurveData MakeCurve(bool rising) { const int sampleRate = 100_000; const int count = 200; var voltage = new double[count]; for (int i = 0; i < count; i++) { double ratio = i / (double)(count - 1); voltage[i] = rising ? 28 * ratio : 28 * (1 - ratio); } return new CurveData { SampleRateHz = sampleRate, TriggerSampleIndex = 50, TriggerTimeSec = 50.0 / sampleRate, Voltage = voltage, EngineeringChannels = new[] { new CurveChannelData(0, DaqChannelRole.OutputVoltage, "Vout", "V", 1, 0, voltage) } }; } private sealed class ApproximateDoubleComparer : IEqualityComparer { public bool Equals(double x, double y) => Math.Abs(x - y) < 1e-6; public int GetHashCode(double obj) => 0; } }