Skip to content

Commit

Permalink
SLVS-1628 Remove taint related methods from SonarQubeService (#5833)
Browse files Browse the repository at this point in the history
  • Loading branch information
georgii-borovinskikh-sonarsource authored Nov 15, 2024
1 parent 102e546 commit 9be04ab
Show file tree
Hide file tree
Showing 16 changed files with 757 additions and 3,080 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ public async Task InvokeAsync_FilePathNormalized()
BaseAddress = new Uri(ValidBaseAddress)
};

// the contents of the json below were left untouched during the cleanup of the taint related methods & requests of SonarQube.Client
// because they still represent a valid issue format (with flows and secondary locations),
// while the fact that the contents have mentions of taint in them is irrelevant for this test
var request = $"api/issues/search?projects={projectKey}&statuses={expectedEscapedStatusesInRequest}&p=1&ps=500";
const string response = @"
{
Expand Down Expand Up @@ -138,6 +141,9 @@ public async Task InvokeAsync_ResponseWithFlows_IsDeserializedCorrectly()
BaseAddress = new Uri(ValidBaseAddress)
};

// the contents of the json below were left untouched during the cleanup of the taint related methods & requests of SonarQube.Client
// because they still represent a valid issue format (with flows and secondary locations),
// while the fact that the contents have mentions of taint in them is irrelevant for this test
var request = $"api/issues/search?projects={projectKey}&statuses={expectedEscapedStatusesInRequest}&p=1&ps=500";
const string response = @"
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,142 +18,135 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using SonarQube.Client.Api;
using SonarQube.Client.Api.V7_20;
using SonarQube.Client.Tests.Infra;
using static SonarQube.Client.Tests.Infra.MocksHelper;

namespace SonarQube.Client.Tests.Requests.Api.V7_20
namespace SonarQube.Client.Tests.Requests.Api.V7_20;

