diff --git a/src/SLCore.UnitTests/Listener/Analysis/RaiseFindingToAnalysisIssueConverterTests.cs b/src/SLCore.UnitTests/Listener/Analysis/RaiseFindingToAnalysisIssueConverterTests.cs index 52145d9861..2fa04bdb9b 100644 --- a/src/SLCore.UnitTests/Listener/Analysis/RaiseFindingToAnalysisIssueConverterTests.cs +++ b/src/SLCore.UnitTests/Listener/Analysis/RaiseFindingToAnalysisIssueConverterTests.cs @@ -77,7 +77,7 @@ public void GetAnalysisIssues_HasIssues_ConvertsCorrectly() null, null, "context1", - Either.CreateLeft(new(IssueSeverity.MAJOR, RuleType.CODE_SMELL))); + new StandardModeDetails(IssueSeverity.MAJOR, RuleType.CODE_SMELL)); var issue2 = new RaisedIssueDto(Guid.NewGuid(), "serverKey2", "ruleKey2", @@ -89,7 +89,7 @@ public void GetAnalysisIssues_HasIssues_ConvertsCorrectly() [IssueWithFlowsAndQuickFixesUseCase.Issue2Flow1, IssueWithFlowsAndQuickFixesUseCase.Issue2Flow2], [IssueWithFlowsAndQuickFixesUseCase.Issue2Fix1, IssueWithFlowsAndQuickFixesUseCase.Issue2Fix2], "context2", - Either.CreateRight(new (CleanCodeAttribute.COMPLETE, IssueWithFlowsAndQuickFixesUseCase.Issue2Impacts))); + new MQRModeDetails(CleanCodeAttribute.COMPLETE, IssueWithFlowsAndQuickFixesUseCase.Issue2Impacts)); var result = testSubject.GetAnalysisIssues(new FileUri("C:\\IssueFile.cs"), new List { issue1, issue2 }).ToList(); @@ -113,7 +113,7 @@ public void GetAnalysisIssues_HasHotspot_ConvertsCorrectly() "context1", VulnerabilityProbability.HIGH, HotspotStatus.FIXED, - Either.CreateLeft(new(IssueSeverity.MAJOR, RuleType.CODE_SMELL))); + new StandardModeDetails(IssueSeverity.MAJOR, RuleType.CODE_SMELL)); var issue2 = new RaisedHotspotDto(Guid.NewGuid(), "serverKey2", "ruleKey2", @@ -126,7 +126,7 @@ public void GetAnalysisIssues_HasHotspot_ConvertsCorrectly() [IssueWithFlowsAndQuickFixesUseCase.Issue2Fix1, IssueWithFlowsAndQuickFixesUseCase.Issue2Fix2], "context2", VulnerabilityProbability.HIGH, HotspotStatus.FIXED, - Either.CreateRight(new(CleanCodeAttribute.COMPLETE, IssueWithFlowsAndQuickFixesUseCase.Issue2Impacts))); + new MQRModeDetails(CleanCodeAttribute.COMPLETE, IssueWithFlowsAndQuickFixesUseCase.Issue2Impacts)); var result = testSubject.GetAnalysisIssues(new FileUri("C:\\IssueFile.cs"), new List { issue1, issue2 }).ToList(); @@ -152,7 +152,7 @@ public void GetAnalysisIssues_IssueHasUnflattenedFlows_FlattensIntoSingleFlow() UnflattenedFlowsUseCase.UnflattenedFlows, default, default, - Either.CreateLeft(new(default, default))) + new StandardModeDetails(default, default)) }); UnflattenedFlowsUseCase.VerifyFlattenedFlow(analysisIssues); @@ -179,7 +179,7 @@ public void GetAnalysisIssues_HotspotHasUnflattenedFlows_FlattensIntoSingleFlow( default, VulnerabilityProbability.HIGH, HotspotStatus.SAFE, - Either.CreateLeft(new(default, default))) + new StandardModeDetails(default, default)) }); UnflattenedFlowsUseCase.VerifyFlattenedFlow(analysisIssues); @@ -209,7 +209,7 @@ public void GetAnalysisIssues_HotspotHasVulnerabilityProbability_AnalysisHotspot default, vulnerabilityProbability, HotspotStatus.SAFE, - Either.CreateLeft(new(default, default))) + new StandardModeDetails(default, default)) }); analysisIssues.Single().Should().BeOfType().Which.HotspotPriority.Should().Be(expectedHotspotPriority); @@ -236,7 +236,7 @@ public void GetAnalysisIssues_HotspotHasNoVulnerabilityProbability_AnalysisHotsp default, null, HotspotStatus.SAFE, - Either.CreateLeft(new(default, default))) + new StandardModeDetails(default, default)) }); analysisIssues.Single().Should().BeOfType().Which.HotspotPriority.Should().BeNull(); diff --git a/src/SLCore.UnitTests/Listener/Analysis/RaiseIssuesParamsTests.cs b/src/SLCore.UnitTests/Listener/Analysis/RaiseIssuesParamsTests.cs index d02201e2b1..798fd3318d 100644 --- a/src/SLCore.UnitTests/Listener/Analysis/RaiseIssuesParamsTests.cs +++ b/src/SLCore.UnitTests/Listener/Analysis/RaiseIssuesParamsTests.cs @@ -22,7 +22,6 @@ using SonarLint.VisualStudio.SLCore.Common.Models; using SonarLint.VisualStudio.SLCore.Listener.Analysis; using SonarLint.VisualStudio.SLCore.Listener.Analysis.Models; -using SonarLint.VisualStudio.SLCore.Protocol; using SonarLint.VisualStudio.SLCore.Service.Rules.Models; namespace SonarLint.VisualStudio.SLCore.UnitTests.Listener.Analysis; @@ -51,8 +50,7 @@ public void RaisedIssueDto_MqrMode_DeserializedCorrectly() [], [], null, - Either.CreateRight(new MQRModeDetails(CleanCodeAttribute.COMPLETE, - [new ImpactDto(SoftwareQuality.MAINTAINABILITY, ImpactSeverity.LOW)]))) + new MQRModeDetails(CleanCodeAttribute.COMPLETE, [new ImpactDto(SoftwareQuality.MAINTAINABILITY, ImpactSeverity.LOW)])) ] } }, @@ -126,7 +124,7 @@ public void RaisedIssueDto_StandardMode_DeserializedCorrectly() [], [], null, - Either.CreateLeft(new StandardModeDetails(IssueSeverity.BLOCKER, RuleType.BUG))) + new StandardModeDetails(IssueSeverity.BLOCKER, RuleType.BUG)) ] } }, @@ -197,7 +195,7 @@ public void RaiseHotspotParams_MqrMode_DeserializedCorrectly() null, VulnerabilityProbability.HIGH, HotspotStatus.TO_REVIEW, - Either.CreateRight(new MQRModeDetails(CleanCodeAttribute.CLEAR, [new ImpactDto(SoftwareQuality.SECURITY, ImpactSeverity.HIGH)]))) + new MQRModeDetails(CleanCodeAttribute.CLEAR, [new ImpactDto(SoftwareQuality.SECURITY, ImpactSeverity.HIGH)])) ] } }, @@ -275,7 +273,7 @@ public void RaiseHotspotParams_StandardMode_DeserializedCorrectly() null, VulnerabilityProbability.HIGH, HotspotStatus.TO_REVIEW, - Either.CreateLeft(new StandardModeDetails(IssueSeverity.MINOR, RuleType.VULNERABILITY))) + new StandardModeDetails(IssueSeverity.MINOR, RuleType.VULNERABILITY)) ] } }, @@ -324,4 +322,350 @@ public void RaiseHotspotParams_StandardMode_DeserializedCorrectly() deserialized.Should().BeEquivalentTo(expected, options => options.ComparingByMembers().ComparingByMembers().ComparingByMembers()); } + + /// + /// The fields severity, type are still set by SlCore, but they are deprecated and should be ignored. + /// Instead, the values from of should be used + /// + [TestMethod] + public void RaisedIssueDto_StandardMode_IgnoresDeprecatedFields() + { + var expected = new RaiseFindingParams("SLVS_Bound_VS2019", + new Dictionary> + { + { + new FileUri( + "file:///C:/Users/developer/Documents/Repos/sonarlint-visualstudio-sampleprojects%20AAA%20ЖЖЖЖ/bound/sonarcloud/SLVS_Samples_Bound_VS2019/Secrets/ShouldExclude/Excluded.yml"), + [ + new RaisedIssueDto(Guid.Parse("10bd4422-7d55-402f-889c-e080dbe4c781"), + null, + "secrets:S6336", + "Make sure this Alibaba Cloud Access Key Secret gets revoked, changed, and removed from the code.", + DateTimeOffset.FromUnixTimeMilliseconds(1718182975467), + true, + false, + new TextRangeDto(14, 24, 14, 54), + [], + [], + null, + new StandardModeDetails(IssueSeverity.BLOCKER, RuleType.BUG)) + ] + } + }, + false, + Guid.Parse("11ec4b5a-8ff6-4211-ab95-8c16eb8c7f0a")); + + var serialized = + """ + { + "configurationScopeId": "SLVS_Bound_VS2019", + "issuesByFileUri": { + "file:///C:/Users/developer/Documents/Repos/sonarlint-visualstudio-sampleprojects%20AAA%20ЖЖЖЖ/bound/sonarcloud/SLVS_Samples_Bound_VS2019/Secrets/ShouldExclude/Excluded.yml": [ + { + "id": "10bd4422-7d55-402f-889c-e080dbe4c781", + "serverKey": null, + "ruleKey": "secrets:S6336", + "primaryMessage": "Make sure this Alibaba Cloud Access Key Secret gets revoked, changed, and removed from the code.", + "severityMode": { + "severity": "BLOCKER", + "type": "BUG" + }, + "severity": "MINOR", + "type": "CODE_SMELL", + "cleanCodeAttribute": "TRUSTWORTHY", + "impacts": [ + { + "softwareQuality": "SECURITY", + "impactSeverity": "HIGH" + } + ], + "introductionDate": 1718182975467, + "isOnNewCode": true, + "resolved": false, + "textRange": { + "startLine": 14, + "startLineOffset": 24, + "endLine": 14, + "endLineOffset": 54 + }, + "flows": [], + "quickFixes": [], + "ruleDescriptionContextKey": null + } + ] + }, + "isIntermediatePublication": false, + "analysisId": "11ec4b5a-8ff6-4211-ab95-8c16eb8c7f0a" + } + """; + + var deserialized = JsonConvert.DeserializeObject>(serialized); + + deserialized.Should().BeEquivalentTo(expected, options => + options.ComparingByMembers>().ComparingByMembers().ComparingByMembers()); + } + + /// + /// The fields cleanCodeAttribute, impacts are still set by SlCore, but they are deprecated and should be ignored. + /// Instead, the values from of should be used + /// + [TestMethod] + public void RaisedIssueDto_MqrMode_IgnoresDeprecatedFields() + { + var expected = new RaiseFindingParams("SLVS_Bound_VS2019", + new Dictionary> + { + { + new FileUri( + "file:///C:/Users/developer/Documents/Repos/sonarlint-visualstudio-sampleprojects%20AAA%20ЖЖЖЖ/bound/sonarcloud/SLVS_Samples_Bound_VS2019/Secrets/ShouldExclude/Excluded.yml"), + [ + new RaisedIssueDto(Guid.Parse("10bd4422-7d55-402f-889c-e080dbe4c781"), + null, + "secrets:S6336", + "Make sure this Alibaba Cloud Access Key Secret gets revoked, changed, and removed from the code.", + DateTimeOffset.FromUnixTimeMilliseconds(1718182975467), + true, + false, + new TextRangeDto(14, 24, 14, 54), + [], + [], + null, + new MQRModeDetails(CleanCodeAttribute.COMPLETE, [new ImpactDto(SoftwareQuality.MAINTAINABILITY, ImpactSeverity.LOW)])) + ] + } + }, + false, + Guid.Parse("11ec4b5a-8ff6-4211-ab95-8c16eb8c7f0a")); + + var serialized = + """ + { + "configurationScopeId": "SLVS_Bound_VS2019", + "issuesByFileUri": { + "file:///C:/Users/developer/Documents/Repos/sonarlint-visualstudio-sampleprojects%20AAA%20ЖЖЖЖ/bound/sonarcloud/SLVS_Samples_Bound_VS2019/Secrets/ShouldExclude/Excluded.yml": [ + { + "id": "10bd4422-7d55-402f-889c-e080dbe4c781", + "serverKey": null, + "ruleKey": "secrets:S6336", + "primaryMessage": "Make sure this Alibaba Cloud Access Key Secret gets revoked, changed, and removed from the code.", + "severityMode": { + "cleanCodeAttribute": "COMPLETE", + "impacts": [ + { + "softwareQuality": "MAINTAINABILITY", + "impactSeverity": "LOW" + } + ] + }, + "severity": "MINOR", + "type": "CODE_SMELL", + "cleanCodeAttribute": "TRUSTWORTHY", + "impacts": [ + { + "softwareQuality": "SECURITY", + "impactSeverity": "HIGH" + } + ], + "introductionDate": 1718182975467, + "isOnNewCode": true, + "resolved": false, + "textRange": { + "startLine": 14, + "startLineOffset": 24, + "endLine": 14, + "endLineOffset": 54 + }, + "flows": [], + "quickFixes": [], + "ruleDescriptionContextKey": null + } + ] + }, + "isIntermediatePublication": false, + "analysisId": "11ec4b5a-8ff6-4211-ab95-8c16eb8c7f0a" + } + """; + + var deserialized = JsonConvert.DeserializeObject>(serialized); + + deserialized.Should().BeEquivalentTo(expected, options => + options.ComparingByMembers>().ComparingByMembers().ComparingByMembers()); + } + + /// + /// The fields cleanCodeAttribute, impacts are still set by SlCore, but they are deprecated and should be ignored. + /// Instead, the values from of should be used + /// + [TestMethod] + public void RaiseHotspotParams_MqrMode_IgnoresDeprecatedFields() + { + var expected = new RaiseHotspotParams("SLVS_Bound_VS2019", + new Dictionary> + { + { + new FileUri( + "file:///C:/Users/developer/Documents/Repos/sonarlint-visualstudio-sampleprojects%20AAA%20ЖЖЖЖ/bound/sonarcloud/SLVS_Samples_Bound_VS2019/Secrets/ShouldExclude/Excluded.yml"), + [ + new RaisedHotspotDto(Guid.Parse("10bd4422-7d55-402f-889c-e080dbe4c781"), + null, + "secrets:S6336", + "Make sure this Alibaba Cloud Access Key Secret gets revoked, changed, and removed from the code.", + DateTimeOffset.FromUnixTimeMilliseconds(1718182975467), + true, + false, + new TextRangeDto(14, 24, 14, 54), + [], + [], + null, + VulnerabilityProbability.HIGH, + HotspotStatus.TO_REVIEW, + new MQRModeDetails(CleanCodeAttribute.CLEAR, [new ImpactDto(SoftwareQuality.SECURITY, ImpactSeverity.HIGH)])) + ] + } + }, + false, + Guid.Parse("11ec4b5a-8ff6-4211-ab95-8c16eb8c7f0a")); + + var serialized = + """ + { + "configurationScopeId": "SLVS_Bound_VS2019", + "hotspotsByFileUri": { + "file:///C:/Users/developer/Documents/Repos/sonarlint-visualstudio-sampleprojects%20AAA%20ЖЖЖЖ/bound/sonarcloud/SLVS_Samples_Bound_VS2019/Secrets/ShouldExclude/Excluded.yml": [ + { + "id": "10bd4422-7d55-402f-889c-e080dbe4c781", + "serverKey": null, + "ruleKey": "secrets:S6336", + "primaryMessage": "Make sure this Alibaba Cloud Access Key Secret gets revoked, changed, and removed from the code.", + "severityMode": { + "cleanCodeAttribute": "CLEAR", + "impacts": [ + { + "softwareQuality": "SECURITY", + "impactSeverity": "HIGH" + } + ] + }, + "severity": "MINOR", + "type": "CODE_SMELL", + "cleanCodeAttribute": "TRUSTWORTHY", + "impacts": [ + { + "softwareQuality": "RELIABILITY", + "impactSeverity": "LOW" + } + ], + "introductionDate": 1718182975467, + "isOnNewCode": true, + "resolved": false, + "textRange": { + "startLine": 14, + "startLineOffset": 24, + "endLine": 14, + "endLineOffset": 54 + }, + "flows": [], + "quickFixes": [], + "ruleDescriptionContextKey": null, + "vulnerabilityProbability": "HIGH", + "status": "TO_REVIEW" + } + ] + }, + "isIntermediatePublication": false, + "analysisId": "11ec4b5a-8ff6-4211-ab95-8c16eb8c7f0a" + } + """; + + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.Should().BeEquivalentTo(expected, options => + options.ComparingByMembers().ComparingByMembers().ComparingByMembers()); + } + + /// + /// The fields severity, type are still set by SlCore, but they are deprecated and should be ignored. + /// Instead, the values from of should be used + /// + [TestMethod] + public void RaiseHotspotParams_StandardMode_IgnoresDeprecatedFields() + { + var expected = new RaiseHotspotParams("SLVS_Bound_VS2019", + new Dictionary> + { + { + new FileUri( + "file:///C:/Users/developer/Documents/Repos/sonarlint-visualstudio-sampleprojects%20AAA%20ЖЖЖЖ/bound/sonarcloud/SLVS_Samples_Bound_VS2019/Secrets/ShouldExclude/Excluded.yml"), + [ + new RaisedHotspotDto(Guid.Parse("10bd4422-7d55-402f-889c-e080dbe4c781"), + null, + "secrets:S6336", + "Make sure this Alibaba Cloud Access Key Secret gets revoked, changed, and removed from the code.", + DateTimeOffset.FromUnixTimeMilliseconds(1718182975467), + true, + false, + new TextRangeDto(14, 24, 14, 54), + [], + [], + null, + VulnerabilityProbability.HIGH, + HotspotStatus.TO_REVIEW, + new StandardModeDetails(IssueSeverity.MINOR, RuleType.VULNERABILITY)) + ] + } + }, + false, + Guid.Parse("11ec4b5a-8ff6-4211-ab95-8c16eb8c7f0a")); + + var serialized = + """ + { + "configurationScopeId": "SLVS_Bound_VS2019", + "hotspotsByFileUri": { + "file:///C:/Users/developer/Documents/Repos/sonarlint-visualstudio-sampleprojects%20AAA%20ЖЖЖЖ/bound/sonarcloud/SLVS_Samples_Bound_VS2019/Secrets/ShouldExclude/Excluded.yml": [ + { + "id": "10bd4422-7d55-402f-889c-e080dbe4c781", + "serverKey": null, + "ruleKey": "secrets:S6336", + "primaryMessage": "Make sure this Alibaba Cloud Access Key Secret gets revoked, changed, and removed from the code.", + "severityMode": { + "severity": "MINOR", + "type": "VULNERABILITY" + }, + "severity": "INFO", + "type": "SECURITY_HOTSPOT", + "cleanCodeAttribute": "TRUSTWORTHY", + "impacts": [ + { + "softwareQuality": "RELIABILITY", + "impactSeverity": "LOW" + } + ], + "introductionDate": 1718182975467, + "isOnNewCode": true, + "resolved": false, + "textRange": { + "startLine": 14, + "startLineOffset": 24, + "endLine": 14, + "endLineOffset": 54 + }, + "flows": [], + "quickFixes": [], + "ruleDescriptionContextKey": null, + "vulnerabilityProbability": "HIGH", + "status": "TO_REVIEW" + } + ] + }, + "isIntermediatePublication": false, + "analysisId": "11ec4b5a-8ff6-4211-ab95-8c16eb8c7f0a" + } + """; + + var deserialized = JsonConvert.DeserializeObject(serialized); + + deserialized.Should().BeEquivalentTo(expected, options => + options.ComparingByMembers().ComparingByMembers().ComparingByMembers()); + } }