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.ArrayList;
23 import java.util.Collections;
24 import java.util.List;
25 import java.util.Random;
26 import org.junit.Rule;
27 import org.junit.Test;
28 import org.junit.rules.ExpectedException;
29 import org.sonar.api.profiles.ProfileDefinition;
30 import org.sonar.api.profiles.RulesProfile;
31 import org.sonar.api.resources.Language;
32 import org.sonar.api.resources.Languages;
33 import org.sonar.api.utils.ValidationMessages;
34 import org.sonar.server.language.LanguageTesting;
36 import static java.util.Arrays.asList;
37 import static org.assertj.core.api.Assertions.assertThat;
38 import static org.assertj.core.groups.Tuple.tuple;
40 public class BuiltInQProfileRepositoryImplTest {
41 private static final Language FOO_LANGUAGE = LanguageTesting.newLanguage("foo", "foo", "foo");
42 private static final String SONAR_WAY_QP_NAME = "Sonar way";
45 public ExpectedException expectedException = ExpectedException.none();
48 public void get_throws_ISE_if_called_before_initialize() {
49 BuiltInQProfileRepositoryImpl underTest = new BuiltInQProfileRepositoryImpl(new Languages());
51 expectedException.expect(IllegalStateException.class);
52 expectedException.expectMessage("initialize must be called first");
58 public void initialize_throws_ISE_if_called_twice() {
59 BuiltInQProfileRepositoryImpl underTest = new BuiltInQProfileRepositoryImpl(new Languages());
60 underTest.initialize();
62 expectedException.expect(IllegalStateException.class);
63 expectedException.expectMessage("initialize must be called only once");
65 underTest.initialize();
69 public void initialize_creates_no_BuiltInQProfile_when_there_is_no_definition() {
70 BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(FOO_LANGUAGE));
72 underTest.initialize();
74 assertThat(underTest.get()).isEmpty();
78 public void initialize_creates_no_BuiltInQProfile_when_all_definitions_apply_to_non_defined_languages() {
79 BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(), new DummyProfileDefinition("foo", "P1", false));
81 underTest.initialize();
83 assertThat(underTest.get()).isEmpty();
87 public void initialize_throws_IAE_if_profileDefinition_creates_RulesProfile_with_null_name() {
88 DummyProfileDefinition definition = new DummyProfileDefinition("foo", null, false);
89 BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(), definition);
91 expectedException.expect(IllegalArgumentException.class);
92 expectedException.expectMessage("Profile created by Definition " + definition + " can't have a blank name");
94 underTest.initialize();
98 public void initialize_throws_IAE_if_profileDefinition_creates_RulesProfile_with_empty_name() {
99 DummyProfileDefinition definition = new DummyProfileDefinition("foo", "", false);
100 BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(), definition);
102 expectedException.expect(IllegalArgumentException.class);
103 expectedException.expectMessage("Profile created by Definition " + definition + " can't have a blank name");
105 underTest.initialize();
109 public void initialize_makes_single_profile_of_a_language_default_even_if_not_flagged_as_so() {
110 BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(FOO_LANGUAGE), new DummyProfileDefinition("foo", "foo1", false));
112 underTest.initialize();
114 assertThat(underTest.get())
115 .extracting(BuiltInQProfile::getLanguage, BuiltInQProfile::isDefault)
116 .containsExactly(tuple(FOO_LANGUAGE.getKey(), true));
120 public void initialize_makes_single_profile_of_a_language_default_even_if_flagged_as_so() {
121 BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(FOO_LANGUAGE), new DummyProfileDefinition("foo", "foo1", true));
123 underTest.initialize();
125 assertThat(underTest.get())
126 .extracting(BuiltInQProfile::getLanguage, BuiltInQProfile::isDefault)
127 .containsExactly(tuple(FOO_LANGUAGE.getKey(), true));
131 public void initialize_makes_first_profile_of_a_language_default_when_none_flagged_as_so() {
132 List<DummyProfileDefinition> definitions = new ArrayList<>(
133 asList(new DummyProfileDefinition("foo", "foo1", false), new DummyProfileDefinition("foo", "foo2", false)));
134 Collections.shuffle(definitions);
135 String firstName = definitions.get(0).getName();
136 String secondName = definitions.get(1).getName();
137 BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(FOO_LANGUAGE), definitions.toArray(new ProfileDefinition[0]));
139 underTest.initialize();
141 assertThat(underTest.get())
142 .extracting(BuiltInQProfile::getName, BuiltInQProfile::isDefault)
143 .containsExactlyInAnyOrder(tuple(firstName, true), tuple(secondName, false));
147 public void initialize_fails_with_ISE_when_two_profiles_with_different_name_are_default_for_the_same_language() {
148 BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(FOO_LANGUAGE),
149 new DummyProfileDefinition("foo", "foo1", true), new DummyProfileDefinition("foo", "foo2", true));
151 expectedException.expect(IllegalStateException.class);
152 expectedException.expectMessage("Several Quality profiles are flagged as default for the language foo: [foo1, foo2]");
154 underTest.initialize();
158 public void initialize_creates_profile_as_default_even_if_only_one_profile_with_given_name_has_default_flag_true() {
160 boolean flag = new Random().nextBoolean();
161 BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(FOO_LANGUAGE),
162 new DummyProfileDefinition("foo", name, flag), new DummyProfileDefinition("foo", name, !flag));
164 underTest.initialize();
166 assertThat(underTest.get())
167 .extracting(BuiltInQProfile::getLanguage, BuiltInQProfile::isDefault)
168 .containsExactly(tuple("foo", true));
172 public void initialize_creates_single_profile_if_several_profile_have_the_same_name_for_a_given_language() {
173 BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(new Languages(FOO_LANGUAGE),
174 new DummyProfileDefinition("foo", "aName", true), new DummyProfileDefinition("foo", "aName", true));
176 underTest.initialize();
178 assertThat(underTest.get())
179 .extracting(BuiltInQProfile::getLanguage, BuiltInQProfile::getName)
180 .containsExactlyInAnyOrder(tuple(FOO_LANGUAGE.getKey(), "aName"));
184 public void initialize_creates_profile_Sonar_Way_as_default_if_none_other_is_defined_default_for_a_given_language() {
185 BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(
186 new Languages(FOO_LANGUAGE),
187 new DummyProfileDefinition("foo", "doh", false), new DummyProfileDefinition("foo", "boo", false),
188 new DummyProfileDefinition("foo", SONAR_WAY_QP_NAME, false), new DummyProfileDefinition("foo", "goo", false));
190 underTest.initialize();
192 assertThat(underTest.get())
193 .filteredOn(b -> FOO_LANGUAGE.getKey().equals(b.getLanguage()))
194 .filteredOn(BuiltInQProfile::isDefault)
195 .extracting(BuiltInQProfile::getName)
196 .containsExactly(SONAR_WAY_QP_NAME);
200 public void initialize_does_not_create_Sonar_Way_as_default_if_other_profile_is_defined_as_default() {
201 BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(
202 new Languages(FOO_LANGUAGE),
203 new DummyProfileDefinition("foo", SONAR_WAY_QP_NAME, false), new DummyProfileDefinition("foo", "goo", true));
205 underTest.initialize();
207 assertThat(underTest.get())
208 .filteredOn(b -> FOO_LANGUAGE.getKey().equals(b.getLanguage()))
209 .filteredOn(BuiltInQProfile::isDefault)
210 .extracting(BuiltInQProfile::getName)
211 .containsExactly("goo");
215 public void initialize_matches_Sonar_Way_default_with_case_sensitivity() {
216 String sonarWayInOtherCase = SONAR_WAY_QP_NAME.toUpperCase();
217 BuiltInQProfileRepository underTest = new BuiltInQProfileRepositoryImpl(
218 new Languages(FOO_LANGUAGE),
219 new DummyProfileDefinition("foo", "goo", false), new DummyProfileDefinition("foo", sonarWayInOtherCase, false));
221 underTest.initialize();
223 assertThat(underTest.get())
224 .filteredOn(b -> FOO_LANGUAGE.getKey().equals(b.getLanguage()))
225 .filteredOn(BuiltInQProfile::isDefault)
226 .extracting(BuiltInQProfile::getName)
227 .containsExactly("goo");
230 private static final class DummyProfileDefinition extends ProfileDefinition {
231 private final String language;
232 private final String name;
233 private final boolean defaultProfile;
235 private DummyProfileDefinition(String language, String name, boolean defaultProfile) {
236 this.language = language;
238 this.defaultProfile = defaultProfile;
242 public RulesProfile createProfile(ValidationMessages validation) {
243 RulesProfile res = RulesProfile.create(name, language);
244 res.setDefaultProfile(defaultProfile);
248 String getLanguage() {
256 boolean isDefaultProfile() {
257 return defaultProfile;