Example #1
0
        public void GetSuppressedIssues_WhenIssueIsFileLevel_ShouldMatchOnLongestPath()
        {
            // Arrange
            var sonarQubeIssue1 = new SonarQubeIssue("foo.cs", null, null, "message", "sqkey:sqkey:projectId", "S1", true);
            var sonarQubeIssue2 = new SonarQubeIssue("/foo/foo.cs", null, null, "message", "sqkey:sqkey:projectId", "S2", true);

            SetupSolutionBinding(true,
                                 new List <SonarQubeIssue> {
                sonarQubeIssue1, sonarQubeIssue2
            },
                                 new List <SonarQubeModule> {
                new SonarQubeModule("sqkey:sqkey:projectId", "", "src/bar")
            });

            var issuesProvider = new SonarQubeIssuesProvider(mockSqService.Object, "sqkey", mockTimerFactory.Object, testLogger);

            WaitForInitialFetchTaskToStart();

            VerifyServiceGetIssues(Times.Exactly(1)); // issues should be fetched on creation

            // Act / Assert - #1 - Longest path is retrieved first
            var matches = issuesProvider.GetSuppressedIssues("", "C:\\AwesomeProject\\src\\bar\\foo\\foo.cs");

            matches.Should().HaveCount(1);
            matches.First().RuleId.Should().Be("S2");

            // Act / Assert - #2 - Shortest path
            matches = issuesProvider.GetSuppressedIssues("", "C:\\AwesomeProject\\src\\bar\\foo.cs");
            matches.Should().HaveCount(1);
            matches.First().RuleId.Should().Be("S1");
        }
        public void GetIssues_IssuesExists_DifferentSQProjectKey_NoMatches()
        {
            var issue1 = new SonarQubeIssue("file1", "hash1", 0, "message", "otherkey:otherkey:projectID1",
                                            SonarQubeIssueResolutionState.FalsePositive, "S101");
            var issue2 = new SonarQubeIssue("folder1/file1", "hash2", 0, "message", "otherkey:otherkey:projectID2",
                                            SonarQubeIssueResolutionState.FalsePositive, "S102");

            SetupSolutionBinding(isConnected: true,
                                 issues: new List <SonarQubeIssue> {
                issue1, issue2
            });

            var issuesProvider = new SonarQubeIssuesProvider(mockSqService.Object, "sqKey",
                                                             mockTimerFactory.Object, testLogger);

            WaitForInitialFetchTaskToStart();

            VerifyServiceGetIssues(Times.Exactly(1)); // issues should be fetched on creation

            // 1. SonarQube project key doesn't match -> no issues
            var matches = issuesProvider.GetSuppressedIssues("projectID1", "file1");

            matches.Should().BeEmpty();

            // 2. SonarQube project key doesn't match -> no issues
            matches = issuesProvider.GetSuppressedIssues("PROJECTID2", "folder1/file1");
            matches.Should().BeEmpty();

            VerifyServiceGetIssues(Times.Exactly(1)); // cached issues should be used
        }
