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.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.sonar.api.resources.Language;
28 import org.sonar.api.resources.Languages;
29 import org.sonar.api.rule.RuleKey;
30 import org.sonar.api.rule.RuleStatus;
31 import org.sonar.api.rule.Severity;
32 import org.sonar.api.server.ws.WebService;
33 import org.sonar.api.server.ws.WebService.Param;
34 import org.sonar.api.utils.System2;
35 import org.sonar.db.DbClient;
36 import org.sonar.db.DbSession;
37 import org.sonar.db.DbTester;
38 import org.sonar.db.qualityprofile.ActiveRuleDto;
39 import org.sonar.db.qualityprofile.OrgActiveRuleDto;
40 import org.sonar.db.qualityprofile.QProfileDto;
41 import org.sonar.db.qualityprofile.QualityProfileTesting;
42 import org.sonar.db.rule.RuleDefinitionDto;
43 import org.sonar.db.rule.RuleTesting;
44 import org.sonar.db.user.UserDto;
45 import org.sonar.server.es.EsClient;
46 import org.sonar.server.es.EsTester;
47 import org.sonar.server.es.SearchOptions;
48 import org.sonar.server.exceptions.BadRequestException;
49 import org.sonar.server.exceptions.ForbiddenException;
50 import org.sonar.server.language.LanguageTesting;
51 import org.sonar.server.pushapi.qualityprofile.QualityProfileChangeEventService;
52 import org.sonar.server.qualityprofile.QProfileTreeImpl;
53 import org.sonar.server.qualityprofile.builtin.RuleActivator;
54 import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
55 import org.sonar.server.rule.index.RuleIndex;
56 import org.sonar.server.rule.index.RuleIndexer;
57 import org.sonar.server.rule.index.RuleQuery;
58 import org.sonar.server.tester.UserSessionRule;
59 import org.sonar.server.util.TypeValidations;
60 import org.sonar.server.ws.TestRequest;
61 import org.sonar.server.ws.WsActionTester;
62 import org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters;
64 import static java.util.Arrays.asList;
65 import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
66 import static org.assertj.core.api.Assertions.assertThat;
67 import static org.assertj.core.api.Assertions.assertThatThrownBy;
68 import static org.mockito.Mockito.mock;
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 private DbClient dbClient;
84 private DbSession dbSession;
85 private RuleIndex ruleIndex;
86 private RuleIndexer ruleIndexer;
87 private ActiveRuleIndexer activeRuleIndexer;
88 private WsActionTester ws;
89 private Language language = LanguageTesting.newLanguage(randomAlphanumeric(20));
90 private String ruleRepository = randomAlphanumeric(5);
91 private QProfileTreeImpl qProfileTree;
95 dbClient = db.getDbClient();
96 dbSession = db.getSession();
97 EsClient esClient = es.client();
98 ruleIndex = new RuleIndex(esClient, System2.INSTANCE);
99 ruleIndexer = new RuleIndexer(esClient, dbClient);
100 activeRuleIndexer = new ActiveRuleIndexer(dbClient, esClient);
101 TypeValidations typeValidations = new TypeValidations(Collections.emptyList());
102 RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, dbClient, typeValidations, userSession);
103 qProfileTree = new QProfileTreeImpl(dbClient, ruleActivator, System2.INSTANCE, activeRuleIndexer, mock(QualityProfileChangeEventService.class));
104 ChangeParentAction underTest = new ChangeParentAction(
108 new QProfileWsSupport(
113 ws = new WsActionTester(underTest);
114 userSession.logIn().addPermission(ADMINISTER_QUALITY_PROFILES);
118 public void definition() {
119 WebService.Action definition = ws.getDef();
120 assertThat(definition.isPost()).isTrue();
121 assertThat(definition.params()).extracting(Param::key).containsExactlyInAnyOrder(
122 "qualityProfile", "language", "parentQualityProfile");
126 public void change_parent_with_no_parent_before() {
127 QProfileDto parent1 = createProfile();
128 QProfileDto child = createProfile();
130 RuleDefinitionDto rule1 = createRule();
131 createActiveRule(rule1, parent1);
132 ruleIndexer.commitAndIndex(dbSession, rule1.getUuid());
133 activeRuleIndexer.indexAll();
135 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, child.getKee())).isEmpty();
140 .setParam(PARAM_LANGUAGE, child.getLanguage())
141 .setParam(PARAM_QUALITY_PROFILE, child.getName())
142 .setParam(PARAM_PARENT_QUALITY_PROFILE, parent1.getName())
145 // Check rule 1 enabled
146 List<OrgActiveRuleDto> activeRules1 = dbClient.activeRuleDao().selectByProfile(dbSession, child);
147 assertThat(activeRules1).hasSize(1);
148 assertThat(activeRules1.get(0).getKey().getRuleKey().rule()).isEqualTo(rule1.getRuleKey());
150 assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).hasSize(1);
154 public void replace_existing_parent() {
155 QProfileDto parent1 = createProfile();
156 QProfileDto parent2 = createProfile();
157 QProfileDto child = createProfile();
159 RuleDefinitionDto rule1 = createRule();
160 RuleDefinitionDto rule2 = createRule();
161 createActiveRule(rule1, parent1);
162 createActiveRule(rule2, parent2);
163 ruleIndexer.commitAndIndex(dbSession, asList(rule1.getUuid(), rule2.getUuid()));
164 activeRuleIndexer.indexAll();
167 qProfileTree.setParentAndCommit(dbSession, child, parent1);
169 // Set parent 2 through WS
172 .setParam(PARAM_LANGUAGE, child.getLanguage())
173 .setParam(PARAM_QUALITY_PROFILE, child.getName())
174 .setParam(PARAM_PARENT_QUALITY_PROFILE, parent2.getName())
177 // Check rule 2 enabled
178 List<OrgActiveRuleDto> activeRules2 = dbClient.activeRuleDao().selectByProfile(dbSession, child);
179 assertThat(activeRules2).hasSize(1);
180 assertThat(activeRules2.get(0).getKey().getRuleKey().rule()).isEqualTo(rule2.getRuleKey());
182 assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).hasSize(1);
186 public void remove_parent() {
187 QProfileDto parent = createProfile();
188 QProfileDto child = createProfile();
190 RuleDefinitionDto rule1 = createRule();
191 createActiveRule(rule1, parent);
192 ruleIndexer.commitAndIndex(dbSession, rule1.getUuid());
193 activeRuleIndexer.indexAll();
196 qProfileTree.setParentAndCommit(dbSession, child, parent);
198 // Remove parent through WS
201 .setParam(PARAM_LANGUAGE, child.getLanguage())
202 .setParam(PARAM_QUALITY_PROFILE, child.getName())
205 // Check no rule enabled
206 assertThat(dbClient.activeRuleDao().selectByProfile(dbSession, child)).isEmpty();
208 assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).isEmpty();
212 public void change_parent_with_names() {
213 QProfileDto parent1 = createProfile();
214 QProfileDto parent2 = createProfile();
215 QProfileDto child = createProfile();
217 RuleDefinitionDto rule1 = createRule();
218 RuleDefinitionDto rule2 = createRule();
219 createActiveRule(rule1, parent1);
220 createActiveRule(rule2, parent2);
221 ruleIndexer.commitAndIndex(dbSession, rule1.getUuid());
222 activeRuleIndexer.indexAll();
224 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, child.getKee())).isEmpty();
229 .setParam(PARAM_LANGUAGE, child.getLanguage())
230 .setParam(PARAM_QUALITY_PROFILE, child.getName())
231 .setParam(PARAM_PARENT_QUALITY_PROFILE, parent1.getName())
234 // 1. check rule 1 enabled
235 List<OrgActiveRuleDto> activeRules1 = dbClient.activeRuleDao().selectByProfile(dbSession, child);
236 assertThat(activeRules1).hasSize(1);
237 assertThat(activeRules1.get(0).getKey().getRuleKey().rule()).isEqualTo(rule1.getRuleKey());
238 assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).hasSize(1);
243 .setParam(PARAM_LANGUAGE, child.getLanguage())
244 .setParam(PARAM_QUALITY_PROFILE, child.getName())
245 .setParam(QualityProfileWsParameters.PARAM_PARENT_QUALITY_PROFILE, parent2.getName())
248 // 2. check rule 2 enabled
249 List<OrgActiveRuleDto> activeRules2 = dbClient.activeRuleDao().selectByProfile(dbSession, child);
250 assertThat(activeRules2).hasSize(1);
251 assertThat(activeRules2.get(0).getKey().getRuleKey().rule()).isEqualTo(rule2.getRuleKey());
256 .setParam(PARAM_LANGUAGE, child.getLanguage())
257 .setParam(PARAM_QUALITY_PROFILE, child.getName())
258 .setParam(QualityProfileWsParameters.PARAM_PARENT_QUALITY_PROFILE, "")
261 // 3. check no rule enabled
262 List<OrgActiveRuleDto> activeRules = dbClient.activeRuleDao().selectByProfile(dbSession, child);
263 assertThat(activeRules).isEmpty();
264 assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).isEmpty();
268 public void remove_parent_with_empty_key() {
269 QProfileDto parent = createProfile();
270 QProfileDto child = createProfile();
272 RuleDefinitionDto rule1 = createRule();
273 createActiveRule(rule1, parent);
274 ruleIndexer.commitAndIndex(dbSession, rule1.getUuid());
275 activeRuleIndexer.indexAll();
277 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, child.getKee())).isEmpty();
280 qProfileTree.setParentAndCommit(dbSession, child, parent);
285 .setParam(PARAM_LANGUAGE, child.getLanguage())
286 .setParam(PARAM_QUALITY_PROFILE, child.getName())
287 .setParam(PARAM_PARENT_QUALITY_PROFILE, "")
290 // Check no rule enabled
291 assertThat(dbClient.activeRuleDao().selectByProfile(dbSession, child)).isEmpty();
292 assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).isEmpty();
296 public void as_qprofile_editor() {
297 QProfileDto parent1 = createProfile();
298 QProfileDto parent2 = createProfile();
299 QProfileDto child = createProfile();
301 RuleDefinitionDto rule1 = createRule();
302 RuleDefinitionDto rule2 = createRule();
303 createActiveRule(rule1, parent1);
304 createActiveRule(rule2, parent2);
305 ruleIndexer.commitAndIndex(dbSession, asList(rule1.getUuid(), rule2.getUuid()));
306 activeRuleIndexer.indexAll();
308 qProfileTree.setParentAndCommit(dbSession, child, parent1);
309 UserDto user = db.users().insertUser();
310 db.qualityProfiles().addUserPermission(child, user);
311 userSession.logIn(user);
315 .setParam(PARAM_LANGUAGE, child.getLanguage())
316 .setParam(PARAM_QUALITY_PROFILE, child.getName())
317 .setParam(PARAM_PARENT_QUALITY_PROFILE, parent2.getName())
320 List<OrgActiveRuleDto> activeRules2 = dbClient.activeRuleDao().selectByProfile(dbSession, child);
321 assertThat(activeRules2).hasSize(1);
322 assertThat(activeRules2.get(0).getKey().getRuleKey().rule()).isEqualTo(rule2.getRuleKey());
324 assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).hasSize(1);
328 public void fail_if_built_in_profile() {
329 QProfileDto child = db.qualityProfiles().insert(p -> p
330 .setLanguage(language.getKey())
331 .setIsBuiltIn(true));
333 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, child.getKee())).isEmpty();
334 assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).isEmpty();
336 TestRequest request = ws.newRequest()
338 .setParam(PARAM_LANGUAGE, child.getLanguage())
339 .setParam(PARAM_QUALITY_PROFILE, child.getName())
340 .setParam(PARAM_PARENT_QUALITY_PROFILE, "palap");
342 assertThatThrownBy(request::execute)
343 .isInstanceOf(BadRequestException.class);
347 public void fail_if_missing_permission() {
348 userSession.logIn(db.users().insertUser());
350 QProfileDto child = createProfile();
352 TestRequest request = ws.newRequest()
354 .setParam(PARAM_LANGUAGE, child.getLanguage())
355 .setParam(PARAM_QUALITY_PROFILE, child.getName());
357 assertThatThrownBy(request::execute)
358 .isInstanceOf(ForbiddenException.class)
359 .hasMessage("Insufficient privileges");
362 private QProfileDto createProfile() {
363 QProfileDto profile = QualityProfileTesting.newQualityProfileDto()
364 .setLanguage(language.getKey());
365 dbClient.qualityProfileDao().insert(dbSession, profile);
370 private RuleDefinitionDto createRule() {
371 RuleDefinitionDto rule = RuleTesting.newRule(RuleKey.of(ruleRepository, randomAlphanumeric(5)))
372 .setLanguage(language.getKey())
373 .setSeverity(Severity.BLOCKER)
374 .setStatus(RuleStatus.READY);
375 dbClient.ruleDao().insert(dbSession, rule);
380 private ActiveRuleDto createActiveRule(RuleDefinitionDto rule, QProfileDto profile) {
381 ActiveRuleDto activeRule = ActiveRuleDto.createFor(profile, rule)
382 .setSeverity(rule.getSeverityString());
383 dbClient.activeRuleDao().insert(dbSession, activeRule);