Add calculators cloning logic

This commit is contained in:
Evgeny Redikultsev
2024-12-07 20:50:21 +05:00
parent ccaf9a927c
commit 0538c6b53c
18 changed files with 776 additions and 109 deletions

View File

@@ -0,0 +1,89 @@
using Moq;
using NUnit.Framework;
using StructureHelperCommon.Infrastructures.Exceptions;
using StructureHelperCommon.Infrastructures.Interfaces;
using StructureHelperLogics.NdmCalculations.Analyses.ByForces.Logics;
using StructureHelperLogics.NdmCalculations.Cracking;
using StructureHelperLogics.NdmCalculations.Primitives;
namespace StructureHelperTests.UnitTests.UpdateStrategiesTests
{
[TestFixture]
public class CrackCalculatorUpdateCloningStrategyTests
{
private Mock<ICloningStrategy> _cloningStrategyMock;
private Mock<IUpdateStrategy<IHasForceActions>> _forcesUpdateStrategyMock;
private Mock<IUpdateStrategy<IHasPrimitives>> _primitivesUpdateStrategyMock;
private CrackCalculatorUpdateCloningStrategy _strategy;
[SetUp]
public void SetUp()
{
_cloningStrategyMock = new Mock<ICloningStrategy>();
_forcesUpdateStrategyMock = new Mock<IUpdateStrategy<IHasForceActions>>();
_primitivesUpdateStrategyMock = new Mock<IUpdateStrategy<IHasPrimitives>>();
_strategy = new CrackCalculatorUpdateCloningStrategy(
_cloningStrategyMock.Object,
_forcesUpdateStrategyMock.Object,
_primitivesUpdateStrategyMock.Object
);
}
[Test]
public void Update_WithNullSourceObject_ThrowsException()
{
// Arrange
var targetObject = Mock.Of<ICrackCalculator>();
// Act & Assert
Assert.Throws<StructureHelperException>(() => _strategy.Update(targetObject, null));
}
[Test]
public void Update_WithNullTargetObject_ThrowsException()
{
// Arrange
var sourceObject = Mock.Of<ICrackCalculator>();
// Act & Assert
Assert.Throws<StructureHelperException>(() => _strategy.Update(null, sourceObject));
}
[Test]
public void Update_WithSameSourceAndTarget_DoesNothing()
{
// Arrange
var sourceObject = Mock.Of<ICrackCalculator>();
// Act
_strategy.Update(sourceObject, sourceObject);
// Assert
_forcesUpdateStrategyMock.VerifyNoOtherCalls();
_primitivesUpdateStrategyMock.VerifyNoOtherCalls();
}
[Test]
public void Update_InvokesUpdateStrategiesOnInputData()
{
// Arrange
var sourceDataMock = new Mock<ICrackCalculatorInputData>();
var targetDataMock = new Mock<ICrackCalculatorInputData>();
var sourceObjectMock = new Mock<ICrackCalculator>();
sourceObjectMock.Setup(s => s.InputData).Returns(sourceDataMock.Object);
var targetObjectMock = new Mock<ICrackCalculator>();
targetObjectMock.Setup(t => t.InputData).Returns(targetDataMock.Object);
// Act
_strategy.Update(targetObjectMock.Object, sourceObjectMock.Object);
// Assert
_primitivesUpdateStrategyMock.Verify(ps => ps.Update(targetDataMock.Object, sourceDataMock.Object), Times.Once);
_forcesUpdateStrategyMock.Verify(fs => fs.Update(targetDataMock.Object, sourceDataMock.Object), Times.Once);
}
}
}

View File

