// Copyright (C) Stichting Deltares 2016. 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 Application.Ringtoets.Migration.Core;
using Core.Common.Base.Storage;
using Core.Common.Gui;
using Core.Common.TestUtil;
using NUnit.Extensions.Forms;
using NUnit.Framework;
using Rhino.Mocks;
using Ringtoets.Common.Utils;
namespace Application.Ringtoets.Migration.Test
{
[TestFixture]
public class RingtoetsProjectMigratorTest : NUnitFormTest
{
private readonly string currentDatabaseVersion = RingtoetsVersionHelper.GetCurrentDatabaseVersion();
[Test]
public void Constructor_InquiryHelperNull_ThrowsArgumentNullException()
{
// Call
TestDelegate call = () => new RingtoetsProjectMigrator(null);
// Assert
string paramName = Assert.Throws(call).ParamName;
Assert.AreEqual("inquiryHelper", paramName);
}
[Test]
public void Constructor_ReturnsExpectedProperties()
{
// Setup
var mocks = new MockRepository();
var inquiryHelper = mocks.Stub();
mocks.ReplayAll();
// Call
var migrator = new RingtoetsProjectMigrator(inquiryHelper);
// Assert
Assert.IsInstanceOf(migrator);
mocks.VerifyAll();
}
[Test]
public void ShouldMigrate_SourcePathNull_ThrowsArgumentNullException()
{
// Setup
var mocks = new MockRepository();
var inquiryHelper = mocks.Stub();
mocks.ReplayAll();
var migrator = new RingtoetsProjectMigrator(inquiryHelper);
// Call
TestDelegate call = () => migrator.ShouldMigrate(null);
// Assert
string paramName = Assert.Throws(call).ParamName;
Assert.AreEqual("filePath", paramName);
mocks.VerifyAll();
}
[Test]
[TestCase("")]
[TestCase(" ")]
public void ShouldMigrate_InvalidFilePath_ThrowsArgumentException(string invalidFilePath)
{
// Setup
var mocks = new MockRepository();
var inquiryHelper = mocks.Stub();
mocks.ReplayAll();
var migrator = new RingtoetsProjectMigrator(inquiryHelper);
// Call
TestDelegate call = () => migrator.ShouldMigrate(invalidFilePath);
// Assert
string paramName = TestHelper.AssertThrowsArgumentExceptionAndTestMessage(
call, "Bronprojectpad moet een geldig projectpad zijn.").ParamName;
Assert.AreEqual("filePath", paramName);
mocks.VerifyAll();
}
[Test]
public void ShouldMigrate_OutdatedProjectUnsupported_ReturnsAbortedAndGeneratesLogMessages()
{
// Setup
var mocks = new MockRepository();
var inquiryHelper = mocks.Stub();
mocks.ReplayAll();
const string file = "UnsupportedVersion8.rtd";
const string fileVersion = "8";
string sourceFilePath = TestHelper.GetTestDataPath(TestDataPath.Application.Ringtoets.Migration, file);
var migrator = new RingtoetsProjectMigrator(inquiryHelper);
var shouldMigrate = MigrationNeeded.Yes;
// Call
Action call = () => shouldMigrate = migrator.ShouldMigrate(sourceFilePath);
// Assert
string expectedMessage = $"Het migreren van een projectbestand met versie '{fileVersion}' naar versie '{currentDatabaseVersion}' is niet ondersteund.";
TestHelper.AssertLogMessageIsGenerated(call, expectedMessage);
Assert.AreEqual(MigrationNeeded.Aborted, shouldMigrate);
mocks.VerifyAll();
}
[Test]
[TestCase(true)]
[TestCase(false)]
public void ShouldMigrate_OutdatedProjectSupported_AskMigrationConfirmationAndReturnBasedOnConfirmation(bool confirmContinuation)
{
// Setup
string question = "Het project dat u wilt openen is opgeslagen in het formaat van een eerdere versie van Ringtoets." +
$" Weet u zeker dat u het bestand wilt migreren naar het formaat van uw huidige Ringtoetsversie ({currentDatabaseVersion})?";
var mocks = new MockRepository();
var inquiryHelper = mocks.StrictMock();
inquiryHelper.Expect(h => h.InquireContinuation(question)).Return(confirmContinuation);
mocks.ReplayAll();
const string file = "FullTestProject164.rtd";
string sourceFilePath = TestHelper.GetTestDataPath(TestDataPath.Application.Ringtoets.Migration, file);
var migrator = new RingtoetsProjectMigrator(inquiryHelper);
// Call
MigrationNeeded shouldMigrate = MigrationNeeded.No;
Action call = () => shouldMigrate = migrator.ShouldMigrate(sourceFilePath);
// Assert
var expectedLogMessages = new List();
if (!confirmContinuation)
{
expectedLogMessages.Add($"Het migreren van het projectbestand '{sourceFilePath}' is geannuleerd.");
}
TestHelper.AssertLogMessagesAreGenerated(call, expectedLogMessages, expectedLogMessages.Count);
var expectedResult = confirmContinuation ?
MigrationNeeded.Yes :
MigrationNeeded.Aborted;
Assert.AreEqual(expectedResult, shouldMigrate);
mocks.VerifyAll();
}
[Test]
public void ShouldMigrate_LatestProjectVersion_ReturnsFalse()
{
// Setup
var mocks = new MockRepository();
var inquiryHelper = mocks.Stub();
mocks.ReplayAll();
const string currentProjectVersionFile = "FullTestProject171.rtd";
string sourceFilePath = TestHelper.GetTestDataPath(TestDataPath.Application.Ringtoets.Migration, currentProjectVersionFile);
var versionedFile = new RingtoetsVersionedFile(sourceFilePath);
string testProjectVersion = versionedFile.GetVersion();
var migrator = new RingtoetsProjectMigrator(inquiryHelper);
// Pre-condition
string assertionMessage = $"Database version {testProjectVersion} of the testproject must match with the current database version {currentDatabaseVersion}.";
Assert.AreEqual(currentDatabaseVersion, testProjectVersion, assertionMessage);
// Call
MigrationNeeded shouldMigrate = migrator.ShouldMigrate(sourceFilePath);
// Assert
Assert.AreEqual(MigrationNeeded.No, shouldMigrate);
mocks.VerifyAll();
}
[Test]
public void DetermineMigrationLocation_FilePathNull_ThrownArgumentNullException()
{
// Setup
var mocks = new MockRepository();
var inquiryHelper = mocks.Stub();
mocks.ReplayAll();
var migrator = new RingtoetsProjectMigrator(inquiryHelper);
// Call
TestDelegate call = () => migrator.DetermineMigrationLocation(null);
// Assert
string paramName = Assert.Throws(call).ParamName;
Assert.AreEqual("originalFilePath", paramName);
mocks.VerifyAll();
}
[Test]
[TestCase("")]
[TestCase(" ")]
public void DetermineMigrationLocation_InvalidFilePath_ThrowsArgumentException(string invalidFilePath)
{
// Setup
var mocks = new MockRepository();
var inquiryHelper = mocks.Stub();
mocks.ReplayAll();
var migrator = new RingtoetsProjectMigrator(inquiryHelper);
// Call
TestDelegate call = () => migrator.DetermineMigrationLocation(invalidFilePath);
// Assert
string paramName = TestHelper.AssertThrowsArgumentExceptionAndTestMessage(
call, "Bronprojectpad moet een geldig projectpad zijn.").ParamName;
Assert.AreEqual("originalFilePath", paramName);
mocks.VerifyAll();
}
[Test]
public void DetermineMigrationLocation_ValidPath_AsksUserForTargetPathAndReturnsIt()
{
// Setup
const string originalFileName = "Im_a_valid_file_path";
const string expectedFileExtension = "rtd";
string validFilePath = TestHelper.GetScratchPadPath($"{originalFileName}.{expectedFileExtension}");
string versionWithUnderscores = RingtoetsVersionHelper.GetCurrentDatabaseVersion().Replace('.', '-');
var expectedFileFilter = new FileFilterGenerator(expectedFileExtension, "Ringtoets project");
string expectedSuggestedFileName = $"{originalFileName}_{versionWithUnderscores}";
string expectedReturnPath = TestHelper.GetScratchPadPath("Im_a_file_path_to_the_migrated_file.rtd");
var mocks = new MockRepository();
var inquiryHelper = mocks.StrictMock();
inquiryHelper.Expect(h => h.GetTargetFileLocation(expectedFileFilter, expectedSuggestedFileName))
.Return(expectedReturnPath);
mocks.ReplayAll();
var migrator = new RingtoetsProjectMigrator(inquiryHelper);
// Call
string targetFilePath = migrator.DetermineMigrationLocation(validFilePath);
// Assert
Assert.AreEqual(expectedReturnPath, targetFilePath);
mocks.VerifyAll();
}
[Test]
public void Migrate_SourcePathNull_ThrowsArgumentNullException()
{
// Setup
var mocks = new MockRepository();
var inquiryHelper = mocks.Stub();
mocks.ReplayAll();
var migrator = new RingtoetsProjectMigrator(inquiryHelper);
string targetFileName = $"{nameof(RingtoetsProjectMigratorTest)}." +
$"{nameof(Migrate_SourcePathNull_ThrowsArgumentNullException)}.rtd";
string targetFilePath = TestHelper.GetScratchPadPath(targetFileName);
// Call
TestDelegate call = () => migrator.Migrate(null, targetFilePath);
// Assert
string paramName = Assert.Throws(call).ParamName;
Assert.AreEqual("sourceFilePath", paramName);
}
[Test]
public void Migrate_TargetPathNull_ThrowsArgumentNullException()
{
// Setup
var mocks = new MockRepository();
var inquiryHelper = mocks.Stub();
mocks.ReplayAll();
var migrator = new RingtoetsProjectMigrator(inquiryHelper);
string sourceFilePath = TestHelper.GetTestDataPath(TestDataPath.Application.Ringtoets.Migration, "FullTestProject164.rtd");
// Call
TestDelegate call = () => migrator.Migrate(sourceFilePath, null);
// Assert
string paramName = Assert.Throws(call).ParamName;
Assert.AreEqual("targetFilePath", paramName);
}
[Test]
[TestCase("")]
[TestCase(" ")]
public void Migrate_InvalidSourceFilePath_ThrowsArgumentException(string invalidFilePath)
{
// Setup
var mocks = new MockRepository();
var inquiryHelper = mocks.Stub();
mocks.ReplayAll();
var migrator = new RingtoetsProjectMigrator(inquiryHelper);
string targetFileName = $"{nameof(RingtoetsProjectMigratorTest)}." +
$"{nameof(Migrate_InvalidSourceFilePath_ThrowsArgumentException)}.rtd";
string targetFilePath = TestHelper.GetScratchPadPath(targetFileName);
// Call
TestDelegate call = () => migrator.Migrate(invalidFilePath, targetFilePath);
// Assert
string paramName = TestHelper.AssertThrowsArgumentExceptionAndTestMessage(
call, "Bronprojectpad moet een geldig projectpad zijn.").ParamName;
Assert.AreEqual("sourceFilePath", paramName);
mocks.VerifyAll();
}
[Test]
[TestCase("")]
[TestCase(" ")]
public void Migrate_InvalidTargetFilePath_ThrowsArgumentException(string invalidFilePath)
{
// Setup
var mocks = new MockRepository();
var inquiryHelper = mocks.Stub();
mocks.ReplayAll();
var migrator = new RingtoetsProjectMigrator(inquiryHelper);
string sourceFilePath = TestHelper.GetTestDataPath(TestDataPath.Application.Ringtoets.Migration,
"FullTestProject164.rtd");
// Call
TestDelegate call = () => migrator.Migrate(sourceFilePath, invalidFilePath);
// Assert
string paramName = TestHelper.AssertThrowsArgumentExceptionAndTestMessage(
call, "Doelprojectpad moet een geldig projectpad zijn.").ParamName;
Assert.AreEqual("targetFilePath", paramName);
mocks.VerifyAll();
}
[Test]
public void GivenMigratorAndSupportedFile_WhenValidTargetLocationGiven_ThenFileSuccessFullyMigrates()
{
// Given
string sourceFilePath = TestHelper.GetTestDataPath(TestDataPath.Application.Ringtoets.Migration, "FullTestProject164.rtd");
string targetFile = $"{nameof(RingtoetsProjectMigratorTest)}." +
$"{nameof(GivenMigratorAndSupportedFile_WhenValidTargetLocationGiven_ThenFileSuccessFullyMigrates)}.rtd";
string targetFilePath = Path.Combine(TestHelper.GetScratchPadPath(), targetFile);
var mocks = new MockRepository();
var inquiryHelper = mocks.Stub();
mocks.ReplayAll();
var migrator = new RingtoetsProjectMigrator(inquiryHelper);
using (new FileDisposeHelper(targetFilePath))
{
bool migrationSuccessful = false;
// When
Action call = () => migrationSuccessful = migrator.Migrate(sourceFilePath, targetFilePath);
// Then
string expectedMessage = $"Het projectbestand '{sourceFilePath}' is succesvol gemigreerd naar '{targetFilePath}' (versie {currentDatabaseVersion}).";
TestHelper.AssertLogMessageIsGenerated(call, expectedMessage, 1);
Assert.IsTrue(migrationSuccessful);
var toVersionedFile = new RingtoetsVersionedFile(targetFilePath);
Assert.AreEqual(currentDatabaseVersion, toVersionedFile.GetVersion());
}
mocks.VerifyAll();
}
[Test]
public void Migrate_UnableToSaveAtTargetFilePath_MigrationFailsAndLogsError()
{
// Setup
string sourceFilePath = TestHelper.GetTestDataPath(TestDataPath.Application.Ringtoets.Migration, "FullTestProject164.rtd");
string targetFilePath = $"{nameof(RingtoetsProjectMigratorTest)}." +
$"{nameof(Migrate_UnableToSaveAtTargetFilePath_MigrationFailsAndLogsError)}.rtd";
var mocks = new MockRepository();
var inquiryHelper = mocks.Stub();
mocks.ReplayAll();
var migrator = new RingtoetsProjectMigrator(inquiryHelper);
// Assert
using (var fileDisposeHelper = new FileDisposeHelper(targetFilePath))
{
fileDisposeHelper.LockFiles();
bool migrationSuccessful = true;
// Call
Action call = () => migrationSuccessful = migrator.Migrate(sourceFilePath, targetFilePath);
// Assert
TestHelper.AssertLogMessages(call, messages =>
{
string[] msgs = messages.ToArray();
Assert.AreEqual(1, msgs.Length);
StringAssert.StartsWith($"Het migreren van het projectbestand '{sourceFilePath}' is mislukt: ", msgs[0]);
});
Assert.IsFalse(migrationSuccessful);
}
mocks.VerifyAll();
}
[Test]
public void Migrate_UnsupportedSourceFileVersion_MigrationFailsAndLogsError()
{
// Setup
string sourceFilePath = TestHelper.GetTestDataPath(TestDataPath.Application.Ringtoets.Migration, "UnsupportedVersion8.rtd");
string targetFile = $"{nameof(RingtoetsProjectMigratorTest)}." +
$"{nameof(Migrate_UnsupportedSourceFileVersion_MigrationFailsAndLogsError)}";
string targetFilePath = Path.Combine(TestHelper.GetScratchPadPath(), targetFile);
var mocks = new MockRepository();
var inquiryHelper = mocks.Stub();
mocks.ReplayAll();
var migrator = new RingtoetsProjectMigrator(inquiryHelper);
using (new FileDisposeHelper(targetFilePath))
{
bool migrationSuccessful = true;
// Call
Action call = () => migrationSuccessful = migrator.Migrate(sourceFilePath, targetFilePath);
// Assert
TestHelper.AssertLogMessages(call, messages =>
{
string[] msgs = messages.ToArray();
Assert.AreEqual(1, msgs.Length);
StringAssert.StartsWith($"Het migreren van het projectbestand '{sourceFilePath}' is mislukt: ", msgs[0]);
});
Assert.IsFalse(migrationSuccessful);
}
mocks.VerifyAll();
}
[Test]
public void Migrate_TargetFileSameAsSourceFile_MigrationFailsAndLogsError()
{
// Setup
string sourceFilePath = TestHelper.GetTestDataPath(TestDataPath.Application.Ringtoets.Migration, "FullTestProject164.rtd");
var mocks = new MockRepository();
var inquiryHelper = mocks.Stub();
mocks.ReplayAll();
var migrator = new RingtoetsProjectMigrator(inquiryHelper);
bool migrationSuccessful = true;
// Call
Action call = () => migrationSuccessful = migrator.Migrate(sourceFilePath, sourceFilePath);
// Assert
TestHelper.AssertLogMessages(call, messages =>
{
string[] msgs = messages.ToArray();
Assert.AreEqual(1, msgs.Length);
StringAssert.StartsWith($"Het migreren van het projectbestand '{sourceFilePath}' is mislukt: ", msgs[0]);
});
Assert.IsFalse(migrationSuccessful);
mocks.VerifyAll();
}
}
}