Example #3
0
        public void GetSuppressedIssues_WhenProjectHasModulesAndIssueIsOnAFileAtRootLevel_FalseMatch()
        {
            // Same as previous test except that the SonarQube Project contains multiple modules

            // Arrange
            var sonarQubeIssue1 = new SonarQubeIssue("foo.cs", null, null, "message", "sqkey", "S1", true);
            var sonarQubeIssue2 = new SonarQubeIssue("toto/foo.cs", null, null, "message", "sqkey", "S2", true);

            SetupSolutionBinding(true,
                                 new List <SonarQubeIssue> {
                sonarQubeIssue1, sonarQubeIssue2
            },
                                 new List <SonarQubeModule> {
                new SonarQubeModule("sqkey", "", ""), new SonarQubeModule("sqkey:sqkey:guid", "", "src/bar/foo")
            });

            var issuesProvider = new SonarQubeIssuesProvider(mockSqService.Object, "sqkey", mockTimerFactory.Object, testLogger);

            WaitForInitialFetchTaskToStart();

            VerifyServiceGetIssues(Times.Exactly(1)); // issues should be fetched on creation

            // Act / Assert - same file name exists at multiple levels in the hierarchy

            // This is the False Match...
            var matches = issuesProvider.GetSuppressedIssues("", "C:\\AwesomeProject\\src\\bar\\foo\\foo.cs");

            matches.Should().HaveCount(1);
            matches.First().RuleId.Should().Be("S1");

            // ... and this is the correct one
            matches = issuesProvider.GetSuppressedIssues("", "C:\\AwesomeProject\\src\\bar\\foo.cs");
            matches.Should().HaveCount(1);
            matches.First().RuleId.Should().Be("S1");
        }
        public void GetIssues_ErrorInInitialFetchTask_IsSuppressed()
        {
            var issue1 = new SonarQubeIssue("folder1/file1", "hash1", 0, "message", "sqkey:sqkey:projectID1",
                                            SonarQubeIssueResolutionState.FalsePositive, "S101");

            Func <IList <SonarQubeIssue> > serviceFetchIssuesTask = () =>
            {
                InitialFetchWaitHandle.Set(); // signal so the test can continue
                throw new ApplicationException("dummy error from mock");
            };

            SetupSolutionBinding(isConnected: true, serviceFetchIssuesTask: serviceFetchIssuesTask);

            // 1. Create the issue provider
            // The initial fetch should be triggered, but not yet completed
            var issuesProvider = new SonarQubeIssuesProvider(mockSqService.Object, "sqkey",
                                                             mockTimerFactory.Object, testLogger);

            WaitForInitialFetchTaskToStart();

            // 2. Now request the issues - task completes with an error
            var matches = issuesProvider.GetSuppressedIssues("projectid1", "folder1/file1");

            VerifyServiceGetIssues(Times.Once(), "sqkey");
            matches.Should().BeEmpty();

            // 3. Now fetch again - should not wait again, should not error
            matches = issuesProvider.GetSuppressedIssues("folder1/file1", "projectid1");
            matches.Should().BeEmpty();
            VerifyServiceGetIssues(Times.Once());

            testLogger.AssertPartialOutputStrings("Checking for suppressions", "dummy error from mock");
        }
        public void GetIssues_IssuesExists_FiltersByFileAndProject()
        {
            var issue1 = new SonarQubeIssue("folder1/file1", "hash1", 0, "message", "sqkey:sqkey:projectID1",
                                            SonarQubeIssueResolutionState.FalsePositive, "S101");
            var issue2 = new SonarQubeIssue("folder1/file1", "hash2", 0, "message", "sqkey:sqkey:projectID2",
                                            SonarQubeIssueResolutionState.WontFix, "S102");
            var issue3 = new SonarQubeIssue("folder1/file1", "hash3", 0, "message", "sqkey:sqkey:projectID2",
                                            SonarQubeIssueResolutionState.Fixed, "S103");
            var issue4 = new SonarQubeIssue("folder1/file1", "hash4", 0, "message", "sqkey:sqkey: projectID2",
                                            SonarQubeIssueResolutionState.WontFix, "S104");
            var issue5 = new SonarQubeIssue("folder1/file1", "hash5", 0, "message", "sqkey:XXX:projectID2",
                                            SonarQubeIssueResolutionState.FalsePositive, "S105");

            var issue6 = new SonarQubeIssue("folder1/file2", "hash6", 0, "message", "sqkey:sqkey:projectID1",
                                            SonarQubeIssueResolutionState.Unresolved, "S106");
            var issue7 = new SonarQubeIssue("folder2/file1", "hash7", 0, "message", "sqkey:sqkey:projectID1",
                                            SonarQubeIssueResolutionState.Fixed, "S107");

            var issue8 = new SonarQubeIssue("file1", "hash8", 0, "message", "sqkey:sqkey:projectID1",
                                            SonarQubeIssueResolutionState.FalsePositive, "S108");
            var issue9 = new SonarQubeIssue("file1", "hash9", 0, "message", "sqkey:sqkey:projectID1xxx",
                                            SonarQubeIssueResolutionState.WontFix, "S109");
            var issue10 = new SonarQubeIssue("file1", "hash10", 0, "message", "sqkey:sqkey:projectID",
                                             SonarQubeIssueResolutionState.Unresolved, "S110");

            SetupSolutionBinding(isConnected: true,
                                 issues: new List <SonarQubeIssue> {
                issue1, issue2, issue3, issue4, issue5, issue6, issue7, issue8, issue9, issue1
            });

            var issuesProvider = new SonarQubeIssuesProvider(mockSqService.Object, "sqKey",
                                                             mockTimerFactory.Object, testLogger);

            WaitForInitialFetchTaskToStart();

            VerifyServiceGetIssues(Times.Exactly(1)); // issues should be fetched on creation

            // 1. Project id doesn't match -> no issues
            var matches = issuesProvider.GetSuppressedIssues("unrecognisedProjectId", "folder1/file1");

            matches.Should().BeEmpty();
            VerifyServiceGetIssues(Times.Exactly(1), "sqKey"); // cached issues should be used

            // 2. File id doesn't match -> no issues
            matches = issuesProvider.GetSuppressedIssues("projectID1", "folder1/filexxx");
            matches.Should().BeEmpty();

            // 3. File id and guid match -> issues returned
            matches = issuesProvider.GetSuppressedIssues("projectID1", "file1");
            matches.Count().Should().Be(1);
            CheckExpectedIssueReturned("hash8", matches);

            // 4. File id and guid match, case-insensitive -> issues returned
            matches = issuesProvider.GetSuppressedIssues("PROJECTID2", "FOLDER1/FILE1");
            matches.Count().Should().Be(2);
            CheckExpectedIssueReturned("hash2", matches);
            CheckExpectedIssueReturned("hash3", matches);

            VerifyServiceGetIssues(Times.Exactly(1));
        }
        public void GetSuppressedIssues_WhenProjectHasModulesAndIssueIsFileLevelAndIsFound_ReturnsExpectedIssue()
        {
            // Arrange
            var issues = new []
            {
                CreateIssue("foo\\foo.cs", "sqkey:sqkey:projectId", "S2"),
                CreateIssue("foo\\FOO.cs", "sqkey:sqkey:projectId", "S3"),
                CreateIssue("FOO\\foo.cs", "sqkey:sqkey:projectId", "S4"),
                CreateIssue("bar\\bar.cs", "sqkey:sqkey:projectId", "S5")
            };

            SetupSolutionBinding(true,
                                 issues,
                                 new List <SonarQubeModule> {
                new SonarQubeModule("sqkey", "", ""), new SonarQubeModule("sqkey:sqkey:projectId", "", "src\\bar")
            });

            var issuesProvider = new SonarQubeIssuesProvider(mockSqService.Object, "sqkey", mockTimerFactory.Object, testLogger);

            WaitForInitialFetchTaskToStart();

            VerifyServiceGetIssues(Times.Exactly(1)); // issues should be fetched on creation

            // Act
            var matches = issuesProvider.GetSuppressedIssues("guid doesn't matter", "C:\\AwesomeProject\\src\\bar\\foo\\foo.cs");

            // Assert
            matches.Should().HaveCount(3);
            matches.Should().OnlyContain(x => x.RuleId != "S5");
        }
