// Copyright (C) Stichting Deltares 2018. 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.IO;
using Core.Common.TestUtil;
using NUnit.Framework;
using Rhino.Mocks;
using Ringtoets.Common.Data.Hydraulics;
using Ringtoets.Common.IO.HydraRing;
using Ringtoets.Common.IO.TestUtil;
using Ringtoets.HydraRing.IO.HydraulicBoundaryDatabase;
using Ringtoets.HydraRing.IO.HydraulicLocationConfigurationDatabase;
using Ringtoets.Integration.IO.Handlers;
using Ringtoets.Integration.IO.Importers;
namespace Ringtoets.Integration.IO.Test.Importers
{
[TestFixture]
public class HydraulicBoundaryDatabaseImporterTest
{
private const int totalNumberOfSteps = 4;
private static readonly string testDataPath = TestHelper.GetTestDataPath(TestDataPath.Ringtoets.Integration.IO, nameof(HydraulicBoundaryDatabaseImporter));
private readonly string validFilePath = Path.Combine(testDataPath, "complete.sqlite");
[Test]
public void Constructor_UpdateHandlerNull_ThrowsArgumentNullException()
{
// Call
TestDelegate call = () => new HydraulicBoundaryDatabaseImporter(new HydraulicBoundaryDatabase(), null, "");
// Assert
var exception = Assert.Throws(call);
Assert.AreEqual("updateHandler", exception.ParamName);
}
[Test]
public void Constructor_ExpectedValues()
{
// Setup
var mocks = new MockRepository();
var updateHandler = mocks.Stub();
mocks.ReplayAll();
// Call
var importer = new HydraulicBoundaryDatabaseImporter(new HydraulicBoundaryDatabase(), updateHandler, "");
// Assert
Assert.IsInstanceOf>(importer);
mocks.VerifyAll();
}
[Test]
public void Import_FilePathIsDirectory_CancelImportWithErrorMessage()
{
// Setup
var mocks = new MockRepository();
var handler = mocks.StrictMock();
mocks.ReplayAll();
string path = TestHelper.GetTestDataPath(TestDataPath.Ringtoets.Integration.IO, Path.DirectorySeparatorChar.ToString());
var importer = new HydraulicBoundaryDatabaseImporter(new HydraulicBoundaryDatabase(), handler, path);
// Call
var importSuccessful = true;
Action call = () => importSuccessful = importer.Import();
// Assert
string expectedMessage = $"Fout bij het lezen van bestand '{path}': bestandspad mag niet verwijzen naar een lege bestandsnaam.";
AssertImportFailed(call, expectedMessage, ref importSuccessful);
mocks.VerifyAll();
}
[Test]
public void Import_FileDoesNotExist_CancelImportWithErrorMessage()
{
// Setup
var mocks = new MockRepository();
var handler = mocks.StrictMock();
mocks.ReplayAll();
string path = TestHelper.GetTestDataPath(TestDataPath.Ringtoets.Integration.IO, "I_dont_exist");
var importer = new HydraulicBoundaryDatabaseImporter(new HydraulicBoundaryDatabase(), handler, path);
// Call
var importSuccessful = true;
Action call = () => importSuccessful = importer.Import();
// Assert
string expectedMessage = $"Fout bij het lezen van bestand '{path}': het bestand bestaat niet.";
AssertImportFailed(call, expectedMessage, ref importSuccessful);
mocks.VerifyAll();
}
[Test]
public void Import_InvalidSchema_CancelImportWithErrorMessage()
{
// Setup
var mocks = new MockRepository();
var handler = mocks.StrictMock();
mocks.ReplayAll();
string path = Path.Combine(testDataPath, "corruptschema.sqlite");
var importer = new HydraulicBoundaryDatabaseImporter(new HydraulicBoundaryDatabase(), handler, path);
// Call
var importSuccessful = true;
Action call = () => importSuccessful = importer.Import();
// Assert
string expectedMessage = $"Fout bij het lezen van bestand '{path}': kritieke fout opgetreden bij het uitlezen van waardes uit kolommen in de database.";
AssertImportFailed(call, expectedMessage, ref importSuccessful);
mocks.VerifyAll();
}
[Test]
public void Import_EmptySchema_CancelImportWithErrorMessage()
{
// Setup
var mocks = new MockRepository();
var handler = mocks.StrictMock();
mocks.ReplayAll();
string path = Path.Combine(testDataPath, "empty.sqlite");
var importer = new HydraulicBoundaryDatabaseImporter(new HydraulicBoundaryDatabase(), handler, path);
// Call
var importSuccessful = true;
Action call = () => importSuccessful = importer.Import();
// Assert
string expectedMessage = $"Fout bij het lezen van bestand '{path}': kon geen locaties verkrijgen van de database.";
AssertImportFailed(call, expectedMessage, ref importSuccessful);
mocks.VerifyAll();
}
[Test]
public void Import_ExistingFileWithoutHlcd_CancelImportWithErrorMessage()
{
// Setup
var mocks = new MockRepository();
var handler = mocks.StrictMock();
handler.Stub(h => h.IsConfirmationRequired(null, null)).IgnoreArguments().Return(false);
mocks.ReplayAll();
string path = Path.Combine(testDataPath, "withoutHLCD", "complete.sqlite");
var importer = new HydraulicBoundaryDatabaseImporter(new HydraulicBoundaryDatabase(), handler, path);
// Call
var importSuccessful = true;
Action call = () => importSuccessful = importer.Import();
// Assert
string expectedMessage = $"Fout bij het lezen van bestand '{path}': het bijbehorende HLCD bestand is niet gevonden in dezelfde map als het HRD bestand.";
AssertImportFailed(call, expectedMessage, ref importSuccessful);
mocks.VerifyAll();
}
[Test]
public void Import_ExistingFileWithEmptyHlcdSchema_CancelImportWithErrorMessage()
{
// Setup
var mocks = new MockRepository();
var handler = mocks.StrictMock();
handler.Stub(h => h.IsConfirmationRequired(null, null)).IgnoreArguments().Return(false);
mocks.ReplayAll();
string path = Path.Combine(testDataPath, "EmptyHLCDSchema", "complete.sqlite");
string hlcdFilePath = Path.Combine(Path.GetDirectoryName(path), "hlcd.sqlite");
var importer = new HydraulicBoundaryDatabaseImporter(new HydraulicBoundaryDatabase(), handler, path);
// Call
var importSuccessful = true;
Action call = () => importSuccessful = importer.Import();
// Assert
string expectedMessage = $"Fout bij het lezen van bestand '{hlcdFilePath}': het bevragen van de database is mislukt.";
AssertImportFailed(call, expectedMessage, ref importSuccessful);
mocks.VerifyAll();
}
[Test]
public void Import_ExistingFileWithInvalidHlcdSchema_CancelImportWithErrorMessage()
{
// Setup
var mocks = new MockRepository();
var handler = mocks.StrictMock();
handler.Stub(h => h.IsConfirmationRequired(null, null)).IgnoreArguments().Return(false);
mocks.ReplayAll();
string path = Path.Combine(testDataPath, "InvalidHLCDSchema", "complete.sqlite");
string hlcdFilePath = Path.Combine(Path.GetDirectoryName(path), "hlcd.sqlite");
var importer = new HydraulicBoundaryDatabaseImporter(new HydraulicBoundaryDatabase(), handler, path);
// Call
var importSuccessful = true;
Action call = () => importSuccessful = importer.Import();
// Assert
string expectedMessage = $"Fout bij het lezen van bestand '{hlcdFilePath}': kritieke fout opgetreden bij het uitlezen van waardes uit kolommen in de database.";
AssertImportFailed(call, expectedMessage, ref importSuccessful);
mocks.VerifyAll();
}
[Test]
[TestCase("hlcdWithScenarioInformationNoEntries")]
[TestCase("hlcdWithScenarioInformationMultipleEntries")]
public void Import_ExistingFileAndHlcdWithInvalidNumberOfScenarioInformationEntries_CancelImportWithErrorMessage(string testFolder)
{
// Setup
var mocks = new MockRepository();
var handler = mocks.StrictMock();
handler.Stub(h => h.IsConfirmationRequired(null, null)).IgnoreArguments().Return(false);
mocks.ReplayAll();
string path = Path.Combine(testDataPath, testFolder, "complete.sqlite");
string hlcdFilePath = Path.Combine(Path.GetDirectoryName(path), "hlcd.sqlite");
var importer = new HydraulicBoundaryDatabaseImporter(new HydraulicBoundaryDatabase(), handler, path);
// Call
var importSuccessful = true;
Action call = () => importSuccessful = importer.Import();
// Assert
string expectedMessage = $"Fout bij het lezen van bestand '{hlcdFilePath}': placeHolder."
+ $"{Environment.NewLine}Er is geen hydraulische belastingen database gekoppeld.";
TestHelper.AssertLogMessageIsGenerated(call, expectedMessage, 1);
Assert.IsFalse(importSuccessful);
mocks.VerifyAll();
}
[Test]
public void Import_ExistingFileWithoutSettings_CancelImportWithErrorMessage()
{
// Setup
var mocks = new MockRepository();
var handler = mocks.StrictMock();
handler.Stub(h => h.IsConfirmationRequired(null, null)).IgnoreArguments().Return(false);
mocks.ReplayAll();
string path = Path.Combine(testDataPath, "withoutSettings", "complete.sqlite");
var importer = new HydraulicBoundaryDatabaseImporter(new HydraulicBoundaryDatabase(), handler, path);
// Call
var importSuccessful = true;
Action call = () => importSuccessful = importer.Import();
// Assert
string expectedMessage = $"Fout bij het lezen van bestand '{path}': kon het rekeninstellingen bestand niet openen. " +
$"Fout bij het lezen van bestand '{HydraulicBoundaryDatabaseHelper.GetHydraulicBoundarySettingsDatabase(path)}': het bestand bestaat niet.";
AssertImportFailed(call, expectedMessage, ref importSuccessful);
mocks.VerifyAll();
}
[Test]
public void Import_ExistingFileWithInvalidSettings_CancelImportWithErrorMessage()
{
// Setup
var mocks = new MockRepository();
var handler = mocks.StrictMock();
handler.Stub(h => h.IsConfirmationRequired(null, null)).IgnoreArguments().Return(false);
mocks.ReplayAll();
string path = Path.Combine(testDataPath, "invalidSettings", "complete.sqlite");
var importer = new HydraulicBoundaryDatabaseImporter(new HydraulicBoundaryDatabase(), handler, path);
// Call
var importSuccessful = true;
Action call = () => importSuccessful = importer.Import();
// Assert
string expectedMessage = $"Fout bij het lezen van bestand '{path}': de rekeninstellingen database heeft niet het juiste schema.";
AssertImportFailed(call, expectedMessage, ref importSuccessful);
mocks.VerifyAll();
}
[Test]
[TestCase(true)]
[TestCase(false)]
public void Import_WithValidFileAndHlcdWithoutScenarioInformation_UpdatesHydraulicBoundaryDatabaseWithImportedData(bool confirmationRequired)
{
// Setup
var hydraulicBoundaryDatabase = new HydraulicBoundaryDatabase();
var mocks = new MockRepository();
var handler = mocks.StrictMock();
handler.Expect(h => h.IsConfirmationRequired(Arg.Is.Same(hydraulicBoundaryDatabase),
Arg.Is.NotNull))
.WhenCalled(invocation =>
{
AssertReadHydraulicBoundaryDatabase((ReadHydraulicBoundaryDatabase) invocation.Arguments[1]);
})
.Return(confirmationRequired);
if (confirmationRequired)
{
handler.Expect(h => h.InquireConfirmation()).Return(true);
}
handler.Expect(h => h.Update(Arg.Is.Same(hydraulicBoundaryDatabase),
Arg.Is.NotNull,
Arg.Is.NotNull,
Arg>.Is.NotNull,
Arg.Is.Same(validFilePath)))
.WhenCalled(invocation =>
{
AssertReadHydraulicBoundaryDatabase((ReadHydraulicBoundaryDatabase) invocation.Arguments[1]);
var readHydraulicLocationConfigurationDatabase = (ReadHydraulicLocationConfigurationDatabase) invocation.Arguments[2];
Assert.AreEqual(18, readHydraulicLocationConfigurationDatabase.LocationIdMappings.Count());
CollectionAssert.IsEmpty(readHydraulicLocationConfigurationDatabase.ReadHydraulicLocationConfigurationDatabaseSettings);
Assert.IsFalse(readHydraulicLocationConfigurationDatabase.IsScenarioInformationPresent);
var excludedLocationIds = (IEnumerable) invocation.Arguments[3];
Assert.AreEqual(1, excludedLocationIds.Count());
})
.Return(Enumerable.Empty());
mocks.ReplayAll();
var importer = new HydraulicBoundaryDatabaseImporter(hydraulicBoundaryDatabase, handler, validFilePath);
// Call
bool importResult = importer.Import();
// Assert
Assert.IsTrue(importResult);
mocks.VerifyAll();
}
[Test]
public void Import_WithValidFileAndHlcdWithValidScenarioInformation_UpdatesHydraulicBoundaryDatabaseWithImportedData()
{
// Setup
string filePath = Path.Combine(testDataPath, "hlcdWithValidScenarioInformation", "complete.sqlite");
var hydraulicBoundaryDatabase = new HydraulicBoundaryDatabase();
var mocks = new MockRepository();
var handler = mocks.StrictMock();
handler.Stub(h => h.IsConfirmationRequired(Arg.Is.Same(hydraulicBoundaryDatabase),
Arg.Is.NotNull))
.WhenCalled(invocation =>
{
AssertReadHydraulicBoundaryDatabase((ReadHydraulicBoundaryDatabase)invocation.Arguments[1]);
})
.Return(false);
handler.Expect(h => h.Update(Arg.Is.Same(hydraulicBoundaryDatabase),
Arg.Is.NotNull,
Arg.Is.NotNull,
Arg>.Is.NotNull,
Arg.Is.Same(filePath)))
.WhenCalled(invocation =>
{
AssertReadHydraulicBoundaryDatabase((ReadHydraulicBoundaryDatabase)invocation.Arguments[1]);
var readHydraulicLocationConfigurationDatabase = (ReadHydraulicLocationConfigurationDatabase)invocation.Arguments[2];
Assert.AreEqual(18, readHydraulicLocationConfigurationDatabase.LocationIdMappings.Count());
Assert.AreEqual(1, readHydraulicLocationConfigurationDatabase.ReadHydraulicLocationConfigurationDatabaseSettings.Count());
Assert.IsTrue(readHydraulicLocationConfigurationDatabase.IsScenarioInformationPresent);
var excludedLocationIds = (IEnumerable)invocation.Arguments[3];
Assert.AreEqual(0, excludedLocationIds.Count());
})
.Return(Enumerable.Empty());
mocks.ReplayAll();
var importer = new HydraulicBoundaryDatabaseImporter(hydraulicBoundaryDatabase, handler, filePath);
// Call
bool importResult = importer.Import();
// Assert
Assert.IsTrue(importResult);
mocks.VerifyAll();
}
[Test]
public void Import_ValidFiles_ExpectedProgressNotifications()
{
// Setup
var mocks = new MockRepository();
var handler = mocks.Stub();
handler.Stub(h => h.IsConfirmationRequired(null, null)).IgnoreArguments().Return(false);
handler.Stub(h => h.Update(null, null, null, null, null)).IgnoreArguments().Return(Enumerable.Empty());
mocks.ReplayAll();
var progressChangeNotifications = new List();
var importer = new HydraulicBoundaryDatabaseImporter(new HydraulicBoundaryDatabase(), handler, validFilePath);
importer.SetProgressChanged((description, step, steps) => progressChangeNotifications.Add(new ProgressNotification(description, step, steps)));
// Call
bool importResult = importer.Import();
// Assert
Assert.IsTrue(importResult);
var expectedProgressNotifications = new[]
{
new ProgressNotification("Inlezen van het hydraulische belastingen bestand.", 1, totalNumberOfSteps),
new ProgressNotification("Inlezen van het hydraulische locatie configuratie bestand.", 2, totalNumberOfSteps),
new ProgressNotification("Inlezen van het rekeninstellingen bestand.", 3, totalNumberOfSteps),
new ProgressNotification("Geïmporteerde data toevoegen aan het traject.", 4, totalNumberOfSteps)
};
ProgressNotificationTestHelper.AssertProgressNotificationsAreEqual(expectedProgressNotifications, progressChangeNotifications);
mocks.VerifyAll();
}
[Test]
public void Import_CancelImportDuringDialogInteraction_GenerateCanceledLogMessageAndReturnsFalse()
{
// Setup
var mocks = new MockRepository();
var handler = mocks.StrictMock();
handler.Expect(h => h.IsConfirmationRequired(Arg.Is.NotNull,
Arg.Is.NotNull))
.WhenCalled(invocation =>
{
AssertReadHydraulicBoundaryDatabase((ReadHydraulicBoundaryDatabase) invocation.Arguments[1]);
})
.Return(true);
handler.Expect(h => h.InquireConfirmation()).Return(false);
mocks.ReplayAll();
var importer = new HydraulicBoundaryDatabaseImporter(new HydraulicBoundaryDatabase(), handler, validFilePath);
var importResult = true;
// Call
Action call = () => importResult = importer.Import();
// Assert
const string expectedMessage = "Hydraulische belastingen database koppelen afgebroken. Geen gegevens gewijzigd.";
TestHelper.AssertLogMessageWithLevelIsGenerated(call, Tuple.Create(expectedMessage, LogLevelConstant.Info), 1);
Assert.IsFalse(importResult);
mocks.VerifyAll();
}
[Test]
[TestCase(1)]
[TestCase(2)]
[TestCase(3)]
public void Import_CancelOfImportWhilePerformingStep_CancelsImportAndLogs(int stepNumber)
{
// Setup
var mocks = new MockRepository();
var handler = mocks.StrictMock();
handler.Stub(h => h.IsConfirmationRequired(null, null)).IgnoreArguments().Return(false);
mocks.ReplayAll();
var importer = new HydraulicBoundaryDatabaseImporter(new HydraulicBoundaryDatabase(), handler, validFilePath);
importer.SetProgressChanged((description, currentStep, steps) =>
{
if (currentStep == stepNumber)
{
importer.Cancel();
}
});
// Precondition
Assert.IsTrue(File.Exists(validFilePath));
// Call
var importResult = true;
Action call = () => importResult = importer.Import();
// Assert
const string expectedMessage = "Hydraulische belastingen database koppelen afgebroken. Geen gegevens gewijzigd.";
TestHelper.AssertLogMessageWithLevelIsGenerated(call, Tuple.Create(expectedMessage, LogLevelConstant.Info), 1);
Assert.IsFalse(importResult);
mocks.VerifyAll();
}
[Test]
public void Import_CancelImportDuringAddReadDataToDataModel_ContinuesImportAndLogs()
{
// Setup
var mocks = new MockRepository();
var handler = mocks.Stub();
handler.Stub(h => h.IsConfirmationRequired(null, null)).IgnoreArguments().Return(false);
handler.Stub(h => h.Update(null, null, null, null, null)).IgnoreArguments().Return(Enumerable.Empty());
mocks.ReplayAll();
var importer = new HydraulicBoundaryDatabaseImporter(new HydraulicBoundaryDatabase(), handler, validFilePath);
importer.SetProgressChanged((description, step, steps) =>
{
if (step == totalNumberOfSteps)
{
importer.Cancel();
}
});
var importResult = true;
// Call
importer.Import();
Action call = () => importResult = importer.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);
mocks.VerifyAll();
}
[Test]
public void DoPostImportUpdates_HydraulicBoundaryDatabaseIsSetAndAnswerDialogToContinue_NotifyObserversOfTargetAndClearedObjects()
{
// Setup
var hydraulicBoundaryDatabase = new HydraulicBoundaryDatabase();
var mocks = new MockRepository();
var hydraulicBoundaryDatabaseObserver = mocks.Stub();
hydraulicBoundaryDatabaseObserver.Expect(o => o.UpdateObserver());
var observable1 = mocks.StrictMock();
observable1.Expect(o => o.NotifyObservers());
var observable2 = mocks.StrictMock();
observable2.Expect(o => o.NotifyObservers());
var handler = mocks.StrictMock();
handler.Expect(h => h.IsConfirmationRequired(null, null)).IgnoreArguments().Return(false);
handler.Expect(h => h.Update(Arg.Is.NotNull,
Arg.Is.NotNull,
Arg.Is.NotNull,
Arg>.Is.NotNull,
Arg.Is.NotNull))
.Return(new[]
{
observable1,
observable2
});
handler.Expect(h => h.DoPostUpdateActions());
mocks.ReplayAll();
hydraulicBoundaryDatabase.Attach(hydraulicBoundaryDatabaseObserver);
var importer = new HydraulicBoundaryDatabaseImporter(hydraulicBoundaryDatabase, handler, validFilePath);
// Precondition
Assert.IsTrue(importer.Import());
// Call
importer.DoPostImport();
// Assert
mocks.VerifyAll(); // Expect NotifyObservers on updated observables
}
[Test]
public void DoPostImportUpdates_CancelingImport_DoNotNotifyObserversAndNotDoPostReplacementUpdates()
{
// Setup
var hydraulicBoundaryDatabase = new HydraulicBoundaryDatabase();
var mocks = new MockRepository();
var observer = mocks.StrictMock();
var handler = mocks.StrictMock();
var importer = new HydraulicBoundaryDatabaseImporter(hydraulicBoundaryDatabase, handler, validFilePath);
handler.Expect(h => h.IsConfirmationRequired(null, null)).IgnoreArguments()
.WhenCalled(invocation => importer.Cancel())
.Return(false);
mocks.ReplayAll();
hydraulicBoundaryDatabase.Attach(observer);
// Precondition
Assert.IsFalse(importer.Import());
// Call
importer.DoPostImport();
// Assert
mocks.VerifyAll(); // Expect no NotifyObserver calls
}
private static void AssertImportFailed(Action call, string errorMessage, ref bool importSuccessful)
{
string expectedMessage = $"{errorMessage}" +
$"{Environment.NewLine}Er is geen hydraulische belastingen database gekoppeld.";
TestHelper.AssertLogMessageWithLevelIsGenerated(call, new Tuple(expectedMessage,
LogLevelConstant.Error), 1);
Assert.IsFalse(importSuccessful);
}
private static void AssertReadHydraulicBoundaryDatabase(ReadHydraulicBoundaryDatabase readHydraulicBoundaryDatabase)
{
Assert.AreEqual("Dutch coast South19-11-2015 12:0013", readHydraulicBoundaryDatabase.Version);
Assert.AreEqual((long) 13, readHydraulicBoundaryDatabase.TrackId);
Assert.AreEqual(18, readHydraulicBoundaryDatabase.Locations.Count());
ReadHydraulicBoundaryLocation location = readHydraulicBoundaryDatabase.Locations.First();
Assert.AreEqual(1, location.Id);
Assert.AreEqual("punt_flw_ 1", location.Name);
Assert.AreEqual(52697.5, location.CoordinateX);
Assert.AreEqual(427567.0, location.CoordinateY);
}
}
}