public async Task TryLoadSqlProjectPropertiesAsync_UseNameIfSqlTargetNameIsEmpty_Async()
        {
            // Arrange
            const string xml =
                @"<?xml version=""1.0"" encoding=""utf-8""?>
<Project>
  <PropertyGroup>
    <Name>TestProject</Name>
    <OutputPath>bin\Output</OutputPath>
    <DacVersion>2.2.3</DacVersion>
    <SqlTargetName></SqlTargetName>
  </PropertyGroup>
</Project>";
            var project = new SqlProject("a", @"C:\TestProject\TestProject.sqlproj", "c");
            var vsMock  = Mock.Of <IVersionService>();
            var fsaMock = new Mock <IFileSystemAccess>();

            fsaMock.Setup(m => m.ReadFileAsync(project.FullName))
            .ReturnsAsync(xml);
            var loggerMock             = new Mock <ILogger>();
            ISqlProjectService service = new SqlProjectService(vsMock, fsaMock.Object, loggerMock.Object);

            // Act
            var loadedSuccessfully = await service.TryLoadSqlProjectPropertiesAsync(project);

            // Assert
            Assert.IsTrue(loadedSuccessfully);
            loggerMock.Verify(m => m.LogErrorAsync(It.IsAny <string>()), Times.Never);
            loggerMock.Verify(m => m.LogErrorAsync(It.IsAny <Exception>(), It.IsAny <string>()), Times.Never);
            Assert.AreEqual("TestProject", project.ProjectProperties.SqlTargetName);
            Assert.AreEqual(@"C:\TestProject\bin\Output", project.ProjectProperties.BinaryDirectory);
            Assert.AreEqual(new Version(2, 2, 3), project.ProjectProperties.DacVersion);
        }
        public void GetExistingArtifactVersions_ShowError_ExceptionDuringFileSystemAccess()
        {
            // Arrange
            var project = new SqlProject("a", @"C:\TestProject\TestProject.sqlproj", "c");
            var config  = new ConfigurationModel
            {
                ArtifactsPath      = "_Deployment",
                PublishProfilePath = "TestProfile.publish.xml",
                ReplaceUnnamedDefaultConstraintDrops = false,
                VersionPattern = "1.2.3.4",
                CommentOutUnnamedDefaultConstraintDrops = true,
                CreateDocumentationWithScriptCreation   = false,
                CustomHeader = "TestHeader",
                CustomFooter = "TestFooter",
                BuildBeforeScriptCreation = true,
                TrackDacpacVersion        = true
            };
            var vsaMock = new Mock <IVisualStudioAccess>();
            var fsaMock = new Mock <IFileSystemAccess>();

            fsaMock.Setup(m => m.GetDirectoriesIn(@"C:\TestProject\_Deployment"))
            .Throws(new InvalidOperationException("test exception"));
            IArtifactsService service = new ArtifactsService(vsaMock.Object, fsaMock.Object);

            // Act
            var result = service.GetExistingArtifactVersions(project, config);

            // Assert
            Assert.IsNotNull(result);
            Assert.AreEqual(0, result.Length);
            vsaMock.Verify(m => m.ShowModalError("ERROR: Failed to open script creation window: test exception"), Times.Once);
        }
        public void GetExistingArtifactVersions_ShowError_InvalidArtifactsPathConfiguration()
        {
            // Arrange
            var project = new SqlProject("a", @"C:\TestProject\TestProject.sqlproj", "c");
            var config  = new ConfigurationModel
            {
                ArtifactsPath      = "",
                PublishProfilePath = "TestProfile.publish.xml",
                ReplaceUnnamedDefaultConstraintDrops = false,
                VersionPattern = "1.2.3.4",
                CommentOutUnnamedDefaultConstraintDrops = true,
                CreateDocumentationWithScriptCreation   = false,
                CustomHeader = "TestHeader",
                CustomFooter = "TestFooter",
                BuildBeforeScriptCreation = true,
                TrackDacpacVersion        = true
            };
            var vsaMock = new Mock <IVisualStudioAccess>();
            var fsaMock = new Mock <IFileSystemAccess>();
            IArtifactsService service = new ArtifactsService(vsaMock.Object, fsaMock.Object);

            // Act
            var result = service.GetExistingArtifactVersions(project, config);

            // Assert
            Assert.IsNotNull(result);
            Assert.AreEqual(0, result.Length);
            vsaMock.Verify(m => m.ShowModalError("ERROR: The configured artifacts path is not valid. Please ensure that the configuration is correct."), Times.Once);
        }
        public async Task Work_ScriptCreationStateModel_CompleteRun_Async()
        {
            // Arrange
            var fsaMock    = new Mock <IFileSystemAccess>();
            var loggerMock = new Mock <ILogger>();
            IWorkUnit <ScriptCreationStateModel> unit = new CleanNewArtifactsDirectoryUnit(fsaMock.Object, loggerMock.Object);
            var project         = new SqlProject("a", "b", "c");
            var configuration   = ConfigurationModel.GetDefault();
            var previousVersion = new Version(1, 0);

            Task HandlerFunc(bool b) => Task.CompletedTask;

            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 ScriptCreationStateModel(project, configuration, previousVersion, true, HandlerFunc)
            {
                Paths = paths
            };

            // Act
            await unit.Work(model, CancellationToken.None);

            // Assert
            Assert.AreEqual(StateModelState.TriedToCleanArtifactsDirectory, model.CurrentState);
            Assert.IsNull(model.Result);
            fsaMock.Verify(m => m.TryToCleanDirectory("newArtifactsDirectory"), Times.Once);
            loggerMock.Verify(m => m.LogInfoAsync(It.IsNotNull <string>()), Times.Once);
        }
        public async Task Work_ScriptCreationStateModel_ValidVersion_Latest_Async()
        {
            // Arrange
            var project         = new SqlProject("a", "b", "c");
            var configuration   = ConfigurationModel.GetDefault();
            var previousVersion = new Version(1, 2, 3);

            Task HandleWorkInProgressChanged(bool arg) => Task.CompletedTask;

            var model = new ScriptCreationStateModel(project, configuration, previousVersion, true, HandleWorkInProgressChanged)
            {
                FormattedTargetVersion = null
            };
            var vsaMock    = new Mock <IVisualStudioAccess>();
            var loggerMock = new Mock <ILogger>();
            IWorkUnit <ScriptCreationStateModel> unit = new ValidateTargetVersionUnit(vsaMock.Object, loggerMock.Object);

            // Act
            await unit.Work(model, CancellationToken.None);

            // Assert
            Assert.AreEqual(StateModelState.FormattedTargetVersionValidated, model.CurrentState);
            Assert.IsNull(model.Result);
            vsaMock.Verify(m => m.ShowModalError(It.IsAny <string>()), Times.Never);
            loggerMock.Verify(m => m.LogErrorAsync(It.IsAny <string>()), Times.Never);
        }
        public async Task SaveConfiguration_SavedWithChangeNotification_Async()
        {
            // Arrange
            var fsaMock = new Mock <IFileSystemAccess>();

            fsaMock.Setup(m => m.WriteFileAsync(It.IsNotNull <string>(), It.IsNotNull <string>()))
            .Returns(Task.CompletedTask);
            var                   vsaMock = new Mock <IVisualStudioAccess>();
            SqlProject            configurationChangedProject = null;
            var                   loggerMock = Mock.Of <ILogger>();
            IConfigurationService service    = new ConfigurationService(fsaMock.Object, vsaMock.Object, loggerMock);

            service.ConfigurationChanged += (sender,
                                             args) => configurationChangedProject = args.Project;
            var project = new SqlProject("", "C:\\Temp\\Test\\Test.sqlproj", "");
            var model   = ConfigurationModel.GetDefault();

            // Act
            var result = await service.SaveConfigurationAsync(project, model);

            // Assert
            Assert.IsTrue(result);
            fsaMock.Verify(m => m.WriteFileAsync("C:\\Temp\\Test\\Properties\\ssdtlifecycle.json", It.IsNotNull <string>()), Times.Once);
            Assert.AreSame(project, configurationChangedProject);
            vsaMock.Verify(m => m.AddItemToProjectProperties(project, "C:\\Temp\\Test\\Properties\\ssdtlifecycle.json"), Times.Once);
        }
        public async Task ScaffoldAsync_InvalidOperationException_CallCreateWhileRunning_Async()
        {
            // Arrange
            var wufMock    = Mock.Of <IWorkUnitFactory>();
            var vsaMock    = Mock.Of <IVisualStudioAccess>();
            var loggerMock = Mock.Of <ILogger>();
            IScaffoldingService service = new ScaffoldingService(wufMock, vsaMock, loggerMock);
            var       project           = new SqlProject("a", "b", "c");
            var       configuration     = ConfigurationModel.GetDefault();
            var       targetVersion     = new Version(1, 0);
            var       invokedSecondTime = false;
            Exception thrownException   = null;

            service.IsScaffoldingChanged += (sender,
                                             args) =>
            {
                if (!service.IsScaffolding)
                {
                    return;
                }
                invokedSecondTime = true;
                thrownException   = Assert.Throws <InvalidOperationException>(() => service.ScaffoldAsync(project, configuration, targetVersion, CancellationToken.None));
            };

            // Act
            await service.ScaffoldAsync(project, configuration, targetVersion, CancellationToken.None);

            // Assert
            Assert.IsTrue(invokedSecondTime);
            Assert.IsNotNull(thrownException);
            Assert.IsInstanceOf <InvalidOperationException>(thrownException);
        }
