Esempio n. 1
0
        private async Task ModifyInternalAsync(ScriptModificationModel model)
        {
            var(errorsWhileLoading, oldDefaultConstraints, currentDefaultConstraints) = await GetDefaultConstraints(model.Paths);

            if (errorsWhileLoading)
            {
                return;
            }

            var defaultConstraintsToRemove = oldDefaultConstraints.Where(m => m.ConstraintName == null)
                                             .Except(currentDefaultConstraints)
                                             .ToDictionary(constraint => constraint, constraint => false);

            var(resultText, regexMatchTimeouts, failedReplacements) = ReplaceUnnamedDefaultConstraintStatements(model.CurrentScript, defaultConstraintsToRemove);
            if (regexMatchTimeouts > 0)
            {
                await _logger.LogWarningAsync($"{nameof(ReplaceUnnamedDefaultConstraintDropsModifier)}: Regular expression matching timed out {regexMatchTimeouts} time(s).");
            }
            if (failedReplacements > 0)
            {
                await _logger.LogWarningAsync($"{nameof(ReplaceUnnamedDefaultConstraintDropsModifier)}: Script defines {failedReplacements} unnamed default constraint(s) more to drop than the DACPAC models provide.");
            }

            model.CurrentScript = resultText;
        }
Esempio n. 2
0
        public async Task Modify_ReplaceSpecialKeyword_PreviousVersion_Async()
        {
            // Arrange
            IScriptModifier s       = new AddCustomHeaderModifier();
            const string    input   = "foobar";
            var             project = new SqlProject("a", "b", "c");

            project.ProjectProperties.DacVersion = new Version(1, 3, 0);
            var configuration = new ConfigurationModel
            {
                CustomHeader = "Script base version: {PREVIOUS_VERSION}"
            };
            var directories = new DirectoryPaths("projectDirectory", "latestArtifactsDirectory", "newArtifactsDirectory");
            var sourcePaths = new DeploySourcePaths("newDacpacPath", "publishProfilePath", "previousDacpacPath");
            var targetPaths = new DeployTargetPaths("deployScriptPath", "deployReportPath");
            var paths       = new PathCollection(directories, sourcePaths, targetPaths);
            var model       = new ScriptModificationModel(input, project, configuration, paths, new Version(1, 2, 0), false);

            // Act
            await s.ModifyAsync(model);

            // Assert
            Assert.IsNotNull(model.CurrentScript);
            Assert.AreEqual("Script base version: 1.2.0\r\nfoobar", model.CurrentScript);
        }
        Task IScriptModifier.ModifyAsync(ScriptModificationModel model)
        {
            if (model == null)
            {
                throw new ArgumentNullException(nameof(model));
            }

            return(RemoveSqlCmdStatementsInternal(model));
        }
        public async Task ModifyAsync_ErrorsGettingDacpacConstraints_Async()
        {
            // Arrange
            var daMock     = new Mock <IDacAccess>();
            var loggerMock = new Mock <ILogger>();

            daMock.Setup(m => m.GetDefaultConstraintsAsync("previousDacpacPath"))
            .ReturnsAsync(() => (new DefaultConstraint[0], new []
            {
                "oldError1",
                "oldError2"
            }));
            daMock.Setup(m => m.GetDefaultConstraintsAsync("newDacpacPath"))
            .ReturnsAsync(() => (new DefaultConstraint[0], new[]
            {
                "newError1",
                "newError2"
            }));
            var project = new SqlProject("a", "b", "c");
            var config  = new ConfigurationModel
            {
                ArtifactsPath = "foobar",
                ReplaceUnnamedDefaultConstraintDrops    = true,
                CommentOutUnnamedDefaultConstraintDrops = false,
                PublishProfilePath = "Test.publish.xml",
                VersionPattern     = "1.2.3.4",
                CreateDocumentationWithScriptCreation = true,
                CustomHeader = "awesome header",
                CustomFooter = "lame footer",
                BuildBeforeScriptCreation = true,
                TrackDacpacVersion        = false
            };
            var             directories = new DirectoryPaths("projectDirectory", "latestArtifactsDirectory", "newArtifactsDirectory");
            var             sourcePaths = new DeploySourcePaths("newDacpacPath", "publishProfilePath", "previousDacpacPath");
            var             targetPaths = new DeployTargetPaths("deployScriptPath", "deployReportPath");
            var             paths       = new PathCollection(directories, sourcePaths, targetPaths);
            IScriptModifier modifier    = new ReplaceUnnamedDefaultConstraintDropsModifier(daMock.Object, loggerMock.Object);
            var             model       = new ScriptModificationModel(MultipleDropDefaultConstraintStatements, project, config, paths, new Version(1, 0, 0), false);

            // Act
            await modifier.ModifyAsync(model);

            // Assert
            Assert.AreEqual(MultipleDropDefaultConstraintStatements, model.CurrentScript);
            loggerMock.Verify(m => m.LogErrorAsync("Failed to load the default constraints of the previous DACPAC:"), Times.Once);
            loggerMock.Verify(m => m.LogErrorAsync("oldError1"), Times.Once);
            loggerMock.Verify(m => m.LogErrorAsync("oldError2"), Times.Once);
            loggerMock.Verify(m => m.LogErrorAsync("Failed to load the default constraints of the current DACPAC:"), Times.Once);
            loggerMock.Verify(m => m.LogErrorAsync("newError1"), Times.Once);
            loggerMock.Verify(m => m.LogErrorAsync("newError2"), Times.Once);
        }
