Index: Application/Ringtoets/test/Application.Ringtoets.Storage.Test/Application.Ringtoets.Storage.Test.csproj =================================================================== diff -u -r04f5526f955c773d4987e820e2aca2614dfbd8d8 -rd8e4a22bfd0197db115f65780b026b4365f26f94 --- Application/Ringtoets/test/Application.Ringtoets.Storage.Test/Application.Ringtoets.Storage.Test.csproj (.../Application.Ringtoets.Storage.Test.csproj) (revision 04f5526f955c773d4987e820e2aca2614dfbd8d8) +++ Application/Ringtoets/test/Application.Ringtoets.Storage.Test/Application.Ringtoets.Storage.Test.csproj (.../Application.Ringtoets.Storage.Test.csproj) (revision d8e4a22bfd0197db115f65780b026b4365f26f94) @@ -122,6 +122,7 @@ + Index: Application/Ringtoets/test/Application.Ringtoets.Storage.Test/IntegrationTests/MigrationTo173IntegrationTest.cs =================================================================== diff -u --- Application/Ringtoets/test/Application.Ringtoets.Storage.Test/IntegrationTests/MigrationTo173IntegrationTest.cs (revision 0) +++ Application/Ringtoets/test/Application.Ringtoets.Storage.Test/IntegrationTests/MigrationTo173IntegrationTest.cs (revision d8e4a22bfd0197db115f65780b026b4365f26f94) @@ -0,0 +1,353 @@ +// 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.Collections.ObjectModel; +using System.Data; +using System.Data.SQLite; +using Application.Ringtoets.Migration.Core; +using Core.Common.Base.IO; +using Core.Common.IO.Readers; +using Core.Common.TestUtil; +using NUnit.Framework; + +namespace Application.Ringtoets.Storage.Test.IntegrationTests +{ + public class MigrationTo173IntegrationTest + { + private const string newVersion = "17.3"; + + [Test] + public void Given172Project_WhenUpgradedTo173_ThenProjectAsExpected() + { + // Given + string sourceFilePath = TestHelper.GetTestDataPath(TestDataPath.Application.Ringtoets.Migration.Core, + "FullTestProject172.rtd"); + var fromVersionedFile = new RingtoetsVersionedFile(sourceFilePath); + + string targetFilePath = TestHelper.GetScratchPadPath(nameof(Given172Project_WhenUpgradedTo173_ThenProjectAsExpected)); + string logFilePath = TestHelper.GetScratchPadPath(string.Concat(nameof(Given172Project_WhenUpgradedTo173_ThenProjectAsExpected), ".log")); + var migrator = new RingtoetsSqLiteDatabaseFileMigrator + { + LogPath = logFilePath + }; + + using (new FileDisposeHelper(logFilePath)) + using (new FileDisposeHelper(targetFilePath)) + { + // When + migrator.Migrate(fromVersionedFile, newVersion, targetFilePath); + + // Then + using (var reader = new MigratedDatabaseReader(targetFilePath)) + { + AssertTablesContentMigrated(reader, sourceFilePath); + + AssertVersions(reader); + AssertDatabase(reader); + } + + AssertLogDatabase(logFilePath); + } + } + + [Test] + public void GivenEmpty164Project_WhenNoChangesMade_ThenLogDatabaseContainsMessagesSayingNoChangesMade() + { + // Given + string sourceFilePath = TestHelper.GetTestDataPath(TestDataPath.Application.Ringtoets.Migration.Core, + "Empty valid Release 16.4.rtd"); + var fromVersionedFile = new RingtoetsVersionedFile(sourceFilePath); + + string targetFilePath = TestHelper.GetScratchPadPath( + nameof(GivenEmpty164Project_WhenNoChangesMade_ThenLogDatabaseContainsMessagesSayingNoChangesMade)); + string logFilePath = TestHelper.GetScratchPadPath( + string.Concat(nameof(GivenEmpty164Project_WhenNoChangesMade_ThenLogDatabaseContainsMessagesSayingNoChangesMade), ".log")); + var migrator = new RingtoetsSqLiteDatabaseFileMigrator + { + LogPath = logFilePath + }; + + using (new FileDisposeHelper(logFilePath)) + using (new FileDisposeHelper(targetFilePath)) + { + // When + migrator.Migrate(fromVersionedFile, newVersion, targetFilePath); + + using (var reader = new MigrationLogDatabaseReader(logFilePath)) + { + ReadOnlyCollection messages = reader.GetMigrationLogMessages(); + Assert.AreEqual(6, messages.Count); + AssertMigrationLogMessageEqual( + new MigrationLogMessage("5", "17.1", "Gevolgen van de migratie van versie 16.4 naar versie 17.1:"), + messages[0]); + AssertMigrationLogMessageEqual( + new MigrationLogMessage("5", "17.1", "* Geen aanpassingen."), + messages[1]); + AssertMigrationLogMessageEqual( + new MigrationLogMessage("17.1", "17.2", "Gevolgen van de migratie van versie 17.1 naar versie 17.2:"), + messages[2]); + AssertMigrationLogMessageEqual( + new MigrationLogMessage("17.1", "17.2", "* Geen aanpassingen."), + messages[3]); + AssertMigrationLogMessageEqual( + new MigrationLogMessage("17.2", newVersion, "Gevolgen van de migratie van versie 17.2 naar versie 17.3:"), + messages[4]); + AssertMigrationLogMessageEqual( + new MigrationLogMessage("17.2", newVersion, "* Geen aanpassingen."), + messages[5]); + } + } + } + + [Test] + public void GivenEmpty171Project_WhenNoChangesMade_ThenLogDatabaseContainsMessagesSayingNoChangesMade() + { + // Given + string sourceFilePath = TestHelper.GetTestDataPath(TestDataPath.Application.Ringtoets.Migration.Core, + "Empty valid Release 17.1.rtd"); + var fromVersionedFile = new RingtoetsVersionedFile(sourceFilePath); + + string targetFilePath = TestHelper.GetScratchPadPath( + nameof(GivenEmpty171Project_WhenNoChangesMade_ThenLogDatabaseContainsMessagesSayingNoChangesMade)); + string logFilePath = TestHelper.GetScratchPadPath( + string.Concat(nameof(GivenEmpty171Project_WhenNoChangesMade_ThenLogDatabaseContainsMessagesSayingNoChangesMade), ".log")); + var migrator = new RingtoetsSqLiteDatabaseFileMigrator + { + LogPath = logFilePath + }; + + using (new FileDisposeHelper(logFilePath)) + using (new FileDisposeHelper(targetFilePath)) + { + // When + migrator.Migrate(fromVersionedFile, newVersion, targetFilePath); + + using (var reader = new MigrationLogDatabaseReader(logFilePath)) + { + ReadOnlyCollection messages = reader.GetMigrationLogMessages(); + Assert.AreEqual(4, messages.Count); + AssertMigrationLogMessageEqual( + new MigrationLogMessage("17.1", "17.2", "Gevolgen van de migratie van versie 17.1 naar versie 17.2:"), + messages[0]); + AssertMigrationLogMessageEqual( + new MigrationLogMessage("17.1", "17.2", "* Geen aanpassingen."), + messages[1]); + AssertMigrationLogMessageEqual( + new MigrationLogMessage("17.2", newVersion, "Gevolgen van de migratie van versie 17.2 naar versie 17.3:"), + messages[2]); + AssertMigrationLogMessageEqual( + new MigrationLogMessage("17.2", newVersion, "* Geen aanpassingen."), + messages[3]); + } + } + } + + private static void AssertTablesContentMigrated(MigratedDatabaseReader reader, string sourceFilePath) + { + var tables = new[] + { + "AssessmentSectionEntity", + "BackgroundDataEntity", + "BackgroundDataMetaEntity", + "CalculationGroupEntity", + "ClosingStructureEntity", + "ClosingStructuresCalculationEntity", + "ClosingStructuresFailureMechanismMetaEntity", + "ClosingStructuresOutputEntity", + "ClosingStructuresSectionResultEntity", + "DikeProfileEntity", + "DuneErosionFailureMechanismMetaEntity", + "DuneErosionSectionResultEntity", + "DuneLocationEntity", + "DuneLocationOutputEntity", + "FailureMechanismEntity", + "FailureMechanismSectionEntity", + "FaultTreeIllustrationPointEntity", + "FaultTreeIllustrationPointStochastEntity", + "FaultTreeSubmechanismIllustrationPointEntity", + "ForeshoreProfileEntity", + "GeneralResultFaultTreeIllustrationPointEntity", + "GeneralResultFaultTreeIllustrationPointStochastEntity", + "GeneralResultSubMechanismIllustrationPointEntity", + "GeneralResultSubMechanismIllustrationPointStochastEntity", + "GrassCoverErosionInwardsCalculationEntity", + "GrassCoverErosionInwardsDikeHeightOutputEntity", + "GrassCoverErosionInwardsFailureMechanismMetaEntity", + "GrassCoverErosionInwardsOutputEntity", + "GrassCoverErosionInwardsOvertoppingRateOutputEntity", + "GrassCoverErosionInwardsSectionResultEntity", + "GrassCoverErosionOutwardsFailureMechanismMetaEntity", + "GrassCoverErosionOutwardsHydraulicLocationEntity", + "GrassCoverErosionOutwardsHydraulicLocationOutputEntity", + "GrassCoverErosionOutwardsSectionResultEntity", + "GrassCoverErosionOutwardsWaveConditionsCalculationEntity", + "GrassCoverErosionOutwardsWaveConditionsOutputEntity", + "GrassCoverSlipOffInwardsSectionResultEntity", + "GrassCoverSlipOffOutwardsSectionResultEntity", + "HeightStructureEntity", + "HeightStructuresCalculationEntity", + "HeightStructuresFailureMechanismMetaEntity", + "HeightStructuresOutputEntity", + "HeightStructuresSectionResultEntity", + "HydraulicLocationEntity", + "HydraulicLocationOutputEntity", + "IllustrationPointResultEntity", + "MacroStabilityInwardsCalculationEntity", + "MacroStabilityInwardsCalculationOutputEntity", + "MacroStabilityInwardsCharacteristicPointEntity", + "MacroStabilityInwardsFailureMechanismMetaEntity", + "MacroStabilityInwardsPreconsolidationStressEntity", + "MacroStabilityInwardsSectionResultEntity", + "MacroStabilityInwardsSemiProbabilisticOutputEntity", + "MacroStabilityInwardsSoilLayerOneDEntity", + "MacroStabilityInwardsSoilLayerTwoDEntity", + "MacroStabilityInwardsSoilProfileOneDEntity", + "MacroStabilityInwardsSoilProfileTwoDEntity", + "MacroStabilityInwardsSoilProfileTwoDSoilLayerTwoDEntity", + "MacroStabilityInwardsStochasticSoilProfileEntity", + "MacrostabilityOutwardsSectionResultEntity", + "MicrostabilitySectionResultEntity", + "PipingCalculationEntity", + "PipingCalculationOutputEntity", + "PipingCharacteristicPointEntity", + "PipingFailureMechanismMetaEntity", + "PipingSectionResultEntity", + "PipingSemiProbabilisticOutputEntity", + "PipingSoilLayerEntity", + "PipingSoilProfileEntity", + "PipingStochasticSoilProfileEntity", + "PipingStructureSectionResultEntity", + "ProjectEntity", + "StabilityPointStructureEntity", + "StabilityPointStructuresCalculationEntity", + "StabilityPointStructuresFailureMechanismMetaEntity", + "StabilityPointStructuresOutputEntity", + "StabilityPointStructuresSectionResultEntity", + "StabilityStoneCoverFailureMechanismMetaEntity", + "StabilityStoneCoverSectionResultEntity", + "StabilityStoneCoverWaveConditionsCalculationEntity", + "StabilityStoneCoverWaveConditionsOutputEntity", + "StochastEntity", + "StochasticSoilModelEntity", + "StrengthStabilityLengthwiseConstructionSectionResultEntity", + "SubMechanismIllustrationPointEntity", + "SubMechanismIllustrationPointStochastEntity", + "SurfaceLineEntity", + "TechnicalInnovationSectionResultEntity", + "TopLevelFaultTreeIllustrationPointEntity", + "TopLevelSubMechanismIllustrationPointEntity", + "VersionEntity", + "WaterPressureAsphaltCoverSectionResultEntity", + "WaveImpactAsphaltCoverFailureMechanismMetaEntity", + "WaveImpactAsphaltCoverSectionResultEntity", + "WaveImpactAsphaltCoverWaveConditionsCalculationEntity", + "WaveImpactAsphaltCoverWaveConditionsOutputEntity" + }; + + foreach (string table in tables) + { + string validateMigratedTable = + $"ATTACH DATABASE \"{sourceFilePath}\" AS SOURCEPROJECT; " + + $"SELECT COUNT() = (SELECT COUNT() FROM [SOURCEPROJECT].{table}) " + + $"FROM {table};" + + "DETACH SOURCEPROJECT;"; + reader.AssertReturnedDataIsValid(validateMigratedTable); + } + } + + private static void AssertMigrationLogMessageEqual(MigrationLogMessage expected, MigrationLogMessage actual) + { + Assert.AreEqual(expected.ToVersion, actual.ToVersion); + Assert.AreEqual(expected.FromVersion, actual.FromVersion); + Assert.AreEqual(expected.Message, actual.Message); + } + + private static void AssertLogDatabase(string logFilePath) + { + using (var reader = new MigrationLogDatabaseReader(logFilePath)) + { + ReadOnlyCollection messages = reader.GetMigrationLogMessages(); + + Assert.AreEqual(2, messages.Count); + var i = 0; + AssertMigrationLogMessageEqual( + new MigrationLogMessage("17.2", newVersion, "Gevolgen van de migratie van versie 17.2 naar versie 17.3:"), + messages[i++]); + AssertMigrationLogMessageEqual( + new MigrationLogMessage("17.2", newVersion, "* Geen aanpassingen."), + messages[i]); + } + } + + private static void AssertVersions(MigratedDatabaseReader reader) + { + const string validateVersion = + "SELECT COUNT() = 1 " + + "FROM [VersionEntity] " + + "WHERE [Version] = \"17.3\";"; + reader.AssertReturnedDataIsValid(validateVersion); + } + + private static void AssertDatabase(MigratedDatabaseReader reader) + { + const string validateForeignKeys = + "PRAGMA foreign_keys;"; + reader.AssertReturnedDataIsValid(validateForeignKeys); + } + + /// + /// Database reader for migrated database. + /// + private class MigratedDatabaseReader : SqLiteDatabaseReaderBase + { + /// + /// Creates a new instance of . + /// + /// The path of the database file to open. + /// Thrown when: + /// + /// The contains invalid characters. + /// No file could be found at . + /// Unable to open database file. + /// + /// + public MigratedDatabaseReader(string databaseFilePath) : base(databaseFilePath) {} + + /// + /// Asserts that the results in one field with the value true. + /// + /// The query to execute. + /// The execution of + /// failed. + public void AssertReturnedDataIsValid(string queryString) + { + using (IDataReader dataReader = CreateDataReader(queryString)) + { + Assert.IsTrue(dataReader.Read(), "No data can be read from the data reader " + + $"when using query '{queryString}'."); + Assert.AreEqual(1, dataReader.FieldCount, $"Expected one field, was {dataReader.FieldCount} " + + $"fields when using query '{queryString}'."); + Assert.AreEqual(1, dataReader[0], $"Result should be 1 when using query '{queryString}'."); + } + } + } + } +}