Beispiel #8
0
        public async Task Work_ScaffoldingStateModel_LoadedSuccessful_Async()
        {
            // Arrange
            var project       = new SqlProject("a", "b", "c");
            var configuration = ConfigurationModel.GetDefault();
            var targetVersion = new Version(1, 2, 3);

            Task HandleWorkInProgressChanged(bool arg) => Task.CompletedTask;

            var model       = new ScaffoldingStateModel(project, configuration, targetVersion, HandleWorkInProgressChanged);
            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 spsMock     = new Mock <ISqlProjectService>();

            spsMock.Setup(m => m.TryLoadPathsForScaffoldingAsync(project, configuration)).ReturnsAsync(paths);
            IWorkUnit <ScaffoldingStateModel> unit = new LoadPathsUnit(spsMock.Object);

            // Act
            await unit.Work(model, CancellationToken.None);

            // Assert
            Assert.AreEqual(StateModelState.PathsLoaded, model.CurrentState);
            Assert.IsNull(model.Result);
        }
        private bool TryGetArtifactsBaseDirectory(SqlProject project,
                                                  ConfigurationModel configuration,
                                                  out string artifactsBaseDirectory)
        {
            var projectPath      = project.FullName;
            var projectDirectory = Path.GetDirectoryName(projectPath);

            if (projectDirectory == null)
            {
                _visualStudioAccess.ShowModalError("ERROR: Cannot determine project directory.");
                artifactsBaseDirectory = null;
                return(false);
            }

            var artifactPathErrors = ConfigurationModelValidations.ValidateArtifactsPath(configuration);

            if (artifactPathErrors.Any())
            {
                _visualStudioAccess.ShowModalError("ERROR: The configured artifacts path is not valid. Please ensure that the configuration is correct.");
                artifactsBaseDirectory = null;
                return(false);
            }

            artifactsBaseDirectory = Path.Combine(projectDirectory, configuration.ArtifactsPath);
            return(true);
        }
