// 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 Application.Ringtoets.Migration.Core; using Core.Common.IO.Readers; using Core.Common.TestUtil; using NUnit.Framework; namespace Application.Ringtoets.Storage.Test.IntegrationTests { public class MigrationTo172IntegrationTest { private const string newVersion = "17.2"; [Test] public void Given171Project_WhenUpgradedTo172_ThenProjectAsExpected() { // Given string sourceFilePath = TestHelper.GetTestDataPath(TestDataPath.Application.Ringtoets.Migration.Core, "FullTestProject171.rtd"); var fromVersionedFile = new RingtoetsVersionedFile(sourceFilePath); string targetFilePath = TestHelper.GetScratchPadPath(nameof(Given171Project_WhenUpgradedTo172_ThenProjectAsExpected)); string logFilePath = TestHelper.GetScratchPadPath(string.Concat(nameof(Given171Project_WhenUpgradedTo172_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); AssertGrassCoverErosionOutwardsFailureMechanism(reader); AssertStabilityStoneCoverFailureMechanism(reader); AssertWaveImpactAsphaltCoverFailureMechanism(reader); AssertHeightStructuresFailureMechanism(reader); AssertClosingStructuresFailureMechanism(reader); AssertClosingStructures(reader); AssertHeightStructures(reader); AssertStabilityPointStructures(reader); AssertForeshoreProfiles(reader); AssertVersions(reader); AssertDatabase(reader); } AssertLogDatabase(logFilePath); } } private static void AssertTablesContentMigrated(MigratedDatabaseReader reader, string sourceFilePath) { var tables = new[] { "AssessmentSectionEntity", "CalculationGroupEntity", "CharacteristicPointEntity", "ClosingStructureEntity", "ClosingStructuresCalculationEntity", "ClosingStructuresSectionResultEntity", "DikeProfileEntity", "DuneErosionSectionResultEntity", "FailureMechanismEntity", "FailureMechanismSectionEntity", "ForeshoreProfileEntity", "GrassCoverErosionInwardsCalculationEntity", "GrassCoverErosionInwardsFailureMechanismMetaEntity", "GrassCoverErosionInwardsSectionResultEntity", "GrassCoverErosionOutwardsFailureMechanismMetaEntity", "GrassCoverErosionOutwardsHydraulicLocationEntity", "GrassCoverErosionOutwardsSectionResultEntity", "GrassCoverErosionOutwardsWaveConditionsCalculationEntity", "GrassCoverSlipOffInwardsSectionResultEntity", "GrassCoverSlipOffOutwardsSectionResultEntity", "HeightStructureEntity", "HeightStructuresCalculationEntity", "HeightStructuresFailureMechanismMetaEntity", "HeightStructuresSectionResultEntity", "HydraulicLocationEntity", "MacroStabilityInwardsSectionResultEntity", "MacrostabilityOutwardsSectionResultEntity", "MicrostabilitySectionResultEntity", "PipingCalculationEntity", "PipingFailureMechanismMetaEntity", "PipingSectionResultEntity", "PipingStructureSectionResultEntity", "ProjectEntity", "SoilLayerEntity", "SoilProfileEntity", "StabilityPointStructureEntity", "StabilityPointStructuresCalculationEntity", "StabilityPointStructuresFailureMechanismMetaEntity", "StabilityPointStructuresSectionResultEntity", "StabilityStoneCoverSectionResultEntity", "StabilityStoneCoverWaveConditionsCalculationEntity", "StochasticSoilModelEntity", "StochasticSoilProfileEntity", "StrengthStabilityLengthwiseConstructionSectionResultEntity", "SurfaceLineEntity", "TechnicalInnovationSectionResultEntity", "VersionEntity", "WaterPressureAsphaltCoverSectionResultEntity", "WaveImpactAsphaltCoverSectionResultEntity", "WaveImpactAsphaltCoverWaveConditionsCalculationEntity" }; 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 AssertGrassCoverErosionOutwardsFailureMechanism(MigratedDatabaseReader reader) { const string validateForeshoreProfileCollectionSourcePath = "SELECT SUM([IsInvalid]) = 0 " + "FROM(" + "SELECT " + "CASE WHEN " + "COUNT([ForeshoreProfileEntityId]) AND [ForeshoreProfileCollectionSourcePath] IS NULL " + "OR " + "[ForeshoreProfileCollectionSourcePath] IS NOT NULL AND NOT COUNT([ForeshoreProfileEntityId]) " + "THEN 1 ELSE 0 END AS[IsInvalid] " + "FROM[GrassCoverErosionOutwardsFailureMechanismMetaEntity] " + "LEFT JOIN[ForeshoreProfileEntity] USING([FailureMechanismEntityId]) " + "GROUP BY[FailureMechanismEntityId]);"; reader.AssertReturnedDataIsValid(validateForeshoreProfileCollectionSourcePath); } private static void AssertStabilityStoneCoverFailureMechanism(MigratedDatabaseReader reader) { const string validateForeshoreProfileCollectionSourcePath = "SELECT SUM([IsInvalid]) = 0 " + "FROM(" + "SELECT " + "CASE WHEN " + "COUNT([ForeshoreProfileEntityId]) AND [ForeshoreProfileCollectionSourcePath] IS NULL " + "OR " + "[ForeshoreProfileCollectionSourcePath] IS NOT NULL AND NOT COUNT([ForeshoreProfileEntityId]) " + "THEN 1 ELSE 0 END AS[IsInvalid] " + "FROM[StabilityStoneCoverFailureMechanismMetaEntity] " + "LEFT JOIN[ForeshoreProfileEntity] USING([FailureMechanismEntityId]) " + "GROUP BY[FailureMechanismEntityId]);"; reader.AssertReturnedDataIsValid(validateForeshoreProfileCollectionSourcePath); } private static void AssertWaveImpactAsphaltCoverFailureMechanism(MigratedDatabaseReader reader) { const string validateForeshoreProfileCollectionSourcePath = "SELECT SUM([IsInvalid]) = 0 " + "FROM(" + "SELECT " + "CASE WHEN " + "COUNT([ForeshoreProfileEntityId]) AND [ForeshoreProfileCollectionSourcePath] IS NULL " + "OR " + "[ForeshoreProfileCollectionSourcePath] IS NOT NULL AND NOT COUNT([ForeshoreProfileEntityId]) " + "THEN 1 ELSE 0 END AS[IsInvalid] " + "FROM[WaveImpactAsphaltCoverFailureMechanismMetaEntity] " + "LEFT JOIN[ForeshoreProfileEntity] USING([FailureMechanismEntityId]) " + "GROUP BY[FailureMechanismEntityId]);"; reader.AssertReturnedDataIsValid(validateForeshoreProfileCollectionSourcePath); } private static void AssertHeightStructuresFailureMechanism(MigratedDatabaseReader reader) { const string validateStructuresCollectionSourcePath = "SELECT SUM([IsInvalid]) = 0 " + "FROM (SELECT " + "CASE WHEN " + "COUNT([HeightStructureEntityId]) AND [HeightStructureCollectionSourcePath] IS NULL " + "OR " + "[HeightStructureCollectionSourcePath] IS NOT NULL AND NOT COUNT([HeightStructureEntityId]) " + "THEN 1 ELSE 0 END AS [IsInvalid] " + "FROM [HeightStructuresFailureMechanismMetaEntity] " + "LEFT JOIN [HeightStructureEntity] USING ([FailureMechanismEntityId]) " + "GROUP BY [FailureMechanismEntityId]);"; reader.AssertReturnedDataIsValid(validateStructuresCollectionSourcePath); const string validateForeshoreProfileCollectionSourcePath = "SELECT SUM([IsInvalid]) = 0 " + "FROM(" + "SELECT " + "CASE WHEN " + "COUNT([ForeshoreProfileEntityId]) AND [ForeshoreProfileCollectionSourcePath] IS NULL " + "OR " + "[ForeshoreProfileCollectionSourcePath] IS NOT NULL AND NOT COUNT([ForeshoreProfileEntityId]) " + "THEN 1 ELSE 0 END AS[IsInvalid] " + "FROM[HeightStructuresFailureMechanismMetaEntity] " + "LEFT JOIN[ForeshoreProfileEntity] USING([FailureMechanismEntityId]) " + "GROUP BY[FailureMechanismEntityId]);"; reader.AssertReturnedDataIsValid(validateForeshoreProfileCollectionSourcePath); } private static void AssertClosingStructuresFailureMechanism(MigratedDatabaseReader reader) { const string validateStructuresCollectionSourcePath = "SELECT SUM([IsInvalid]) = 0 " + "FROM (SELECT " + "CASE WHEN " + "COUNT([ClosingStructureEntityId]) AND [ClosingStructureCollectionSourcePath] IS NULL " + "OR " + "[ClosingStructureCollectionSourcePath] IS NOT NULL AND NOT COUNT([ClosingStructureEntityId]) " + "THEN 1 ELSE 0 END AS [IsInvalid] " + "FROM [ClosingStructuresFailureMechanismMetaEntity] " + "LEFT JOIN [ClosingStructureEntity] USING ([FailureMechanismEntityId]) " + "GROUP BY [FailureMechanismEntityId]);"; reader.AssertReturnedDataIsValid(validateStructuresCollectionSourcePath); const string validateForeshoreProfileCollectionSourcePath = "SELECT SUM([IsInvalid]) = 0 " + "FROM(" + "SELECT " + "CASE WHEN " + "COUNT([ForeshoreProfileEntityId]) AND [ForeshoreProfileCollectionSourcePath] IS NULL " + "OR " + "[ForeshoreProfileCollectionSourcePath] IS NOT NULL AND NOT COUNT([ForeshoreProfileEntityId]) " + "THEN 1 ELSE 0 END AS[IsInvalid] " + "FROM[ClosingStructuresFailureMechanismMetaEntity] " + "LEFT JOIN[ForeshoreProfileEntity] USING([FailureMechanismEntityId]) " + "GROUP BY[FailureMechanismEntityId]);"; reader.AssertReturnedDataIsValid(validateForeshoreProfileCollectionSourcePath); } private static void AssertLogDatabase(string logFilePath) { using (var reader = new MigrationLogDatabaseReader(logFilePath)) { ReadOnlyCollection messages = reader.GetMigrationLogMessages(); Assert.AreEqual(17, messages.Count); AssertMigrationLogMessageEqual( new MigrationLogMessage("17.1", newVersion, "Gevolgen van de migratie van versie 17.1 naar versie 17.2:"), messages[0]); AssertMigrationLogMessageEqual( new MigrationLogMessage("17.1", newVersion, "* Traject: 'assessmentSection'"), messages[1]); AssertMigrationLogMessageEqual( new MigrationLogMessage("17.1", newVersion, " + Toetsspoor: 'Hoogte kunstwerk'"), messages[2]); AssertMigrationLogMessageEqual( new MigrationLogMessage("17.1", newVersion, " - Het ID van kunstwerk '10' is veranderd naar '104'."), messages[3]); AssertMigrationLogMessageEqual( new MigrationLogMessage("17.1", newVersion, " + Toetsspoor: 'Betrouwbaarheid sluiting kunstwerk'"), messages[4]); AssertMigrationLogMessageEqual( new MigrationLogMessage("17.1", newVersion, " - Het ID van kunstwerk '1' is veranderd naar '102'."), messages[5]); AssertMigrationLogMessageEqual( new MigrationLogMessage("17.1", newVersion, " + Toetsspoor: 'Golfklappen op asfaltbekleding'"), messages[6]); AssertMigrationLogMessageEqual( new MigrationLogMessage("17.1", newVersion, " - Het ID van voorlandprofiel '10' is veranderd naar '10004'."), messages[7]); AssertMigrationLogMessageEqual( new MigrationLogMessage("17.1", newVersion, " + Toetsspoor: 'Stabiliteit steenzetting'"), messages[8]); AssertMigrationLogMessageEqual( new MigrationLogMessage("17.1", newVersion, " - Het ID van voorlandprofiel '100' is veranderd naar '10006'."), messages[9]); AssertMigrationLogMessageEqual( new MigrationLogMessage("17.1", newVersion, " + Toetsspoor: 'Sterkte en stabiliteit puntconstructies'"), messages[10]); AssertMigrationLogMessageEqual( new MigrationLogMessage("17.1", newVersion, " - Het ID van kunstwerk '1' is veranderd naar '102'."), messages[11]); AssertMigrationLogMessageEqual( new MigrationLogMessage("17.1", newVersion, "* Traject: 'Demo traject'"), messages[12]); AssertMigrationLogMessageEqual( new MigrationLogMessage("17.1", newVersion, " + Toetsspoor: 'Betrouwbaarheid sluiting kunstwerk'"), messages[13]); AssertMigrationLogMessageEqual( new MigrationLogMessage("17.1", newVersion, " - Het ID van kunstwerk '10' is veranderd naar '104'."), messages[14]); AssertMigrationLogMessageEqual( new MigrationLogMessage("17.1", newVersion, " + Toetsspoor: 'Sterkte en stabiliteit puntconstructies'"), messages[15]); AssertMigrationLogMessageEqual( new MigrationLogMessage("17.1", newVersion, " - Het ID van kunstwerk '10' is veranderd naar '104'."), messages[16]); } } 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 AssertVersions(MigratedDatabaseReader reader) { const string validateVersion = "SELECT COUNT() = 1 " + "FROM VersionEntity " + "WHERE [Version] = \"17.2\";"; reader.AssertReturnedDataIsValid(validateVersion); } private static void AssertDatabase(MigratedDatabaseReader reader) { const string validateForeignKeys = "PRAGMA foreign_keys;"; reader.AssertReturnedDataIsValid(validateForeignKeys); } private static void AssertForeshoreProfiles(MigratedDatabaseReader reader) { const string validateForeshoreProfiles = "SELECT COUNT(DISTINCT([Id])) IS COUNT() " + "FROM ForeshoreProfileEntity " + "GROUP BY [FailureMechanismEntityId]"; reader.AssertReturnedDataIsValid(validateForeshoreProfiles); } private static void AssertHeightStructures(MigratedDatabaseReader reader) { const string validateHeightStructures = "SELECT COUNT(DISTINCT(Id)) = COUNT() " + "FROM HeightStructureEntity " + "GROUP BY [FailureMechanismEntityId]"; reader.AssertReturnedDataIsValid(validateHeightStructures); } private static void AssertClosingStructures(MigratedDatabaseReader reader) { const string validateClosingStructures = "SELECT COUNT(DISTINCT(Id)) = COUNT() " + "FROM ClosingStructureEntity " + "GROUP BY [FailureMechanismEntityId]"; reader.AssertReturnedDataIsValid(validateClosingStructures); } private static void AssertStabilityPointStructures(MigratedDatabaseReader reader) { const string validateStabilityPointStructures = "SELECT COUNT(DISTINCT(Id)) = COUNT() " + "FROM StabilityPointStructureEntity " + "GROUP BY [FailureMechanismEntityId]"; reader.AssertReturnedDataIsValid(validateStabilityPointStructures); } /// /// 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}'."); } } } } }