Example #7
0
        public void GetSuppressedIssues_WhenIssueIsFileLevel_ShouldMatchUsingCasingInsensitiveComparison()
        {
            // Arrange
            var sonarQubeIssue1 = new SonarQubeIssue("foo.CS", null, null, "message", "sqkey:sqkey:projectId", "S1", true);
            var sonarQubeIssue2 = new SonarQubeIssue("/foo/FOO.cs", null, null, "message", "sqkey:sqkey:projectId", "S2", true);

            SetupSolutionBinding(true,
                                 new List <SonarQubeIssue> {
                sonarQubeIssue1, sonarQubeIssue2
            },
                                 new List <SonarQubeModule> {
                new SonarQubeModule("sqkey:sqkey:projectId", "", "src/bar")
            });

            var issuesProvider = new SonarQubeIssuesProvider(mockSqService.Object, "sqkey", mockTimerFactory.Object, testLogger);

            WaitForInitialFetchTaskToStart();

            VerifyServiceGetIssues(Times.Exactly(1)); // issues should be fetched on creation

            // Act
            var matches = issuesProvider.GetSuppressedIssues("", "C:\\AWESOMEProject\\SRC\\bar\\FOO\\foo.cS");

            // Assert
            matches.Should().HaveCount(1);
            matches.First().RuleId.Should().Be("S2");
        }
        public void GetIssues_NotConnected_NoErrors()
        {
            // Arrange
            SetupSolutionBinding(isConnected: false, issues: null);

            int callCount = 0;

            // This time we want the test to pause until IsConnected is called by the inital fetch task
            mockSqService.Setup(x => x.IsConnected)
            .Returns(false)
            .Callback(() => { InitialFetchWaitHandle.Set(); callCount++; })      // signal so the test can continue
            .Verifiable();

            // 1. Initialise the class
            var issuesProvider = new SonarQubeIssuesProvider(mockSqService.Object, "sqKey",
                                                             mockTimerFactory.Object, testLogger);

            WaitForInitialFetchTaskToStart();

            // 2. Now dispose. Should stop the background fetching
            int callsBeforeDispose = callCount;

            issuesProvider.Dispose();

            // 3. Now try to fetch - should block until the background task has completed
            var issues = issuesProvider.GetSuppressedIssues("dummy guid", "dummy file path");

            issues.Should().BeEmpty();
            VerifyServiceGetIssues(Times.Never());

            // Timing: increment could have afer dispose called but before the cancellation token was set
            callCount.Should().BeLessOrEqualTo(callsBeforeDispose + 1);

            testLogger.AssertNoOutputMessages();
        }
