From f9ee73577c260df6c33f1d6ae70dd960d306af1d Mon Sep 17 00:00:00 2001 From: "[Dorian Hawkins]" Date: Wed, 20 Nov 2024 22:27:36 -0500 Subject: [PATCH 1/2] Added a test for the Constructor of StimThread --- .../Core/Stimulation/StimThreadTests.cs | 203 ++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 tests/EStimLibrary.UnitTests/Core/Stimulation/StimThreadTests.cs diff --git a/tests/EStimLibrary.UnitTests/Core/Stimulation/StimThreadTests.cs b/tests/EStimLibrary.UnitTests/Core/Stimulation/StimThreadTests.cs new file mode 100644 index 0000000..39fda24 --- /dev/null +++ b/tests/EStimLibrary.UnitTests/Core/Stimulation/StimThreadTests.cs @@ -0,0 +1,203 @@ +using EStimLibrary.Core; +using EStimLibrary.Core.HardwareInterfaces; +using EStimLibrary.Core.Stimulation; +using EStimLibrary.Core.Stimulation.Data; + + +namespace EStimLibrary.UnitTests.Core.Stimulators; + + +/// +/// A class to test StimThread.cs +/// +public class StimThreadTests +{ + /// + /// + /// + /// + /// The function we are adding to the StimThread. + /// This will be a dummy function to test that it gets initialized + [Theory] + [MemberData(nameof(ConstructorTestData))] + public void Constructor_ShouldInitializeStimThreadCorrectly( + Dictionary perStimConfigData) + { + var originalDataShallow = + perStimConfigData; + var originalDataDeep = + DeepCopyHelper.DeepCopyPerStimConfigData(perStimConfigData); + StimThread stimThread = new StimThread(perStimConfigData, thread => { }); + Assert.Equal(originalDataShallow, stimThread.PerStimulatorConfigs); + Assert.Empty(stimThread.PulseTrainsPerStimulator); + Assert.Empty(stimThread.TrainParamsPerStimulator); + Assert.True(compareConfigDataPerStimulator(originalDataDeep, + stimThread.PerStimulatorConfigs)); + } + + public static IEnumerable ConstructorTestData() + { + return new List + { + new object[] + { + new Dictionary + { + { 0, new ThreadConfigDataPerStimulator( + 0, + new List + { + new Lead( + new SortedSet { 1 }, + new SortedSet { 1 }, + Constants.CurrentDirection.SINK + ), + new Lead( + new SortedSet { 2 }, + new SortedSet { 2 }, + Constants.CurrentDirection.SOURCE + ) + }, + BaseStimParams.ExampleParamData, + new SortedSet(BaseStimParams.ParamOrderIndices.Keys) + { + BaseStimParams.PA, + BaseStimParams.PW, + BaseStimParams.IPD, + BaseStimParams.AnodeRatio + }) + } + }, + } + } + ; + } + + private static bool compareConfigDataPerStimulator(Dictionary x, + Dictionary y) + { + foreach (var kvp in x) + { + if (!y.ContainsKey(kvp.Key)) return false; + + var threadConfigDataX = kvp.Value; + var threadConfigDataY = y[kvp.Key]; + + if (!ThreadConfigDataEquals(threadConfigDataX, threadConfigDataY)) return false; + } + return true; + } + + private static bool ThreadConfigDataEquals(ThreadConfigDataPerStimulator x, ThreadConfigDataPerStimulator y) + { + return x.GlobalStimId == y.GlobalStimId + && LeadListEqual(x.IndependentLeads, y.IndependentLeads) + && StimParamDataEquals(x.StimParamData, y.StimParamData) + && x.ModulatableStimParams.SetEquals(y.ModulatableStimParams); + } + + private static bool LeadListEqual(IEnumerable x, IEnumerable y) + { + var xList = x.ToList(); + var yList = y.ToList(); + + if (xList.Count != yList.Count) return false; + + for (int i = 0; i < xList.Count; i++) + { + if (!LeadEquals(xList[i], yList[i])) return false; + } + + return true; + } + + private static bool LeadEquals(Lead x, Lead y) + { + return x.ContactSet.SetEquals(y.ContactSet) + && x.OutputSet.SetEquals(y.OutputSet) + && x.CurrentDirection == y.CurrentDirection; + } + + private static bool StimParamDataEquals(Dictionary> x, Dictionary> y) + { + if (x.Count != y.Count) return false; + + foreach (var kvp in x) + { + if (!y.ContainsKey(kvp.Key)) return false; + + var tupleX = kvp.Value; + var tupleY = y[kvp.Key]; + + if (!tupleX.Item1.Equals(tupleY.Item1) || !object.Equals(tupleX.Item2, tupleY.Item2)) return false; + } + + return true; + } + + private static class DeepCopyHelper + { + public static Dictionary DeepCopyPerStimConfigData( + Dictionary original) + { + var copy = new Dictionary(); + + foreach (var kvp in original) + { + var copiedThreadConfigData = new ThreadConfigDataPerStimulator( + kvp.Value.GlobalStimId, + DeepCopyLeads(kvp.Value.IndependentLeads), + DeepCopyStimParamData(kvp.Value.StimParamData), + new SortedSet(kvp.Value.ModulatableStimParams) + ); + + copy[kvp.Key] = copiedThreadConfigData; + } + + return copy; + } + + private static List DeepCopyLeads(IEnumerable originalLeads) + { + return originalLeads.Select(lead => new Lead( + new SortedSet(lead.ContactSet), + new SortedSet(lead.OutputSet), + lead.CurrentDirection + )).ToList(); + } + + private static Dictionary> DeepCopyStimParamData(Dictionary> original) + { + var copy = new Dictionary>(); + + foreach (var kvp in original) + { + var copiedTuple = new Tuple( + DeepCopyDataLimits(kvp.Value.Item1), + kvp.Value.Item2 + ); + + copy[kvp.Key] = copiedTuple; + } + + return copy; + } + + private static IDataLimits DeepCopyDataLimits(IDataLimits original) + { + switch (original) + { + case ContinuousDataLimits continuousLimits: + return new ContinuousDataLimits(continuousLimits.MinBound, continuousLimits.MaxBound); + case FixedOptionDataLimits fixedOptionLimits: + return new FixedOptionDataLimits(new SortedSet(fixedOptionLimits.DataOptions)); + case FixedOptionDataLimits fixedOptionLimitsInt: + return new FixedOptionDataLimits(new SortedSet(fixedOptionLimitsInt.DataOptions)); + case ContinuousIntDataLimits continuousIntLimits: + return new ContinuousIntDataLimits(continuousIntLimits.MinBound, continuousIntLimits.MaxBound); + default: + throw new InvalidOperationException("Unsupported IDataLimits type."); + } + } + } +} \ No newline at end of file From ca7939fa3b2ba5facd3291c8144975b456d790d4 Mon Sep 17 00:00:00 2001 From: "[Dorian Hawkins]" Date: Wed, 20 Nov 2024 22:40:49 -0500 Subject: [PATCH 2/2] Fix error that caused test to fail --- .../Core/Stimulation/StimThreadTests.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/EStimLibrary.UnitTests/Core/Stimulation/StimThreadTests.cs b/tests/EStimLibrary.UnitTests/Core/Stimulation/StimThreadTests.cs index 39fda24..433010a 100644 --- a/tests/EStimLibrary.UnitTests/Core/Stimulation/StimThreadTests.cs +++ b/tests/EStimLibrary.UnitTests/Core/Stimulation/StimThreadTests.cs @@ -31,7 +31,7 @@ public void Constructor_ShouldInitializeStimThreadCorrectly( Assert.Equal(originalDataShallow, stimThread.PerStimulatorConfigs); Assert.Empty(stimThread.PulseTrainsPerStimulator); Assert.Empty(stimThread.TrainParamsPerStimulator); - Assert.True(compareConfigDataPerStimulator(originalDataDeep, + Assert.True(CompareConfigDataPerStimulator(originalDataDeep, stimThread.PerStimulatorConfigs)); } @@ -72,8 +72,11 @@ public static IEnumerable ConstructorTestData() } ; } + + + - private static bool compareConfigDataPerStimulator(Dictionary x, + private static bool CompareConfigDataPerStimulator(Dictionary x, Dictionary y) { foreach (var kvp in x) @@ -190,9 +193,9 @@ private static IDataLimits DeepCopyDataLimits(IDataLimits original) case ContinuousDataLimits continuousLimits: return new ContinuousDataLimits(continuousLimits.MinBound, continuousLimits.MaxBound); case FixedOptionDataLimits fixedOptionLimits: - return new FixedOptionDataLimits(new SortedSet(fixedOptionLimits.DataOptions)); + return new FixedOptionDataLimits(fixedOptionLimits.DataOptions); case FixedOptionDataLimits fixedOptionLimitsInt: - return new FixedOptionDataLimits(new SortedSet(fixedOptionLimitsInt.DataOptions)); + return new FixedOptionDataLimits(fixedOptionLimitsInt.DataOptions); case ContinuousIntDataLimits continuousIntLimits: return new ContinuousIntDataLimits(continuousIntLimits.MinBound, continuousIntLimits.MaxBound); default: