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 com.google.common.collect.ImmutableMap;
23 import com.google.common.collect.MapDifference.ValueDifference;
24 import org.assertj.core.data.MapEntry;
25 import org.junit.After;
26 import org.junit.Before;
27 import org.junit.Rule;
28 import org.junit.Test;
29 import org.sonar.api.rule.Severity;
30 import org.sonar.api.server.rule.RuleParamType;
31 import org.sonar.api.utils.System2;
32 import org.sonar.db.DbClient;
33 import org.sonar.db.DbSession;
34 import org.sonar.db.DbTester;
35 import org.sonar.db.qualityprofile.QProfileDto;
36 import org.sonar.db.qualityprofile.QualityProfileTesting;
37 import org.sonar.db.rule.RuleDefinitionDto;
38 import org.sonar.db.rule.RuleParamDto;
39 import org.sonar.db.rule.RuleTesting;
40 import org.sonar.server.es.EsTester;
41 import org.sonar.server.pushapi.qualityprofile.QualityProfileChangeEventService;
42 import org.sonar.server.qualityprofile.QProfileComparison.ActiveRuleDiff;
43 import org.sonar.server.qualityprofile.QProfileComparison.QProfileComparisonResult;
44 import org.sonar.server.qualityprofile.builtin.RuleActivator;
45 import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
46 import org.sonar.server.rule.index.RuleIndex;
47 import org.sonar.server.tester.UserSessionRule;
48 import org.sonar.server.util.IntegerTypeValidation;
49 import org.sonar.server.util.TypeValidations;
51 import static java.util.Collections.singleton;
52 import static java.util.Collections.singletonList;
53 import static org.assertj.core.api.Assertions.assertThat;
54 import static org.mockito.Mockito.mock;
56 public class QProfileComparisonTest {
59 public UserSessionRule userSession = UserSessionRule.standalone().anonymous();
61 public DbTester dbTester = DbTester.create();
63 public EsTester es = EsTester.create();
65 private DbSession dbSession;
66 private QProfileRules qProfileRules;
67 private QProfileComparison comparison;
69 private RuleDefinitionDto xooRule1;
70 private RuleDefinitionDto xooRule2;
71 private QProfileDto left;
72 private QProfileDto right;
75 public void before() {
76 DbClient db = dbTester.getDbClient();
77 dbSession = db.openSession(false);
78 RuleIndex ruleIndex = new RuleIndex(es.client(), System2.INSTANCE);
79 ActiveRuleIndexer activeRuleIndexer = new ActiveRuleIndexer(db, es.client());
80 QualityProfileChangeEventService qualityProfileChangeEventService = mock(QualityProfileChangeEventService.class);
81 RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, db, new TypeValidations(singletonList(new IntegerTypeValidation())), userSession);
82 qProfileRules = new QProfileRulesImpl(db, ruleActivator, ruleIndex, activeRuleIndexer, qualityProfileChangeEventService);
83 comparison = new QProfileComparison(db);
85 xooRule1 = RuleTesting.newXooX1().setSeverity("MINOR").getDefinition();
86 xooRule2 = RuleTesting.newXooX2().setSeverity("MAJOR").getDefinition();
87 db.ruleDao().insert(dbSession, xooRule1);
88 db.ruleDao().insert(dbSession, xooRule2);
89 db.ruleDao().insertRuleParam(dbSession, xooRule1, RuleParamDto.createFor(xooRule1)
90 .setName("max").setType(RuleParamType.INTEGER.type()));
91 db.ruleDao().insertRuleParam(dbSession, xooRule1, RuleParamDto.createFor(xooRule1)
92 .setName("min").setType(RuleParamType.INTEGER.type()));
94 left = QualityProfileTesting.newQualityProfileDto().setLanguage("xoo");
95 right = QualityProfileTesting.newQualityProfileDto().setLanguage("xoo");
96 db.qualityProfileDao().insert(dbSession, left, right);
102 public void after() {
107 public void compare_empty_profiles() {
108 QProfileComparisonResult result = comparison.compare(dbSession, left, right);
109 assertThat(result.left().getKee()).isEqualTo(left.getKee());
110 assertThat(result.right().getKee()).isEqualTo(right.getKee());
111 assertThat(result.same()).isEmpty();
112 assertThat(result.inLeft()).isEmpty();
113 assertThat(result.inRight()).isEmpty();
114 assertThat(result.modified()).isEmpty();
115 assertThat(result.collectRuleKeys()).isEmpty();
119 public void compare_same() {
120 RuleActivation commonActivation = RuleActivation.create(xooRule1.getUuid(), Severity.CRITICAL,
121 ImmutableMap.of("min", "7", "max", "42"));
122 qProfileRules.activateAndCommit(dbSession, left, singleton(commonActivation));
123 qProfileRules.activateAndCommit(dbSession, right, singleton(commonActivation));
125 QProfileComparisonResult result = comparison.compare(dbSession, left, right);
126 assertThat(result.left().getKee()).isEqualTo(left.getKee());
127 assertThat(result.right().getKee()).isEqualTo(right.getKee());
128 assertThat(result.same()).isNotEmpty().containsOnlyKeys(xooRule1.getKey());
129 assertThat(result.inLeft()).isEmpty();
130 assertThat(result.inRight()).isEmpty();
131 assertThat(result.modified()).isEmpty();
132 assertThat(result.collectRuleKeys()).containsOnly(xooRule1.getKey());
136 public void compare_only_left() {
137 RuleActivation activation = RuleActivation.create(xooRule1.getUuid());
138 qProfileRules.activateAndCommit(dbSession, left, singleton(activation));
140 QProfileComparisonResult result = comparison.compare(dbSession, left, right);
141 assertThat(result.left().getKee()).isEqualTo(left.getKee());
142 assertThat(result.right().getKee()).isEqualTo(right.getKee());
143 assertThat(result.same()).isEmpty();
144 assertThat(result.inLeft()).isNotEmpty().containsOnlyKeys(xooRule1.getKey());
145 assertThat(result.inRight()).isEmpty();
146 assertThat(result.modified()).isEmpty();
147 assertThat(result.collectRuleKeys()).containsOnly(xooRule1.getKey());
151 public void compare_only_right() {
152 qProfileRules.activateAndCommit(dbSession, right, singleton(RuleActivation.create(xooRule1.getUuid())));
154 QProfileComparisonResult result = comparison.compare(dbSession, left, right);
155 assertThat(result.left().getKee()).isEqualTo(left.getKee());
156 assertThat(result.right().getKee()).isEqualTo(right.getKee());
157 assertThat(result.same()).isEmpty();
158 assertThat(result.inLeft()).isEmpty();
159 assertThat(result.inRight()).isNotEmpty().containsOnlyKeys(xooRule1.getKey());
160 assertThat(result.modified()).isEmpty();
161 assertThat(result.collectRuleKeys()).containsOnly(xooRule1.getKey());
165 public void compare_disjoint() {
166 qProfileRules.activateAndCommit(dbSession, left, singleton(RuleActivation.create(xooRule1.getUuid())));
167 qProfileRules.activateAndCommit(dbSession, right, singleton(RuleActivation.create(xooRule2.getUuid())));
169 QProfileComparisonResult result = comparison.compare(dbSession, left, right);
170 assertThat(result.left().getKee()).isEqualTo(left.getKee());
171 assertThat(result.right().getKee()).isEqualTo(right.getKee());
172 assertThat(result.same()).isEmpty();
173 assertThat(result.inLeft()).isNotEmpty().containsOnlyKeys(xooRule1.getKey());
174 assertThat(result.inRight()).isNotEmpty().containsOnlyKeys(xooRule2.getKey());
175 assertThat(result.modified()).isEmpty();
176 assertThat(result.collectRuleKeys()).containsOnly(xooRule1.getKey(), xooRule2.getKey());
180 public void compare_modified_severity() {
181 qProfileRules.activateAndCommit(dbSession, left, singleton(RuleActivation.create(xooRule1.getUuid(), Severity.CRITICAL, null)));
182 qProfileRules.activateAndCommit(dbSession, right, singleton(RuleActivation.create(xooRule1.getUuid(), Severity.BLOCKER, null)));
184 QProfileComparisonResult result = comparison.compare(dbSession, left, right);
185 assertThat(result.left().getKee()).isEqualTo(left.getKee());
186 assertThat(result.right().getKee()).isEqualTo(right.getKee());
187 assertThat(result.same()).isEmpty();
188 assertThat(result.inLeft()).isEmpty();
189 assertThat(result.inRight()).isEmpty();
190 assertThat(result.modified()).isNotEmpty().containsOnlyKeys(xooRule1.getKey());
191 assertThat(result.collectRuleKeys()).containsOnly(xooRule1.getKey());
193 ActiveRuleDiff activeRuleDiff = result.modified().get(xooRule1.getKey());
194 assertThat(activeRuleDiff.leftSeverity()).isEqualTo(Severity.CRITICAL);
195 assertThat(activeRuleDiff.rightSeverity()).isEqualTo(Severity.BLOCKER);
196 assertThat(activeRuleDiff.paramDifference().areEqual()).isTrue();
200 public void compare_modified_param() {
201 qProfileRules.activateAndCommit(dbSession, left, singleton(RuleActivation.create(xooRule1.getUuid(), null, ImmutableMap.of("max", "20"))));
202 qProfileRules.activateAndCommit(dbSession, right, singleton(RuleActivation.create(xooRule1.getUuid(), null, ImmutableMap.of("max", "30"))));
204 QProfileComparisonResult result = comparison.compare(dbSession, left, right);
205 assertThat(result.left().getKee()).isEqualTo(left.getKee());
206 assertThat(result.right().getKee()).isEqualTo(right.getKee());
207 assertThat(result.same()).isEmpty();
208 assertThat(result.inLeft()).isEmpty();
209 assertThat(result.inRight()).isEmpty();
210 assertThat(result.modified()).isNotEmpty().containsOnlyKeys(xooRule1.getKey());
211 assertThat(result.collectRuleKeys()).containsOnly(xooRule1.getKey());
213 ActiveRuleDiff activeRuleDiff = result.modified().get(xooRule1.getKey());
214 assertThat(activeRuleDiff.leftSeverity()).isEqualTo(activeRuleDiff.rightSeverity()).isEqualTo(xooRule1.getSeverityString());
215 assertThat(activeRuleDiff.paramDifference().areEqual()).isFalse();
216 assertThat(activeRuleDiff.paramDifference().entriesDiffering()).isNotEmpty();
217 ValueDifference<String> paramDiff = activeRuleDiff.paramDifference().entriesDiffering().get("max");
218 assertThat(paramDiff.leftValue()).isEqualTo("20");
219 assertThat(paramDiff.rightValue()).isEqualTo("30");
223 public void compare_different_params() {
224 qProfileRules.activateAndCommit(dbSession, left, singleton(RuleActivation.create(xooRule1.getUuid(), null, ImmutableMap.of("max", "20"))));
225 qProfileRules.activateAndCommit(dbSession, right, singleton(RuleActivation.create(xooRule1.getUuid(), null, ImmutableMap.of("min", "5"))));
227 QProfileComparisonResult result = comparison.compare(dbSession, left, right);
228 assertThat(result.left().getKee()).isEqualTo(left.getKee());
229 assertThat(result.right().getKee()).isEqualTo(right.getKee());
230 assertThat(result.same()).isEmpty();
231 assertThat(result.inLeft()).isEmpty();
232 assertThat(result.inRight()).isEmpty();
233 assertThat(result.modified()).isNotEmpty().containsOnlyKeys(xooRule1.getKey());
234 assertThat(result.collectRuleKeys()).containsOnly(xooRule1.getKey());
236 ActiveRuleDiff activeRuleDiff = result.modified().get(xooRule1.getKey());
237 assertThat(activeRuleDiff.leftSeverity()).isEqualTo(activeRuleDiff.rightSeverity()).isEqualTo(xooRule1.getSeverityString());
238 assertThat(activeRuleDiff.paramDifference().areEqual()).isFalse();
239 assertThat(activeRuleDiff.paramDifference().entriesDiffering()).isEmpty();
240 assertThat(activeRuleDiff.paramDifference().entriesOnlyOnLeft()).containsExactly(MapEntry.entry("max", "20"));
241 assertThat(activeRuleDiff.paramDifference().entriesOnlyOnRight()).containsExactly(MapEntry.entry("min", "5"));