Example #9
0
        public void GetSuppressedIssues_WhenProjectHasNoModulesAndIssueIsModuleLevelAndFound_ReturnsExpectedIssue()
        {
            // Arrange
            var sonarQubeIssue1 = new SonarQubeIssue(null, null, null, "message", "sqkey", "S1", true);
            var sonarQubeIssue2 = new SonarQubeIssue("/foo/bar.cs", "hash", 12, "message", "sqkey", "S2", true);

            SetupSolutionBinding(true, new List <SonarQubeIssue> {
                sonarQubeIssue1
            },
                                 new List <SonarQubeModule> {
                new SonarQubeModule("sqkey", "", "")
            });

            var issuesProvider = new SonarQubeIssuesProvider(mockSqService.Object, "sqkey", mockTimerFactory.Object, testLogger);

            WaitForInitialFetchTaskToStart();

            VerifyServiceGetIssues(Times.Exactly(1)); // issues should be fetched on creation

            // Act
            var matches = issuesProvider.GetSuppressedIssues("projectId", null);

            // Assert
            matches.Should().HaveCount(1);
            matches.First().RuleId.Should().Be("S1");
        }
        public void GetIssues_IssuesNotYetFetch_WaitsForIssuesToBeFetched()
        {
            var issue1 = new SonarQubeIssue("folder1/file1", "hash1", 0, "message", "sqkey:sqkey:projectID1",
                                            SonarQubeIssueResolutionState.FalsePositive, "S101");

            int  callbackCount     = 0;
            bool callbackCompleted = false;
            Func <IList <SonarQubeIssue> > serviceFetchIssuesTask = () =>
            {
                callbackCount++;

                InitialFetchWaitHandle.Set(); // signal so the test can continue

                Thread.Sleep(Debugger.IsAttached ? 5000 : 500);
                callbackCompleted = true;
                return(new List <SonarQubeIssue> {
                    issue1
                });
            };

            SetupSolutionBinding(isConnected: true, serviceFetchIssuesTask: serviceFetchIssuesTask);

            // 1. Create the issue provider
            // The initial fetch should be triggered, but not yet completed
            var issuesProvider = new SonarQubeIssuesProvider(mockSqService.Object, "sqKey",
                                                             mockTimerFactory.Object, testLogger);

            WaitForInitialFetchTaskToStart();

            // 2. Now request the issues - should wait until the issues have been retrieved
            var matches = issuesProvider.GetSuppressedIssues("projectid1", "folder1/file1");

            VerifyServiceGetIssues(Times.Once(), "sqKey");
            callbackCount.Should().Be(1);
            callbackCompleted.Should().BeTrue();
            matches.Count().Should().Be(1);
            CheckExpectedIssueReturned("hash1", matches);

            // 3. Now fetch again - should not wait again
            matches = issuesProvider.GetSuppressedIssues("folder1/file1", "projectid1");

            VerifyServiceGetIssues(Times.Once());
            callbackCount.Should().Be(1);
        }
        public void GetIssues_ErrorFetchingOnTimerElapsed_IsSuppressed()
        {
            // Tests that the timer trigger that causes the data to be refetched won't propagate errors
            // if the GetIssues call throws.

            var issue1 = new SonarQubeIssue("folder1/file1", "hash1", 0, "message", "sqkey:sqkey:projectId",
                                            SonarQubeIssueResolutionState.FalsePositive, "S101");

            SetupSolutionBinding(isConnected: true, issues: new List <SonarQubeIssue> {
                issue1
            });

            // 1. Create the issue provider and call GetIssues to make sure the issues are cached
            var issuesProvider = new SonarQubeIssuesProvider(mockSqService.Object, "sqkey",
                                                             mockTimerFactory.Object, testLogger);
            var matches = issuesProvider.GetSuppressedIssues("projectId", "folder1/file1");

            VerifyServiceGetIssues(Times.Once());
            matches.Count().Should().Be(1);
            testLogger.AssertPartialOutputStrings("Checking for suppressions", "1");

            // 2. Configure service to throw, then execute the fetch trigger
            int fetchCallCount = 0;

            testLogger.Reset();
            Func <IList <SonarQubeIssue> > serviceFetchIssuesTask = () =>
            {
                fetchCallCount++;
                throw new ApplicationException("dummy error from mock");
            };

            SetupSolutionBinding(isConnected: true, serviceFetchIssuesTask: serviceFetchIssuesTask);

            RaiseTimerElapsed(DateTime.UtcNow);

            // 3. Fetch issues again - should used cached issues
            matches = issuesProvider.GetSuppressedIssues("projectId", "folder1/file1");
            VerifyServiceGetIssues(Times.Exactly(2));
            matches.Count().Should().Be(1);
            fetchCallCount.Should().Be(1);

            VerifyTimerStart(Times.Exactly(1)); // once, on construction
            testLogger.AssertPartialOutputStrings("Checking for suppressions", "dummy error from mock");
        }
