]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-11423 Add details to check run output on issue update
authorJanos Gyerik <janos.gyerik@sonarsource.com>
Mon, 12 Nov 2018 16:03:55 +0000 (17:03 +0100)
committerSonarTech <sonartech@sonarsource.com>
Tue, 8 Jan 2019 19:21:05 +0000 (20:21 +0100)
server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java
server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexTest.java

index b646a926a4d8e1a107078a91f2b1646f40c1c305..8e6db6af587c6aad08764d1927ee55c09ea8056e 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.server.issue.index;
 
 import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Maps;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -93,6 +94,8 @@ import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
 import static org.elasticsearch.index.query.QueryBuilders.rangeQuery;
 import static org.elasticsearch.index.query.QueryBuilders.termQuery;
 import static org.elasticsearch.index.query.QueryBuilders.termsQuery;
+import static org.sonar.api.issue.Issue.STATUS_OPEN;
+import static org.sonar.api.issue.Issue.STATUS_REOPENED;
 import static org.sonar.core.util.stream.MoreCollectors.uniqueIndex;
 import static org.sonar.server.es.BaseDoc.epochMillisToEpochSeconds;
 import static org.sonar.server.es.EsUtils.escapeSpecialRegexChars;
@@ -805,6 +808,27 @@ public class IssueIndex {
       .collect(MoreCollectors.toList(branchUuids.size()));
   }
 