Beispiel #10
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);
        }
Beispiel #11
0
 public void Modify(SqlProject project)
 {
     foreach (var modifier in _modifiers)
     {
         modifier.Modify(project);
     }
 }
        void IVisualStudioAccess.RemoveItemFromProjectRoot(SqlProject project,
                                                           string item)
        {
            if (project == null)
            {
                throw new ArgumentNullException(nameof(project));
            }
            if (item == null)
            {
                throw new ArgumentNullException(nameof(item));
            }

            ThreadHelper.ThrowIfNotOnUIThread();
            var p = _dte2.Solution.Projects.OfType <Project>().SingleOrDefault(m =>
            {
                ThreadHelper.ThrowIfNotOnUIThread();
                return(m.UniqueName == project.UniqueName);
            });

            var matchingItem = p?.ProjectItems.OfType <ProjectItem>().SingleOrDefault(m =>
            {
                ThreadHelper.ThrowIfNotOnUIThread();
                return(m.Name == item);
            });

            matchingItem?.Remove();
        }
        public async Task TryLoadSqlProjectPropertiesAsync_Error_NoXmlRoot_Async()
        {
            // Arrange
            const string xml     = @"<?xml version=""1.0"" encoding=""utf-8""?>";
            var          project = new SqlProject("a", @"C:\TestProject.sqlproj", "c");
            var          vsMock  = Mock.Of <IVersionService>();
            var          fsaMock = new Mock <IFileSystemAccess>();

            fsaMock.Setup(m => m.ReadFileAsync(project.FullName))
            .ReturnsAsync(xml);
            var loggedErrorMessages = new List <(Exception Exception, string Message)>();
            var loggerMock          = new Mock <ILogger>();

            loggerMock.Setup(m => m.LogErrorAsync(It.IsAny <Exception>(), It.IsAny <string>()))
            .Callback((Exception e, string message) => loggedErrorMessages.Add((e, message)))
            .Returns(Task.CompletedTask);
            ISqlProjectService service = new SqlProjectService(vsMock, fsaMock.Object, loggerMock.Object);

            // Act
            var loadedSuccessfully = await service.TryLoadSqlProjectPropertiesAsync(project);

            // Assert
            Assert.IsFalse(loadedSuccessfully);
            Assert.AreEqual(1, loggedErrorMessages.Count);
            Assert.IsNotNull(loggedErrorMessages[0]);
            Assert.IsNotNull(loggedErrorMessages[0].Exception);
            Assert.IsTrue(loggedErrorMessages[0].Message.StartsWith(@"Cannot read contents of ""C:\TestProject.sqlproj"""));
        }
        public async Task TryLoadSqlProjectPropertiesAsync_IssueWarningIfNameNodeIsDifferentFromProjectName_Async()
        {
            // Arrange
            const string xml =
                @"<?xml version=""1.0"" encoding=""utf-8""?>
<Project>
  <PropertyGroup>
    <Name>TestProject</Name>
    <OutputPath>bin\Output</OutputPath>
    <DacVersion>2.2.3</DacVersion>
  </PropertyGroup>
</Project>";
            var project = new SqlProject("awesomeproject", @"C:\TestProject\TestProject.sqlproj", "c");
            var vsMock  = Mock.Of <IVersionService>();
            var fsaMock = new Mock <IFileSystemAccess>();

            fsaMock.Setup(m => m.ReadFileAsync(project.FullName))
            .ReturnsAsync(xml);
            var loggerMock             = new Mock <ILogger>();
            ISqlProjectService service = new SqlProjectService(vsMock, fsaMock.Object, loggerMock.Object);

            // Act
            var loadedSuccessfully = await service.TryLoadSqlProjectPropertiesAsync(project);

            // Assert
            Assert.IsTrue(loadedSuccessfully);
            loggerMock.Verify(m => m.LogErrorAsync(It.IsAny <string>()), Times.Never);
            loggerMock.Verify(m => m.LogErrorAsync(It.IsAny <Exception>(), It.IsAny <string>()), Times.Never);
            Assert.AreEqual("TestProject", project.ProjectProperties.SqlTargetName);
            Assert.AreEqual(@"C:\TestProject\bin\Output", project.ProjectProperties.BinaryDirectory);
            Assert.AreEqual(new Version(2, 2, 3), project.ProjectProperties.DacVersion);
            loggerMock.Verify(m => m.LogWarningAsync("XML node 'Name' doesn't match the actual project name. This could cause an unexpected behavior."), Times.Once);
            loggerMock.Verify(m => m.LogDebugAsync("Value of 'Name' node: TestProject"), Times.Once);
            loggerMock.Verify(m => m.LogDebugAsync("Actual project name: awesomeproject"), Times.Once);
        }
        public async Task GetConfigurationOrDefaultAsync_SqlProject_ErrorWhileReading_UseDefault_Async()
        {
            // Arrange
            var exception = new FileNotFoundException("foo");
            var fsaMock   = new Mock <IFileSystemAccess>();

            fsaMock.Setup(m => m.CheckIfFileExists("C:\\Temp\\Test\\Properties\\ssdtlifecycle.json"))
            .Returns(true);
            fsaMock.Setup(m => m.ReadFileAsync("C:\\Temp\\Test\\Properties\\ssdtlifecycle.json"))
            .Throws(exception);
            var vsaMock    = new Mock <IVisualStudioAccess>();
            var loggerMock = new Mock <ILogger>();
            IConfigurationService service = new ConfigurationService(fsaMock.Object, vsaMock.Object, loggerMock.Object);
            var project = new SqlProject("", "C:\\Temp\\Test\\Test.sqlproj", "");
            var defaultConfiguration = ConfigurationModel.GetDefault();

            // Act
            var configuration = await service.GetConfigurationOrDefaultAsync(project);

            // Assert
            Assert.IsNotNull(configuration);
            vsaMock.Verify(m => m.ShowModalError(It.Is <string>(s => s.Contains("Accessing the configuration file failed."))), Times.Once);
            loggerMock.Verify(m => m.LogErrorAsync(exception, It.Is <string>(s => s.Contains("Failed to read the configuration from file"))), Times.Once);
            Assert.IsTrue(defaultConfiguration.Equals(configuration));
        }
        public async Task Work_ScriptCreationStateModel_NoRepositoryConfigured_Async()
        {
            // Arrange
            var project         = new SqlProject("a", "b", "c");
            var configuration   = ConfigurationModel.GetDefault();
            var previousVersion = new Version(1, 2, 3);

            Task HandleWorkInProgressChanged(bool arg) => Task.CompletedTask;

            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 ScriptCreationStateModel(project, configuration, previousVersion, true, HandleWorkInProgressChanged)
            {
                Paths = paths
            };
            var fsaMock    = new Mock <IFileSystemAccess>();
            var loggerMock = new Mock <ILogger>();
            IWorkUnit <ScriptCreationStateModel> unit = new CopyDacpacToSharedDacpacRepositoryUnit(fsaMock.Object, loggerMock.Object);

            // Act
            await unit.Work(model, CancellationToken.None);

            // Assert
            Assert.AreEqual(StateModelState.TriedToCopyDacpacToSharedDacpacRepository, model.CurrentState);
            Assert.IsNull(model.Result);
            fsaMock.Verify(m => m.EnsureDirectoryExists(It.IsAny <string>()), Times.Never);
            fsaMock.Verify(m => m.CopyFile(It.IsAny <string>(), It.IsAny <string>()), Times.Never);
            loggerMock.Verify(m => m.LogErrorAsync(It.IsAny <string>()), Times.Never);
            loggerMock.Verify(m => m.LogErrorAsync(It.IsAny <Exception>(), It.IsAny <string>()), Times.Never);
        }
        public async Task SaveConfiguration_FileSystemAccessError_Async()
        {
            // Arrange
            var exception = new IOException("foo");
            var fsaMock   = new Mock <IFileSystemAccess>();

            fsaMock.Setup(m => m.WriteFileAsync(It.IsNotNull <string>(), It.IsNotNull <string>()))
            .Throws(exception);
            var                   vsaMock = new Mock <IVisualStudioAccess>();
            SqlProject            configurationChangedProject = null;
            var                   loggerMock = new Mock <ILogger>();
            IConfigurationService service    = new ConfigurationService(fsaMock.Object, vsaMock.Object, loggerMock.Object);

            service.ConfigurationChanged += (sender,
                                             args) => configurationChangedProject = args.Project;
            var project = new SqlProject("", "C:\\Temp\\Test\\Test.sqlproj", "");
            var model   = ConfigurationModel.GetDefault();

            // Act
            var result = await service.SaveConfigurationAsync(project, model);

            // Assert
            Assert.IsFalse(result);
            fsaMock.Verify(m => m.WriteFileAsync("C:\\Temp\\Test\\Properties\\ssdtlifecycle.json", It.IsNotNull <string>()), Times.Once);
            Assert.IsNull(configurationChangedProject);
            vsaMock.Verify(m => m.AddItemToProjectProperties(It.IsAny <SqlProject>(), It.IsAny <string>()), Times.Never);
            loggerMock.Verify(m => m.LogErrorAsync(exception, "Failed to save the configuration"), Times.Once);
            vsaMock.Verify(m => m.ShowModalError("Failed to save the configuration. Please check the SSDT Lifecycle output window for details."), Times.Once);
        }
        public async Task Work_ScaffoldingStateModel_InvalidCharsInNewDacpacPath_Async()
        {
            // Arrange
            var project       = new SqlProject("a", "b", "c");
            var configuration = ConfigurationModel.GetDefault();

            configuration.SharedDacpacRepositoryPath = "C:\\Temp\\Test\\";
            var targetVersion = new Version(1, 2, 3);

            Task HandleWorkInProgressChanged(bool arg) => Task.CompletedTask;

            var directories = new DirectoryPaths("projectDirectory", "latestArtifactsDirectory", "newArtifactsDirectory");
            var sourcePaths = new DeploySourcePaths("newDacpacPath" + new string(Path.GetInvalidPathChars()), "publishProfilePath", "previousDacpacPath");
            var targetPaths = new DeployTargetPaths("deployScriptPath", "deployReportPath");
            var paths       = new PathCollection(directories, sourcePaths, targetPaths);
            var model       = new ScaffoldingStateModel(project, configuration, targetVersion, HandleWorkInProgressChanged)
            {
                Paths = paths
            };
            var fsaMock    = new Mock <IFileSystemAccess>();
            var loggerMock = new Mock <ILogger>();
            IWorkUnit <ScaffoldingStateModel> unit = new CopyDacpacToSharedDacpacRepositoryUnit(fsaMock.Object, loggerMock.Object);

            // Act
            await unit.Work(model, CancellationToken.None);

            // Assert
            Assert.AreEqual(StateModelState.TriedToCopyDacpacToSharedDacpacRepository, model.CurrentState);
            Assert.IsFalse(model.Result);
            fsaMock.Verify(m => m.EnsureDirectoryExists(It.IsAny <string>()), Times.Never);
            fsaMock.Verify(m => m.CopyFile(It.IsAny <string>(), It.IsAny <string>()), Times.Never);
            loggerMock.Verify(m => m.LogInfoAsync("Copying DACPAC to shared DACPAC repository ..."), Times.Once);
            loggerMock.Verify(m => m.LogErrorAsync(It.Is <string>(s => s.StartsWith("Failed to copy DACPAC to shared DACPAC repository: "))), Times.Once);
        }