Esempio n. 5
0
        public void CurrentScript_Set_ArgumentNullException_WhenSetTotNull()
        {
            // Arrange
            var initialScript   = "script";
            var project         = new SqlProject("a", "b", "c");
            var configuration   = new ConfigurationModel();
            var directories     = new DirectoryPaths("projectDirectory", "latestArtifactsDirectory", "newArtifactsDirectory");
            var sourcePaths     = new DeploySourcePaths("newDacpacPath", "publishProfilePath", "previousDacpacPath");
            var targetPaths     = new DeployTargetPaths("deployScriptPath", "deployReportPath");
            var paths           = new PathCollection(directories, sourcePaths, targetPaths);
            var previousVersion = new Version(1, 2, 0);
            var model           = new ScriptModificationModel(initialScript, project, configuration, paths, previousVersion, true);

            // Act & Assert
            // ReSharper disable once AssignNullToNotNullAttribute
            Assert.Throws <ArgumentNullException>(() => model.CurrentScript = null);
        }
        public async Task ModifyAsync_CorrectReplacement_OneRegexTimeout_Async()
        {
            // Arrange
            var schemaName     = new string('a', 1_000_000) + '.';
            var input          = string.Format(MultipleDropDefaultConstraintStatementsWithPlaceholder, schemaName);
            var expectedOutput = string.Format(MultipleDropDefaultConstraintStatementsReplacedPartiallyWithPlaceholder, schemaName);
            var daMock         = new Mock <IDacAccess>();
            var loggerMock     = new Mock <ILogger>();

            daMock.Setup(m => m.GetDefaultConstraintsAsync("previousDacpacPath"))
            .ReturnsAsync(() => (new[]
            {
                new DefaultConstraint("dbo", "Author", "LastName", null),
                new DefaultConstraint("dbo", "Book", "Title", null),
                new DefaultConstraint("dbo", "Book", "RegisteredDate", "DF_RegisteredDate_Today")
            }, null));
            daMock.Setup(m => m.GetDefaultConstraintsAsync("newDacpacPath"))
            .ReturnsAsync(() => (new DefaultConstraint[0], null));
            var project = new SqlProject("a", "b", "c");
            var config  = new ConfigurationModel
            {
                ArtifactsPath = "foobar",
                ReplaceUnnamedDefaultConstraintDrops    = true,
                CommentOutUnnamedDefaultConstraintDrops = false,
                PublishProfilePath = "Test.publish.xml",
                VersionPattern     = "1.2.3.4",
                CreateDocumentationWithScriptCreation = true,
                CustomHeader = "awesome header",
                CustomFooter = "lame footer",
                BuildBeforeScriptCreation = true,
                TrackDacpacVersion        = false
            };
            var             directories = new DirectoryPaths("projectDirectory", "latestArtifactsDirectory", "newArtifactsDirectory");
            var             sourcePaths = new DeploySourcePaths("newDacpacPath", "publishProfilePath", "previousDacpacPath");
            var             targetPaths = new DeployTargetPaths("deployScriptPath", "deployReportPath");
            var             paths       = new PathCollection(directories, sourcePaths, targetPaths);
            IScriptModifier modifier    = new ReplaceUnnamedDefaultConstraintDropsModifier(daMock.Object, loggerMock.Object);
            var             model       = new ScriptModificationModel(input, project, config, paths, new Version(1, 0, 0), false);

            // Act
            await modifier.ModifyAsync(model);

            // Assert
            Assert.AreEqual(expectedOutput, model.CurrentScript);
            loggerMock.Verify(m => m.LogWarningAsync($"{nameof(ReplaceUnnamedDefaultConstraintDropsModifier)}: Regular expression matching timed out 1 time(s)."), Times.Once);
        }
