3 * Copyright (C) 2009-2021 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;
24 import org.junit.Rule;
25 import org.junit.Test;
26 import org.junit.rules.ExpectedException;
27 import org.sonar.api.resources.Language;
28 import org.sonar.api.resources.Languages;
29 import org.sonar.api.rule.RuleKey;
30 import org.sonar.api.server.profile.BuiltInQualityProfilesDefinition;
31 import org.sonar.db.DbClient;
32 import org.sonar.db.DbTester;
33 import org.sonar.db.rule.RuleDefinitionDto;
34 import org.sonar.server.language.LanguageTesting;
36 import static java.util.Arrays.asList;
37 import static java.util.Collections.emptyList;
38 import static java.util.Collections.singletonList;
39 import static org.assertj.core.api.Assertions.assertThat;
40 import static org.assertj.core.groups.Tuple.tuple;
41 import static org.mockito.Mockito.mock;
42 import static org.sonar.db.rule.RuleTesting.EXTERNAL_XOO;
43 import static org.sonar.server.qualityprofile.BuiltInQProfile.ActiveRule;
45 public class BuiltInQProfileRepositoryImplTest {
46 private static final Language FOO_LANGUAGE = LanguageTesting.newLanguage("foo", "foo", "foo");
47 private static final String SONAR_WAY_QP_NAME = "Sonar way";
50 public ExpectedException expectedException = ExpectedException.none();
52 public DbTester db = DbTester.create();
54 private DbClient dbClient = db.getDbClient();
57 public void create_qprofile_with_rule() {
58 RuleDefinitionDto rule1 = db.rules().insert();
59 RuleDefinitionDto rule2 = db.rules().insert();
61 List<DummyProfileDefinition> definitions = singletonList(new DummyProfileDefinition("foo", "foo", false,
62 asList(rule1.getKey(), rule2.getKey())));
63 BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(dbClient, new Languages(FOO_LANGUAGE), definitions.toArray(new BuiltInQualityProfilesDefinition[0]));
65 underTest.initialize();
67 assertThat(underTest.get())
68 .extracting(BuiltInQProfile::getName)
69 .containsExactlyInAnyOrder("foo");
70 assertThat(underTest.get().get(0).getActiveRules())
71 .extracting(ActiveRule::getRuleUuid, ActiveRule::getRuleKey)
72 .containsExactlyInAnyOrder(
73 tuple(rule1.getUuid(), rule1.getKey()),
74 tuple(rule2.getUuid(), rule2.getKey()));
78 public void make_single_profile_of_a_language_default_even_if_not_flagged_as_so() {
79 BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(dbClient, new Languages(FOO_LANGUAGE), new DummyProfileDefinition("foo", "foo1", false));
81 underTest.initialize();
83 assertThat(underTest.get())
84 .extracting(BuiltInQProfile::getLanguage, BuiltInQProfile::isDefault)
85 .containsExactly(tuple(FOO_LANGUAGE.getKey(), true));
89 public void make_single_profile_of_a_language_default_even_if_flagged_as_so() {
90 BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(dbClient, new Languages(FOO_LANGUAGE), new DummyProfileDefinition("foo", "foo1", true));
92 underTest.initialize();
94 assertThat(underTest.get())
95 .extracting(BuiltInQProfile::getLanguage, BuiltInQProfile::isDefault)
96 .containsExactly(tuple(FOO_LANGUAGE.getKey(), true));
100 public void make_first_profile_of_a_language_default_when_none_flagged_as_so() {
101 List<DummyProfileDefinition> definitions = new ArrayList<>(
102 asList(new DummyProfileDefinition("foo", "foo1", false), new DummyProfileDefinition("foo", "foo2", false)));
103 String firstName = definitions.get(0).getName();
104 String secondName = definitions.get(1).getName();
105 BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(dbClient, new Languages(FOO_LANGUAGE), definitions.toArray(new BuiltInQualityProfilesDefinition[0]));
107 underTest.initialize();
109 assertThat(underTest.get())
110 .extracting(BuiltInQProfile::getName, BuiltInQProfile::isDefault)
111 .containsExactlyInAnyOrder(tuple(firstName, true), tuple(secondName, false));
115 public void create_profile_Sonar_Way_as_default_if_none_other_is_defined_default_for_a_given_language() {
116 BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(
117 dbClient, new Languages(FOO_LANGUAGE),
118 new DummyProfileDefinition("foo", "doh", false), new DummyProfileDefinition("foo", "boo", false),
119 new DummyProfileDefinition("foo", SONAR_WAY_QP_NAME, false), new DummyProfileDefinition("foo", "goo", false));
121 underTest.initialize();
123 assertThat(underTest.get())
124 .filteredOn(b -> FOO_LANGUAGE.getKey().equals(b.getLanguage()))
125 .filteredOn(BuiltInQProfile::isDefault)
126 .extracting(BuiltInQProfile::getName)
127 .containsExactly(SONAR_WAY_QP_NAME);
131 public void do_not_create_Sonar_Way_as_default_if_other_profile_is_defined_as_default() {
132 BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(
133 dbClient, new Languages(FOO_LANGUAGE),
134 new DummyProfileDefinition("foo", SONAR_WAY_QP_NAME, false), new DummyProfileDefinition("foo", "goo", true));
136 underTest.initialize();
138 assertThat(underTest.get())
139 .filteredOn(b -> FOO_LANGUAGE.getKey().equals(b.getLanguage()))
140 .filteredOn(BuiltInQProfile::isDefault)
141 .extracting(BuiltInQProfile::getName)
142 .containsExactly("goo");
146 public void match_Sonar_Way_default_with_case_sensitivity() {
147 String sonarWayInOtherCase = SONAR_WAY_QP_NAME.toUpperCase();
148 BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(
149 dbClient, new Languages(FOO_LANGUAGE),
150 new DummyProfileDefinition("foo", "goo", false), new DummyProfileDefinition("foo", sonarWayInOtherCase, false));
152 underTest.initialize();
154 assertThat(underTest.get())
155 .filteredOn(b -> FOO_LANGUAGE.getKey().equals(b.getLanguage()))
156 .filteredOn(BuiltInQProfile::isDefault)
157 .extracting(BuiltInQProfile::getName)
158 .containsExactly("goo");
162 public void create_no_BuiltInQProfile_when_all_definitions_apply_to_non_defined_languages() {
163 BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(mock(DbClient.class), new Languages(), new DummyProfileDefinition("foo", "P1", false));
165 underTest.initialize();
167 assertThat(underTest.get()).isEmpty();
171 public void create_qprofile_with_deprecated_rule() {
172 RuleDefinitionDto rule1 = db.rules().insert();
173 db.rules().insertDeprecatedKey(d -> d.setRuleUuid(rule1.getUuid()).setOldRepositoryKey("oldRepo").setOldRuleKey("oldKey"));
174 RuleDefinitionDto rule2 = db.rules().insert();
175 List<DummyProfileDefinition> definitions = singletonList(new DummyProfileDefinition("foo", "foo", false,
176 asList(RuleKey.of("oldRepo", "oldKey"), rule2.getKey())));
177 BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(dbClient, new Languages(FOO_LANGUAGE), definitions.toArray(new BuiltInQualityProfilesDefinition[0]));
179 underTest.initialize();
181 assertThat(underTest.get())
182 .extracting(BuiltInQProfile::getName)
183 .containsExactlyInAnyOrder("foo");
184 assertThat(underTest.get().get(0).getActiveRules())
185 .extracting(ActiveRule::getRuleUuid, ActiveRule::getRuleKey)
186 .containsExactlyInAnyOrder(
187 tuple(rule1.getUuid(), rule1.getKey()),
188 tuple(rule2.getUuid(), rule2.getKey()));
192 public void fail_with_ISE_when_rule_does_not_exist() {
193 List<DummyProfileDefinition> definitions = singletonList(new DummyProfileDefinition("foo", "foo", false, singletonList(EXTERNAL_XOO)));
194 BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(dbClient, new Languages(FOO_LANGUAGE), definitions.toArray(new BuiltInQualityProfilesDefinition[0]));
196 expectedException.expect(IllegalStateException.class);
197 expectedException.expectMessage(String.format("Rule with key '%s' not found", EXTERNAL_XOO.toString()));
199 underTest.initialize();
203 public void fail_with_ISE_when_two_profiles_with_different_name_are_default_for_the_same_language() {
204 BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(dbClient, new Languages(FOO_LANGUAGE),
205 new DummyProfileDefinition("foo", "foo1", true), new DummyProfileDefinition("foo", "foo2", true));
207 expectedException.expect(IllegalStateException.class);
208 expectedException.expectMessage("Several Quality profiles are flagged as default for the language foo: [foo1, foo2]");
210 underTest.initialize();
214 public void get_throws_ISE_if_called_before_initialize() {
215 BuiltInQProfileRepositoryImpl underTest = new BuiltInQProfileRepositoryImpl(mock(DbClient.class), new Languages());
217 expectedException.expect(IllegalStateException.class);
218 expectedException.expectMessage("initialize must be called first");
224 public void initialize_throws_ISE_if_called_twice() {
225 BuiltInQProfileRepositoryImpl underTest = new BuiltInQProfileRepositoryImpl(mock(DbClient.class), new Languages());
226 underTest.initialize();
228 expectedException.expect(IllegalStateException.class);
229 expectedException.expectMessage("initialize must be called only once");
231 underTest.initialize();
235 public void initialize_throws_ISE_if_language_has_no_builtin_qp() {
236 BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(mock(DbClient.class), new Languages(FOO_LANGUAGE));
238 expectedException.expect(IllegalStateException.class);
239 expectedException.expectMessage("The following languages have no built-in quality profiles: foo");
241 underTest.initialize();
244 private static final class DummyProfileDefinition implements BuiltInQualityProfilesDefinition {
245 private final String language;
246 private final String name;
247 private final boolean defaultProfile;
248 private final List<RuleKey> activeRuleKeys;
250 private DummyProfileDefinition(String language, String name, boolean defaultProfile, List<RuleKey> activeRuleKeys) {
251 this.language = language;
253 this.defaultProfile = defaultProfile;
254 this.activeRuleKeys = activeRuleKeys;
257 private DummyProfileDefinition(String language, String name, boolean defaultProfile) {
258 this(language, name, defaultProfile, emptyList());
262 public void define(Context context) {
263 NewBuiltInQualityProfile builtInQualityProfile = context.createBuiltInQualityProfile(name, language);
264 activeRuleKeys.forEach(activeRuleKey -> builtInQualityProfile.activateRule(activeRuleKey.repository(), activeRuleKey.rule()));
265 builtInQualityProfile.setDefault(defaultProfile);
266 builtInQualityProfile.done();