Example #12
0
        public void GetSuppressedIssues_WhenProjectHasModulesAndIssueIsFileLevelAndIsNotFound_ReturnsNoIssue()
        {
            // Arrange
            var sonarQubeIssue1 = new SonarQubeIssue("\\foo\\foo.cs", null, null, "message", "sqkey:sqkey:projectId", "S1", true);
            var sonarQubeIssue2 = new SonarQubeIssue("/foo/foo.cs", null, null, "message", "sqkey:sqkey:projectId", "S2", true);
            var sonarQubeIssue3 = new SonarQubeIssue("foo\\foo.cs", null, null, "message", "sqkey:sqkey:projectId", "S3", true);
            var sonarQubeIssue4 = new SonarQubeIssue("foo/foo.cs", null, null, "message", "sqkey:sqkey:projectId", "S4", true);
            var sonarQubeIssue5 = new SonarQubeIssue("bar/bar.cs", null, null, "message", "sqkey:sqkey:projectId", "S5", true);

            SetupSolutionBinding(true,
                                 new List <SonarQubeIssue> {
                sonarQubeIssue1, sonarQubeIssue2, sonarQubeIssue3, sonarQubeIssue4, sonarQubeIssue5
            },
                                 new List <SonarQubeModule> {
                new SonarQubeModule("sqkey", "", ""), new SonarQubeModule("sqkey:sqkey:projectId", "", "src/bar")
            });

            var issuesProvider = new SonarQubeIssuesProvider(mockSqService.Object, "sqkey", mockTimerFactory.Object, testLogger);

            WaitForInitialFetchTaskToStart();

            VerifyServiceGetIssues(Times.Exactly(1)); // issues should be fetched on creation

            // We're deliberately faking SonarQube returning paths with \ instead of / which
            // the code should handle, but with an assertion since it means the format returned
            // by SonarQube has changed.
            using (new AssertIgnoreScope())
            {
                // Act / Assert - #1 - file extension is not right
                var matches = issuesProvider.GetSuppressedIssues("guid doesn't matter", "C:\\AwesomeProject\\src\\bar\\foo\\foo.vb");
                matches.Should().BeEmpty();

                // Act / Assert - #2 - path is not normalized while comparison is strict for delimiters
                matches = issuesProvider.GetSuppressedIssues("guid doesn't matter", "C:/AwesomeProject/src/bar/foo/foo.cs");
                matches.Should().BeEmpty();

                // Act / Assert - #3 - current file is one level up compared to remote file
                matches = issuesProvider.GetSuppressedIssues("guid doesn't matter", "C:\\AwesomeProject\\src\\bar\\foo.cs");
                matches.Should().BeEmpty();
            }
        }
        public void GetSuppressedIssues_WhenProjectHasModulesAndIssueIsFileLevelAndIsNotFound_ReturnsNoIssue()
        {
            // Arrange
            var issues = new []
            {
                CreateIssue("foo\\foo.cs", "sqkey:sqkey:projectId", "S2"),
                CreateIssue("foo\\foo.cs", "sqkey:sqkey:projectId", "S3"),
                CreateIssue("foo\\foo.cs", "sqkey:sqkey:projectId", "S4"),
                CreateIssue("bar\\bar.cs", "sqkey:sqkey:projectId", "S5"),
            };

            SetupSolutionBinding(true,
                                 issues,
                                 new List <SonarQubeModule> {
                new SonarQubeModule("sqkey", "", ""), new SonarQubeModule("sqkey:sqkey:projectId", "", "src\\bar")
            });

            var issuesProvider = new SonarQubeIssuesProvider(mockSqService.Object, "sqkey", mockTimerFactory.Object, testLogger);

            WaitForInitialFetchTaskToStart();

            VerifyServiceGetIssues(Times.Exactly(1)); // issues should be fetched on creation

            // Act / Assert - #1 - file extension is not right
            var matches = issuesProvider.GetSuppressedIssues("guid doesn't matter", "C:\\AwesomeProject\\src\\bar\\foo\\foo.vb");

            matches.Should().BeEmpty();

            using (new AssertIgnoreScope())
            {
                // Act / Assert - #2 - path is not normalized while comparison is strict for delimiters
                matches = issuesProvider.GetSuppressedIssues("guid doesn't matter", "C:/AwesomeProject/src/bar/foo/foo.cs");
                matches.Should().BeEmpty();
            }

            // Act / Assert - #3 - current file is one level up compared to remote file
            matches = issuesProvider.GetSuppressedIssues("guid doesn't matter", "C:\\AwesomeProject\\src\\bar\\foo.cs");
            matches.Should().BeEmpty();
        }
