// Copyright (C) Stichting Deltares 2017. All rights reserved. // // This file is part of Ringtoets. // // Ringtoets 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 Core.Common.Base; using Core.Common.Base.Data; using Core.Common.Base.Geometry; using Core.Common.Base.IO; using Core.Common.TestUtil; using Core.Common.Utils.Builders; using NUnit.Framework; using Ringtoets.Common.Data.AssessmentSection; using Ringtoets.Common.Data.TestUtil; using Ringtoets.Common.IO.FileImporters; using Ringtoets.Common.IO.Structures; using CoreCommonUtilsResources = Core.Common.Utils.Properties.Resources; namespace Ringtoets.Common.IO.Test.FileImporters { [TestFixture] public class StructuresImporterTest { private readonly ObservableList testImportTarget = new ObservableList(); private readonly ReferenceLine testReferenceLine = new ReferenceLine(); private readonly string testFilePath = string.Empty; [Test] public void Constructor_Always_ExpectedValues() { // Call var importer = new TestStructuresImporter(testImportTarget, testReferenceLine, testFilePath); // Assert Assert.IsInstanceOf(importer); } [Test] public void Constructor_ImportTargetNull_ThrowArgumentNullException() { // Call TestDelegate call = () => new TestStructuresImporter(null, testReferenceLine, testFilePath); // Assert var exception = Assert.Throws(call); Assert.AreEqual("importTarget", exception.ParamName); } [Test] public void Constructor_ReferenceLineNull_ThrowArgumentNullException() { // Call TestDelegate call = () => new TestStructuresImporter(testImportTarget, null, testFilePath); // Assert var exception = Assert.Throws(call); Assert.AreEqual("referenceLine", exception.ParamName); } [Test] public void Constructor_FilePathNull_ThrowArgumentNullException() { // Call TestDelegate call = () => new TestStructuresImporter(testImportTarget, testReferenceLine, null); // Assert var exception = Assert.Throws(call); Assert.AreEqual("filePath", exception.ParamName); } [Test] [TestCase("")] [TestCase(" ")] public void Import_FromInvalidEmptyPath_FalseAndLogError(string filePath) { // Setup var testStructuresImporter = new TestStructuresImporter(testImportTarget, testReferenceLine, filePath); // Call var importResult = true; Action call = () => importResult = testStructuresImporter.Import(); // Assert TestHelper.AssertLogMessages(call, messages => { string[] messageArray = messages.ToArray(); string expectedMessage = new FileReaderErrorMessageBuilder(filePath) .Build(CoreCommonUtilsResources.Error_Path_must_be_specified); StringAssert.StartsWith(expectedMessage, messageArray[0]); }); Assert.IsFalse(importResult); } [Test] public void Import_FromPathContainingInvalidPathCharacters_FalseAndLogError() { // Setup const string filePath = "c:\\Invalid_Characters.shp"; char[] invalidPathChars = Path.GetInvalidPathChars(); string invalidPath = filePath.Replace('_', invalidPathChars[0]); var testStructuresImporter = new TestStructuresImporter(testImportTarget, testReferenceLine, invalidPath); // Call var importResult = true; Action call = () => importResult = testStructuresImporter.Import(); // Assert TestHelper.AssertLogMessages(call, messages => { string expectedMessage = new FileReaderErrorMessageBuilder(invalidPath) .Build("Er zitten ongeldige tekens in het bestandspad. Alle tekens in het bestandspad moeten geldig zijn."); StringAssert.StartsWith(expectedMessage, messages.First()); }); Assert.IsFalse(importResult); } [Test] public void Import_FromDirectoryPath_FalseAndLogError() { // Setup string folderPath = TestHelper.GetTestDataPath(TestDataPath.Ringtoets.Common.IO) + Path.DirectorySeparatorChar; var testStructuresImporter = new TestStructuresImporter(testImportTarget, testReferenceLine, folderPath); // Call var importResult = true; Action call = () => importResult = testStructuresImporter.Import(); // Assert string expectedMessage = new FileReaderErrorMessageBuilder(folderPath) .Build(CoreCommonUtilsResources.Error_Path_must_not_point_to_empty_file_name); TestHelper.AssertLogMessageIsGenerated(call, expectedMessage, 1); Assert.IsFalse(importResult); } [Test] [TestCase("Multiple_Polygon_with_ID.shp")] [TestCase("Multiple_PolyLine_with_ID.shp")] [TestCase("Single_Multi-Polygon_with_ID.shp")] [TestCase("Single_Multi-PolyLine_with_ID.shp")] [TestCase("Single_Polygon_with_ID.shp")] [TestCase("Single_PolyLine_with_ID.shp")] public void Import_FromFileWithNonPointFeatures_FalseAndLogError(string shapeFileName) { // Setup string filePath = TestHelper.GetTestDataPath(TestDataPath.Core.Components.Gis.IO, shapeFileName); var profilesImporter = new TestStructuresImporter(testImportTarget, testReferenceLine, filePath); // Call var importResult = true; Action call = () => importResult = profilesImporter.Import(); // Assert string expectedMessage = $"Fout bij het lezen van bestand '{filePath}': kon geen punten vinden in dit bestand."; TestHelper.AssertLogMessageWithLevelIsGenerated(call, Tuple.Create(expectedMessage, LogLevelConstant.Error), 1); Assert.IsFalse(importResult); } [Test] public void Import_InvalidShapefile_ReturnsFalse() { // Setup string invalidFilePath = TestHelper.GetTestDataPath(TestDataPath.Ringtoets.Common.IO, Path.Combine("Structures", "StructuresWithoutKWKIDENT", "Kunstwerken.shp")); var profilesImporter = new TestStructuresImporter(testImportTarget, testReferenceLine, invalidFilePath); // Call bool importResult = profilesImporter.Import(); // Assert Assert.IsFalse(importResult); } [Test] public void Import_InvalidCsvFile_ReturnsFalse() { // Setup string invalidFilePath = TestHelper.GetTestDataPath(TestDataPath.Ringtoets.Common.IO, Path.Combine("Structures", "CorrectShpIncorrectCsv", "CorrectKunstwerken_IncorrectCsv.shp")); ReferenceLine referenceLine = CreateReferenceLine(); var profilesImporter = new TestStructuresImporter(testImportTarget, referenceLine, invalidFilePath); // Call bool importResult = profilesImporter.Import(); // Assert Assert.IsFalse(importResult); } [Test] public void Import_CancelOfImportWhenReadingLocations_CancelsImportAndLogs() { // Setup string filePath = TestHelper.GetTestDataPath(TestDataPath.Ringtoets.Common.IO, Path.Combine("Structures", "CorrectFiles", "Kunstwerken.shp")); ReferenceLine referenceLine = CreateReferenceLine(); var importTarget = new ObservableList(); var testStructuresImporter = new TestStructuresImporter(importTarget, referenceLine, filePath); testStructuresImporter.SetProgressChanged((description, step, steps) => { if (description.Contains("Inlezen van kunstwerklocaties uit een shapebestand.")) { testStructuresImporter.Cancel(); } }); var importResult = true; // Call Action call = () => importResult = testStructuresImporter.Import(); // Assert TestHelper.AssertLogMessageIsGenerated(call, "Kunstwerken importeren is afgebroken. Geen gegevens ingelezen."); Assert.IsFalse(importResult); } [Test] public void Import_CancelOfImportWhenCreatingStructures_ContinueImportAndLogWarning() { // Setup string filePath = TestHelper.GetTestDataPath(TestDataPath.Ringtoets.Common.IO, Path.Combine("Structures", "CorrectFiles", "Kunstwerken.shp")); ReferenceLine referenceLine = CreateReferenceLine(); var importTarget = new ObservableList(); var testStructuresImporter = new TestStructuresImporter(importTarget, referenceLine, filePath); testStructuresImporter.SetProgressChanged((description, step, steps) => { if (description.Contains("Geïmporteerde data toevoegen aan het toetsspoor.")) { testStructuresImporter.Cancel(); } }); var importResult = true; // Call Action call = () => importResult = testStructuresImporter.Import(); // Assert const string expectedMessage = "Huidige actie was niet meer te annuleren en is daarom voortgezet."; TestHelper.AssertLogMessageWithLevelIsGenerated(call, Tuple.Create(expectedMessage, LogLevelConstant.Warn), 1); Assert.IsTrue(importResult); } [Test] public void Import_CancelOfImportWhenReadingStructureData_FalseAndLogInfo() { // Setup string filePath = TestHelper.GetTestDataPath(TestDataPath.Ringtoets.Common.IO, Path.Combine("Structures", "CorrectFiles", "Kunstwerken.shp")); ReferenceLine referenceLine = CreateReferenceLine(); var importTarget = new ObservableList(); var testStructuresImporter = new TestStructuresImporter(importTarget, referenceLine, filePath); testStructuresImporter.SetProgressChanged((description, step, steps) => { if (description.Contains("Inlezen van kunstwerkgegevens uit een kommagescheiden bestand.")) { testStructuresImporter.Cancel(); } }); var importResult = true; // Call Action call = () => importResult = testStructuresImporter.Import(); // Assert const string expectedMessage = "Kunstwerken importeren is afgebroken. Geen gegevens ingelezen."; TestHelper.AssertLogMessageWithLevelIsGenerated(call, Tuple.Create(expectedMessage, LogLevelConstant.Info), 1); Assert.IsFalse(importResult); } [Test] public void Import_ReuseOfCanceledImportToValidTargetWithValidFile_ReturnsTrue() { // Setup string filePath = TestHelper.GetTestDataPath(TestDataPath.Ringtoets.Common.IO, Path.Combine("Structures", "CorrectFiles", "Kunstwerken.shp")); ReferenceLine referenceLine = CreateReferenceLine(); var importTarget = new ObservableList(); var testStructuresImporter = new TestStructuresImporter(importTarget, referenceLine, filePath); testStructuresImporter.SetProgressChanged((description, step, steps) => testStructuresImporter.Cancel()); bool importResult = testStructuresImporter.Import(); // Precondition Assert.IsFalse(importResult); testStructuresImporter.SetProgressChanged(null); // Call importResult = testStructuresImporter.Import(); // Assert Assert.IsTrue(importResult); } [Test] public void Import_LocationOutsideReferenceLine_FalseAndLogError() { // Setup string filePath = TestHelper.GetTestDataPath(TestDataPath.Ringtoets.Common.IO, Path.Combine("Structures", "CorrectFiles", "Kunstwerken.shp")); var referencePoints = new List { new Point2D(131144.094, 549979.893), new Point2D(131538.705, 548316.752), new Point2D(135878.442, 532149.859), new Point2D(131225.017, 548395.948), new Point2D(131270.38, 548367.462) }; var referenceLine = new ReferenceLine(); referenceLine.SetGeometry(referencePoints); var testStructuresImporter = new TestStructuresImporter(new ObservableList(), referenceLine, filePath); // Call var importResult = true; Action call = () => importResult = testStructuresImporter.Import(); // Assert const string expectedMessage = "Een kunstwerklocatie met KWKIDENT 'KUNST6' ligt niet op de referentielijn."; TestHelper.AssertLogMessageWithLevelIsGenerated(call, Tuple.Create(expectedMessage, LogLevelConstant.Error), 1); Assert.IsFalse(importResult); } [Test] public void Import_DuplicateLocation_FalseAndLogError() { // Setup string filePath = TestHelper.GetTestDataPath(TestDataPath.Ringtoets.Common.IO, Path.Combine("Structures", "DuplicateLocation", "Kunstwerken.shp")); ReferenceLine referenceLine = CreateReferenceLine(); var testStructuresImporter = new TestStructuresImporter(new ObservableList(), referenceLine, filePath); // Call var importResult = true; Action call = () => importResult = testStructuresImporter.Import(); // Assert const string expectedMessage = "Kunstwerklocatie met KWKIDENT 'KUNST3' is opnieuw ingelezen."; TestHelper.AssertLogMessageWithLevelIsGenerated(call, Tuple.Create(expectedMessage, LogLevelConstant.Error), 1); Assert.IsFalse(importResult); } [Test] public void Import_LocationKWKIDENTNull_FalseAndLogError() { // Setup string filePath = TestHelper.GetTestDataPath(TestDataPath.Ringtoets.Common.IO, Path.Combine("Structures", "StructuresWithNullKWKident", "Kunstwerken.shp")); ReferenceLine referenceLine = CreateReferenceLine(); var testStructuresImporter = new TestStructuresImporter(new ObservableList(), referenceLine, filePath); // Call var importResult = true; Action call = () => importResult = testStructuresImporter.Import(); // Assert const string expectedMessages = "Fout bij het lezen van kunstwerk op regel 1. Het kunstwerk heeft geen geldige waarde voor attribuut 'KWKIDENT'."; TestHelper.AssertLogMessageWithLevelIsGenerated(call, Tuple.Create(expectedMessages, LogLevelConstant.Error), 1); Assert.IsFalse(importResult); } [Test] public void Import_IllegalCsvFile_ReturnsFalse() { // Setup string filePath = TestHelper.GetTestDataPath(TestDataPath.Ringtoets.Common.IO, Path.Combine("Structures", "IllegalCsv", "Kunstwerken.shp")); ReferenceLine referenceLine = CreateReferenceLine(); var testStructuresImporter = new TestStructuresImporter(new ObservableList(), referenceLine, filePath); // Call bool importResult = testStructuresImporter.Import(); // Assert Assert.IsFalse(importResult); } [Test] public void GetStandardDeviation_RowHasStandardDeviation_ReturnVarianceValue() { // Setup string filePath = TestHelper.GetTestDataPath(TestDataPath.Ringtoets.Common.IO, Path.Combine("Structures", "CorrectFiles", "Kunstwerken.shp")); var referenceLine = new ReferenceLine(); var importTarget = new ObservableList(); var importer = new TestStructuresImporter(importTarget, referenceLine, filePath); var parameter = new StructuresParameterRow { AlphanumericValue = "", LineNumber = 3, LocationId = "A", NumericalValue = -2, ParameterId = "B", VarianceType = VarianceType.StandardDeviation, VarianceValue = 1.2 }; // Call var standardDeviation = (RoundedDouble) 0.0; Action call = () => standardDeviation = importer.GetStandardDeviation(parameter, ""); // Assert TestHelper.AssertLogMessagesCount(call, 0); Assert.AreEqual(parameter.VarianceValue, standardDeviation, standardDeviation.GetAccuracy()); } [Test] public void GetStandardDeviation_RowHasCoefficientOfVariation_LogWarningReturnConvertedVarianceValue() { // Setup string filePath = TestHelper.GetTestDataPath(TestDataPath.Ringtoets.Common.IO, Path.Combine("Structures", "CorrectFiles", "Kunstwerken.shp")); var referenceLine = new ReferenceLine(); var importTarget = new ObservableList(); var importer = new TestStructuresImporter(importTarget, referenceLine, filePath); var parameter = new StructuresParameterRow { AlphanumericValue = "", LineNumber = 3, LocationId = "A", NumericalValue = -2, ParameterId = "B", VarianceType = VarianceType.CoefficientOfVariation, VarianceValue = 1.2 }; const string structureName = ""; // Call var standardDeviation = (RoundedDouble) 0.0; Action call = () => standardDeviation = importer.GetStandardDeviation(parameter, structureName); // Assert string expectedMessage = string.Format("De variatie voor parameter '{2}' van kunstwerk '{0}' ({1}) wordt omgerekend in een standaardafwijking (regel {3}).", structureName, parameter.LocationId, parameter.ParameterId, parameter.LineNumber); TestHelper.AssertLogMessageWithLevelIsGenerated(call, Tuple.Create(expectedMessage, LogLevelConstant.Warn), 1); double expectedStandardDeviation = parameter.VarianceValue * Math.Abs(parameter.NumericalValue); Assert.AreEqual(expectedStandardDeviation, standardDeviation, standardDeviation.GetAccuracy()); } [Test] public void GetCoefficientOfVariation_RowHasCoefficientOfVariation_ReturnVarianceValue() { // Setup string filePath = TestHelper.GetTestDataPath(TestDataPath.Ringtoets.Common.IO, Path.Combine("Structures", "CorrectFiles", "Kunstwerken.shp")); var referenceLine = new ReferenceLine(); var importTarget = new ObservableList(); var importer = new TestStructuresImporter(importTarget, referenceLine, filePath); var parameter = new StructuresParameterRow { AlphanumericValue = "", LineNumber = 3, LocationId = "A", NumericalValue = -3, ParameterId = "B", VarianceType = VarianceType.CoefficientOfVariation, VarianceValue = 2.3 }; // Call var coefficientOfVariation = (RoundedDouble) 0.0; Action call = () => coefficientOfVariation = importer.GetCoefficientOfVariation(parameter, ""); // Assert TestHelper.AssertLogMessagesCount(call, 0); Assert.AreEqual(parameter.VarianceValue, coefficientOfVariation, coefficientOfVariation.GetAccuracy()); } [Test] public void GetCoefficientOfVariation_RowHasStandardDeviation_LogWarningReturnConvertedVarianceValue() { // Setup string filePath = TestHelper.GetTestDataPath(TestDataPath.Ringtoets.Common.IO, Path.Combine("Structures", "CorrectFiles", "Kunstwerken.shp")); var referenceLine = new ReferenceLine(); var importTarget = new ObservableList(); var importer = new TestStructuresImporter(importTarget, referenceLine, filePath); var parameter = new StructuresParameterRow { AlphanumericValue = "", LineNumber = 3, LocationId = "A", NumericalValue = -3, ParameterId = "B", VarianceType = VarianceType.StandardDeviation, VarianceValue = 2.3 }; const string structureName = ""; // Call var coefficientOfVariation = (RoundedDouble) 0.0; Action call = () => coefficientOfVariation = importer.GetCoefficientOfVariation(parameter, structureName); // Assert string expectedMessage = string.Format( "De variatie voor parameter '{2}' van kunstwerk '{0}' ({1}) wordt omgerekend in een variatiecoëfficiënt (regel {3}).", structureName, parameter.LocationId, parameter.ParameterId, parameter.LineNumber); TestHelper.AssertLogMessageWithLevelIsGenerated(call, Tuple.Create(expectedMessage, LogLevelConstant.Warn), 1); double expectedStandardDeviation = parameter.VarianceValue / Math.Abs(parameter.NumericalValue); Assert.AreEqual(expectedStandardDeviation, coefficientOfVariation, coefficientOfVariation.GetAccuracy()); } private static ReferenceLine CreateReferenceLine() { var referencePoints = new List { new Point2D(131144.094, 549979.893), new Point2D(131538.705, 548316.752), new Point2D(135878.442, 532149.859), new Point2D(131225.017, 548395.948), new Point2D(131270.38, 548367.462), new Point2D(131507.119, 548322.951) }; var referenceLine = new ReferenceLine(); referenceLine.SetGeometry(referencePoints); return referenceLine; } private class TestStructuresImporter : StructuresImporter> { public TestStructuresImporter(ObservableList importTarget, ReferenceLine referenceLine, string filePath) : base(importTarget, referenceLine, filePath) {} public new RoundedDouble GetStandardDeviation(StructuresParameterRow parameter, string structureName) { return base.GetStandardDeviation(parameter, structureName); } public new RoundedDouble GetCoefficientOfVariation(StructuresParameterRow parameter, string structureName) { return base.GetCoefficientOfVariation(parameter, structureName); } protected override void CreateSpecificStructures(ICollection structureLocations, Dictionary> groupedStructureParameterRows) {} } } }