// 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;
}
}
}