public void SolutionBindingOperation_Initialization_ArgChecks()
        {
            // Arrange
            SolutionBindingOperation testSubject = this.CreateTestSubject("key");

            // Act + Assert
            Exceptions.Expect <ArgumentNullException>(() => testSubject.Initialize(null, GetQualityProfiles()));
            Exceptions.Expect <ArgumentNullException>(() => testSubject.Initialize(new Project[0], null));
        }
        public void SolutionBindingOperation_Initialization()
        {
            // Arrange
            var cs1Project = this.solutionMock.AddOrGetProject("CS1.csproj");

            cs1Project.SetCSProjectKind();
            var cs2Project = this.solutionMock.AddOrGetProject("CS2.csproj");

            cs2Project.SetCSProjectKind();
            var vbProject = this.solutionMock.AddOrGetProject("VB.vbproj");

            vbProject.SetVBProjectKind();
            SolutionBindingOperation testSubject = this.CreateTestSubject("key");
            var projects = new[] { cs1Project, vbProject, cs2Project };

            // Sanity
            testSubject.Binders.Should().BeEmpty("Not expecting any project binders");

            // Act
            testSubject.Initialize(projects, GetQualityProfiles());

            // Assert
            testSubject.SolutionFullPath.Should().Be(@"c:\solution\xxx.sln");
            testSubject.Binders.Should().HaveCount(projects.Length, "Should be one per managed project");
        }
Ejemplo n.º 3
0
        public void SolutionBindingOperation_Initialization()
        {
            // Setup
            var cs1Project = this.solutionMock.AddOrGetProject("CS1.csproj");

            cs1Project.SetCSProjectKind();
            var cs2Project = this.solutionMock.AddOrGetProject("CS2.csproj");

            cs2Project.SetCSProjectKind();
            var vbProject = this.solutionMock.AddOrGetProject("VB.vbproj");

            vbProject.SetVBProjectKind();
            SolutionBindingOperation testSubject = this.CreateTestSubject("key");
            var projects = new[] { cs1Project, vbProject, cs2Project };

            // Sanity
            Assert.AreEqual(0, testSubject.Binders.Count, "Not expecting any project binders");

            // Act
            testSubject.Initialize(projects, GetQualityProfiles());

            // Verify
            Assert.AreEqual(@"c:\solution\xxx.sln", testSubject.SolutionFullPath);
            Assert.AreEqual(projects.Length, testSubject.Binders.Count, "Should be one per managed project");
        }
        public void SolutionBindingOperation_GetRuleSetInformation()
        {
            // Arrange
            SolutionBindingOperation testSubject = this.CreateTestSubject("key");

            // Test case 1: unknown ruleset map
            // Act + Assert
            using (new AssertIgnoreScope())
            {
                testSubject.GetRuleSetInformation(Language.CSharp).Should().BeNull();
            }

            // Test case 2: known ruleset map
            // Arrange
            var ruleSetMap = new Dictionary <Language, RuleSet>();

            ruleSetMap[Language.CSharp] = new RuleSet("cs");
            ruleSetMap[Language.VBNET]  = new RuleSet("vb");

            testSubject.RegisterKnownRuleSets(ruleSetMap);
            testSubject.Initialize(new ProjectMock[0], GetQualityProfiles());
            testSubject.Prepare(CancellationToken.None);

            // Act
            string filePath = testSubject.GetRuleSetInformation(Language.CSharp).NewRuleSetFilePath;

            // Assert
            string.IsNullOrWhiteSpace(filePath).Should().BeFalse();
            filePath.Should().Be(testSubject.RuleSetsInformationMap[Language.CSharp].NewRuleSetFilePath, "NewRuleSetFilePath is expected to be updated during Prepare and returned now");
        }
