import static org.sonar.core.util.Uuids.UUID_EXAMPLE_03;
import static org.sonar.server.qualityprofile.ws.BulkChangeWsResponse.writeResponse;
import static org.sonar.server.qualityprofile.ws.QProfileReference.fromKey;
-import static org.sonar.server.rule.ws.SearchAction.defineRuleSearchParameters;
+import static org.sonar.server.rule.ws.SearchAction.defineGenericRuleSearchParameters;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_ACTIVATE_RULES;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_TARGET_KEY;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_TARGET_SEVERITY;
.setSince("4.4")
.setHandler(this);
- defineRuleSearchParameters(activate);
+ defineGenericRuleSearchParameters(activate);
activate.createParam(PARAM_TARGET_KEY)
.setDescription("Quality Profile key on which the rule activation is done. To retrieve a quality profile key please see <code>api/qualityprofiles/search</code>")
import static org.sonar.core.util.Uuids.UUID_EXAMPLE_04;
import static org.sonar.server.qualityprofile.ws.BulkChangeWsResponse.writeResponse;
-import static org.sonar.server.rule.ws.SearchAction.defineRuleSearchParameters;
+import static org.sonar.server.rule.ws.SearchAction.defineGenericRuleSearchParameters;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.ACTION_DEACTIVATE_RULES;
import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_TARGET_KEY;
.setSince("4.4")
.setHandler(this);
- defineRuleSearchParameters(deactivate);
+ defineGenericRuleSearchParameters(deactivate);
deactivate.createParam(PARAM_TARGET_KEY)
.setDescription("Quality Profile key on which the rule deactivation is done. To retrieve a profile key please see <code>api/qualityprofiles/search</code>")
this.wsSupport = wsSupport;
}
+ /**
+ * Similar to {@link #createRuleQuery(DbSession, Request)} but sets additional fields which are only used
+ * for the rule search WS.
+ */
+ public RuleQuery createRuleSearchQuery(DbSession dbSession, Request request) {
+ RuleQuery query = createRuleQuery(dbSession, request);
+ query.setIsExternal(request.paramAsBoolean(PARAM_IS_EXTERNAL));
+ return query;
+ }
+
/**
* Create a {@link RuleQuery} from a {@link Request}.
* When a profile key is set, the language of the profile is automatically set in the query
query.setInheritance(request.paramAsStrings(PARAM_INHERITANCE));
query.setActiveSeverities(request.paramAsStrings(PARAM_ACTIVE_SEVERITIES));
query.setIsTemplate(request.paramAsBoolean(PARAM_IS_TEMPLATE));
- query.setIsExternal(request.paramAsBoolean(PARAM_IS_EXTERNAL));
query.setTemplateKey(request.param(PARAM_TEMPLATE_KEY));
query.setTypes(toEnums(request.paramAsStrings(PARAM_TYPES), RuleType.class));
query.setKey(request.param(PARAM_RULE_KEY));
public static final String FIELD_PARAMS = "params";
public static final String FIELD_ACTIVES = "actives";
- public static final Set<String> OPTIONAL_FIELDS = ImmutableSet.of(FIELD_REPO, FIELD_NAME, FIELD_CREATED_AT, FIELD_SEVERITY, FIELD_STATUS, FIELD_INTERNAL_KEY, FIELD_IS_EXTERNAL, FIELD_IS_TEMPLATE,
- FIELD_TEMPLATE_KEY, FIELD_TAGS, FIELD_SYSTEM_TAGS, FIELD_LANGUAGE, FIELD_LANGUAGE_NAME, FIELD_HTML_DESCRIPTION, FIELD_MARKDOWN_DESCRIPTION, FIELD_NOTE_LOGIN,
- FIELD_MARKDOWN_NOTE, FIELD_HTML_NOTE,
+ public static final Set<String> OPTIONAL_FIELDS = ImmutableSet.of(FIELD_REPO, FIELD_NAME, FIELD_CREATED_AT, FIELD_SEVERITY, FIELD_STATUS, FIELD_INTERNAL_KEY,
+ FIELD_IS_EXTERNAL, FIELD_IS_TEMPLATE, FIELD_TEMPLATE_KEY, FIELD_TAGS, FIELD_SYSTEM_TAGS, FIELD_LANGUAGE, FIELD_LANGUAGE_NAME, FIELD_HTML_DESCRIPTION,
+ FIELD_MARKDOWN_DESCRIPTION, FIELD_NOTE_LOGIN, FIELD_MARKDOWN_NOTE, FIELD_HTML_NOTE,
FIELD_DEFAULT_DEBT_REM_FUNCTION, FIELD_EFFORT_TO_FIX_DESCRIPTION, FIELD_DEBT_OVERLOADED, FIELD_DEBT_REM_FUNCTION,
FIELD_DEFAULT_REM_FUNCTION, FIELD_GAP_DESCRIPTION, FIELD_REM_FUNCTION_OVERLOADED, FIELD_REM_FUNCTION,
FIELD_PARAMS, FIELD_ACTIVES, FIELD_SCOPE);
.setChangelog(new Change("7.1", "The field 'scope' has been added to the response"))
.setChangelog(new Change("7.1", "The field 'scope' has been added to the 'f' parameter"))
.setChangelog(new Change("7.2", "The field 'isExternal' has been added to the response"))
- .setChangelog(new Change("7.2", "The field 'isExternal' has been added to the 'f' parameter"));;
+ .setChangelog(new Change("7.2", "The field 'isExternal' has been added to the 'f' parameter"));
action.createParam(FACETS)
.setDescription("Comma-separated list of the facets to be computed. No facet is computed by default.")
try (DbSession dbSession = dbClient.openSession(false)) {
SearchRequest searchWsRequest = toSearchWsRequest(request);
SearchOptions context = buildSearchOptions(searchWsRequest);
- RuleQuery query = ruleQueryFactory.createRuleQuery(dbSession, request);
+ RuleQuery query = ruleQueryFactory.createRuleSearchQuery(dbSession, request);
SearchResult searchResult = doSearch(dbSession, query, context);
SearchResponse responseBuilder = buildResponse(dbSession, searchWsRequest, context, searchResult, query);
writeProtobuf(responseBuilder, request, response);
.setHandler(this);
// Rule-specific search parameters
- defineRuleSearchParameters(action);
+ defineGenericRuleSearchParameters(action);
+
+ action
+ .createParam(PARAM_IS_EXTERNAL)
+ .setDescription("Filter external engine rules")
+ .setBooleanPossibleValues()
+ .setSince("7.2");
}
- public static void defineRuleSearchParameters(WebService.NewAction action) {
+ public static void defineGenericRuleSearchParameters(WebService.NewAction action) {
action
.createParam(TEXT_QUERY)
.setMinimumLength(2)
.setDescription("Filter template rules")
.setBooleanPossibleValues();
- action
- .createParam(PARAM_IS_EXTERNAL)
- .setDescription("Filter external engine rules")
- .setBooleanPossibleValues()
- .setSince("7.2");
-
action
.createParam(PARAM_TEMPLATE_KEY)
.setDescription("Key of the template rule to filter on. Used to search for the custom rules based on this template.")
import java.util.HashMap;
import java.util.Map;
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.sonar.api.rule.RuleKey;
import org.sonar.core.issue.DefaultIssue;
import org.sonar.db.protobuf.DbCommons.TextRange;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
public class IssueCreationDateCalculatorTest {
private static final String COMPONENT_UUID = "ab12";
- @Rule
+ @org.junit.Rule
public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule();
+ @org.junit.Rule
+ public ExpectedException exception = ExpectedException.none();
+
private ScmInfoRepository scmInfoRepository = mock(ScmInfoRepository.class);
private IssueFieldsSetter issueUpdater = mock(IssueFieldsSetter.class);
private ActiveRulesHolder activeRulesHolder = mock(ActiveRulesHolder.class);
private Map<String, ScannerPlugin> scannerPlugins = new HashMap<>();
private RuleRepository ruleRepository = mock(RuleRepository.class);
private ScmInfo scmInfo;
+ private Rule rule = mock(Rule.class);
@Before
public void before() {
when(component.getUuid()).thenReturn(COMPONENT_UUID);
calculator = new IssueCreationDateCalculator(analysisMetadataHolder, scmInfoRepository, issueUpdater, activeRulesHolder, ruleRepository);
+ when(ruleRepository.findByKey(ruleKey)).thenReturn(java.util.Optional.of(rule));
when(activeRulesHolder.get(any(RuleKey.class)))
.thenReturn(Optional.absent());
when(activeRulesHolder.get(ruleKey))
assertNoChangeOfCreationDate();
}
+ @Test
+ public void should_fail_if_rule_is_not_found() {
+ previousAnalysisWas(2000L);
+ currentAnalysisIs(3000L);
+
+ when(ruleRepository.findByKey(ruleKey)).thenReturn(java.util.Optional.empty());
+ newIssue();
+
+ exception.expect(IllegalStateException.class);
+ exception.expectMessage("The rule with key 'reop:rule' raised an issue, but no rule with that key was found");
+ run();
+ }
+
@Test
public void should_change_date_if_scm_is_available_and_rule_is_new() {
previousAnalysisWas(2000L);
assertChangeOfCreationDateTo(1200L);
}
+ @Test
+ public void should_backdate_external_issues() {
+ analysisMetadataHolder.setBaseAnalysis(null);
+ currentAnalysisIs(3000L);
+
+ newIssue();
+ when(rule.isExternal()).thenReturn(true);
+ when(issue.getLocations()).thenReturn(DbIssues.Locations.newBuilder().setTextRange(range(2, 3)).build());
+ withScmAt(2, 1200L);
+ withScmAt(3, 1300L);
+
+ run();
+
+ assertChangeOfCreationDateTo(1300L);
+ verifyZeroInteractions(activeRulesHolder);
+ }
+
@Test
public void should_use_primary_location_when_backdating() {
analysisMetadataHolder.setBaseAnalysis(null);
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
-import org.sonar.api.config.internal.MapSettings;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.utils.System2;
import org.sonar.db.DbClient;
private RuleRepositoryImpl ruleRepository;
@org.junit.Rule
- public EsTester es = new EsTester(new RuleIndexDefinition(new MapSettings().asConfig()));
+ public EsTester es = EsTester.create();
private RuleIndexer indexer = new RuleIndexer(es.client(), dbClient);
private ExternalRuleCreator externalRuleCreator = new ExternalRuleCreator(dbClient, System2.INSTANCE, indexer);
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import org.sonar.api.config.internal.MapSettings;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rules.RuleType;
import org.sonar.api.utils.System2;
import org.sonar.server.computation.task.step.ComputationStep;
import org.sonar.server.es.EsTester;
import org.sonar.server.rule.ExternalRuleCreator;
-import org.sonar.server.rule.index.RuleIndexDefinition;
import org.sonar.server.util.cache.DiskCache;
import static java.util.Collections.singletonList;
public BatchReportReaderRule reportReader = new BatchReportReaderRule();
@Rule
public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule()
- .setOrganizationUuid("org-1","qg-uuid-1");
+ .setOrganizationUuid("org-1", "qg-uuid-1");
private DbSession session = db.getSession();
private DbClient dbClient = db.getDbClient();
private ComputationStep step;
@org.junit.Rule
- public EsTester es = new EsTester(new RuleIndexDefinition(new MapSettings().asConfig()));
+ public EsTester es = EsTester.create();
private ExternalRuleCreator externalRuleCreator = mock(ExternalRuleCreator.class);
package org.sonar.server.rule;
import org.junit.Test;
-import org.sonar.api.config.internal.MapSettings;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.utils.System2;
import org.sonar.db.DbSession;
import org.sonar.server.computation.task.projectanalysis.issue.NewExternalRule;
import org.sonar.server.computation.task.projectanalysis.issue.Rule;
import org.sonar.server.es.EsTester;
-import org.sonar.server.rule.index.RuleIndexDefinition;
import org.sonar.server.rule.index.RuleIndexer;
import static org.assertj.core.api.Assertions.assertThat;
@org.junit.Rule
public DbTester dbTester = DbTester.create(System2.INSTANCE);
@org.junit.Rule
- public EsTester es = new EsTester(new RuleIndexDefinition(new MapSettings().asConfig()));
-
+ public EsTester es = EsTester.create();
+
private RuleIndexer indexer = new RuleIndexer(es.client(), dbTester.getDbClient());
private ExternalRuleCreator underTest = new ExternalRuleCreator(dbTester.getDbClient(), System2.INSTANCE, indexer);
private DbSession dbSession = dbTester.getSession();
SearchIdResult<Integer> results = underTest.search(query, new SearchOptions());
assertThat(results.getIds()).hasSize(2);
- // Only template
- query = new RuleQuery().setIsTemplate(true);
+ // Only external
+ query = new RuleQuery().setIsExternal(true);
results = underTest.search(query, new SearchOptions());
assertThat(results.getIds()).containsOnly(ruleIsExternal.getId());
- // Only not template
- query = new RuleQuery().setIsTemplate(false);
+ // Only not external
+ query = new RuleQuery().setIsExternal(false);
results = underTest.search(query, new SearchOptions());
assertThat(results.getIds()).containsOnly(ruleIsNotExternal.getId());
// null => no filter
- query = new RuleQuery().setIsTemplate(null);
+ query = new RuleQuery().setIsExternal(null);
results = underTest.search(query, new SearchOptions());
assertThat(results.getIds()).containsOnly(ruleIsExternal.getId(), ruleIsNotExternal.getId());
}
assertThat(result.isAscendingSort()).isFalse();
assertThat(result.getAvailableSinceLong()).isNotNull();
assertThat(result.getInheritance()).containsOnly(INHERITED, OVERRIDES);
- assertThat(result.isExternal()).isTrue();
assertThat(result.isTemplate()).isTrue();
assertThat(result.getLanguages()).containsOnly(qualityProfile.getLanguage());
assertThat(result.getQueryText()).isEqualTo("S001");
assertThat(def.since()).isEqualTo("4.4");
assertThat(def.isInternal()).isFalse();
assertThat(def.responseExampleAsString()).isNotEmpty();
- assertThat(def.params()).hasSize(23);
+ assertThat(def.params()).hasSize(24);
WebService.Param compareToProfile = def.param("compareToProfile");
assertThat(compareToProfile.since()).isEqualTo("6.5");
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import javax.annotation.Nullable;
import org.sonar.api.batch.sensor.internal.DefaultStorable;
import org.sonar.api.batch.sensor.internal.SensorStorage;
import org.sonar.api.batch.sensor.issue.IssueLocation;
super(null);
}
- public AbstractDefaultIssue(SensorStorage storage) {
+ public AbstractDefaultIssue(@Nullable SensorStorage storage) {
super(storage);
}
super(null);
}
- public DefaultExternalIssue(SensorStorage storage) {
+ public DefaultExternalIssue(@Nullable SensorStorage storage) {
super(storage);
}
super(null);
}
- public DefaultIssue(SensorStorage storage) {
+ public DefaultIssue(@Nullable SensorStorage storage) {
super(storage);
}
}
private static ScannerReport.ExternalIssue createReportExternalIssue(ExternalIssue issue, int componentRef) {
- String primaryMessage = issue.primaryLocation().message();
+ String primaryMessage = Strings.isNullOrEmpty(issue.primaryLocation().message()) ? issue.ruleTitle() : issue.primaryLocation().message();
Severity severity = Severity.valueOf(issue.severity().name());
ScannerReport.ExternalIssue.Builder builder = ScannerReport.ExternalIssue.newBuilder();