Beispiel #19
0
        public void Modify(SqlProject project)
        {
            foreach (var batch in project.Objects.Batches.ToList())
            {
                foreach (var statement in batch.Statements.OfType <CreateTableStatement>())
                {
                    var constrains = statement.Definition.TableConstraints;

                    if (constrains.Count == 0)
                    {
                        continue;
                    }

                    var alterTable =
                        new AlterTableAddTableElementStatement
                    {
                        SchemaObjectName = statement.SchemaObjectName,
                        Definition       = new TableDefinition()
                    };

                    foreach (var constraint in constrains)
                    {
                        alterTable.Definition.TableConstraints.Add(constraint);
                    }

                    project.Objects.Batches.Add(new TSqlBatch
                    {
                        Statements = { alterTable }
                    });

                    statement.Definition.TableConstraints.Clear();
                }
            }
        }
        private async Task TryToDeleteRefactorLogInternal(IStateModel stateModel,
                                                          SqlProject project,
                                                          ConfigurationModel configuration,
                                                          PathCollection paths)
        {
            if (!configuration.DeleteRefactorlogAfterVersionedScriptGeneration)
            {
                stateModel.CurrentState = StateModelState.DeletedRefactorLog;
                return;
            }

            await _logger.LogInfoAsync("Deleting refactorlog files ...");

            var deletedFiles = _fileSystemAccess.TryToCleanDirectory(paths.Directories.ProjectDirectory, "*.refactorlog");

            if (deletedFiles.Length == 0)
            {
                await _logger.LogTraceAsync("No files were deleted.");
            }
            else
            {
                foreach (var deletedFile in deletedFiles)
                {
                    _visualStudioAccess.RemoveItemFromProjectRoot(project, deletedFile);
                    await _logger.LogTraceAsync($"Deleted file {deletedFile} ...");
                }
            }

            stateModel.CurrentState = StateModelState.DeletedRefactorLog;
        }
        public async Task ScaffoldAsync_CompleteRun_ExceptionInStopLongRunningTask_Async()
        {
            // Arrange
            var wufMock = Mock.Of <IWorkUnitFactory>();
            var vsaMock = new Mock <IVisualStudioAccess>();

            vsaMock.Setup(m => m.StopLongRunningTaskIndicatorAsync())
            .ThrowsAsync(new Exception("test exception"));
            var loggerMock = Mock.Of <ILogger>();
            IScaffoldingService service = new ScaffoldingService(wufMock, vsaMock.Object, loggerMock);
            var project        = new SqlProject("a", "b", "c");
            var configuration  = ConfigurationModel.GetDefault();
            var targetVersion  = new Version(1, 0);
            var isCreatingList = new List <bool>();

            service.IsScaffoldingChanged += (sender,
                                             args) =>
            {
                isCreatingList.Add(service.IsScaffolding);
            };

            // Act
            var result = await service.ScaffoldAsync(project, configuration, targetVersion, CancellationToken.None);

            // Assert
            Assert.IsTrue(result);
            Assert.AreEqual(2, isCreatingList.Count);
            Assert.IsTrue(isCreatingList[0]);
            Assert.IsFalse(isCreatingList[1]);
            vsaMock.Verify(m => m.StartLongRunningTaskIndicatorAsync(), Times.Once);
            vsaMock.Verify(m => m.ClearSSDTLifecycleOutputAsync(), Times.Once);
            vsaMock.Verify(m => m.StopLongRunningTaskIndicatorAsync(), Times.Once);
        }
