aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-server
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@sonarsource.com>2014-05-01 13:48:41 +0200
committerSimon Brandhof <simon.brandhof@sonarsource.com>2014-05-01 13:48:41 +0200
commitb7ded5c1d2dab0359213d3bb9b4ad78eaef874dc (patch)
tree730ea6a26e5388eef088ebe10c823e4860a32344 /sonar-server
parent743cd21fb175ca4f14cd5e85295835c9c743d194 (diff)
downloadsonarqube-b7ded5c1d2dab0359213d3bb9b4ad78eaef874dc.tar.gz
sonarqube-b7ded5c1d2dab0359213d3bb9b4ad78eaef874dc.zip
Drop UnsuportedException and improve rule search
Diffstat (limited to 'sonar-server')
-rw-r--r--sonar-server/src/main/java/org/sonar/server/rule2/RuleDao.java6
-rw-r--r--sonar-server/src/main/java/org/sonar/server/rule2/RuleNormalizer.java2
-rw-r--r--sonar-server/src/main/java/org/sonar/server/rule2/RuleQuery.java33
-rw-r--r--sonar-server/src/main/java/org/sonar/server/rule2/ws/SearchAction.java88
-rw-r--r--sonar-server/src/main/java/org/sonar/server/search/QueryOptions.java52
-rw-r--r--sonar-server/src/main/java/org/sonar/server/ws/WebServiceEngine.java4
-rw-r--r--sonar-server/src/test/java/org/sonar/server/rule2/RuleMediumTest.java227
-rw-r--r--sonar-server/src/test/java/org/sonar/server/rule2/RuleSearchMediumTest.java186
-rw-r--r--sonar-server/src/test/java/org/sonar/server/rule2/RuleServiceMediumTest.java107
-rw-r--r--sonar-server/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java2
10 files changed, 439 insertions, 268 deletions
diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/RuleDao.java b/sonar-server/src/main/java/org/sonar/server/rule2/RuleDao.java
index 87be472f55a..7a7fa10f9b0 100644
--- a/sonar-server/src/main/java/org/sonar/server/rule2/RuleDao.java
+++ b/sonar-server/src/main/java/org/sonar/server/rule2/RuleDao.java
@@ -26,7 +26,6 @@ import org.apache.ibatis.session.SqlSession;
import org.sonar.api.BatchComponent;
import org.sonar.api.ServerComponent;
import org.sonar.api.rule.RuleKey;
-import org.sonar.core.db.UnsuportedException;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
import org.sonar.core.rule.RuleConstants;
@@ -37,7 +36,6 @@ import org.sonar.core.rule.RuleRuleTagDto;
import org.sonar.server.db.BaseDao;
import javax.annotation.CheckForNull;
-
import java.sql.Timestamp;
import java.util.Collection;
import java.util.List;
@@ -77,12 +75,12 @@ public class RuleDao extends BaseDao<RuleDto, RuleKey>
@Override
protected void doDelete(RuleDto item, SqlSession session) {
- throw new UnsuportedException("Rules cannot be deleted");
+ throw new UnsupportedOperationException("Rules cannot be deleted");
}
@Override
protected void doDeleteByKey(RuleKey key, SqlSession session) {
- throw new UnsuportedException("Rules cannot be deleted");
+ throw new UnsupportedOperationException("Rules cannot be deleted");
}
public List<RuleDto> selectAll() {
diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/RuleNormalizer.java b/sonar-server/src/main/java/org/sonar/server/rule2/RuleNormalizer.java
index 27e8a348673..894984a8b3b 100644
--- a/sonar-server/src/main/java/org/sonar/server/rule2/RuleNormalizer.java
+++ b/sonar-server/src/main/java/org/sonar/server/rule2/RuleNormalizer.java
@@ -37,7 +37,7 @@ public class RuleNormalizer extends BaseNormalizer<RuleDto, RuleKey> {
private RuleDao ruleDao;
- public enum RuleField {
+ public static enum RuleField {
KEY("key"),
REPOSITORY("repo"),
NAME("name"),
diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/RuleQuery.java b/sonar-server/src/main/java/org/sonar/server/rule2/RuleQuery.java
index e60fe20540d..258b07d36bf 100644
--- a/sonar-server/src/main/java/org/sonar/server/rule2/RuleQuery.java
+++ b/sonar-server/src/main/java/org/sonar/server/rule2/RuleQuery.java
@@ -30,7 +30,38 @@ import java.util.Collection;
public class RuleQuery {
public static enum SortField {
- NAME, CREATED_AT
+ KEY(RuleNormalizer.RuleField.KEY),
+ REPOSITORY(RuleNormalizer.RuleField.REPOSITORY),
+ NAME(RuleNormalizer.RuleField.NAME),
+ CREATED_AT(RuleNormalizer.RuleField.CREATED_AT),
+ DESCRIPTION(RuleNormalizer.RuleField.DESCRIPTION),
+ SEVERITY(RuleNormalizer.RuleField.SEVERITY),
+ STATUS(RuleNormalizer.RuleField.STATUS),
+ LANGUAGE(RuleNormalizer.RuleField.LANGUAGE);
+
+ private final RuleNormalizer.RuleField field;
+
+ private SortField(RuleNormalizer.RuleField field) {
+ this.field = field;
+ }
+
+ RuleNormalizer.RuleField field() {
+ return field;
+ }
+
+ @Override
+ public String toString() {
+ return field.toString();
+ }
+
+ /**
+ * Same than {@link #valueOf(String)} but returns <code>null</code> if parameter
+ * is <code>null</code>
+ */
+ @CheckForNull
+ public static SortField valueOfOrNull(@Nullable String s) {
+ return s == null ? null : valueOf(s);
+ }
}
private String key;
diff --git a/sonar-server/src/main/java/org/sonar/server/rule2/ws/SearchAction.java b/sonar-server/src/main/java/org/sonar/server/rule2/ws/SearchAction.java
index 25fa57c060a..e78ec9f345a 100644
--- a/sonar-server/src/main/java/org/sonar/server/rule2/ws/SearchAction.java
+++ b/sonar-server/src/main/java/org/sonar/server/rule2/ws/SearchAction.java
@@ -52,9 +52,19 @@ public class SearchAction implements RequestHandler {
private static final String PARAM_SEVERITIES = "severities";
private static final String PARAM_STATUSES = "statuses";
private static final String PARAM_LANGUAGES = "languages";
+ private static final String PARAM_DEBT_CHARACTERISTICS = "debtCharacteristics";
+ private static final String PARAM_HAS_DEBT_CHARACTERISTIC = "hasDebtCharacteristic";
private static final String PARAM_TAGS = "tags";
+ private static final String PARAM_ALL_OF_TAGS = "allOfTags";
+ // generic search parameters
+ private static final String PARAM_PAGE = "p";
+ private static final String PARAM_PAGE_SIZE = "ps";
+ private static final String PARAM_FIELDS = "f";
+ private static final String PARAM_SORT = "s";
+ private static final String PARAM_ASCENDING = "asc";
+
private final RuleService service;
public SearchAction(RuleService service) {
@@ -85,13 +95,33 @@ public class SearchAction implements RequestHandler {
.setExampleValue("CRITICAL,BLOCKER");
action
+ .createParam(PARAM_LANGUAGES)
+ .setDescription("Comma-separated list of languages")
+ .setExampleValue("java,js");
+
+ action
.createParam(PARAM_STATUSES)
.setDescription("Comma-separated list of status codes")
.setPossibleValues(RuleStatus.values())
.setExampleValue(RuleStatus.READY.toString());
action
- .createParam("tags")
+ .createParam(PARAM_DEBT_CHARACTERISTICS)
+ .setDescription("Comma-separated list of technical debt characteristics or sub-characteristics")
+ .setExampleValue("RELIABILITY");
+
+ action
+ .createParam(PARAM_HAS_DEBT_CHARACTERISTIC)
+ .setDescription("Filter rules that have a technical debt characteristic")
+ .setPossibleValues("false", "true");
+
+ action
+ .createParam(PARAM_TAGS)
+ .setDescription("Comma-separated list of tags. Returned rules match any of the tags (OR operator)")
+ .setExampleValue("security,java8");
+
+ action
+ .createParam(PARAM_ALL_OF_TAGS)
.setDescription("Comma-separated list of tags. Returned rules match all the tags (AND operator)")
.setExampleValue("security,java8");
@@ -106,10 +136,34 @@ public class SearchAction implements RequestHandler {
.setExampleValue("java:Sonar way");
action
- .createParam("fields")
+ .createParam(PARAM_FIELDS)
.setDescription("Comma-separated list of the fields to be returned in response. All the fields are returned by default.")
.setPossibleValues(RuleIndex.PUBLIC_FIELDS)
.setExampleValue(String.format("%s,%s,%s", RuleNormalizer.RuleField.KEY, RuleNormalizer.RuleField.REPOSITORY, RuleNormalizer.RuleField.LANGUAGE));
+
+ action
+ .createParam(PARAM_PAGE)
+ .setDescription("1-based page number")
+ .setExampleValue("42")
+ .setDefaultValue("1");
+
+ action
+ .createParam(PARAM_PAGE_SIZE)
+ .setDescription("Page size. Must be greater than 0.")
+ .setExampleValue("10")
+ .setDefaultValue("25");
+
+ // TODO limit the fields to sort on + document possible values + default value ?
+ action
+ .createParam(PARAM_SORT)
+ .setDescription("Sort field")
+ .setExampleValue(RuleNormalizer.RuleField.LANGUAGE.key());
+
+ action
+ .createParam(PARAM_ASCENDING)
+ .setDescription("Ascending sort")
+ .setPossibleValues("false", "true")
+ .setDefaultValue("true");
}
@Override
@@ -120,9 +174,33 @@ public class SearchAction implements RequestHandler {
query.setRepositories(request.paramAsStrings(PARAM_REPOSITORIES));
query.setStatuses(toStatuses(request.paramAsStrings(PARAM_STATUSES)));
query.setLanguages(request.paramAsStrings(PARAM_LANGUAGES));
+ query.setDebtCharacteristics(request.paramAsStrings(PARAM_DEBT_CHARACTERISTICS));
+ query.setHasDebtCharacteristic(request.paramAsBoolean(PARAM_HAS_DEBT_CHARACTERISTIC));
+
+ // TODO move to QueryOptions ?
+ query.setSortField(RuleQuery.SortField.valueOfOrNull(request.param(PARAM_SORT)));
+ query.setAscendingSort(request.paramAsBoolean(PARAM_ASCENDING, true));
+
+ QueryOptions options = new QueryOptions();
+ options.setFieldsToReturn(request.paramAsStrings(PARAM_FIELDS));
+ options.setPage(
+ request.paramAsInt(PARAM_PAGE, 1),
+ request.paramAsInt(PARAM_PAGE_SIZE, 25));
+
+ Results results = service.search(query, options);
+ JsonWriter json = response.newJsonWriter().beginObject();
+ writeStatistics(results, json);
+ writeHits(results, json);
+ json.close();
+ }
+
+ private void writeStatistics(Results results, JsonWriter json) {
+ json.prop("total", results.getTotal());
+ json.prop("time", results.getTime());
+ }
- Results results = service.search(query, new QueryOptions());
- JsonWriter json = response.newJsonWriter().beginObject().name("hits").beginArray();
+ private void writeHits(Results results, JsonWriter json) {
+ json.name("hits").beginArray();
for (Hit hit : results.getHits()) {
json.beginObject();
for (Map.Entry<String, Object> entry : hit.getFields().entrySet()) {
@@ -132,7 +210,7 @@ public class SearchAction implements RequestHandler {
json.endObject();
}
json.endArray();
- json.endObject().close();
+ json.endObject();
}
@CheckForNull
diff --git a/sonar-server/src/main/java/org/sonar/server/search/QueryOptions.java b/sonar-server/src/main/java/org/sonar/server/search/QueryOptions.java
index 19d2719538c..c4a4f242a89 100644
--- a/sonar-server/src/main/java/org/sonar/server/search/QueryOptions.java
+++ b/sonar-server/src/main/java/org/sonar/server/search/QueryOptions.java
@@ -25,6 +25,7 @@ import com.google.common.collect.Sets;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
+import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
@@ -36,15 +37,12 @@ public class QueryOptions {
public static final int DEFAULT_OFFSET = 0;
public static final int DEFAULT_LIMIT = 10;
- public static final boolean DEFAULT_ASCENDING = true;
private int offset = DEFAULT_OFFSET;
private int limit = DEFAULT_LIMIT;
- private boolean ascending = DEFAULT_ASCENDING;
- private String sortField;
private Set<String> fieldsToReturn;
- public QueryOptions(){
+ public QueryOptions() {
fieldsToReturn = new HashSet<String>();
}
@@ -65,6 +63,17 @@ public class QueryOptions {
}
/**
+ * Set offset and limit according to page approach
+ */
+ public QueryOptions setPage(int page, int pageSize) {
+ Preconditions.checkArgument(page > 0, "Page must be positive");
+ Preconditions.checkArgument(pageSize >= 0, "Page size must be positive or greater than 0");
+ this.offset = (page * pageSize) - pageSize;
+ this.limit = pageSize;
+ return this;
+ }
+
+ /**
* Limit on the number of results to return. Defaults to {@link #DEFAULT_LIMIT}.
*/
public int getLimit() {
@@ -79,35 +88,13 @@ public class QueryOptions {
return this;
}
- /**
- * Is ascending sort ? Defaults to {@link #DEFAULT_ASCENDING}
- */
- public boolean isAscending() {
- return ascending;
- }
-
- public QueryOptions setAscending(boolean ascending) {
- this.ascending = ascending;
- return this;
- }
-
- @CheckForNull
- public String getSortField() {
- return sortField;
- }
-
- public QueryOptions setSortField(@Nullable String sortField) {
- this.sortField = sortField;
- return this;
- }
-
@CheckForNull
public Set<String> getFieldsToReturn() {
return fieldsToReturn;
}
- public QueryOptions setFieldsToReturn(@Nullable Set<String> c) {
- this.fieldsToReturn = c;
+ public QueryOptions setFieldsToReturn(@Nullable Collection<String> c) {
+ this.fieldsToReturn = (c == null ? null : Sets.newHashSet(c));
return this;
}
@@ -122,6 +109,15 @@ public class QueryOptions {
return this;
}
+ public QueryOptions addFieldsToReturn(String... c) {
+ if (fieldsToReturn == null) {
+ fieldsToReturn = Sets.newHashSet(c);
+ } else {
+ fieldsToReturn.addAll(Arrays.asList(c));
+ }
+ return this;
+ }
+
public QueryOptions filterFieldsToReturn(final Set<String> keep) {
if (fieldsToReturn == null) {
fieldsToReturn = keep;
diff --git a/sonar-server/src/main/java/org/sonar/server/ws/WebServiceEngine.java b/sonar-server/src/main/java/org/sonar/server/ws/WebServiceEngine.java
index f566c4d75c8..b46bcd8134e 100644
--- a/sonar-server/src/main/java/org/sonar/server/ws/WebServiceEngine.java
+++ b/sonar-server/src/main/java/org/sonar/server/ws/WebServiceEngine.java
@@ -126,7 +126,9 @@ public class WebServiceEngine implements ServerComponent, Startable {
public String param(String key) {
Param paramDef = action.param(key);
if (paramDef == null) {
- throw new BadRequestException(String.format("Parameter '%s' is undefined for action '%s'", key, action.key()));
+ String message = String.format("BUG - parameter '%s' is undefined for action '%s'", key, action.key());
+ LoggerFactory.getLogger(getClass()).error(message);
+ throw new IllegalStateException(message);
}
String value = StringUtils.defaultString(super.param(key), paramDef.defaultValue());
diff --git a/sonar-server/src/test/java/org/sonar/server/rule2/RuleMediumTest.java b/sonar-server/src/test/java/org/sonar/server/rule2/RuleMediumTest.java
deleted file mode 100644
index 6a1895150b0..00000000000
--- a/sonar-server/src/test/java/org/sonar/server/rule2/RuleMediumTest.java
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube 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.
- *
- * SonarQube 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 org.sonar.server.rule2;
-
-import com.google.common.collect.Iterables;
-import com.sun.org.apache.xerces.internal.util.SynchronizedSymbolTable;
-import org.junit.After;
-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.utils.DateUtils;
-import org.sonar.check.Cardinality;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.MyBatis;
-import org.sonar.core.rule.RuleDto;
-import org.sonar.server.search.Hit;
-import org.sonar.server.search.QueryOptions;
-import org.sonar.server.search.Results;
-import org.sonar.server.tester.ServerTester;
-
-import java.util.Arrays;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-public class RuleMediumTest {
-
- @ClassRule
- public static ServerTester tester = new ServerTester();
-
- @After
- public void clear_data_store() {
- tester.clearDataStores();
- }
-
- @Test
- public void insert_in_db_and_index_in_es() {
- // insert db
- RuleKey ruleKey = RuleKey.of("javascript", "S001");
- RuleDao dao = tester.get(RuleDao.class);
- dao.insert(newRuleDto(ruleKey));
-
- // verify that rule is persisted in db
- RuleDto persistedDto = dao.selectByKey(ruleKey);
- assertThat(persistedDto).isNotNull();
- assertThat(persistedDto.getId()).isGreaterThanOrEqualTo(0);
- assertThat(persistedDto.getRuleKey()).isEqualTo(ruleKey.rule());
- assertThat(persistedDto.getLanguage()).isEqualTo("js");
-
- // verify that rule is indexed in es
- RuleIndex index = tester.get(RuleIndex.class);
- index.refresh();
-
- Hit hit = index.getByKey(ruleKey);
- assertThat(hit).isNotNull();
- assertThat(hit.getFieldAsString(RuleNormalizer.RuleField.REPOSITORY.key())).isEqualTo(ruleKey.repository());
- assertThat(hit.getFieldAsString(RuleNormalizer.RuleField.KEY.key())).isEqualTo(ruleKey.rule());
- assertThat(hit.getFieldAsString(RuleNormalizer.RuleField.LANGUAGE.key())).isEqualTo("js");
- assertThat(hit.getFieldAsString(RuleNormalizer.RuleField.NAME.key())).isEqualTo("Rule S001");
- assertThat(hit.getFieldAsString(RuleNormalizer.RuleField.DESCRIPTION.key())).isEqualTo("Description S001");
- assertThat(hit.getFieldAsString(RuleNormalizer.RuleField.STATUS.key())).isEqualTo(RuleStatus.READY.toString());
- }
-
- @Test
- public void search_rule_field_allowed(){
- String lang = "java";
-
- RuleDao dao = tester.get(RuleDao.class);
- dao.insert(newRuleDto(RuleKey.of("javascript", "S001"))
- .setLanguage(lang));
-
- RuleService service = tester.get(RuleService.class).refresh();
-
- RuleQuery query = service.newRuleQuery();
-
- QueryOptions options = new QueryOptions();
- options.getFieldsToReturn().add(RuleNormalizer.RuleField.LANGUAGE.key());
-
- Results results = service.search(query, options);
-
- assertThat(results.getTotal()).isEqualTo(1);
- assertThat(results.getHits()).hasSize(1);
- assertThat(Iterables.getFirst(results.getHits(), null).getFieldAsString("key")).isEqualTo("S001");
- assertThat(Iterables.getFirst(results.getHits(), null)
- .getFieldAsString(RuleNormalizer.RuleField.LANGUAGE.key()))
- .isNotNull();
- assertThat(Iterables.getFirst(results.getHits(), null)
- .getFieldAsString(RuleNormalizer.RuleField.LANGUAGE.key()))
- .isEqualTo(lang);
- }
-
- @Test
- public void search_rule_no_field_selected() {
- String lang = "java";
-
- RuleDao dao = tester.get(RuleDao.class);
- dao.insert(newRuleDto(RuleKey.of("javascript", "S001"))
- .setLanguage(lang));
-
- RuleService service = tester.get(RuleService.class).refresh();
-
- RuleQuery query = service.newRuleQuery();
-
- QueryOptions options = new QueryOptions();
-
- Results results = service.search(query, options);
-
- assertThat(results.getTotal()).isEqualTo(1);
- assertThat(results.getHits()).hasSize(1);
- assertThat(Iterables.getFirst(results.getHits(), null).getFieldAsString("key")).isEqualTo("S001");
- assertThat(Iterables.getFirst(results.getHits(), null)
- .getFieldAsString(RuleNormalizer.RuleField.LANGUAGE.key()))
- .isNull();
- }
-
- @Test
- public void search_rule_field_not_allowed(){
- RuleDao dao = tester.get(RuleDao.class);
- dao.insert(newRuleDto(RuleKey.of("javascript", "S001"))
- .setConfigKey("I should not see this"));
-
- RuleService service = tester.get(RuleService.class).refresh();
-
- RuleQuery query = service.newRuleQuery();
- QueryOptions options = new QueryOptions();
- options.getFieldsToReturn().add(RuleNormalizer.RuleField.INTERNAL_KEY.key());
-
- Results results = service.search(query, options);
-
- assertThat(results.getTotal()).isEqualTo(1);
- assertThat(results.getHits()).hasSize(1);
- assertThat(Iterables.getFirst(results.getHits(), null).getFieldAsString("key")).isEqualTo("S001");
- assertThat(Iterables.getFirst(results.getHits(), null)
- .getFieldAsString(RuleNormalizer.RuleField.INTERNAL_KEY.key()))
- .isNull();
- }
-
- @Test
- public void search_rules_partial_match() throws InterruptedException {
- RuleDao dao = tester.get(RuleDao.class);
- dao.insert(newRuleDto(RuleKey.of("javascript", "S001"))
- .setName("testing the partial match and matching of rule"));
-
- RuleService service = tester.get(RuleService.class).refresh();
-
- RuleQuery query = service.newRuleQuery().setQueryText("test");
- Results results = service.search(query, new QueryOptions());
-
- assertThat(results.getTotal()).isEqualTo(1);
- assertThat(results.getHits()).hasSize(1);
- assertThat(Iterables.getFirst(results.getHits(), null).getFieldAsString("key")).isEqualTo("S001");
-
- }
-
-
- @Test
- public void search_rules_no_filters() throws InterruptedException {
- RuleDao dao = tester.get(RuleDao.class);
- dao.insert(newRuleDto(RuleKey.of("javascript", "S001")));
-
- RuleService service = tester.get(RuleService.class).refresh();
-
- RuleQuery query = service.newRuleQuery();
- Results results = service.search(query, new QueryOptions());
-
- assertThat(results.getTotal()).isEqualTo(1);
- assertThat(results.getHits()).hasSize(1);
- assertThat(Iterables.getFirst(results.getHits(), null).getFieldAsString("key")).isEqualTo("S001");
-
- }
-
- @Test
- public void search_rules_by_repositories() throws InterruptedException {
- RuleDao dao = tester.get(RuleDao.class);
- dao.insert(newRuleDto(RuleKey.of("javascript", "S001")));
- dao.insert(newRuleDto(RuleKey.of("java", "S002")));
-
- RuleService service = tester.get(RuleService.class).refresh();
-
- RuleQuery query = service.newRuleQuery().setRepositories(Arrays.asList("findbugs", "java"));
- Results results = service.search(query, new QueryOptions());
-
- assertThat(results.getTotal()).isEqualTo(1);
- assertThat(results.getHits()).hasSize(1);
- assertThat(Iterables.getFirst(results.getHits(), null).getFieldAsString("key")).isEqualTo("S002");
- }
-
- private RuleDto newRuleDto(RuleKey ruleKey) {
- return new RuleDto()
- .setRuleKey(ruleKey.rule())
- .setRepositoryKey(ruleKey.repository())
- .setName("Rule " + ruleKey.rule())
- .setDescription("Description " + ruleKey.rule())
- .setStatus(RuleStatus.READY.toString())
- .setConfigKey("InternalKey" + ruleKey.rule())
- .setSeverity(Severity.INFO)
- .setCardinality(Cardinality.SINGLE)
- .setLanguage("js")
- .setRemediationFunction("linear")
- .setDefaultRemediationFunction("linear_offset")
- .setRemediationCoefficient("1h")
- .setDefaultRemediationCoefficient("5d")
- .setRemediationOffset("5min")
- .setDefaultRemediationOffset("10h")
- .setEffortToFixDescription(ruleKey.repository() + "." + ruleKey.rule() + ".effortToFix")
- .setCreatedAt(DateUtils.parseDate("2013-12-16"))
- .setUpdatedAt(DateUtils.parseDate("2013-12-17"));
- }
-}
diff --git a/sonar-server/src/test/java/org/sonar/server/rule2/RuleSearchMediumTest.java b/sonar-server/src/test/java/org/sonar/server/rule2/RuleSearchMediumTest.java
new file mode 100644
index 00000000000..98cbd5595b8
--- /dev/null
+++ b/sonar-server/src/test/java/org/sonar/server/rule2/RuleSearchMediumTest.java
@@ -0,0 +1,186 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 org.sonar.server.rule2;
+
+import com.google.common.collect.Iterables;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Ignore;
+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.utils.DateUtils;
+import org.sonar.check.Cardinality;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.server.search.Hit;
+import org.sonar.server.search.QueryOptions;
+import org.sonar.server.search.Results;
+import org.sonar.server.tester.ServerTester;
+
+import java.util.Arrays;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class RuleSearchMediumTest {
+
+ @ClassRule
+ public static ServerTester tester = new ServerTester();
+
+ RuleDao dao = tester.get(RuleDao.class);
+ RuleIndex index = tester.get(RuleIndex.class);
+
+ @Before
+ public void clear_data_store() {
+ tester.clearDataStores();
+ }
+
+ @Test
+ @Ignore("TODO")
+ public void return_all_doc_fields_by_default() {
+ dao.insert(newRuleDto(RuleKey.of("javascript", "S001")));
+ index.refresh();
+
+ QueryOptions options = new QueryOptions();
+ Results results = index.search(new RuleQuery(), options);
+
+ assertThat(results.getHits()).hasSize(1);
+ Hit hit = Iterables.getFirst(results.getHits(), null);
+ assertThat(hit.getFields()).hasSize(RuleNormalizer.RuleField.values().length);
+ }
+
+ @Test
+ @Ignore("TODO permanent 'repo' is missing")
+ public void select_doc_fields_to_load() {
+ dao.insert(newRuleDto(RuleKey.of("javascript", "S001")));
+ index.refresh();
+
+ QueryOptions options = new QueryOptions();
+ options.addFieldsToReturn(RuleNormalizer.RuleField.LANGUAGE.key(), RuleNormalizer.RuleField.STATUS.key());
+ Results results = index.search(new RuleQuery(), options);
+
+ assertThat(results.getHits()).hasSize(1);
+ Hit hit = Iterables.getFirst(results.getHits(), null);
+ assertThat(hit.getFields()).hasSize(4);
+
+ // request fields
+ assertThat(hit.getFieldAsString(RuleNormalizer.RuleField.LANGUAGE.key())).isEqualTo("js");
+ assertThat(hit.getFieldAsString(RuleNormalizer.RuleField.STATUS.key())).isEqualTo(RuleStatus.READY.name());
+
+ // permanent fields
+ assertThat(hit.getFieldAsString(RuleNormalizer.RuleField.REPOSITORY.key())).isEqualTo("javascript");
+ assertThat(hit.getFieldAsString(RuleNormalizer.RuleField.KEY.key())).isEqualTo("S001");
+ }
+
+ @Test
+ public void search_by_name() throws InterruptedException {
+ dao.insert(newRuleDto(RuleKey.of("javascript", "S001"))
+ .setName("testing the partial match and matching of rule"));
+ index.refresh();
+
+ // substring
+ RuleQuery query = new RuleQuery().setQueryText("test");
+ assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(1);
+
+ // substring
+ query = new RuleQuery().setQueryText("partial match");
+ assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(1);
+
+ // case-insensitive
+ query = new RuleQuery().setQueryText("TESTING");
+ assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(1);
+
+ // not found
+ query = new RuleQuery().setQueryText("not present");
+ assertThat(index.search(query, new QueryOptions()).getHits()).isEmpty();
+ }
+
+ @Test
+ @Ignore("TODO")
+ public void search_by_key_through_query_text() throws InterruptedException {
+ dao.insert(newRuleDto(RuleKey.of("javascript", "S001")));
+ dao.insert(newRuleDto(RuleKey.of("cobol", "S001")));
+ dao.insert(newRuleDto(RuleKey.of("php", "S002")));
+ index.refresh();
+
+ // key
+ RuleQuery query = new RuleQuery().setQueryText("S001");
+ assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(2);
+
+ // partial key does not match
+ query = new RuleQuery().setQueryText("S00");
+ assertThat(index.search(query, new QueryOptions()).getHits()).isEmpty();
+
+ // repo:key -> nice-to-have !
+ query = new RuleQuery().setQueryText("javascript:S001");
+ assertThat(index.search(query, new QueryOptions()).getHits()).hasSize(1);
+ }
+
+ @Test
+ public void search_all_rules() throws InterruptedException {
+ dao.insert(newRuleDto(RuleKey.of("javascript", "S001")));
+ dao.insert(newRuleDto(RuleKey.of("java", "S002")));
+ index.refresh();
+
+ Results results = index.search(new RuleQuery(), new QueryOptions());
+
+ assertThat(results.getTotal()).isEqualTo(2);
+ assertThat(results.getHits()).hasSize(2);
+ }
+
+ @Test
+ public void search_rules_by_any_of_repositories() throws InterruptedException {
+ dao.insert(newRuleDto(RuleKey.of("findbugs", "S001")));
+ dao.insert(newRuleDto(RuleKey.of("pmd", "S002")));
+ index.refresh();
+
+ RuleQuery query = new RuleQuery().setRepositories(Arrays.asList("checkstyle", "pmd"));
+ Results results = index.search(query, new QueryOptions());
+ assertThat(results.getHits()).hasSize(1);
+ assertThat(Iterables.getFirst(results.getHits(), null).getFieldAsString("key")).isEqualTo("S002");
+
+ // no results
+ query = new RuleQuery().setRepositories(Arrays.asList("checkstyle"));
+ assertThat(index.search(query, new QueryOptions()).getHits()).isEmpty();
+ }
+
+ private RuleDto newRuleDto(RuleKey ruleKey) {
+ return new RuleDto()
+ .setRuleKey(ruleKey.rule())
+ .setRepositoryKey(ruleKey.repository())
+ .setName("Rule " + ruleKey.rule())
+ .setDescription("Description " + ruleKey.rule())
+ .setStatus(RuleStatus.READY.toString())
+ .setConfigKey("InternalKey" + ruleKey.rule())
+ .setSeverity(Severity.INFO)
+ .setCardinality(Cardinality.SINGLE)
+ .setLanguage("js")
+ .setRemediationFunction("linear")
+ .setDefaultRemediationFunction("linear_offset")
+ .setRemediationCoefficient("1h")
+ .setDefaultRemediationCoefficient("5d")
+ .setRemediationOffset("5min")
+ .setDefaultRemediationOffset("10h")
+ .setEffortToFixDescription(ruleKey.repository() + "." + ruleKey.rule() + ".effortToFix")
+ .setCreatedAt(DateUtils.parseDate("2013-12-16"))
+ .setUpdatedAt(DateUtils.parseDate("2013-12-17"));
+ }
+}
diff --git a/sonar-server/src/test/java/org/sonar/server/rule2/RuleServiceMediumTest.java b/sonar-server/src/test/java/org/sonar/server/rule2/RuleServiceMediumTest.java
new file mode 100644
index 00000000000..3bbbd9117a0
--- /dev/null
+++ b/sonar-server/src/test/java/org/sonar/server/rule2/RuleServiceMediumTest.java
@@ -0,0 +1,107 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 org.sonar.server.rule2;
+
+import org.junit.After;
+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.utils.DateUtils;
+import org.sonar.check.Cardinality;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.server.search.Hit;
+import org.sonar.server.tester.ServerTester;
+
+import java.util.Collection;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class RuleServiceMediumTest {
+
+ @ClassRule
+ public static ServerTester tester = new ServerTester();
+
+ @Before
+ public void clear_data_store() {
+ tester.clearDataStores();
+ }
+
+ @Test
+ public void insert_in_db_and_index_in_es() {
+ // insert db
+ RuleKey ruleKey = RuleKey.of("javascript", "S001");
+ RuleDao dao = tester.get(RuleDao.class);
+ dao.insert(newRuleDto(ruleKey));
+
+ // verify that rule is persisted in db
+ RuleDto persistedDto = dao.selectByKey(ruleKey);
+ assertThat(persistedDto).isNotNull();
+ assertThat(persistedDto.getId()).isGreaterThanOrEqualTo(0);
+ assertThat(persistedDto.getRuleKey()).isEqualTo(ruleKey.rule());
+ assertThat(persistedDto.getLanguage()).isEqualTo("js");
+
+ // verify that rule is indexed in es
+ RuleIndex index = tester.get(RuleIndex.class);
+ index.refresh();
+
+ Hit hit = index.getByKey(ruleKey);
+ assertThat(hit).isNotNull();
+ assertThat(hit.getFieldAsString(RuleNormalizer.RuleField.REPOSITORY.key())).isEqualTo(ruleKey.repository());
+ assertThat(hit.getFieldAsString(RuleNormalizer.RuleField.KEY.key())).isEqualTo(ruleKey.rule());
+ assertThat(hit.getFieldAsString(RuleNormalizer.RuleField.LANGUAGE.key())).isEqualTo("js");
+ assertThat(hit.getFieldAsString(RuleNormalizer.RuleField.NAME.key())).isEqualTo("Rule S001");
+ assertThat(hit.getFieldAsString(RuleNormalizer.RuleField.DESCRIPTION.key())).isEqualTo("Description S001");
+ assertThat(hit.getFieldAsString(RuleNormalizer.RuleField.STATUS.key())).isEqualTo(RuleStatus.READY.toString());
+ assertThat(hit.getField(RuleNormalizer.RuleField.CREATED_AT.key())).isNotNull();
+ assertThat(hit.getField(RuleNormalizer.RuleField.UPDATED_AT.key())).isNotNull();
+ assertThat(hit.getFieldAsString(RuleNormalizer.RuleField.INTERNAL_KEY.key())).isEqualTo("InternalKeyS001");
+ assertThat(hit.getFieldAsString(RuleNormalizer.RuleField.SEVERITY.key())).isEqualTo("INFO");
+//TODO assertThat((Collection) hit.getField(RuleNormalizer.RuleField.SYSTEM_TAGS.key())).isEmpty();
+//TODO assertThat((Collection) hit.getField(RuleNormalizer.RuleField.TAGS.key())).isEmpty();
+ assertThat((Boolean) hit.getField(RuleNormalizer.RuleField.TEMPLATE.key())).isFalse();
+ }
+
+ //TODO test delete, update, tags, params
+
+ private RuleDto newRuleDto(RuleKey ruleKey) {
+ return new RuleDto()
+ .setRuleKey(ruleKey.rule())
+ .setRepositoryKey(ruleKey.repository())
+ .setName("Rule " + ruleKey.rule())
+ .setDescription("Description " + ruleKey.rule())
+ .setStatus(RuleStatus.READY.toString())
+ .setConfigKey("InternalKey" + ruleKey.rule())
+ .setSeverity(Severity.INFO)
+ .setCardinality(Cardinality.SINGLE)
+ .setLanguage("js")
+ .setRemediationFunction("linear")
+ .setDefaultRemediationFunction("linear_offset")
+ .setRemediationCoefficient("1h")
+ .setDefaultRemediationCoefficient("5d")
+ .setRemediationOffset("5min")
+ .setDefaultRemediationOffset("10h")
+ .setEffortToFixDescription(ruleKey.repository() + "." + ruleKey.rule() + ".effortToFix")
+ .setCreatedAt(DateUtils.parseDate("2013-12-16"))
+ .setUpdatedAt(DateUtils.parseDate("2013-12-17"));
+ }
+}
diff --git a/sonar-server/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java b/sonar-server/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java
index 4434f4705d6..299581ebd21 100644
--- a/sonar-server/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/ws/WebServiceEngineTest.java
@@ -164,7 +164,7 @@ public class WebServiceEngineTest {
ServletResponse response = new ServletResponse();
engine.execute(request, response, "api/system", "fail_with_undeclared_parameter");
- assertThat(response.stream().outputAsString()).isEqualTo("{\"errors\":[{\"msg\":\"Parameter 'unknown' is undefined for action 'fail_with_undeclared_parameter'\"}]}");
+ assertThat(response.stream().outputAsString()).isEqualTo("{\"errors\":[{\"msg\":\"BUG - parameter 'unknown' is undefined for action 'fail_with_undeclared_parameter'\"}]}");
}
@Test