Esempio n. 7
0
        public async Task Modify_CorrectModification_Async()
        {
            // Arrange
            IScriptModifier modifier      = new CommentOutUnnamedDefaultConstraintDropsModifier();
            var             project       = new SqlProject("", "", "");
            var             configuration = new ConfigurationModel();
            var             directories   = new DirectoryPaths("projectDirectory", "latestArtifactsDirectory", "newArtifactsDirectory");
            var             sourcePaths   = new DeploySourcePaths("newDacpacPath", "publishProfilePath", "previousDacpacPath");
            var             targetPaths   = new DeployTargetPaths("deployScriptPath", "deployReportPath");
            var             paths         = new PathCollection(directories, sourcePaths, targetPaths);
            var             model         = new ScriptModificationModel(MultipleDropDefaultConstraintStatements, project, configuration, paths, new Version(1, 0, 0), false);

            // Act
            await modifier.ModifyAsync(model);

            // Assert
            Assert.AreEqual(MultipleDropDefaultConstraintStatementsCommented, model.CurrentScript);
        }
        public void Modify_ArgumentException_ProjectPropertiesSqlTargetNameNull()
        {
            // Arrange
            IScriptModifier modifier      = new TrackDacpacVersionModifier();
            var             project       = new SqlProject("", "", "");
            var             configuration = new ConfigurationModel();
            var             directories   = new DirectoryPaths("projectDirectory", "latestArtifactsDirectory", "newArtifactsDirectory");
            var             sourcePaths   = new DeploySourcePaths("newDacpacPath", "publishProfilePath", "previousDacpacPath");
            var             targetPaths   = new DeployTargetPaths("deployScriptPath", "deployReportPath");
            var             paths         = new PathCollection(directories, sourcePaths, targetPaths);
            var             model         = new ScriptModificationModel(MultiLineInputWithFinalGo, project, configuration, paths, new Version(1, 0, 0), false);

            // Act
            var e = Assert.Throws <ArgumentException>(() => modifier.ModifyAsync(model));

            // Assert
            Assert.IsNotNull(e);
            Assert.IsTrue(e.Message.Contains(nameof(SqlProjectProperties.SqlTargetName)));
        }
        public async Task ModifyAsync_CorrectReplacement_Async()
        {
            // Arrange
            var daMock     = new Mock <IDacAccess>();
            var loggerMock = new Mock <ILogger>();

            daMock.Setup(m => m.GetDefaultConstraintsAsync("previousDacpacPath"))
            .ReturnsAsync(() => (new[]
            {
                new DefaultConstraint("dbo", "Author", "LastName", null),
                new DefaultConstraint("dbo", "Book", "Title", null),
                new DefaultConstraint("dbo", "Book", "RegisteredDate", "DF_RegisteredDate_Today")
            }, null));
            daMock.Setup(m => m.GetDefaultConstraintsAsync("newDacpacPath"))
            .ReturnsAsync(() => (new DefaultConstraint[0], null));
            var project = new SqlProject("a", "b", "c");
            var config  = new ConfigurationModel
            {
                ArtifactsPath = "foobar",
                ReplaceUnnamedDefaultConstraintDrops    = true,
                CommentOutUnnamedDefaultConstraintDrops = false,
                PublishProfilePath = "Test.publish.xml",
                VersionPattern     = "1.2.3.4",
                CreateDocumentationWithScriptCreation = true,
                CustomHeader = "awesome header",
                CustomFooter = "lame footer",
                BuildBeforeScriptCreation = true,
                TrackDacpacVersion        = false
            };
            var             directories = new DirectoryPaths("projectDirectory", "latestArtifactsDirectory", "newArtifactsDirectory");
            var             sourcePaths = new DeploySourcePaths("newDacpacPath", "publishProfilePath", "previousDacpacPath");
            var             targetPaths = new DeployTargetPaths("deployScriptPath", "deployReportPath");
            var             paths       = new PathCollection(directories, sourcePaths, targetPaths);
            IScriptModifier modifier    = new ReplaceUnnamedDefaultConstraintDropsModifier(daMock.Object, loggerMock.Object);
            var             model       = new ScriptModificationModel(MultipleDropDefaultConstraintStatements, project, config, paths, new Version(1, 0, 0), false);

            // Act
            await modifier.ModifyAsync(model);

            // Assert
            Assert.AreEqual(MultipleDropDefaultConstraintStatementsReplaced, model.CurrentScript);
        }
        private async Task <bool> ApplyAllModifiers(SqlProject project,
                                                    ConfigurationModel configuration,
                                                    PathCollection paths,
                                                    Version previousVersion,
                                                    bool createLatest,
                                                    IReadOnlyDictionary <ScriptModifier, IScriptModifier> modifiers)
        {
            string initialScript;

            try
            {
                initialScript = await _fileSystemAccess.ReadFileAsync(paths.DeployTargets.DeployScriptPath);
            }
            catch (Exception e)
            {
                await _logger.LogErrorAsync(e, "Failed to read the generated script");

                return(false);
            }

            var model = new ScriptModificationModel(initialScript, project, configuration, paths, previousVersion, createLatest);

            foreach (var m in modifiers.OrderBy(m => m.Key))
            {
                await _logger.LogInfoAsync($"Modifying script: {m.Key}");

                await m.Value.ModifyAsync(model);
            }

            try
            {
                await _fileSystemAccess.WriteFileAsync(paths.DeployTargets.DeployScriptPath, model.CurrentScript);
            }
            catch (Exception e)
            {
                await _logger.LogErrorAsync(e, "Failed to write the modified script");

                return(false);
            }
            return(true);
        }
        public async Task Modify_CorrectModification_MajorMinorVersion_Async(string input)
        {
            // Arrange
            IScriptModifier modifier = new TrackDacpacVersionModifier();
            var             project  = new SqlProject("", "", "");

            project.ProjectProperties.SqlTargetName = "Database.TestProject";
            project.ProjectProperties.DacVersion    = new Version(500, 30);
            var configuration = new ConfigurationModel();
            var directories   = new DirectoryPaths("projectDirectory", "latestArtifactsDirectory", "newArtifactsDirectory");
            var sourcePaths   = new DeploySourcePaths("newDacpacPath", "publishProfilePath", "previousDacpacPath");
            var targetPaths   = new DeployTargetPaths("deployScriptPath", "deployReportPath");
            var paths         = new PathCollection(directories, sourcePaths, targetPaths);
            var model         = new ScriptModificationModel(input, project, configuration, paths, new Version(1, 0, 0), false);

            // Act
            await modifier.ModifyAsync(model);

            // Assert
            Assert.AreEqual(FinalMultilineStatementMajorMinorVersion, model.CurrentScript);
        }
        Task IScriptModifier.ModifyAsync(ScriptModificationModel model)
        {
            if (model == null)
            {
                throw new ArgumentNullException(nameof(model));
            }

            model.CurrentScript = ForEachMatch(model.CurrentScript,
                                               "DROP CONSTRAINT ;",
                                               1,
                                               range =>
            {
                var lines    = range.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
                var newLines = lines.Select(m => string.IsNullOrWhiteSpace(m)
                                                                                        ? m
                                                                                        : $"-- {m}").ToArray();
                var replacement = string.Join(Environment.NewLine, newLines);
                return(replacement);
            });
            return(Task.CompletedTask);
        }
        public async Task ModifyAsync_CorrectModification_Async(string input)
        {
            // Arrange
            IScriptModifier modifier = new RemoveSqlCmdStatementsModifier();
            var             project  = new SqlProject("a", "b", "c");

            project.ProjectProperties.DacVersion = new Version(1, 3, 0);
            var configuration = new ConfigurationModel
            {
                CustomFooter = "footer"
            };
            var directories = new DirectoryPaths("projectDirectory", "latestArtifactsDirectory", "newArtifactsDirectory");
            var sourcePaths = new DeploySourcePaths("newDacpacPath", "publishProfilePath", "previousDacpacPath");
            var targetPaths = new DeployTargetPaths("deployScriptPath", "deployReportPath");
            var paths       = new PathCollection(directories, sourcePaths, targetPaths);
            var model       = new ScriptModificationModel(input, project, configuration, paths, new Version(1, 2, 0), false);

            // Act
            await modifier.ModifyAsync(model);

            // Assert
            Assert.AreEqual(MultiLineInputWithoutSqlcmdStatements, model.CurrentScript);
        }
