Index: DamClients/DamUI/trunk/src/Dam/Deltares.Dam.Tests/Geometry2DImporter/SoilProfile2DImporterTest.cs =================================================================== diff -u --- DamClients/DamUI/trunk/src/Dam/Deltares.Dam.Tests/Geometry2DImporter/SoilProfile2DImporterTest.cs (revision 0) +++ DamClients/DamUI/trunk/src/Dam/Deltares.Dam.Tests/Geometry2DImporter/SoilProfile2DImporterTest.cs (revision 4819) @@ -0,0 +1,244 @@ +// Copyright (C) Stichting Deltares 2024. All rights reserved. +// +// This file is part of the application DAM - UI. +// +// DAM - UI 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 Deltares.Dam.Data; +using Deltares.Dam.Data.Geometry2DImporter; +using Deltares.Geotechnics.Soils; +using NUnit.Framework; +using GeotechnicsWaterPressureInterpolationModel = Deltares.Geotechnics.Soils.WaterpressureInterpolationModel; + +namespace Deltares.Dam.Tests.Geometry2DImporter +{ + [TestFixture] + public class SoilProfile2DImporterTest + { + private const string TestDataFolder = @"TestData\StiImporter\"; + + [Test] + [TestCase(null)] + [TestCase(" ")] + [TestCase("")] + public void Import_InvalidSoilProfileDirectory_ThrowsArgumentException(string invalidSoilProfileDirectory) + { + // Call + TestDelegate call = () => SoilProfile2DImporter.Import(invalidSoilProfileDirectory, new Segment(), new SoilList()); + + // Assert + Assert.That(call, Throws.ArgumentException + .With.Message.EqualTo("'soilProfileDirectory' cannot be null or consist of whitespaces only.")); + } + + [Test] + public void Import_SegmentNull_ThrowsArgumentNullException() + { + // Call + TestDelegate call = () => SoilProfile2DImporter.Import(string.Empty, null, new SoilList()); + + // Assert + Assert.That(call, Throws.TypeOf() + .With.Property(nameof(ArgumentNullException.ParamName)) + .EqualTo("segment")); + } + + [Test] + public void Import_AvailableSoilsNull_ThrowsArgumentNullException() + { + // Call + TestDelegate call = () => SoilProfile2DImporter.Import(string.Empty, new Segment(), null); + + // Assert + Assert.That(call, Throws.TypeOf() + .With.Property(nameof(ArgumentNullException.ParamName)) + .EqualTo("availableSoils")); + } + + [Test] + public void Import_WithValidArguments_ReturnsExpectedSoilProfiles() + { + // Setup + const string profileOneName = "SimpleProfile.sti"; + const string profileTwoName = "Tutorial-1a 10.1.4.3.sti"; + Segment segment = CreateSegmentWithProfiles(new[] + { + profileOneName, + profileTwoName + }); + SoilList availableSoils = CreateSoilList(new[] + { + "Soft Clay", + "Sand", + "Peat", + "Muck" + }); + + // Call + IEnumerable soilProfiles = SoilProfile2DImporter.Import(TestDataFolder, segment, availableSoils); + + // Assert + Assert.That(soilProfiles.Count, Is.EqualTo(2)); + + SoilProfile2D soilProfileOne = soilProfiles.ElementAt(0); + Assert.That(soilProfileOne.Name, Is.EqualTo(profileOneName)); + Assert.That(soilProfileOne.Surfaces.Select(s => s.Name), Is.EqualTo(new[] + { + "Soft Clay", + "Muck" + }).AsCollection); + AssertSoilLayerProperties(soilProfileOne.Surfaces); + + SoilProfile2D soilProfileTwo = soilProfiles.ElementAt(1); + Assert.That(soilProfileTwo.Name, Is.EqualTo(profileTwoName)); + Assert.That(soilProfileTwo.Surfaces.Select(s => s.Name), Is.EquivalentTo(new[] + { + "Soft Clay", + "Sand", + "Peat", + "Soft Clay" + })); // Check only whether all the surfaces are present as the order differs on different machines. + AssertSoilLayerProperties(soilProfileTwo.Surfaces); + } + + [Test] + public void Import_WithProfileNamesNotHavingStiExtension_ReturnsExpectedSoilProfiles() + { + // Setup + const string profileOneFileName = "SimpleProfile"; + const string profileTwoFileName = "Tutorial-1a 10.1.4.3"; + Segment segment = CreateSegmentWithProfiles(new[] + { + profileOneFileName, + profileTwoFileName + }); + SoilList availableSoils = CreateSoilList(new[] + { + "Soft Clay", + "Sand", + "Peat", + "Muck" + }); + + // Call + IEnumerable soilProfiles = SoilProfile2DImporter.Import(TestDataFolder, segment, availableSoils); + + // Assert + Assert.That(soilProfiles.Count, Is.EqualTo(2)); + + SoilProfile2D soilProfileOne = soilProfiles.ElementAt(0); + Assert.That(soilProfileOne.Name, Is.EqualTo(profileOneFileName)); + Assert.That(soilProfileOne.Surfaces.Select(s => s.Name), Is.EqualTo(new[] + { + "Soft Clay", + "Muck" + }).AsCollection); + AssertSoilLayerProperties(soilProfileOne.Surfaces); + + SoilProfile2D soilProfileTwo = soilProfiles.ElementAt(1); + Assert.That(soilProfileTwo.Name, Is.EqualTo(profileTwoFileName)); + Assert.That(soilProfileTwo.Surfaces.Select(s => s.Name), Is.EquivalentTo(new[] + { + "Soft Clay", + "Sand", + "Peat", + "Soft Clay" + })); // Check only whether all the surfaces are present as the order differs on different machines. + AssertSoilLayerProperties(soilProfileTwo.Surfaces); + } + + [Test] + public void Import_WithIncompleteSoilList_ThrowsSoilProfileImporterException() + { + const string invalidSoilProfile = "Tutorial-1a 10.1.4.3.sti"; // Soil profile also contains peat and sand for its layers + const string profileName = "SimpleProfile"; + Segment segment = CreateSegmentWithProfiles(new[] + { + $"{profileName}.sti", + invalidSoilProfile + }); + SoilList availableSoils = CreateSoilList(new[] + { + "Soft Clay", + "Muck" + }); + + Assert.That(() => SoilProfile2DImporter.Import(TestDataFolder, segment, availableSoils), + Throws.Exception.TypeOf().With.Message.EqualTo($"'{invalidSoilProfile}' contains the undefined soil: Peat.")); + } + + [Test] + public void Import_WithSoilProfileCausingReadException_ThrowsSoilProfileImporterException() + { + const string invalidSoilProfileName = "NonExistentSoilProfile"; + Segment segment = CreateSegmentWithProfiles(new[] + { + "SimpleProfile.sti", + invalidSoilProfileName + }); + SoilList availableSoils = CreateSoilList(new[] + { + "Soft Clay", + "Muck" + }); + + Assert.That(() => SoilProfile2DImporter.Import(TestDataFolder, segment, availableSoils), + Throws.TypeOf().With.Message.Contains($"Could not import soil profile '{invalidSoilProfileName}': ")); + } + + private static Segment CreateSegmentWithProfiles(IEnumerable soilProfileNames) + { + var random = new Random(21); + + var segment = new Segment(); + foreach (string soilProfileName in soilProfileNames) + { + segment.AddSoilGeometry2DProbability(soilProfileName, random.NextDouble(), null); + } + + return segment; + } + + private static void AssertSoilLayerProperties(IEnumerable soilLayers) + { + foreach (SoilLayer2D soilLayer in soilLayers) + { + Assert.That(soilLayer.WaterpressureInterpolationModel, Is.EqualTo(GeotechnicsWaterPressureInterpolationModel.Hydrostatic)); + } + } + + private static SoilList CreateSoilList(IEnumerable soilNames) + { + var soilList = new SoilList(); + + foreach (string soilName in soilNames) + { + var soilToBeAdded = new Soil + { + Name = soilName + }; + soilList.Add(soilToBeAdded); + } + + return soilList; + } + } +} \ No newline at end of file Index: DamClients/DamUI/trunk/src/Dam/Deltares.Dam.Tests/Geometry2DImporter/StiFileValidatorTest.cs =================================================================== diff -u --- DamClients/DamUI/trunk/src/Dam/Deltares.Dam.Tests/Geometry2DImporter/StiFileValidatorTest.cs (revision 0) +++ DamClients/DamUI/trunk/src/Dam/Deltares.Dam.Tests/Geometry2DImporter/StiFileValidatorTest.cs (revision 4819) @@ -0,0 +1,142 @@ +// Copyright (C) Stichting Deltares 2024. All rights reserved. +// +// This file is part of the application DAM - UI. +// +// DAM - UI 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.IO; +using Deltares.Dam.Data.Geometry2DImporter; +using NUnit.Framework; + +namespace Deltares.Dam.Tests.Geometry2DImporter +{ + [TestFixture] + public class StiFileValidatorTest + { + private const string TestDataFolder = @"TestData\StiImporter\"; + + [Test] + [TestCase(null)] + [TestCase("")] + [TestCase(" ")] + public void Constructor_FilePathNullOrEmpty_ThrowsArgumentException(string filePath) + { + // Call + TestDelegate call = () => new StiFileValidator(filePath); + + // Assert + Assert.That(call, Throws.ArgumentException + .With.Message.EqualTo("'filePath' cannot be null or consist of whitespaces only.")); + } + + [Test] + public void Constructor_FileResultsInIOException_ThrowsStiFileReadException() + { + // Setup + const string nonExistingFile = "DoesNotExist"; + + // Call + TestDelegate call = () => new StiFileValidator(nonExistingFile); + + // Assert + var exception = Assert.Throws(call); + Exception innerException = exception.InnerException; + Assert.That(innerException, Is.InstanceOf()); + Assert.That(exception.Message, Is.EqualTo(innerException.Message)); + } + + [Test] + [TestCase("Tutorial-1a 10.1.4.3.sti")] + [TestCase("Tutorial-1a 14.1.2.1.sti")] + [TestCase("Tutorial-1a 16.1.2.1.sti")] + public void GivenValidatorWithSupportedFileVersions_WhenValidateCalled_ThenNoValidationMessages(string fileName) + { + // Setup + string filePath = Path.Combine(TestDataFolder, fileName); + var fileValidator = new StiFileValidator(filePath); + + // Call + IEnumerable validationMessages = fileValidator.Validate(); + + // Assert + Assert.That(validationMessages, Is.Empty); + } + + [Test] + public void GivenValidatorWithSupportedFormat_WhenValidateFileFormatCalled_ThenNoValidationMessages() + { + // Setup + string filePath = Path.Combine(TestDataFolder, "Tutorial-1a 10.1.4.3.sti"); + var fileValidator = new StiFileValidator(filePath); + + // Call + IEnumerable messages = fileValidator.Validate(); + + // Assert + Assert.That(messages, Is.Empty); + } + + [Test] + [TestCaseSource(nameof(GetUnsupportedFileVersions))] + public void GivenValidatorWithUnsupportedFileVersions_WhenValidateFileVersionCalled_ThenLogMessagesGenerated( + string fileName, + string propertyName) + { + // Given + string filePath = Path.Combine(TestDataFolder, fileName); + var fileValidator = new StiFileValidator(filePath); + + // When + IEnumerable messages = fileValidator.Validate(); + + // Then + var expectedErrorMessage = $"{propertyName} data in '{filePath}' is of a version of D-Geo Stability that is not supported and cannot be read."; + Assert.That(messages, Is.EqualTo(new[] + { + expectedErrorMessage + }).AsCollection); + } + + [Test] + [TestCase("GeoFile.geo")] + [TestCase("SeepFile.SEI")] + public void GivenValidatorWithUnsupportedFormat_WhenValidateFileFormatCalled_ThenLogMessagesGenerated(string fileName) + { + // Given + string filePath = Path.Combine(TestDataFolder, fileName); + var fileValidator = new StiFileValidator(filePath); + + // When + IEnumerable messages = fileValidator.Validate(); + + // Then + Assert.That(messages, Is.EqualTo(new[] + { + $"{filePath} is not a D-Geo Stability file (*.sti)." + }).AsCollection); + } + + private static IEnumerable GetUnsupportedFileVersions() + { + yield return new TestCaseData("InvalidSoilVersion.sti", "Soil"); + yield return new TestCaseData("InvalidGeometryVersion.sti", "Geometry"); + } + } +} \ No newline at end of file Index: DamClients/DamUI/trunk/src/Dam/Deltares.Dam.Tests/Geometry2DImporter/StiFileReaderTest.cs =================================================================== diff -u --- DamClients/DamUI/trunk/src/Dam/Deltares.Dam.Tests/Geometry2DImporter/StiFileReaderTest.cs (revision 0) +++ DamClients/DamUI/trunk/src/Dam/Deltares.Dam.Tests/Geometry2DImporter/StiFileReaderTest.cs (revision 4819) @@ -0,0 +1,182 @@ +// Copyright (C) Stichting Deltares 2024. All rights reserved. +// +// This file is part of the application DAM - UI. +// +// DAM - UI 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.IO; +using System.Linq; +using Deltares.Dam.Data.Geometry2DImporter; +using Deltares.Geometry; +using Deltares.Geotechnics.Soils; +using Deltares.Standard.Logging; +using NUnit.Framework; + +namespace Deltares.Dam.Tests.Geometry2DImporter +{ + [TestFixture] + public class StiFileReaderTest + { + private const string TestDataFolder = @"TestData\StiImporter\"; + + [Test] + [TestCase(null)] + [TestCase("")] + [TestCase(" ")] + public void ReadSoilProfile_WithInvalidFilePath_ThrowsArgumentException(string invalidFilePath) + { + // Setup + var reader = new StiFileReader(); + + // Call + TestDelegate call = () => reader.ReadSoilProfile(invalidFilePath); + + // Assert + Assert.That(call, Throws.ArgumentException + .With.Message.EqualTo("'filePath' cannot be null or consist of whitespaces only.")); + } + + [Test] + public void ReadSoilProfile_WithInvalidVersion_ThrowsStiFileReadException() + { + // Setup + LogManager.Messages.Clear(); // Clear the messages before the test starts as the log manager is a singleton. + + string filePath = Path.Combine(TestDataFolder, "InvalidSoilVersion.sti"); + + var reader = new StiFileReader(); + + // Call + TestDelegate call = () => reader.ReadSoilProfile(filePath); + + // Assert + Assert.That(call, Throws.Exception.TypeOf() + .With.Message.EqualTo($"'{filePath}' is an unsupported file.")); + + var expectedMessage = $"Soil data in '{filePath}' is of a version of D-Geo Stability that is not supported and cannot be read."; + Assert.That(LogManager.Messages.Select(m => m.Message), Is.EqualTo(new[] + { + expectedMessage + }).AsCollection); + Assert.That(LogManager.Messages.Select(m => m.MessageType), Is.EqualTo(new[] + { + LogMessageType.Error + }).AsCollection); + Assert.That(LogManager.Messages.Select(m => m.Subject), Is.EqualTo(new[] + { + reader + }).AsCollection); + } + + [Test] + public void ReadSoilProfile_WithValidFile_ReturnsExpectedSoilProfile() + { + // Setup + string filePath = Path.Combine(TestDataFolder, "SimpleProfile.sti"); + + var reader = new StiFileReader(); + + // Call + SoilProfile2D soilProfile = reader.ReadSoilProfile(filePath); + + // Assert + Assert.That(soilProfile, Is.Not.Null); + Assert.That(soilProfile.Surfaces.Count, Is.EqualTo(2)); + + var topLeftPoint = new GeometryPoint(0, 0, -4); + var topRightPoint = new GeometryPoint(75, 0, -4); + var bottomLeftPoint = new GeometryPoint(0, 0, -6); + var bottomRightPoint = new GeometryPoint(75, 0, -6); + SoilLayer2D layerOne = soilProfile.Surfaces.ElementAt(0); + Assert.That(layerOne.Name, Is.EqualTo("Soft Clay")); + AssertSoilLayerGeometry(bottomLeftPoint, bottomRightPoint, topLeftPoint, topRightPoint, layerOne); + + topLeftPoint = new GeometryPoint(0, 0, -2); + topRightPoint = new GeometryPoint(75, 0, -2); + bottomLeftPoint = new GeometryPoint(0, 0, -4); + bottomRightPoint = new GeometryPoint(75, 0, -4); + SoilLayer2D layerTwo = soilProfile.Surfaces.ElementAt(1); + Assert.That(layerTwo.Name, Is.EqualTo("Muck")); + AssertSoilLayerGeometry(bottomLeftPoint, bottomRightPoint, topLeftPoint, topRightPoint, layerTwo); + + Assert.That(soilProfile.PreconsolidationStresses, Is.Empty); + } + + [Test] + public void ReadSoilProfile_WithInvalidFile_ThrowsStiFileReadException() + { + // Setup + string filePath = Path.Combine(TestDataFolder, "SimpleProfileWithException.sti"); // This file contains more coordinates than the maximum specified + + var reader = new StiFileReader(); + + // Call + TestDelegate call = () => reader.ReadSoilProfile(filePath); + + // Assert + var exception = Assert.Throws(call); + Exception innerException = exception.InnerException; + Assert.That(innerException, Is.Not.Null); + Assert.That(exception.Message, Is.EqualTo($"Reading file '{filePath}' failed: {innerException.Message}.")); + } + + private static void AssertSoilLayerGeometry(GeometryPoint bottomLeftPoint, + GeometryPoint bottomRightPoint, + GeometryPoint topLeftPoint, + GeometryPoint topRightPoint, + SoilLayer2D layer) + { + GeometrySurface geometrySurface = layer.GeometrySurface; + Assert.That(geometrySurface.InnerLoops, Is.Empty); // Layers do not have inner loops + + GeometryLoop actualGeometry = geometrySurface.OuterLoop; + GeometryPoint[] expectedPoints = + { + bottomRightPoint, + bottomLeftPoint, + topLeftPoint, + topRightPoint + }; + + Assert.That(actualGeometry.Points.Count, Is.EqualTo(expectedPoints.Length)); + for (var i = 0; i < expectedPoints.Length; i++) + { + GeometryPoint actualPoint = actualGeometry.Points[i]; + Assert.That(actualPoint.LocationEquals(expectedPoints[i]), Is.True); + } + + List curves = actualGeometry.CurveList; + var expectedCurves = new[] + { + new GeometryCurve(bottomLeftPoint, bottomRightPoint), + new GeometryCurve(bottomLeftPoint, topLeftPoint), + new GeometryCurve(topLeftPoint, topRightPoint), + new GeometryCurve(bottomRightPoint, topRightPoint) + }; + + int expectedNrOfCurves = expectedCurves.Length; + Assert.That(curves.Count, Is.EqualTo(expectedNrOfCurves)); + for (var i = 0; i < expectedNrOfCurves; i++) + { + Assert.That(curves[i].LocationEquals(expectedCurves[i]), Is.True); + } + } + } +} \ No newline at end of file Fisheye: Tag 4819 refers to a dead (removed) revision in file `DamClients/DamUI/trunk/src/Dam/Deltares.Dam.Tests/StiImporter/SoilProfile2DImporterTest.cs'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 4819 refers to a dead (removed) revision in file `DamClients/DamUI/trunk/src/Dam/Deltares.Dam.Tests/StiImporter/StiFileValidatorTest.cs'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 4819 refers to a dead (removed) revision in file `DamClients/DamUI/trunk/src/Dam/Deltares.Dam.Tests/StiImporter/StiFileReaderTest.cs'. Fisheye: No comparison available. Pass `N' to diff?