// Copyright (C) Stichting Deltares 2025. 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.Geometry;
using Deltares.Geotechnics.Soils;
using Deltares.Standard.Validation;
using NUnit.Framework;
using GeotechnicsWaterPressureInterpolationModel = Deltares.Geotechnics.Soils.WaterpressureInterpolationModel;
namespace Deltares.Dam.Tests.Geometry2DImporter
{
[TestFixture]
public class SoilProfile2DImporterTest
{
private const string stixTestDataFolder = @"TestData\Geometry2DImporter\";
[Test]
[TestCase(null)]
[TestCase(" ")]
[TestCase("")]
public void Import_InvalidSoilProfileDirectory_ThrowsArgumentException(string invalidSoilProfileDirectory)
{
// Call
TestDelegate call = () => SoilProfile2DImporter.Import(invalidSoilProfileDirectory, new Segment(), new SoilList(), null);
// 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(), null);
// 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, 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.stix";
const string profileTwoName = "Tutorial-1a.stix";
Segment segment = CreateSegmentWithProfiles(new[]
{
profileOneName,
profileTwoName
});
SoilList availableSoils = CreateSoilList(new[]
{
"Soft Clay",
"Sand",
"Peat",
"Muck"
});
// Call
IEnumerable soilProfiles = SoilProfile2DImporter.Import(stixTestDataFolder, segment, availableSoils, null);
// Assert
Assert.That(soilProfiles.Count, Is.EqualTo(2));
SoilProfile2D soilProfileOne = soilProfiles.ElementAt(0);
Assert.Multiple(() =>
{
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.Multiple(() =>
{
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";
Segment segment = CreateSegmentWithProfiles(new[]
{
profileOneFileName,
profileTwoFileName
});
SoilList availableSoils = CreateSoilList(new[]
{
"Soft Clay",
"Sand",
"Peat",
"Muck"
});
// Call
IEnumerable soilProfiles = SoilProfile2DImporter.Import(stixTestDataFolder, segment, availableSoils, null);
// Assert
Assert.That(soilProfiles.Count, Is.EqualTo(2));
SoilProfile2D soilProfileOne = soilProfiles.ElementAt(0);
Assert.Multiple(() =>
{
Assert.That(soilProfileOne.Name, Is.EqualTo(profileOneFileName + ".stix"));
Assert.That(soilProfileOne.Surfaces.Select(s => s.Name), Is.EqualTo(new[]
{
"Soft Clay",
"Muck"
}).AsCollection);
});
AssertSoilLayerProperties(soilProfileOne.Surfaces);
SoilProfile2D soilProfileTwo = soilProfiles.ElementAt(1);
Assert.Multiple(() =>
{
Assert.That(soilProfileTwo.Name, Is.EqualTo(profileTwoFileName + ".stix"));
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.stix"; // Soil profile also contains peat and sand for its layers
const string profileName = "SimpleProfile";
Segment segment = CreateSegmentWithProfiles(new[]
{
$"{profileName}.stix",
invalidSoilProfile
});
SoilList availableSoils = CreateSoilList(new[]
{
"Soft Clay",
"Muck"
});
Assert.That(() => SoilProfile2DImporter.Import(stixTestDataFolder, segment, availableSoils, null),
Throws.Exception.TypeOf().With.Message.EqualTo($"'{invalidSoilProfile}' contains the undefined soil: Sand."));
}
[Test]
public void Import_WithSoilProfileCausingReadException_ThrowsSoilProfileImporterException()
{
const string invalidSoilProfileName = "NonExistentSoilProfile";
Segment segment = CreateSegmentWithProfiles(new[]
{
"SimpleProfile.stix",
invalidSoilProfileName
});
SoilList availableSoils = CreateSoilList(new[]
{
"Soft Clay",
"Muck"
});
Assert.That(() => SoilProfile2DImporter.Import(stixTestDataFolder, segment, availableSoils, null),
Throws.TypeOf().With.Message.Contains($"Could not import soil profile '{invalidSoilProfileName}': "));
}
[TestFixture]
public class GivenStixFiles
{
private static Segment segment;
private static SoilList availableSoils;
private static IList aquifers;
[SetUp]
public static void Arrange()
{
const string fileName1 = "DWP_1.stix";
const string fileName2 = "DWP_Aquifer.stix";
segment = CreateSegmentWithProfiles(new[]
{
fileName1,
fileName2
});
availableSoils = CreateSoilList(new[]
{
"wl_zand",
"veen",
"klei",
"klei antropogeen",
"zand antropogeen"
});
aquifers =
[
new Aquifer
{
StixFileName = fileName1,
LayerName = "L 5"
},
new Aquifer
{
StixFileName = fileName2,
LayerName = "Aquifer" // there are 2 layers with the name "Aquifer" in the stix file
},
new Aquifer
{
StixFileName = fileName2,
LayerName = "L 11"
}
];
}
[Test]
public void WhenImported_ThenAquifersAreSetAsExpected()
{
// Call
List soilProfiles = SoilProfile2DImporter.Import(stixTestDataFolder, segment, availableSoils, aquifers).ToList();
// Assert
Assert.That(soilProfiles, Has.Count.EqualTo(2));
SoilProfile2D soilProfile = soilProfiles.ElementAt(0);
for (var index = 0; index < soilProfile.Surfaces.Count; index++)
{
SoilLayer2D surface = soilProfile.Surfaces[index];
if (index == 4)
{
Assert.That(surface.IsAquifer, Is.True);
}
else
{
Assert.That(surface.IsAquifer, Is.False);
}
}
soilProfile = soilProfiles.ElementAt(1);
for (var index = 0; index < soilProfile.Surfaces.Count; index++)
{
SoilLayer2D surface = soilProfile.Surfaces[index];
if (index == 0 || index == 1 || index == 10)
{
Assert.That(surface.IsAquifer, Is.True);
}
else
{
Assert.That(surface.IsAquifer, Is.False);
}
}
}
[TestCase(0.0)]
[TestCase(10.0)]
[TestCase(-9.999)]
public void WhenImported_ThenSoilProfile2DHasValidGeometry(double xSoilProfile2DOrigin)
{
// Call
List soilProfiles = SoilProfile2DImporter.Import(stixTestDataFolder, segment,
availableSoils, aquifers, xSoilProfile2DOrigin).ToList();
// Assert
Assert.That(soilProfiles, Has.Count.EqualTo(2));
GeometryData geometry = soilProfiles.ElementAt(0).Geometry;
Assert.That(geometry.Surfaces, Has.Count.EqualTo(12));
Assert.That(geometry.Left, Is.EqualTo(xSoilProfile2DOrigin));
Assert.That(soilProfiles[0].Surfaces[0].GeometrySurface.OuterLoop.GetMinX(), Is.EqualTo(xSoilProfile2DOrigin));
ValidationResult[] validationResults = geometry.ValidateGeometry();
Assert.That(validationResults, Has.Length.EqualTo(0));
geometry = soilProfiles.ElementAt(1).Geometry;
validationResults = geometry.ValidateGeometry();
Assert.That(validationResults, Has.Length.EqualTo(0));
}
}
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;
}
}
}