Esempio n. 14
0
        public void Constructor_CorrectInitialization()
        {
            // Arrange
            var initialScript   = "script";
            var project         = new SqlProject("a", "b", "c");
            var configuration   = new ConfigurationModel();
            var directories     = new DirectoryPaths("projectDirectory", "latestArtifactsDirectory", "newArtifactsDirectory");
            var sourcePaths     = new DeploySourcePaths("newDacpacPath", "publishProfilePath", "previousDacpacPath");
            var targetPaths     = new DeployTargetPaths("deployScriptPath", "deployReportPath");
            var paths           = new PathCollection(directories, sourcePaths, targetPaths);
            var previousVersion = new Version(1, 2, 0);

            // Act
            var model = new ScriptModificationModel(initialScript, project, configuration, paths, previousVersion, true);

            // Assert
            Assert.AreEqual(initialScript, model.CurrentScript);
            Assert.AreSame(project, model.Project);
            Assert.AreSame(configuration, model.Configuration);
            Assert.AreSame(paths, model.Paths);
            Assert.AreSame(previousVersion, model.PreviousVersion);
            Assert.IsTrue(model.CreateLatest);
        }
        Task IScriptModifier.ModifyAsync(ScriptModificationModel model)
        {
            if (model == null)
            {
                throw new ArgumentNullException(nameof(model));
            }

            if (string.IsNullOrWhiteSpace(model.Configuration.CustomHeader))
            {
                return(Task.CompletedTask);
            }

            var header = model.Configuration.CustomHeader;

            header = header.Replace(Constants.ScriptModificationSpecialKeywordPreviousVersion, model.PreviousVersion.ToString());
            header = header.Replace(Constants.ScriptModificationSpecialKeywordNextVersion, model.CreateLatest ? "latest" : model.Project.ProjectProperties.DacVersion.ToString());
            var sb = new StringBuilder(header);

            sb.AppendLine();
            sb.Append(model.CurrentScript);
            model.CurrentScript = sb.ToString();
            return(Task.CompletedTask);
        }