+  public BranchStatistics searchPrStatistics(String projectUuid, String pullRequestUuid) {
+    SearchRequestBuilder request = client.prepareSearch(INDEX_TYPE_ISSUE)
+      .setRouting(projectUuid)
+      .setQuery(
+        boolQuery()
+          .must(termQuery(FIELD_ISSUE_BRANCH_UUID, pullRequestUuid))
+          .mustNot(existsQuery(FIELD_ISSUE_RESOLUTION))
+          .must(termsQuery(FIELD_ISSUE_STATUS, STATUS_OPEN, STATUS_REOPENED))
+          .must(termQuery(FIELD_ISSUE_IS_MAIN_BRANCH, Boolean.toString(false))))
+      .setSize(0)
+      .addAggregation(AggregationBuilders.terms("types").field(FIELD_ISSUE_TYPE));
+
+    ImmutableMap<String, Long> issueCountByType = ((StringTerms) request.get()
+      .getAggregations()
+      .get("types")).getBuckets()
+      .stream()
+      .collect(uniqueIndex(StringTerms.Bucket::getKeyAsString, InternalTerms.Bucket::getDocCount));
+
+    return new BranchStatistics(pullRequestUuid, issueCountByType);
+  }
+
   public List<SecurityStandardCategoryStatistics> getSansTop25Report(String projectUuid, boolean isViewOrApp, boolean includeCwe) {
     SearchRequestBuilder request = prepareNonClosedVulnerabilitiesAndHotspotSearch(projectUuid, isViewOrApp);
     Stream.of(SANS_TOP_25_INSECURE_INTERACTION, SANS_TOP_25_RISKY_RESOURCE, SANS_TOP_25_POROUS_DEFENSES).forEach(sansCategory -> {
index cb5c4ef44cabe236a360124f33713b004bbbfcf9..7531fb233005e97ab9a24079ac0590d9e66a5de8 100644 (file)
@@ -21,6 +21,9 @@ package org.sonar.server.issue.index;
 
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterators;
+import com.tngtech.java.junit.dataprovider.DataProvider;
+import com.tngtech.java.junit.dataprovider.DataProviderRunner;
+import com.tngtech.java.junit.dataprovider.UseDataProvider;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -32,6 +35,7 @@ import org.elasticsearch.search.SearchHit;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
 import org.sonar.api.issue.Issue;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.internal.TestSystem2;
@@ -61,7 +65,15 @@ import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.entry;
 import static org.assertj.core.api.Assertions.tuple;
 import static org.junit.rules.ExpectedException.none;
+import static org.sonar.api.issue.Issue.RESOLUTION_FALSE_POSITIVE;
 import static org.sonar.api.issue.Issue.RESOLUTION_FIXED;
+import static org.sonar.api.issue.Issue.RESOLUTION_REMOVED;
+import static org.sonar.api.issue.Issue.RESOLUTION_WONT_FIX;
+import static org.sonar.api.issue.Issue.STATUS_CLOSED;
+import static org.sonar.api.issue.Issue.STATUS_CONFIRMED;
+import static org.sonar.api.issue.Issue.STATUS_OPEN;
+import static org.sonar.api.issue.Issue.STATUS_REOPENED;
+import static org.sonar.api.issue.Issue.STATUS_RESOLVED;
 import static org.sonar.api.resources.Qualifiers.PROJECT;
 import static org.sonar.api.rules.RuleType.BUG;
 import static org.sonar.api.rules.RuleType.CODE_SMELL;
@@ -73,6 +85,7 @@ import static org.sonar.db.user.GroupTesting.newGroupDto;
 import static org.sonar.db.user.UserTesting.newUserDto;
 import static org.sonar.server.issue.IssueDocTesting.newDoc;
 
+@RunWith(DataProviderRunner.class)
 public class IssueIndexTest {
 
   @Rule
@@ -332,6 +345,47 @@ public class IssueIndexTest {
     assertThat(underTest.searchBranchStatistics(project.uuid(), singletonList("unknown"))).isEmpty();
   }
 
+  @Test
+  @UseDataProvider("resolutionAndStatusAndExpectedCount")
+  public void searchPrStatistics_finds_unresolved_and_unconfirmed_issues(String status, String resolution, long expectedCount) {
+    ComponentDto project = db.components().insertMainBranch();
+    ComponentDto pr = db.components().insertProjectBranch(project);
+    ComponentDto fileOnPr = db.components().insertComponent(newFileDto(pr));
+    indexIssues(newDoc(project),
+      newDoc(pr).setType(BUG).setStatus(status).setResolution(resolution),
+      newDoc(pr).setType(VULNERABILITY).setStatus(status).setResolution(resolution),
+      newDoc(pr).setType(CODE_SMELL).setStatus(status).setResolution(resolution),
+      newDoc(fileOnPr).setType(BUG).setStatus(status).setResolution(resolution),
+      newDoc(fileOnPr).setType(VULNERABILITY).setStatus(status).setResolution(resolution),
+      newDoc(fileOnPr).setType(CODE_SMELL).setStatus(status).setResolution(resolution)
+    );
+
+    BranchStatistics branchStatistics = underTest.searchPrStatistics(project.uuid(), pr.uuid());
+
+    assertThat(branchStatistics)
+      .extracting(
+        BranchStatistics::getBranchUuid,
+        BranchStatistics::getBugs,
+        BranchStatistics::getVulnerabilities,
+        BranchStatistics::getCodeSmells
+      ).containsExactly(pr.uuid(), expectedCount, expectedCount, expectedCount);
+  }
+
+  @DataProvider
+  public static Object[][] resolutionAndStatusAndExpectedCount() {
+    return new Object[][] {
+      {STATUS_OPEN, null, 2},
+      {STATUS_REOPENED, null, 2},
+      {STATUS_CONFIRMED, null, 0},
+      {STATUS_RESOLVED, null, 0},
+      {STATUS_CLOSED, null, 0},
+      {STATUS_RESOLVED, RESOLUTION_FIXED, 0},
+      {STATUS_RESOLVED, RESOLUTION_FALSE_POSITIVE, 0},
+      {STATUS_RESOLVED, RESOLUTION_WONT_FIX, 0},
+      {STATUS_RESOLVED, RESOLUTION_REMOVED, 0},
+    };
+  }
+
   private void addIssues(ComponentDto component, int bugs, int vulnerabilities, int codeSmelles) {
     List<IssueDoc> issues = new ArrayList<>();
     IntStream.range(0, bugs).forEach(b -> issues.add(newDoc(component).setType(BUG).setResolution(null)));