-
Notifications
You must be signed in to change notification settings - Fork 77
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0e75982
commit fe5d47f
Showing
5 changed files
with
336 additions
and
148 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
/* | ||
* SonarLint for Visual Studio | ||
* Copyright (C) 2016-2023 SonarSource SA | ||
* mailto:info AT sonarsource DOT com | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU Lesser General Public | ||
* License as published by the Free Software Foundation; either | ||
* version 3 of the License, or (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
* Lesser General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public License | ||
* along with this program; if not, write to the Free Software Foundation, | ||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
*/ | ||
|
||
using System; | ||
using SonarLint.VisualStudio.Core.Suppressions; | ||
using SonarLint.VisualStudio.TestInfrastructure; | ||
using SonarQube.Client.Models; | ||
|
||
namespace SonarLint.VisualStudio.ConnectedMode.UnitTests; | ||
|
||
[TestClass] | ||
public class IssueMatcherTests | ||
{ | ||
[TestMethod] | ||
public void MefCtor_CheckIsExported() | ||
{ | ||
MefTestHelpers.CheckTypeCanBeImported<IssueMatcher, IIssueMatcher>(); | ||
} | ||
|
||
[TestMethod] | ||
public void MefCtor_CheckIsSingleton() | ||
{ | ||
MefTestHelpers.CheckIsSingletonMefComponent<IssueMatcher>(); | ||
} | ||
|
||
[DataTestMethod] | ||
[DataRow("CorrectRuleId", 1, "CorrectHash", true)] // exact matches | ||
[DataRow("correctRULEID", 1, "CorrectHash", true)] // rule-id is case-insensitive | ||
[DataRow("CorrectRuleId", 1, "wrong hash", true)] // matches on line | ||
[DataRow("CorrectRuleId", 9999, "CorrectHash", true)] // matches on hash only | ||
[DataRow("CorrectRuleId", 2, "correcthash", false)] // hash is case-sensitive | ||
[DataRow("CorrectRuleId", 2, "wrong hash", false)] // wrong line and hash | ||
[DataRow("CorrectRuleId", null, null, false)] // server file issue | ||
[DataRow("wrong rule Id", 1, "CorrectHash", false)] | ||
public void IsMatch_MatchesBasedOnAllParameters(string serverRuleId, int? serverIssueLine, | ||
string serverHash, bool expectedResult) | ||
{ | ||
var issueToMatch = CreateIssueToMatch("CorrectRuleId", 1, "CorrectHash"); | ||
var serverIssue = CreateServerIssue(serverRuleId, serverIssueLine, serverHash); | ||
|
||
CreateTestSubject().IsGoodMatch(issueToMatch, serverIssue).Should().Be(expectedResult); | ||
} | ||
|
||
[DataTestMethod] | ||
[DataRow("CorrectRuleId", null, null, true)] // exact matches | ||
[DataRow("CorrectRuleId", null, "hash", true)] // hash should be ignored for file-level issues | ||
[DataRow("WrongRuleId", null, null, false)] // wrong rule | ||
[DataRow("CorrectRuleId", 1, "hash", false)] // not a file issue | ||
[DataRow("CorrectRuleId", 999, null, false)] // not a file issue - should not match a file issue, even though the hash is the same | ||
public void IsMatch_FileLevelIssue(string serverRuleId, int? serverIssueLine, | ||
string serverHash, bool expectedResult) | ||
{ | ||
// File issues have line number of 0 and an empty hash | ||
var issueToMatch = CreateIssueToMatch("CorrectRuleId", null, null); | ||
var serverIssue = CreateServerIssue(serverRuleId, serverIssueLine, serverHash); | ||
|
||
CreateTestSubject().IsGoodMatch(issueToMatch, serverIssue); | ||
} | ||
|
||
[TestMethod] | ||
// Module-level issues i.e. no file | ||
[DataRow(null, null, true)] | ||
[DataRow(null, "", true)] | ||
[DataRow("", null, true)] | ||
[DataRow("", "", true)] | ||
|
||
// Module-level issues should not match non-module-level issues | ||
[DataRow(@"any.txt", "", false)] | ||
[DataRow(@"any.txt", null, false)] | ||
[DataRow("", @"c:\any.txt", false)] | ||
[DataRow(null, @"c:\any.txt", false)] | ||
|
||
// File issues | ||
[DataRow(@"same.txt", @"c:\same.txt", true)] | ||
[DataRow(@"SAME.TXT", @"c:\same.txt", true)] | ||
[DataRow(@"same.TXT", @"c:\XXXsame.txt", false)] // partial file name -> should not match | ||
[DataRow(@"differentExt.123", @"a:\differentExt.999", false)] // different extension -> should not match | ||
[DataRow(@"aaa\partial\file.cs", @"d:\partial\file.cs", false)] | ||
// Only matching the local path tail, so the same server path can match multiple local files | ||
[DataRow(@"partial\file.cs", @"c:\aaa\partial\file.cs", true)] | ||
[DataRow(@"partial\file.cs", @"c:\aaa\bbb\partial\file.cs", true)] | ||
[DataRow(@"partial\file.cs", @"c:\aaa\bbb\ccc\partial\file.cs", true)] | ||
public void IsMatch_CheckFileComparisons(string serverFilePath, string localFilePath, bool expected) | ||
{ | ||
var issueToMatch = CreateIssueToMatch("111", 0, "hash", filePath: localFilePath); | ||
|
||
var serverIssue = CreateServerIssue("111", 0, "hash", filePath: serverFilePath); | ||
|
||
CreateTestSubject().IsGoodMatch(issueToMatch, serverIssue).Should().Be(expected); | ||
} | ||
|
||
[TestMethod] | ||
public void FindMatchOrDefault_FindsFirstMatch() | ||
{ | ||
var ruleId = "111"; | ||
var startLine = 0; | ||
var issueToMatch = CreateIssueToMatch(ruleId, startLine, null, @"c:\root\dir\file.cs"); | ||
var serverPath = @"dir\file.cs"; | ||
|
||
var correctServerIssue = CreateServerIssue(ruleId, startLine, null, serverPath); | ||
|
||
CreateTestSubject().GetFirstMatchFromSameFileOrNull(issueToMatch, new[] | ||
{ | ||
CreateServerIssue("222", startLine, null, serverPath), | ||
CreateServerIssue(ruleId, 111, null, serverPath), | ||
correctServerIssue, | ||
CreateServerIssue(ruleId, startLine, null, serverPath) // finds only the firs match | ||
}).Should().BeSameAs(correctServerIssue); | ||
} | ||
|
||
[TestMethod] | ||
public void FindMatchOrDefault_NoServerIssues_ReturnsNull() | ||
{ | ||
var issueToMatch = CreateIssueToMatch("1", 1, "1"); | ||
|
||
CreateTestSubject().GetFirstMatchFromSameFileOrNull(issueToMatch, Array.Empty<SonarQubeIssue>()).Should().BeNull(); | ||
} | ||
|
||
private IssueMatcher CreateTestSubject() | ||
{ | ||
return new IssueMatcher(); | ||
} | ||
|
||
private IFilterableIssue CreateIssueToMatch(string ruleId, int? startLine, string lineHash, string filePath = null) => | ||
new TestFilterableIssue | ||
{ | ||
RuleId = ruleId, | ||
StartLine = startLine, | ||
LineHash = lineHash, | ||
FilePath = filePath | ||
}; | ||
|
||
private SonarQubeIssue CreateServerIssue(string ruleId, int? startLine, string lineHash, | ||
string filePath = null) | ||
{ | ||
var sonarQubeIssue = new SonarQubeIssue(null, filePath, lineHash, null, null, ruleId, false, SonarQubeIssueSeverity.Info, | ||
DateTimeOffset.MinValue, DateTimeOffset.MinValue, | ||
startLine.HasValue | ||
? new IssueTextRange(startLine.Value, 1, 1, 1) | ||
: null, | ||
flows: null); | ||
|
||
return sonarQubeIssue; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.