From ccaf9a927c0417ea299bd5fd3d51db1eb53e7ab5 Mon Sep 17 00:00:00 2001 From: Evgeny Redikultsev Date: Sat, 7 Dec 2024 16:52:18 +0500 Subject: [PATCH] Add Cross-section repositort tests --- .../MainWindow/AnalysesManagerView.xaml | 2 +- .../HasForceActionUpdateCloningStrategy.cs | 36 +++++ .../Interfaces/IGetUpdateStrategy.cs | 13 ++ .../CrossSectionRepositoryCloneStrategy.cs | 133 ++++-------------- .../HasMaterialsUpdateCloningStrategy.cs | 38 +++++ .../HasCalculatorsUpdateCloningStrategy.cs | 114 +++++++++++++++ .../HasPrimitivesUpdateCloningStrategy.cs | 50 +++++++ ...asForceActionUpdateCloningStrategyTests.cs | 95 +++++++++++++ .../HasMaterialsUpdateCloningStrategyTests.cs | 103 ++++++++++++++ ...HasPrimitivesUpdateCloningStrategyTests.cs | 111 +++++++++++++++ 10 files changed, 588 insertions(+), 107 deletions(-) create mode 100644 StructureHelperCommon/Infrastructures/Interfaces/HasForceActionUpdateCloningStrategy.cs create mode 100644 StructureHelperCommon/Infrastructures/Interfaces/IGetUpdateStrategy.cs create mode 100644 StructureHelperLogics/Models/Materials/Logics/HasMaterialsUpdateCloningStrategy.cs create mode 100644 StructureHelperLogics/NdmCalculations/Analyses/ByForces/Logics/HasCalculatorsUpdateCloningStrategy.cs create mode 100644 StructureHelperLogics/NdmCalculations/Primitives/Logics/HasPrimitivesUpdateCloningStrategy.cs create mode 100644 StructureHelperTests/UnitTests/UpdateStrategiesTests/HasForceActionUpdateCloningStrategyTests.cs create mode 100644 StructureHelperTests/UnitTests/UpdateStrategiesTests/HasMaterialsUpdateCloningStrategyTests.cs create mode 100644 StructureHelperTests/UnitTests/UpdateStrategiesTests/HasPrimitivesUpdateCloningStrategyTests.cs diff --git a/StructureHelper/Windows/MainWindow/AnalysesManagerView.xaml b/StructureHelper/Windows/MainWindow/AnalysesManagerView.xaml index 5d85973..b0d7f77 100644 --- a/StructureHelper/Windows/MainWindow/AnalysesManagerView.xaml +++ b/StructureHelper/Windows/MainWindow/AnalysesManagerView.xaml @@ -185,7 +185,7 @@ - + diff --git a/StructureHelperCommon/Infrastructures/Interfaces/HasForceActionUpdateCloningStrategy.cs b/StructureHelperCommon/Infrastructures/Interfaces/HasForceActionUpdateCloningStrategy.cs new file mode 100644 index 0000000..4f66ed3 --- /dev/null +++ b/StructureHelperCommon/Infrastructures/Interfaces/HasForceActionUpdateCloningStrategy.cs @@ -0,0 +1,36 @@ +using StructureHelperCommon.Services; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperCommon.Infrastructures.Interfaces +{ + /// + /// Creates deep copy of internal elements of object which has calculators + /// + public class HasForceActionUpdateCloningStrategy : IUpdateStrategy + { + private ICloningStrategy cloningStrategy; + + public HasForceActionUpdateCloningStrategy(ICloningStrategy cloningStrategy) + { + this.cloningStrategy = cloningStrategy; + } + + public void Update(IHasForceActions targetObject, IHasForceActions sourceObject) + { + CheckObject.IsNull(cloningStrategy); + CheckObject.IsNull(sourceObject); + CheckObject.IsNull(targetObject); + if (ReferenceEquals(targetObject, sourceObject)) { return; } + targetObject.ForceActions.Clear(); + foreach (var force in sourceObject.ForceActions) + { + var newForce = cloningStrategy.Clone(force); + targetObject.ForceActions.Add(newForce); + } + } + } +} diff --git a/StructureHelperCommon/Infrastructures/Interfaces/IGetUpdateStrategy.cs b/StructureHelperCommon/Infrastructures/Interfaces/IGetUpdateStrategy.cs new file mode 100644 index 0000000..debda11 --- /dev/null +++ b/StructureHelperCommon/Infrastructures/Interfaces/IGetUpdateStrategy.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperCommon.Infrastructures.Interfaces +{ + public interface IGetUpdateStrategy where T : ISaveable + { + IUpdateStrategy GetStrategy(); + } +} diff --git a/StructureHelperLogics/Models/CrossSections/CrossSectionRepositoryCloneStrategy.cs b/StructureHelperLogics/Models/CrossSections/CrossSectionRepositoryCloneStrategy.cs index 5ba37f7..bcd3a68 100644 --- a/StructureHelperLogics/Models/CrossSections/CrossSectionRepositoryCloneStrategy.cs +++ b/StructureHelperLogics/Models/CrossSections/CrossSectionRepositoryCloneStrategy.cs @@ -3,10 +3,12 @@ using StructureHelperCommon.Infrastructures.Interfaces; using StructureHelperCommon.Models.Calculators; using StructureHelperCommon.Models.Parameters; using StructureHelperLogics.Models.Materials; +using StructureHelperLogics.Models.Materials.Logics; using StructureHelperLogics.NdmCalculations.Analyses.ByForces; using StructureHelperLogics.NdmCalculations.Analyses.ByForces.LimitCurve; using StructureHelperLogics.NdmCalculations.Cracking; using StructureHelperLogics.NdmCalculations.Primitives; +using StructureHelperLogics.NdmCalculations.Primitives.Logics; namespace StructureHelperLogics.Models.CrossSections { @@ -14,129 +16,48 @@ namespace StructureHelperLogics.Models.CrossSections { private ICloningStrategy cloningStrategy; private CrossSectionRepository targetRepository; - private IUpdateStrategy limitCurvesInputDataUpdateStrategy; + private IUpdateStrategy forcesUpdateStrategy; + private IUpdateStrategy materialsUpdateStrategy; + private IUpdateStrategy primitivesUpdateStrategy; + private IUpdateStrategy calculatorsUpdateStrategy; + public CrossSectionRepositoryCloneStrategy( ICloningStrategy cloningStrategy, - IUpdateStrategy limitCurvesInputDataUpdateStrategy) + IUpdateStrategy forcesUpdateStrategy, + IUpdateStrategy materialsUpdateStrategy, + IUpdateStrategy primitivesUpdateStrategy, + IUpdateStrategy calculatorsUpdateStrategy) { this.cloningStrategy = cloningStrategy; - this.limitCurvesInputDataUpdateStrategy = limitCurvesInputDataUpdateStrategy; + this.forcesUpdateStrategy = forcesUpdateStrategy; + this.materialsUpdateStrategy = materialsUpdateStrategy; + this.primitivesUpdateStrategy = primitivesUpdateStrategy; + this.calculatorsUpdateStrategy = calculatorsUpdateStrategy; } public CrossSectionRepositoryCloneStrategy() : this ( new DeepCloningStrategy(), - new LimitCurvesCalculatorInputDataUpdateStrategy()) + new HasForceActionUpdateCloningStrategy(null), + new HasMaterialsUpdateCloningStrategy(null), + new HasPrimitivesUpdateCloningStrategy(null), + new HasCalculatorsUpdateCloningStrategy(null)) { + forcesUpdateStrategy = new HasForceActionUpdateCloningStrategy(cloningStrategy); + materialsUpdateStrategy = new HasMaterialsUpdateCloningStrategy(cloningStrategy); + primitivesUpdateStrategy = new HasPrimitivesUpdateCloningStrategy(cloningStrategy); + calculatorsUpdateStrategy = new HasCalculatorsUpdateCloningStrategy(cloningStrategy); } public ICrossSectionRepository GetClone(ICrossSectionRepository sourceObject) { targetRepository = new(); - ProcessForces(targetRepository, sourceObject); - ProcessMaterials(targetRepository, sourceObject); - ProcessPrimitives(targetRepository, sourceObject); - ProcessCalculators(targetRepository, sourceObject); + forcesUpdateStrategy.Update(targetRepository, sourceObject); + materialsUpdateStrategy.Update(targetRepository, sourceObject); + primitivesUpdateStrategy.Update(targetRepository, sourceObject); + calculatorsUpdateStrategy.Update(targetRepository, sourceObject); return targetRepository; } - - private void ProcessCalculators(IHasCalculators targetObject, IHasCalculators sourceObject) - { - targetObject.Calculators.Clear(); - foreach (var calculator in sourceObject.Calculators) - { - var newCalculator = cloningStrategy.Clone(calculator); - if (calculator is IForceCalculator forceCalculator) - { - ProcessForceCalculator(newCalculator, forceCalculator); - } - else if (calculator is CrackCalculator crackCalculator) - { - ProcessCrackCalculator(newCalculator, crackCalculator); - } - else if (calculator is ILimitCurvesCalculator limitCalculator) - { - ProcessLimitCurvesCalculator(newCalculator, limitCalculator); - } - else - { - throw new StructureHelperException(ErrorStrings.ObjectTypeIsUnknownObj(calculator)); - } - targetRepository.Calculators.Add(newCalculator); - } - } - - private void ProcessLimitCurvesCalculator(ICalculator newCalculator, ILimitCurvesCalculator limitCalculator) - { - var sourceData = limitCalculator.InputData; - var targetData = ((ILimitCurvesCalculator)newCalculator).InputData; - limitCurvesInputDataUpdateStrategy.Update(targetData, sourceData); - foreach (var series in targetData.PrimitiveSeries) - { - List collection = UpdatePrimitivesCollection(series); - series.Collection.AddRange(collection); - } - } - - private void ProcessCrackCalculator(ICalculator newCalculator, CrackCalculator crackCalculator) - { - var sourceData = crackCalculator.InputData; - var targetData = ((ICrackCalculator)newCalculator).InputData; - ProcessPrimitives(targetData, sourceData); - ProcessForces(targetData, sourceData); - } - - private void ProcessForceCalculator(ICalculator newCalculator, IForceCalculator forceCalculator) - { - var sourceData = forceCalculator.InputData; - var targetData = ((IForceCalculator)newCalculator).InputData; - ProcessPrimitives(targetData, sourceData); - ProcessForces(targetData, sourceData); - } - - private List UpdatePrimitivesCollection(NamedCollection series) - { - List collection = new(); - foreach (var item in series.Collection) - { - var newItem = cloningStrategy.Clone(item); - collection.Add(newItem); - } - series.Collection.Clear(); - return collection; - } - - private void ProcessMaterials(IHasHeadMaterials targetObject, IHasHeadMaterials sourceObject) - { - targetObject.HeadMaterials.Clear(); - foreach (var material in sourceObject.HeadMaterials) - { - var newMaterial = cloningStrategy.Clone(material); - targetRepository.HeadMaterials.Add(newMaterial); - } - } - - private void ProcessForces(IHasForceActions targetObject, IHasForceActions sourceObject) - { - targetObject.ForceActions.Clear(); - foreach (var force in sourceObject.ForceActions) - { - var newForce = cloningStrategy.Clone(force); - targetObject.ForceActions.Add(newForce); - } - } - - private void ProcessPrimitives(IHasPrimitives targetObject, IHasPrimitives sourceObject) - { - targetObject.Primitives.Clear(); - foreach (var primitive in sourceObject.Primitives) - { - var newPrimitive = cloningStrategy.Clone(primitive); - var material = cloningStrategy.Clone(primitive.NdmElement.HeadMaterial); - newPrimitive.NdmElement.HeadMaterial = material; - targetObject.Primitives.Add(newPrimitive); - } - } } } diff --git a/StructureHelperLogics/Models/Materials/Logics/HasMaterialsUpdateCloningStrategy.cs b/StructureHelperLogics/Models/Materials/Logics/HasMaterialsUpdateCloningStrategy.cs new file mode 100644 index 0000000..3a3521f --- /dev/null +++ b/StructureHelperLogics/Models/Materials/Logics/HasMaterialsUpdateCloningStrategy.cs @@ -0,0 +1,38 @@ +using StructureHelperCommon.Infrastructures.Interfaces; +using StructureHelperCommon.Services; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StructureHelperLogics.Models.Materials.Logics +{ + /// + /// Creates deep copy of internal elements of object which has materials + /// + public class HasMaterialsUpdateCloningStrategy : IUpdateStrategy + { + private ICloningStrategy cloningStrategy; + + public HasMaterialsUpdateCloningStrategy(ICloningStrategy cloningStrategy) + { + this.cloningStrategy = cloningStrategy; + } + + /// + public void Update(IHasHeadMaterials targetObject, IHasHeadMaterials sourceObject) + { + CheckObject.IsNull(cloningStrategy); + CheckObject.IsNull(sourceObject); + CheckObject.IsNull(targetObject); + if (ReferenceEquals(targetObject, sourceObject)) { return; } + targetObject.HeadMaterials.Clear(); + foreach (var material in sourceObject.HeadMaterials) + { + var newMaterial = cloningStrategy.Clone(material); + targetObject.HeadMaterials.Add(newMaterial); + } + } + } +} diff --git a/StructureHelperLogics/NdmCalculations/Analyses/ByForces/Logics/HasCalculatorsUpdateCloningStrategy.cs b/StructureHelperLogics/NdmCalculations/Analyses/ByForces/Logics/HasCalculatorsUpdateCloningStrategy.cs new file mode 100644 index 0000000..4235c3f --- /dev/null +++ b/StructureHelperLogics/NdmCalculations/Analyses/ByForces/Logics/HasCalculatorsUpdateCloningStrategy.cs @@ -0,0 +1,114 @@ +using StructureHelperCommon.Infrastructures.Exceptions; +using StructureHelperCommon.Infrastructures.Interfaces; +using StructureHelperCommon.Models.Calculators; +using StructureHelperCommon.Models.Parameters; +using StructureHelperCommon.Services; +using StructureHelperLogics.NdmCalculations.Analyses.ByForces.LimitCurve; +using StructureHelperLogics.NdmCalculations.Cracking; +using StructureHelperLogics.NdmCalculations.Primitives; +using StructureHelperLogics.NdmCalculations.Primitives.Logics; + +namespace StructureHelperLogics.NdmCalculations.Analyses.ByForces +{ + /// + /// Creates deep copy of internal elements of object which has calculators + /// + public class HasCalculatorsUpdateCloningStrategy : IUpdateStrategy + { + private ICloningStrategy cloningStrategy; + private IUpdateStrategy forcesUpdateStrategy; + private IUpdateStrategy primitivesUpdateStrategy; + private IUpdateStrategy limitCurvesInputDataUpdateStrategy; + + public HasCalculatorsUpdateCloningStrategy(ICloningStrategy cloningStrategy) : this( + cloningStrategy, + new HasForceActionUpdateCloningStrategy(cloningStrategy), + new HasPrimitivesUpdateCloningStrategy(cloningStrategy), + new LimitCurvesCalculatorInputDataUpdateStrategy() + ) + { + } + + public HasCalculatorsUpdateCloningStrategy( + ICloningStrategy cloningStrategy, + IUpdateStrategy forcesUpdateStrategy, + IUpdateStrategy primitivesUpdateStrategy, + IUpdateStrategy limitCurvesInputDataUpdateStrategy) + { + this.cloningStrategy = cloningStrategy; + this.forcesUpdateStrategy = forcesUpdateStrategy; + this.primitivesUpdateStrategy = primitivesUpdateStrategy; + this.limitCurvesInputDataUpdateStrategy = limitCurvesInputDataUpdateStrategy; + } + + public void Update(IHasCalculators targetObject, IHasCalculators sourceObject) + { + CheckObject.IsNull(cloningStrategy); + CheckObject.IsNull(sourceObject); + CheckObject.IsNull(targetObject); + if (ReferenceEquals(targetObject, sourceObject)) { return; } + targetObject.Calculators.Clear(); + foreach (var calculator in sourceObject.Calculators) + { + var newCalculator = cloningStrategy.Clone(calculator); + if (calculator is IForceCalculator forceCalculator) + { + ProcessForceCalculator(newCalculator, forceCalculator); + } + else if (calculator is CrackCalculator crackCalculator) + { + ProcessCrackCalculator(newCalculator, crackCalculator); + } + else if (calculator is ILimitCurvesCalculator limitCalculator) + { + ProcessLimitCurvesCalculator(newCalculator, limitCalculator); + } + else + { + throw new StructureHelperException(ErrorStrings.ObjectTypeIsUnknownObj(calculator)); + } + targetObject.Calculators.Add(newCalculator); + } + } + + private void ProcessLimitCurvesCalculator(ICalculator newCalculator, ILimitCurvesCalculator limitCalculator) + { + var sourceData = limitCalculator.InputData; + var targetData = ((ILimitCurvesCalculator)newCalculator).InputData; + limitCurvesInputDataUpdateStrategy.Update(targetData, sourceData); + foreach (var series in targetData.PrimitiveSeries) + { + List collection = UpdatePrimitivesCollection(series); + series.Collection.AddRange(collection); + } + } + + private void ProcessCrackCalculator(ICalculator newCalculator, CrackCalculator crackCalculator) + { + var sourceData = crackCalculator.InputData; + var targetData = ((ICrackCalculator)newCalculator).InputData; + primitivesUpdateStrategy.Update(targetData, sourceData); + forcesUpdateStrategy.Update(targetData, sourceData); + } + + private void ProcessForceCalculator(ICalculator newCalculator, IForceCalculator forceCalculator) + { + var sourceData = forceCalculator.InputData; + var targetData = ((IForceCalculator)newCalculator).InputData; + primitivesUpdateStrategy.Update(targetData, sourceData); + forcesUpdateStrategy.Update(targetData, sourceData); + } + + private List UpdatePrimitivesCollection(NamedCollection series) + { + List collection = new(); + foreach (var item in series.Collection) + { + var newItem = cloningStrategy.Clone(item); + collection.Add(newItem); + } + series.Collection.Clear(); + return collection; + } + } +} diff --git a/StructureHelperLogics/NdmCalculations/Primitives/Logics/HasPrimitivesUpdateCloningStrategy.cs b/StructureHelperLogics/NdmCalculations/Primitives/Logics/HasPrimitivesUpdateCloningStrategy.cs new file mode 100644 index 0000000..9c2478e --- /dev/null +++ b/StructureHelperLogics/NdmCalculations/Primitives/Logics/HasPrimitivesUpdateCloningStrategy.cs @@ -0,0 +1,50 @@ +using StructureHelperCommon.Infrastructures.Interfaces; +using StructureHelperCommon.Services; + +namespace StructureHelperLogics.NdmCalculations.Primitives.Logics +{ + /// + /// Creates deep copy of internal elements of object which has primitives + /// + public class HasPrimitivesUpdateCloningStrategy : IUpdateStrategy + { + private ICloningStrategy cloningStrategy; + + public HasPrimitivesUpdateCloningStrategy(ICloningStrategy cloningStrategy) + { + this.cloningStrategy = cloningStrategy; + } + + public void Update(IHasPrimitives targetObject, IHasPrimitives sourceObject) + { + CheckObject.IsNull(cloningStrategy); + CheckObject.IsNull(sourceObject); + CheckObject.IsNull(targetObject); + if (ReferenceEquals(targetObject, sourceObject)) { return; } + targetObject.Primitives.Clear(); + foreach (var primitive in sourceObject.Primitives) + { + ProcessPrimitive(targetObject, primitive); + } + } + + private void ProcessPrimitive(IHasPrimitives targetObject, INdmPrimitive primitive) + { + var newPrimitive = cloningStrategy.Clone(primitive); + if (primitive.NdmElement.HeadMaterial is not null) + { + var material = cloningStrategy.Clone(primitive.NdmElement.HeadMaterial); + newPrimitive.NdmElement.HeadMaterial = material; + } + targetObject.Primitives.Add(newPrimitive); + if (primitive is IHasHostPrimitive hasHost) + { + if (hasHost.HostPrimitive is not null) + { + INdmPrimitive hostPrimitive = cloningStrategy.Clone(hasHost.HostPrimitive); + (newPrimitive as IHasHostPrimitive).HostPrimitive = hostPrimitive; + } + } + } + } +} diff --git a/StructureHelperTests/UnitTests/UpdateStrategiesTests/HasForceActionUpdateCloningStrategyTests.cs b/StructureHelperTests/UnitTests/UpdateStrategiesTests/HasForceActionUpdateCloningStrategyTests.cs new file mode 100644 index 0000000..05d8ad9 --- /dev/null +++ b/StructureHelperTests/UnitTests/UpdateStrategiesTests/HasForceActionUpdateCloningStrategyTests.cs @@ -0,0 +1,95 @@ +using Moq; +using NUnit.Framework; +using StructureHelperCommon.Infrastructures.Exceptions; +using StructureHelperCommon.Infrastructures.Interfaces; +using StructureHelperCommon.Models.Forces; +using System.Collections.Generic; +namespace StructureHelperTests.UnitTests.UpdateStrategiesTests +{ + + + [TestFixture] + public class HasForceActionUpdateCloningStrategyTests + { + private Mock _cloningStrategyMock; + private HasForceActionUpdateCloningStrategy _strategy; + + [SetUp] + public void SetUp() + { + _cloningStrategyMock = new Mock(); + _strategy = new HasForceActionUpdateCloningStrategy(_cloningStrategyMock.Object); + } + + [Test] + public void Update_WithNullCloningStrategy_ThrowsStructureHelperException() + { + var targetObjectMock = new Mock(); + var sourceObjectMock = new Mock(); + Assert.Throws(() => + { + new HasForceActionUpdateCloningStrategy(null).Update(targetObjectMock.Object, sourceObjectMock.Object); + }); + } + + [Test] + public void Update_WithNullSourceObject_ThrowsStructureHelperException() + { + var targetObjectMock = new Mock(); + Assert.Throws(() => + { + _strategy.Update(targetObjectMock.Object, null); + }); + } + + [Test] + public void Update_WithNullTargetObject_ThrowsStructureHelperException() + { + var sourceObjectMock = new Mock(); + Assert.Throws(() => + { + _strategy.Update(null, sourceObjectMock.Object); + }); + } + + [Test] + public void Update_WithSameObjects_DoesNotPerformCloning() + { + var sourceObjectMock = new Mock(); + _strategy.Update(sourceObjectMock.Object, sourceObjectMock.Object); + + _cloningStrategyMock.Verify(cs => cs.Clone(It.IsAny(), null), Times.Never); + } + + [Test] + public void Update_ClonesEachForceActionAndAddsToTargetObject() + { + // Arrange + var targetForceActions = new List(); + var targetObjectMock = new Mock(); + var sourceObjectMock = new Mock(); + + var sourceForceActions = new List { new ForceCombinationByFactor(), new ForceCombinationByFactor() }; + var clonedForceActions = new List { new ForceCombinationByFactor(), new ForceCombinationByFactor() }; + + sourceObjectMock.SetupGet(s => s.ForceActions).Returns(sourceForceActions); + targetObjectMock.SetupGet(t => t.ForceActions).Returns(targetForceActions); + + _cloningStrategyMock.Setup(cs => cs.Clone(sourceForceActions[0], null)) + .Returns(clonedForceActions[0]); + _cloningStrategyMock.Setup(cs => cs.Clone(sourceForceActions[1], null)) + .Returns(clonedForceActions[1]); + + // Act + _strategy.Update(targetObjectMock.Object, sourceObjectMock.Object); + + // Assert + Assert.That(targetForceActions, Has.Count.EqualTo(2)); + Assert.That(targetForceActions, Is.EquivalentTo(clonedForceActions)); + + _cloningStrategyMock.Verify(cs => cs.Clone(sourceForceActions[0], null), Times.Once); + _cloningStrategyMock.Verify(cs => cs.Clone(sourceForceActions[1], null), Times.Once); + } + } + +} diff --git a/StructureHelperTests/UnitTests/UpdateStrategiesTests/HasMaterialsUpdateCloningStrategyTests.cs b/StructureHelperTests/UnitTests/UpdateStrategiesTests/HasMaterialsUpdateCloningStrategyTests.cs new file mode 100644 index 0000000..66d6082 --- /dev/null +++ b/StructureHelperTests/UnitTests/UpdateStrategiesTests/HasMaterialsUpdateCloningStrategyTests.cs @@ -0,0 +1,103 @@ +using Moq; +using NUnit.Framework; +using StructureHelper.Models.Materials; +using StructureHelperCommon.Infrastructures.Exceptions; +using StructureHelperCommon.Infrastructures.Interfaces; +using StructureHelperLogics.Models.Materials.Logics; +using StructureHelperLogics.Models.Materials; +using System.Collections.Generic; + +namespace StructureHelperTests.UnitTests.UpdateStrategiesTests +{ + + + [TestFixture] + public class HasMaterialsUpdateCloningStrategyTests + { + private Mock _cloningStrategyMock; + private HasMaterialsUpdateCloningStrategy _strategy; + + [SetUp] + public void SetUp() + { + _cloningStrategyMock = new Mock(); + _strategy = new HasMaterialsUpdateCloningStrategy(_cloningStrategyMock.Object); + } + + [Test] + public void Update_WithNullCloningStrategy_ThrowsStructureHelperException() + { + var targetObjectMock = new Mock(); + var sourceObjectMock = new Mock(); + Assert.Throws(() => + { + new HasMaterialsUpdateCloningStrategy(null).Update(targetObjectMock.Object, sourceObjectMock.Object); + }); + } + + [Test] + public void Update_WithNullSourceObject_ThrowsStructureHelperException() + { + var targetObjectMock = new Mock(); + Assert.Throws(() => + { + _strategy.Update(targetObjectMock.Object, null); + }); + } + + [Test] + public void Update_WithNullTargetObject_ThrowsStructureHelperException() + { + var sourceObjectMock = new Mock(); + Assert.Throws(() => + { + _strategy.Update(null, sourceObjectMock.Object); + }); + } + + [Test] + public void Update_WithSameObjects_DoesNotPerformCloning() + { + var sourceObjectMock = new Mock(); + _strategy.Update(sourceObjectMock.Object, sourceObjectMock.Object); + + _cloningStrategyMock.Verify(cs => cs.Clone(It.IsAny(), null), Times.Never); + } + + [Test] + public void Update_ClonesAndAddsEachMaterialToTarget() + { + // Arrange + var targetMaterials = new List(); + var targetObjectMock = new Mock(); + targetObjectMock.SetupGet(t => t.HeadMaterials).Returns(targetMaterials); + + var sourceMaterials = new List + { + Mock.Of(m => m.Name == "Material1"), + Mock.Of(m => m.Name == "Material2") + }; + var sourceObjectMock = new Mock(); + sourceObjectMock.SetupGet(s => s.HeadMaterials).Returns(sourceMaterials); + + var clonedMaterial1 = Mock.Of(m => m.Name == "ClonedMaterial1"); + var clonedMaterial2 = Mock.Of(m => m.Name == "ClonedMaterial2"); + + _cloningStrategyMock.Setup(cs => cs.Clone(sourceMaterials[0], null)).Returns(clonedMaterial1); + _cloningStrategyMock.Setup(cs => cs.Clone(sourceMaterials[1], null)).Returns(clonedMaterial2); + + // Act + _strategy.Update(targetObjectMock.Object, sourceObjectMock.Object); + + // Assert + //Assert.IsEmpty(targetMaterials, "Target materials should be cleared before adding new ones."); + Assert.That(targetMaterials, Has.Count.EqualTo(2)); + Assert.That(targetMaterials, Contains.Item(clonedMaterial1)); + Assert.That(targetMaterials, Contains.Item(clonedMaterial2)); + + _cloningStrategyMock.Verify(cs => cs.Clone(sourceMaterials[0], null), Times.Once); + _cloningStrategyMock.Verify(cs => cs.Clone(sourceMaterials[1], null), Times.Once); + } + } + +} diff --git a/StructureHelperTests/UnitTests/UpdateStrategiesTests/HasPrimitivesUpdateCloningStrategyTests.cs b/StructureHelperTests/UnitTests/UpdateStrategiesTests/HasPrimitivesUpdateCloningStrategyTests.cs new file mode 100644 index 0000000..0b070d3 --- /dev/null +++ b/StructureHelperTests/UnitTests/UpdateStrategiesTests/HasPrimitivesUpdateCloningStrategyTests.cs @@ -0,0 +1,111 @@ +using Moq; +using NUnit.Framework; +using StructureHelperCommon.Infrastructures.Exceptions; +using StructureHelperCommon.Infrastructures.Interfaces; +using StructureHelperLogics.NdmCalculations.Primitives.Logics; +using StructureHelperLogics.NdmCalculations.Primitives; +using System.Collections.Generic; + +namespace StructureHelperTests.UnitTests.UpdateStrategiesTests +{ + + + [TestFixture] + public class HasPrimitivesUpdateCloningStrategyTests + { + private Mock _cloningStrategyMock; + private HasPrimitivesUpdateCloningStrategy _strategy; + + [SetUp] + public void SetUp() + { + _cloningStrategyMock = new Mock(); + _strategy = new HasPrimitivesUpdateCloningStrategy(_cloningStrategyMock.Object); + } + + [Test] + public void Update_WithNullCloningStrategy_ThrowsStructureHelperException() + { + var targetObjectMock = new Mock(); + var sourceObjectMock = new Mock(); + Assert.Throws(() => + { + new HasPrimitivesUpdateCloningStrategy(null).Update(targetObjectMock.Object, sourceObjectMock.Object); + }); + } + + [Test] + public void Update_WithNullSourceObject_ThrowsStructureHelperException() + { + var targetObjectMock = new Mock(); + Assert.Throws(() => + { + _strategy.Update(targetObjectMock.Object, null); + }); + } + + [Test] + public void Update_WithNullTargetObject_ThrowsStructureHelperException() + { + var sourceObjectMock = new Mock(); + Assert.Throws(() => + { + _strategy.Update(null, sourceObjectMock.Object); + }); + } + + [Test] + public void Update_WithSameObjects_DoesNotPerformCloning() + { + var sourceObjectMock = new Mock(); + _strategy.Update(sourceObjectMock.Object, sourceObjectMock.Object); + + _cloningStrategyMock.Verify(cs => cs.Clone(It.IsAny(), null), Times.Never); + } + + [Test] + public void Update_ProcessesEachPrimitiveCorrectly() + { + // Arrange + ICloningStrategy deepCloningStrategy = new DeepCloningStrategy(); + var targetPrimitives = new List(); + var targetObjectMock = new Mock(); + targetObjectMock.SetupGet(t => t.Primitives).Returns(targetPrimitives); + + var sourcePrimitive1 = Mock.Of(p => p.Name == "sp1" && p.NdmElement == new NdmElement()); + var sourceHostPrimitive = Mock.Of(p => p.Name == "shp" && p.NdmElement == new NdmElement()); + var sourcePrimitive2 = Mock.Of(p => p.Name == "sp2" && p.NdmElement == new NdmElement() && p.HostPrimitive == sourceHostPrimitive); + var sourcePrimitives = new List + { + sourcePrimitive1, + sourcePrimitive2 + }; + var sourceObjectMock = new Mock(); + sourceObjectMock.SetupGet(s => s.Primitives).Returns(sourcePrimitives); + + var clonedPrimitive1 = Mock.Of(p => p.Name == "cp1" && p.NdmElement == new NdmElement()); + var clonedPrimitive2 = Mock.Of(p => p.Name == "cp2" && p.NdmElement == new NdmElement() && p.HostPrimitive == sourceHostPrimitive); + var clonedHostPrimitive = Mock.Of(p => p.Name == "chp" && p.NdmElement == new NdmElement()); + + _cloningStrategyMock.Setup(cs => cs.Clone(sourcePrimitive1, null)).Returns(clonedPrimitive1); + _cloningStrategyMock.Setup(cs => cs.Clone(It.Is(p => p.Name == "sp2"), null)).Returns(clonedPrimitive2); + //_cloningStrategyMock.Setup(cs => cs.Clone(sourcePrimitive2, null)).Returns(clonedPrimitive2); + _cloningStrategyMock.Setup(cs => cs.Clone(sourcePrimitive2.HostPrimitive, null)).Returns(clonedHostPrimitive); + + // Act + _strategy.Update(targetObjectMock.Object, sourceObjectMock.Object); + + // Assert + //Assert.IsEmpty(targetPrimitives, "Target primitives should be cleared before adding new ones."); + Assert.That(targetPrimitives, Has.Count.EqualTo(2)); + Assert.That(targetPrimitives, Contains.Item(clonedPrimitive1)); + Assert.That(targetPrimitives, Contains.Item(clonedPrimitive2)); + + _cloningStrategyMock.Verify(cs => cs.Clone(sourcePrimitive1, null), Times.Once); + _cloningStrategyMock.Verify(cs => cs.Clone(It.Is(p => p.Name == "sp2"), null), Times.Once); + //_cloningStrategyMock.Verify(cs => cs.Clone(sourcePrimitive2, null), Times.Once); + _cloningStrategyMock.Verify(cs => cs.Clone(sourcePrimitive2.HostPrimitive, null), Times.Once); + } + } +} +