[TestClass]
public class GetIssuesRequestWrapperTests
{
[TestClass]
public class GetIssuesRequestWrapperTests
private const string ComponentPropertyNameSonarQube = "components";
private const string ComponentPropertyNameSonarCloud = "componentKeys";

[DataTestMethod]
[DataRow(ComponentPropertyNameSonarQube, DisplayName = "SonarQube")]
[DataRow(ComponentPropertyNameSonarCloud, DisplayName = "SonarCloud")]
public async Task InvokeAsync_NoIssueKeys_ExpectedPropertiesArePassedInMultipleRequests(string componentPropertyName)
{
private const string ComponentPropertyNameSonarQube = "components";
private const string ComponentPropertyNameSonarCloud = "componentKeys";

[DataTestMethod]
[DataRow(ComponentPropertyNameSonarQube, DisplayName = "SonarQube")]
[DataRow(ComponentPropertyNameSonarCloud, DisplayName = "SonarCloud")]
public async Task InvokeAsync_NoIssueKeys_ExpectedPropertiesArePassedInMultipleRequests(string componentPropertyName)
var testSubject = CreateTestSubject(componentPropertyName, "aaaProject", "xStatus", "yBranch", null, "rule1", "component1");

var handlerMock = new Mock<HttpMessageHandler>(MockBehavior.Strict);
var httpClient = new HttpClient(handlerMock.Object)
{
var testSubject = CreateTestSubject(componentPropertyName, "aaaProject", "xStatus", "yBranch", null, "rule1", "component1");
BaseAddress = new Uri(ValidBaseAddress)
};

var handlerMock = new Mock<HttpMessageHandler>(MockBehavior.Strict);
var httpClient = new HttpClient(handlerMock.Object)
{
BaseAddress = new Uri(ValidBaseAddress)
};
SetupHttpRequest(handlerMock, EmptyGetIssuesResponse);

SetupHttpRequest(handlerMock, EmptyGetIssuesResponse);
_ = await testSubject.InvokeAsync(httpClient, CancellationToken.None);

_ = await testSubject.InvokeAsync(httpClient, CancellationToken.None);
// The wrapper is expected to make three calls, for code smells, bugs, then vulnerabilities
handlerMock.Invocations.Count.Should().Be(2);
CheckExpectedQueryStringsParameters(componentPropertyName, handlerMock, 0, expectedTypes: "CODE_SMELL");
CheckExpectedQueryStringsParameters(componentPropertyName, handlerMock, 1, expectedTypes: "BUG");
}

// The wrapper is expected to make three calls, for code smells, bugs, then vulnerabilities
handlerMock.Invocations.Count.Should().Be(3);
CheckExpectedQueryStringsParameters(componentPropertyName, handlerMock, 0, expectedTypes: "CODE_SMELL");
CheckExpectedQueryStringsParameters(componentPropertyName, handlerMock, 1, expectedTypes: "BUG");
CheckExpectedQueryStringsParameters(componentPropertyName, handlerMock, 2, expectedTypes: "VULNERABILITY");
}
[DataTestMethod]
[DataRow(ComponentPropertyNameSonarQube, DisplayName = "SonarQube")]
[DataRow(ComponentPropertyNameSonarCloud, DisplayName = "SonarCloud")]
public async Task InvokeAsync_HasIssueKeys_ExpectedPropertiesArePassedInASingleRequest(string componentPropertyName)
{
var issueKeys = new[] { "issue1", "issue2" };
var testSubject = CreateTestSubject(componentPropertyName,"aaaProject", "xStatus", "yBranch", issueKeys, "rule1", "component1");

[DataTestMethod]
[DataRow(ComponentPropertyNameSonarQube, DisplayName = "SonarQube")]
[DataRow(ComponentPropertyNameSonarCloud, DisplayName = "SonarCloud")]
public async Task InvokeAsync_HasIssueKeys_ExpectedPropertiesArePassedInASingleRequest(string componentPropertyName)
var handlerMock = new Mock<HttpMessageHandler>(MockBehavior.Strict);
var httpClient = new HttpClient(handlerMock.Object)
{
var issueKeys = new[] { "issue1", "issue2" };
var testSubject = CreateTestSubject(componentPropertyName,"aaaProject", "xStatus", "yBranch", issueKeys, "rule1", "component1");
BaseAddress = new Uri(ValidBaseAddress)
};

var handlerMock = new Mock<HttpMessageHandler>(MockBehavior.Strict);
var httpClient = new HttpClient(handlerMock.Object)
{
BaseAddress = new Uri(ValidBaseAddress)
};
SetupHttpRequest(handlerMock, EmptyGetIssuesResponse);

SetupHttpRequest(handlerMock, EmptyGetIssuesResponse);
_ = await testSubject.InvokeAsync(httpClient, CancellationToken.None);

_ = await testSubject.InvokeAsync(httpClient, CancellationToken.None);
// The wrapper is expected to make one call with the given issueKeys
handlerMock.Invocations.Count.Should().Be(1);

// The wrapper is expected to make one call with the given issueKeys
handlerMock.Invocations.Count.Should().Be(1);

CheckExpectedQueryStringsParameters(componentPropertyName, handlerMock, 0, expectedKeys: issueKeys);
}

private static IGetIssuesRequest CreateTestSubject(string componentPropertyName, string projectKey, string statusesToRequest, string branch, string[] issueKeys, string ruleId, string componentKey)
{
return componentPropertyName switch
{
ComponentPropertyNameSonarQube => new GetIssuesRequestWrapper<GetIssuesWithComponentSonarQubeRequest>
{
Logger = new TestLogger(),
ProjectKey = projectKey,
Statuses = statusesToRequest,
Branch = branch,
IssueKeys = issueKeys,
RuleId = ruleId,
ComponentKey = componentKey
},
ComponentPropertyNameSonarCloud => new GetIssuesRequestWrapper<GetIssuesWithComponentSonarCloudRequest>
{
Logger = new TestLogger(),
ProjectKey = projectKey,
Statuses = statusesToRequest,
Branch = branch,
IssueKeys = issueKeys,
RuleId = ruleId,
ComponentKey = componentKey
},
_ => throw new ArgumentOutOfRangeException()
};
}
CheckExpectedQueryStringsParameters(componentPropertyName, handlerMock, 0, expectedKeys: issueKeys);
}