Esempio n. 16
0
        public async Task Modify_NoLeadingNewLineWhenNullOrWhiteSpace_Async(string customHeader)
        {
            // Arrange
            IScriptModifier s             = new AddCustomHeaderModifier();
            const string    input         = "foobar";
            var             project       = new SqlProject("a", "b", "c");
            var             configuration = new ConfigurationModel
            {
                CustomHeader = customHeader
            };
            var directories = new DirectoryPaths("projectDirectory", "latestArtifactsDirectory", "newArtifactsDirectory");
            var sourcePaths = new DeploySourcePaths("newDacpacPath", "publishProfilePath", "previousDacpacPath");
            var targetPaths = new DeployTargetPaths("deployScriptPath", "deployReportPath");
            var paths       = new PathCollection(directories, sourcePaths, targetPaths);
            var model       = new ScriptModificationModel(input, project, configuration, paths, new Version(1, 0, 0), false);

            // Act
            await s.ModifyAsync(model);

            // Assert
            Assert.IsNotNull(model.CurrentScript);
            Assert.AreEqual("foobar", model.CurrentScript);
        }
Esempio n. 17
0
        Task IScriptModifier.ModifyAsync(ScriptModificationModel model)
        {
            if (model == null)
            {
                throw new ArgumentNullException(nameof(model));
            }
            if (model.Project.ProjectProperties.SqlTargetName == null)
            {
                throw new ArgumentException($"{nameof(ScriptModificationModel.Project)}.{nameof(SqlProject.ProjectProperties)}.{nameof(SqlProjectProperties.SqlTargetName)} must be set.", nameof(model));
            }
            if (model.Project.ProjectProperties.DacVersion == null)
            {
                throw new ArgumentException($"{nameof(ScriptModificationModel.Project)}.{nameof(SqlProject.ProjectProperties)}.{nameof(SqlProjectProperties.DacVersion)} must be set.", nameof(model));
            }

            // Prepare format string
            var(createAndInsertStatement, updateStatement) = GetFinalStatementsFromTemplate(model.CurrentScript, model.Project);

            var createAndInsertStatementSet          = false;
            var modifiedWithInsertAndCreateStatement = ForEachMatch(model.CurrentScript,
                                                                    "USE [$(DatabaseName)];",
                                                                    0,
                                                                    s =>
            {
                if (createAndInsertStatementSet)
                {
                    return(s);
                }
                createAndInsertStatementSet = true;
                return(s + createAndInsertStatement);
            });

            model.CurrentScript = modifiedWithInsertAndCreateStatement + updateStatement;

            return(Task.CompletedTask);
        }
 private static Task RemoveSqlCmdStatementsInternal(ScriptModificationModel model)
 {
     model.CurrentScript = ForEachMatch(model.CurrentScript,
                                        "USE [$(DatabaseName)];",
                                        0,
                                        s => string.Empty);
     model.CurrentScript = ForEachMatch(model.CurrentScript,
                                        "IF N'$(__IsSqlCmdEnabled)' NOT LIKE N'True'",
                                        0,
                                        s => string.Empty);
     model.CurrentScript = ForEachMatch(model.CurrentScript,
                                        @":setvar __IsSqlCmdEnabled ""True""",
                                        0,
                                        s => string.Empty);
     model.CurrentScript = ForEachMatch(model.CurrentScript,
                                        ":on error exit",
                                        0,
                                        s => string.Empty);
     model.CurrentScript = ForEachMatch(model.CurrentScript,
                                        ":setvar DatabaseName",
                                        0,
                                        s => string.Empty);
     return(Task.CompletedTask);
 }