Example #14
0
        public void GetSuppressedIssues_WhenProjectHasNoModuleAndIssueIsOnAFileAtRootLevelWithNoModules_FalseMatch()
        {
            // On this test we are in an unlikely situation of having an issue suppressed only on a file(1) which is associated
            // with the root module and whose name also exists deeper in the file system hierarchy.
            // (1) If some issue was suppressed for the file deeper in the hierarchy it wouldn't find the wrong match as we
            //     test from the longest matching to the shortest.

            // Arrange
            var sonarQubeIssue1 = new SonarQubeIssue("foo.cs", null, null, "message", "sqkey", "S1", true);
            var sonarQubeIssue2 = new SonarQubeIssue("toto/foo.cs", null, null, "message", "sqkey", "S2", true);

            SetupSolutionBinding(true,
                                 new List <SonarQubeIssue> {
                sonarQubeIssue1, sonarQubeIssue2
            },
                                 new List <SonarQubeModule> {
                new SonarQubeModule("sqkey", "", "")
            });

            var issuesProvider = new SonarQubeIssuesProvider(mockSqService.Object, "sqkey", mockTimerFactory.Object, testLogger);

            WaitForInitialFetchTaskToStart();

            VerifyServiceGetIssues(Times.Exactly(1)); // issues should be fetched on creation

            // Act / Assert - same file name exists at multiple levels in the hierarchy

            // This is the False Match...
            var matches = issuesProvider.GetSuppressedIssues("", "C:\\AwesomeProject\\src\\bar\\foo\\foo.cs");

            matches.Should().HaveCount(1);
            matches.First().RuleId.Should().Be("S1");

            // ... and this is the correct one
            matches = issuesProvider.GetSuppressedIssues("", "C:\\AwesomeProject\\src\\bar\\foo.cs");
            matches.Should().HaveCount(1);
            matches.First().RuleId.Should().Be("S1");
        }