Beispiel #22
0
        public void GetViewModel_SameInstanceForSameProjects_DifferentSqlProjectInstancesWithSameUniqueName()
        {
            // Arrange
            var vsaMock    = Mock.Of <IVisualStudioAccess>();
            var loggerMock = Mock.Of <ILogger>();
            var spMock     = Mock.Of <IServiceProvider>();
            var cs         = new OleMenuCommandService(spMock);
            var p1         = new SqlProject("", "", "1");
            var p2         = new SqlProject("", "", "1");
            ViewModelTestImplementation vm1;
            ViewModelTestImplementation vm2;

            using (var dr = new DependencyResolver(vsaMock, loggerMock, cs))

            // Act
            {
                vm1 = dr.GetViewModel <ViewModelTestImplementation>(p1);
                vm2 = dr.GetViewModel <ViewModelTestImplementation>(p2);
            }

            // Assert
            Assert.IsNotNull(vm1);
            Assert.IsNotNull(vm2);
            Assert.AreSame(vm1, vm2);
            Assert.AreSame(p1, vm1.Project);
            Assert.AreSame(p1, vm2.Project);
        }
Beispiel #23
0
        private async Task <bool> SaveConfigurationInternalAsync(SqlProject project,
                                                                 ConfigurationModel model)
        {
            var targetPath = GetConfigurationPath(project);
            var serialized = JsonConvert.SerializeObject(model, Formatting.Indented);

            try
            {
                // Save configuration physically.
                await _fileSystemAccess.WriteFileAsync(targetPath, serialized);
            }
            catch (Exception e)
            {
                await _logger.LogErrorAsync(e, "Failed to save the configuration");

                _visualStudioAccess.ShowModalError("Failed to save the configuration. Please check the SSDT Lifecycle output window for details.");
                return(false);
            }

            // Notify about changes
            ConfigurationChanged?.Invoke(this, new ProjectConfigurationChangedEventArgs(project));

            // Add configuration to the project, if it hasn't been added before.
            _visualStudioAccess.AddItemToProjectProperties(project, targetPath);

            return(true);
        }