private static void CheckExpectedQueryStringsParameters(string componentKeyName,
Mock<HttpMessageHandler> handlerMock,
int invocationIndex,
string expectedTypes = null,
string[] expectedKeys = null)
private static IGetIssuesRequest CreateTestSubject(string componentPropertyName, string projectKey, string statusesToRequest, string branch, string[] issueKeys, string ruleId, string componentKey)
{
return componentPropertyName switch
{
var actualQueryString = GetActualQueryStringForInvocation(handlerMock, invocationIndex);

Console.WriteLine($"Invocation [{invocationIndex}]: {actualQueryString}");
actualQueryString.Contains($"?{componentKeyName}=component1").Should().BeTrue();
actualQueryString.Contains("&projects=aaaProject").Should().BeTrue();
actualQueryString.Contains("&statuses=xStatus").Should().BeTrue();
actualQueryString.Contains("&branch=yBranch").Should().BeTrue();
actualQueryString.Contains("&rules=rule1").Should().BeTrue();

if (expectedTypes != null)
ComponentPropertyNameSonarQube => new GetIssuesRequestWrapper<GetIssuesWithComponentSonarQubeRequest>
{
actualQueryString.Contains($"&types={expectedTypes}").Should().BeTrue();
}
else
Logger = new TestLogger(),
ProjectKey = projectKey,
Statuses = statusesToRequest,
Branch = branch,
IssueKeys = issueKeys,
RuleId = ruleId,
ComponentKey = componentKey
},
ComponentPropertyNameSonarCloud => new GetIssuesRequestWrapper<GetIssuesWithComponentSonarCloudRequest>
{
actualQueryString.Contains("types").Should().BeFalse();
}
Logger = new TestLogger(),
ProjectKey = projectKey,
Statuses = statusesToRequest,
Branch = branch,
IssueKeys = issueKeys,
RuleId = ruleId,
ComponentKey = componentKey
},
_ => throw new ArgumentOutOfRangeException()
};
}

if (expectedKeys != null)
{
var keys = string.Join("%2C", expectedKeys);
actualQueryString.Contains($"&issues={keys}").Should().BeTrue();
}
else
{
actualQueryString.Contains("issues").Should().BeFalse();
}
private static void CheckExpectedQueryStringsParameters(string componentKeyName,
Mock<HttpMessageHandler> handlerMock,
int invocationIndex,
string expectedTypes = null,
string[] expectedKeys = null)
{
var actualQueryString = GetActualQueryStringForInvocation(handlerMock, invocationIndex);

Console.WriteLine($"Invocation [{invocationIndex}]: {actualQueryString}");
actualQueryString.Contains($"?{componentKeyName}=component1").Should().BeTrue();
actualQueryString.Contains("&projects=aaaProject").Should().BeTrue();
actualQueryString.Contains("&statuses=xStatus").Should().BeTrue();
actualQueryString.Contains("&branch=yBranch").Should().BeTrue();
actualQueryString.Contains("&rules=rule1").Should().BeTrue();

if (expectedTypes != null)
{
actualQueryString.Contains($"&types={expectedTypes}").Should().BeTrue();
}
else
{
actualQueryString.Contains("types").Should().BeFalse();
}

private static string GetActualQueryStringForInvocation(Mock<HttpMessageHandler> handlerMock, int invocationIndex)
if (expectedKeys != null)
{
var keys = string.Join("%2C", expectedKeys);
actualQueryString.Contains($"&issues={keys}").Should().BeTrue();
}
else
{
var requestMessage = (HttpRequestMessage)handlerMock.Invocations[invocationIndex].Arguments[0];
return requestMessage.RequestUri.Query;
actualQueryString.Contains("issues").Should().BeFalse();
}

}

private static string GetActualQueryStringForInvocation(Mock<HttpMessageHandler> handlerMock, int invocationIndex)
{
var requestMessage = (HttpRequestMessage)handlerMock.Invocations[invocationIndex].Arguments[0];
return requestMessage.RequestUri.Query;
}
}
Loading

0 comments on commit 9be04ab

Please sign in to comment.