Example #15
0
        public void GetSuppressedIssues_WhenProjectHasNoModulesAndIssueIsOnAFileWhoseRelativePathExistsMultipleTimes_FalseMatch()
        {
            // Arrange
            var sonarQubeIssue1 = new SonarQubeIssue("aaa/foo.cs", null, null, "message", "sqkey", "S1", true);
            var sonarQubeIssue2 = new SonarQubeIssue("toto/foo.cs", null, null, "message", "sqkey", "S2", true);

            SetupSolutionBinding(true,
                                 new List <SonarQubeIssue> {
                sonarQubeIssue1, sonarQubeIssue2
            },
                                 new List <SonarQubeModule> {
                new SonarQubeModule("sqkey", "", "")
            });

            var issuesProvider = new SonarQubeIssuesProvider(mockSqService.Object, "sqkey", mockTimerFactory.Object, testLogger);

            WaitForInitialFetchTaskToStart();

            VerifyServiceGetIssues(Times.Exactly(1)); // issues should be fetched on creation

            // Act / Assert

            // #1 - matches the correct file...
            var matches = issuesProvider.GetSuppressedIssues("", "C:\\aaa\\foo.cs");

            matches.Should().HaveCount(1);
            matches.First().RuleId.Should().Be("S1");

            // #2 - ...but also matches a wrong file deeper in the hierarchy with the same suffix...
            matches = issuesProvider.GetSuppressedIssues("", "C:\\bar\\bar2\\aaa\\foo.cs");
            matches.Should().HaveCount(1);
            matches.First().RuleId.Should().Be("S1");

            // #3 - ... but no match for files upper in the hierarchy.
            matches = issuesProvider.GetSuppressedIssues("", "C:\\foo.cs");
            matches.Should().BeEmpty();
        }
        public void GetIssues_NoIssuesOnServer_ReturnsEmptyList()
        {
            SetupSolutionBinding(isConnected: true, issues: null);

            // 1. Created -> issues fetch in background
            var issuesProvider = new SonarQubeIssuesProvider(mockSqService.Object, "sqKey", mockTimerFactory.Object);

            WaitForInitialFetchTaskToStart();

            VerifyServiceGetIssues(Times.Exactly(1), "sqKey");

            // 2. SonarQube project key doesn't match -> no issues
            var matches = issuesProvider.GetSuppressedIssues("any project", "any file");

            matches.Should().NotBeNull();
            matches.Should().BeEmpty();

            // Cached issues should be used after first fetch. Should not refetch just
            // because the initial fetch returned no items.
            VerifyServiceGetIssues(Times.Exactly(1));
        }
