From 4dc494d58f8aae681a2237a5a6f990e189fb859f Mon Sep 17 00:00:00 2001 From: Michael Clarke Date: Tue, 27 Dec 2022 15:09:41 +0000 Subject: [PATCH] #704: Add support for Sonarqube 9.8 The retrieval of the list of pull requests has been removed from the scanner engine, as well as the issue metrics on the Pull Request web service. The scanner has therefore been altered to implement the updated APIs and drop the classes that implemented the removed interfaces, and the Pull Request web service has had the gathering and population of the issue metrics removed. --- build.gradle | 2 +- .../plugin/CommunityBranchPlugin.java | 5 +- .../CommunityPlatformEditionProvider.java | 37 --- .../CommunityBranchConfigurationLoader.java | 4 +- .../CommunityProjectPullRequestsLoader.java | 126 ---------- .../ws/pullrequest/action/ListAction.java | 24 +- .../plugin/CommunityBranchPluginTest.java | 6 +- .../report/ReportGeneratorTest.java | 2 +- ...ommunityBranchConfigurationLoaderTest.java | 41 ++-- ...unityRepositoryPullRequestsLoaderTest.java | 216 ------------------ .../ws/pullrequest/action/ListActionTest.java | 19 +- 11 files changed, 36 insertions(+), 446 deletions(-) delete mode 100644 src/main/java/com/github/mc1arke/sonarqube/plugin/CommunityPlatformEditionProvider.java delete mode 100644 src/main/java/com/github/mc1arke/sonarqube/plugin/scanner/CommunityProjectPullRequestsLoader.java delete mode 100644 src/test/java/com/github/mc1arke/sonarqube/plugin/scanner/CommunityRepositoryPullRequestsLoaderTest.java diff --git a/build.gradle b/build.gradle index d55ccae6a..e0c606eb8 100644 --- a/build.gradle +++ b/build.gradle @@ -40,7 +40,7 @@ repositories { } } -def sonarqubeVersion = '9.7.0.61563' +def sonarqubeVersion = '9.8.0.63668' def sonarqubeLibDir = "${projectDir}/sonarqube-lib" def sonarLibraries = "${sonarqubeLibDir}/sonarqube-${sonarqubeVersion}/lib" diff --git a/src/main/java/com/github/mc1arke/sonarqube/plugin/CommunityBranchPlugin.java b/src/main/java/com/github/mc1arke/sonarqube/plugin/CommunityBranchPlugin.java index dda863b13..be1822654 100644 --- a/src/main/java/com/github/mc1arke/sonarqube/plugin/CommunityBranchPlugin.java +++ b/src/main/java/com/github/mc1arke/sonarqube/plugin/CommunityBranchPlugin.java @@ -32,7 +32,6 @@ import com.github.mc1arke.sonarqube.plugin.scanner.CommunityBranchConfigurationLoader; import com.github.mc1arke.sonarqube.plugin.scanner.CommunityBranchParamsValidator; import com.github.mc1arke.sonarqube.plugin.scanner.CommunityProjectBranchesLoader; -import com.github.mc1arke.sonarqube.plugin.scanner.CommunityProjectPullRequestsLoader; import com.github.mc1arke.sonarqube.plugin.scanner.ScannerPullRequestPropertySensor; import com.github.mc1arke.sonarqube.plugin.scanner.autoconfiguration.AzureDevopsAutoConfigurer; import com.github.mc1arke.sonarqube.plugin.scanner.autoconfiguration.BitbucketPipelinesAutoConfigurer; @@ -137,7 +136,7 @@ public void load(CoreExtension.Context context) { .category(CoreProperties.CATEGORY_HOUSEKEEPING) .subCategory(CoreProperties.SUBCATEGORY_BRANCHES_AND_PULL_REQUESTS) .multiValues(true) - .defaultValue("master,develop,trunk") + .defaultValue("main,master,develop,trunk") .onQualifiers(Qualifiers.PROJECT) .index(2) .build() @@ -164,7 +163,7 @@ public void load(CoreExtension.Context context) { @Override public void define(Plugin.Context context) { if (SonarQubeSide.SCANNER == context.getRuntime().getSonarQubeSide()) { - context.addExtensions(CommunityProjectBranchesLoader.class, CommunityProjectPullRequestsLoader.class, + context.addExtensions(CommunityProjectBranchesLoader.class, CommunityBranchConfigurationLoader.class, CommunityBranchParamsValidator.class, ScannerPullRequestPropertySensor.class, BranchConfigurationFactory.class, AzureDevopsAutoConfigurer.class, BitbucketPipelinesAutoConfigurer.class, diff --git a/src/main/java/com/github/mc1arke/sonarqube/plugin/CommunityPlatformEditionProvider.java b/src/main/java/com/github/mc1arke/sonarqube/plugin/CommunityPlatformEditionProvider.java deleted file mode 100644 index cb90c21d0..000000000 --- a/src/main/java/com/github/mc1arke/sonarqube/plugin/CommunityPlatformEditionProvider.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2021 Michael Clarke - * - * 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. - * - */ -package com.github.mc1arke.sonarqube.plugin; - -import org.sonar.core.platform.PlatformEditionProvider; - -import java.util.Optional; - -public class CommunityPlatformEditionProvider extends PlatformEditionProvider { - - private final Edition edition; - - public CommunityPlatformEditionProvider(Edition edition) { - this.edition = edition; - } - - @Override - public Optional get() { - return Optional.of(edition); - } -} diff --git a/src/main/java/com/github/mc1arke/sonarqube/plugin/scanner/CommunityBranchConfigurationLoader.java b/src/main/java/com/github/mc1arke/sonarqube/plugin/scanner/CommunityBranchConfigurationLoader.java index 5acbab8c0..7d94f333f 100644 --- a/src/main/java/com/github/mc1arke/sonarqube/plugin/scanner/CommunityBranchConfigurationLoader.java +++ b/src/main/java/com/github/mc1arke/sonarqube/plugin/scanner/CommunityBranchConfigurationLoader.java @@ -29,7 +29,6 @@ import org.sonar.scanner.scan.branch.BranchConfigurationLoader; import org.sonar.scanner.scan.branch.DefaultBranchConfiguration; import org.sonar.scanner.scan.branch.ProjectBranches; -import org.sonar.scanner.scan.branch.ProjectPullRequests; import java.util.Arrays; import java.util.Collections; @@ -70,8 +69,7 @@ public CommunityBranchConfigurationLoader(System2 system2, AnalysisWarnings anal } @Override - public BranchConfiguration load(Map localSettings, ProjectBranches projectBranches, - ProjectPullRequests pullRequests) { + public BranchConfiguration load(Map localSettings, ProjectBranches projectBranches) { List nonEmptyParameters = localSettings.entrySet().stream() .filter(e -> StringUtils.isNotEmpty(e.getValue())) .map(Map.Entry::getKey) diff --git a/src/main/java/com/github/mc1arke/sonarqube/plugin/scanner/CommunityProjectPullRequestsLoader.java b/src/main/java/com/github/mc1arke/sonarqube/plugin/scanner/CommunityProjectPullRequestsLoader.java deleted file mode 100644 index 4728f6d91..000000000 --- a/src/main/java/com/github/mc1arke/sonarqube/plugin/scanner/CommunityProjectPullRequestsLoader.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2020 Michael Clarke - * - * 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. - * - */ -package com.github.mc1arke.sonarqube.plugin.scanner; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import org.sonar.api.utils.MessageException; -import org.sonar.api.utils.log.Logger; -import org.sonar.api.utils.log.Loggers; -import org.sonar.scanner.bootstrap.ScannerWsClient; -import org.sonar.scanner.scan.branch.ProjectPullRequests; -import org.sonar.scanner.scan.branch.ProjectPullRequestsLoader; -import org.sonar.scanner.scan.branch.PullRequestInfo; -import org.sonarqube.ws.client.GetRequest; -import org.sonarqube.ws.client.HttpException; -import org.sonarqube.ws.client.WsResponse; - -import java.io.IOException; -import java.io.Reader; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -/** - * Loads the Pull Requests currently known by SonarQube from the server component for client applications. - * - * @author Michael Clarke - */ -public class CommunityProjectPullRequestsLoader implements ProjectPullRequestsLoader { - - private static final Logger LOGGER = Loggers.get(CommunityProjectPullRequestsLoader.class); - private static final String PROJECT_PULL_REQUESTS_URL = "/api/project_pull_requests/list?project="; - - private final ScannerWsClient scannerWsClient; - private final Gson gson; - - public CommunityProjectPullRequestsLoader(ScannerWsClient scannerWsClient) { - super(); - this.scannerWsClient = scannerWsClient; - this.gson = - new GsonBuilder().registerTypeAdapter(PullRequestInfo.class, createPullRequestInfoJsonDeserialiser()) - .create(); - } - - private static JsonDeserializer createPullRequestInfoJsonDeserialiser() { - return (jsonElement, type, jsonDeserializationContext) -> { - JsonObject jsonObject = jsonElement.getAsJsonObject(); - long parsedDate = 0; - try { - String analysisDate = Optional.ofNullable(jsonObject.get("analysisDate")).map(JsonElement::getAsString).orElse(null); - if(analysisDate == null) { - LOGGER.warn("Analysis Date not provided in Pull Requests API response. Will use '0' date"); - } else { - parsedDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") - .parse(analysisDate).getTime(); - } - } catch (ParseException e) { - LOGGER.warn("Could not parse date from Pull Requests API response. Will use '0' date", e); - } - final String base = Optional.ofNullable(jsonObject.get("base")).map(JsonElement::getAsString).orElse(null); - return new PullRequestInfo(jsonObject.get("key").getAsString(), jsonObject.get("branch").getAsString(), - base, parsedDate); - }; - } - - @Override - public ProjectPullRequests load(String projectKey) { - try { - GetRequest branchesGetRequest = new GetRequest( - PROJECT_PULL_REQUESTS_URL + URLEncoder.encode(projectKey, StandardCharsets.UTF_8.name())); - - try (WsResponse branchesResponse = scannerWsClient - .call(branchesGetRequest); Reader reader = branchesResponse - .contentReader()) { - PullRequestsResponse parsedResponse = gson.fromJson(reader, PullRequestsResponse.class); - return new ProjectPullRequests(parsedResponse.getPullRequests()); - } - } catch (IOException e) { - throw MessageException.of("Could not load pull requests from server", e); - } catch (HttpException e) { - if (404 == e.code()) { - return new ProjectPullRequests(new ArrayList<>()); - } else { - throw MessageException.of("Could not load pull requests from server", e); - } - } - } - - /*package*/ static class PullRequestsResponse { - - private final List pullRequests; - - /*package*/ PullRequestsResponse(List pullRequests) { - super(); - this.pullRequests = pullRequests; - } - - /*package*/ List getPullRequests() { - return pullRequests; - } - } - -} diff --git a/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/pullrequest/action/ListAction.java b/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/pullrequest/action/ListAction.java index a434ee416..1892cc8d0 100644 --- a/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/pullrequest/action/ListAction.java +++ b/src/main/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/pullrequest/action/ListAction.java @@ -23,7 +23,6 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; -import java.util.function.Function; import java.util.stream.Collectors; import javax.annotation.Nullable; @@ -47,8 +46,6 @@ import org.sonar.db.project.ProjectDto; import org.sonar.db.protobuf.DbProjectBranches; import org.sonar.server.component.ComponentFinder; -import org.sonar.server.issue.index.IssueIndex; -import org.sonar.server.issue.index.PrStatistics; import org.sonar.server.user.UserSession; import org.sonar.server.ws.WsUtils; import org.sonarqube.ws.ProjectPullRequests; @@ -59,18 +56,16 @@ public class ListAction extends ProjectWsAction { private final UserSession userSession; - private final IssueIndex issueIndex; private final ProtoBufWriter protoBufWriter; @Autowired - public ListAction(DbClient dbClient, ComponentFinder componentFinder, UserSession userSession, IssueIndex issueIndex) { - this(dbClient, componentFinder, userSession, issueIndex, WsUtils::writeProtobuf); + public ListAction(DbClient dbClient, ComponentFinder componentFinder, UserSession userSession) { + this(dbClient, componentFinder, userSession, WsUtils::writeProtobuf); } - ListAction(DbClient dbClient, ComponentFinder componentFinder, UserSession userSession, IssueIndex issueIndex, ProtoBufWriter protoBufWriter) { + ListAction(DbClient dbClient, ComponentFinder componentFinder, UserSession userSession, ProtoBufWriter protoBufWriter) { super("list", dbClient, componentFinder); this.userSession = userSession; - this.issueIndex = issueIndex; this.protoBufWriter = protoBufWriter; } @@ -96,8 +91,6 @@ public void handleProjectRequest(ProjectDto project, Request request, Response r .collect(Collectors.toList())) .stream().collect(MoreCollectors.uniqueIndex(BranchDto::getUuid)); - Map branchStatisticsByBranchUuid = issueIndex.searchBranchStatistics(project.getUuid(), pullRequestUuids).stream() - .collect(MoreCollectors.uniqueIndex(PrStatistics::getBranchUuid, Function.identity())); Map qualityGateMeasuresByComponentUuids = getDbClient().liveMeasureDao() .selectByComponentUuidsAndMetricKeys(dbSession, pullRequestUuids, List.of(CoreMetrics.ALERT_STATUS_KEY)).stream() .collect(MoreCollectors.uniqueIndex(LiveMeasureDto::getComponentUuid)); @@ -106,7 +99,7 @@ public void handleProjectRequest(ProjectDto project, Request request, Response r ProjectPullRequests.ListWsResponse.Builder protobufResponse = ProjectPullRequests.ListWsResponse.newBuilder(); pullRequests - .forEach(b -> addPullRequest(protobufResponse, b, mergeBranchesByUuid, qualityGateMeasuresByComponentUuids.get(b.getUuid()), branchStatisticsByBranchUuid.get(b.getUuid()), + .forEach(b -> addPullRequest(protobufResponse, b, mergeBranchesByUuid, qualityGateMeasuresByComponentUuids.get(b.getUuid()), analysisDateByBranchUuid.get(b.getUuid()))); protoBufWriter.write(protobufResponse.build(), request, response); } @@ -121,7 +114,7 @@ private static void checkPermission(ProjectDto project, UserSession userSession) } private static void addPullRequest(ProjectPullRequests.ListWsResponse.Builder response, BranchDto branch, Map mergeBranchesByUuid, - @Nullable LiveMeasureDto qualityGateMeasure, PrStatistics prStatistics, @Nullable String analysisDate) { + @Nullable LiveMeasureDto qualityGateMeasure, @Nullable String analysisDate) { Optional mergeBranch = Optional.ofNullable(mergeBranchesByUuid.get(branch.getMergeBranchUuid())); ProjectPullRequests.PullRequest.Builder builder = ProjectPullRequests.PullRequest.newBuilder(); @@ -146,18 +139,15 @@ private static void addPullRequest(ProjectPullRequests.ListWsResponse.Builder re } Optional.ofNullable(analysisDate).ifPresent(builder::setAnalysisDate); - setQualityGate(builder, qualityGateMeasure, prStatistics); + setQualityGate(builder, qualityGateMeasure); response.addPullRequests(builder); } - private static void setQualityGate(ProjectPullRequests.PullRequest.Builder builder, @Nullable LiveMeasureDto qualityGateMeasure, @Nullable PrStatistics prStatistics) { + private static void setQualityGate(ProjectPullRequests.PullRequest.Builder builder, @Nullable LiveMeasureDto qualityGateMeasure) { ProjectPullRequests.Status.Builder statusBuilder = ProjectPullRequests.Status.newBuilder(); if (qualityGateMeasure != null) { Optional.ofNullable(qualityGateMeasure.getDataAsString()).ifPresent(statusBuilder::setQualityGateStatus); } - statusBuilder.setBugs(prStatistics == null ? 0L : prStatistics.getBugs()); - statusBuilder.setVulnerabilities(prStatistics == null ? 0L : prStatistics.getVulnerabilities()); - statusBuilder.setCodeSmells(prStatistics == null ? 0L : prStatistics.getCodeSmells()); builder.setStatus(statusBuilder); } } diff --git a/src/test/java/com/github/mc1arke/sonarqube/plugin/CommunityBranchPluginTest.java b/src/test/java/com/github/mc1arke/sonarqube/plugin/CommunityBranchPluginTest.java index 4fbb27cc0..8ebdc01bd 100644 --- a/src/test/java/com/github/mc1arke/sonarqube/plugin/CommunityBranchPluginTest.java +++ b/src/test/java/com/github/mc1arke/sonarqube/plugin/CommunityBranchPluginTest.java @@ -40,7 +40,7 @@ import com.github.mc1arke.sonarqube.plugin.scanner.CommunityBranchConfigurationLoader; import com.github.mc1arke.sonarqube.plugin.scanner.CommunityBranchParamsValidator; import com.github.mc1arke.sonarqube.plugin.scanner.CommunityProjectBranchesLoader; -import com.github.mc1arke.sonarqube.plugin.scanner.CommunityProjectPullRequestsLoader; +import com.github.mc1arke.sonarqube.plugin.scanner.ScannerPullRequestPropertySensor; import com.github.mc1arke.sonarqube.plugin.server.CommunityBranchFeatureExtension; import com.github.mc1arke.sonarqube.plugin.server.CommunityBranchSupportDelegate; @@ -63,8 +63,8 @@ void shouldDefineClassesForScannerSide() { .addExtensions(argumentCaptor.capture(), argumentCaptor.capture(), argumentCaptor.capture()); - assertThat(argumentCaptor.getAllValues().subList(0, 4)).isEqualTo(Arrays.asList(CommunityProjectBranchesLoader.class, CommunityProjectPullRequestsLoader.class, - CommunityBranchConfigurationLoader.class, CommunityBranchParamsValidator.class)); + assertThat(argumentCaptor.getAllValues().subList(0, 4)).isEqualTo(Arrays.asList(CommunityProjectBranchesLoader.class, + CommunityBranchConfigurationLoader.class, CommunityBranchParamsValidator.class, ScannerPullRequestPropertySensor.class)); } @Test diff --git a/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/report/ReportGeneratorTest.java b/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/report/ReportGeneratorTest.java index 96c90c107..2fcaca3c6 100644 --- a/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/report/ReportGeneratorTest.java +++ b/src/test/java/com/github/mc1arke/sonarqube/plugin/ce/pullrequest/report/ReportGeneratorTest.java @@ -59,7 +59,7 @@ class ReportGeneratorTest { "98, 90.svg?sanitize=true, 1, 3.svg?sanitize=true", ",NoCoverageInfo.svg?sanitize=true,,NoDuplicationInfo.svg?sanitize=true"}) @ParameterizedTest - void shouldProduceCorrectAnlysisSummary(String coverage, String coverageImage, String duplications, String duplicationsImage) { + void shouldProduceCorrectAnalysisSummary(String coverage, String coverageImage, String duplications, String duplicationsImage) { AnalysisDetails analysisDetails = mock(AnalysisDetails.class); doReturn("5").when(analysisDetails).getPullRequestId(); doReturn("projectKey").when(analysisDetails).getAnalysisProjectKey(); diff --git a/src/test/java/com/github/mc1arke/sonarqube/plugin/scanner/CommunityBranchConfigurationLoaderTest.java b/src/test/java/com/github/mc1arke/sonarqube/plugin/scanner/CommunityBranchConfigurationLoaderTest.java index 7312eb828..b749fec85 100644 --- a/src/test/java/com/github/mc1arke/sonarqube/plugin/scanner/CommunityBranchConfigurationLoaderTest.java +++ b/src/test/java/com/github/mc1arke/sonarqube/plugin/scanner/CommunityBranchConfigurationLoaderTest.java @@ -18,19 +18,6 @@ */ package com.github.mc1arke.sonarqube.plugin.scanner; -import org.junit.jupiter.api.Test; -import org.sonar.api.notifications.AnalysisWarnings; -import org.sonar.api.utils.System2; -import org.sonar.scanner.scan.branch.BranchConfiguration; -import org.sonar.scanner.scan.branch.BranchConfigurationLoader; -import org.sonar.scanner.scan.branch.DefaultBranchConfiguration; -import org.sonar.scanner.scan.branch.ProjectBranches; -import org.sonar.scanner.scan.branch.ProjectPullRequests; - -import java.util.List; -import java.util.Map; -import java.util.Optional; - import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.any; @@ -39,6 +26,18 @@ import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import org.junit.jupiter.api.Test; +import org.sonar.api.notifications.AnalysisWarnings; +import org.sonar.api.utils.System2; +import org.sonar.scanner.scan.branch.BranchConfiguration; +import org.sonar.scanner.scan.branch.BranchConfigurationLoader; +import org.sonar.scanner.scan.branch.DefaultBranchConfiguration; +import org.sonar.scanner.scan.branch.ProjectBranches; + /** * @author Michael Clarke */ @@ -57,7 +56,7 @@ void shouldReturnResultFromAutoConfigurerIfPresentAndNoParametersSpecified() { ProjectBranches projectBranches = mock(ProjectBranches.class); - BranchConfiguration actual = testCase.load(Map.of(), projectBranches, mock(ProjectPullRequests.class)); + BranchConfiguration actual = testCase.load(Map.of(), projectBranches); assertThat(actual).isSameAs(branchConfiguration); verify(branchAutoConfigurer).detectConfiguration(system2, projectBranches); @@ -70,7 +69,7 @@ void shouldReturnDefaultBranchIfAutoConfigurerNoResultAndNoParametersSpecified() ProjectBranches projectBranches = mock(ProjectBranches.class); - BranchConfiguration actual = testCase.load(Map.of(), projectBranches, mock(ProjectPullRequests.class)); + BranchConfiguration actual = testCase.load(Map.of(), projectBranches); assertThat(actual).usingRecursiveComparison().isEqualTo(new DefaultBranchConfiguration()); verify(branchAutoConfigurer).detectConfiguration(system2, projectBranches); @@ -83,7 +82,7 @@ void shouldCreateBranchConfigurationIfAnyBranchPropertiesSet() { BranchConfiguration branchConfiguration = mock(BranchConfiguration.class); when(branchConfigurationFactory.createBranchConfiguration(any(), any())).thenReturn(branchConfiguration); - BranchConfiguration actual = testCase.load(Map.of("sonar.branch.name", "branch", "sonar.branch.target", "target"), projectBranches, mock(ProjectPullRequests.class)); + BranchConfiguration actual = testCase.load(Map.of("sonar.branch.name", "branch", "sonar.branch.target", "target"), projectBranches); assertThat(actual).isSameAs(branchConfiguration); verify(branchConfigurationFactory).createBranchConfiguration("branch", projectBranches); @@ -97,7 +96,7 @@ void shouldCreatePullConfigurationIfAnyPullRequestPropertiesSet() { BranchConfiguration branchConfiguration = mock(BranchConfiguration.class); when(branchConfigurationFactory.createPullRequestConfiguration(any(), any(), any(), any())).thenReturn(branchConfiguration); - BranchConfiguration actual = testCase.load(Map.of("sonar.pullrequest.key", "key", "sonar.pullrequest.branch", "source", "sonar.pullrequest.base", "target"), projectBranches, mock(ProjectPullRequests.class)); + BranchConfiguration actual = testCase.load(Map.of("sonar.pullrequest.key", "key", "sonar.pullrequest.branch", "source", "sonar.pullrequest.base", "target"), projectBranches); assertThat(actual).isSameAs(branchConfiguration); verify(branchConfigurationFactory).createPullRequestConfiguration("key", "source", "target", projectBranches); @@ -107,17 +106,17 @@ void shouldCreatePullConfigurationIfAnyPullRequestPropertiesSet() { @Test void shouldThrowErrorIfBothBranchAndPullRequestParametersPresent() { - assertThatThrownBy(() -> testCase.load(Map.of("sonar.pullrequest.key", "key", "sonar.pullrequest.branch", "source", "sonar.branch.name", "branch"), mock(ProjectBranches.class), mock(ProjectPullRequests.class))).hasMessage("sonar.pullrequest and sonar.branch parameters should not be specified in the same scan"); + assertThatThrownBy(() -> testCase.load(Map.of("sonar.pullrequest.key", "key", "sonar.pullrequest.branch", "source", "sonar.branch.name", "branch"), mock(ProjectBranches.class))).hasMessage("sonar.pullrequest and sonar.branch parameters should not be specified in the same scan"); } @Test - void shouldThrowErrorIfPullRequestAnlysisWithoutPullRequestKey() { - assertThatThrownBy(() -> testCase.load(Map.of("sonar.pullrequest.base", "target"), mock(ProjectBranches.class), mock(ProjectPullRequests.class))).hasMessage("sonar.pullrequest.key is required for a pull request analysis"); + void shouldThrowErrorIfPullRequestAnalysisWithoutPullRequestKey() { + assertThatThrownBy(() -> testCase.load(Map.of("sonar.pullrequest.base", "target"), mock(ProjectBranches.class))).hasMessage("sonar.pullrequest.key is required for a pull request analysis"); } @Test void shouldThrowErrorIfPullRequestAnalysisWithoutPullRequestBranch() { - assertThatThrownBy(() -> testCase.load(Map.of("sonar.pullrequest.key", "key"), mock(ProjectBranches.class), mock(ProjectPullRequests.class))).hasMessage("sonar.pullrequest.branch is required for a pull request analysis"); + assertThatThrownBy(() -> testCase.load(Map.of("sonar.pullrequest.key", "key"), mock(ProjectBranches.class))).hasMessage("sonar.pullrequest.branch is required for a pull request analysis"); } } diff --git a/src/test/java/com/github/mc1arke/sonarqube/plugin/scanner/CommunityRepositoryPullRequestsLoaderTest.java b/src/test/java/com/github/mc1arke/sonarqube/plugin/scanner/CommunityRepositoryPullRequestsLoaderTest.java deleted file mode 100644 index 5bd3b9ba4..000000000 --- a/src/test/java/com/github/mc1arke/sonarqube/plugin/scanner/CommunityRepositoryPullRequestsLoaderTest.java +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (C) 2019 Michael Clarke - * - * 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. - * - */ -package com.github.mc1arke.sonarqube.plugin.scanner; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.sonar.api.utils.MessageException; -import org.sonar.scanner.bootstrap.ScannerWsClient; -import org.sonar.scanner.protocol.GsonHelper; -import org.sonar.scanner.scan.branch.ProjectPullRequests; -import org.sonar.scanner.scan.branch.PullRequestInfo; -import org.sonarqube.ws.client.HttpException; -import org.sonarqube.ws.client.WsResponse; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.Reader; -import java.io.StringReader; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -/** - * @author Michael Clarke - */ -public class CommunityRepositoryPullRequestsLoaderTest { - - private final ScannerWsClient scannerWsClient = mock(ScannerWsClient.class); - private final ExpectedException expectedException = ExpectedException.none(); - - @Rule - public ExpectedException expectedException() { - return expectedException; - } - - @Test - public void testEmptyPullRequestsOnEmptyServerResponse() { - WsResponse mockResponse = mock(WsResponse.class); - when(scannerWsClient.call(any())).thenReturn(mockResponse); - - StringReader stringReader = new StringReader(GsonHelper.create() - .toJson(new CommunityProjectPullRequestsLoader.PullRequestsResponse( - new ArrayList<>()))); - when(mockResponse.contentReader()).thenReturn(stringReader); - - CommunityProjectPullRequestsLoader testCase = new CommunityProjectPullRequestsLoader(scannerWsClient); - ProjectPullRequests response = testCase.load("projectKey"); - assertTrue(response.isEmpty()); - } - - @Test - public void testAllPullRequestsFromNonEmptyServerResponse() throws ParseException { - WsResponse mockResponse = mock(WsResponse.class); - when(scannerWsClient.call(any())).thenReturn(mockResponse); - - StringReader stringReader = new StringReader( - "{\"pullRequests\":[{\"key\":\"101\",\"title\":\"dummybranch\",\"branch\":\"dummybranch\",\"base\":\"master\",\"status\":{\"qualityGateStatus\":\"OK\",\"bugs\":0,\"vulnerabilities\":0,\"codeSmells\":0},\"analysisDate\":\"2019-04-04T19:44:27+0100\"}]}"); - when(mockResponse.contentReader()).thenReturn(stringReader); - - CommunityProjectPullRequestsLoader testCase = new CommunityProjectPullRequestsLoader(scannerWsClient); - ProjectPullRequests response = testCase.load("key"); - assertFalse(response.isEmpty()); - - PullRequestInfo responseInfo = response.get("dummybranch"); - assertNotNull(responseInfo); - assertEquals(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").parse("2019-04-04T19:44:27+0100").getTime(), - responseInfo.getAnalysisDate()); - assertEquals("master", responseInfo.getBase()); - assertEquals("dummybranch", responseInfo.getBranch()); - assertEquals("101", responseInfo.getKey()); - } - - @Test - public void testAllPullRequestsFromNonEmptyServerResponseWithInvalidDate() { - WsResponse mockResponse = mock(WsResponse.class); - when(scannerWsClient.call(any())).thenReturn(mockResponse); - - StringReader stringReader = new StringReader( - "{\"pullRequests\":[{\"key\":\"101\",\"title\":\"dummybranch\",\"branch\":\"dummybranch\",\"base\":\"master\",\"status\":{\"qualityGateStatus\":\"OK\",\"bugs\":0,\"vulnerabilities\":0,\"codeSmells\":0},\"analysisDate\":\"\"}]}"); - when(mockResponse.contentReader()).thenReturn(stringReader); - - CommunityProjectPullRequestsLoader testCase = new CommunityProjectPullRequestsLoader(scannerWsClient); - ProjectPullRequests response = testCase.load("key"); - assertFalse(response.isEmpty()); - - PullRequestInfo responseInfo = response.get("dummybranch"); - assertNotNull(responseInfo); - assertEquals(0, responseInfo.getAnalysisDate()); - assertEquals("master", responseInfo.getBase()); - assertEquals("dummybranch", responseInfo.getBranch()); - assertEquals("101", responseInfo.getKey()); - } - - @Test - public void testAllPullRequestsFromNonEmptyServerResponseWithoutBase() { - WsResponse mockResponse = mock(WsResponse.class); - when(scannerWsClient.call(any())).thenReturn(mockResponse); - - StringReader stringReader = new StringReader( - "{\"pullRequests\":[{\"key\":\"101\",\"title\":\"dummybranch\",\"branch\":\"dummybranch\",\"status\":{\"qualityGateStatus\":\"OK\",\"bugs\":0,\"vulnerabilities\":0,\"codeSmells\":0},\"analysisDate\":\"\"}]}"); - when(mockResponse.contentReader()).thenReturn(stringReader); - - CommunityProjectPullRequestsLoader testCase = new CommunityProjectPullRequestsLoader(scannerWsClient); - ProjectPullRequests response = testCase.load("key"); - assertFalse(response.isEmpty()); - - PullRequestInfo responseInfo = response.get("dummybranch"); - assertNotNull(responseInfo); - assertEquals(0, responseInfo.getAnalysisDate()); - assertNull(responseInfo.getBase()); - assertEquals("dummybranch", responseInfo.getBranch()); - assertEquals("101", responseInfo.getKey()); - } - - @Test - public void testAllPullRequestsFromNonEmptyServerResponseWithoutAnalysisDateAndQualityGateStatusForCancelledPr() { - WsResponse mockResponse = mock(WsResponse.class); - when(scannerWsClient.call(any())).thenReturn(mockResponse); - - StringReader stringReader = new StringReader( - "{\"pullRequests\":[{\"key\":\"101\",\"title\":\"dummybranch\",\"branch\":\"dummybranch\",\"base\":\"master\",\"status\":{\"bugs\":0,\"vulnerabilities\":0,\"codeSmells\":0}}]}"); - when(mockResponse.contentReader()).thenReturn(stringReader); - - CommunityProjectPullRequestsLoader testCase = new CommunityProjectPullRequestsLoader(scannerWsClient); - ProjectPullRequests response = testCase.load("key"); - assertFalse(response.isEmpty()); - - PullRequestInfo responseInfo = response.get("dummybranch"); - assertNotNull(responseInfo); - assertEquals(0, - responseInfo.getAnalysisDate()); - assertEquals("master", responseInfo.getBase()); - assertEquals("dummybranch", responseInfo.getBranch()); - assertEquals("101", responseInfo.getKey()); - } - - @Test - public void testMessageExceptionOnIOException() { - WsResponse mockResponse = mock(WsResponse.class); - when(scannerWsClient.call(any())).thenReturn(mockResponse); - - Reader mockReader = new BufferedReader(new StringReader(GsonHelper.create() - .toJson(new CommunityProjectPullRequestsLoader.PullRequestsResponse( - new ArrayList<>())))) { - public void close() throws IOException { - throw new IOException("Dummy IO Exception"); - } - }; - when(mockResponse.contentReader()).thenReturn(mockReader); - - expectedException.expectMessage("Could not load pull requests from server"); - expectedException.expect(MessageException.class); - - CommunityProjectPullRequestsLoader testCase = new CommunityProjectPullRequestsLoader(scannerWsClient); - testCase.load("project"); - - - } - - - @Test - public void testErrorOnNon404HttpResponse() { - WsResponse mockResponse = mock(WsResponse.class); - when(scannerWsClient.call(any())).thenReturn(mockResponse); - - Reader mockReader = new BufferedReader(new StringReader(GsonHelper.create() - .toJson(new CommunityProjectPullRequestsLoader.PullRequestsResponse( - new ArrayList<>())))) { - public void close() { - throw new HttpException("url", 12, "content"); - } - }; - when(mockResponse.contentReader()).thenReturn(mockReader); - - expectedException.expectMessage("Could not load pull requests from server"); - expectedException.expect(MessageException.class); - - CommunityProjectPullRequestsLoader testCase = new CommunityProjectPullRequestsLoader(scannerWsClient); - testCase.load("project"); - } - - - @Test - public void testEmptyListOn404HttpResponse() { - when(scannerWsClient.call(any())).thenThrow(new HttpException("url", 404, "content")); - - CommunityProjectPullRequestsLoader testCase = new CommunityProjectPullRequestsLoader(scannerWsClient); - assertTrue(testCase.load("project").isEmpty()); - } -} diff --git a/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/pullrequest/action/ListActionTest.java b/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/pullrequest/action/ListActionTest.java index 07c29a5ce..0d976d7ca 100644 --- a/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/pullrequest/action/ListActionTest.java +++ b/src/test/java/com/github/mc1arke/sonarqube/plugin/server/pullrequest/ws/pullrequest/action/ListActionTest.java @@ -27,7 +27,6 @@ import static org.mockito.Mockito.when; import java.util.List; -import java.util.Map; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; @@ -44,11 +43,8 @@ import org.sonar.db.measure.LiveMeasureDto; import org.sonar.db.project.ProjectDto; import org.sonar.db.protobuf.DbProjectBranches; -import org.sonar.scanner.protocol.output.ScannerReport; import org.sonar.server.component.ComponentFinder; import org.sonar.server.exceptions.ForbiddenException; -import org.sonar.server.issue.index.IssueIndex; -import org.sonar.server.issue.index.PrStatistics; import org.sonar.server.user.UserSession; import org.sonarqube.ws.ProjectPullRequests; @@ -57,9 +53,8 @@ class ListActionTest { private final DbClient dbClient = mock(DbClient.class); private final UserSession userSession = mock(UserSession.class); private final ComponentFinder componentFinder = mock(ComponentFinder.class); - private final IssueIndex issueIndex = mock(IssueIndex.class); private final ProtoBufWriter protoBufWriter = mock(ProtoBufWriter.class); - private final ListAction underTest = new ListAction(dbClient, componentFinder, userSession, issueIndex, protoBufWriter); + private final ListAction underTest = new ListAction(dbClient, componentFinder, userSession, protoBufWriter); @Test void shouldDefineEndpointWithProjectParameter() { @@ -139,9 +134,6 @@ void shouldExecuteRequestWithValidParameter() { when(dbClient.snapshotDao()).thenReturn(snapshotDao); when(snapshotDao.selectLastAnalysesByRootComponentUuids(any(), any())).thenReturn(List.of(new SnapshotDto().setComponentUuid("componentUuid").setCreatedAt(1234L))); - when(issueIndex.searchBranchStatistics(any(), any())).thenReturn(List.of(new PrStatistics("uuid1", Map.of(ScannerReport.IssueType.BUG.name(), 11L, ScannerReport.IssueType.CODE_SMELL.name(), 22L, ScannerReport.IssueType.VULNERABILITY.name(), 33L)), - new PrStatistics("uuid4", Map.of(ScannerReport.IssueType.BUG.name(), 1L, ScannerReport.IssueType.CODE_SMELL.name(), 2L, ScannerReport.IssueType.VULNERABILITY.name(), 3L)))); - Response response = mock(Response.class); ProjectPullRequests.ListWsResponse expected = ProjectPullRequests.ListWsResponse.newBuilder() @@ -152,9 +144,6 @@ void shouldExecuteRequestWithValidParameter() { .setBase("branch2Key") .setStatus(ProjectPullRequests.Status.newBuilder() .setQualityGateStatus("live measure") - .setBugs(11) - .setVulnerabilities(33) - .setCodeSmells(22) .build()) .setUrl("url") .setTarget("target") @@ -164,9 +153,6 @@ void shouldExecuteRequestWithValidParameter() { .setTitle("title2") .setBranch("prBranch2") .setStatus(ProjectPullRequests.Status.newBuilder() - .setBugs(0) - .setCodeSmells(0) - .setVulnerabilities(0) .build()) .setIsOrphan(true) .setUrl("url2")) @@ -176,9 +162,6 @@ void shouldExecuteRequestWithValidParameter() { .setBranch("prBranch2") .setBase("branch2Key") .setStatus(ProjectPullRequests.Status.newBuilder() - .setBugs(1) - .setVulnerabilities(3) - .setCodeSmells(2) .build()) .setUrl("url3") .setTarget("branch2Key")