3 * Copyright (C) 2009-2017 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.List;
23 import java.util.Optional;
24 import org.junit.Before;
25 import org.junit.Rule;
26 import org.junit.Test;
27 import org.sonar.api.profiles.RulesProfile;
28 import org.sonar.api.rules.RulePriority;
29 import org.sonar.api.utils.System2;
30 import org.sonar.api.utils.internal.TestSystem2;
31 import org.sonar.db.DbTester;
32 import org.sonar.db.qualityprofile.ActiveRuleDto;
33 import org.sonar.db.qualityprofile.RulesProfileDto;
34 import org.sonar.db.rule.RuleDefinitionDto;
35 import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
36 import org.sonar.server.tester.UserSessionRule;
37 import org.sonar.server.util.IntegerTypeValidation;
38 import org.sonar.server.util.StringTypeValidation;
39 import org.sonar.server.util.TypeValidations;
41 import static java.util.Arrays.asList;
42 import static org.assertj.core.api.Assertions.assertThat;
43 import static org.mockito.Mockito.mock;
44 import static org.sonar.api.rules.RulePriority.BLOCKER;
45 import static org.sonar.api.rules.RulePriority.CRITICAL;
46 import static org.sonar.api.rules.RulePriority.MAJOR;
47 import static org.sonar.db.qualityprofile.QualityProfileTesting.newRuleProfileDto;
49 public class BuiltInQProfileUpdateImplTest {
51 private static final long NOW = 1_000;
52 private static final long PAST = NOW - 100;
55 public BuiltInQProfileRepositoryRule builtInProfileRepository = new BuiltInQProfileRepositoryRule();
57 public DbTester db = DbTester.create().setDisableDefaultOrganization(true);
59 public UserSessionRule userSession = UserSessionRule.standalone();
60 private System2 system2 = new TestSystem2().setNow(NOW);
61 private ActiveRuleIndexer activeRuleIndexer = mock(ActiveRuleIndexer.class);
62 private RuleActivatorContextFactory contextFactory = new RuleActivatorContextFactory(db.getDbClient());
63 private TypeValidations typeValidations = new TypeValidations(asList(new StringTypeValidation(), new IntegerTypeValidation()));
64 private RuleActivator ruleActivator = new RuleActivator(system2, db.getDbClient(), null, contextFactory, typeValidations, activeRuleIndexer, userSession);
66 private BuiltInQProfileUpdateImpl underTest = new BuiltInQProfileUpdateImpl(db.getDbClient(), ruleActivator, activeRuleIndexer);
68 private RulesProfileDto persistedProfile;
72 persistedProfile = newRuleProfileDto(rp -> rp
75 .setRulesUpdatedAt(null));
76 db.getDbClient().qualityProfileDao().insert(db.getSession(), persistedProfile);
81 public void activate_new_rules() {
82 RuleDefinitionDto rule1 = db.rules().insert(r -> r.setLanguage("xoo"));
83 RuleDefinitionDto rule2 = db.rules().insert(r -> r.setLanguage("xoo"));
84 RulesProfile apiProfile = RulesProfile.create("Sonar way", "xoo");
85 activateRuleInDef(apiProfile, rule1, CRITICAL);
86 activateRuleInDef(apiProfile, rule2, MAJOR);
87 BuiltInQProfile builtIn = builtInProfileRepository.create(apiProfile);
89 underTest.update(db.getSession(), builtIn, persistedProfile);
91 List<ActiveRuleDto> activeRules = db.getDbClient().activeRuleDao().selectByRuleProfile(db.getSession(), persistedProfile);
92 assertThat(activeRules).hasSize(2);
93 assertThatRuleIsNewlyActivated(activeRules, rule1, CRITICAL);
94 assertThatRuleIsNewlyActivated(activeRules, rule2, MAJOR);
95 assertThatProfileIsMarkedAsUpdated(persistedProfile);
99 public void already_activated_rule_is_updated_in_case_of_differences() {
100 RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage("xoo"));
101 RulesProfile apiProfile = RulesProfile.create("Sonar way", "xoo");
102 activateRuleInDef(apiProfile, rule, CRITICAL);
103 BuiltInQProfile builtIn = builtInProfileRepository.create(apiProfile);
105 activateRuleInDb(persistedProfile, rule, BLOCKER);
107 underTest.update(db.getSession(), builtIn, persistedProfile);
109 List<ActiveRuleDto> activeRules = db.getDbClient().activeRuleDao().selectByRuleProfile(db.getSession(), persistedProfile);
110 assertThat(activeRules).hasSize(1);
111 assertThatRuleIsUpdated(activeRules, rule, CRITICAL);
112 assertThatProfileIsMarkedAsUpdated(persistedProfile);
116 public void already_activated_rule_is_not_touched_if_no_differences() {
117 RuleDefinitionDto rule = db.rules().insert(r -> r.setLanguage("xoo"));
118 RulesProfile apiProfile = RulesProfile.create("Sonar way", "xoo");
119 activateRuleInDef(apiProfile, rule, CRITICAL);
120 BuiltInQProfile builtIn = builtInProfileRepository.create(apiProfile);
122 activateRuleInDb(persistedProfile, rule, CRITICAL);
124 underTest.update(db.getSession(), builtIn, persistedProfile);
126 List<ActiveRuleDto> activeRules = db.getDbClient().activeRuleDao().selectByRuleProfile(db.getSession(), persistedProfile);
127 assertThat(activeRules).hasSize(1);
128 assertThatRuleIsUntouched(activeRules, rule, CRITICAL);
129 assertThatProfileIsNotMarkedAsUpdated(persistedProfile);
133 public void deactivate_rule_that_is_not_in_built_in_definition_anymore() {
134 RuleDefinitionDto rule1 = db.rules().insert(r -> r.setLanguage("xoo"));
135 RuleDefinitionDto rule2 = db.rules().insert(r -> r.setLanguage("xoo"));
136 RulesProfile apiProfile = RulesProfile.create("Sonar way", "xoo");
137 activateRuleInDef(apiProfile, rule2, CRITICAL);
138 BuiltInQProfile builtIn = builtInProfileRepository.create(apiProfile);
140 // built-in definition contains only rule2
141 // so rule1 must be deactivated
142 activateRuleInDb(persistedProfile, rule1, CRITICAL);
144 underTest.update(db.getSession(), builtIn, persistedProfile);
146 List<ActiveRuleDto> activeRules = db.getDbClient().activeRuleDao().selectByRuleProfile(db.getSession(), persistedProfile);
147 assertThat(activeRules).hasSize(1);
148 assertThatRuleIsDeactivated(activeRules, rule1);
149 assertThatProfileIsMarkedAsUpdated(persistedProfile);
153 public void activate_deactivate_and_update_three_rules_at_the_same_time() {
154 RuleDefinitionDto rule1 = db.rules().insert(r -> r.setLanguage("xoo"));
155 RuleDefinitionDto rule2 = db.rules().insert(r -> r.setLanguage("xoo"));
156 RuleDefinitionDto rule3 = db.rules().insert(r -> r.setLanguage("xoo"));
157 RulesProfile apiProfile = RulesProfile.create("Sonar way", "xoo");
158 activateRuleInDef(apiProfile, rule1, CRITICAL);
159 activateRuleInDef(apiProfile, rule2, MAJOR);
160 BuiltInQProfile builtIn = builtInProfileRepository.create(apiProfile);
162 // rule1 must be updated (blocker to critical)
163 // rule2 must be activated
164 // rule3 must be deactivated
165 activateRuleInDb(persistedProfile, rule1, BLOCKER);
166 activateRuleInDb(persistedProfile, rule3, BLOCKER);
168 underTest.update(db.getSession(), builtIn, persistedProfile);
170 List<ActiveRuleDto> activeRules = db.getDbClient().activeRuleDao().selectByRuleProfile(db.getSession(), persistedProfile);
171 assertThat(activeRules).hasSize(2);
172 assertThatRuleIsUpdated(activeRules, rule1, CRITICAL);
173 assertThatRuleIsNewlyActivated(activeRules, rule2, MAJOR);
174 assertThatRuleIsDeactivated(activeRules, rule3);
175 assertThatProfileIsMarkedAsUpdated(persistedProfile);
179 private static void assertThatRuleIsNewlyActivated(List<ActiveRuleDto> activeRules, RuleDefinitionDto rule, RulePriority severity) {
180 ActiveRuleDto activeRule = findRule(activeRules, rule).get();
182 assertThat(activeRule.getInheritance()).isNull();
183 assertThat(activeRule.getSeverityString()).isEqualTo(severity.name());
184 assertThat(activeRule.getCreatedAt()).isEqualTo(NOW);
185 assertThat(activeRule.getUpdatedAt()).isEqualTo(NOW);
188 private static void assertThatRuleIsUpdated(List<ActiveRuleDto> activeRules, RuleDefinitionDto rule, RulePriority severity) {
189 ActiveRuleDto activeRule = findRule(activeRules, rule).get();
191 assertThat(activeRule.getInheritance()).isNull();
192 assertThat(activeRule.getSeverityString()).isEqualTo(severity.name());
193 assertThat(activeRule.getCreatedAt()).isEqualTo(PAST);
194 assertThat(activeRule.getUpdatedAt()).isEqualTo(NOW);
197 private static void assertThatRuleIsUntouched(List<ActiveRuleDto> activeRules, RuleDefinitionDto rule, RulePriority severity) {
198 ActiveRuleDto activeRule = findRule(activeRules, rule).get();
200 assertThat(activeRule.getInheritance()).isNull();
201 assertThat(activeRule.getSeverityString()).isEqualTo(severity.name());
202 assertThat(activeRule.getCreatedAt()).isEqualTo(PAST);
203 assertThat(activeRule.getUpdatedAt()).isEqualTo(PAST);
206 private static void assertThatRuleIsDeactivated(List<ActiveRuleDto> activeRules, RuleDefinitionDto rule) {
207 assertThat(findRule(activeRules, rule)).isEmpty();
210 private void assertThatProfileIsMarkedAsUpdated(RulesProfileDto dto) {
211 RulesProfileDto reloaded = db.getDbClient().qualityProfileDao().selectBuiltInRulesProfiles(db.getSession())
213 .filter(p -> p.getKee().equals(dto.getKee()))
216 assertThat(reloaded.getRulesUpdatedAt()).isNotEmpty();
219 private void assertThatProfileIsNotMarkedAsUpdated(RulesProfileDto dto) {
220 RulesProfileDto reloaded = db.getDbClient().qualityProfileDao().selectBuiltInRulesProfiles(db.getSession())
222 .filter(p -> p.getKee().equals(dto.getKee()))
225 assertThat(reloaded.getRulesUpdatedAt()).isNull();
228 private static Optional<ActiveRuleDto> findRule(List<ActiveRuleDto> activeRules, RuleDefinitionDto rule) {
229 return activeRules.stream()
230 .filter(ar -> ar.getRuleKey().equals(rule.getKey()))
234 private static void activateRuleInDef(RulesProfile apiProfile, RuleDefinitionDto rule, RulePriority severity) {
235 apiProfile.activateRule(org.sonar.api.rules.Rule.create(rule.getRepositoryKey(), rule.getRuleKey()), severity);
238 private void activateRuleInDb(RulesProfileDto profile, RuleDefinitionDto rule, RulePriority severity) {
239 ActiveRuleDto dto = new ActiveRuleDto()
240 .setProfileId(profile.getId())
241 .setSeverity(severity.name())
242 .setRuleId(rule.getId())
245 db.getDbClient().activeRuleDao().insert(db.getSession(), dto);