// Copyright (C) Stichting Deltares 2019. All rights reserved. // // This file is part of the Dam Engine. // // The Dam Engine is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero 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 Affero General Public License for more details. // // You should have received a copy of the GNU Affero 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.Collections.Generic; using System.Data; using System.IO; using System.Xml.Schema; using Deltares.DamEngine.Calculators.KernelWrappers.Common; using Deltares.DamEngine.Calculators.KernelWrappers.DamMacroStabilityCommon; using Deltares.DamEngine.Calculators.KernelWrappers.Interfaces; using Deltares.DamEngine.Calculators.KernelWrappers.MacroStabilityInwards; using Deltares.DamEngine.Calculators.Tests.KernelWrappers.DamMacroStabilityCommon; using Deltares.DamEngine.Data.Design; using Deltares.DamEngine.Data.General; using Deltares.DamEngine.Data.General.Results; using Deltares.DamEngine.Data.Standard.Calculation; using Deltares.DamEngine.TestHelpers.Factories; using Deltares.MacroStability.Geometry; using Deltares.MacroStability.Standard; using NUnit.Framework; using LogMessage = Deltares.DamEngine.Data.Standard.Logging.LogMessage; using LogMessageType = Deltares.DamEngine.Data.Standard.Logging.LogMessageType; namespace Deltares.DamEngine.Calculators.Tests.KernelWrappers.MacroStabilityInwards { [TestFixture] public class MacroStabilityInwardsKernelWrapperTests { private const string TestFolder = @"..\..\Deltares.DamEngine.Calculators.Tests\KernelWrappers\MacroStabilityInwards\TestFiles"; [Test] public void TestPrepare() { var kernelWrapper = new MacroStabilityInwardsKernelWrapper(); kernelWrapper.CreateStabilityCalculator(); kernelWrapper.FailureMechanismParametersMStab = new FailureMechanismParametersMStab(); IKernelDataInput kernelDataInput; IKernelDataOutput kernelDataOutput; var kernelInput = CreateDamKernelInputForTest(); // Situation 1: no uplift. Expected PrepareResult.NotRelevant kernelInput.Location.ModelFactors.UpliftCriterionStability = 0.8; var prepareResult = kernelWrapper.Prepare(kernelInput, 0, out kernelDataInput, out kernelDataOutput); Assert.AreEqual(PrepareResult.NotRelevant, prepareResult); MacroStabilityOutput damMacroStabilityOutput = (MacroStabilityOutput)kernelDataOutput; Assert.AreEqual(CalculationResult.NoRun, damMacroStabilityOutput.CalculationResult); Assert.AreEqual(false, damMacroStabilityOutput.UpliftSituation.IsUplift); // Situation 2: there is uplift and prepare succeeds. Expected PrepareResult.Successful kernelInput.Location.ModelFactors.UpliftCriterionStability = 1.2; // ToDo MWDAM-1356: Not clear yet what must be done in Prepare and XML input not written yet. kernelWrapper.tmpPresumePrepareSucceeds = true; //ToDo replace by input that makes prepare succeed prepareResult = kernelWrapper.Prepare(kernelInput, 0, out kernelDataInput, out kernelDataOutput); Assert.AreEqual(PrepareResult.Successful, prepareResult); damMacroStabilityOutput = (MacroStabilityOutput)kernelDataOutput; Assert.AreEqual(CalculationResult.NoRun, damMacroStabilityOutput.CalculationResult); Assert.AreEqual(true, damMacroStabilityOutput.UpliftSituation.IsUplift); // Situation 3: there is uplift and prepare fails. Expected PrepareResult.Failed kernelInput.Location.ModelFactors.UpliftCriterionStability = 1.2; // ToDo MWDAM-1356: Not clear yet what must be done in Prepare and XML input not written yet. kernelWrapper.tmpPresumePrepareSucceeds = false; //ToDo replace by input that makes prepare fail prepareResult = kernelWrapper.Prepare(kernelInput, 0, out kernelDataInput, out kernelDataOutput); Assert.AreEqual(PrepareResult.Failed, prepareResult); damMacroStabilityOutput = (MacroStabilityOutput)kernelDataOutput; Assert.AreEqual(CalculationResult.NoRun, damMacroStabilityOutput.CalculationResult); Assert.AreEqual(true, damMacroStabilityOutput.UpliftSituation.IsUplift); } [Test] public void TestValidate() { var kernelWrapper = new MacroStabilityInwardsKernelWrapper(); kernelWrapper.CreateStabilityCalculator(); // Validate without setting values. Expected error messages. var macroStabilityInput1 = new MacroStabilityInput(); var macroStabilityOutput1 = new MacroStabilityOutput(); macroStabilityOutput1.CalculationResult = CalculationResult.NoRun; List messages; var errorCount = kernelWrapper.Validate(macroStabilityInput1, macroStabilityOutput1, out messages); Assert.IsTrue(errorCount > 0); Assert.AreEqual(CalculationResult.InvalidInputData, macroStabilityOutput1.CalculationResult); // Validate the input when valid input is provided. Expected no messages. var macroStabilityInput2 = new MacroStabilityInput(); var macroStabilityOutput2 = new MacroStabilityOutput(); macroStabilityOutput2.CalculationResult = CalculationResult.NoRun; messages.Clear(); // ToDo MWDAM-1356: Not clear yet what input must be provided to make Validate succeed. Temporary test code added. // start of temporary test code kernelWrapper.tmpPresumeInputValid = true; //ToDo replace by input that makes Validate succeed // end of temporary test code errorCount = kernelWrapper.Validate(macroStabilityInput2, macroStabilityOutput2, out messages); Assert.IsTrue(errorCount == 0); Assert.AreEqual(CalculationResult.NoRun, macroStabilityOutput2.CalculationResult); } [Test] public void TestParseValidationResultOk() { List messages; var kernelWrapper = new MacroStabilityInwardsKernelWrapper(); var xmlFileName = Path.Combine(TestFolder, "ValidateOk.xml"); string xmlValidationResult = File.ReadAllText(xmlFileName); kernelWrapper.ParseValidationResult(xmlValidationResult, out messages); Assert.AreEqual(0, messages.Count); } [TestCase("ValidateInfo.xml", LogMessageType.Info, "Dit is een Info bericht voor test")] [TestCase("ValidateWarning.xml", LogMessageType.Warning, "Dit is een Waarschuwings bericht voor test")] [TestCase("ValidateError.xml", LogMessageType.Error, "Voor geval 'Klei dijk op klei' (1A) moet de laag onder de dijk geen watervoerende laag zijn.")] public void TestParseValidationResultMessages(string fileName, LogMessageType logMessageType, string message) { List messages; var kernelWrapper = new MacroStabilityInwardsKernelWrapper(); var xmlFileName = Path.Combine(TestFolder, fileName); string xmlValidationResult = File.ReadAllText(xmlFileName); kernelWrapper.ParseValidationResult(xmlValidationResult, out messages); Assert.AreEqual(1, messages.Count); Assert.AreEqual(logMessageType, messages[0].MessageType); Assert.AreEqual(message, messages[0].Message); } [Test] [ExpectedException(typeof(XmlSchemaValidationException), ExpectedMessage = "The 'Severity' attribute is invalid - The value 'Wrong' is invalid according to its datatype 'ValidationType' - The Enumeration constraint failed.")] public void TestParseValidationResultMessageWrongType() { List messages; var kernelWrapper = new MacroStabilityInwardsKernelWrapper(); var xmlFileName = Path.Combine(TestFolder, "ValidateWrong.xml"); string xmlValidationResult = File.ReadAllText(xmlFileName); kernelWrapper.ParseValidationResult(xmlValidationResult, out messages); } [TestCase(ValidationResultType.Info, LogMessageType.Info)] [TestCase(ValidationResultType.Warning, LogMessageType.Warning)] [TestCase(ValidationResultType.Error, LogMessageType.Error)] public void TestConvertKernelValidationResultTypeToLogMessageType(ValidationResultType validationResultType, LogMessageType logMessageType) { Assert.AreEqual(logMessageType, MacroStabilityInwardsKernelWrapper.ConvertKernelValidationResultTypeToLogMessageType(validationResultType)); } [Test] // Result1True.xml is generated with BmMacrostabiliteit 'Benchmark 1-01b.wti' // Result2True.xml is generated with BmMacrostabiliteit 'Benchmark 4-01b.wti' // An info and warning message were manually added // Result3False.xml is same as Result1True.xml but changed manually to Succeeded="false" SafetyFactor="NaN" // and added an error message public void TestParseRunResult() { const double diff = 0.001; List messages; MacroStabilityOutputItem macroStabilityOutputItem = new MacroStabilityOutputItem(); var kernelWrapper = new MacroStabilityInwardsKernelWrapper(); // Result 1 succeeded, has a SafetyFactor of ca. 3.856, no messages var xmlFileName = Path.Combine(TestFolder, "Result1True.xml"); string xmlRunResult = File.ReadAllText(xmlFileName); kernelWrapper.ParseRunResult(xmlRunResult, out macroStabilityOutputItem, out messages); Assert.AreEqual(0, messages.Count); Assert.AreEqual(CalculationResult.Succeeded, macroStabilityOutputItem.CalculationResult); Assert.AreEqual(3.856, macroStabilityOutputItem.SafetyFactor, diff); Assert.AreEqual(56.599, macroStabilityOutputItem.CircleSurfacePointLeftXCoordinate, diff); Assert.AreEqual(77.665, macroStabilityOutputItem.CircleSurfacePointRightXCoordinate, diff); Assert.AreEqual(MStabModelType.UpliftVan, macroStabilityOutputItem.StabilityModelType); // Result 2 succeeded, has a SafetyFactor of ca. 1.857, has info and warning, but no error messages xmlFileName = Path.Combine(TestFolder, "Result2True.xml"); xmlRunResult = File.ReadAllText(xmlFileName); kernelWrapper.ParseRunResult(xmlRunResult, out macroStabilityOutputItem, out messages); Assert.AreEqual(2, messages.Count); Assert.AreEqual(LogMessageType.Info, messages[0].MessageType); Assert.AreEqual(LogMessageType.Warning, messages[1].MessageType); Assert.AreEqual(CalculationResult.Succeeded, macroStabilityOutputItem.CalculationResult); Assert.AreEqual(1.857, macroStabilityOutputItem.SafetyFactor, diff); Assert.AreEqual(48.195, macroStabilityOutputItem.CircleSurfacePointLeftXCoordinate, diff); Assert.AreEqual(54.715, macroStabilityOutputItem.CircleSurfacePointRightXCoordinate, diff); Assert.AreEqual(MStabModelType.UpliftVan, macroStabilityOutputItem.StabilityModelType); // Result 3 failed - has a SafetyFactor of NaN, has an error mesage xmlFileName = Path.Combine(TestFolder, "Result3False.xml"); xmlRunResult = File.ReadAllText(xmlFileName); kernelWrapper.ParseRunResult(xmlRunResult, out macroStabilityOutputItem, out messages); Assert.AreEqual(1, messages.Count); Assert.AreEqual(LogMessageType.Error, messages[0].MessageType); Assert.AreEqual(CalculationResult.RunFailed, macroStabilityOutputItem.CalculationResult); Assert.AreEqual(double.NaN, macroStabilityOutputItem.SafetyFactor, diff); } [TestCase(MacroStability.Standard.LogMessageType.Info, LogMessageType.Info)] [TestCase(MacroStability.Standard.LogMessageType.Warning, LogMessageType.Warning)] [TestCase(MacroStability.Standard.LogMessageType.Error, LogMessageType.Error)] public void TestConvertKernelLogMessageTypeToLogMessageType(MacroStability.Standard.LogMessageType kernelLogMessageType, LogMessageType logMessageType) { Assert.AreEqual(logMessageType, MacroStabilityInwardsKernelWrapper.ConvertKernelLogMessageTypeToLogMessageType(kernelLogMessageType)); } [Test] public void TestPostProcess() { const double diff = 0.0001; var kernelWrapper = new MacroStabilityInwardsKernelWrapper(); var kernelInput = CreateDamKernelInputForTest(); MacroStabilityOutput macroStabilityOutput = new MacroStabilityOutput(); DesignScenario designScenario = new DesignScenario { Location = kernelInput.Location }; List results; macroStabilityOutput.CalculationResult = CalculationResult.Succeeded; var macroStabilityOutputItem = new MacroStabilityOutputItem(); macroStabilityOutputItem.CalculationResult = CalculationResult.Succeeded; macroStabilityOutput.UpliftSituation = new UpliftSituation { IsUplift = true }; macroStabilityOutputItem.SafetyFactor = 2.34; macroStabilityOutput.StabilityOutputItems = new List(); macroStabilityOutput.StabilityOutputItems.Add(macroStabilityOutputItem); kernelWrapper.PostProcess(kernelInput, macroStabilityOutput, designScenario, "", out results); Assert.IsTrue(results.Count > 0); foreach (var result in results) { Assert.AreEqual(CalculationResult.Succeeded, result.CalculationResult); Assert.AreEqual(true, ((UpliftSituation)result.StabilityDesignResults.UpliftSituation).IsUplift); Assert.AreEqual(0, result.StabilityDesignResults.NumberOfIterations); //NumberOfIterations can not be set for this test, so always zero here Assert.AreEqual(2.34, result.StabilityDesignResults.SafetyFactor, diff); Assert.AreEqual(kernelInput.Location.SurfaceLine, result.StabilityDesignResults.RedesignedSurfaceLine); Assert.AreEqual(kernelInput.SubSoilScenario.ToString(), result.ProfileName); } } [Test] public void TestFullCalculationFails() { var kernelWrapper = new MacroStabilityInwardsKernelWrapper(); kernelWrapper.CreateStabilityCalculator(); IKernelDataInput kernelDataInput = new MacroStabilityInput(); IKernelDataOutput kernelDataOutput = new MacroStabilityOutput(); // Run the dll List messages; MacroStabilityInput macroStabilityInput = (MacroStabilityInput)kernelDataInput; kernelWrapper.tmpPresumeRunSucceeds = false; //ToDo MWDAM-1356 replace by input that makes Execute fail kernelWrapper.Execute(kernelDataInput, kernelDataOutput, out messages); MacroStabilityOutput macroStabilityOutput = (MacroStabilityOutput)kernelDataOutput; Assert.IsTrue(messages.Count > 0); Assert.AreEqual(CalculationResult.RunFailed, macroStabilityOutput.CalculationResult); } [Test] public void TestFullCalculationSucceeds() { const double diff = 0.0001; var kernelWrapper = new MacroStabilityInwardsKernelWrapper(); kernelWrapper.CreateStabilityCalculator(); kernelWrapper.FailureMechanismParametersMStab = new FailureMechanismParametersMStab(); // Prepare the wrapper. Result is input for the calculation dll IKernelDataInput kernelDataInput; IKernelDataOutput kernelDataOutput; var kernelInput = CreateDamKernelInputForTest(); PrepareResult prepareResult = kernelWrapper.Prepare(kernelInput, 0, out kernelDataInput, out kernelDataOutput); // ToDo MWDAM-1356: xml input not written yet. Skip for now. //Assert.AreEqual(PrepareResult.Successful, prepareResult1); // Validate the input List messages; kernelWrapper.tmpPresumeInputValid = true; //ToDo MWDAM-1356: replace by input that makes Validate succeed var errorCount = kernelWrapper.Validate(kernelDataInput, kernelDataOutput, out messages); // ToDo MWDAM-1356: Not clear yet what input must be provided to make Validate succeed. Skip for now. //Assert.IsTrue(errorCount == 0); // Run the dll kernelWrapper.tmpPresumeRunSucceeds = true; //ToDo MWDAM-1356: replace by input that makes Execute succeed kernelWrapper.Execute(kernelDataInput, kernelDataOutput, out messages); MacroStabilityOutput macroStabilityOutput = (MacroStabilityOutput)kernelDataOutput; // ToDo MWDAM-1356: Input must be set first in Prepare // start of temporary test code Assert.AreEqual(0, messages.Count); Assert.AreEqual(CalculationResult.Succeeded, macroStabilityOutput.CalculationResult); Assert.AreEqual(1, macroStabilityOutput.StabilityOutputItems.Count); Assert.AreEqual(1.357, macroStabilityOutput.StabilityOutputItems[0].SafetyFactor, diff); // ToDo replace by actual value when calculation is done and output is parsed // end of temporary test code // Fill the design results DesignScenario designScenario = new DesignScenario { Location = kernelInput.Location }; List results; kernelWrapper.PostProcess(kernelInput, macroStabilityOutput, designScenario, "", out results); Assert.IsTrue(results.Count > 0); foreach (var result in results) { Assert.AreEqual(CalculationResult.Succeeded, result.CalculationResult); Assert.AreEqual(1.357, result.StabilityDesignResults.SafetyFactor); // ToDo: Add all output items when it is clear what parts of StabilityDesignResults will be filled } } [Test] [ExpectedException(typeof(NoNullAllowedException), ExpectedMessage = "Geen invoer object gedefinieerd voor Macrostabiliteit")] [SetUICulture("nl-NL")] public void TestLanguageNLThrowsExceptionWhenInputIsNull() { List messages; var kernelWrapper = new MacroStabilityInwardsKernelWrapper(); kernelWrapper.Execute(null, null, out messages); ; } [Test] [ExpectedException(typeof(NoNullAllowedException), ExpectedMessage = "No input object defined for Macro Stability")] [SetUICulture("en-US")] public void TestLanguageENThrowsExceptionWhenStabilityInputIsNull() { List messages; var kernelWrapper = new MacroStabilityInwardsKernelWrapper(); kernelWrapper.Execute(null, null, out messages); } [Test] [ExpectedException(typeof(NoNullAllowedException), ExpectedMessage = "Geen uitvoer object gedefinieerd voor Macrostabiliteit")] [SetUICulture("nl-NL")] public void TestThrowsExceptionWhenStabilityOutputIsNull() { var kernelWrapper = new MacroStabilityInwardsKernelWrapper(); List results; kernelWrapper.PostProcess(new DamKernelInput(), null, null, "", out results); } [Test] [ExpectedException(typeof(NoNullAllowedException), ExpectedMessage = "Geen Dam invoer object gedefinieerd voor Macrostabiliteit")] [SetUICulture("nl-NL")] public void TestThrowsExceptionWhenDamKernelInputIsNull() { var kernelWrapper = new MacroStabilityInwardsKernelWrapper(); List results; kernelWrapper.PostProcess(null, null, null, "", out results); } [Test] [ExpectedException(typeof(NoNullAllowedException), ExpectedMessage = "Geen reken object gedefinieerd voor Macrostabiliteit")] [SetUICulture("nl-NL")] public void TestThrowsExceptionWhenDamKernelIsNull() { List messages; var kernelWrapper = new MacroStabilityInwardsKernelWrapper(); IKernelDataInput kernelDataInput = new DamMacroStabilityInput(); IKernelDataOutput kernelDataOutput = new DamMacroStabilityOutput(); kernelWrapper.Validate(kernelDataInput, kernelDataOutput, out messages); } private static DamKernelInput CreateDamKernelInputForTest() { var location = DamMacroStabilityTestHelper.CreateLocation(FactoryForSurfaceLines.CreateSurfaceLineTutorial1()); var subSoilScenario = new SoilGeometryProbability(); subSoilScenario.SoilProfileType = SoilProfileType.ProfileType2D; subSoilScenario.StiFileName = ""; subSoilScenario.FullStiFileName = ""; subSoilScenario.SoilProfile2D = DamMacroStabilityTestHelper.CreateSoilProfile2D(); subSoilScenario.SegmentFailureMechanismType = FailureMechanismSystemType.StabilityInside; var damKernelInput = new DamKernelInput(); damKernelInput.Location = location; damKernelInput.SubSoilScenario = subSoilScenario; damKernelInput.RiverLevelLow = null; damKernelInput.DamFailureMechanismeCalculationSpecification = new DamFailureMechanismeCalculationSpecification(); return damKernelInput; } } }