Example #17
0
        public void GetSuppressedIssues_WhenProjectHasModulesAndIssueIsFileLevelAndIsFound_ReturnsExpectedIssue()
        {
            // Arrange
            var sonarQubeIssue1 = new SonarQubeIssue("\\foo\\foo.cs", null, null, "message", "sqkey:sqkey:projectId", "S1", true);
            var sonarQubeIssue2 = new SonarQubeIssue("/foo/foo.cs", null, null, "message", "sqkey:sqkey:projectId", "S2", true);
            var sonarQubeIssue3 = new SonarQubeIssue("foo\\FOO.cs", null, null, "message", "sqkey:sqkey:projectId", "S3", true);
            var sonarQubeIssue4 = new SonarQubeIssue("FOO/foo.cs", null, null, "message", "sqkey:sqkey:projectId", "S4", true);
            var sonarQubeIssue5 = new SonarQubeIssue("bar/bar.cs", null, null, "message", "sqkey:sqkey:projectId", "S5", true);

            SetupSolutionBinding(true,
                                 new List <SonarQubeIssue> {
                sonarQubeIssue1, sonarQubeIssue2, sonarQubeIssue3, sonarQubeIssue4, sonarQubeIssue5
            },
                                 new List <SonarQubeModule> {
                new SonarQubeModule("sqkey", "", ""), new SonarQubeModule("sqkey:sqkey:projectId", "", "src/bar")
            });

            var issuesProvider = new SonarQubeIssuesProvider(mockSqService.Object, "sqkey", mockTimerFactory.Object, testLogger);

            WaitForInitialFetchTaskToStart();

            VerifyServiceGetIssues(Times.Exactly(1)); // issues should be fetched on creation

            // Act
            IEnumerable <SonarQubeIssue> matches;

            // We're deliberately faking SonarQube returning paths with \ instead of / which
            // the code should handle, but with an assertion since it means the format returned
            // by SonarQube has changed.
            using (new AssertIgnoreScope())
            {
                matches = issuesProvider.GetSuppressedIssues("guid doesn't matter", "C:\\AwesomeProject\\src\\bar\\foo\\foo.cs");
            }

            // Assert
            matches.Should().HaveCount(4);
            matches.Should().OnlyContain(x => x.RuleId != "S5");
        }
Example #18
0
        public void GetSuppressedIssues_WhenProjectHasModulesAndIssueIsModuleLevelAndIsNotFound_ReturnsNoIssue()
        {
            // Arrange
            var sonarQubeIssue1 = new SonarQubeIssue(null, null, null, "message", "sqkey:sqkey:projectId2", "S1", true);
            var sonarQubeIssue2 = new SonarQubeIssue("/foo/bar.cs", "hash", 123, "message", "sqkey:sqkey:projectId", "S2", true);
            var sonarQubeIssue3 = new SonarQubeIssue("/foo/bar.cs", "hash", 12, "message", "FOOBAR", "S3", true);

            SetupSolutionBinding(true, new List <SonarQubeIssue> {
                sonarQubeIssue1, sonarQubeIssue2, sonarQubeIssue3
            });

            var issuesProvider = new SonarQubeIssuesProvider(mockSqService.Object, "sqkey", mockTimerFactory.Object, testLogger);

            WaitForInitialFetchTaskToStart();

            VerifyServiceGetIssues(Times.Exactly(1)); // issues should be fetched on creation

            // Act
            var matches = issuesProvider.GetSuppressedIssues("FOOBAR", null);

            // Assert
            matches.Should().BeEmpty();
        }
        public void GetSuppressedIssues_WhenProjectHasModulesAndIssueIsModuleLevelFound_ReturnsExpectedIssue()
        {
            // Arrange
            var sonarQubeIssue1 = CreateIssue(filePath: null, "sqkey:sqkey:projectId2", "S1");
            var sonarQubeIssue2 = CreateIssue(filePath: null, "sqkey:sqkey:projectId", "S2");
            var sonarQubeIssue3 = CreateIssue("foo\\bar.cs", "sqkey:sqkey:projectId", "S3");

            SetupSolutionBinding(true, new List <SonarQubeIssue> {
                sonarQubeIssue1, sonarQubeIssue2, sonarQubeIssue3
            });

            var issuesProvider = new SonarQubeIssuesProvider(mockSqService.Object, "sqkey", mockTimerFactory.Object, testLogger);

            WaitForInitialFetchTaskToStart();

            VerifyServiceGetIssues(Times.Exactly(1)); // issues should be fetched on creation

            // Act
            var matches = issuesProvider.GetSuppressedIssues("projectId", null);

            // Assert
            matches.Should().HaveCount(1);
            matches.First().RuleId.Should().Be("S2");
        }