3 * Copyright (C) 2009-2020 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.ws;
22 import java.util.Collections;
23 import java.util.List;
24 import org.junit.Before;
25 import org.junit.Rule;
26 import org.junit.Test;
27 import org.junit.rules.ExpectedException;
28 import org.sonar.api.resources.Language;
29 import org.sonar.api.resources.Languages;
30 import org.sonar.api.rule.RuleKey;
31 import org.sonar.api.rule.RuleStatus;
32 import org.sonar.api.rule.Severity;
33 import org.sonar.api.server.ws.WebService;
34 import org.sonar.api.server.ws.WebService.Param;
35 import org.sonar.api.utils.System2;
36 import org.sonar.db.DbClient;
37 import org.sonar.db.DbSession;
38 import org.sonar.db.DbTester;
39 import org.sonar.db.qualityprofile.ActiveRuleDto;
40 import org.sonar.db.qualityprofile.OrgActiveRuleDto;
41 import org.sonar.db.qualityprofile.QProfileDto;
42 import org.sonar.db.qualityprofile.QualityProfileTesting;
43 import org.sonar.db.rule.RuleDefinitionDto;
44 import org.sonar.db.rule.RuleTesting;
45 import org.sonar.db.user.UserDto;
46 import org.sonar.server.es.EsClient;
47 import org.sonar.server.es.EsTester;
48 import org.sonar.server.es.SearchOptions;
49 import org.sonar.server.exceptions.BadRequestException;
50 import org.sonar.server.exceptions.ForbiddenException;
51 import org.sonar.server.language.LanguageTesting;
52 import org.sonar.server.organization.TestDefaultOrganizationProvider;
53 import org.sonar.server.qualityprofile.QProfileTreeImpl;
54 import org.sonar.server.qualityprofile.RuleActivator;
55 import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
56 import org.sonar.server.rule.index.RuleIndex;
57 import org.sonar.server.rule.index.RuleIndexer;
58 import org.sonar.server.rule.index.RuleQuery;
59 import org.sonar.server.tester.UserSessionRule;
60 import org.sonar.server.util.TypeValidations;
61 import org.sonar.server.ws.TestRequest;
62 import org.sonar.server.ws.WsActionTester;
63 import org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters;
65 import static java.util.Arrays.asList;
66 import static java.util.Collections.emptySet;
67 import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
68 import static org.assertj.core.api.Assertions.assertThat;
69 import static org.sonar.db.permission.GlobalPermission.ADMINISTER_QUALITY_PROFILES;
70 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LANGUAGE;
71 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PARENT_QUALITY_PROFILE;
72 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_QUALITY_PROFILE;
74 public class ChangeParentActionTest {
77 public DbTester db = DbTester.create(System2.INSTANCE);
79 public EsTester es = EsTester.create();
81 public UserSessionRule userSession = UserSessionRule.standalone();
83 public ExpectedException expectedException = ExpectedException.none();
85 private DbClient dbClient;
86 private DbSession dbSession;
87 private RuleIndex ruleIndex;
88 private RuleIndexer ruleIndexer;
89 private ActiveRuleIndexer activeRuleIndexer;
90 private WsActionTester ws;
91 private Language language = LanguageTesting.newLanguage(randomAlphanumeric(20));
92 private String ruleRepository = randomAlphanumeric(5);
93 private QProfileTreeImpl qProfileTree;
97 dbClient = db.getDbClient();
98 dbSession = db.getSession();
99 EsClient esClient = es.client();
100 ruleIndex = new RuleIndex(esClient, System2.INSTANCE);
101 ruleIndexer = new RuleIndexer(esClient, dbClient);
102 activeRuleIndexer = new ActiveRuleIndexer(dbClient, esClient);
103 TypeValidations typeValidations = new TypeValidations(Collections.emptyList());
104 RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, dbClient, typeValidations, userSession);
105 qProfileTree = new QProfileTreeImpl(dbClient, ruleActivator, System2.INSTANCE, activeRuleIndexer);
106 ChangeParentAction underTest = new ChangeParentAction(
110 new QProfileWsSupport(
113 TestDefaultOrganizationProvider.from(db)),
116 ws = new WsActionTester(underTest);
117 userSession.logIn().addPermission(ADMINISTER_QUALITY_PROFILES);
121 public void definition() {
122 WebService.Action definition = ws.getDef();
123 assertThat(definition.isPost()).isTrue();
124 assertThat(definition.params()).extracting(Param::key).containsExactlyInAnyOrder(
125 "qualityProfile", "language", "parentQualityProfile");
129 public void change_parent_with_no_parent_before() {
130 QProfileDto parent1 = createProfile();
131 QProfileDto child = createProfile();
133 RuleDefinitionDto rule1 = createRule();
134 createActiveRule(rule1, parent1);
135 ruleIndexer.commitAndIndex(dbSession, rule1.getUuid());
136 activeRuleIndexer.indexOnStartup(emptySet());
138 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, child.getKee())).isEmpty();
143 .setParam(PARAM_LANGUAGE, child.getLanguage())
144 .setParam(PARAM_QUALITY_PROFILE, child.getName())
145 .setParam(PARAM_PARENT_QUALITY_PROFILE, parent1.getName())
148 // Check rule 1 enabled
149 List<OrgActiveRuleDto> activeRules1 = dbClient.activeRuleDao().selectByProfile(dbSession, child);
150 assertThat(activeRules1).hasSize(1);
151 assertThat(activeRules1.get(0).getKey().getRuleKey().rule()).isEqualTo(rule1.getRuleKey());
153 assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).hasSize(1);
157 public void replace_existing_parent() {
158 QProfileDto parent1 = createProfile();
159 QProfileDto parent2 = createProfile();
160 QProfileDto child = createProfile();
162 RuleDefinitionDto rule1 = createRule();
163 RuleDefinitionDto rule2 = createRule();
164 createActiveRule(rule1, parent1);
165 createActiveRule(rule2, parent2);
166 ruleIndexer.commitAndIndex(dbSession, asList(rule1.getUuid(), rule2.getUuid()));
167 activeRuleIndexer.indexOnStartup(emptySet());
170 qProfileTree.setParentAndCommit(dbSession, child, parent1);
172 // Set parent 2 through WS
175 .setParam(PARAM_LANGUAGE, child.getLanguage())
176 .setParam(PARAM_QUALITY_PROFILE, child.getName())
177 .setParam(PARAM_PARENT_QUALITY_PROFILE, parent2.getName())
180 // Check rule 2 enabled
181 List<OrgActiveRuleDto> activeRules2 = dbClient.activeRuleDao().selectByProfile(dbSession, child);
182 assertThat(activeRules2).hasSize(1);
183 assertThat(activeRules2.get(0).getKey().getRuleKey().rule()).isEqualTo(rule2.getRuleKey());
185 assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).hasSize(1);
189 public void remove_parent() {
190 QProfileDto parent = createProfile();
191 QProfileDto child = createProfile();
193 RuleDefinitionDto rule1 = createRule();
194 createActiveRule(rule1, parent);
195 ruleIndexer.commitAndIndex(dbSession, rule1.getUuid());
196 activeRuleIndexer.indexOnStartup(emptySet());
199 qProfileTree.setParentAndCommit(dbSession, child, parent);
201 // Remove parent through WS
204 .setParam(PARAM_LANGUAGE, child.getLanguage())
205 .setParam(PARAM_QUALITY_PROFILE, child.getName())
208 // Check no rule enabled
209 assertThat(dbClient.activeRuleDao().selectByProfile(dbSession, child)).isEmpty();
211 assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).isEmpty();
215 public void change_parent_with_names() {
216 QProfileDto parent1 = createProfile();
217 QProfileDto parent2 = createProfile();
218 QProfileDto child = createProfile();
220 RuleDefinitionDto rule1 = createRule();
221 RuleDefinitionDto rule2 = createRule();
222 createActiveRule(rule1, parent1);
223 createActiveRule(rule2, parent2);
224 ruleIndexer.commitAndIndex(dbSession, rule1.getUuid());
225 activeRuleIndexer.indexOnStartup(emptySet());
227 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, child.getKee())).isEmpty();
232 .setParam(PARAM_LANGUAGE, child.getLanguage())
233 .setParam(PARAM_QUALITY_PROFILE, child.getName())
234 .setParam(PARAM_PARENT_QUALITY_PROFILE, parent1.getName())
237 // 1. check rule 1 enabled
238 List<OrgActiveRuleDto> activeRules1 = dbClient.activeRuleDao().selectByProfile(dbSession, child);
239 assertThat(activeRules1).hasSize(1);
240 assertThat(activeRules1.get(0).getKey().getRuleKey().rule()).isEqualTo(rule1.getRuleKey());
241 assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).hasSize(1);
246 .setParam(PARAM_LANGUAGE, child.getLanguage())
247 .setParam(PARAM_QUALITY_PROFILE, child.getName())
248 .setParam(QualityProfileWsParameters.PARAM_PARENT_QUALITY_PROFILE, parent2.getName())
251 // 2. check rule 2 enabled
252 List<OrgActiveRuleDto> activeRules2 = dbClient.activeRuleDao().selectByProfile(dbSession, child);
253 assertThat(activeRules2).hasSize(1);
254 assertThat(activeRules2.get(0).getKey().getRuleKey().rule()).isEqualTo(rule2.getRuleKey());
259 .setParam(PARAM_LANGUAGE, child.getLanguage())
260 .setParam(PARAM_QUALITY_PROFILE, child.getName())
261 .setParam(QualityProfileWsParameters.PARAM_PARENT_QUALITY_PROFILE, "")
264 // 3. check no rule enabled
265 List<OrgActiveRuleDto> activeRules = dbClient.activeRuleDao().selectByProfile(dbSession, child);
266 assertThat(activeRules).isEmpty();
267 assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).isEmpty();
271 public void remove_parent_with_empty_key() {
272 QProfileDto parent = createProfile();
273 QProfileDto child = createProfile();
275 RuleDefinitionDto rule1 = createRule();
276 createActiveRule(rule1, parent);
277 ruleIndexer.commitAndIndex(dbSession, rule1.getUuid());
278 activeRuleIndexer.indexOnStartup(emptySet());
280 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, child.getKee())).isEmpty();
283 qProfileTree.setParentAndCommit(dbSession, child, parent);
288 .setParam(PARAM_LANGUAGE, child.getLanguage())
289 .setParam(PARAM_QUALITY_PROFILE, child.getName())
290 .setParam(PARAM_PARENT_QUALITY_PROFILE, "")
293 // Check no rule enabled
294 assertThat(dbClient.activeRuleDao().selectByProfile(dbSession, child)).isEmpty();
295 assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).isEmpty();
299 public void as_qprofile_editor() {
300 QProfileDto parent1 = createProfile();
301 QProfileDto parent2 = createProfile();
302 QProfileDto child = createProfile();
304 RuleDefinitionDto rule1 = createRule();
305 RuleDefinitionDto rule2 = createRule();
306 createActiveRule(rule1, parent1);
307 createActiveRule(rule2, parent2);
308 ruleIndexer.commitAndIndex(dbSession, asList(rule1.getUuid(), rule2.getUuid()));
309 activeRuleIndexer.indexOnStartup(emptySet());
311 qProfileTree.setParentAndCommit(dbSession, child, parent1);
312 UserDto user = db.users().insertUser();
313 db.qualityProfiles().addUserPermission(child, user);
314 userSession.logIn(user);
318 .setParam(PARAM_LANGUAGE, child.getLanguage())
319 .setParam(PARAM_QUALITY_PROFILE, child.getName())
320 .setParam(PARAM_PARENT_QUALITY_PROFILE, parent2.getName())
323 List<OrgActiveRuleDto> activeRules2 = dbClient.activeRuleDao().selectByProfile(dbSession, child);
324 assertThat(activeRules2).hasSize(1);
325 assertThat(activeRules2.get(0).getKey().getRuleKey().rule()).isEqualTo(rule2.getRuleKey());
327 assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).hasSize(1);
331 public void fail_if_built_in_profile() {
332 QProfileDto child = db.qualityProfiles().insert(p -> p
333 .setLanguage(language.getKey())
334 .setIsBuiltIn(true));
336 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, child.getKee())).isEmpty();
337 assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).isEmpty();
339 TestRequest request = ws.newRequest()
341 .setParam(PARAM_LANGUAGE, child.getLanguage())
342 .setParam(PARAM_QUALITY_PROFILE, child.getName())
343 .setParam(PARAM_PARENT_QUALITY_PROFILE, "palap");
345 expectedException.expect(BadRequestException.class);
351 public void fail_if_missing_permission() {
352 userSession.logIn(db.users().insertUser());
354 QProfileDto child = createProfile();
356 TestRequest request = ws.newRequest()
358 .setParam(PARAM_LANGUAGE, child.getLanguage())
359 .setParam(PARAM_QUALITY_PROFILE, child.getName());
361 expectedException.expect(ForbiddenException.class);
362 expectedException.expectMessage("Insufficient privileges");
366 private QProfileDto createProfile() {
367 QProfileDto profile = QualityProfileTesting.newQualityProfileDto()
368 .setLanguage(language.getKey());
369 dbClient.qualityProfileDao().insert(dbSession, profile);
374 private RuleDefinitionDto createRule() {
375 RuleDefinitionDto rule = RuleTesting.newRule(RuleKey.of(ruleRepository, randomAlphanumeric(5)))
376 .setLanguage(language.getKey())
377 .setSeverity(Severity.BLOCKER)
378 .setStatus(RuleStatus.READY);
379 dbClient.ruleDao().insert(dbSession, rule);
384 private ActiveRuleDto createActiveRule(RuleDefinitionDto rule, QProfileDto profile) {
385 ActiveRuleDto activeRule = ActiveRuleDto.createFor(profile, rule)
386 .setSeverity(rule.getSeverityString());
387 dbClient.activeRuleDao().insert(dbSession, activeRule);