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.qualityprofile.QProfileTreeImpl;
52 import org.sonar.server.qualityprofile.RuleActivator;
53 import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
54 import org.sonar.server.rule.index.RuleIndex;
55 import org.sonar.server.rule.index.RuleIndexer;
56 import org.sonar.server.rule.index.RuleQuery;
57 import org.sonar.server.tester.UserSessionRule;
58 import org.sonar.server.util.TypeValidations;
59 import org.sonar.server.ws.TestRequest;
60 import org.sonar.server.ws.WsActionTester;
61 import org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters;
63 import static java.util.Arrays.asList;
64 import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
65 import static org.assertj.core.api.Assertions.assertThat;
66 import static org.assertj.core.api.Assertions.assertThatThrownBy;
67 import static org.sonar.db.permission.GlobalPermission.ADMINISTER_QUALITY_PROFILES;
68 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LANGUAGE;
69 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PARENT_QUALITY_PROFILE;
70 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_QUALITY_PROFILE;
72 public class ChangeParentActionTest {
75 public DbTester db = DbTester.create(System2.INSTANCE);
77 public EsTester es = EsTester.create();
79 public UserSessionRule userSession = UserSessionRule.standalone();
81 private DbClient dbClient;
82 private DbSession dbSession;
83 private RuleIndex ruleIndex;
84 private RuleIndexer ruleIndexer;
85 private ActiveRuleIndexer activeRuleIndexer;
86 private WsActionTester ws;
87 private Language language = LanguageTesting.newLanguage(randomAlphanumeric(20));
88 private String ruleRepository = randomAlphanumeric(5);
89 private QProfileTreeImpl qProfileTree;
93 dbClient = db.getDbClient();
94 dbSession = db.getSession();
95 EsClient esClient = es.client();
96 ruleIndex = new RuleIndex(esClient, System2.INSTANCE);
97 ruleIndexer = new RuleIndexer(esClient, dbClient);
98 activeRuleIndexer = new ActiveRuleIndexer(dbClient, esClient);
99 TypeValidations typeValidations = new TypeValidations(Collections.emptyList());
100 RuleActivator ruleActivator = new RuleActivator(System2.INSTANCE, dbClient, typeValidations, userSession);
101 qProfileTree = new QProfileTreeImpl(dbClient, ruleActivator, System2.INSTANCE, activeRuleIndexer);
102 ChangeParentAction underTest = new ChangeParentAction(
106 new QProfileWsSupport(
111 ws = new WsActionTester(underTest);
112 userSession.logIn().addPermission(ADMINISTER_QUALITY_PROFILES);
116 public void definition() {
117 WebService.Action definition = ws.getDef();
118 assertThat(definition.isPost()).isTrue();
119 assertThat(definition.params()).extracting(Param::key).containsExactlyInAnyOrder(
120 "qualityProfile", "language", "parentQualityProfile");
124 public void change_parent_with_no_parent_before() {
125 QProfileDto parent1 = createProfile();
126 QProfileDto child = createProfile();
128 RuleDefinitionDto rule1 = createRule();
129 createActiveRule(rule1, parent1);
130 ruleIndexer.commitAndIndex(dbSession, rule1.getUuid());
131 activeRuleIndexer.indexAll();
133 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, child.getKee())).isEmpty();
138 .setParam(PARAM_LANGUAGE, child.getLanguage())
139 .setParam(PARAM_QUALITY_PROFILE, child.getName())
140 .setParam(PARAM_PARENT_QUALITY_PROFILE, parent1.getName())
143 // Check rule 1 enabled
144 List<OrgActiveRuleDto> activeRules1 = dbClient.activeRuleDao().selectByProfile(dbSession, child);
145 assertThat(activeRules1).hasSize(1);
146 assertThat(activeRules1.get(0).getKey().getRuleKey().rule()).isEqualTo(rule1.getRuleKey());
148 assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).hasSize(1);
152 public void replace_existing_parent() {
153 QProfileDto parent1 = createProfile();
154 QProfileDto parent2 = createProfile();
155 QProfileDto child = createProfile();
157 RuleDefinitionDto rule1 = createRule();
158 RuleDefinitionDto rule2 = createRule();
159 createActiveRule(rule1, parent1);
160 createActiveRule(rule2, parent2);
161 ruleIndexer.commitAndIndex(dbSession, asList(rule1.getUuid(), rule2.getUuid()));
162 activeRuleIndexer.indexAll();
165 qProfileTree.setParentAndCommit(dbSession, child, parent1);
167 // Set parent 2 through WS
170 .setParam(PARAM_LANGUAGE, child.getLanguage())
171 .setParam(PARAM_QUALITY_PROFILE, child.getName())
172 .setParam(PARAM_PARENT_QUALITY_PROFILE, parent2.getName())
175 // Check rule 2 enabled
176 List<OrgActiveRuleDto> activeRules2 = dbClient.activeRuleDao().selectByProfile(dbSession, child);
177 assertThat(activeRules2).hasSize(1);
178 assertThat(activeRules2.get(0).getKey().getRuleKey().rule()).isEqualTo(rule2.getRuleKey());
180 assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).hasSize(1);
184 public void remove_parent() {
185 QProfileDto parent = createProfile();
186 QProfileDto child = createProfile();
188 RuleDefinitionDto rule1 = createRule();
189 createActiveRule(rule1, parent);
190 ruleIndexer.commitAndIndex(dbSession, rule1.getUuid());
191 activeRuleIndexer.indexAll();
194 qProfileTree.setParentAndCommit(dbSession, child, parent);
196 // Remove parent through WS
199 .setParam(PARAM_LANGUAGE, child.getLanguage())
200 .setParam(PARAM_QUALITY_PROFILE, child.getName())
203 // Check no rule enabled
204 assertThat(dbClient.activeRuleDao().selectByProfile(dbSession, child)).isEmpty();
206 assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).isEmpty();
210 public void change_parent_with_names() {
211 QProfileDto parent1 = createProfile();
212 QProfileDto parent2 = createProfile();
213 QProfileDto child = createProfile();
215 RuleDefinitionDto rule1 = createRule();
216 RuleDefinitionDto rule2 = createRule();
217 createActiveRule(rule1, parent1);
218 createActiveRule(rule2, parent2);
219 ruleIndexer.commitAndIndex(dbSession, rule1.getUuid());
220 activeRuleIndexer.indexAll();
222 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, child.getKee())).isEmpty();
227 .setParam(PARAM_LANGUAGE, child.getLanguage())
228 .setParam(PARAM_QUALITY_PROFILE, child.getName())
229 .setParam(PARAM_PARENT_QUALITY_PROFILE, parent1.getName())
232 // 1. check rule 1 enabled
233 List<OrgActiveRuleDto> activeRules1 = dbClient.activeRuleDao().selectByProfile(dbSession, child);
234 assertThat(activeRules1).hasSize(1);
235 assertThat(activeRules1.get(0).getKey().getRuleKey().rule()).isEqualTo(rule1.getRuleKey());
236 assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).hasSize(1);
241 .setParam(PARAM_LANGUAGE, child.getLanguage())
242 .setParam(PARAM_QUALITY_PROFILE, child.getName())
243 .setParam(QualityProfileWsParameters.PARAM_PARENT_QUALITY_PROFILE, parent2.getName())
246 // 2. check rule 2 enabled
247 List<OrgActiveRuleDto> activeRules2 = dbClient.activeRuleDao().selectByProfile(dbSession, child);
248 assertThat(activeRules2).hasSize(1);
249 assertThat(activeRules2.get(0).getKey().getRuleKey().rule()).isEqualTo(rule2.getRuleKey());
254 .setParam(PARAM_LANGUAGE, child.getLanguage())
255 .setParam(PARAM_QUALITY_PROFILE, child.getName())
256 .setParam(QualityProfileWsParameters.PARAM_PARENT_QUALITY_PROFILE, "")
259 // 3. check no rule enabled
260 List<OrgActiveRuleDto> activeRules = dbClient.activeRuleDao().selectByProfile(dbSession, child);
261 assertThat(activeRules).isEmpty();
262 assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).isEmpty();
266 public void remove_parent_with_empty_key() {
267 QProfileDto parent = createProfile();
268 QProfileDto child = createProfile();
270 RuleDefinitionDto rule1 = createRule();
271 createActiveRule(rule1, parent);
272 ruleIndexer.commitAndIndex(dbSession, rule1.getUuid());
273 activeRuleIndexer.indexAll();
275 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, child.getKee())).isEmpty();
278 qProfileTree.setParentAndCommit(dbSession, child, parent);
283 .setParam(PARAM_LANGUAGE, child.getLanguage())
284 .setParam(PARAM_QUALITY_PROFILE, child.getName())
285 .setParam(PARAM_PARENT_QUALITY_PROFILE, "")
288 // Check no rule enabled
289 assertThat(dbClient.activeRuleDao().selectByProfile(dbSession, child)).isEmpty();
290 assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).isEmpty();
294 public void as_qprofile_editor() {
295 QProfileDto parent1 = createProfile();
296 QProfileDto parent2 = createProfile();
297 QProfileDto child = createProfile();
299 RuleDefinitionDto rule1 = createRule();
300 RuleDefinitionDto rule2 = createRule();
301 createActiveRule(rule1, parent1);
302 createActiveRule(rule2, parent2);
303 ruleIndexer.commitAndIndex(dbSession, asList(rule1.getUuid(), rule2.getUuid()));
304 activeRuleIndexer.indexAll();
306 qProfileTree.setParentAndCommit(dbSession, child, parent1);
307 UserDto user = db.users().insertUser();
308 db.qualityProfiles().addUserPermission(child, user);
309 userSession.logIn(user);
313 .setParam(PARAM_LANGUAGE, child.getLanguage())
314 .setParam(PARAM_QUALITY_PROFILE, child.getName())
315 .setParam(PARAM_PARENT_QUALITY_PROFILE, parent2.getName())
318 List<OrgActiveRuleDto> activeRules2 = dbClient.activeRuleDao().selectByProfile(dbSession, child);
319 assertThat(activeRules2).hasSize(1);
320 assertThat(activeRules2.get(0).getKey().getRuleKey().rule()).isEqualTo(rule2.getRuleKey());
322 assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).hasSize(1);
326 public void fail_if_built_in_profile() {
327 QProfileDto child = db.qualityProfiles().insert(p -> p
328 .setLanguage(language.getKey())
329 .setIsBuiltIn(true));
331 assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, child.getKee())).isEmpty();
332 assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).isEmpty();
334 TestRequest request = ws.newRequest()
336 .setParam(PARAM_LANGUAGE, child.getLanguage())
337 .setParam(PARAM_QUALITY_PROFILE, child.getName())
338 .setParam(PARAM_PARENT_QUALITY_PROFILE, "palap");
340 assertThatThrownBy(request::execute)
341 .isInstanceOf(BadRequestException.class);
345 public void fail_if_missing_permission() {
346 userSession.logIn(db.users().insertUser());
348 QProfileDto child = createProfile();
350 TestRequest request = ws.newRequest()
352 .setParam(PARAM_LANGUAGE, child.getLanguage())
353 .setParam(PARAM_QUALITY_PROFILE, child.getName());
355 assertThatThrownBy(request::execute)
356 .isInstanceOf(ForbiddenException.class)
357 .hasMessage("Insufficient privileges");
360 private QProfileDto createProfile() {
361 QProfileDto profile = QualityProfileTesting.newQualityProfileDto()
362 .setLanguage(language.getKey());
363 dbClient.qualityProfileDao().insert(dbSession, profile);
368 private RuleDefinitionDto createRule() {
369 RuleDefinitionDto rule = RuleTesting.newRule(RuleKey.of(ruleRepository, randomAlphanumeric(5)))
370 .setLanguage(language.getKey())
371 .setSeverity(Severity.BLOCKER)
372 .setStatus(RuleStatus.READY);
373 dbClient.ruleDao().insert(dbSession, rule);
378 private ActiveRuleDto createActiveRule(RuleDefinitionDto rule, QProfileDto profile) {
379 ActiveRuleDto activeRule = ActiveRuleDto.createFor(profile, rule)
380 .setSeverity(rule.getSeverityString());
381 dbClient.activeRuleDao().insert(dbSession, activeRule);