@@ -0,0 +1,117 @@
using Moq;
using NUnit.Framework;
using StructureHelperCommon.Infrastructures.Exceptions;
using StructureHelperCommon.Infrastructures.Interfaces;
namespace StructureHelperTests.UnitTests.UpdateStrategiesTests
{
[TestFixture]
public class DeepCloningStrategyTests
{
private DeepCloningStrategy _strategy;
[SetUp]
public void SetUp()
{
_strategy = new DeepCloningStrategy();
}
[Test]
public void Clone_WithNullOriginal_ReturnsNull()
{
// Act
var result = _strategy.Clone<object>(null);
// Assert
Assert.IsNull(result);
}
[Test]
public void Clone_WhenObjectAlreadyCloned_ReturnsExistingClone()
{
// Arrange
var original = new Mock<ICloneable>().Object;
var expectedClone = new Mock<ICloneable>().Object;
// Use reflection to populate the internal dictionary (_clonedObjects)
var clonedObjects = new Dictionary<object, object> { { original, expectedClone } };
var internalField = typeof(DeepCloningStrategy).GetField("_clonedObjects", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
internalField.SetValue(_strategy, clonedObjects);
// Act
var result = _strategy.Clone(original);
// Assert
Assert.AreSame(expectedClone, result);
}
[Test]
public void Clone_WithCustomCloneStrategy_UsesCloneStrategyToCloneObject()
{
// Arrange
var original = new Mock<ICloneable>().Object;
var expectedClone = new Mock<ICloneable>().Object;
var cloneStrategyMock = new Mock<ICloneStrategy<ICloneable>>();
cloneStrategyMock.Setup(cs => cs.GetClone(original)).Returns(expectedClone);
// Act
var result = _strategy.Clone(original, cloneStrategyMock.Object);
// Assert
Assert.AreSame(expectedClone, result);
cloneStrategyMock.Verify(cs => cs.GetClone(original), Times.Once);
}
[Test]
public void Clone_WhenObjectImplementsICloneable_UsesCloneMethod()
{
// Arrange
var originalMock = new Mock<ICloneable>();
var expectedClone = new Mock<ICloneable>().Object;
originalMock.Setup(o => o.Clone()).Returns(expectedClone);
// Act
var result = _strategy.Clone(originalMock.Object);
// Assert
Assert.AreSame(expectedClone, result);
originalMock.Verify(o => o.Clone(), Times.Once);
}
[Test]
public void Clone_WhenObjectNotCloneableAndNoCloneStrategy_ThrowsStructureHelperException()
{
// Arrange
var original = new object(); // Not ICloneable
// Act & Assert
var exception = Assert.Throws<StructureHelperException>(() => _strategy.Clone(original));
Assert.That(exception.Message, Does.Contain("object is not IClonable and cloning strategy is null"));
}
[Test]
public void Clone_AddsClonedObjectToDictionary()
{
// Arrange
var originalMock = new Mock<ICloneable>();
var expectedClone = new Mock<ICloneable>().Object;
originalMock.Setup(o => o.Clone()).Returns(expectedClone);
// Act
var result = _strategy.Clone(originalMock.Object);
// Use reflection to check the private dictionary (_clonedObjects)
var internalField = typeof(DeepCloningStrategy).GetField("_clonedObjects", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
var clonedObjects = (Dictionary<object, object>)internalField.GetValue(_strategy);
// Assert
Assert.AreSame(expectedClone, clonedObjects[originalMock.Object]);
}
}
}

View File

@@ -0,0 +1,91 @@
using Moq;
using NUnit.Framework;
using StructureHelperCommon.Infrastructures.Exceptions;
using StructureHelperCommon.Infrastructures.Interfaces;
using StructureHelperLogics.NdmCalculations.Analyses.ByForces.Logics;
using StructureHelperLogics.NdmCalculations.Analyses.ByForces;
using StructureHelperLogics.NdmCalculations.Primitives;
namespace StructureHelperTests.UnitTests.UpdateStrategiesTests
{
[TestFixture]
public class ForceCalculatorUpdateCloningStrategyTests
{
private Mock<ICloningStrategy> _cloningStrategyMock;
private Mock<IUpdateStrategy<IHasForceActions>> _forcesUpdateStrategyMock;
private Mock<IUpdateStrategy<IHasPrimitives>> _primitivesUpdateStrategyMock;
private ForceCalculatorUpdateCloningStrategy _strategy;
[SetUp]
public void SetUp()
{
_cloningStrategyMock = new Mock<ICloningStrategy>();
_forcesUpdateStrategyMock = new Mock<IUpdateStrategy<IHasForceActions>>();
_primitivesUpdateStrategyMock = new Mock<IUpdateStrategy<IHasPrimitives>>();
_strategy = new ForceCalculatorUpdateCloningStrategy(
_cloningStrategyMock.Object,
_forcesUpdateStrategyMock.Object,
_primitivesUpdateStrategyMock.Object
);
}
[Test]
public void Update_WithNullSourceObject_ThrowsException()
{
// Arrange
var targetObject = Mock.Of<IForceCalculator>();
// Act & Assert
Assert.Throws<StructureHelperException>(() => _strategy.Update(targetObject, null));
}
[Test]
public void Update_WithNullTargetObject_ThrowsException()
{
// Arrange
var sourceObject = Mock.Of<IForceCalculator>();
// Act & Assert
Assert.Throws<StructureHelperException>(() => _strategy.Update(null, sourceObject));
}
[Test]
public void Update_WithSameSourceAndTarget_DoesNothing()
{
// Arrange
var sourceObject = Mock.Of<IForceCalculator>();
// Act
_strategy.Update(sourceObject, sourceObject);
// Assert
_forcesUpdateStrategyMock.VerifyNoOtherCalls();
_primitivesUpdateStrategyMock.VerifyNoOtherCalls();
}
[Test]
public void Update_InvokesUpdateStrategiesOnInputData()
{
// Arrange
var sourceDataMock = new Mock<IForceCalculatorInputData>();
var targetDataMock = new Mock<IForceCalculatorInputData>();
var sourceObjectMock = new Mock<IForceCalculator>();
sourceObjectMock.Setup(s => s.InputData).Returns(sourceDataMock.Object);
var targetObjectMock = new Mock<IForceCalculator>();
targetObjectMock.Setup(t => t.InputData).Returns(targetDataMock.Object);
// Act
_strategy.Update(targetObjectMock.Object, sourceObjectMock.Object);
// Assert
_primitivesUpdateStrategyMock.Verify(ps => ps.Update(targetDataMock.Object, sourceDataMock.Object), Times.Once);
_forcesUpdateStrategyMock.Verify(fs => fs.Update(targetDataMock.Object, sourceDataMock.Object), Times.Once);
}
}
}

View File

@@ -0,0 +1,138 @@
using Moq;
using NUnit.Framework;
using StructureHelperCommon.Infrastructures.Exceptions;
using StructureHelperCommon.Infrastructures.Interfaces;
using StructureHelperCommon.Models.Calculators;
using StructureHelperLogics.NdmCalculations.Analyses.ByForces;
using StructureHelperLogics.NdmCalculations.Cracking;
using System;
using System.Collections.Generic;
namespace StructureHelperTests.UnitTests.UpdateStrategiesTests
{
[TestFixture]
public class HasCalculatorsUpdateCloningStrategyTests
{
private Mock<ICloningStrategy> _cloningStrategyMock;
private Mock<IUpdateStrategy<IForceCalculator>> _forceCalculatorUpdateStrategyMock;
private Mock<IUpdateStrategy<ICrackCalculator>> _crackCalculatorUpdateStrategyMock;
private Mock<IUpdateStrategy<ILimitCurvesCalculator>> _limitCurvesCalculatorUpdateStrategyMock;
private HasCalculatorsUpdateCloningStrategy _strategy;
[SetUp]
public void SetUp()
{
_cloningStrategyMock = new Mock<ICloningStrategy>();
_forceCalculatorUpdateStrategyMock = new Mock<IUpdateStrategy<IForceCalculator>>();
_crackCalculatorUpdateStrategyMock = new Mock<IUpdateStrategy<ICrackCalculator>>();
_limitCurvesCalculatorUpdateStrategyMock = new Mock<IUpdateStrategy<ILimitCurvesCalculator>>();
_strategy = new HasCalculatorsUpdateCloningStrategy(
_cloningStrategyMock.Object,
_forceCalculatorUpdateStrategyMock.Object,
_crackCalculatorUpdateStrategyMock.Object,
_limitCurvesCalculatorUpdateStrategyMock.Object
);
}
[Test]
public void Update_WithNullSourceObject_ThrowsException()
{
// Arrange
var targetObject = Mock.Of<IHasCalculators>();
// Act & Assert
Assert.Throws<StructureHelperException>(() => _strategy.Update(targetObject, null));
}
[Test]
public void Update_WithNullTargetObject_ThrowsException()
{
// Arrange
var sourceObject = Mock.Of<IHasCalculators>();
// Act & Assert
Assert.Throws<StructureHelperException>(() => _strategy.Update(null, sourceObject));
}
[Test]
public void Update_WithSameSourceAndTarget_DoesNothing()
{
// Arrange
var calculators = new List<ICalculator> { Mock.Of<IForceCalculator>() };
var sourceObject = Mock.Of<IHasCalculators>(s => s.Calculators == calculators);
var targetObject = sourceObject;
// Act
_strategy.Update(targetObject, sourceObject);
// Assert
_cloningStrategyMock.VerifyNoOtherCalls();
_forceCalculatorUpdateStrategyMock.VerifyNoOtherCalls();
_crackCalculatorUpdateStrategyMock.VerifyNoOtherCalls();
_limitCurvesCalculatorUpdateStrategyMock.VerifyNoOtherCalls();
}
[Test]
public void Update_ProcessesEachCalculatorCorrectly()
{
// Arrange
var sourceForceCalculator = Mock.Of<IForceCalculator>(x => x.Name == "Force");
var sourceCrackCalculator = Mock.Of<ICrackCalculator>(x => x.Name == "Crack");
var sourceLimitCurvesCalculator = Mock.Of<ILimitCurvesCalculator>(x => x.Name == "Curves");
var sourceCalculators = new List<ICalculator>
{
sourceForceCalculator,
sourceCrackCalculator,
sourceLimitCurvesCalculator
};
var sourceObjectMock = new Mock<IHasCalculators>();
sourceObjectMock.Setup(s => s.Calculators).Returns(sourceCalculators);
var targetCalculators = new List<ICalculator>();
var targetObjectMock = new Mock<IHasCalculators>();
targetObjectMock.Setup(t => t.Calculators).Returns(targetCalculators);
var clonedForceCalculator = Mock.Of<IForceCalculator>();
var clonedCrackCalculator = Mock.Of<ICrackCalculator>();
var clonedLimitCurvesCalculator = Mock.Of<ILimitCurvesCalculator>();
_cloningStrategyMock.Setup(cs => cs.Clone(It.Is<ICalculator>(x => x.Name == "Force"), null)).Returns(clonedForceCalculator);
_cloningStrategyMock.Setup(cs => cs.Clone(It.Is<ICalculator>(x => x.Name == "Crack"), null)).Returns(clonedCrackCalculator);
_cloningStrategyMock.Setup(cs => cs.Clone(It.Is<ICalculator>(x => x.Name == "Curves"), null)).Returns(clonedLimitCurvesCalculator);
// Act
_strategy.Update(targetObjectMock.Object, sourceObjectMock.Object);
// Assert
Assert.That(targetCalculators, Has.Count.EqualTo(3));
Assert.That(targetCalculators, Contains.Item(clonedForceCalculator));
Assert.That(targetCalculators, Contains.Item(clonedCrackCalculator));
Assert.That(targetCalculators, Contains.Item(clonedLimitCurvesCalculator));
_forceCalculatorUpdateStrategyMock.Verify(f => f.Update(clonedForceCalculator, sourceForceCalculator), Times.Once);
_crackCalculatorUpdateStrategyMock.Verify(c => c.Update(clonedCrackCalculator, sourceCrackCalculator), Times.Once);
_limitCurvesCalculatorUpdateStrategyMock.Verify(l => l.Update(clonedLimitCurvesCalculator, sourceLimitCurvesCalculator), Times.Once);
}
[Test]
public void Update_WithUnknownCalculatorType_ThrowsException()
{
// Arrange
var unknownCalculator = Mock.Of<ICalculator>();
var sourceCalculators = new List<ICalculator> { unknownCalculator };
var sourceObjectMock = new Mock<IHasCalculators>();
sourceObjectMock.Setup(s => s.Calculators).Returns(sourceCalculators);
var targetObjectMock = new Mock<IHasCalculators>();
targetObjectMock.Setup(t => t.Calculators).Returns(new List<ICalculator>());
// Act & Assert
var exception = Assert.Throws<StructureHelperException>(() => _strategy.Update(targetObjectMock.Object, sourceObjectMock.Object));
Assert.That(exception.Message, Does.Contain(ErrorStrings.ObjectTypeIsUnknown));
}
}
}

View File

@@ -0,0 +1,111 @@
using Moq;
using NUnit.Framework;
using StructureHelperCommon.Infrastructures.Exceptions;
using StructureHelperCommon.Infrastructures.Interfaces;
using StructureHelperCommon.Models.Parameters;
using StructureHelperLogics.NdmCalculations.Analyses.ByForces;
using StructureHelperLogics.NdmCalculations.Analyses.ByForces.LimitCurve;
using StructureHelperLogics.NdmCalculations.Primitives;
namespace StructureHelperTests.UnitTests.UpdateStrategiesTests
{
[TestFixture]
public class LimitCurvesCalculatorUpdateCloningStrategyTests
{
private Mock<ICloningStrategy> _cloningStrategyMock;
private Mock<IUpdateStrategy<ILimitCurvesCalculatorInputData>> _inputDataUpdateStrategyMock;
private LimitCurvesCalculatorUpdateCloningStrategy _strategy;
[SetUp]
public void SetUp()
{
_cloningStrategyMock = new Mock<ICloningStrategy>();
_inputDataUpdateStrategyMock = new Mock<IUpdateStrategy<ILimitCurvesCalculatorInputData>>();
_strategy = new LimitCurvesCalculatorUpdateCloningStrategy(
_cloningStrategyMock.Object,
_inputDataUpdateStrategyMock.Object);
}
[Test]
public void Update_WithNullSourceObject_ThrowsException()
{
// Arrange
var targetObject = Mock.Of<ILimitCurvesCalculator>();
// Act & Assert
Assert.Throws<StructureHelperException>(() => _strategy.Update(targetObject, null));
}
[Test]
public void Update_WithNullTargetObject_ThrowsException()
{
// Arrange
var sourceObject = Mock.Of<ILimitCurvesCalculator>();
// Act & Assert
Assert.Throws<StructureHelperException>(() => _strategy.Update(null, sourceObject));
}
[Test]
public void Update_WithSameSourceAndTarget_DoesNothing()
{
// Arrange
var sourceObject = Mock.Of<ILimitCurvesCalculator>();
// Act
_strategy.Update(sourceObject, sourceObject);
// Assert
_cloningStrategyMock.VerifyNoOtherCalls();
_inputDataUpdateStrategyMock.VerifyNoOtherCalls();
}
//[Test]
public void Update_UpdatesInputDataAndProcessesEachPrimitiveSeries()
{
// Arrange
var targetSeries = new NamedCollection<INdmPrimitive> { Collection = new List<INdmPrimitive>() };
var targetData = Mock.Of<ILimitCurvesCalculatorInputData>(d => d.PrimitiveSeries == new List<NamedCollection<INdmPrimitive>> { targetSeries });
var targetObjectMock = new Mock<ILimitCurvesCalculator>();
targetObjectMock.Setup(t => t.InputData).Returns(targetData);
var sourcePrimitive1 = Mock.Of<INdmPrimitive>(p => p.Name == "sp1");
var sourcePrimitive2 = Mock.Of<INdmPrimitive>(p => p.Name == "sp2");
var sourceSeries = new NamedCollection<INdmPrimitive>
{
Collection = new List<INdmPrimitive> { sourcePrimitive1, sourcePrimitive2 }
};
var sourceData = Mock.Of<ILimitCurvesCalculatorInputData>(d => d.PrimitiveSeries == new List<NamedCollection<INdmPrimitive>> { sourceSeries });
var sourceObjectMock = new Mock<ILimitCurvesCalculator>();
sourceObjectMock.Setup(s => s.InputData).Returns(sourceData);
var clonedPrimitive1 = Mock.Of<INdmPrimitive>(p => p.Name == "cp1");
var clonedPrimitive2 = Mock.Of<INdmPrimitive>(p => p.Name == "cp2");
_cloningStrategyMock.Setup(cs => cs.Clone(It.Is<INdmPrimitive>(p => p.Name == "sp1"), null)).Returns(clonedPrimitive1);
_cloningStrategyMock.Setup(cs => cs.Clone(It.Is<INdmPrimitive>(p => p.Name == "sp2"), null)).Returns(clonedPrimitive2);
// Act
_strategy.Update(targetObjectMock.Object, sourceObjectMock.Object);
// Assert
_inputDataUpdateStrategyMock.Verify(
us => us.Update(targetData, sourceData),
Times.Once);
Assert.That(targetSeries.Collection, Has.Count.EqualTo(2));
Assert.That(targetSeries.Collection, Contains.Item(clonedPrimitive1));
Assert.That(targetSeries.Collection, Contains.Item(clonedPrimitive2));
_cloningStrategyMock.Verify(cs => cs.Clone(sourcePrimitive1, null), Times.Once);
_cloningStrategyMock.Verify(cs => cs.Clone(sourcePrimitive2, null), Times.Once);
}
}
}