Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators.Tests/PlLinesCreator/SoilProfileValidatorTests.cs =================================================================== diff -u --- DamEngine/trunk/src/Deltares.DamEngine.Calculators.Tests/PlLinesCreator/SoilProfileValidatorTests.cs (revision 0) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators.Tests/PlLinesCreator/SoilProfileValidatorTests.cs (revision 5409) @@ -0,0 +1,355 @@ +// Copyright (C) Stichting Deltares 2025. 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; +using System.Linq; +using Deltares.DamEngine.Calculators.PlLinesCreator; +using Deltares.DamEngine.Data.General; +using Deltares.DamEngine.Data.Geometry; +using Deltares.DamEngine.Data.Geotechnics; +using Deltares.DamEngine.TestHelpers.Factories; +using NUnit.Framework; + +namespace Deltares.DamEngine.Calculators.Tests.PlLinesCreator; + +[TestFixture] +public class SoilProfileValidatorTests +{ + private const double leftCoordinate = -50; + private const double rightCoordinate = 50; + private const double middleXCoordinate = 0.5 * (leftCoordinate + rightCoordinate); + private const string generalMessage = "Voor dit scenario wordt geen berekening uitgevoerd " + + "omdat het ondergrondprofiel niet voldoet aan de eisen die aan de aanleg van het waternet worden gesteld: "; + + [SetUp] + public void TestFixtureSetup() {} + + [SetUp] + public void TestSetup() {} + + [Test] + [SetUICulture("nl-NL")] + public void GivenSurfaceLineIsNull_WhenValidating_ThenLanguageNLThrowsException() + { + var soilProfileValidator = new SoilProfileValidator + { + SurfaceLine = null + }; + Assert.That(() => soilProfileValidator.ValidateSoilProfileForPlLinesCreator(), + Throws.InstanceOf().With.Message.EqualTo(generalMessage + "Geen hoogtegeometrie gedefinieerd.")); + } + + [Test] + [TestCase(CharacteristicPointType.DikeTopAtRiver)] + [TestCase(CharacteristicPointType.DikeTopAtPolder)] + [TestCase(CharacteristicPointType.DikeToeAtPolder)] + [SetUICulture("nl-NL")] + public void GivenSurfaceLineWhereRequiredCharacteristicPointsAreMissing_WhenValidating_ThenLanguageNLThrowsException(CharacteristicPointType missingPointType) + { + SurfaceLine2 surfaceLine = FactoryForSurfaceLines.CreateSurfacelineSimpleDike(); + CharacteristicPoint pointToBeRemoved = surfaceLine.CharacteristicPoints.First(point => point.CharacteristicPointType == missingPointType ); + surfaceLine.CharacteristicPoints.Remove(pointToBeRemoved); + + var soilProfileValidator = new SoilProfileValidator + { + SurfaceLine = surfaceLine + }; + + Assert.That(() => soilProfileValidator.ValidateSoilProfileForPlLinesCreator(), + Throws.InstanceOf().With.Message.EqualTo + (generalMessage + + "Er ontbreekt tenminste één van de volgende verplichte karakteristieke punten: Kruin buitentalud, Kruin binnentalud, Teen dijk binnenwaarts.")); + } + + [Test] + [SetUICulture("nl-NL")] + public void GivenSurfaceLineWithOnlyOnePoint_WhenValidating_ThenLanguageNLThrowsException() + { + var soilProfileValidator = new SoilProfileValidator + { + SurfaceLine = new SurfaceLine2() + }; + soilProfileValidator.SurfaceLine.Geometry.Points.Add(new GeometryPoint(0, 0)); + + Assert.That(() => soilProfileValidator.ValidateSoilProfileForPlLinesCreator(), + Throws.InstanceOf().With.Message.EqualTo + (generalMessage +"Ten minste twee hoogtegeometrie punten zijn vereist.")); + } + + [Test] + [SetUICulture("nl-NL")] + public void GivenSoilProfile1DIsNull_WhenValidating_ThenLanguageNLThrowsException() + { + var soilProfileValidator = new SoilProfileValidator + { + SurfaceLine = FactoryForSurfaceLines.CreateSurfacelineSimpleDike(), + SoilProfileType = SoilProfileType.ProfileType1D, + SoilProfile1D = null + }; + Assert.That(() => soilProfileValidator.ValidateSoilProfileForPlLinesCreator(), + Throws.InstanceOf().With.Message.EqualTo + (generalMessage + + "Er is niet voldoende informatie over het ondergrondprofiel (Profiel 1D, Profiel 2D of Ophoogmateriaal dijk) beschikbaar voor de PL-lijnen te maken.")); + } + + [Test] + [SetUICulture("nl-NL")] + public void GivenSoilProfile2DIsNull_WhenValidating_ThenLanguageNLThrowsException() + { + var soilProfileValidator = new SoilProfileValidator + { + SurfaceLine = FactoryForSurfaceLines.CreateSurfacelineSimpleDike(), + SoilProfileType = SoilProfileType.ProfileType2D, + SoilProfile2D = null + }; + Assert.That(() => soilProfileValidator.ValidateSoilProfileForPlLinesCreator(), + Throws.InstanceOf().With.Message.EqualTo + (generalMessage + + "Er is niet voldoende informatie over het ondergrondprofiel (Profiel 1D, Profiel 2D of Ophoogmateriaal dijk) beschikbaar voor de PL-lijnen te maken.")); + } + + /// + /// --------------------------------------------------- Level 0 m + /// top layer + /// -------------------------|------------------------- Level -10 m + /// bottom layer left | bottom layer right + /// -------------------------|------------------------- Level -20 m + /// + [Test] + [SetUICulture("nl-NL")] + [TestCase(false, true, false)] + [TestCase(false, false, true)] + [TestCase(true, false, false)] + public void GivenSoilProfile2DWithNoContinuousBottomAquiferLayer_WhenValidating_ThenLanguageNLThrowsException( + bool isTopLayerAquifer, bool isLeftBottomLayerAquifer, bool isRightBottomLayerAquifer) + { + // Setup + SoilLayer2D soilLayer = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(0, -10, leftCoordinate, rightCoordinate, null, null, isTopLayerAquifer); + SoilLayer2D soilLayerAquiferPartOne = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-10, -20, leftCoordinate, middleXCoordinate, null, null, isLeftBottomLayerAquifer); + SoilLayer2D soilLayerAquiferPartTwo = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-10, -20, middleXCoordinate, rightCoordinate, null, null, isRightBottomLayerAquifer); + + var soilProfile = new SoilProfile2D + { + Geometry = new GeometryData + { + Left = leftCoordinate, + Right = rightCoordinate, + Bottom = -20 + }, + Name = "SoilProfileValidatorTest" + }; + soilProfile.Surfaces.Add(soilLayer); + soilProfile.Surfaces.Add(soilLayerAquiferPartOne); + soilProfile.Surfaces.Add(soilLayerAquiferPartTwo); + + var soilProfileValidator = new SoilProfileValidator + { + SurfaceLine = FactoryForSurfaceLines.CreateHorizontalSurfaceLine(0, leftCoordinate, rightCoordinate), + SoilProfileType = SoilProfileType.ProfileType2D, + SoilProfile2D = soilProfile, + DikeEmbankmentMaterial = new Soil() + }; + + // Call and assert + Assert.That(() => soilProfileValidator.ValidateSoilProfileForPlLinesCreator(), + Throws.InstanceOf().With.Message.EqualTo + (generalMessage + + "De onderste laag is geen (continue) watervoerende laag in ondergrondprofiel 'SoilProfileValidatorTest'.")); + + } + + /// + /// --------------------------------------------------- Level 0 m + /// + /// |------------------------- Level -5 m + /// top layer | right aquifer + /// |------------------------- Level -9 m + /// + /// -------------------------|------------------------- Level -10 m + /// left aquifer | + /// -------------------------| Level -20 m + /// + [Test] + [SetUICulture("nl-NL")] + public void GivenSoilProfile2DWithDiscontinuousBottomAquiferLayer_WhenValidating_ThenLanguageNLThrowsException() + { + // Setup + SoilLayer2D soilLayer = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(0, -10, leftCoordinate, rightCoordinate); + SoilLayer2D soilLayerAquiferPartOne = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-10, -20, leftCoordinate, middleXCoordinate, null, null,true); + SoilLayer2D soilLayerAquiferPartTwo = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-5, -9, middleXCoordinate, rightCoordinate, null,null, true); + var soilProfile = new SoilProfile2D + { + Geometry = new GeometryData + { + Left = leftCoordinate, + Right = rightCoordinate, + Bottom = -20 + }, + Name = "SoilProfileTest" + }; + soilProfile.Surfaces.Add(soilLayer); + soilProfile.Surfaces.Add(soilLayerAquiferPartOne); + soilProfile.Surfaces.Add(soilLayerAquiferPartTwo); + + var soilProfileValidator = new SoilProfileValidator + { + SurfaceLine = FactoryForSurfaceLines.CreateHorizontalSurfaceLine(0, leftCoordinate, rightCoordinate), + SoilProfileType = SoilProfileType.ProfileType2D, + SoilProfile2D = soilProfile, + DikeEmbankmentMaterial = new Soil() + }; + + // Call and assert + Assert.That(() => soilProfileValidator.ValidateSoilProfileForPlLinesCreator(), + Throws.InstanceOf().With.Message.EqualTo + (generalMessage + + "De onderste laag is geen (continue) watervoerende laag in ondergrondprofiel 'SoilProfileTest'.")); + } + + [Test] + [TestCase(true)] + [TestCase(false)] + [SetUICulture("nl-NL")] + public void GivenSoilProfile2DWithUniqueLayerType_WhenValidating_ThenLanguageNLThrowsException(bool areAllLayersAquifer) + { + SurfaceLine2 surfaceLine = FactoryForSurfaceLines.CreateSurfacelineSimpleDike(); + SoilProfile1D soilProfile1D = FactoryForSoilProfiles.CreateClaySandProfile(surfaceLine.CharacteristicPoints.Select(p => p.Z).Max() - 1); + soilProfile1D.Layers[0].IsAquifer = areAllLayersAquifer; + soilProfile1D.Layers[1].IsAquifer = areAllLayersAquifer; + var soilSurfaceProfile = new SoilSurfaceProfile + { + SoilProfile = soilProfile1D, + SurfaceLine2 = surfaceLine, + DikeEmbankmentMaterial = new Soil(), + Name = "Only sand" + }; + SoilProfile2D soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D(); + + var soilProfileValidator = new SoilProfileValidator + { + SoilProfileType = SoilProfileType.ProfileType2D, + SurfaceLine = surfaceLine, + SoilProfile2D = soilProfile2D, + DikeEmbankmentMaterial = new Soil() + }; + + string layerTypeMissing = areAllLayersAquifer ? "waterkerende" : "watervoerende"; + Assert.That(() => soilProfileValidator.ValidateSoilProfileForPlLinesCreator(), + Throws.InstanceOf().With.Message.EqualTo + (generalMessage + "Het ondergrondprofiel bevat helemaal geen " + layerTypeMissing + " laag.")); + } + + + [Test] + public void GivenClayDikeBodyOnSand_WhenValidating_ThenNoExceptionReturned() + { + const bool isException = true; + try + { + SurfaceLine2 surfaceLine = FactoryForSurfaceLines.CreateSurfacelineSimpleDike(); + SoilProfile1D soilProfile1D = FactoryForSoilProfiles.CreateClaySandProfile(4); + var soilSurfaceProfile = new SoilSurfaceProfile + { + SoilProfile = soilProfile1D, + SurfaceLine2 = surfaceLine, + DikeEmbankmentMaterial = new Soil(), + Name = "Clay dike on Sand" + }; + SoilProfile2D soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D(); + + var soilProfileValidator = new SoilProfileValidator + { + SoilProfileType = SoilProfileType.ProfileType2D, + SurfaceLine = surfaceLine, + SoilProfile2D = soilProfile2D, + DikeEmbankmentMaterial = new Soil() + }; + soilProfileValidator.ValidateSoilProfileForPlLinesCreator(); + } + catch (Exception e) + { + Assert.That(isException, Is.False, "No exception was expected however the following exception was thrown: " + e.Message); + } + } + + [Test] + public void GivenSoilProfileWithTwoInBetweenAquifer_WhenValidating_ThenNoExceptionReturned() + { + const bool isException = true; + try + { + SoilProfile1D soilProfile1D = FactoryForSoilProfiles.CreateSoilProfile1DWithTwoClustersOfInBetweenAquifers(out SurfaceLine2 surfaceLine); + var soilSurfaceProfile = new SoilSurfaceProfile + { + SoilProfile = soilProfile1D, + SurfaceLine2 = surfaceLine, + DikeEmbankmentMaterial = new Soil(), + Name = "SoilProfileWith2InBetweenAquifers" + }; + SoilProfile2D soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D(); + + var soilProfileValidator = new SoilProfileValidator + { + SoilProfileType = SoilProfileType.ProfileType2D, + SurfaceLine = surfaceLine, + SoilProfile2D = soilProfile2D, + DikeEmbankmentMaterial = new Soil() + }; + soilProfileValidator.ValidateSoilProfileForPlLinesCreator(); + } + catch (Exception e) + { + Assert.That(isException, Is.False, "No exception was expected however the following exception was thrown: " + e.Message); + } + } + + [Test] + public void GivenDikeBodyWithInBetweenAquifer_WhenValidating_ThenNoExceptionReturned() + { + const bool isException = true; + try + { + SurfaceLine2 surfaceLine = FactoryForSurfaceLines.CreateSurfacelineSimpleDike(); + SoilProfile1D soilProfile1D = FactoryForSoilProfiles.CreateClaySandClaySandProfile(5, 4, 3, 0); + var soilSurfaceProfile = new SoilSurfaceProfile + { + SoilProfile = soilProfile1D, + SurfaceLine2 = surfaceLine, + DikeEmbankmentMaterial = new Soil(), + Name = "DikeBodyWithInBetweenAquifer" + }; + SoilProfile2D soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D(); + + var soilProfileValidator = new SoilProfileValidator + { + SoilProfileType = SoilProfileType.ProfileType2D, + SurfaceLine = surfaceLine, + SoilProfile2D = soilProfile2D, + DikeEmbankmentMaterial = new Soil() + }; + soilProfileValidator.ValidateSoilProfileForPlLinesCreator(); + } + catch (Exception e) + { + Assert.That(isException, Is.False, "No exception was expected however the following exception was thrown: " + e.Message); + } + } +} \ No newline at end of file