Ejemplo n.º 5
0
        public void SolutionBindingOperation_GetRuleSetInformation()
        {
            // Arrange
            SolutionBindingOperation testSubject = this.CreateTestSubject();

            // Test case 1: unknown ruleset map
            var ruleSetMap = new Dictionary <Language, IBindingConfig>();

            testSubject.RegisterKnownConfigFiles(ruleSetMap);

            // Act + Assert
            using (new AssertIgnoreScope())
            {
                testSubject.GetBindingConfig(Language.CSharp).Should().BeNull();
            }

            // Test case 2: known ruleset map
            // Arrange
            ruleSetMap[Language.CSharp] = CreateMockConfigFile("c:\\csharp.txt").Object;
            ruleSetMap[Language.VBNET]  = CreateMockConfigFile("c:\\vb.txt").Object;

            testSubject.RegisterKnownConfigFiles(ruleSetMap);
            testSubject.Initialize(new ProjectMock[0]);
            testSubject.Prepare(CancellationToken.None);

            // Act
            var config = testSubject.GetBindingConfig(Language.CSharp);

            // Assert
            config.Should().Be(testSubject.RuleSetsInformationMap[Language.CSharp]);
        }
Ejemplo n.º 6
0
        public void SolutionBindingOperation_Initialization_ArgChecks()
        {
            // Arrange
            SolutionBindingOperation testSubject = this.CreateTestSubject();

            // Act + Assert
            Exceptions.Expect <ArgumentNullException>(() => testSubject.Initialize(null));
        }
        public void SolutionBindingOperation_Prepare()
        {
            // Arrange
            var csProject = this.solutionMock.AddOrGetProject("CS.csproj");

            csProject.SetCSProjectKind();
            var vbProject = this.solutionMock.AddOrGetProject("VB.vbproj");

            vbProject.SetVBProjectKind();
            var projects = new[] { csProject, vbProject };

            SolutionBindingOperation testSubject = this.CreateTestSubject("key");

            var csConfigFile = CreateMockRuleSetConfigFile("cs");
            var vbConfigFile = CreateMockRuleSetConfigFile("vb");
            var ruleSetMap   = new Dictionary <Language, IBindingConfigFile>();

            ruleSetMap[Language.CSharp] = csConfigFile.Object;
            ruleSetMap[Language.VBNET]  = vbConfigFile.Object;

            testSubject.RegisterKnownConfigFiles(ruleSetMap);
            testSubject.Initialize(projects, GetQualityProfiles());
            testSubject.Binders.Clear(); // Ignore the real binders, not part of this test scope
            var binder = new ConfigurableBindingOperation();

            testSubject.Binders.Add(binder);
            bool prepareCalledForBinder = false;

            binder.PrepareAction = (ct) => prepareCalledForBinder = true;
            string sonarQubeRulesDirectory = Path.Combine(SolutionRoot, ConfigurableSolutionRuleSetsInformationProvider.DummyLegacyModeFolderName);

            var csharpRulesetPath = Path.Combine(sonarQubeRulesDirectory, "keycsharp.ruleset");
            var vbRulesetPath     = Path.Combine(sonarQubeRulesDirectory, "keyvb.ruleset");

            // Sanity
            this.sccFileSystem.directories.Should().NotContain(sonarQubeRulesDirectory);
            testSubject.RuleSetsInformationMap[Language.CSharp].NewFilePath.Should().Be(csharpRulesetPath);
            testSubject.RuleSetsInformationMap[Language.VBNET].NewFilePath.Should().Be(vbRulesetPath);

            // Act
            testSubject.Prepare(CancellationToken.None);

            // Assert
            this.sccFileSystem.directories.Should().NotContain(sonarQubeRulesDirectory);
            prepareCalledForBinder.Should().BeTrue("Expected to propagate the prepare call to binders");
            CheckSaveWasNotCalled(csConfigFile);
            CheckSaveWasNotCalled(vbConfigFile);

            // Act (write pending)
            this.sccFileSystem.WritePendingNoErrorsExpected();

            // Assert
            CheckRuleSetFileWasSaved(csConfigFile, csharpRulesetPath);
            CheckRuleSetFileWasSaved(vbConfigFile, vbRulesetPath);
            this.sccFileSystem.directories.Should().Contain(sonarQubeRulesDirectory);
        }
        private void ExecuteCommitSolutionBindingTest(SonarLintMode bindingMode)
        {
            // Arrange
            var configProvider = new ConfigurableConfigurationProvider();

            this.serviceProvider.RegisterService(typeof(IConfigurationProvider), configProvider);
            var csProject = this.solutionMock.AddOrGetProject("CS.csproj");

            csProject.SetCSProjectKind();
            var projects = new[] { csProject };

            var connectionInformation            = new ConnectionInformation(new Uri("http://xyz"));
            SolutionBindingOperation testSubject = this.CreateTestSubject("key", connectionInformation, bindingMode);

            var configFileMock    = CreateMockRuleSetConfigFile("cs");
            var languageToFileMap = new Dictionary <Language, IBindingConfigFile>()
            {
                { Language.CSharp, configFileMock.Object }
            };

            testSubject.RegisterKnownConfigFiles(languageToFileMap);
            var profiles = GetQualityProfiles();

            DateTime expectedTimeStamp = DateTime.Now;

            profiles[Language.CSharp] = new SonarQubeQualityProfile("expected profile Key", "", "", false, expectedTimeStamp);
            testSubject.Initialize(projects, profiles);
            testSubject.Binders.Clear(); // Ignore the real binders, not part of this test scope
            bool commitCalledForBinder = false;

            testSubject.Binders.Add(new ConfigurableBindingOperation {
                CommitAction = () => commitCalledForBinder = true
            });
            testSubject.Prepare(CancellationToken.None);

            // Sanity
            configProvider.SavedConfiguration.Should().BeNull();

            // Act
            var commitResult = testSubject.CommitSolutionBinding();

            // Assert
            commitResult.Should().BeTrue();
            commitCalledForBinder.Should().BeTrue();

            configProvider.SavedConfiguration.Should().NotBeNull();
            configProvider.SavedConfiguration.Mode.Should().Be(bindingMode);

            var savedProject = configProvider.SavedConfiguration.Project;

            savedProject.ServerUri.Should().Be(connectionInformation.ServerUri);
            savedProject.Profiles.Should().HaveCount(1);
            savedProject.Profiles[Language.CSharp].ProfileKey.Should().Be("expected profile Key");
            savedProject.Profiles[Language.CSharp].ProfileTimestamp.Should().Be(expectedTimeStamp);
        }
        public void SolutionBindingOperation_CommitSolutionBinding()
        {
            // Arrange
            var configProvider = new ConfigurableConfigurationProvider();

            this.serviceProvider.RegisterService(typeof(IConfigurationProvider), configProvider);
            var csProject = this.solutionMock.AddOrGetProject("CS.csproj");

            csProject.SetCSProjectKind();
            var projects = new[] { csProject };

            var connectionInformation            = new ConnectionInformation(new Uri("http://xyz"));
            SolutionBindingOperation testSubject = this.CreateTestSubject("key", connectionInformation);

            var ruleSetMap = new Dictionary <Language, RuleSet>();

            ruleSetMap[Language.CSharp] = new RuleSet("cs");
            testSubject.RegisterKnownRuleSets(ruleSetMap);
            var profiles = GetQualityProfiles();

            DateTime expectedTimeStamp = DateTime.Now;

            profiles[Language.CSharp] = new SonarQubeQualityProfile("expected profile Key", "", "", false, expectedTimeStamp);
            testSubject.Initialize(projects, profiles);
            testSubject.Binders.Clear(); // Ignore the real binders, not part of this test scope
            bool commitCalledForBinder = false;

            testSubject.Binders.Add(new ConfigurableBindingOperation {
                CommitAction = () => commitCalledForBinder = true
            });
            testSubject.Prepare(CancellationToken.None);

            // Sanity
            configProvider.SavedConfiguration.Should().BeNull();

            // Act
            var commitResult = testSubject.CommitSolutionBinding();

            // Assert
            commitResult.Should().BeTrue();
            commitCalledForBinder.Should().BeTrue();
            this.solutionItemsProject.Files.ContainsKey(@"c:\solution\SonarQube\keyCSharp.ruleset").Should().BeTrue("Ruleset was expected to be added to solution items");

            configProvider.SavedConfiguration.Should().NotBeNull();
            configProvider.SavedConfiguration.Mode.Should().Be(SonarLintMode.LegacyConnected);

            var savedProject = configProvider.SavedConfiguration.Project;

            savedProject.ServerUri.Should().Be(connectionInformation.ServerUri);
            savedProject.Profiles.Should().HaveCount(1);
            savedProject.Profiles[Language.CSharp].ProfileKey.Should().Be("expected profile Key");
            savedProject.Profiles[Language.CSharp].ProfileTimestamp.Should().Be(expectedTimeStamp);
        }
        public void SolutionBindingOperation_CommitSolutionBinding()
        {
            // Arrange
            this.serviceProvider.RegisterService(typeof(Persistence.ISolutionBindingSerializer), this.solutionBinding);
            var csProject = this.solutionMock.AddOrGetProject("CS.csproj");

            csProject.SetCSProjectKind();
            var projects = new[] { csProject };

            var connectionInformation            = new ConnectionInformation(new Uri("http://xyz"));
            SolutionBindingOperation testSubject = this.CreateTestSubject("key", connectionInformation);

            var ruleSetMap = new Dictionary <Language, RuleSet>();

            ruleSetMap[Language.CSharp] = new RuleSet("cs");
            testSubject.RegisterKnownRuleSets(ruleSetMap);
            var profiles = GetQualityProfiles();

            profiles[Language.CSharp] = new QualityProfile {
                Key = "C# Profile", QualityProfileTimestamp = DateTime.Now
            };
            testSubject.Initialize(projects, profiles);
            testSubject.Binders.Clear(); // Ignore the real binders, not part of this test scope
            bool commitCalledForBinder = false;

            testSubject.Binders.Add(new ConfigurableBindingOperation {
                CommitAction = () => commitCalledForBinder = true
            });
            testSubject.Prepare(CancellationToken.None);
            this.solutionBinding.WriteSolutionBindingAction = bindingInfo =>
            {
                bindingInfo.ServerUri.Should().Be(connectionInformation.ServerUri);
                bindingInfo.Profiles.Should().HaveCount(1);

                QualityProfile csProfile = profiles[Language.CSharp];
                bindingInfo.Profiles[Language.CSharp].ProfileKey.Should().Be(csProfile.Key);
                bindingInfo.Profiles[Language.CSharp].ProfileTimestamp.Should().Be(csProfile.QualityProfileTimestamp);

                return("Doesn't matter");
            };

            // Sanity
            this.solutionBinding.WrittenFilesCount.Should().Be(0);

            // Act
            var commitResult = testSubject.CommitSolutionBinding();

            // Assert
            commitResult.Should().BeTrue();
            commitCalledForBinder.Should().BeTrue();
            this.solutionItemsProject.Files.ContainsKey(@"c:\solution\SonarQube\keyCSharp.ruleset").Should().BeTrue("Ruleset was expected to be added to solution items");
            this.solutionBinding.WrittenFilesCount.Should().Be(1);
        }
        public void SolutionBindingOperation_Prepare()
        {
            // Arrange
            var csProject = this.solutionMock.AddOrGetProject("CS.csproj");

            csProject.SetCSProjectKind();
            var vbProject = this.solutionMock.AddOrGetProject("VB.vbproj");

            vbProject.SetVBProjectKind();
            var projects = new[] { csProject, vbProject };

            SolutionBindingOperation testSubject = this.CreateTestSubject("key");

            var ruleSetMap = new Dictionary <Language, RuleSet>();

            ruleSetMap[Language.CSharp] = new RuleSet("cs");
            ruleSetMap[Language.VBNET]  = new RuleSet("vb");

            testSubject.RegisterKnownRuleSets(ruleSetMap);
            testSubject.Initialize(projects, GetQualityProfiles());
            testSubject.Binders.Clear(); // Ignore the real binders, not part of this test scope
            var binder = new ConfigurableBindingOperation();

            testSubject.Binders.Add(binder);
            bool prepareCalledForBinder = false;

            binder.PrepareAction = (ct) => prepareCalledForBinder = true;
            string sonarQubeRulesDirectory = Path.Combine(SolutionRoot, Constants.SonarQubeManagedFolderName);

            // Sanity
            this.sccFileSystem.directories.Should().NotContain(sonarQubeRulesDirectory);
            testSubject.RuleSetsInformationMap[Language.CSharp].NewRuleSetFilePath.Should().Be(@"c:\solution\SonarQube\keyCSharp.ruleset");
            testSubject.RuleSetsInformationMap[Language.VBNET].NewRuleSetFilePath.Should().Be(@"c:\solution\SonarQube\keyVB.ruleset");

            // Act
            testSubject.Prepare(CancellationToken.None);

            // Assert
            this.sccFileSystem.directories.Should().NotContain(sonarQubeRulesDirectory);
            prepareCalledForBinder.Should().BeTrue("Expected to propagate the prepare call to binders");
            this.sccFileSystem.files.Should().NotContainKey(@"c:\solution\SonarQube\keyCSharp.ruleset");
            this.sccFileSystem.files.Should().NotContainKey(@"c:\solution\SonarQube\keyVB.ruleset");

            // Act (write pending)
            this.sccFileSystem.WritePendingNoErrorsExpected();

            // Assert
            this.sccFileSystem.files.Should().ContainKey(@"c:\solution\SonarQube\keyCSharp.ruleset");
            this.sccFileSystem.files.Should().ContainKey(@"c:\solution\SonarQube\keyVB.ruleset");
            this.sccFileSystem.directories.Should().Contain(sonarQubeRulesDirectory);
        }
        public void SolutionBindingOperation_Prepare_Cancellation_DuringBindersPrepare()
        {
            // Arrange
            var csProject = this.solutionMock.AddOrGetProject("CS.csproj");

            csProject.SetCSProjectKind();
            var vbProject = this.solutionMock.AddOrGetProject("VB.vbproj");

            vbProject.SetVBProjectKind();
            var projects = new[] { csProject, vbProject };

            SolutionBindingOperation testSubject = this.CreateTestSubject("key");

            var csConfigFile      = CreateMockRuleSetConfigFile("cs");
            var vbConfigFile      = CreateMockRuleSetConfigFile("vb");
            var languageToFileMap = new Dictionary <Language, IBindingConfigFile>();

            languageToFileMap[Language.CSharp] = csConfigFile.Object;
            languageToFileMap[Language.VBNET]  = vbConfigFile.Object;

            testSubject.RegisterKnownConfigFiles(languageToFileMap);
            testSubject.Initialize(projects, GetQualityProfiles());
            testSubject.Binders.Clear(); // Ignore the real binders, not part of this test scope
            bool prepareCalledForBinder = false;

            using (CancellationTokenSource src = new CancellationTokenSource())
            {
                testSubject.Binders.Add(new ConfigurableBindingOperation {
                    PrepareAction = (t) => src.Cancel()
                });
                testSubject.Binders.Add(new ConfigurableBindingOperation {
                    PrepareAction = (t) => prepareCalledForBinder = true
                });

                // Act
                testSubject.Prepare(src.Token);
            }

            // Assert
            string expectedSolutionFolder = Path.Combine(SolutionRoot, ConfigurableSolutionRuleSetsInformationProvider.DummyLegacyModeFolderName);

            testSubject.RuleSetsInformationMap[Language.CSharp].NewFilePath.Should().Be(Path.Combine(expectedSolutionFolder, "keycsharp.ruleset"));
            testSubject.RuleSetsInformationMap[Language.VBNET].NewFilePath.Should().Be(Path.Combine(expectedSolutionFolder, "keyvb.ruleset"));
            prepareCalledForBinder.Should().BeFalse("Expected to be canceled as soon as possible i.e. after the first binder");

            CheckSaveWasNotCalled(csConfigFile);
            CheckSaveWasNotCalled(vbConfigFile);
        }
        public void SolutionBindingOperation_Prepare_Cancellation_BeforeBindersPrepare()
        {
            // Arrange
            var csProject = this.solutionMock.AddOrGetProject("CS.csproj");

            csProject.SetCSProjectKind();
            var vbProject = this.solutionMock.AddOrGetProject("VB.vbproj");

            vbProject.SetVBProjectKind();
            var projects = new[] { csProject, vbProject };

            SolutionBindingOperation testSubject = this.CreateTestSubject("key");

            var csConfigFile = CreateMockRuleSetConfigFile("cs");
            var vbConfigFile = CreateMockRuleSetConfigFile("vb");
            var ruleSetMap   = new Dictionary <Language, IBindingConfigFile>();

            ruleSetMap[Language.CSharp] = csConfigFile.Object;
            ruleSetMap[Language.VBNET]  = vbConfigFile.Object;

            testSubject.RegisterKnownConfigFiles(ruleSetMap);
            testSubject.Initialize(projects, GetQualityProfiles());
            testSubject.Binders.Clear(); // Ignore the real binders, not part of this test scope
            bool prepareCalledForBinder = false;

            using (CancellationTokenSource src = new CancellationTokenSource())
            {
                testSubject.Binders.Add(new ConfigurableBindingOperation {
                    PrepareAction = (t) => prepareCalledForBinder = true
                });
                src.Cancel();

                // Act
                testSubject.Prepare(src.Token);
            }

            // Assert
            testSubject.RuleSetsInformationMap[Language.CSharp].NewFilePath.Should().NotBeNull("Expected to be set before Prepare is called");
            testSubject.RuleSetsInformationMap[Language.VBNET].NewFilePath.Should().NotBeNull("Expected to be set before Prepare is called");
            prepareCalledForBinder.Should().BeFalse("Expected to be canceled as soon as possible i.e. before the first binder");
            CheckSaveWasNotCalled(csConfigFile);
            CheckSaveWasNotCalled(vbConfigFile);
        }
        public void SolutionBindingOperation_Prepare_Cancellation_DuringBindersPrepare()
        {
            // Arrange
            var csProject = this.solutionMock.AddOrGetProject("CS.csproj");

            csProject.SetCSProjectKind();
            var vbProject = this.solutionMock.AddOrGetProject("VB.vbproj");

            vbProject.SetVBProjectKind();
            var projects = new[] { csProject, vbProject };

            SolutionBindingOperation testSubject = this.CreateTestSubject("key");
            var ruleSetMap = new Dictionary <Language, RuleSet>();

            ruleSetMap[Language.CSharp] = new RuleSet("cs");
            ruleSetMap[Language.VBNET]  = new RuleSet("vb");

            testSubject.RegisterKnownRuleSets(ruleSetMap);
            testSubject.Initialize(projects, GetQualityProfiles());
            testSubject.Binders.Clear(); // Ignore the real binders, not part of this test scope
            bool prepareCalledForBinder = false;

            using (CancellationTokenSource src = new CancellationTokenSource())
            {
                testSubject.Binders.Add(new ConfigurableBindingOperation {
                    PrepareAction = (t) => src.Cancel()
                });
                testSubject.Binders.Add(new ConfigurableBindingOperation {
                    PrepareAction = (t) => prepareCalledForBinder = true
                });

                // Act
                testSubject.Prepare(src.Token);
            }

            // Assert
            testSubject.RuleSetsInformationMap[Language.CSharp].NewRuleSetFilePath.Should().Be(@"c:\solution\SonarQube\keyCSharp.ruleset");
            testSubject.RuleSetsInformationMap[Language.VBNET].NewRuleSetFilePath.Should().Be(@"c:\solution\SonarQube\keyVB.ruleset");
            prepareCalledForBinder.Should().BeFalse("Expected to be canceled as soon as possible i.e. after the first binder");
        }