Beispiel #24
0
        public async Task TryInitializeToolWindowAsync_ViewModelInitializationSucceeds_Async()
        {
            // Arrange
            var project = new SqlProject("a", "b", "c");
            var vsaMock = new Mock <IVisualStudioAccess>();

            vsaMock.Setup(m => m.GetSelectedSqlProject()).Returns(project);
            var loggerMock = Mock.Of <ILogger>();
            var spMock     = Mock.Of <IServiceProvider>();
            var cs         = new OleMenuCommandService(spMock);
            var dr         = new DependencyResolver(vsaMock.Object, loggerMock, cs);
            var twi        = new ToolWindowInitializer(vsaMock.Object, dr);
            var viewMock   = new Mock <IView>();
            var windowMock = new Mock <IVisualStudioToolWindow>();

            windowMock.SetupGet(m => m.Content).Returns(viewMock.Object);

            // Act
            var(success, fullProjectPath) = await twi.TryInitializeToolWindowAsync <ViewModelBaseTestImplementationWithSuccessfulInitialization>(windowMock.Object);

            // Assert
            Assert.IsTrue(success);
            Assert.AreEqual("b", fullProjectPath);
            viewMock.Verify(m => m.SetDataContext(It.Is <IViewModel>(model => model != null && model.GetType() == typeof(ViewModelBaseTestImplementationWithSuccessfulInitialization))));
        }
        public async Task Work_ScaffoldingStateModel_InvalidVersion_Async(string dacVersionString)
        {
            // Arrange
            var dacVersion             = Version.Parse(dacVersionString);
            var formattedTargetVersion = new Version(1, 2, 4);
            var project = new SqlProject("a", "b", "c");

            project.ProjectProperties.DacVersion = dacVersion;
            var configuration = ConfigurationModel.GetDefault();
            var targetVersion = new Version(1, 2, 3);

            Task HandleWorkInProgressChanged(bool arg) => Task.CompletedTask;

            var model = new ScaffoldingStateModel(project, configuration, targetVersion, HandleWorkInProgressChanged)
            {
                FormattedTargetVersion = formattedTargetVersion
            };
            var vsaMock    = new Mock <IVisualStudioAccess>();
            var loggerMock = new Mock <ILogger>();
            IWorkUnit <ScaffoldingStateModel> unit = new ValidateTargetVersionUnit(vsaMock.Object, loggerMock.Object);

            // Act
            await unit.Work(model, CancellationToken.None);

            // Assert
            Assert.AreEqual(StateModelState.FormattedTargetVersionValidated, model.CurrentState);
            Assert.IsFalse(model.Result);
            vsaMock.Verify(m => m.ShowModalError("Please change the DAC version in the SQL project settings (see output window)."), Times.Once);
            loggerMock.Verify(m => m.LogErrorAsync(It.IsAny <string>()), Times.Once);
        }
        public async Task Work_ScaffoldingStateModel_CopyFailed_Async()
        {
            // Arrange
            var project       = new SqlProject("a", "b", "c");
            var configuration = ConfigurationModel.GetDefault();
            var targetVersion = new Version(1, 2, 3);

            Task HandleWorkInProgressChanged(bool arg) => Task.CompletedTask;

            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 ScaffoldingStateModel(project, configuration, targetVersion, HandleWorkInProgressChanged)
            {
                Paths = paths
            };
            var bsMock = new Mock <IBuildService>();

            bsMock.Setup(m => m.CopyBuildResultAsync(project, paths.Directories.NewArtifactsDirectory)).ReturnsAsync(false);
            IWorkUnit <ScaffoldingStateModel> unit = new CopyBuildResultUnit(bsMock.Object);

            // Act
            await unit.Work(model, CancellationToken.None);

            // Assert
            Assert.AreEqual(StateModelState.TriedToCopyBuildResult, model.CurrentState);
            Assert.IsFalse(model.Result);
        }
        public void GetExistingArtifactVersions_NoValidDirectories()
        {
            // Arrange
            var project = new SqlProject("a", @"C:\TestProject\TestProject.sqlproj", "c");
            var config  = new ConfigurationModel
            {
                ArtifactsPath      = "_Deployment",
                PublishProfilePath = "TestProfile.publish.xml",
                ReplaceUnnamedDefaultConstraintDrops = false,
                VersionPattern = "1.2.3.4",
                CommentOutUnnamedDefaultConstraintDrops = true,
                CreateDocumentationWithScriptCreation   = false,
                CustomHeader = "TestHeader",
                CustomFooter = "TestFooter",
                BuildBeforeScriptCreation = true,
                TrackDacpacVersion        = true
            };
            var vsaMock = new Mock <IVisualStudioAccess>();
            var fsaMock = new Mock <IFileSystemAccess>();

            fsaMock.Setup(m => m.GetDirectoriesIn(@"C:\TestProject\_Deployment"))
            .Returns(new []
            {
                @"C:\TestProject\_Deployment\foo"
            });
            IArtifactsService service = new ArtifactsService(vsaMock.Object, fsaMock.Object);

            // Act
            var result = service.GetExistingArtifactVersions(project, config);

            // Assert
            Assert.IsNotNull(result);
            Assert.AreEqual(0, result.Length);
            vsaMock.Verify(m => m.ShowModalError(It.IsAny <string>()), Times.Never);
        }
