// Copyright (C) Stichting Deltares 2017. All rights reserved. // // This file is part of Ringtoets. // // Ringtoets 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 . // // All names, logos, and references to "Deltares" are registered trademarks of // Stichting Deltares and remain full property of Stichting Deltares at all times. // All rights reserved. using System; using System.Collections.Generic; using System.Linq; using Core.Common.Base; using Core.Common.Base.Data; using Core.Common.Base.Geometry; using Core.Common.TestUtil; using NUnit.Framework; using Ringtoets.ClosingStructures.Data; using Ringtoets.ClosingStructures.Data.TestUtil; using Ringtoets.Common.Data.Calculation; using Ringtoets.Common.Data.DikeProfiles; using Ringtoets.Common.Data.FailureMechanism; using Ringtoets.Common.Data.TestUtil; using Ringtoets.GrassCoverErosionOutwards.Data; using Ringtoets.HeightStructures.Data; using Ringtoets.HeightStructures.Data.TestUtil; using Ringtoets.Integration.Plugin.FileImporters; using Ringtoets.Integration.TestUtils; using Ringtoets.Revetment.TestUtil; using Ringtoets.StabilityPointStructures.Data; using Ringtoets.StabilityPointStructures.Data.TestUtil; using Ringtoets.StabilityStoneCover.Data; using Ringtoets.WaveImpactAsphaltCover.Data; namespace Ringtoets.Integration.Test.FileImporters { [TestFixture] public class ForeshoreProfileUpdateDataStrategyIntegrationTest { private const string sourceFilePath = "path/to/foreshoreProfiles"; [Test] [TestCaseSource(nameof(GetSupportedFailureMechanisms))] public void UpdateForeshoreProfilesWithImportedData_SupportedFailureMechanisms_UpdatesAffectedCalculationAndReturnsAffectedData( IFailureMechanism failureMechanism, ForeshoreProfileCollection foreshoreProfiles, ForeshoreProfile unaffectedForeshoreProfile) { // Setup ForeshoreProfile profileToBeUpdated = foreshoreProfiles[0]; ForeshoreProfile profileToUpdateFrom = DeepCloneAndModify(profileToBeUpdated); ForeshoreProfile profileToBeRemoved = foreshoreProfiles[1]; var strategy = new ForeshoreProfileUpdateDataStrategy(failureMechanism); ICalculation[] calculationsWithUpdatedForeshoreProfile = failureMechanism.Calculations .Cast>() .Where(calc => ReferenceEquals(GetForeshoreProfile(calc), profileToBeUpdated)) .ToArray(); ICalculation[] calculationsWithUpdatedForeshoreProfileWithOutputs = calculationsWithUpdatedForeshoreProfile.Where(calc => calc.HasOutput) .ToArray(); ICalculation[] calculationsWithRemovedForeshoreProfile = failureMechanism.Calculations .Cast>() .Where(calc => ReferenceEquals(GetForeshoreProfile(calc), profileToBeRemoved)) .ToArray(); ICalculation[] calculationsWithRemovedForeshoreProfileWithOutputs = calculationsWithRemovedForeshoreProfile.Where(calc => calc.HasOutput) .ToArray(); ICalculation[] calculationsWithUnaffectedForeshoreProfile = failureMechanism.Calculations .Cast>() .Where(calc => ReferenceEquals(GetForeshoreProfile(calc), unaffectedForeshoreProfile)) .ToArray(); ICalculation[] calculationsWithUnaffectedForeshoreProfileAndOutput = failureMechanism.Calculations .Cast>() .Where(calc => ReferenceEquals(GetForeshoreProfile(calc), unaffectedForeshoreProfile)) .ToArray(); // Call IEnumerable affectedObjects = strategy.UpdateForeshoreProfilesWithImportedData(foreshoreProfiles, new[] { profileToUpdateFrom, new TestForeshoreProfile(unaffectedForeshoreProfile.Name, unaffectedForeshoreProfile.Id) }, sourceFilePath); // Assert Assert.IsTrue(calculationsWithUnaffectedForeshoreProfileAndOutput.All(calc => calc.HasOutput)); Assert.IsTrue(calculationsWithUnaffectedForeshoreProfile.All(calc => ReferenceEquals(GetForeshoreProfile(calc), unaffectedForeshoreProfile))); Assert.IsTrue(calculationsWithUpdatedForeshoreProfile.All(calc => !calc.HasOutput)); Assert.IsTrue(calculationsWithUpdatedForeshoreProfile.All(calc => ReferenceEquals(GetForeshoreProfile(calc), profileToBeUpdated))); Assert.IsTrue(calculationsWithRemovedForeshoreProfile.All(calc => !calc.HasOutput)); Assert.IsTrue(calculationsWithRemovedForeshoreProfile.All(calc => GetForeshoreProfile(calc) == null)); var expectedAffectedObjects = new List { foreshoreProfiles, profileToBeUpdated }; expectedAffectedObjects.AddRange(calculationsWithUpdatedForeshoreProfileWithOutputs); expectedAffectedObjects.AddRange(calculationsWithRemovedForeshoreProfileWithOutputs); expectedAffectedObjects.AddRange(calculationsWithUpdatedForeshoreProfile.Select(calc => calc.InputParameters)); expectedAffectedObjects.AddRange(calculationsWithRemovedForeshoreProfile.Select(calc => calc.InputParameters)); CollectionAssert.AreEquivalent(expectedAffectedObjects, affectedObjects); } private static ForeshoreProfile GetForeshoreProfile(ICalculation calc) { return ((IHasForeshoreProfile) calc.InputParameters).ForeshoreProfile; } /// /// Makes a deep clone of the foreshore profile and modifies all the properties, /// except the . /// /// The foreshore profile to deep clone. /// A deep clone of the . private static ForeshoreProfile DeepCloneAndModify(ForeshoreProfile foreshoreProfile) { var random = new Random(21); Point2D originalWorldCoordinate = foreshoreProfile.WorldReferencePoint; var modifiedWorldCoordinate = new Point2D(originalWorldCoordinate.X + random.NextDouble(), originalWorldCoordinate.Y + random.NextDouble()); List modifiedForeshoreGeometry = foreshoreProfile.Geometry.ToList(); modifiedForeshoreGeometry.Add(new Point2D(1, 2)); RoundedDouble originalBreakWaterHeight = foreshoreProfile.BreakWater?.Height ?? (RoundedDouble) 0.0; var modifiedBreakWater = new BreakWater(random.NextEnumValue(), originalBreakWaterHeight + random.NextDouble()); string modifiedName = $"new_name_{foreshoreProfile.Name}"; double modifiedOrientation = foreshoreProfile.Orientation + random.NextDouble(); double modifiedX0 = foreshoreProfile.X0 + random.NextDouble(); return new ForeshoreProfile(modifiedWorldCoordinate, modifiedForeshoreGeometry, modifiedBreakWater, new ForeshoreProfile.ConstructionProperties { Name = modifiedName, Id = foreshoreProfile.Id, Orientation = modifiedOrientation, X0 = modifiedX0 }); } #region TestData private static IEnumerable GetSupportedFailureMechanisms() { const string unaffectedProfileName = "Custom Profile"; const string unaffectedProfileId = "Custom ID"; var unaffectedForeshoreProfile = new TestForeshoreProfile(unaffectedProfileName, unaffectedProfileId); WaveImpactAsphaltCoverFailureMechanism waveImpactAsphaltCoverFailureMechanism = CreateWaveImpactAsphaltCoverFailureMechanismWithAllUpdateForeshoreProfileScenarios(unaffectedForeshoreProfile); yield return new TestCaseData( waveImpactAsphaltCoverFailureMechanism, waveImpactAsphaltCoverFailureMechanism.ForeshoreProfiles, unaffectedForeshoreProfile) .SetName("WaveImpactAsphaltCoverFailureMechanism"); GrassCoverErosionOutwardsFailureMechanism grassCoverErosionOutwardsFailureMechanism = CreateGrassCoverErosionOutwardsFailureMechanismWithAllUpdateForeshoreProfileScenarios(unaffectedForeshoreProfile); yield return new TestCaseData( grassCoverErosionOutwardsFailureMechanism, grassCoverErosionOutwardsFailureMechanism.ForeshoreProfiles, unaffectedForeshoreProfile) .SetName("GrassCoverErosionOutwardsFailureMechanism"); StabilityStoneCoverFailureMechanism stabilityStoneCoverFailureMechanism = CreateStabilityStoneCoverFailureMechanismWithAllUpdateForeshoreProfileScenarios(unaffectedForeshoreProfile); yield return new TestCaseData( stabilityStoneCoverFailureMechanism, stabilityStoneCoverFailureMechanism.ForeshoreProfiles, unaffectedForeshoreProfile) .SetName("StabilityStoneCoverFailureMechanism"); StabilityPointStructuresFailureMechanism stabilityPointStructuresFailureMechanism = CreateStabilityPointStructuresFailureMechanismWithAllUpdateForeshoreProfileScenarios(unaffectedForeshoreProfile); yield return new TestCaseData( stabilityPointStructuresFailureMechanism, stabilityPointStructuresFailureMechanism.ForeshoreProfiles, unaffectedForeshoreProfile) .SetName("StabilityPointStructuresFailureMechanism"); ClosingStructuresFailureMechanism closingStructuresFailureMechanism = CreateClosingStructuresFailureMechanismWithAllUpdateForeshoreProfileScenarios(unaffectedForeshoreProfile); yield return new TestCaseData( closingStructuresFailureMechanism, closingStructuresFailureMechanism.ForeshoreProfiles, unaffectedForeshoreProfile) .SetName("ClosingStructuresFailureMechanism"); HeightStructuresFailureMechanism heightStructuresFailureMechanism = CreateHeightStructuresFailureMechanismWithAllUpdateForeshoreProfileScenarios(unaffectedForeshoreProfile); yield return new TestCaseData( heightStructuresFailureMechanism, heightStructuresFailureMechanism.ForeshoreProfiles, unaffectedForeshoreProfile) .SetName("HeightStructuresFailureMechanism"); } private static WaveImpactAsphaltCoverFailureMechanism CreateWaveImpactAsphaltCoverFailureMechanismWithAllUpdateForeshoreProfileScenarios( ForeshoreProfile unaffectedForeshoreProfile) { WaveImpactAsphaltCoverFailureMechanism waveImpactAsphaltCoverFailureMechanism = TestDataGenerator.GetWaveImpactAsphaltCoverFailureMechanismWithAllCalculationConfigurations(); waveImpactAsphaltCoverFailureMechanism.ForeshoreProfiles.AddRange(new[] { unaffectedForeshoreProfile }, sourceFilePath); var unaffectedCalculation = new WaveImpactAsphaltCoverWaveConditionsCalculation { InputParameters = { ForeshoreProfile = unaffectedForeshoreProfile }, Output = new WaveImpactAsphaltCoverWaveConditionsOutput(new[] { new TestWaveConditionsOutput() }) }; waveImpactAsphaltCoverFailureMechanism.WaveConditionsCalculationGroup.Children.Add(unaffectedCalculation); return waveImpactAsphaltCoverFailureMechanism; } private static GrassCoverErosionOutwardsFailureMechanism CreateGrassCoverErosionOutwardsFailureMechanismWithAllUpdateForeshoreProfileScenarios( ForeshoreProfile unaffectedForeshoreProfile) { GrassCoverErosionOutwardsFailureMechanism grassCoverErosionOutwardsFailureMechanism = TestDataGenerator.GetGrassCoverErosionOutwardsFailureMechanismWithAllCalculationConfigurations(); grassCoverErosionOutwardsFailureMechanism.ForeshoreProfiles.AddRange(new[] { unaffectedForeshoreProfile }, sourceFilePath); var unaffectedCalculation = new GrassCoverErosionOutwardsWaveConditionsCalculation { InputParameters = { ForeshoreProfile = unaffectedForeshoreProfile }, Output = new GrassCoverErosionOutwardsWaveConditionsOutput(new[] { new TestWaveConditionsOutput() }) }; grassCoverErosionOutwardsFailureMechanism.WaveConditionsCalculationGroup.Children.Add(unaffectedCalculation); return grassCoverErosionOutwardsFailureMechanism; } private static StabilityStoneCoverFailureMechanism CreateStabilityStoneCoverFailureMechanismWithAllUpdateForeshoreProfileScenarios( ForeshoreProfile unaffectedForeshoreProfile) { StabilityStoneCoverFailureMechanism stabilityStoneCoverFailureMechanism = TestDataGenerator.GetStabilityStoneCoverFailureMechanismWithAllCalculationConfigurations(); stabilityStoneCoverFailureMechanism.ForeshoreProfiles.AddRange(new[] { unaffectedForeshoreProfile }, sourceFilePath); var unaffectedCalculation = new StabilityStoneCoverWaveConditionsCalculation { InputParameters = { ForeshoreProfile = unaffectedForeshoreProfile }, Output = new StabilityStoneCoverWaveConditionsOutput(new[] { new TestWaveConditionsOutput() }, new[] { new TestWaveConditionsOutput() }) }; stabilityStoneCoverFailureMechanism.WaveConditionsCalculationGroup.Children.Add(unaffectedCalculation); return stabilityStoneCoverFailureMechanism; } private static HeightStructuresFailureMechanism CreateHeightStructuresFailureMechanismWithAllUpdateForeshoreProfileScenarios( ForeshoreProfile unaffectedForeshoreProfile) { HeightStructuresFailureMechanism heightStructuresFailureMechanism = TestDataGenerator.GetHeightStructuresFailureMechanismWithAlLCalculationConfigurations(); heightStructuresFailureMechanism.ForeshoreProfiles.AddRange(new[] { unaffectedForeshoreProfile }, sourceFilePath); var unaffectedCalculation = new TestHeightStructuresCalculation { InputParameters = { ForeshoreProfile = unaffectedForeshoreProfile }, Output = new TestStructuresOutput() }; heightStructuresFailureMechanism.CalculationsGroup.Children.Add(unaffectedCalculation); return heightStructuresFailureMechanism; } private static ClosingStructuresFailureMechanism CreateClosingStructuresFailureMechanismWithAllUpdateForeshoreProfileScenarios( ForeshoreProfile unaffectedForeshoreProfile) { ClosingStructuresFailureMechanism closingStructuresFailureMechanism = TestDataGenerator.GetClosingStructuresFailureMechanismWithAllCalculationConfigurations(); closingStructuresFailureMechanism.ForeshoreProfiles.AddRange(new[] { unaffectedForeshoreProfile }, sourceFilePath); var unaffectedCalculation = new TestClosingStructuresCalculation { InputParameters = { ForeshoreProfile = unaffectedForeshoreProfile }, Output = new TestStructuresOutput() }; closingStructuresFailureMechanism.CalculationsGroup.Children.Add(unaffectedCalculation); return closingStructuresFailureMechanism; } private static StabilityPointStructuresFailureMechanism CreateStabilityPointStructuresFailureMechanismWithAllUpdateForeshoreProfileScenarios( ForeshoreProfile unaffectedForeshoreProfile) { StabilityPointStructuresFailureMechanism stabilityPointStructuresFailureMechanism = TestDataGenerator.GetStabilityPointStructuresFailureMechanismWithAllCalculationConfigurations(); stabilityPointStructuresFailureMechanism.ForeshoreProfiles.AddRange(new[] { unaffectedForeshoreProfile }, sourceFilePath); var unaffectedCalculation = new TestStabilityPointStructuresCalculation { InputParameters = { ForeshoreProfile = unaffectedForeshoreProfile }, Output = new TestStructuresOutput() }; stabilityPointStructuresFailureMechanism.CalculationsGroup.Children.Add(unaffectedCalculation); return stabilityPointStructuresFailureMechanism; } #endregion } }