Ejemplo n.º 15
0
        private void ExecuteCommitSolutionBindingTest(SonarLintMode bindingMode, string expectedFilePath)
        {
            // Arrange
            var csProject = solutionMock.AddOrGetProject("CS.csproj");

            csProject.SetCSProjectKind();
            var csConfigFile         = CreateMockConfigFile(expectedFilePath);
            var csBinder             = new Mock <IProjectBinder>();
            var csBinderCommitAction = new Mock <BindProject>();

            projectBinderFactoryMock.Setup(x => x.Get(csProject)).Returns(csBinder.Object);

            csBinder
            .Setup(x => x.GetBindAction(csConfigFile.Object, csProject, CancellationToken.None))
            .Returns(csBinderCommitAction.Object);

            var projects = new[] { csProject };

            var connectionInformation            = new ConnectionInformation(new Uri("http://xyz"));
            SolutionBindingOperation testSubject = this.CreateTestSubject(bindingMode);

            var languageToFileMap = new Dictionary <Language, IBindingConfig>()
            {
                { Language.CSharp, csConfigFile.Object }
            };

            testSubject.RegisterKnownConfigFiles(languageToFileMap);

            DateTime expectedTimeStamp = DateTime.Now;

            testSubject.Initialize(projects);
            testSubject.Prepare(CancellationToken.None);

            // Act
            var commitResult = testSubject.CommitSolutionBinding();

            // Assert
            commitResult.Should().BeTrue();
            csBinderCommitAction.Verify(x => x(), Times.Once);
        }
        public void SolutionBindingOperation_Initialization()
        {
            // Arrange
            var cs1Project = this.solutionMock.AddOrGetProject("CS1.csproj");

            cs1Project.SetCSProjectKind();
            var cs2Project = this.solutionMock.AddOrGetProject("CS2.csproj");

            cs2Project.SetCSProjectKind();
            var vbProject = this.solutionMock.AddOrGetProject("VB.vbproj");

            vbProject.SetVBProjectKind();
            var otherProjectType = this.solutionMock.AddOrGetProject("xxx.proj");

            otherProjectType.ProjectKind = "{" + Guid.NewGuid().ToString() + "}";

            var logger = new TestLogger();

            SolutionBindingOperation testSubject = this.CreateTestSubject("key", logger: logger);
            var projects = new[] { cs1Project, vbProject, cs2Project, otherProjectType };

            // Sanity
            testSubject.Binders.Should().BeEmpty("Not expecting any project binders");

            // Act
            testSubject.Initialize(projects, GetQualityProfiles());

            // Assert
            testSubject.SolutionFullPath.Should().Be(Path.Combine(SolutionRoot, "xxx.sln"));
            testSubject.Binders.Should().HaveCount(3, "Should be one per managed project");

            testSubject.Binders.Select(x => ((ProjectBindingOperation)x).ProjectFullPath)
            .Should().BeEquivalentTo("CS1.csproj", "CS2.csproj", "VB.vbproj");

            logger.AssertPartialOutputStringExists("xxx.proj"); // expecting a message about the project that won't be bound, but not the others
            logger.AssertPartialOutputStringDoesNotExist("CS1.csproj");
        }