Beispiel #28
0
        public async Task Work_ScriptCreationStateModel_NoModifiers_Async()
        {
            // Arrange
            var mpsMock    = new Mock <IScriptModifierProviderService>();
            var fsaMock    = new Mock <IFileSystemAccess>();
            var loggerMock = new Mock <ILogger>();
            IWorkUnit <ScriptCreationStateModel> unit = new ModifyDeploymentScriptUnit(mpsMock.Object, fsaMock.Object, loggerMock.Object);
            var project         = new SqlProject("a", "b", "c");
            var configuration   = ConfigurationModel.GetDefault();
            var previousVersion = new Version(1, 0);

            Task HandlerFunc(bool b) => Task.CompletedTask;

            var model = new ScriptCreationStateModel(project, configuration, previousVersion, false, HandlerFunc);

            mpsMock.Setup(m => m.GetScriptModifiers(configuration)).Returns(new Dictionary <ScriptModifier, IScriptModifier>());

            // Act
            await unit.Work(model, CancellationToken.None);

            // Assert
            Assert.AreEqual(StateModelState.ModifiedDeploymentScript, model.CurrentState);
            Assert.IsNull(model.Result);
            mpsMock.Verify(m => m.GetScriptModifiers(It.IsAny <ConfigurationModel>()), Times.Once);
            fsaMock.Verify(m => m.ReadFileAsync(It.IsAny <string>()), Times.Never);
            fsaMock.Verify(m => m.WriteFileAsync(It.IsAny <string>(), It.IsAny <string>()), Times.Never);
            loggerMock.Verify(m => m.LogInfoAsync(It.IsAny <string>()), Times.Never);
        }
