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;
22 import java.util.ArrayList;
23 import java.util.List;
25 import java.util.Optional;
26 import java.util.Random;
27 import java.util.stream.IntStream;
28 import javax.annotation.Nullable;
29 import org.junit.Rule;
30 import org.junit.Test;
31 import org.sonar.api.PropertyType;
32 import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
33 import org.sonar.api.rule.RuleStatus;
34 import org.sonar.api.rule.Severity;
35 import org.sonar.api.utils.System2;
36 import org.sonar.db.DbTester;
37 import org.sonar.db.qualityprofile.ActiveRuleParamDto;
38 import org.sonar.db.qualityprofile.OrgActiveRuleDto;
39 import org.sonar.db.qualityprofile.QProfileDto;
40 import org.sonar.db.rule.RuleDefinitionDto;
41 import org.sonar.db.rule.RuleDto;
42 import org.sonar.db.rule.RuleParamDto;
43 import org.sonar.server.es.EsTester;
44 import org.sonar.server.es.SearchOptions;
45 import org.sonar.server.exceptions.BadRequestException;
46 import org.sonar.server.pushapi.qualityprofile.QualityProfileChangeEventService;
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.tester.UserSessionRule;
53 import org.sonar.server.util.IntegerTypeValidation;
54 import org.sonar.server.util.StringTypeValidation;
55 import org.sonar.server.util.TypeValidations;
57 import static com.google.common.collect.ImmutableMap.of;
58 import static java.util.Arrays.asList;
59 import static java.util.Collections.emptyMap;
60 import static java.util.Collections.singleton;
61 import static java.util.Collections.singletonList;
62 import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
63 import static org.assertj.core.api.Assertions.assertThat;
64 import static org.assertj.core.api.Assertions.assertThatThrownBy;
65 import static org.junit.Assert.fail;
66 import static org.mockito.ArgumentMatchers.any;
67 import static org.mockito.ArgumentMatchers.eq;
68 import static org.mockito.Mockito.mock;
69 import static org.mockito.Mockito.verify;
70 import static org.mockito.Mockito.verifyNoInteractions;
71 import static org.sonar.api.rule.Severity.BLOCKER;
72 import static org.sonar.api.rule.Severity.CRITICAL;
73 import static org.sonar.api.rule.Severity.MAJOR;
74 import static org.sonar.api.rule.Severity.MINOR;
75 import static org.sonar.db.rule.RuleTesting.newCustomRule;
76 import static org.sonar.server.qualityprofile.ActiveRuleInheritance.INHERITED;
78 public class QProfileRuleImplTest {
80 private System2 system2 = new AlwaysIncreasingSystem2();
82 public DbTester db = DbTester.create(system2);
84 public EsTester es = EsTester.create();
86 public UserSessionRule userSession = UserSessionRule.standalone();
87 private RuleIndex ruleIndex = new RuleIndex(es.client(), system2);
88 private ActiveRuleIndexer activeRuleIndexer = new ActiveRuleIndexer(db.getDbClient(), es.client());
89 private RuleIndexer ruleIndexer = new RuleIndexer(es.client(), db.getDbClient());
90 private TypeValidations typeValidations = new TypeValidations(asList(new StringTypeValidation(), new IntegerTypeValidation()));
91 private QualityProfileChangeEventService qualityProfileChangeEventService = mock(QualityProfileChangeEventService.class);
93 private RuleActivator ruleActivator = new RuleActivator(system2, db.getDbClient(), typeValidations, userSession);
94 private QProfileRules underTest = new QProfileRulesImpl(db.getDbClient(), ruleActivator, ruleIndex, activeRuleIndexer, qualityProfileChangeEventService);
97 public void system_activates_rule_without_parameters() {
98 RuleDefinitionDto rule = createRule();
99 QProfileDto profile = createProfile(rule);
100 RuleActivation activation = RuleActivation.create(rule.getUuid(), BLOCKER, null);
101 List<ActiveRuleChange> changes = activate(profile, activation);
103 assertThatRuleIsActivated(profile, rule, changes, BLOCKER, null, emptyMap());
104 assertThatProfileIsUpdatedBySystem(profile);
105 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), any(), eq(profile.getLanguage()));
109 public void user_activates_rule_without_parameters() {
111 RuleDefinitionDto rule = createRule();
112 QProfileDto profile = createProfile(rule);
113 RuleActivation activation = RuleActivation.create(rule.getUuid(), BLOCKER, null);
114 List<ActiveRuleChange> changes = activate(profile, activation);
116 assertThatRuleIsActivated(profile, rule, changes, BLOCKER, null, emptyMap());
117 assertThatProfileIsUpdatedByUser(profile);
118 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), any(), eq(profile.getLanguage()));
122 public void activate_rule_with_default_severity_and_parameters() {
123 RuleDefinitionDto rule = createRule();
124 RuleParamDto ruleParam = db.rules().insertRuleParam(rule, p -> p.setName("min").setDefaultValue("10"));
125 QProfileDto profile = createProfile(rule);
127 RuleActivation activation = RuleActivation.create(rule.getUuid());
128 List<ActiveRuleChange> changes = activate(profile, activation);
130 assertThatRuleIsActivated(profile, rule, changes, rule.getSeverityString(), null, of("min", "10"));
131 assertThatProfileIsUpdatedBySystem(profile);
132 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), any(), eq(profile.getLanguage()));
136 public void activate_rule_with_parameters() {
137 RuleDefinitionDto rule = createRule();
138 RuleParamDto ruleParam = db.rules().insertRuleParam(rule, p -> p.setName("min").setDefaultValue("10"));
139 QProfileDto profile = createProfile(rule);
141 RuleActivation activation = RuleActivation.create(rule.getUuid(), null, of(ruleParam.getName(), "15"));
142 List<ActiveRuleChange> changes = activate(profile, activation);
144 assertThatRuleIsActivated(profile, rule, changes, rule.getSeverityString(), null, of("min", "15"));
145 assertThatProfileIsUpdatedBySystem(profile);
146 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), any(), eq(profile.getLanguage()));
150 public void activate_rule_with_default_severity() {
151 RuleDefinitionDto rule = createRule();
152 QProfileDto profile = createProfile(rule);
154 RuleActivation activation = RuleActivation.create(rule.getUuid());
155 List<ActiveRuleChange> changes = activate(profile, activation);
157 assertThatRuleIsActivated(profile, rule, changes, rule.getSeverityString(), null, emptyMap());
158 assertThatProfileIsUpdatedBySystem(profile);
159 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), any(), eq(profile.getLanguage()));
166 public void activate_rule_with_empty_parameter_having_no_default_value() {
167 RuleDefinitionDto rule = createRule();
168 RuleParamDto ruleParam = db.rules().insertRuleParam(rule, p -> p.setName("min").setDefaultValue("10"));
169 QProfileDto profile = createProfile(rule);
171 RuleActivation activation = RuleActivation.create(rule.getUuid(), null, of("min", ""));
172 List<ActiveRuleChange> changes = activate(profile, activation);
174 assertThatRuleIsActivated(profile, rule, changes, rule.getSeverityString(), null, of("min", "10"));
175 assertThatProfileIsUpdatedBySystem(profile);
176 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), any(), eq(profile.getLanguage()));
184 public void activate_rule_with_negative_integer_value_on_parameter_having_no_default_value() {
185 RuleDefinitionDto rule = createRule();
186 RuleParamDto paramWithoutDefault = db.rules().insertRuleParam(rule, p -> p.setName("min").setDefaultValue(null));
187 RuleParamDto paramWithDefault = db.rules().insertRuleParam(rule, p -> p.setName("max").setDefaultValue("10"));
188 QProfileDto profile = createProfile(rule);
190 RuleActivation activation = RuleActivation.create(rule.getUuid(), null, of(paramWithoutDefault.getName(), "-10"));
191 List<ActiveRuleChange> changes = activate(profile, activation);
193 assertThatRuleIsActivated(profile, rule, changes, rule.getSeverityString(), null,
194 of(paramWithoutDefault.getName(), "-10", paramWithDefault.getName(), paramWithDefault.getDefaultValue()));
195 assertThatProfileIsUpdatedBySystem(profile);
196 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), any(), eq(profile.getLanguage()));
200 public void activation_ignores_unsupported_parameters() {
201 RuleDefinitionDto rule = createRule();
202 RuleParamDto param = db.rules().insertRuleParam(rule, p -> p.setName("max").setDefaultValue("10"));
203 QProfileDto profile = createProfile(rule);
205 RuleActivation activation = RuleActivation.create(rule.getUuid(), null, of("xxx", "yyy"));
206 List<ActiveRuleChange> changes = activate(profile, activation);
208 assertThatRuleIsActivated(profile, rule, changes, rule.getSeverityString(), null, of(param.getName(), param.getDefaultValue()));
209 assertThatProfileIsUpdatedBySystem(profile);
210 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), any(), eq(profile.getLanguage()));
214 public void update_an_already_activated_rule() {
215 RuleDefinitionDto rule = createRule();
216 RuleParamDto param = db.rules().insertRuleParam(rule, p -> p.setName("max").setDefaultValue("10"));
217 QProfileDto profile = createProfile(rule);
219 // initial activation
220 RuleActivation activation = RuleActivation.create(rule.getUuid(), MAJOR, null);
221 List<ActiveRuleChange> changes = activate(profile, activation);
222 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
225 RuleActivation updateActivation = RuleActivation.create(rule.getUuid(), CRITICAL, of(param.getName(), "20"));
226 changes = activate(profile, updateActivation);
228 assertThatRuleIsUpdated(profile, rule, CRITICAL, null, of(param.getName(), "20"));
229 assertThatProfileIsUpdatedBySystem(profile);
230 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
234 public void update_activation_with_parameter_without_default_value() {
235 RuleDefinitionDto rule = createRule();
236 RuleParamDto paramWithoutDefault = db.rules().insertRuleParam(rule, p -> p.setName("min").setDefaultValue(null));
237 RuleParamDto paramWithDefault = db.rules().insertRuleParam(rule, p -> p.setName("max").setDefaultValue("10"));
238 QProfileDto profile = createProfile(rule);
240 // initial activation -> param "max" has a default value
241 RuleActivation activation = RuleActivation.create(rule.getUuid());
242 List<ActiveRuleChange> changes = activate(profile, activation);
244 // update param "min", which has no default value
245 RuleActivation updateActivation = RuleActivation.create(rule.getUuid(), MAJOR, of(paramWithoutDefault.getName(), "3"));
246 changes = activate(profile, updateActivation);
247 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
249 assertThatRuleIsUpdated(profile, rule, MAJOR, null, of(paramWithDefault.getName(), "10", paramWithoutDefault.getName(), "3"));
250 assertThatProfileIsUpdatedBySystem(profile);
251 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
255 public void reset_parameter_to_default_value() {
256 RuleDefinitionDto rule = createRule();
257 RuleParamDto paramWithDefault = db.rules().insertRuleParam(rule, p -> p.setName("max").setDefaultValue("10"));
258 QProfileDto profile = createProfile(rule);
260 // initial activation -> param "max" has a default value
261 RuleActivation activation = RuleActivation.create(rule.getUuid(), null, of(paramWithDefault.getName(), "20"));
262 List<ActiveRuleChange> changes = activate(profile, activation);
263 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
265 // reset to default_value
266 RuleActivation updateActivation = RuleActivation.create(rule.getUuid(), null, of(paramWithDefault.getName(), ""));
267 changes = activate(profile, updateActivation);
269 assertThatRuleIsUpdated(profile, rule, rule.getSeverityString(), null, of(paramWithDefault.getName(), "10"));
270 assertThat(changes).hasSize(1);
271 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
275 public void update_activation_removes_parameter_without_default_value() {
276 RuleDefinitionDto rule = createRule();
277 RuleParamDto paramWithoutDefault = db.rules().insertRuleParam(rule, p -> p.setName("min").setDefaultValue(null));
278 RuleParamDto paramWithDefault = db.rules().insertRuleParam(rule, p -> p.setName("max").setDefaultValue("10"));
279 QProfileDto profile = createProfile(rule);
281 // initial activation -> param "max" has a default value
282 RuleActivation activation = RuleActivation.create(rule.getUuid(), null, of(paramWithoutDefault.getName(), "20"));
283 List<ActiveRuleChange> changes = activate(profile, activation);
284 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
287 RuleActivation updateActivation = RuleActivation.create(rule.getUuid(), null, of(paramWithoutDefault.getName(), ""));
288 changes = activate(profile, updateActivation);
290 assertThatRuleIsUpdated(profile, rule, rule.getSeverityString(), null, of(paramWithDefault.getName(), paramWithDefault.getDefaultValue()));
291 assertThat(changes).hasSize(1);
292 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
296 public void update_activation_with_new_parameter() {
297 RuleDefinitionDto rule = createRule();
298 RuleParamDto param = db.rules().insertRuleParam(rule, p -> p.setName("max").setDefaultValue("10"));
299 QProfileDto profile = createProfile(rule);
301 // initial activation -> param "max" has a default value
302 RuleActivation activation = RuleActivation.create(rule.getUuid());
303 List<ActiveRuleChange> changes = activate(profile, activation);
304 db.getDbClient().activeRuleDao().deleteParametersByRuleProfileUuids(db.getSession(), asList(profile.getRulesProfileUuid()));
305 assertThatRuleIsActivated(profile, rule, changes, rule.getSeverityString(), null, emptyMap());
306 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
308 // contrary to activerule, the param is supposed to be inserted but not updated
309 RuleActivation updateActivation = RuleActivation.create(rule.getUuid(), null, of(param.getName(), ""));
310 changes = activate(profile, updateActivation);
312 assertThatRuleIsUpdated(profile, rule, rule.getSeverityString(), null, of(param.getName(), param.getDefaultValue()));
313 assertThat(changes).hasSize(1);
314 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
318 public void ignore_activation_without_changes() {
319 RuleDefinitionDto rule = createRule();
320 QProfileDto profile = createProfile(rule);
322 // initial activation
323 RuleActivation activation = RuleActivation.create(rule.getUuid());
324 List<ActiveRuleChange> changes = activate(profile, activation);
325 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
327 // update with exactly the same severity and params
328 activation = RuleActivation.create(rule.getUuid());
329 changes = activate(profile, activation);
331 assertThat(changes).isEmpty();
332 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
336 public void do_not_change_severity_and_params_if_unset_and_already_activated() {
337 RuleDefinitionDto rule = createRule();
338 RuleParamDto param = db.rules().insertRuleParam(rule, p -> p.setName("max").setDefaultValue("10"));
339 QProfileDto profile = createProfile(rule);
341 // initial activation -> param "max" has a default value
342 RuleActivation activation = RuleActivation.create(rule.getUuid(), BLOCKER, of(param.getName(), "20"));
343 List<ActiveRuleChange> changes = activate(profile, activation);
344 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
347 // update without any severity or params => keep
348 RuleActivation update = RuleActivation.create(rule.getUuid());
349 changes = activate(profile, update);
351 assertThat(changes).isEmpty();
352 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
356 public void fail_to_activate_rule_if_profile_is_on_different_languages() {
357 RuleDefinitionDto rule = createJavaRule();
358 QProfileDto profile = db.qualityProfiles().insert(p -> p.setLanguage("js"));
359 RuleActivation activation = RuleActivation.create(rule.getUuid());
361 expectFailure("java rule " + rule.getKey() + " cannot be activated on js profile " + profile.getKee(), () -> activate(profile, activation));
362 verifyNoInteractions(qualityProfileChangeEventService);
366 public void fail_to_activate_rule_if_rule_has_REMOVED_status() {
367 RuleDefinitionDto rule = db.rules().insert(r -> r.setStatus(RuleStatus.REMOVED));
368 QProfileDto profile = createProfile(rule);
369 RuleActivation activation = RuleActivation.create(rule.getUuid());
371 expectFailure("Rule was removed: " + rule.getKey(), () -> activate(profile, activation));
372 verifyNoInteractions(qualityProfileChangeEventService);
376 public void fail_to_activate_if_template() {
377 RuleDefinitionDto rule = db.rules().insert(r -> r.setIsTemplate(true));
378 QProfileDto profile = createProfile(rule);
379 RuleActivation activation = RuleActivation.create(rule.getUuid());
381 expectFailure("Rule template can't be activated on a Quality profile: " + rule.getKey(), () -> activate(profile, activation));
382 verifyNoInteractions(qualityProfileChangeEventService);
386 public void fail_to_activate_if_invalid_parameter() {
387 RuleDefinitionDto rule = createRule();
388 RuleParamDto param = db.rules().insertRuleParam(rule, p -> p.setName("max").setDefaultValue("10").setType(PropertyType.INTEGER.name()));
389 QProfileDto profile = createProfile(rule);
391 RuleActivation activation = RuleActivation.create(rule.getUuid(), null, of(param.getName(), "foo"));
392 expectFailure("Value 'foo' must be an integer.", () -> activate(profile, activation));
393 verifyNoInteractions(qualityProfileChangeEventService);
397 public void ignore_parameters_when_activating_custom_rule() {
398 RuleDefinitionDto templateRule = db.rules().insert(r -> r.setIsTemplate(true));
399 RuleParamDto templateParam = db.rules().insertRuleParam(templateRule, p -> p.setName("format"));
400 RuleDefinitionDto customRule = db.rules().insert(newCustomRule(templateRule));
401 RuleParamDto customParam = db.rules().insertRuleParam(customRule, p -> p.setName("format").setDefaultValue("txt"));
402 QProfileDto profile = createProfile(customRule);
404 // initial activation
405 RuleActivation activation = RuleActivation.create(customRule.getUuid(), MAJOR, emptyMap());
406 List<ActiveRuleChange> changes = activate(profile, activation);
407 assertThatRuleIsActivated(profile, customRule, null, MAJOR, null, of("format", "txt"));
408 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
410 // update -> parameter is not changed
411 RuleActivation updateActivation = RuleActivation.create(customRule.getUuid(), BLOCKER, of("format", "xml"));
412 changes = activate(profile, updateActivation);
413 assertThatRuleIsActivated(profile, customRule, null, BLOCKER, null, of("format", "txt"));
414 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
418 public void user_deactivates_a_rule() {
420 RuleDefinitionDto rule = createRule();
421 QProfileDto profile = createProfile(rule);
422 RuleActivation activation = RuleActivation.create(rule.getUuid());
423 List<ActiveRuleChange> changes = activate(profile, activation);
424 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
426 changes = deactivate(profile, rule);
427 verifyNoActiveRules();
428 assertThatProfileIsUpdatedByUser(profile);
429 assertThat(changes).hasSize(1);
430 assertThat(changes.get(0).getType()).isEqualTo(ActiveRuleChange.Type.DEACTIVATED);
431 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
435 public void system_deactivates_a_rule() {
436 RuleDefinitionDto rule = createRule();
437 QProfileDto profile = createProfile(rule);
438 RuleActivation activation = RuleActivation.create(rule.getUuid());
439 List<ActiveRuleChange> changes = activate(profile, activation);
440 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
442 changes = deactivate(profile, rule);
443 verifyNoActiveRules();
444 assertThatProfileIsUpdatedBySystem(profile);
445 assertThatChangeIsDeactivation(changes, rule);
446 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
449 private void assertThatChangeIsDeactivation(List<ActiveRuleChange> changes, RuleDefinitionDto rule) {
450 assertThat(changes).hasSize(1);
451 ActiveRuleChange change = changes.get(0);
452 assertThat(change.getType()).isEqualTo(ActiveRuleChange.Type.DEACTIVATED);
453 assertThat(change.getKey().getRuleKey()).isEqualTo(rule.getKey());
457 public void ignore_deactivation_if_rule_is_not_activated() {
458 RuleDefinitionDto rule = createRule();
459 QProfileDto profile = createProfile(rule);
461 List<ActiveRuleChange> changes = deactivate(profile, rule);
462 verifyNoActiveRules();
463 assertThat(changes).isEmpty();
464 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), any(), eq(profile.getLanguage()));
468 public void deactivate_rule_that_has_REMOVED_status() {
469 RuleDefinitionDto rule = createRule();
470 QProfileDto profile = createProfile(rule);
471 RuleActivation activation = RuleActivation.create(rule.getUuid());
472 List<ActiveRuleChange> changes = activate(profile, activation);
473 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
475 rule.setStatus(RuleStatus.REMOVED);
476 db.getDbClient().ruleDao().update(db.getSession(), rule);
478 changes = deactivate(profile, rule);
479 verifyNoActiveRules();
480 assertThatChangeIsDeactivation(changes, rule);
481 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(profile.getLanguage()));
485 public void activation_on_child_profile_is_propagated_to_descendants() {
486 RuleDefinitionDto rule = createRule();
487 QProfileDto parentProfile = createProfile(rule);
488 QProfileDto childProfile = createChildProfile(parentProfile);
489 QProfileDto grandChildProfile = createChildProfile(childProfile);
491 List<ActiveRuleChange> changes = activate(childProfile, RuleActivation.create(rule.getUuid()));
492 assertThatProfileHasNoActiveRules(parentProfile);
493 assertThatRuleIsActivated(childProfile, rule, changes, rule.getSeverityString(), null, emptyMap());
494 assertThatRuleIsActivated(grandChildProfile, rule, changes, rule.getSeverityString(), INHERITED, emptyMap());
495 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), any(), eq(childProfile.getLanguage()));
499 public void update_on_child_profile_is_propagated_to_descendants() {
500 RuleDefinitionDto rule = createRule();
501 RuleParamDto param = db.rules().insertRuleParam(rule);
502 QProfileDto parentProfile = createProfile(rule);
503 QProfileDto childProfile = createChildProfile(parentProfile);
504 QProfileDto grandChildProfile = createChildProfile(childProfile);
506 System.out.println("ACTIVATE ON " + childProfile.getName());
507 RuleActivation initialActivation = RuleActivation.create(rule.getUuid(), MAJOR, of(param.getName(), "foo"));
508 List<ActiveRuleChange> changes = activate(childProfile, initialActivation);
509 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(childProfile.getLanguage()));
511 System.out.println("---------------");
512 System.out.println("ACTIVATE ON " + childProfile.getName());
513 RuleActivation updateActivation = RuleActivation.create(rule.getUuid(), CRITICAL, of(param.getName(), "bar"));
514 changes = activate(childProfile, updateActivation);
515 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(childProfile.getLanguage()));
517 assertThatProfileHasNoActiveRules(parentProfile);
518 assertThatRuleIsUpdated(childProfile, rule, CRITICAL, null, of(param.getName(), "bar"));
519 assertThatRuleIsUpdated(grandChildProfile, rule, CRITICAL, INHERITED, of(param.getName(), "bar"));
520 assertThat(changes).hasSize(2);
521 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(childProfile.getLanguage()));
525 public void override_activation_of_inherited_profile() {
526 RuleDefinitionDto rule = createRule();
527 RuleParamDto param = db.rules().insertRuleParam(rule);
528 QProfileDto parentProfile = createProfile(rule);
529 QProfileDto childProfile = createChildProfile(parentProfile);
530 QProfileDto grandChildProfile = createChildProfile(childProfile);
532 RuleActivation initialActivation = RuleActivation.create(rule.getUuid(), MAJOR, of(param.getName(), "foo"));
533 List<ActiveRuleChange> changes = activate(childProfile, initialActivation);
534 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(childProfile.getLanguage()));
536 RuleActivation overrideActivation = RuleActivation.create(rule.getUuid(), CRITICAL, of(param.getName(), "bar"));
537 changes = activate(grandChildProfile, overrideActivation);
539 assertThatProfileHasNoActiveRules(parentProfile);
540 assertThatRuleIsUpdated(childProfile, rule, MAJOR, null, of(param.getName(), "foo"));
541 assertThatRuleIsUpdated(grandChildProfile, rule, CRITICAL, ActiveRuleInheritance.OVERRIDES, of(param.getName(), "bar"));
542 assertThat(changes).hasSize(1);
543 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(childProfile.getLanguage()));
547 public void updated_activation_on_parent_is_not_propagated_to_overridden_profiles() {
548 RuleDefinitionDto rule = createRule();
549 RuleParamDto param = db.rules().insertRuleParam(rule);
550 QProfileDto parentProfile = createProfile(rule);
551 QProfileDto childProfile = createChildProfile(parentProfile);
552 QProfileDto grandChildProfile = createChildProfile(childProfile);
554 RuleActivation initialActivation = RuleActivation.create(rule.getUuid(), MAJOR, of(param.getName(), "foo"));
555 List<ActiveRuleChange> changes = activate(childProfile, initialActivation);
556 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(childProfile.getLanguage()));
558 RuleActivation overrideActivation = RuleActivation.create(rule.getUuid(), CRITICAL, of(param.getName(), "bar"));
559 changes = activate(grandChildProfile, overrideActivation);
560 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(grandChildProfile.getLanguage()));
562 // update child --> do not touch grandChild
563 RuleActivation updateActivation = RuleActivation.create(rule.getUuid(), BLOCKER, of(param.getName(), "baz"));
564 changes = activate(childProfile, updateActivation);
566 assertThatProfileHasNoActiveRules(parentProfile);
567 assertThatRuleIsUpdated(childProfile, rule, BLOCKER, null, of(param.getName(), "baz"));
568 assertThatRuleIsUpdated(grandChildProfile, rule, CRITICAL, ActiveRuleInheritance.OVERRIDES, of(param.getName(), "bar"));
569 assertThat(changes).hasSize(1);
570 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(childProfile.getLanguage()));
574 public void reset_on_parent_is_not_propagated_to_overridden_profiles() {
575 RuleDefinitionDto rule = createRule();
576 RuleParamDto param = db.rules().insertRuleParam(rule);
577 QProfileDto parentProfile = createProfile(rule);
578 QProfileDto childProfile = createChildProfile(parentProfile);
579 QProfileDto grandChildProfile = createChildProfile(childProfile);
581 RuleActivation initialActivation = RuleActivation.create(rule.getUuid(), MAJOR, of(param.getName(), "foo"));
582 List<ActiveRuleChange> changes = activate(parentProfile, initialActivation);
583 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(parentProfile.getLanguage()));
585 RuleActivation overrideActivation = RuleActivation.create(rule.getUuid(), CRITICAL, of(param.getName(), "bar"));
586 changes = activate(grandChildProfile, overrideActivation);
587 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(grandChildProfile.getLanguage()));
589 // reset parent --> touch child but not grandChild
590 RuleActivation updateActivation = RuleActivation.createReset(rule.getUuid());
591 changes = activate(parentProfile, updateActivation);
593 assertThatRuleIsUpdated(parentProfile, rule, rule.getSeverityString(), null, of(param.getName(), param.getDefaultValue()));
594 assertThatRuleIsUpdated(childProfile, rule, rule.getSeverityString(), INHERITED, of(param.getName(), param.getDefaultValue()));
595 assertThatRuleIsUpdated(grandChildProfile, rule, CRITICAL, ActiveRuleInheritance.OVERRIDES, of(param.getName(), "bar"));
596 assertThat(changes).hasSize(2);
597 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(parentProfile.getLanguage()));
601 public void active_on_parent_a_rule_already_activated_on_child() {
602 RuleDefinitionDto rule = createRule();
603 RuleParamDto param = db.rules().insertRuleParam(rule);
604 QProfileDto parentProfile = createProfile(rule);
605 QProfileDto childProfile = createChildProfile(parentProfile);
607 RuleActivation childActivation = RuleActivation.create(rule.getUuid(), MAJOR, of(param.getName(), "foo"));
608 List<ActiveRuleChange> changes = activate(childProfile, childActivation);
609 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(childProfile.getLanguage()));
611 RuleActivation parentActivation = RuleActivation.create(rule.getUuid(), CRITICAL, of(param.getName(), "bar"));
612 changes = activate(parentProfile, parentActivation);
614 assertThatRuleIsUpdated(parentProfile, rule, CRITICAL, null, of(param.getName(), "bar"));
615 assertThatRuleIsUpdated(childProfile, rule, MAJOR, ActiveRuleInheritance.OVERRIDES, of(param.getName(), "foo"));
616 assertThat(changes).hasSize(2);
617 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(parentProfile.getLanguage()));
621 public void do_not_mark_as_overridden_if_same_values_than_parent() {
622 RuleDefinitionDto rule = createRule();
623 RuleParamDto param = db.rules().insertRuleParam(rule);
624 QProfileDto parentProfile = createProfile(rule);
625 QProfileDto childProfile = createChildProfile(parentProfile);
627 RuleActivation parentActivation = RuleActivation.create(rule.getUuid(), MAJOR, of(param.getName(), "foo"));
628 List<ActiveRuleChange> changes = activate(parentProfile, parentActivation);
629 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(parentProfile.getLanguage()));
631 RuleActivation overrideActivation = RuleActivation.create(rule.getUuid(), MAJOR, of(param.getName(), "foo"));
632 changes = activate(childProfile, overrideActivation);
634 assertThatRuleIsUpdated(childProfile, rule, MAJOR, INHERITED, of(param.getName(), "foo"));
635 assertThat(changes).isEmpty();
636 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(childProfile.getLanguage()));
640 public void propagate_deactivation_on_children() {
641 RuleDefinitionDto rule = createRule();
642 QProfileDto parentProfile = createProfile(rule);
643 QProfileDto childProfile = createChildProfile(parentProfile);
645 RuleActivation activation = RuleActivation.create(rule.getUuid());
646 List<ActiveRuleChange> changes = activate(parentProfile, activation);
647 assertThatRuleIsActivated(parentProfile, rule, changes, rule.getSeverityString(), null, emptyMap());
648 assertThatRuleIsActivated(childProfile, rule, changes, rule.getSeverityString(), INHERITED, emptyMap());
649 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(parentProfile.getLanguage()));
651 changes = deactivate(parentProfile, rule);
652 assertThatProfileHasNoActiveRules(parentProfile);
653 assertThatProfileHasNoActiveRules(childProfile);
654 assertThat(changes).hasSize(2);
655 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(parentProfile.getLanguage()));
659 public void propagate_deactivation_on_children_even_when_overridden() {
660 RuleDefinitionDto rule = createRule();
661 QProfileDto parentProfile = createProfile(rule);
662 QProfileDto childProfile = createChildProfile(parentProfile);
664 RuleActivation activation = RuleActivation.create(rule.getUuid());
665 List<ActiveRuleChange> changes = activate(parentProfile, activation);
666 assertThatRuleIsActivated(parentProfile, rule, changes, rule.getSeverityString(), null, emptyMap());
667 assertThatRuleIsActivated(childProfile, rule, changes, rule.getSeverityString(), INHERITED, emptyMap());
668 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(parentProfile.getLanguage()));
670 activation = RuleActivation.create(rule.getUuid(), CRITICAL, null);
671 changes = activate(childProfile, activation);
672 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(childProfile.getLanguage()));
674 changes = deactivate(parentProfile, rule);
675 assertThatProfileHasNoActiveRules(parentProfile);
676 assertThatProfileHasNoActiveRules(childProfile);
677 assertThat(changes).hasSize(2);
678 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), eq(changes), eq(parentProfile.getLanguage()));
682 public void cannot_deactivate_rule_inherited() {
683 RuleDefinitionDto rule = createRule();
684 QProfileDto parentProfile = createProfile(rule);
685 QProfileDto childProfile = createChildProfile(parentProfile);
687 RuleActivation activation = RuleActivation.create(rule.getUuid());
688 List<ActiveRuleChange> changes = activate(parentProfile, activation);
689 assertThatRuleIsActivated(parentProfile, rule, changes, rule.getSeverityString(), null, emptyMap());
690 assertThatRuleIsActivated(childProfile, rule, changes, rule.getSeverityString(), INHERITED, emptyMap());
692 assertThatThrownBy(() -> deactivate(childProfile, rule))
693 .isInstanceOf(BadRequestException.class)
694 .hasMessageContaining("Cannot deactivate inherited rule");
695 verify(qualityProfileChangeEventService).distributeRuleChangeEvent(any(), any(), eq(parentProfile.getLanguage()));
699 public void reset_child_profile_do_not_change_parent() {
700 RuleDefinitionDto rule = createRule();
701 QProfileDto parentProfile = createProfile(rule);
702 QProfileDto childProfile = createChildProfile(parentProfile);
704 RuleActivation activation = RuleActivation.create(rule.getUuid(), CRITICAL, null);
705 List<ActiveRuleChange> changes = activate(parentProfile, activation);
706 assertThatRuleIsActivated(parentProfile, rule, changes, CRITICAL, null, emptyMap());
707 assertThatRuleIsActivated(childProfile, rule, changes, CRITICAL, INHERITED, emptyMap());
708 assertThat(changes).hasSize(2);
710 RuleActivation childActivation = RuleActivation.create(rule.getUuid(), BLOCKER, null);
711 changes = activate(childProfile, childActivation);
712 assertThatRuleIsUpdated(childProfile, rule, BLOCKER, ActiveRuleInheritance.OVERRIDES, emptyMap());
713 assertThat(changes).hasSize(1);
715 RuleActivation resetActivation = RuleActivation.createReset(rule.getUuid());
716 changes = activate(childProfile, resetActivation);
717 assertThatRuleIsUpdated(childProfile, rule, CRITICAL, INHERITED, emptyMap());
718 assertThatRuleIsUpdated(parentProfile, rule, CRITICAL, null, emptyMap());
719 assertThat(changes).hasSize(1);
724 public void reset_parent_is_not_propagated_when_child_overrides() {
725 RuleDefinitionDto rule = createRule();
726 QProfileDto baseProfile = createProfile(rule);
727 QProfileDto childProfile = createChildProfile(baseProfile);
728 QProfileDto grandChildProfile = createChildProfile(childProfile);
730 RuleActivation activation = RuleActivation.create(rule.getUuid(), CRITICAL, null);
731 List<ActiveRuleChange> changes = activate(baseProfile, activation);
732 assertThatRuleIsActivated(baseProfile, rule, changes, CRITICAL, null, emptyMap());
733 assertThatRuleIsActivated(childProfile, rule, changes, CRITICAL, INHERITED, emptyMap());
734 assertThatRuleIsActivated(grandChildProfile, rule, changes, CRITICAL, INHERITED, emptyMap());
735 assertThat(changes).hasSize(3);
737 RuleActivation childActivation = RuleActivation.create(rule.getUuid(), BLOCKER, null);
738 changes = activate(childProfile, childActivation);
739 assertThatRuleIsUpdated(childProfile, rule, BLOCKER, ActiveRuleInheritance.OVERRIDES, emptyMap());
740 assertThatRuleIsUpdated(grandChildProfile, rule, BLOCKER, INHERITED, emptyMap());
741 assertThat(changes).hasSize(2);
743 // Reset on parent do not change child nor grandchild
744 RuleActivation resetActivation = RuleActivation.createReset(rule.getUuid());
745 changes = activate(baseProfile, resetActivation);
746 assertThatRuleIsUpdated(baseProfile, rule, rule.getSeverityString(), null, emptyMap());
747 assertThatRuleIsUpdated(childProfile, rule, BLOCKER, ActiveRuleInheritance.OVERRIDES, emptyMap());
748 assertThatRuleIsUpdated(grandChildProfile, rule, BLOCKER, INHERITED, emptyMap());
749 assertThat(changes).hasSize(1);
751 // Reset on child change grandchild
752 resetActivation = RuleActivation.createReset(rule.getUuid());
753 changes = activate(childProfile, resetActivation);
754 assertThatRuleIsUpdated(baseProfile, rule, rule.getSeverityString(), null, emptyMap());
755 assertThatRuleIsUpdated(childProfile, rule, rule.getSeverityString(), INHERITED, emptyMap());
756 assertThatRuleIsUpdated(grandChildProfile, rule, rule.getSeverityString(), INHERITED, emptyMap());
757 assertThat(changes).hasSize(2);
761 public void ignore_reset_if_not_activated() {
762 RuleDefinitionDto rule = createRule();
763 QProfileDto parentProfile = createProfile(rule);
764 createChildProfile(parentProfile);
766 RuleActivation resetActivation = RuleActivation.createReset(rule.getUuid());
767 List<ActiveRuleChange> changes = activate(parentProfile, resetActivation);
768 verifyNoActiveRules();
769 assertThat(changes).isEmpty();
773 public void bulk_activation() {
774 int bulkSize = SearchOptions.MAX_PAGE_SIZE + 10 + new Random().nextInt(100);
775 String language = randomAlphanumeric(10);
776 String repositoryKey = randomAlphanumeric(10);
777 QProfileDto profile = db.qualityProfiles().insert(p -> p.setLanguage(language));
779 List<RuleDto> rules = new ArrayList<>();
780 IntStream.rangeClosed(1, bulkSize).forEach(
781 i -> rules.add(db.rules().insertRule(r -> r.setLanguage(language).setRepositoryKey(repositoryKey))));
783 verifyNoActiveRules();
784 ruleIndexer.indexAll();
786 RuleQuery ruleQuery = new RuleQuery()
787 .setRepositories(singletonList(repositoryKey));
789 BulkChangeResult bulkChangeResult = underTest.bulkActivateAndCommit(db.getSession(), profile, ruleQuery, MINOR);
791 assertThat(bulkChangeResult.countFailed()).isZero();
792 assertThat(bulkChangeResult.countSucceeded()).isEqualTo(bulkSize);
793 assertThat(bulkChangeResult.getChanges()).hasSize(bulkSize);
794 assertThat(db.getDbClient().activeRuleDao().selectByProfile(db.getSession(), profile)).hasSize(bulkSize);
795 rules.stream().forEach(
796 r -> assertThatRuleIsActivated(profile, r.getDefinition(), null, MINOR, null, emptyMap()));
800 public void bulk_deactivation() {
801 int bulkSize = SearchOptions.MAX_PAGE_SIZE + 10 + new Random().nextInt(100);
802 String language = randomAlphanumeric(10);
803 String repositoryKey = randomAlphanumeric(10);
804 QProfileDto profile = db.qualityProfiles().insert(p -> p.setLanguage(language));
806 List<RuleDto> rules = new ArrayList<>();
807 IntStream.rangeClosed(1, bulkSize).forEach(
808 i -> rules.add(db.rules().insertRule(r -> r.setLanguage(language).setRepositoryKey(repositoryKey))));
810 verifyNoActiveRules();
811 ruleIndexer.indexAll();
813 RuleQuery ruleQuery = new RuleQuery()
814 .setRepositories(singletonList(repositoryKey));
816 BulkChangeResult bulkChangeResult = underTest.bulkActivateAndCommit(db.getSession(), profile, ruleQuery, MINOR);
818 assertThat(bulkChangeResult.countFailed()).isZero();
819 assertThat(bulkChangeResult.countSucceeded()).isEqualTo(bulkSize);
820 assertThat(bulkChangeResult.getChanges()).hasSize(bulkSize);
821 assertThat(db.getDbClient().activeRuleDao().selectByProfile(db.getSession(), profile)).hasSize(bulkSize);
823 // Now deactivate all rules
824 bulkChangeResult = underTest.bulkDeactivateAndCommit(db.getSession(), profile, ruleQuery);
826 assertThat(bulkChangeResult.countFailed()).isZero();
827 assertThat(bulkChangeResult.countSucceeded()).isEqualTo(bulkSize);
828 assertThat(bulkChangeResult.getChanges()).hasSize(bulkSize);
829 assertThat(db.getDbClient().activeRuleDao().selectByProfile(db.getSession(), profile)).isEmpty();
830 rules.stream().forEach(
831 r -> assertThatRuleIsNotPresent(profile, r.getDefinition()));
835 public void bulk_deactivation_ignores_errors() {
836 RuleDefinitionDto rule = createRule();
837 QProfileDto parentProfile = createProfile(rule);
838 QProfileDto childProfile = createChildProfile(parentProfile);
840 List<ActiveRuleChange> changes = activate(parentProfile, RuleActivation.create(rule.getUuid()));
841 assertThatRuleIsActivated(parentProfile, rule, null, rule.getSeverityString(), null, emptyMap());
842 assertThatRuleIsActivated(childProfile, rule, null, rule.getSeverityString(), INHERITED, emptyMap());
844 ruleIndexer.indexAll();
846 RuleQuery ruleQuery = new RuleQuery()
847 .setQProfile(childProfile);
848 BulkChangeResult bulkChangeResult = underTest.bulkDeactivateAndCommit(db.getSession(), childProfile, ruleQuery);
850 assertThat(bulkChangeResult.countFailed()).isOne();
851 assertThat(bulkChangeResult.countSucceeded()).isZero();
852 assertThat(bulkChangeResult.getChanges()).isEmpty();
853 assertThatRuleIsActivated(parentProfile, rule, null, rule.getSeverityString(), null, emptyMap());
854 assertThatRuleIsActivated(childProfile, rule, null, rule.getSeverityString(), INHERITED, emptyMap());
858 public void bulk_change_severity() {
859 RuleDefinitionDto rule1 = createJavaRule();
860 RuleDefinitionDto rule2 = createJavaRule();
861 QProfileDto parentProfile = createProfile(rule1);
862 QProfileDto childProfile = createChildProfile(parentProfile);
863 QProfileDto grandchildProfile = createChildProfile(childProfile);
865 activate(parentProfile, RuleActivation.create(rule1.getUuid()));
866 activate(parentProfile, RuleActivation.create(rule2.getUuid()));
868 ruleIndexer.indexAll();
870 RuleQuery query = new RuleQuery()
871 .setRuleKey(rule1.getRuleKey())
872 .setQProfile(parentProfile);
873 BulkChangeResult result = underTest.bulkActivateAndCommit(db.getSession(), parentProfile, query, "BLOCKER");
875 assertThat(result.getChanges()).hasSize(3);
876 assertThat(result.countSucceeded()).isOne();
877 assertThat(result.countFailed()).isZero();
879 // Rule1 must be activated with BLOCKER on all profiles
880 assertThatRuleIsActivated(parentProfile, rule1, null, BLOCKER, null, emptyMap());
881 assertThatRuleIsActivated(childProfile, rule1, null, BLOCKER, INHERITED, emptyMap());
882 assertThatRuleIsActivated(grandchildProfile, rule1, null, BLOCKER, INHERITED, emptyMap());
884 // Rule2 did not changed
885 assertThatRuleIsActivated(parentProfile, rule2, null, rule2.getSeverityString(), null, emptyMap());
886 assertThatRuleIsActivated(childProfile, rule2, null, rule2.getSeverityString(), INHERITED, emptyMap());
887 assertThatRuleIsActivated(grandchildProfile, rule2, null, rule2.getSeverityString(), INHERITED, emptyMap());
891 public void delete_rule_from_all_profiles() {
892 RuleDefinitionDto rule = createRule();
893 QProfileDto parentProfile = createProfile(rule);
894 QProfileDto childProfile = createChildProfile(parentProfile);
895 QProfileDto grandChildProfile = createChildProfile(childProfile);
897 RuleActivation activation = RuleActivation.create(rule.getUuid(), CRITICAL, null);
898 activate(parentProfile, activation);
900 RuleActivation overrideActivation = RuleActivation.create(rule.getUuid(), BLOCKER, null);
901 activate(grandChildProfile, overrideActivation);
903 // Reset on parent do not change child nor grandchild
904 List<ActiveRuleChange> changes = underTest.deleteRule(db.getSession(), rule);
906 assertThatRuleIsNotPresent(parentProfile, rule);
907 assertThatRuleIsNotPresent(childProfile, rule);
908 assertThatRuleIsNotPresent(grandChildProfile, rule);
910 .extracting(ActiveRuleChange::getType)
911 .containsOnly(ActiveRuleChange.Type.DEACTIVATED)
916 public void activation_fails_when_profile_is_built_in() {
917 RuleDefinitionDto rule = createRule();
918 QProfileDto builtInProfile = db.qualityProfiles().insert(p -> p.setLanguage(rule.getLanguage()).setIsBuiltIn(true));
920 assertThatThrownBy(() -> {
921 underTest.activateAndCommit(db.getSession(), builtInProfile, singleton(RuleActivation.create(rule.getUuid())));
923 .isInstanceOf(IllegalArgumentException.class)
924 .hasMessage("The built-in profile " + builtInProfile.getName() + " is read-only and can't be updated");
927 private void assertThatProfileHasNoActiveRules(QProfileDto profile) {
928 List<OrgActiveRuleDto> activeRules = db.getDbClient().activeRuleDao().selectByProfile(db.getSession(), profile);
929 assertThat(activeRules).isEmpty();
932 private List<ActiveRuleChange> deactivate(QProfileDto profile, RuleDefinitionDto rule) {
933 return underTest.deactivateAndCommit(db.getSession(), profile, singleton(rule.getUuid()));
936 private List<ActiveRuleChange> activate(QProfileDto profile, RuleActivation activation) {
937 return underTest.activateAndCommit(db.getSession(), profile, singleton(activation));
940 private QProfileDto createProfile(RuleDefinitionDto rule) {
941 return db.qualityProfiles().insert(p -> p.setLanguage(rule.getLanguage()));
944 private QProfileDto createChildProfile(QProfileDto parent) {
945 return db.qualityProfiles().insert(p -> p
946 .setLanguage(parent.getLanguage())
947 .setParentKee(parent.getKee())
948 .setName("Child of " + parent.getName()));
951 private void assertThatProfileIsUpdatedByUser(QProfileDto profile) {
952 QProfileDto loaded = db.getDbClient().qualityProfileDao().selectByUuid(db.getSession(), profile.getKee());
953 assertThat(loaded.getUserUpdatedAt()).isNotNull();
954 assertThat(loaded.getRulesUpdatedAt()).isNotEmpty();
957 private void assertThatProfileIsUpdatedBySystem(QProfileDto profile) {
958 QProfileDto loaded = db.getDbClient().qualityProfileDao().selectByUuid(db.getSession(), profile.getKee());
959 assertThat(loaded.getUserUpdatedAt()).isNull();
960 assertThat(loaded.getRulesUpdatedAt()).isNotEmpty();
963 private void assertThatRuleIsActivated(QProfileDto profile, RuleDefinitionDto rule, @Nullable List<ActiveRuleChange> changes,
964 String expectedSeverity, @Nullable ActiveRuleInheritance expectedInheritance, Map<String, String> expectedParams) {
965 OrgActiveRuleDto activeRule = db.getDbClient().activeRuleDao().selectByProfile(db.getSession(), profile)
967 .filter(ar -> ar.getRuleKey().equals(rule.getKey()))
969 .orElseThrow(IllegalStateException::new);
971 assertThat(activeRule.getSeverityString()).isEqualTo(expectedSeverity);
972 assertThat(activeRule.getInheritance()).isEqualTo(expectedInheritance != null ? expectedInheritance.name() : null);
974 List<ActiveRuleParamDto> params = db.getDbClient().activeRuleDao().selectParamsByActiveRuleUuid(db.getSession(), activeRule.getUuid());
975 assertThat(params).hasSize(expectedParams.size());
977 if (changes != null) {
978 ActiveRuleChange change = changes.stream()
979 .filter(c -> c.getActiveRule().getUuid().equals(activeRule.getUuid()))
980 .findFirst().orElseThrow(IllegalStateException::new);
981 assertThat(change.getInheritance()).isEqualTo(expectedInheritance);
982 assertThat(change.getSeverity()).isEqualTo(expectedSeverity);
983 assertThat(change.getType()).isEqualTo(ActiveRuleChange.Type.ACTIVATED);
987 private void assertThatRuleIsNotPresent(QProfileDto profile, RuleDefinitionDto rule) {
988 Optional<OrgActiveRuleDto> activeRule = db.getDbClient().activeRuleDao().selectByProfile(db.getSession(), profile)
990 .filter(ar -> ar.getRuleKey().equals(rule.getKey()))
993 assertThat(activeRule).isEmpty();
996 private void assertThatRuleIsUpdated(QProfileDto profile, RuleDefinitionDto rule,
997 String expectedSeverity, @Nullable ActiveRuleInheritance expectedInheritance, Map<String, String> expectedParams) {
998 OrgActiveRuleDto activeRule = db.getDbClient().activeRuleDao().selectByProfile(db.getSession(), profile)
1000 .filter(ar -> ar.getRuleKey().equals(rule.getKey()))
1002 .orElseThrow(IllegalStateException::new);
1004 assertThat(activeRule.getSeverityString()).isEqualTo(expectedSeverity);
1005 assertThat(activeRule.getInheritance()).isEqualTo(expectedInheritance != null ? expectedInheritance.name() : null);
1007 List<ActiveRuleParamDto> params = db.getDbClient().activeRuleDao().selectParamsByActiveRuleUuid(db.getSession(), activeRule.getUuid());
1008 assertThat(params).hasSize(expectedParams.size());
1011 private void expectFailure(String expectedMessage, Runnable runnable) {
1015 } catch (BadRequestException e) {
1016 assertThat(e.getMessage()).isEqualTo(expectedMessage);
1018 verifyNoActiveRules();
1021 private void verifyNoActiveRules() {
1022 assertThat(db.countRowsOfTable(db.getSession(), "active_rules")).isZero();
1025 private RuleDefinitionDto createRule() {
1026 return db.rules().insert(r -> r.setSeverity(Severity.MAJOR));
1029 private RuleDefinitionDto createJavaRule() {
1030 return db.rules().insert(r -> r.setSeverity(Severity.MAJOR).setLanguage("java"));