]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6019 Fix stickyness of "statuses" facet, protect agains IOOBE
authorJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Wed, 21 Jan 2015 12:26:34 +0000 (13:26 +0100)
committerJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Wed, 21 Jan 2015 12:26:40 +0000 (13:26 +0100)
server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleIndex.java
server/sonar-server/src/main/java/org/sonar/server/search/Result.java
server/sonar-server/src/test/java/org/sonar/server/rule/ws/RulesWebServiceMediumTest.java
server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWebServiceMediumTest/statuses_facet_sticky.json [new file with mode: 0644]

index d63b25dc6d02d0140b8556ce74874ad8aced58f7..f3779a75ec93df1b5e7610fc3379720c3fea2e29 100644 (file)
@@ -377,18 +377,19 @@ public class RuleIndex extends BaseIndex<Rule, RuleDto, RuleKey> {
   private void addStatusFacetIfNeeded(RuleQuery query, QueryContext options, Map<String, AggregationBuilder> aggregations, StickyFacetBuilder stickyFacetBuilder) {
     if (options.facets().contains(FACET_STATUSES)) {
       Collection<RuleStatus> statusesFromQuery = query.getStatuses();
-      Object[] selectedStatuses = statusesFromQuery == null ? new Object[0] : statusesFromQuery.toArray();
 
-      AggregationBuilder statuses = AggregationBuilders.filter(FACET_STATUSES + "__top")
-        .filter(stickyFacetBuilder.getStickyFacetFilter(RuleNormalizer.RuleField.STATUS.field())
-          .mustNot(FilterBuilders.termFilter(RuleNormalizer.RuleField.STATUS.field(), RuleStatus.REMOVED.toString())))
+      BoolFilterBuilder facetFilter = stickyFacetBuilder.getStickyFacetFilter(RuleNormalizer.RuleField.STATUS.field());
+      AggregationBuilder statuses = AggregationBuilders.filter(FACET_STATUSES + "_filter")
+        .filter(facetFilter)
         .subAggregation(
-          AggregationBuilders.terms(FACET_STATUSES + "__values").field(RuleNormalizer.RuleField.STATUS.field()))
-        .subAggregation(
-          AggregationBuilders.terms(FACET_STATUSES + "__selected").field(RuleNormalizer.RuleField.STATUS.field())
-            .include(Joiner.on('|').join(selectedStatuses)));
-
-      aggregations.put(FACET_STATUSES, statuses);
+          AggregationBuilders
+            .terms(FACET_STATUSES)
+            .field(RuleNormalizer.RuleField.STATUS.field())
+            .include(Joiner.on('|').join(ALL_STATUSES_EXCEPT_REMOVED))
+            .exclude(RuleStatus.REMOVED.toString())
+            .size(ALL_STATUSES_EXCEPT_REMOVED.size()));
+
+      aggregations.put(FACET_STATUSES, AggregationBuilders.global(FACET_STATUSES).subAggregation(statuses));
     }
   }
 
index 1a8563cd03bcb1153e2c429887bb48f7fe7d0e4d..448a158fb36ea20aeb22395f6afc01d3889fbe4d 100644 (file)
@@ -83,10 +83,11 @@ public class Result<K> {
     } else if (Terms.class.isAssignableFrom(aggregation.getClass())) {
       Terms termAggregation = (Terms) aggregation;
       for (Terms.Bucket value : termAggregation.getBuckets()) {
-        String facetName = aggregation.getName().replace("_selected", "");
-        if (aggregation.getName().contains("__") && !aggregation.getName().startsWith("__")) {
+        String facetName = aggregation.getName();
+        if (facetName.contains("__") && !facetName.startsWith("__")) {
           facetName = facetName.substring(0, facetName.indexOf("__"));
         }
+        facetName = facetName.replace("_selected", "");
         this.facets.put(facetName, new FacetValue(value.getKey(), value.getDocCount()));
       }
     } else if (HasAggregations.class.isAssignableFrom(aggregation.getClass())) {
index eff12f08eec375d21d1b901249b85309a01e636b..782e4b2f52622b898eb475c346012ab2db59382e 100644 (file)
@@ -25,6 +25,7 @@ import org.junit.Before;
 import org.junit.ClassRule;
 import org.junit.Test;
 import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.RuleStatus;
 import org.sonar.api.rule.Severity;
 import org.sonar.api.server.debt.DebtRemediationFunction;
 import org.sonar.api.server.ws.WebService;
@@ -58,7 +59,9 @@ import static org.assertj.core.api.Assertions.assertThat;
 public class RulesWebServiceMediumTest {
 
   @ClassRule
-  public static ServerTester tester = new ServerTester();
+  public static ServerTester tester = new ServerTester()
+    .setProperty("sonar.log.profilingLevel", "FULL")
+    .setProperty("sonar.search.httpPort", "9010");
 
   private static final String API_ENDPOINT = "api/rules";
   private static final String API_SEARCH_METHOD = "search";
@@ -539,6 +542,19 @@ public class RulesWebServiceMediumTest {
     request.execute().assertJson(this.getClass(), "statuses_facet.json", false);
   }
 
+  @Test
+  public void statuses_facet_should_be_sticky() throws Exception {
+    ruleDao.insert(session, RuleTesting.newXooX1());
+    ruleDao.insert(session, RuleTesting.newXooX2().setStatus(RuleStatus.BETA));
+    ruleDao.insert(session, RuleTesting.newXooX3().setStatus(RuleStatus.DEPRECATED));
+    session.commit();
+
+    WsTester.TestRequest request = tester.wsTester().newGetRequest(API_ENDPOINT, API_SEARCH_METHOD);
+    request.setParam(SearchAction.PARAM_STATUSES, "DEPRECATED");
+    request.setParam(SearchAction.PARAM_FACETS, "statuses");
+    request.execute().assertJson(this.getClass(), "statuses_facet_sticky.json", false);
+  }
+
   @Test
   public void sort_by_name() throws Exception {
     ruleDao.insert(session, RuleTesting.newXooX1().setName("Dodgy - Consider returning a zero length array rather than null "));
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWebServiceMediumTest/statuses_facet_sticky.json b/server/sonar-server/src/test/resources/org/sonar/server/rule/ws/RulesWebServiceMediumTest/statuses_facet_sticky.json
new file mode 100644 (file)
index 0000000..a5b7a79
--- /dev/null
@@ -0,0 +1,20 @@
+{"total": 1, "p": 1, "ps": 100, "rules": [
+  {"key": "xoo:x3"}
+],
+"facets": [
+  {
+    "property": "statuses",
+    "values": [
+      {
+        "val": "BETA",
+        "count": 1
+      },{
+        "val": "DEPRECATED",
+        "count": 1
+      },{
+        "val": "READY",
+        "count": 1
+      }
+    ]
+  }
+]}