Beispiel #29
0
        internal TViewModel GetViewModel <TViewModel>([NotNull] SqlProject project) where TViewModel : IViewModel
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(nameof(DependencyResolver));
            }
            if (project == null)
            {
                throw new ArgumentNullException(nameof(project));
            }

            // Check for an existing view model registered with the project.
            if (_viewModels.TryGetValue(typeof(TViewModel), out var instances) &&
                instances.TryGetValue(project.UniqueName, out var instance) &&
                instance is TViewModel existingViewModel)
            {
                return(existingViewModel);
            }

            // Create a new view model and register it with the project.
            var newViewModel = _container.Resolve <TViewModel>(new ParameterOverride("project", project));

            if (!_viewModels.TryGetValue(typeof(TViewModel), out instances))
            {
                instances = new Dictionary <string, object>();
                _viewModels.Add(typeof(TViewModel), instances);
            }
            instances[project.UniqueName] = newViewModel;

            return(newViewModel);
        }
        public async Task TryLoadSqlProjectPropertiesAsync_Error_NoOutputPath_Async()
        {
            // Arrange
            const string xml =
                @"<?xml version=""1.0"" encoding=""utf-8""?>
<Project>
  <PropertyGroup>
    <Name>TestProject</Name>
  </PropertyGroup>
</Project>";
            var project = new SqlProject("a", @"C:\TestProject.sqlproj", "c");
            var vsMock  = Mock.Of <IVersionService>();
            var fsaMock = new Mock <IFileSystemAccess>();

            fsaMock.Setup(m => m.ReadFileAsync(project.FullName))
            .ReturnsAsync(xml);
            var loggedErrorMessages = new List <string>();
            var loggerMock          = new Mock <ILogger>();

            loggerMock.Setup(m => m.LogErrorAsync(It.IsAny <string>()))
            .Callback((string message) => loggedErrorMessages.Add(message))
            .Returns(Task.CompletedTask);
            ISqlProjectService service = new SqlProjectService(vsMock, fsaMock.Object, loggerMock.Object);

            // Act
            var loadedSuccessfully = await service.TryLoadSqlProjectPropertiesAsync(project);

            // Assert
            Assert.IsFalse(loadedSuccessfully);
            Assert.AreEqual(1, loggedErrorMessages.Count);
            Assert.AreEqual(@"Cannot read output path of ""C:\TestProject.sqlproj"". " +
                            "Please make sure that the \"OutputPath\" for the current configuration is set correctly, e.g. \"bin\\Output\\\". " +
                            "This value can be set from your database project => \"Properties\" => \"Build\" => \"Output path\".",
                            loggedErrorMessages[0]);
        }