@@ -28,6 +28,7 @@ import javax.annotation.Nullable; | |||
import org.apache.commons.lang.builder.ReflectionToStringBuilder; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.rule.RuleStatus; | |||
import org.sonar.core.rule.RuleType; | |||
import org.sonar.server.search.BaseDoc; | |||
/** | |||
@@ -168,6 +169,15 @@ public class RuleDoc extends BaseDoc { | |||
return this; | |||
} | |||
public RuleType type() { | |||
return RuleType.valueOf((String) getField(RuleIndexDefinition.FIELD_RULE_TYPE)); | |||
} | |||
public RuleDoc setType(RuleType ruleType) { | |||
setField(RuleIndexDefinition.FIELD_RULE_TYPE, ruleType.name()); | |||
return this; | |||
} | |||
public long createdAt() { | |||
return (Long) getField(RuleIndexDefinition.FIELD_RULE_CREATED_AT); | |||
} |
@@ -60,6 +60,7 @@ import org.elasticsearch.search.sort.SortOrder; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.rule.RuleStatus; | |||
import org.sonar.api.rule.Severity; | |||
import org.sonar.core.rule.RuleType; | |||
import org.sonar.server.es.BaseIndex; | |||
import org.sonar.server.es.EsClient; | |||
import org.sonar.server.es.SearchIdResult; | |||
@@ -86,6 +87,7 @@ import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_RULE_KE | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_SEVERITY; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_STATUS; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_TEMPLATE_KEY; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_TYPE; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_UPDATED_AT; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.INDEX; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.TYPE_ACTIVE_RULE; | |||
@@ -103,24 +105,11 @@ public class RuleIndex extends BaseIndex { | |||
public static final String FACET_SEVERITIES = "severities"; | |||
public static final String FACET_ACTIVE_SEVERITIES = "active_severities"; | |||
public static final String FACET_STATUSES = "statuses"; | |||
public static final String FACET_TYPES = "types"; | |||
public static final String FACET_OLD_DEFAULT = "true"; | |||
public static final List<String> ALL_STATUSES_EXCEPT_REMOVED = ImmutableList.copyOf( | |||
Collections2.filter( | |||
Collections2.transform( | |||
Arrays.asList(RuleStatus.values()), | |||
new Function<RuleStatus, String>() { | |||
@Override | |||
public String apply(@Nonnull RuleStatus input) { | |||
return input.toString(); | |||
} | |||
}), | |||
new Predicate<String>() { | |||
@Override | |||
public boolean apply(@Nonnull String input) { | |||
return !RuleStatus.REMOVED.toString().equals(input); | |||
} | |||
})); | |||
Collections2.filter(Collections2.transform(Arrays.asList(RuleStatus.values()), RuleStatusToString.INSTANCE), NotRemoved.INSTANCE)); | |||
public RuleIndex(EsClient client) { | |||
super(client); | |||
@@ -266,6 +255,11 @@ public class RuleIndex extends BaseIndex { | |||
FilterBuilders.termsFilter(FIELD_RULE_ALL_TAGS, query.getTags())); | |||
} | |||
if (!CollectionUtils.isEmpty(query.getTypes())) { | |||
filters.put(FIELD_RULE_TYPE, | |||
FilterBuilders.termsFilter(FIELD_RULE_TYPE, query.getTypes())); | |||
} | |||
if (query.getAvailableSinceLong() != null) { | |||
filters.put("availableSince", FilterBuilders.rangeFilter(FIELD_RULE_CREATED_AT) | |||
.gte(query.getAvailableSinceLong())); | |||
@@ -363,19 +357,25 @@ public class RuleIndex extends BaseIndex { | |||
Collection<String> languages = query.getLanguages(); | |||
aggregations.put(FACET_LANGUAGES, | |||
stickyFacetBuilder.buildStickyFacet(FIELD_RULE_LANGUAGE, FACET_LANGUAGES, | |||
languages == null ? new String[0] : languages.toArray())); | |||
(languages == null) ? new String[0] : languages.toArray())); | |||
} | |||
if (options.getFacets().contains(FACET_TAGS) || options.getFacets().contains(FACET_OLD_DEFAULT)) { | |||
Collection<String> tags = query.getTags(); | |||
aggregations.put(FACET_TAGS, | |||
stickyFacetBuilder.buildStickyFacet(FIELD_RULE_ALL_TAGS, FACET_TAGS, | |||
tags == null ? new String[0] : tags.toArray())); | |||
(tags == null) ? new String[0] : tags.toArray())); | |||
} | |||
if (options.getFacets().contains(FACET_TYPES)) { | |||
Collection<RuleType> types = query.getTypes(); | |||
aggregations.put(FACET_TYPES, | |||
stickyFacetBuilder.buildStickyFacet(FIELD_RULE_TYPE, FACET_TYPES, | |||
(types == null) ? new String[0] : types.toArray())); | |||
} | |||
if (options.getFacets().contains("repositories") || options.getFacets().contains(FACET_OLD_DEFAULT)) { | |||
Collection<String> repositories = query.getRepositories(); | |||
aggregations.put(FACET_REPOSITORIES, | |||
stickyFacetBuilder.buildStickyFacet(FIELD_RULE_REPOSITORY, FACET_REPOSITORIES, | |||
repositories == null ? new String[0] : repositories.toArray())); | |||
(repositories == null) ? new String[0] : repositories.toArray())); | |||
} | |||
} | |||
@@ -508,4 +508,22 @@ public class RuleIndex extends BaseIndex { | |||
} | |||
} | |||
private enum RuleStatusToString implements Function<RuleStatus, String> { | |||
INSTANCE; | |||
@Override | |||
public String apply(@Nonnull RuleStatus input) { | |||
return input.toString(); | |||
} | |||
} | |||
private enum NotRemoved implements Predicate<String> { | |||
INSTANCE; | |||
@Override | |||
public boolean apply(@Nonnull String input) { | |||
return !RuleStatus.REMOVED.toString().equals(input); | |||
} | |||
} | |||
} |
@@ -48,6 +48,7 @@ public class RuleIndexDefinition implements IndexDefinition { | |||
public static final String FIELD_RULE_IS_TEMPLATE = "isTemplate"; | |||
public static final String FIELD_RULE_TEMPLATE_KEY = "templateKey"; | |||
public static final String FIELD_RULE_ALL_TAGS = "allTags"; | |||
public static final String FIELD_RULE_TYPE = "type"; | |||
public static final String FIELD_RULE_CREATED_AT = "createdAt"; | |||
public static final String FIELD_RULE_UPDATED_AT = "updatedAt"; | |||
@@ -106,6 +107,7 @@ public class RuleIndexDefinition implements IndexDefinition { | |||
ruleMapping.stringFieldBuilder(FIELD_RULE_TEMPLATE_KEY).docValues().build(); | |||
ruleMapping.stringFieldBuilder(FIELD_RULE_ALL_TAGS).enableGramSearch().build(); | |||
ruleMapping.stringFieldBuilder(FIELD_RULE_TYPE).build(); | |||
ruleMapping.createLongField(FIELD_RULE_CREATED_AT); | |||
ruleMapping.createLongField(FIELD_RULE_UPDATED_AT); |
@@ -25,6 +25,7 @@ import javax.annotation.CheckForNull; | |||
import javax.annotation.Nullable; | |||
import org.sonar.api.rule.RuleStatus; | |||
import org.sonar.api.rule.Severity; | |||
import org.sonar.core.rule.RuleType; | |||
import static java.util.Arrays.asList; | |||
@@ -37,6 +38,7 @@ public class RuleQuery { | |||
private Collection<String> severities; | |||
private Collection<RuleStatus> statuses; | |||
private Collection<String> tags; | |||
private Collection<RuleType> types; | |||
private Boolean activation; | |||
private String qProfileKey; | |||
private Collection<String> inheritance; | |||
@@ -162,6 +164,16 @@ public class RuleQuery { | |||
return this; | |||
} | |||
@CheckForNull | |||
public Collection<RuleType> getTypes() { | |||
return types; | |||
} | |||
public RuleQuery setTypes(@Nullable Collection<RuleType> types) { | |||
this.types = types; | |||
return this; | |||
} | |||
@CheckForNull | |||
public Collection<String> getInheritance() { | |||
return inheritance; |
@@ -31,6 +31,7 @@ import java.util.Set; | |||
import javax.annotation.Nullable; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.core.rule.RuleType; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.ResultSetIterator; | |||
@@ -61,6 +62,7 @@ public class RuleResultSetIterator extends ResultSetIterator<RuleDoc> { | |||
"t.plugin_name", | |||
"r.plugin_config_key", | |||
"r.language", | |||
"r.rule_type", | |||
"r.created_at", | |||
"r.updated_at", | |||
}; | |||
@@ -129,8 +131,9 @@ public class RuleResultSetIterator extends ResultSetIterator<RuleDoc> { | |||
doc.setInternalKey(rs.getString(13)); | |||
doc.setLanguage(rs.getString(14)); | |||
doc.setCreatedAt(rs.getLong(15)); | |||
doc.setUpdatedAt(rs.getLong(16)); | |||
doc.setType(RuleType.valueOf(rs.getInt(15))); | |||
doc.setCreatedAt(rs.getLong(16)); | |||
doc.setUpdatedAt(rs.getLong(17)); | |||
return doc; | |||
} |
@@ -24,6 +24,7 @@ import java.util.Arrays; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.rule.RuleStatus; | |||
import org.sonar.api.rule.Severity; | |||
import org.sonar.core.rule.RuleType; | |||
import org.sonar.db.rule.RuleTesting; | |||
public class RuleDocTesting { | |||
@@ -43,7 +44,8 @@ public class RuleDocTesting { | |||
.setStatus(RuleStatus.READY.name()) | |||
.setLanguage("xoo") | |||
.setIsTemplate(false) | |||
.setAllTags(Arrays.asList("bug", "performance")) | |||
.setAllTags(Arrays.asList("spring", "performance")) | |||
.setType(RuleType.CODE_SMELL) | |||
.setCreatedAt(150000000L) | |||
.setUpdatedAt(160000000L); | |||
} |
@@ -30,6 +30,7 @@ import org.junit.Test; | |||
import org.sonar.api.config.Settings; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.rule.RuleStatus; | |||
import org.sonar.core.rule.RuleType; | |||
import org.sonar.db.qualityprofile.ActiveRuleKey; | |||
import org.sonar.db.rule.RuleTesting; | |||
import org.sonar.server.es.EsTester; | |||
@@ -50,12 +51,16 @@ import static org.sonar.api.rule.Severity.CRITICAL; | |||
import static org.sonar.api.rule.Severity.INFO; | |||
import static org.sonar.api.rule.Severity.MAJOR; | |||
import static org.sonar.api.rule.Severity.MINOR; | |||
import static org.sonar.core.rule.RuleType.BUG; | |||
import static org.sonar.core.rule.RuleType.CODE_SMELL; | |||
import static org.sonar.core.rule.RuleType.VULNERABILITY; | |||
import static org.sonar.server.qualityprofile.ActiveRule.Inheritance.INHERITED; | |||
import static org.sonar.server.qualityprofile.ActiveRule.Inheritance.OVERRIDES; | |||
import static org.sonar.server.rule.index.RuleDocTesting.newDoc; | |||
import static org.sonar.server.rule.index.RuleIndex.FACET_LANGUAGES; | |||
import static org.sonar.server.rule.index.RuleIndex.FACET_REPOSITORIES; | |||
import static org.sonar.server.rule.index.RuleIndex.FACET_TAGS; | |||
import static org.sonar.server.rule.index.RuleIndex.FACET_TYPES; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.INDEX; | |||
import static org.sonar.server.rule.index.RuleIndexDefinition.TYPE_ACTIVE_RULE; | |||
@@ -188,7 +193,7 @@ public class RuleIndexTest { | |||
} | |||
@Test | |||
public void search_by_tag() { | |||
public void search_by_tags() { | |||
indexRules( | |||
newDoc(RuleKey.of("java", "S001")).setAllTags(singleton("tag1")), | |||
newDoc(RuleKey.of("java", "S002")).setAllTags(singleton("tag2"))); | |||
@@ -226,6 +231,39 @@ public class RuleIndexTest { | |||
assertThat(index.search(query, new SearchOptions()).getIds()).hasSize(2); | |||
} | |||
@Test | |||
public void search_by_types() { | |||
indexRules( | |||
newDoc(RULE_KEY_1).setType(CODE_SMELL), | |||
newDoc(RULE_KEY_2).setType(VULNERABILITY), | |||
newDoc(RULE_KEY_3).setType(BUG), | |||
newDoc(RULE_KEY_4).setType(BUG) | |||
); | |||
// find all | |||
RuleQuery query = new RuleQuery(); | |||
assertThat(index.search(query, new SearchOptions()).getIds()).hasSize(4); | |||
// type3 in filter | |||
query = new RuleQuery().setTypes(ImmutableSet.of(VULNERABILITY)); | |||
assertThat(index.search(query, new SearchOptions()).getIds()).containsOnly(RULE_KEY_2); | |||
query = new RuleQuery().setTypes(ImmutableSet.of(BUG)); | |||
assertThat(index.search(query, new SearchOptions()).getIds()).containsOnly(RULE_KEY_3,RULE_KEY_4); | |||
// types in query => nothing | |||
query = new RuleQuery().setQueryText("code smell bug vulnerability"); | |||
assertThat(index.search(query, new SearchOptions()).getIds()).isEmpty(); | |||
// null list => no filter | |||
query = new RuleQuery().setTypes(Collections.<RuleType>emptySet()); | |||
assertThat(index.search(query, new SearchOptions()).getIds()).hasSize(4); | |||
// null list => no filter | |||
query = new RuleQuery().setTypes(null); | |||
assertThat(index.search(query, new SearchOptions()).getIds()).hasSize(4); | |||
} | |||
@Test | |||
public void search_by_is_template() { | |||
indexRules( | |||
@@ -546,30 +584,31 @@ public class RuleIndexTest { | |||
@Test | |||
public void sticky_facets() { | |||
indexRules( | |||
newDoc(RuleKey.of("xoo", "S001")).setLanguage("java").setAllTags(Collections.<String>emptyList()), | |||
newDoc(RuleKey.of("xoo", "S002")).setLanguage("java").setAllTags(Collections.<String>emptyList()), | |||
newDoc(RuleKey.of("xoo", "S003")).setLanguage("java").setAllTags(asList("T1", "T2")), | |||
newDoc(RuleKey.of("xoo", "S011")).setLanguage("cobol").setAllTags(Collections.<String>emptyList()), | |||
newDoc(RuleKey.of("xoo", "S012")).setLanguage("cobol").setAllTags(Collections.<String>emptyList()), | |||
newDoc(RuleKey.of("foo", "S013")).setLanguage("cobol").setAllTags(asList("T3", "T4")), | |||
newDoc(RuleKey.of("foo", "S111")).setLanguage("cpp").setAllTags(Collections.<String>emptyList()), | |||
newDoc(RuleKey.of("foo", "S112")).setLanguage("cpp").setAllTags(Collections.<String>emptyList()), | |||
newDoc(RuleKey.of("foo", "S113")).setLanguage("cpp").setAllTags(asList("T2", "T3"))); | |||
newDoc(RuleKey.of("xoo", "S001")).setLanguage("java").setAllTags(Collections.<String>emptyList()).setType(BUG), | |||
newDoc(RuleKey.of("xoo", "S002")).setLanguage("java").setAllTags(Collections.<String>emptyList()).setType(CODE_SMELL), | |||
newDoc(RuleKey.of("xoo", "S003")).setLanguage("java").setAllTags(asList("T1", "T2")).setType(CODE_SMELL), | |||
newDoc(RuleKey.of("xoo", "S011")).setLanguage("cobol").setAllTags(Collections.<String>emptyList()).setType(CODE_SMELL), | |||
newDoc(RuleKey.of("xoo", "S012")).setLanguage("cobol").setAllTags(Collections.<String>emptyList()).setType(BUG), | |||
newDoc(RuleKey.of("foo", "S013")).setLanguage("cobol").setAllTags(asList("T3", "T4")).setType(VULNERABILITY), | |||
newDoc(RuleKey.of("foo", "S111")).setLanguage("cpp").setAllTags(Collections.<String>emptyList()).setType(BUG), | |||
newDoc(RuleKey.of("foo", "S112")).setLanguage("cpp").setAllTags(Collections.<String>emptyList()).setType(CODE_SMELL), | |||
newDoc(RuleKey.of("foo", "S113")).setLanguage("cpp").setAllTags(asList("T2", "T3")).setType(CODE_SMELL)); | |||
// 0 assert Base | |||
assertThat(index.search(new RuleQuery(), new SearchOptions()).getIds()).hasSize(9); | |||
// 1 Facet with no filters at all | |||
SearchIdResult result = index.search(new RuleQuery(), new SearchOptions().addFacets(asList("languages", "repositories", "tags"))); | |||
assertThat(result.getFacets().getAll()).hasSize(3); | |||
SearchIdResult result = index.search(new RuleQuery(), new SearchOptions().addFacets(asList(FACET_LANGUAGES, FACET_REPOSITORIES, FACET_TAGS, FACET_TYPES))); | |||
assertThat(result.getFacets().getAll()).hasSize(4); | |||
assertThat(result.getFacets().getAll().get(FACET_LANGUAGES).keySet()).containsOnly("cpp", "java", "cobol"); | |||
assertThat(result.getFacets().getAll().get(FACET_REPOSITORIES).keySet()).containsOnly("xoo", "foo"); | |||
assertThat(result.getFacets().getAll().get(FACET_TAGS).keySet()).containsOnly("T1", "T2", "T3", "T4"); | |||
assertThat(result.getFacets().getAll().get(FACET_TYPES).keySet()).containsOnly("BUG", "CODE_SMELL", "VULNERABILITY"); | |||
// 2 Facet with a language filter | |||
// -- lang facet should still have all language | |||
result = index.search(new RuleQuery().setLanguages(ImmutableList.of("cpp")) | |||
, new SearchOptions().addFacets(asList("languages", "repositories", "tags"))); | |||
, new SearchOptions().addFacets(asList(FACET_LANGUAGES, FACET_REPOSITORIES, FACET_TAGS))); | |||
assertThat(result.getIds()).hasSize(3); | |||
assertThat(result.getFacets().getAll()).hasSize(3); | |||
assertThat(result.getFacets().get(FACET_LANGUAGES).keySet()).containsOnly("cpp", "java", "cobol"); | |||
@@ -581,26 +620,29 @@ public class RuleIndexTest { | |||
result = index.search(new RuleQuery() | |||
.setLanguages(ImmutableList.of("cpp")) | |||
.setTags(ImmutableList.of("T2")) | |||
, new SearchOptions().addFacets(asList("languages", "repositories", "tags"))); | |||
, new SearchOptions().addFacets(asList(FACET_LANGUAGES, FACET_REPOSITORIES, FACET_TAGS))); | |||
assertThat(result.getIds()).hasSize(1); | |||
assertThat(result.getFacets().getAll()).hasSize(3); | |||
assertThat(result.getFacets().get(FACET_LANGUAGES).keySet()).containsOnly("cpp", "java"); | |||
assertThat(result.getFacets().get(FACET_REPOSITORIES).keySet()).containsOnly("foo"); | |||
assertThat(result.getFacets().get(FACET_TAGS).keySet()).containsOnly("T2", "T3"); | |||
// 4 facet with 2 filters | |||
// 4 facet with 3 filters | |||
// -- lang facet for tag T2 | |||
// -- tag facet for lang cpp & java | |||
// -- repository for (cpp || java) & T2 | |||
// -- type | |||
result = index.search(new RuleQuery() | |||
.setLanguages(ImmutableList.of("cpp", "java")) | |||
.setTags(ImmutableList.of("T2")) | |||
, new SearchOptions().addFacets(asList("languages", "repositories", "tags"))); | |||
.setTypes(asList(BUG, CODE_SMELL)) | |||
, new SearchOptions().addFacets(asList(FACET_LANGUAGES, FACET_REPOSITORIES, FACET_TAGS, FACET_TYPES))); | |||
assertThat(result.getIds()).hasSize(2); | |||
assertThat(result.getFacets().getAll()).hasSize(3); | |||
assertThat(result.getFacets().getAll()).hasSize(4); | |||
assertThat(result.getFacets().get(FACET_LANGUAGES).keySet()).containsOnly("cpp", "java"); | |||
assertThat(result.getFacets().get(FACET_REPOSITORIES).keySet()).containsOnly("foo", "xoo"); | |||
assertThat(result.getFacets().get(FACET_TAGS).keySet()).containsOnly("T1", "T2", "T3"); | |||
assertThat(result.getFacets().get(FACET_TYPES).keySet()).containsOnly("CODE_SMELL"); | |||
} | |||
@Test |
@@ -25,14 +25,17 @@ import org.junit.ClassRule; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.sonar.api.config.Settings; | |||
import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.rule.RuleStatus; | |||
import org.sonar.api.rule.Severity; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.core.rule.RuleType; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.rule.RuleDto; | |||
import org.sonar.db.rule.RuleTesting; | |||
import org.sonar.server.es.EsTester; | |||
import static com.google.common.collect.Sets.newHashSet; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
@@ -44,6 +47,27 @@ public class RuleIndexerTest { | |||
@Rule | |||
public DbTester dbTester = DbTester.create(System2.INSTANCE); | |||
DbClient dbClient = dbTester.getDbClient(); | |||
DbSession dbSession = dbTester.getSession(); | |||
RuleDto rule = new RuleDto() | |||
.setRuleKey("S001") | |||
.setRepositoryKey("xoo") | |||
.setConfigKey("S1") | |||
.setName("Null Pointer") | |||
.setDescription("S001 desc") | |||
.setDescriptionFormat(RuleDto.Format.HTML) | |||
.setLanguage("xoo") | |||
.setSeverity(Severity.BLOCKER) | |||
.setStatus(RuleStatus.READY) | |||
.setIsTemplate(true) | |||
.setTags(newHashSet("performance")) | |||
.setSystemTags(newHashSet("cwe")) | |||
.setType(RuleType.BUG) | |||
.setCreatedAt(1500000000000L) | |||
.setUpdatedAt(1600000000000L); | |||
@Before | |||
public void setUp() { | |||
esTester.truncateIndices(); | |||
@@ -58,7 +82,8 @@ public class RuleIndexerTest { | |||
@Test | |||
public void index_nothing_if_disabled() { | |||
dbTester.prepareDbUnit(getClass(), "index.xml"); | |||
dbClient.ruleDao().insert(dbSession, rule); | |||
dbSession.commit(); | |||
createIndexer().setEnabled(false).index(); | |||
@@ -67,7 +92,8 @@ public class RuleIndexerTest { | |||
@Test | |||
public void index() { | |||
dbTester.prepareDbUnit(getClass(), "index.xml"); | |||
dbClient.ruleDao().insert(dbSession, rule); | |||
dbSession.commit(); | |||
RuleIndexer indexer = createIndexer(); | |||
indexer.index(); | |||
@@ -80,17 +106,13 @@ public class RuleIndexerTest { | |||
RuleIndexer indexer = createIndexer(); | |||
// Create and Index rule | |||
RuleDto ruleDto = RuleTesting.newDto(RuleKey.of("xoo", "S001")) | |||
.setStatus(RuleStatus.READY) | |||
.setUpdatedAt(1000L); | |||
dbTester.getDbClient().ruleDao().insert(dbTester.getSession(), ruleDto); | |||
dbTester.getSession().commit(); | |||
dbClient.ruleDao().insert(dbSession, rule.setStatus(RuleStatus.READY)); | |||
dbSession.commit(); | |||
indexer.index(); | |||
assertThat(esTester.countDocuments(RuleIndexDefinition.INDEX, RuleIndexDefinition.TYPE_RULE)).isEqualTo(1); | |||
// Remove rule | |||
ruleDto.setStatus(RuleStatus.REMOVED); | |||
ruleDto.setUpdatedAt(2000L); | |||
dbTester.getDbClient().ruleDao().update(dbTester.getSession(), ruleDto); | |||
dbTester.getDbClient().ruleDao().update(dbTester.getSession(), rule.setStatus(RuleStatus.READY).setUpdatedAt(2000000000000L)); | |||
dbTester.getSession().commit(); | |||
indexer.index(); | |||
@@ -30,16 +30,56 @@ import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.rule.RuleStatus; | |||
import org.sonar.api.rule.Severity; | |||
import org.sonar.api.utils.System2; | |||
import org.sonar.core.rule.RuleType; | |||
import org.sonar.db.DbClient; | |||
import org.sonar.db.DbSession; | |||
import org.sonar.db.DbTester; | |||
import org.sonar.db.rule.RuleDto; | |||
import static com.google.common.collect.Sets.newHashSet; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class RuleResultSetIteratorTest { | |||
@Rule | |||
public DbTester dbTester = DbTester.create(System2.INSTANCE); | |||
DbClient dbClient = dbTester.getDbClient(); | |||
DbSession dbSession = dbTester.getSession(); | |||
RuleDto templateRule = new RuleDto() | |||
.setRuleKey("S001") | |||
.setRepositoryKey("xoo") | |||
.setConfigKey("S1") | |||
.setName("Null Pointer") | |||
.setDescription("S001 desc") | |||
.setDescriptionFormat(RuleDto.Format.HTML) | |||
.setLanguage("xoo") | |||
.setSeverity(Severity.BLOCKER) | |||
.setStatus(RuleStatus.READY) | |||
.setIsTemplate(true) | |||
.setTags(newHashSet("performance")) | |||
.setSystemTags(newHashSet("cwe")) | |||
.setType(RuleType.BUG) | |||
.setCreatedAt(1500000000000L) | |||
.setUpdatedAt(1600000000000L); | |||
RuleDto customRule = new RuleDto() | |||
.setRuleKey("S002") | |||
.setRepositoryKey("xoo") | |||
.setConfigKey("S2") | |||
.setName("Slow") | |||
.setDescription("*S002 desc*") | |||
.setDescriptionFormat(RuleDto.Format.MARKDOWN) | |||
.setLanguage("xoo") | |||
.setSeverity(Severity.MAJOR) | |||
.setStatus(RuleStatus.BETA) | |||
.setIsTemplate(false) | |||
.setType(RuleType.CODE_SMELL) | |||
.setCreatedAt(2000000000000L) | |||
.setUpdatedAt(2100000000000L); | |||
@Before | |||
public void setUp() { | |||
dbTester.truncateTables(); | |||
@@ -47,14 +87,17 @@ public class RuleResultSetIteratorTest { | |||
@Test | |||
public void iterator_over_one_rule() { | |||
dbTester.prepareDbUnit(getClass(), "one_rule.xml"); | |||
dbClient.ruleDao().insert(dbSession, templateRule); | |||
dbSession.commit(); | |||
RuleResultSetIterator it = RuleResultSetIterator.create(dbTester.getDbClient(), dbTester.getSession(), 0L); | |||
Map<String, RuleDoc> rulesByKey = rulesByKey(it); | |||
it.close(); | |||
assertThat(rulesByKey).hasSize(1); | |||
RuleDoc rule = rulesByKey.get("S001"); | |||
RuleDoc rule = rulesByKey.get(templateRule.getRuleKey()); | |||
assertThat(rule).isNotNull(); | |||
assertThat(rule.key()).isEqualTo(RuleKey.of("xoo", "S001")); | |||
assertThat(rule.keyAsList()).containsOnly("xoo", "S001"); | |||
assertThat(rule.ruleKey()).isEqualTo("S001"); | |||
@@ -65,15 +108,18 @@ public class RuleResultSetIteratorTest { | |||
assertThat(rule.language()).isEqualTo("xoo"); | |||
assertThat(rule.severity()).isEqualTo(Severity.BLOCKER); | |||
assertThat(rule.status()).isEqualTo(RuleStatus.READY); | |||
assertThat(rule.isTemplate()).isFalse(); | |||
assertThat(rule.allTags()).containsOnly("bug", "performance", "cwe"); | |||
assertThat(rule.isTemplate()).isTrue(); | |||
assertThat(rule.allTags()).containsOnly("performance", "cwe"); | |||
assertThat(rule.createdAt()).isEqualTo(1500000000000L); | |||
assertThat(rule.updatedAt()).isEqualTo(1600000000000L); | |||
} | |||
@Test | |||
public void select_after_date() { | |||
dbTester.prepareDbUnit(getClass(), "shared.xml"); | |||
dbClient.ruleDao().insert(dbSession, templateRule); | |||
dbClient.ruleDao().insert(dbSession, customRule); | |||
dbSession.commit(); | |||
RuleResultSetIterator it = RuleResultSetIterator.create(dbTester.getDbClient(), dbTester.getSession(), 1_900_000_000_000L); | |||
assertThat(it.hasNext()).isTrue(); | |||
@@ -86,7 +132,9 @@ public class RuleResultSetIteratorTest { | |||
@Test | |||
public void iterator_over_rules() { | |||
dbTester.prepareDbUnit(getClass(), "shared.xml"); | |||
dbClient.ruleDao().insert(dbSession, templateRule); | |||
dbClient.ruleDao().insert(dbSession, customRule); | |||
dbSession.commit(); | |||
RuleResultSetIterator it = RuleResultSetIterator.create(dbTester.getDbClient(), dbTester.getSession(), 0L); | |||
Map<String, RuleDoc> rulesByKey = rulesByKey(it); | |||
@@ -94,7 +142,7 @@ public class RuleResultSetIteratorTest { | |||
assertThat(rulesByKey).hasSize(2); | |||
RuleDoc rule = rulesByKey.get("S001"); | |||
RuleDoc rule = rulesByKey.get(templateRule.getRuleKey()); | |||
assertThat(rule.key()).isEqualTo(RuleKey.of("xoo", "S001")); | |||
assertThat(rule.keyAsList()).containsOnly("xoo", "S001"); | |||
assertThat(rule.ruleKey()).isEqualTo("S001"); | |||
@@ -105,12 +153,12 @@ public class RuleResultSetIteratorTest { | |||
assertThat(rule.language()).isEqualTo("xoo"); | |||
assertThat(rule.severity()).isEqualTo(Severity.BLOCKER); | |||
assertThat(rule.status()).isEqualTo(RuleStatus.READY); | |||
assertThat(rule.isTemplate()).isFalse(); | |||
assertThat(rule.allTags()).containsOnly("bug", "performance", "cwe"); | |||
assertThat(rule.isTemplate()).isTrue(); | |||
assertThat(rule.allTags()).containsOnly("performance", "cwe"); | |||
assertThat(rule.createdAt()).isEqualTo(1500000000000L); | |||
assertThat(rule.updatedAt()).isEqualTo(1600000000000L); | |||
rule = rulesByKey.get("S002"); | |||
rule = rulesByKey.get(customRule.getRuleKey()); | |||
assertThat(rule.key()).isEqualTo(RuleKey.of("xoo", "S002")); | |||
assertThat(rule.keyAsList()).containsOnly("xoo", "S002"); | |||
assertThat(rule.ruleKey()).isEqualTo("S002"); | |||
@@ -119,9 +167,9 @@ public class RuleResultSetIteratorTest { | |||
assertThat(rule.name()).isEqualTo("Slow"); | |||
assertThat(rule.htmlDescription()).isEqualTo("<strong>S002 desc</strong>"); | |||
assertThat(rule.language()).isEqualTo("xoo"); | |||
assertThat(rule.severity()).isEqualTo(Severity.CRITICAL); | |||
assertThat(rule.severity()).isEqualTo(Severity.MAJOR); | |||
assertThat(rule.status()).isEqualTo(RuleStatus.BETA); | |||
assertThat(rule.isTemplate()).isTrue(); | |||
assertThat(rule.isTemplate()).isFalse(); | |||
assertThat(rule.allTags()).isEmpty(); | |||
assertThat(rule.createdAt()).isEqualTo(2000000000000L); | |||
assertThat(rule.updatedAt()).isEqualTo(2100000000000L); | |||
@@ -129,7 +177,9 @@ public class RuleResultSetIteratorTest { | |||
@Test | |||
public void custom_rule() { | |||
dbTester.prepareDbUnit(getClass(), "custom_rule.xml"); | |||
dbClient.ruleDao().insert(dbSession, templateRule); | |||
dbClient.ruleDao().insert(dbSession, customRule.setTemplateId(templateRule.getId())); | |||
dbSession.commit(); | |||
RuleResultSetIterator it = RuleResultSetIterator.create(dbTester.getDbClient(), dbTester.getSession(), 0L); | |||
Map<String, RuleDoc> rulesByKey = rulesByKey(it); | |||
@@ -137,18 +187,20 @@ public class RuleResultSetIteratorTest { | |||
assertThat(rulesByKey).hasSize(2); | |||
RuleDoc rule = rulesByKey.get("S001"); | |||
RuleDoc rule = rulesByKey.get(templateRule.getRuleKey()); | |||
assertThat(rule.isTemplate()).isTrue(); | |||
assertThat(rule.templateKey()).isNull(); | |||
rule = rulesByKey.get("S002"); | |||
rule = rulesByKey.get(customRule.getRuleKey()); | |||
assertThat(rule.isTemplate()).isFalse(); | |||
assertThat(rule.templateKey()).isEqualTo(RuleKey.of("xoo", "S001")); | |||
} | |||
@Test | |||
public void removed_rule_is_returned() { | |||
dbTester.prepareDbUnit(getClass(), "removed_rule.xml"); | |||
dbClient.ruleDao().insert(dbSession, templateRule.setStatus(RuleStatus.REMOVED)); | |||
dbSession.commit(); | |||
RuleResultSetIterator it = RuleResultSetIterator.create(dbTester.getDbClient(), dbTester.getSession(), 0L); | |||
Map<String, RuleDoc> rulesByKey = rulesByKey(it); | |||
it.close(); |
@@ -1,12 +0,0 @@ | |||
<dataset> | |||
<rules id="1" name="Null Pointer" plugin_rule_key="S001" | |||
plugin_config_key="S1" plugin_name="xoo" | |||
description_format="HTML" description="S001 desc" language="xoo" | |||
priority="4" status="READY" | |||
is_template="[false]" template_id="[null]" | |||
tags="bug,performance" system_tags="cwe" | |||
created_at="1500000000000" updated_at="1600000000000" | |||
/> | |||
</dataset> |
@@ -1,12 +0,0 @@ | |||
<dataset> | |||
<rules id="1" name="Null Pointer" plugin_rule_key="S001" | |||
plugin_config_key="S1" plugin_name="xoo" | |||
description_format="HTML" description="S001 desc" language="xoo" | |||
priority="4" status="REMOVED" | |||
is_template="[false]" template_id="[null]" | |||
tags="bug,performance" system_tags="cwe" | |||
created_at="1500000000000" updated_at="1600000000000" | |||
/> | |||
</dataset> |
@@ -1,23 +0,0 @@ | |||
<dataset> | |||
<!-- Template rule --> | |||
<rules id="1" name="Null Pointer" plugin_rule_key="S001" | |||
plugin_config_key="S1" plugin_name="xoo" | |||
description_format="HTML" description="S001 desc" language="xoo" | |||
priority="4" status="READY" | |||
is_template="[true]" template_id="[null]" | |||
tags="bug,performance" system_tags="cwe" | |||
created_at="1500000000000" updated_at="1600000000000" | |||
/> | |||
<!-- Custom rule --> | |||
<rules id="2" name="Slow" plugin_rule_key="S002" | |||
plugin_config_key="S2" plugin_name="xoo" | |||
description_format="MARKDOWN" description="*S002 desc*" language="xoo" | |||
priority="3" status="BETA" | |||
is_template="[false]" template_id="1" | |||
tags="[null]" system_tags="[null]" | |||
created_at="2000000000000" updated_at="2100000000000" | |||
/> | |||
</dataset> |
@@ -1,12 +0,0 @@ | |||
<dataset> | |||
<rules id="1" name="Null Pointer" plugin_rule_key="S001" | |||
plugin_config_key="S1" plugin_name="xoo" | |||
description_format="HTML" description="S001 desc" language="xoo" | |||
priority="4" status="READY" | |||
is_template="[false]" template_id="[null]" | |||
tags="bug,performance" system_tags="cwe" | |||
created_at="1500000000000" updated_at="1600000000000" | |||
/> | |||
</dataset> |
@@ -1,12 +0,0 @@ | |||
<dataset> | |||
<rules id="1" name="Null Pointer" plugin_rule_key="S001" | |||
plugin_config_key="S1" plugin_name="xoo" | |||
description_format="HTML" description="S001 desc" language="xoo" | |||
priority="4" status="REMOVED" | |||
is_template="[false]" template_id="[null]" | |||
tags="bug,performance" system_tags="cwe" | |||
created_at="1500000000000" updated_at="1600000000000" | |||
/> | |||
</dataset> |
@@ -1,20 +0,0 @@ | |||
<dataset> | |||
<rules id="1" name="Null Pointer" plugin_rule_key="S001" | |||
plugin_config_key="S1" plugin_name="xoo" | |||
description_format="HTML" description="S001 desc" language="xoo" | |||
priority="4" status="READY" | |||
is_template="[false]" template_id="[null]" | |||
tags="bug,performance" system_tags="cwe" | |||
created_at="1500000000000" updated_at="1600000000000" | |||
/> | |||
<rules id="2" name="Slow" plugin_rule_key="S002" | |||
plugin_config_key="S2" plugin_name="xoo" | |||
description_format="MARKDOWN" description="*S002 desc*" language="xoo" | |||
priority="3" status="BETA" | |||
is_template="[true]" template_id="[null]" | |||
tags="[null]" system_tags="[null]" | |||
created_at="2000000000000" updated_at="2100000000000" | |||
/> | |||
</dataset> |