]> source.dussan.org Git - sonarqube.git/blob
8afc5b9adff806019c1715b6f4d255df73e26feb
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2020 SonarSource SA
4  * mailto:info AT sonarsource DOT com
5  *
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.
10  *
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.
15  *
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.
19  */
20 package org.sonar.server.qualityprofile;
21
22 import java.util.ArrayList;
23 import java.util.List;
24 import java.util.Map;
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.junit.rules.ExpectedException;
32 import org.sonar.api.PropertyType;
33 import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
34 import org.sonar.api.rule.RuleStatus;
35 import org.sonar.api.rule.Severity;
36 import org.sonar.api.utils.System2;
37 import org.sonar.db.DbTester;
38 import org.sonar.db.qualityprofile.ActiveRuleParamDto;
39 import org.sonar.db.qualityprofile.OrgActiveRuleDto;
40 import org.sonar.db.qualityprofile.QProfileDto;
41 import org.sonar.db.rule.RuleDefinitionDto;
42 import org.sonar.db.rule.RuleDto;
43 import org.sonar.db.rule.RuleParamDto;
44 import org.sonar.server.es.EsTester;
45 import org.sonar.server.es.SearchOptions;
46 import org.sonar.server.exceptions.BadRequestException;
47 import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
48 import org.sonar.server.rule.index.RuleIndex;
49 import org.sonar.server.rule.index.RuleIndexer;
50 import org.sonar.server.rule.index.RuleQuery;
51 import org.sonar.server.tester.UserSessionRule;
52 import org.sonar.server.util.IntegerTypeValidation;
53 import org.sonar.server.util.StringTypeValidation;
54 import org.sonar.server.util.TypeValidations;
55
56 import static com.google.common.collect.ImmutableMap.of;
57 import static java.util.Arrays.asList;
58 import static java.util.Collections.emptyMap;
59 import static java.util.Collections.singleton;
60 import static java.util.Collections.singletonList;
61 import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
62 import static org.assertj.core.api.Assertions.assertThat;
63 import static org.junit.Assert.fail;
64 import static org.sonar.api.rule.Severity.BLOCKER;
65 import static org.sonar.api.rule.Severity.CRITICAL;
66 import static org.sonar.api.rule.Severity.MAJOR;
67 import static org.sonar.api.rule.Severity.MINOR;
68 import static org.sonar.db.rule.RuleTesting.newCustomRule;
69 import static org.sonar.server.qualityprofile.ActiveRuleInheritance.INHERITED;
70
71 public class QProfileRuleImplTest {
72
73   @Rule
74   public ExpectedException expectedException = ExpectedException.none();
75
76   private System2 system2 = new AlwaysIncreasingSystem2();
77   @Rule
78   public DbTester db = DbTester.create(system2);
79   @Rule
80   public EsTester es = EsTester.create();
81   @Rule
82   public UserSessionRule userSession = UserSessionRule.standalone();
83   private RuleIndex ruleIndex = new RuleIndex(es.client(), system2);
84   private ActiveRuleIndexer activeRuleIndexer = new ActiveRuleIndexer(db.getDbClient(), es.client());
85   private RuleIndexer ruleIndexer = new RuleIndexer(es.client(), db.getDbClient());
86   private TypeValidations typeValidations = new TypeValidations(asList(new StringTypeValidation(), new IntegerTypeValidation()));
87
88   private RuleActivator ruleActivator = new RuleActivator(system2, db.getDbClient(), typeValidations, userSession);
89   private QProfileRules underTest = new QProfileRulesImpl(db.getDbClient(), ruleActivator, ruleIndex, activeRuleIndexer);
90
91   @Test
92   public void system_activates_rule_without_parameters() {
93     RuleDefinitionDto rule = createRule();
94     QProfileDto profile = createProfile(rule);
95     RuleActivation activation = RuleActivation.create(rule.getUuid(), BLOCKER, null);
96     List<ActiveRuleChange> changes = activate(profile, activation);
97
98     assertThatRuleIsActivated(profile, rule, changes, BLOCKER, null, emptyMap());
99     assertThatProfileIsUpdatedBySystem(profile);
100   }
101
102   @Test
103   public void user_activates_rule_without_parameters() {
104     userSession.logIn();
105     RuleDefinitionDto rule = createRule();
106     QProfileDto profile = createProfile(rule);
107     RuleActivation activation = RuleActivation.create(rule.getUuid(), BLOCKER, null);
108     List<ActiveRuleChange> changes = activate(profile, activation);
109
110     assertThatRuleIsActivated(profile, rule, changes, BLOCKER, null, emptyMap());
111     assertThatProfileIsUpdatedByUser(profile);
112   }
113
114   @Test
115   public void activate_rule_with_default_severity_and_parameters() {
116     RuleDefinitionDto rule = createRule();
117     RuleParamDto ruleParam = db.rules().insertRuleParam(rule, p -> p.setName("min").setDefaultValue("10"));
118     QProfileDto profile = createProfile(rule);
119
120     RuleActivation activation = RuleActivation.create(rule.getUuid());
121     List<ActiveRuleChange> changes = activate(profile, activation);
122
123     assertThatRuleIsActivated(profile, rule, changes, rule.getSeverityString(), null, of("min", "10"));
124     assertThatProfileIsUpdatedBySystem(profile);
125   }
126
127   @Test
128   public void activate_rule_with_parameters() {
129     RuleDefinitionDto rule = createRule();
130     RuleParamDto ruleParam = db.rules().insertRuleParam(rule, p -> p.setName("min").setDefaultValue("10"));
131     QProfileDto profile = createProfile(rule);
132
133     RuleActivation activation = RuleActivation.create(rule.getUuid(), null, of(ruleParam.getName(), "15"));
134     List<ActiveRuleChange> changes = activate(profile, activation);
135
136     assertThatRuleIsActivated(profile, rule, changes, rule.getSeverityString(), null, of("min", "15"));
137     assertThatProfileIsUpdatedBySystem(profile);
138   }
139
140   @Test
141   public void activate_rule_with_default_severity() {
142     RuleDefinitionDto rule = createRule();
143     QProfileDto profile = createProfile(rule);
144
145     RuleActivation activation = RuleActivation.create(rule.getUuid());
146     List<ActiveRuleChange> changes = activate(profile, activation);
147
148     assertThatRuleIsActivated(profile, rule, changes, rule.getSeverityString(), null, emptyMap());
149     assertThatProfileIsUpdatedBySystem(profile);
150   }
151
152   /**
153    * SONAR-5841
154    */
155   @Test
156   public void activate_rule_with_empty_parameter_having_no_default_value() {
157     RuleDefinitionDto rule = createRule();
158     RuleParamDto ruleParam = db.rules().insertRuleParam(rule, p -> p.setName("min").setDefaultValue("10"));
159     QProfileDto profile = createProfile(rule);
160
161     RuleActivation activation = RuleActivation.create(rule.getUuid(), null, of("min", ""));
162     List<ActiveRuleChange> changes = activate(profile, activation);
163
164     assertThatRuleIsActivated(profile, rule, changes, rule.getSeverityString(), null, of("min", "10"));
165     assertThatProfileIsUpdatedBySystem(profile);
166   }
167
168   /**
169    * //   * SONAR-5840
170    * //
171    */
172   @Test
173   public void activate_rule_with_negative_integer_value_on_parameter_having_no_default_value() {
174     RuleDefinitionDto rule = createRule();
175     RuleParamDto paramWithoutDefault = db.rules().insertRuleParam(rule, p -> p.setName("min").setDefaultValue(null));
176     RuleParamDto paramWithDefault = db.rules().insertRuleParam(rule, p -> p.setName("max").setDefaultValue("10"));
177     QProfileDto profile = createProfile(rule);
178
179     RuleActivation activation = RuleActivation.create(rule.getUuid(), null, of(paramWithoutDefault.getName(), "-10"));
180     List<ActiveRuleChange> changes = activate(profile, activation);
181
182     assertThatRuleIsActivated(profile, rule, changes, rule.getSeverityString(), null,
183       of(paramWithoutDefault.getName(), "-10", paramWithDefault.getName(), paramWithDefault.getDefaultValue()));
184     assertThatProfileIsUpdatedBySystem(profile);
185   }
186
187   @Test
188   public void activation_ignores_unsupported_parameters() {
189     RuleDefinitionDto rule = createRule();
190     RuleParamDto param = db.rules().insertRuleParam(rule, p -> p.setName("max").setDefaultValue("10"));
191     QProfileDto profile = createProfile(rule);
192
193     RuleActivation activation = RuleActivation.create(rule.getUuid(), null, of("xxx", "yyy"));
194     List<ActiveRuleChange> changes = activate(profile, activation);
195
196     assertThatRuleIsActivated(profile, rule, changes, rule.getSeverityString(), null, of(param.getName(), param.getDefaultValue()));
197     assertThatProfileIsUpdatedBySystem(profile);
198   }
199
200   @Test
201   public void update_an_already_activated_rule() {
202     RuleDefinitionDto rule = createRule();
203     RuleParamDto param = db.rules().insertRuleParam(rule, p -> p.setName("max").setDefaultValue("10"));
204     QProfileDto profile = createProfile(rule);
205
206     // initial activation
207     RuleActivation activation = RuleActivation.create(rule.getUuid(), MAJOR, null);
208     activate(profile, activation);
209
210     // update
211     RuleActivation updateActivation = RuleActivation.create(rule.getUuid(), CRITICAL, of(param.getName(), "20"));
212     List<ActiveRuleChange> changes = activate(profile, updateActivation);
213
214     assertThatRuleIsUpdated(profile, rule, CRITICAL, null, of(param.getName(), "20"));
215     assertThatProfileIsUpdatedBySystem(profile);
216   }
217
218   @Test
219   public void update_activation_with_parameter_without_default_value() {
220     RuleDefinitionDto rule = createRule();
221     RuleParamDto paramWithoutDefault = db.rules().insertRuleParam(rule, p -> p.setName("min").setDefaultValue(null));
222     RuleParamDto paramWithDefault = db.rules().insertRuleParam(rule, p -> p.setName("max").setDefaultValue("10"));
223     QProfileDto profile = createProfile(rule);
224
225     // initial activation -> param "max" has a default value
226     RuleActivation activation = RuleActivation.create(rule.getUuid());
227     activate(profile, activation);
228
229     // update param "min", which has no default value
230     RuleActivation updateActivation = RuleActivation.create(rule.getUuid(), MAJOR, of(paramWithoutDefault.getName(), "3"));
231     List<ActiveRuleChange> changes = activate(profile, updateActivation);
232
233     assertThatRuleIsUpdated(profile, rule, MAJOR, null, of(paramWithDefault.getName(), "10", paramWithoutDefault.getName(), "3"));
234     assertThatProfileIsUpdatedBySystem(profile);
235   }
236
237   @Test
238   public void reset_parameter_to_default_value() {
239     RuleDefinitionDto rule = createRule();
240     RuleParamDto paramWithDefault = db.rules().insertRuleParam(rule, p -> p.setName("max").setDefaultValue("10"));
241     QProfileDto profile = createProfile(rule);
242
243     // initial activation -> param "max" has a default value
244     RuleActivation activation = RuleActivation.create(rule.getUuid(), null, of(paramWithDefault.getName(), "20"));
245     activate(profile, activation);
246
247     // reset to default_value
248     RuleActivation updateActivation = RuleActivation.create(rule.getUuid(), null, of(paramWithDefault.getName(), ""));
249     List<ActiveRuleChange> changes = activate(profile, updateActivation);
250
251     assertThatRuleIsUpdated(profile, rule, rule.getSeverityString(), null, of(paramWithDefault.getName(), "10"));
252     assertThat(changes).hasSize(1);
253   }
254
255   @Test
256   public void update_activation_removes_parameter_without_default_value() {
257     RuleDefinitionDto rule = createRule();
258     RuleParamDto paramWithoutDefault = db.rules().insertRuleParam(rule, p -> p.setName("min").setDefaultValue(null));
259     RuleParamDto paramWithDefault = db.rules().insertRuleParam(rule, p -> p.setName("max").setDefaultValue("10"));
260     QProfileDto profile = createProfile(rule);
261
262     // initial activation -> param "max" has a default value
263     RuleActivation activation = RuleActivation.create(rule.getUuid(), null, of(paramWithoutDefault.getName(), "20"));
264     activate(profile, activation);
265
266     // remove parameter
267     RuleActivation updateActivation = RuleActivation.create(rule.getUuid(), null, of(paramWithoutDefault.getName(), ""));
268     List<ActiveRuleChange> changes = activate(profile, updateActivation);
269
270     assertThatRuleIsUpdated(profile, rule, rule.getSeverityString(), null, of(paramWithDefault.getName(), paramWithDefault.getDefaultValue()));
271     assertThat(changes).hasSize(1);
272   }
273
274   @Test
275   public void update_activation_with_new_parameter() {
276     RuleDefinitionDto rule = createRule();
277     RuleParamDto param = db.rules().insertRuleParam(rule, p -> p.setName("max").setDefaultValue("10"));
278     QProfileDto profile = createProfile(rule);
279
280     // initial activation -> param "max" has a default value
281     RuleActivation activation = RuleActivation.create(rule.getUuid());
282     List<ActiveRuleChange> changes = activate(profile, activation);
283     db.getDbClient().activeRuleDao().deleteParametersByRuleProfileUuids(db.getSession(), asList(profile.getRulesProfileUuid()));
284     assertThatRuleIsActivated(profile, rule, changes, rule.getSeverityString(), null, emptyMap());
285
286     // contrary to activerule, the param is supposed to be inserted but not updated
287     RuleActivation updateActivation = RuleActivation.create(rule.getUuid(), null, of(param.getName(), ""));
288     changes = activate(profile, updateActivation);
289
290     assertThatRuleIsUpdated(profile, rule, rule.getSeverityString(), null, of(param.getName(), param.getDefaultValue()));
291     assertThat(changes).hasSize(1);
292   }
293
294   @Test
295   public void ignore_activation_without_changes() {
296     RuleDefinitionDto rule = createRule();
297     QProfileDto profile = createProfile(rule);
298
299     // initial activation
300     RuleActivation activation = RuleActivation.create(rule.getUuid());
301     activate(profile, activation);
302
303     // update with exactly the same severity and params
304     activation = RuleActivation.create(rule.getUuid());
305     List<ActiveRuleChange> changes = activate(profile, activation);
306
307     assertThat(changes).isEmpty();
308   }
309
310   @Test
311   public void do_not_change_severity_and_params_if_unset_and_already_activated() {
312     RuleDefinitionDto rule = createRule();
313     RuleParamDto param = db.rules().insertRuleParam(rule, p -> p.setName("max").setDefaultValue("10"));
314     QProfileDto profile = createProfile(rule);
315
316     // initial activation -> param "max" has a default value
317     RuleActivation activation = RuleActivation.create(rule.getUuid(), BLOCKER, of(param.getName(), "20"));
318     activate(profile, activation);
319
320     // update without any severity or params => keep
321     RuleActivation update = RuleActivation.create(rule.getUuid());
322     List<ActiveRuleChange> changes = activate(profile, update);
323
324     assertThat(changes).isEmpty();
325   }
326
327   @Test
328   public void fail_to_activate_rule_if_profile_is_on_different_languages() {
329     RuleDefinitionDto rule = createJavaRule();
330     QProfileDto profile = db.qualityProfiles().insert(p -> p.setLanguage("js"));
331     RuleActivation activation = RuleActivation.create(rule.getUuid());
332
333     expectFailure("java rule " + rule.getKey() + " cannot be activated on js profile " + profile.getKee(), () -> activate(profile, activation));
334   }
335
336   @Test
337   public void fail_to_activate_rule_if_rule_has_REMOVED_status() {
338     RuleDefinitionDto rule = db.rules().insert(r -> r.setStatus(RuleStatus.REMOVED));
339     QProfileDto profile = createProfile(rule);
340     RuleActivation activation = RuleActivation.create(rule.getUuid());
341
342     expectFailure("Rule was removed: " + rule.getKey(), () -> activate(profile, activation));
343   }
344
345   @Test
346   public void fail_to_activate_if_template() {
347     RuleDefinitionDto rule = db.rules().insert(r -> r.setIsTemplate(true));
348     QProfileDto profile = createProfile(rule);
349     RuleActivation activation = RuleActivation.create(rule.getUuid());
350
351     expectFailure("Rule template can't be activated on a Quality profile: " + rule.getKey(), () -> activate(profile, activation));
352   }
353
354   @Test
355   public void fail_to_activate_if_invalid_parameter() {
356     RuleDefinitionDto rule = createRule();
357     RuleParamDto param = db.rules().insertRuleParam(rule, p -> p.setName("max").setDefaultValue("10").setType(PropertyType.INTEGER.name()));
358     QProfileDto profile = createProfile(rule);
359
360     RuleActivation activation = RuleActivation.create(rule.getUuid(), null, of(param.getName(), "foo"));
361     expectFailure("Value 'foo' must be an integer.", () -> activate(profile, activation));
362   }
363
364   @Test
365   public void ignore_parameters_when_activating_custom_rule() {
366     RuleDefinitionDto templateRule = db.rules().insert(r -> r.setIsTemplate(true));
367     RuleParamDto templateParam = db.rules().insertRuleParam(templateRule, p -> p.setName("format"));
368     RuleDefinitionDto customRule = db.rules().insert(newCustomRule(templateRule));
369     RuleParamDto customParam = db.rules().insertRuleParam(customRule, p -> p.setName("format").setDefaultValue("txt"));
370     QProfileDto profile = createProfile(customRule);
371
372     // initial activation
373     RuleActivation activation = RuleActivation.create(customRule.getUuid(), MAJOR, emptyMap());
374     activate(profile, activation);
375     assertThatRuleIsActivated(profile, customRule, null, MAJOR, null, of("format", "txt"));
376
377     // update -> parameter is not changed
378     RuleActivation updateActivation = RuleActivation.create(customRule.getUuid(), BLOCKER, of("format", "xml"));
379     activate(profile, updateActivation);
380     assertThatRuleIsActivated(profile, customRule, null, BLOCKER, null, of("format", "txt"));
381   }
382
383   @Test
384   public void user_deactivates_a_rule() {
385     userSession.logIn();
386     RuleDefinitionDto rule = createRule();
387     QProfileDto profile = createProfile(rule);
388     RuleActivation activation = RuleActivation.create(rule.getUuid());
389     activate(profile, activation);
390
391     List<ActiveRuleChange> changes = deactivate(profile, rule);
392     verifyNoActiveRules();
393     assertThatProfileIsUpdatedByUser(profile);
394     assertThat(changes).hasSize(1);
395     assertThat(changes.get(0).getType()).isEqualTo(ActiveRuleChange.Type.DEACTIVATED);
396   }
397
398   @Test
399   public void system_deactivates_a_rule() {
400     RuleDefinitionDto rule = createRule();
401     QProfileDto profile = createProfile(rule);
402     RuleActivation activation = RuleActivation.create(rule.getUuid());
403     activate(profile, activation);
404
405     List<ActiveRuleChange> changes = deactivate(profile, rule);
406     verifyNoActiveRules();
407     assertThatProfileIsUpdatedBySystem(profile);
408     assertThatChangeIsDeactivation(changes, rule);
409   }
410
411   private void assertThatChangeIsDeactivation(List<ActiveRuleChange> changes, RuleDefinitionDto rule) {
412     assertThat(changes).hasSize(1);
413     ActiveRuleChange change = changes.get(0);
414     assertThat(change.getType()).isEqualTo(ActiveRuleChange.Type.DEACTIVATED);
415     assertThat(change.getKey().getRuleKey()).isEqualTo(rule.getKey());
416   }
417
418   @Test
419   public void ignore_deactivation_if_rule_is_not_activated() {
420     RuleDefinitionDto rule = createRule();
421     QProfileDto profile = createProfile(rule);
422
423     List<ActiveRuleChange> changes = deactivate(profile, rule);
424     verifyNoActiveRules();
425     assertThat(changes).hasSize(0);
426   }
427
428   @Test
429   public void deactivate_rule_that_has_REMOVED_status() {
430     RuleDefinitionDto rule = createRule();
431     QProfileDto profile = createProfile(rule);
432     RuleActivation activation = RuleActivation.create(rule.getUuid());
433     activate(profile, activation);
434
435     rule.setStatus(RuleStatus.REMOVED);
436     db.getDbClient().ruleDao().update(db.getSession(), rule);
437
438     List<ActiveRuleChange> changes = deactivate(profile, rule);
439     verifyNoActiveRules();
440     assertThatChangeIsDeactivation(changes, rule);
441   }
442
443   @Test
444   public void activation_on_child_profile_is_propagated_to_descendants() {
445     RuleDefinitionDto rule = createRule();
446     QProfileDto parentProfile = createProfile(rule);
447     QProfileDto childProfile = createChildProfile(parentProfile);
448     QProfileDto grandChildProfile = createChildProfile(childProfile);
449
450     List<ActiveRuleChange> changes = activate(childProfile, RuleActivation.create(rule.getUuid()));
451     assertThatProfileHasNoActiveRules(parentProfile);
452     assertThatRuleIsActivated(childProfile, rule, changes, rule.getSeverityString(), null, emptyMap());
453     assertThatRuleIsActivated(grandChildProfile, rule, changes, rule.getSeverityString(), INHERITED, emptyMap());
454   }
455
456   @Test
457   public void update_on_child_profile_is_propagated_to_descendants() {
458     RuleDefinitionDto rule = createRule();
459     RuleParamDto param = db.rules().insertRuleParam(rule);
460     QProfileDto parentProfile = createProfile(rule);
461     QProfileDto childProfile = createChildProfile(parentProfile);
462     QProfileDto grandChildProfile = createChildProfile(childProfile);
463
464     System.out.println("ACTIVATE ON " + childProfile.getName());
465     RuleActivation initialActivation = RuleActivation.create(rule.getUuid(), MAJOR, of(param.getName(), "foo"));
466     activate(childProfile, initialActivation);
467
468     System.out.println("---------------");
469     System.out.println("ACTIVATE ON " + childProfile.getName());
470     RuleActivation updateActivation = RuleActivation.create(rule.getUuid(), CRITICAL, of(param.getName(), "bar"));
471     List<ActiveRuleChange> changes = activate(childProfile, updateActivation);
472
473     assertThatProfileHasNoActiveRules(parentProfile);
474     assertThatRuleIsUpdated(childProfile, rule, CRITICAL, null, of(param.getName(), "bar"));
475     assertThatRuleIsUpdated(grandChildProfile, rule, CRITICAL, INHERITED, of(param.getName(), "bar"));
476     assertThat(changes).hasSize(2);
477   }
478
479   @Test
480   public void override_activation_of_inherited_profile() {
481     RuleDefinitionDto rule = createRule();
482     RuleParamDto param = db.rules().insertRuleParam(rule);
483     QProfileDto parentProfile = createProfile(rule);
484     QProfileDto childProfile = createChildProfile(parentProfile);
485     QProfileDto grandChildProfile = createChildProfile(childProfile);
486
487     RuleActivation initialActivation = RuleActivation.create(rule.getUuid(), MAJOR, of(param.getName(), "foo"));
488     activate(childProfile, initialActivation);
489
490     RuleActivation overrideActivation = RuleActivation.create(rule.getUuid(), CRITICAL, of(param.getName(), "bar"));
491     List<ActiveRuleChange> changes = activate(grandChildProfile, overrideActivation);
492
493     assertThatProfileHasNoActiveRules(parentProfile);
494     assertThatRuleIsUpdated(childProfile, rule, MAJOR, null, of(param.getName(), "foo"));
495     assertThatRuleIsUpdated(grandChildProfile, rule, CRITICAL, ActiveRuleInheritance.OVERRIDES, of(param.getName(), "bar"));
496     assertThat(changes).hasSize(1);
497   }
498
499   @Test
500   public void updated_activation_on_parent_is_not_propagated_to_overridden_profiles() {
501     RuleDefinitionDto rule = createRule();
502     RuleParamDto param = db.rules().insertRuleParam(rule);
503     QProfileDto parentProfile = createProfile(rule);
504     QProfileDto childProfile = createChildProfile(parentProfile);
505     QProfileDto grandChildProfile = createChildProfile(childProfile);
506
507     RuleActivation initialActivation = RuleActivation.create(rule.getUuid(), MAJOR, of(param.getName(), "foo"));
508     activate(childProfile, initialActivation);
509
510     RuleActivation overrideActivation = RuleActivation.create(rule.getUuid(), CRITICAL, of(param.getName(), "bar"));
511     activate(grandChildProfile, overrideActivation);
512
513     // update child --> do not touch grandChild
514     RuleActivation updateActivation = RuleActivation.create(rule.getUuid(), BLOCKER, of(param.getName(), "baz"));
515     List<ActiveRuleChange> changes = activate(childProfile, updateActivation);
516
517     assertThatProfileHasNoActiveRules(parentProfile);
518     assertThatRuleIsUpdated(childProfile, rule, BLOCKER, null, of(param.getName(), "baz"));
519     assertThatRuleIsUpdated(grandChildProfile, rule, CRITICAL, ActiveRuleInheritance.OVERRIDES, of(param.getName(), "bar"));
520     assertThat(changes).hasSize(1);
521   }
522
523   @Test
524   public void reset_on_parent_is_not_propagated_to_overridden_profiles() {
525     RuleDefinitionDto rule = createRule();
526     RuleParamDto param = db.rules().insertRuleParam(rule);
527     QProfileDto parentProfile = createProfile(rule);
528     QProfileDto childProfile = createChildProfile(parentProfile);
529     QProfileDto grandChildProfile = createChildProfile(childProfile);
530
531     RuleActivation initialActivation = RuleActivation.create(rule.getUuid(), MAJOR, of(param.getName(), "foo"));
532     activate(parentProfile, initialActivation);
533
534     RuleActivation overrideActivation = RuleActivation.create(rule.getUuid(), CRITICAL, of(param.getName(), "bar"));
535     activate(grandChildProfile, overrideActivation);
536
537     // reset parent --> touch child but not grandChild
538     RuleActivation updateActivation = RuleActivation.createReset(rule.getUuid());
539     List<ActiveRuleChange> changes = activate(parentProfile, updateActivation);
540
541     assertThatRuleIsUpdated(parentProfile, rule, rule.getSeverityString(), null, of(param.getName(), param.getDefaultValue()));
542     assertThatRuleIsUpdated(childProfile, rule, rule.getSeverityString(), INHERITED, of(param.getName(), param.getDefaultValue()));
543     assertThatRuleIsUpdated(grandChildProfile, rule, CRITICAL, ActiveRuleInheritance.OVERRIDES, of(param.getName(), "bar"));
544     assertThat(changes).hasSize(2);
545   }
546
547   @Test
548   public void active_on_parent_a_rule_already_activated_on_child() {
549     RuleDefinitionDto rule = createRule();
550     RuleParamDto param = db.rules().insertRuleParam(rule);
551     QProfileDto parentProfile = createProfile(rule);
552     QProfileDto childProfile = createChildProfile(parentProfile);
553
554     RuleActivation childActivation = RuleActivation.create(rule.getUuid(), MAJOR, of(param.getName(), "foo"));
555     activate(childProfile, childActivation);
556
557     RuleActivation parentActivation = RuleActivation.create(rule.getUuid(), CRITICAL, of(param.getName(), "bar"));
558     List<ActiveRuleChange> changes = activate(parentProfile, parentActivation);
559
560     assertThatRuleIsUpdated(parentProfile, rule, CRITICAL, null, of(param.getName(), "bar"));
561     assertThatRuleIsUpdated(childProfile, rule, MAJOR, ActiveRuleInheritance.OVERRIDES, of(param.getName(), "foo"));
562     assertThat(changes).hasSize(2);
563   }
564
565   @Test
566   public void do_not_mark_as_overridden_if_same_values_than_parent() {
567     RuleDefinitionDto rule = createRule();
568     RuleParamDto param = db.rules().insertRuleParam(rule);
569     QProfileDto parentProfile = createProfile(rule);
570     QProfileDto childProfile = createChildProfile(parentProfile);
571
572     RuleActivation parentActivation = RuleActivation.create(rule.getUuid(), MAJOR, of(param.getName(), "foo"));
573     activate(parentProfile, parentActivation);
574
575     RuleActivation overrideActivation = RuleActivation.create(rule.getUuid(), MAJOR, of(param.getName(), "foo"));
576     List<ActiveRuleChange> changes = activate(childProfile, overrideActivation);
577
578     assertThatRuleIsUpdated(childProfile, rule, MAJOR, INHERITED, of(param.getName(), "foo"));
579     assertThat(changes).hasSize(0);
580   }
581
582   @Test
583   public void propagate_deactivation_on_children() {
584     RuleDefinitionDto rule = createRule();
585     QProfileDto parentProfile = createProfile(rule);
586     QProfileDto childProfile = createChildProfile(parentProfile);
587
588     RuleActivation activation = RuleActivation.create(rule.getUuid());
589     List<ActiveRuleChange> changes = activate(parentProfile, activation);
590     assertThatRuleIsActivated(parentProfile, rule, changes, rule.getSeverityString(), null, emptyMap());
591     assertThatRuleIsActivated(childProfile, rule, changes, rule.getSeverityString(), INHERITED, emptyMap());
592
593     changes = deactivate(parentProfile, rule);
594     assertThatProfileHasNoActiveRules(parentProfile);
595     assertThatProfileHasNoActiveRules(childProfile);
596     assertThat(changes).hasSize(2);
597   }
598
599   @Test
600   public void propagate_deactivation_on_children_even_when_overridden() {
601     RuleDefinitionDto rule = createRule();
602     QProfileDto parentProfile = createProfile(rule);
603     QProfileDto childProfile = createChildProfile(parentProfile);
604
605     RuleActivation activation = RuleActivation.create(rule.getUuid());
606     List<ActiveRuleChange> changes = activate(parentProfile, activation);
607     assertThatRuleIsActivated(parentProfile, rule, changes, rule.getSeverityString(), null, emptyMap());
608     assertThatRuleIsActivated(childProfile, rule, changes, rule.getSeverityString(), INHERITED, emptyMap());
609
610     activation = RuleActivation.create(rule.getUuid(), CRITICAL, null);
611     activate(childProfile, activation);
612
613     changes = deactivate(parentProfile, rule);
614     assertThatProfileHasNoActiveRules(parentProfile);
615     assertThatProfileHasNoActiveRules(childProfile);
616     assertThat(changes).hasSize(2);
617   }
618
619   @Test
620   public void cannot_deactivate_rule_inherited() {
621     RuleDefinitionDto rule = createRule();
622     QProfileDto parentProfile = createProfile(rule);
623     QProfileDto childProfile = createChildProfile(parentProfile);
624
625     RuleActivation activation = RuleActivation.create(rule.getUuid());
626     List<ActiveRuleChange> changes = activate(parentProfile, activation);
627     assertThatRuleIsActivated(parentProfile, rule, changes, rule.getSeverityString(), null, emptyMap());
628     assertThatRuleIsActivated(childProfile, rule, changes, rule.getSeverityString(), INHERITED, emptyMap());
629
630     expectedException.expect(BadRequestException.class);
631     expectedException.expectMessage("Cannot deactivate inherited rule");
632     deactivate(childProfile, rule);
633   }
634
635   @Test
636   public void reset_child_profile_do_not_change_parent() {
637     RuleDefinitionDto rule = createRule();
638     QProfileDto parentProfile = createProfile(rule);
639     QProfileDto childProfile = createChildProfile(parentProfile);
640
641     RuleActivation activation = RuleActivation.create(rule.getUuid(), CRITICAL, null);
642     List<ActiveRuleChange> changes = activate(parentProfile, activation);
643     assertThatRuleIsActivated(parentProfile, rule, changes, CRITICAL, null, emptyMap());
644     assertThatRuleIsActivated(childProfile, rule, changes, CRITICAL, INHERITED, emptyMap());
645     assertThat(changes).hasSize(2);
646
647     RuleActivation childActivation = RuleActivation.create(rule.getUuid(), BLOCKER, null);
648     changes = activate(childProfile, childActivation);
649     assertThatRuleIsUpdated(childProfile, rule, BLOCKER, ActiveRuleInheritance.OVERRIDES, emptyMap());
650     assertThat(changes).hasSize(1);
651
652     RuleActivation resetActivation = RuleActivation.createReset(rule.getUuid());
653     changes = activate(childProfile, resetActivation);
654     assertThatRuleIsUpdated(childProfile, rule, CRITICAL, INHERITED, emptyMap());
655     assertThatRuleIsUpdated(parentProfile, rule, CRITICAL, null, emptyMap());
656     assertThat(changes).hasSize(1);
657   }
658
659   @Test
660   public void reset_parent_is_not_propagated_when_child_overrides() {
661     RuleDefinitionDto rule = createRule();
662     QProfileDto baseProfile = createProfile(rule);
663     QProfileDto childProfile = createChildProfile(baseProfile);
664     QProfileDto grandChildProfile = createChildProfile(childProfile);
665
666     RuleActivation activation = RuleActivation.create(rule.getUuid(), CRITICAL, null);
667     List<ActiveRuleChange> changes = activate(baseProfile, activation);
668     assertThatRuleIsActivated(baseProfile, rule, changes, CRITICAL, null, emptyMap());
669     assertThatRuleIsActivated(childProfile, rule, changes, CRITICAL, INHERITED, emptyMap());
670     assertThatRuleIsActivated(grandChildProfile, rule, changes, CRITICAL, INHERITED, emptyMap());
671     assertThat(changes).hasSize(3);
672
673     RuleActivation childActivation = RuleActivation.create(rule.getUuid(), BLOCKER, null);
674     changes = activate(childProfile, childActivation);
675     assertThatRuleIsUpdated(childProfile, rule, BLOCKER, ActiveRuleInheritance.OVERRIDES, emptyMap());
676     assertThatRuleIsUpdated(grandChildProfile, rule, BLOCKER, INHERITED, emptyMap());
677     assertThat(changes).hasSize(2);
678
679     // Reset on parent do not change child nor grandchild
680     RuleActivation resetActivation = RuleActivation.createReset(rule.getUuid());
681     changes = activate(baseProfile, resetActivation);
682     assertThatRuleIsUpdated(baseProfile, rule, rule.getSeverityString(), null, emptyMap());
683     assertThatRuleIsUpdated(childProfile, rule, BLOCKER, ActiveRuleInheritance.OVERRIDES, emptyMap());
684     assertThatRuleIsUpdated(grandChildProfile, rule, BLOCKER, INHERITED, emptyMap());
685     assertThat(changes).hasSize(1);
686
687     // Reset on child change grandchild
688     resetActivation = RuleActivation.createReset(rule.getUuid());
689     changes = activate(childProfile, resetActivation);
690     assertThatRuleIsUpdated(baseProfile, rule, rule.getSeverityString(), null, emptyMap());
691     assertThatRuleIsUpdated(childProfile, rule, rule.getSeverityString(), INHERITED, emptyMap());
692     assertThatRuleIsUpdated(grandChildProfile, rule, rule.getSeverityString(), INHERITED, emptyMap());
693     assertThat(changes).hasSize(2);
694   }
695
696   @Test
697   public void ignore_reset_if_not_activated() {
698     RuleDefinitionDto rule = createRule();
699     QProfileDto parentProfile = createProfile(rule);
700     createChildProfile(parentProfile);
701
702     RuleActivation resetActivation = RuleActivation.createReset(rule.getUuid());
703     List<ActiveRuleChange> changes = activate(parentProfile, resetActivation);
704     verifyNoActiveRules();
705     assertThat(changes).hasSize(0);
706   }
707
708   @Test
709   public void bulk_activation() {
710     int bulkSize = SearchOptions.MAX_PAGE_SIZE + 10 + new Random().nextInt(100);
711     String language = randomAlphanumeric(10);
712     String repositoryKey = randomAlphanumeric(10);
713     QProfileDto profile = db.qualityProfiles().insert(p -> p.setLanguage(language));
714
715     List<RuleDto> rules = new ArrayList<>();
716     IntStream.rangeClosed(1, bulkSize).forEach(
717       i -> rules.add(db.rules().insertRule(r -> r.setLanguage(language).setRepositoryKey(repositoryKey))));
718
719     verifyNoActiveRules();
720     ruleIndexer.indexOnStartup(ruleIndexer.getIndexTypes());
721
722     RuleQuery ruleQuery = new RuleQuery()
723       .setRepositories(singletonList(repositoryKey));
724
725     BulkChangeResult bulkChangeResult = underTest.bulkActivateAndCommit(db.getSession(), profile, ruleQuery, MINOR);
726
727     assertThat(bulkChangeResult.countFailed()).isEqualTo(0);
728     assertThat(bulkChangeResult.countSucceeded()).isEqualTo(bulkSize);
729     assertThat(bulkChangeResult.getChanges()).hasSize(bulkSize);
730     assertThat(db.getDbClient().activeRuleDao().selectByProfile(db.getSession(), profile)).hasSize(bulkSize);
731     rules.stream().forEach(
732       r -> assertThatRuleIsActivated(profile, r.getDefinition(), null, MINOR, null, emptyMap()));
733   }
734
735   @Test
736   public void bulk_deactivation() {
737     int bulkSize = SearchOptions.MAX_PAGE_SIZE + 10 + new Random().nextInt(100);
738     String language = randomAlphanumeric(10);
739     String repositoryKey = randomAlphanumeric(10);
740     QProfileDto profile = db.qualityProfiles().insert(p -> p.setLanguage(language));
741
742     List<RuleDto> rules = new ArrayList<>();
743     IntStream.rangeClosed(1, bulkSize).forEach(
744       i -> rules.add(db.rules().insertRule(r -> r.setLanguage(language).setRepositoryKey(repositoryKey))));
745
746     verifyNoActiveRules();
747     ruleIndexer.indexOnStartup(ruleIndexer.getIndexTypes());
748
749     RuleQuery ruleQuery = new RuleQuery()
750       .setRepositories(singletonList(repositoryKey));
751
752     BulkChangeResult bulkChangeResult = underTest.bulkActivateAndCommit(db.getSession(), profile, ruleQuery, MINOR);
753
754     assertThat(bulkChangeResult.countFailed()).isEqualTo(0);
755     assertThat(bulkChangeResult.countSucceeded()).isEqualTo(bulkSize);
756     assertThat(bulkChangeResult.getChanges()).hasSize(bulkSize);
757     assertThat(db.getDbClient().activeRuleDao().selectByProfile(db.getSession(), profile)).hasSize(bulkSize);
758
759     // Now deactivate all rules
760     bulkChangeResult = underTest.bulkDeactivateAndCommit(db.getSession(), profile, ruleQuery);
761
762     assertThat(bulkChangeResult.countFailed()).isEqualTo(0);
763     assertThat(bulkChangeResult.countSucceeded()).isEqualTo(bulkSize);
764     assertThat(bulkChangeResult.getChanges()).hasSize(bulkSize);
765     assertThat(db.getDbClient().activeRuleDao().selectByProfile(db.getSession(), profile)).hasSize(0);
766     rules.stream().forEach(
767       r -> assertThatRuleIsNotPresent(profile, r.getDefinition()));
768   }
769
770   @Test
771   public void bulk_deactivation_ignores_errors() {
772     RuleDefinitionDto rule = createRule();
773     QProfileDto parentProfile = createProfile(rule);
774     QProfileDto childProfile = createChildProfile(parentProfile);
775
776     List<ActiveRuleChange> changes = activate(parentProfile, RuleActivation.create(rule.getUuid()));
777     assertThatRuleIsActivated(parentProfile, rule, null, rule.getSeverityString(), null, emptyMap());
778     assertThatRuleIsActivated(childProfile, rule, null, rule.getSeverityString(), INHERITED, emptyMap());
779
780     ruleIndexer.indexOnStartup(ruleIndexer.getIndexTypes());
781
782     RuleQuery ruleQuery = new RuleQuery()
783       .setQProfile(childProfile);
784     BulkChangeResult bulkChangeResult = underTest.bulkDeactivateAndCommit(db.getSession(), childProfile, ruleQuery);
785
786     assertThat(bulkChangeResult.countFailed()).isEqualTo(1);
787     assertThat(bulkChangeResult.countSucceeded()).isEqualTo(0);
788     assertThat(bulkChangeResult.getChanges()).hasSize(0);
789     assertThatRuleIsActivated(parentProfile, rule, null, rule.getSeverityString(), null, emptyMap());
790     assertThatRuleIsActivated(childProfile, rule, null, rule.getSeverityString(), INHERITED, emptyMap());
791   }
792
793   @Test
794   public void bulk_change_severity() {
795     RuleDefinitionDto rule1 = createJavaRule();
796     RuleDefinitionDto rule2 = createJavaRule();
797     QProfileDto parentProfile = createProfile(rule1);
798     QProfileDto childProfile = createChildProfile(parentProfile);
799     QProfileDto grandchildProfile = createChildProfile(childProfile);
800
801     activate(parentProfile, RuleActivation.create(rule1.getUuid()));
802     activate(parentProfile, RuleActivation.create(rule2.getUuid()));
803
804     ruleIndexer.indexOnStartup(ruleIndexer.getIndexTypes());
805
806     RuleQuery query = new RuleQuery()
807       .setRuleKey(rule1.getRuleKey())
808       .setQProfile(parentProfile);
809     BulkChangeResult result = underTest.bulkActivateAndCommit(db.getSession(), parentProfile, query, "BLOCKER");
810
811     assertThat(result.getChanges()).hasSize(3);
812     assertThat(result.countSucceeded()).isEqualTo(1);
813     assertThat(result.countFailed()).isEqualTo(0);
814
815     // Rule1 must be activated with BLOCKER on all profiles
816     assertThatRuleIsActivated(parentProfile, rule1, null, BLOCKER, null, emptyMap());
817     assertThatRuleIsActivated(childProfile, rule1, null, BLOCKER, INHERITED, emptyMap());
818     assertThatRuleIsActivated(grandchildProfile, rule1, null, BLOCKER, INHERITED, emptyMap());
819
820     // Rule2 did not changed
821     assertThatRuleIsActivated(parentProfile, rule2, null, rule2.getSeverityString(), null, emptyMap());
822     assertThatRuleIsActivated(childProfile, rule2, null, rule2.getSeverityString(), INHERITED, emptyMap());
823     assertThatRuleIsActivated(grandchildProfile, rule2, null, rule2.getSeverityString(), INHERITED, emptyMap());
824   }
825
826   @Test
827   public void delete_rule_from_all_profiles() {
828     RuleDefinitionDto rule = createRule();
829     QProfileDto parentProfile = createProfile(rule);
830     QProfileDto childProfile = createChildProfile(parentProfile);
831     QProfileDto grandChildProfile = createChildProfile(childProfile);
832
833     RuleActivation activation = RuleActivation.create(rule.getUuid(), CRITICAL, null);
834     activate(parentProfile, activation);
835
836     RuleActivation overrideActivation = RuleActivation.create(rule.getUuid(), BLOCKER, null);
837     activate(grandChildProfile, overrideActivation);
838
839     // Reset on parent do not change child nor grandchild
840     List<ActiveRuleChange> changes = underTest.deleteRule(db.getSession(), rule);
841
842     assertThatRuleIsNotPresent(parentProfile, rule);
843     assertThatRuleIsNotPresent(childProfile, rule);
844     assertThatRuleIsNotPresent(grandChildProfile, rule);
845     assertThat(changes)
846       .extracting(ActiveRuleChange::getType)
847       .containsOnly(ActiveRuleChange.Type.DEACTIVATED)
848       .hasSize(3);
849   }
850
851   @Test
852   public void activation_fails_when_profile_is_built_in() {
853     RuleDefinitionDto rule = createRule();
854     QProfileDto builtInProfile = db.qualityProfiles().insert(p -> p.setLanguage(rule.getLanguage()).setIsBuiltIn(true));
855
856     expectedException.expect(IllegalArgumentException.class);
857     expectedException.expectMessage("The built-in profile " + builtInProfile.getName() + " is read-only and can't be updated");
858
859     underTest.activateAndCommit(db.getSession(), builtInProfile, singleton(RuleActivation.create(rule.getUuid())));
860   }
861
862   private void assertThatProfileHasNoActiveRules(QProfileDto profile) {
863     List<OrgActiveRuleDto> activeRules = db.getDbClient().activeRuleDao().selectByProfile(db.getSession(), profile);
864     assertThat(activeRules).isEmpty();
865   }
866
867   private List<ActiveRuleChange> deactivate(QProfileDto profile, RuleDefinitionDto rule) {
868     return underTest.deactivateAndCommit(db.getSession(), profile, singleton(rule.getUuid()));
869   }
870
871   private List<ActiveRuleChange> activate(QProfileDto profile, RuleActivation activation) {
872     return underTest.activateAndCommit(db.getSession(), profile, singleton(activation));
873   }
874
875   private QProfileDto createProfile(RuleDefinitionDto rule) {
876     return db.qualityProfiles().insert(p -> p.setLanguage(rule.getLanguage()));
877   }
878
879   private QProfileDto createChildProfile(QProfileDto parent) {
880     return db.qualityProfiles().insert(p -> p
881       .setLanguage(parent.getLanguage())
882       .setParentKee(parent.getKee())
883       .setName("Child of " + parent.getName()));
884   }
885
886   private void assertThatProfileIsUpdatedByUser(QProfileDto profile) {
887     QProfileDto loaded = db.getDbClient().qualityProfileDao().selectByUuid(db.getSession(), profile.getKee());
888     assertThat(loaded.getUserUpdatedAt()).isNotNull();
889     assertThat(loaded.getRulesUpdatedAt()).isNotEmpty();
890   }
891
892   private void assertThatProfileIsUpdatedBySystem(QProfileDto profile) {
893     QProfileDto loaded = db.getDbClient().qualityProfileDao().selectByUuid(db.getSession(), profile.getKee());
894     assertThat(loaded.getUserUpdatedAt()).isNull();
895     assertThat(loaded.getRulesUpdatedAt()).isNotEmpty();
896   }
897
898   private void assertThatRuleIsActivated(QProfileDto profile, RuleDefinitionDto rule, @Nullable List<ActiveRuleChange> changes,
899     String expectedSeverity, @Nullable ActiveRuleInheritance expectedInheritance, Map<String, String> expectedParams) {
900     OrgActiveRuleDto activeRule = db.getDbClient().activeRuleDao().selectByProfile(db.getSession(), profile)
901       .stream()
902       .filter(ar -> ar.getRuleKey().equals(rule.getKey()))
903       .findFirst()
904       .orElseThrow(IllegalStateException::new);
905
906     assertThat(activeRule.getSeverityString()).isEqualTo(expectedSeverity);
907     assertThat(activeRule.getInheritance()).isEqualTo(expectedInheritance != null ? expectedInheritance.name() : null);
908     assertThat(activeRule.getCreatedAt()).isNotNull();
909     assertThat(activeRule.getUpdatedAt()).isNotNull();
910
911     List<ActiveRuleParamDto> params = db.getDbClient().activeRuleDao().selectParamsByActiveRuleUuid(db.getSession(), activeRule.getUuid());
912     assertThat(params).hasSize(expectedParams.size());
913
914     if (changes != null) {
915       ActiveRuleChange change = changes.stream()
916         .filter(c -> c.getActiveRule().getUuid().equals(activeRule.getUuid()))
917         .findFirst().orElseThrow(IllegalStateException::new);
918       assertThat(change.getInheritance()).isEqualTo(expectedInheritance);
919       assertThat(change.getSeverity()).isEqualTo(expectedSeverity);
920       assertThat(change.getType()).isEqualTo(ActiveRuleChange.Type.ACTIVATED);
921     }
922   }
923
924   private void assertThatRuleIsNotPresent(QProfileDto profile, RuleDefinitionDto rule) {
925     Optional<OrgActiveRuleDto> activeRule = db.getDbClient().activeRuleDao().selectByProfile(db.getSession(), profile)
926       .stream()
927       .filter(ar -> ar.getRuleKey().equals(rule.getKey()))
928       .findFirst();
929
930     assertThat(activeRule).isEmpty();
931   }
932
933   private void assertThatRuleIsUpdated(QProfileDto profile, RuleDefinitionDto rule,
934     String expectedSeverity, @Nullable ActiveRuleInheritance expectedInheritance, Map<String, String> expectedParams) {
935     OrgActiveRuleDto activeRule = db.getDbClient().activeRuleDao().selectByProfile(db.getSession(), profile)
936       .stream()
937       .filter(ar -> ar.getRuleKey().equals(rule.getKey()))
938       .findFirst()
939       .orElseThrow(IllegalStateException::new);
940
941     assertThat(activeRule.getSeverityString()).isEqualTo(expectedSeverity);
942     assertThat(activeRule.getInheritance()).isEqualTo(expectedInheritance != null ? expectedInheritance.name() : null);
943     assertThat(activeRule.getCreatedAt()).isNotNull();
944     assertThat(activeRule.getUpdatedAt()).isNotNull();
945
946     List<ActiveRuleParamDto> params = db.getDbClient().activeRuleDao().selectParamsByActiveRuleUuid(db.getSession(), activeRule.getUuid());
947     assertThat(params).hasSize(expectedParams.size());
948   }
949
950   private void expectFailure(String expectedMessage, Runnable runnable) {
951     try {
952       runnable.run();
953       fail();
954     } catch (BadRequestException e) {
955       assertThat(e.getMessage()).isEqualTo(expectedMessage);
956     }
957     verifyNoActiveRules();
958   }
959
960   private void verifyNoActiveRules() {
961     assertThat(db.countRowsOfTable(db.getSession(), "active_rules")).isEqualTo(0);
962   }
963
964   private RuleDefinitionDto createRule() {
965     return db.rules().insert(r -> r.setSeverity(Severity.MAJOR));
966   }
967
968   private RuleDefinitionDto createJavaRule() {
969     return db.rules().insert(r -> r.setSeverity(Severity.MAJOR).setLanguage("java"));
970   }
971 }