3 * Copyright (C) 2009-2022 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.server.qualityprofile.ws;
22 import com.google.common.collect.ImmutableSet;
23 import java.util.Collections;
24 import java.util.Optional;
25 import org.junit.Rule;
26 import org.junit.Test;
27 import org.sonar.api.rule.RuleKey;
28 import org.sonar.api.rule.RuleStatus;
29 import org.sonar.api.rule.Severity;
30 import org.sonar.api.server.ws.WebService.Param;
31 import org.sonar.api.utils.System2;
32 import org.sonar.db.DbClient;
33 import org.sonar.db.DbSession;
34 import org.sonar.db.DbTester;
35 import org.sonar.db.qualityprofile.ActiveRuleDto;
36 import org.sonar.db.qualityprofile.ActiveRuleKey;
37 import org.sonar.db.qualityprofile.QProfileDto;
38 import org.sonar.db.qualityprofile.QualityProfileTesting;
39 import org.sonar.db.rule.RuleDefinitionDto;
40 import org.sonar.db.rule.RuleTesting;
41 import org.sonar.server.es.EsTester;
42 import org.sonar.server.es.SearchOptions;
43 import org.sonar.server.exceptions.BadRequestException;
44 import org.sonar.server.pushapi.qualityprofile.QualityProfileChangeEventService;
45 import org.sonar.server.qualityprofile.QProfileRules;
46 import org.sonar.server.qualityprofile.QProfileRulesImpl;
47 import org.sonar.server.qualityprofile.builtin.RuleActivator;
48 import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
49 import org.sonar.server.rule.index.RuleIndex;
50 import org.sonar.server.rule.index.RuleIndexer;
51 import org.sonar.server.rule.index.RuleQuery;
52 import org.sonar.server.rule.ws.RuleQueryFactory;
53 import org.sonar.server.tester.UserSessionRule;
54 import org.sonar.server.util.TypeValidations;
55 import org.sonar.server.ws.WsActionTester;
57 import static java.util.Collections.emptyList;
58 import static org.assertj.core.api.Assertions.assertThat;
59 import static org.junit.Assert.fail;
60 import static org.mockito.Mockito.mock;
61 import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_LANGUAGES;
62 import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_QPROFILE;
63 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_KEY;
64 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_RESET;
65 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_RULE;
66 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_SEVERITY;
67 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_TARGET_KEY;
68 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_TARGET_SEVERITY;
70 public class QProfilesWsMediumTest {
73 public UserSessionRule userSessionRule = UserSessionRule.standalone()
76 public EsTester es = EsTester.create();
78 public DbTester dbTester = DbTester.create();
80 private final DbClient dbClient = dbTester.getDbClient();
81 private final DbSession dbSession = dbTester.getSession();
82 private final RuleIndex ruleIndex = new RuleIndex(es.client(), System2.INSTANCE);
83 private final RuleIndexer ruleIndexer = new RuleIndexer(es.client(), dbClient);
84 private final ActiveRuleIndexer activeRuleIndexer = new ActiveRuleIndexer(dbClient, es.client());
85 private final TypeValidations typeValidations = new TypeValidations(emptyList());
86 private final QualityProfileChangeEventService qualityProfileChangeEventService = mock(QualityProfileChangeEventService.class);
87 private final RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, dbClient, typeValidations, userSessionRule);
88 private final QProfileRules qProfileRules = new QProfileRulesImpl(dbClient, ruleActivator, ruleIndex, activeRuleIndexer, qualityProfileChangeEventService);
89 private final QProfileWsSupport qProfileWsSupport = new QProfileWsSupport(dbClient, userSessionRule);
90 private final RuleQueryFactory ruleQueryFactory = new RuleQueryFactory(dbClient);
92 private final WsActionTester wsDeactivateRule = new WsActionTester(new DeactivateRuleAction(dbClient, qProfileRules, userSessionRule, qProfileWsSupport));
93 private final WsActionTester wsDeactivateRules = new WsActionTester(new DeactivateRulesAction(ruleQueryFactory, userSessionRule, qProfileRules, qProfileWsSupport, dbClient));
94 private final WsActionTester wsActivateRule = new WsActionTester(new ActivateRuleAction(dbClient, qProfileRules, userSessionRule, qProfileWsSupport));
95 private final WsActionTester wsActivateRules = new WsActionTester(new ActivateRulesAction(ruleQueryFactory, userSessionRule, qProfileRules, qProfileWsSupport, dbClient));
98 public void deactivate_rule() {
99 QProfileDto profile = createProfile("java");
100 RuleDefinitionDto rule = createRule(profile.getLanguage(), "toto");
101 createActiveRule(rule, profile);
102 ruleIndexer.commitAndIndex(dbSession, rule.getUuid());
103 activeRuleIndexer.indexAll();
105 // 0. Assert No Active Rule for profile
106 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, profile.getKee())).hasSize(1);
108 // 1. Deactivate Rule
109 wsDeactivateRule.newRequest().setMethod("POST")
110 .setParam(PARAM_KEY, profile.getKee())
111 .setParam(PARAM_RULE, rule.getKey().toString())
113 dbSession.clearCache();
115 // 2. Assert ActiveRule in DAO
116 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, profile.getKee())).isEmpty();
120 public void bulk_deactivate_rule() {
121 QProfileDto profile = createProfile("java");
122 RuleDefinitionDto rule0 = createRule(profile.getLanguage(), "toto1");
123 RuleDefinitionDto rule1 = createRule(profile.getLanguage(), "toto2");
124 RuleDefinitionDto rule2 = createRule(profile.getLanguage(), "toto3");
125 RuleDefinitionDto rule3 = createRule(profile.getLanguage(), "toto4");
126 createActiveRule(rule0, profile);
127 createActiveRule(rule2, profile);
128 createActiveRule(rule3, profile);
129 createActiveRule(rule1, profile);
131 activeRuleIndexer.indexAll();
133 // 0. Assert No Active Rule for profile
134 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, profile.getKee())).hasSize(4);
136 // 1. Deactivate Rule
137 wsDeactivateRules.newRequest().setMethod("POST")
138 .setParam(PARAM_TARGET_KEY, profile.getKee())
140 dbSession.clearCache();
142 // 2. Assert ActiveRule in DAO
143 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, profile.getKee())).isEmpty();
147 public void bulk_deactivate_rule_not_all() {
148 QProfileDto profile = createProfile("java");
149 QProfileDto php = createProfile("php");
150 RuleDefinitionDto rule0 = createRule(profile.getLanguage(), "toto1");
151 RuleDefinitionDto rule1 = createRule(profile.getLanguage(), "toto2");
152 createActiveRule(rule0, profile);
153 createActiveRule(rule1, profile);
154 createActiveRule(rule0, php);
155 createActiveRule(rule1, php);
157 activeRuleIndexer.indexAll();
159 // 0. Assert No Active Rule for profile
160 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, profile.getKee())).hasSize(2);
162 // 1. Deactivate Rule
163 wsDeactivateRules.newRequest().setMethod("POST")
164 .setParam(PARAM_TARGET_KEY, profile.getKee())
166 dbSession.clearCache();
168 // 2. Assert ActiveRule in DAO
169 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, profile.getKee())).isEmpty();
170 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, php.getKee())).hasSize(2);
174 public void bulk_deactivate_rule_by_profile() {
175 QProfileDto profile = createProfile("java");
176 RuleDefinitionDto rule0 = createRule(profile.getLanguage(), "hello");
177 RuleDefinitionDto rule1 = createRule(profile.getLanguage(), "world");
178 createActiveRule(rule0, profile);
179 createActiveRule(rule1, profile);
181 activeRuleIndexer.indexAll();
183 // 0. Assert No Active Rule for profile
184 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, profile.getKee())).hasSize(2);
186 // 1. Deactivate Rule
187 wsDeactivateRules.newRequest().setMethod("POST")
188 .setParam(PARAM_TARGET_KEY, profile.getKee())
189 .setParam(Param.TEXT_QUERY, "hello")
191 dbSession.clearCache();
193 // 2. Assert ActiveRule in DAO
194 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, profile.getKee())).hasSize(1);
198 public void activate_rule() {
199 QProfileDto profile = createProfile("java");
200 RuleDefinitionDto rule = createRule(profile.getLanguage(), "toto");
201 ruleIndexer.commitAndIndex(dbSession, rule.getUuid());
203 // 0. Assert No Active Rule for profile
204 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, profile.getKee())).isEmpty();
207 wsActivateRule.newRequest().setMethod("POST")
208 .setParam(PARAM_KEY, profile.getKee())
209 .setParam(PARAM_RULE, rule.getKey().toString())
211 dbSession.clearCache();
213 // 2. Assert ActiveRule in DAO
214 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, profile.getKee())).hasSize(1);
218 public void activate_rule_diff_languages() {
219 QProfileDto profile = createProfile("java");
220 RuleDefinitionDto rule = createRule("php", "toto");
221 ruleIndexer.commitAndIndex(dbSession, rule.getUuid());
223 // 0. Assert No Active Rule for profile
224 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, profile.getKee())).isEmpty();
228 wsActivateRule.newRequest().setMethod("POST")
229 .setParam(PARAM_KEY, profile.getKee())
230 .setParam(PARAM_RULE, rule.getKey().toString())
232 dbSession.clearCache();
234 } catch (BadRequestException e) {
235 assertThat(e.getMessage()).isEqualTo("php rule blah:toto cannot be activated on java profile Pjava");
240 public void activate_rule_override_severity() {
241 QProfileDto profile = createProfile("java");
242 RuleDefinitionDto rule = createRule(profile.getLanguage(), "toto");
243 ruleIndexer.commitAndIndex(dbSession, rule.getUuid());
245 // 0. Assert No Active Rule for profile
246 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, profile.getKee())).isEmpty();
249 wsActivateRule.newRequest().setMethod("POST")
250 .setParam(PARAM_KEY, profile.getKee())
251 .setParam(PARAM_RULE, rule.getKey().toString())
252 .setParam(PARAM_SEVERITY, "MINOR")
254 dbSession.clearCache();
256 // 2. Assert ActiveRule in DAO
257 ActiveRuleKey activeRuleKey = ActiveRuleKey.of(profile, rule.getKey());
259 Optional<ActiveRuleDto> activeRuleDto = dbClient.activeRuleDao().selectByKey(dbSession, activeRuleKey);
260 assertThat(activeRuleDto).isPresent();
261 assertThat(activeRuleDto.get().getSeverityString()).isEqualTo(Severity.MINOR);
265 public void bulk_activate_rule() {
266 QProfileDto profile = createProfile("java");
267 createRule(profile.getLanguage(), "toto");
268 createRule(profile.getLanguage(), "tata");
269 createRule(profile.getLanguage(), "hello");
270 createRule(profile.getLanguage(), "world");
273 // 0. Assert No Active Rule for profile
274 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, profile.getKee())).isEmpty();
277 wsActivateRules.newRequest().setMethod("POST")
278 .setParam(PARAM_TARGET_KEY, profile.getKee())
279 .setParam(PARAM_LANGUAGES, "java")
281 .assertJson(getClass(), "bulk_activate_rule.json");
282 dbSession.clearCache();
284 // 2. Assert ActiveRule in DAO
285 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, profile.getKee())).hasSize(4);
289 public void bulk_activate_rule_not_all() {
290 QProfileDto java = createProfile("java");
291 QProfileDto php = createProfile("php");
292 createRule(java.getLanguage(), "toto");
293 createRule(java.getLanguage(), "tata");
294 createRule(php.getLanguage(), "hello");
295 createRule(php.getLanguage(), "world");
298 // 0. Assert No Active Rule for profile
299 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, php.getKee())).isEmpty();
302 wsActivateRules.newRequest().setMethod("POST")
303 .setParam(PARAM_TARGET_KEY, php.getKee())
304 .setParam(PARAM_LANGUAGES, "php")
306 .assertJson(getClass(), "bulk_activate_rule_not_all.json");
307 dbSession.clearCache();
309 // 2. Assert ActiveRule in DAO
310 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, php.getKee())).hasSize(2);
314 public void bulk_activate_rule_by_query() {
315 QProfileDto profile = createProfile("java");
316 createRule(profile.getLanguage(), "toto");
317 createRule(profile.getLanguage(), "tata");
318 createRule(profile.getLanguage(), "hello");
319 createRule(profile.getLanguage(), "world");
322 // 0. Assert No Active Rule for profile
323 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, profile.getKee())).isEmpty();
325 // 1. Activate Rule with query returning 0 hits
326 wsActivateRules.newRequest().setMethod("POST")
327 .setParam(PARAM_TARGET_KEY, profile.getKee())
328 .setParam(Param.TEXT_QUERY, "php")
330 dbSession.clearCache();
332 // 2. Assert ActiveRule in DAO
333 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, profile.getKee())).isEmpty();
335 // 1. Activate Rule with query returning 1 hits
336 wsActivateRules.newRequest().setMethod("POST")
337 .setParam(PARAM_TARGET_KEY, profile.getKee())
338 .setParam(Param.TEXT_QUERY, "world")
342 // 2. Assert ActiveRule in DAO
343 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, profile.getKee())).hasSize(1);
347 public void bulk_activate_rule_by_query_with_severity() {
348 QProfileDto profile = createProfile("java");
349 RuleDefinitionDto rule0 = createRule(profile.getLanguage(), "toto");
350 RuleDefinitionDto rule1 = createRule(profile.getLanguage(), "tata");
353 // 0. Assert No Active Rule for profile
354 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, profile.getKee())).isEmpty();
356 // 2. Assert ActiveRule with BLOCKER severity
357 assertThat(ruleIndex.search(
358 new RuleQuery().setSeverities(ImmutableSet.of("BLOCKER")),
359 new SearchOptions()).getUuids()).hasSize(2);
361 // 1. Activate Rule with query returning 2 hits
362 wsActivateRules.newRequest().setMethod("POST")
363 .setParam(PARAM_TARGET_KEY, profile.getKee())
364 .setParam(PARAM_TARGET_SEVERITY, "MINOR")
368 // 2. Assert ActiveRule with MINOR severity
369 assertThat(dbClient.activeRuleDao().selectByOrgRuleUuid(dbSession, rule0.getUuid()).get(0).getSeverityString()).isEqualTo("MINOR");
370 assertThat(ruleIndex.searchAll(new RuleQuery()
371 .setQProfile(profile)
372 .setKey(rule0.getKey().toString())
373 .setActiveSeverities(Collections.singleton("MINOR"))
374 .setActivation(true))).toIterable().hasSize(1);
378 public void does_not_return_warnings_when_bulk_activate_on_profile_and_rules_exist_on_another_language_than_profile() {
379 QProfileDto javaProfile = createProfile("java");
380 createRule(javaProfile.getLanguage(), "toto");
381 createRule(javaProfile.getLanguage(), "tata");
382 QProfileDto phpProfile = createProfile("php");
383 createRule(phpProfile.getLanguage(), "hello");
384 createRule(phpProfile.getLanguage(), "world");
388 wsActivateRules.newRequest().setMethod("POST")
389 .setParam(PARAM_TARGET_KEY, javaProfile.getKee())
390 .setParam(PARAM_QPROFILE, javaProfile.getKee())
391 .setParam("activation", "false")
393 .assertJson(getClass(), "does_not_return_warnings_when_bulk_activate_on_profile_and_rules_exist_on_another_language_than_profile.json");
394 dbSession.clearCache();
396 // 2. Assert ActiveRule in DAO
397 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, javaProfile.getKee())).hasSize(2);
401 public void reset() {
402 QProfileDto profile = QualityProfileTesting.newQualityProfileDto().setLanguage("java");
403 QProfileDto childProfile = QualityProfileTesting.newQualityProfileDto().setParentKee(profile.getKee()).setLanguage("java");
404 dbClient.qualityProfileDao().insert(dbSession, profile, childProfile);
406 RuleDefinitionDto rule = createRule(profile.getLanguage(), "rule");
407 ActiveRuleDto active1 = ActiveRuleDto.createFor(profile, rule)
408 .setSeverity(rule.getSeverityString());
409 ActiveRuleDto active2 = ActiveRuleDto.createFor(childProfile, rule)
410 .setSeverity("MINOR");
411 dbClient.activeRuleDao().insert(dbSession, active1);
412 dbClient.activeRuleDao().insert(dbSession, active2);
415 activeRuleIndexer.indexAll();
417 // 0. assert rule child rule is minor
418 Optional<ActiveRuleDto> activeRuleDto = dbClient.activeRuleDao().selectByKey(dbSession, active2.getKey());
419 assertThat(activeRuleDto).isPresent();
420 assertThat(activeRuleDto.get().getSeverityString()).isEqualTo(Severity.MINOR);
422 // 1. reset child rule
423 wsActivateRule.newRequest().setMethod("POST")
424 .setParam(PARAM_KEY, childProfile.getKee())
425 .setParam(PARAM_RULE, rule.getKey().toString())
426 .setParam(PARAM_RESET, "true")
428 dbSession.clearCache();
430 // 2. assert rule child rule is NOT minor
431 activeRuleDto = dbClient.activeRuleDao().selectByKey(dbSession, active2.getKey());
432 assertThat(activeRuleDto).isPresent();
433 assertThat(activeRuleDto.get().getSeverityString()).isNotEqualTo(Severity.MINOR);
436 private QProfileDto createProfile(String lang) {
437 QProfileDto profile = QualityProfileTesting.newQualityProfileDto().setName("P" + lang).setLanguage(lang);
438 dbClient.qualityProfileDao().insert(dbSession, profile);
442 private RuleDefinitionDto createRule(String lang, String id) {
443 RuleDefinitionDto rule = RuleTesting.newRule(RuleKey.of("blah", id))
445 .setSeverity(Severity.BLOCKER)
446 .setStatus(RuleStatus.READY);
447 dbClient.ruleDao().insert(dbSession, rule);
448 ruleIndexer.commitAndIndex(dbSession, rule.getUuid());
452 private ActiveRuleDto createActiveRule(RuleDefinitionDto rule, QProfileDto profile) {
453 ActiveRuleDto activeRule = ActiveRuleDto.createFor(profile, rule)
454 .setSeverity(rule.getSeverityString());
455 dbClient.activeRuleDao().insert(dbSession, activeRule);