]> source.dussan.org Git - sonarqube.git/blob
e09e88d9179368c80fe34d6d8ab555a888cd3418
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2022 SonarSource SA
4  * mailto:info AT sonarsource DOT com
5  *
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.
10  *
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.
15  *
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.
19  */
20 package org.sonar.server.qualityprofile.ws;
21
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;
63
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;
73
74 public class ChangeParentActionTest {
75
76   @Rule
77   public DbTester db = DbTester.create(System2.INSTANCE);
78   @Rule
79   public EsTester es = EsTester.create();
80   @Rule
81   public UserSessionRule userSession = UserSessionRule.standalone();
82
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;
92
93   @Before
94   public void setUp() {
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(
105       dbClient,
106       qProfileTree,
107       new Languages(),
108       new QProfileWsSupport(
109         dbClient,
110         userSession),
111       userSession);
112
113     ws = new WsActionTester(underTest);
114     userSession.logIn().addPermission(ADMINISTER_QUALITY_PROFILES);
115   }
116
117   @Test
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");
123   }
124
125   @Test
126   public void change_parent_with_no_parent_before() {
127     QProfileDto parent1 = createProfile();
128     QProfileDto child = createProfile();
129
130     RuleDefinitionDto rule1 = createRule();
131     createActiveRule(rule1, parent1);
132     ruleIndexer.commitAndIndex(dbSession, rule1.getUuid());
133     activeRuleIndexer.indexAll();
134
135     assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, child.getKee())).isEmpty();
136
137     // Set parent
138     ws.newRequest()
139       .setMethod("POST")
140       .setParam(PARAM_LANGUAGE, child.getLanguage())
141       .setParam(PARAM_QUALITY_PROFILE, child.getName())
142       .setParam(PARAM_PARENT_QUALITY_PROFILE, parent1.getName())
143       .execute();
144
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());
149
150     assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).hasSize(1);
151   }
152
153   @Test
154   public void replace_existing_parent() {
155     QProfileDto parent1 = createProfile();
156     QProfileDto parent2 = createProfile();
157     QProfileDto child = createProfile();
158
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();
165
166     // Set parent 1
167     qProfileTree.setParentAndCommit(dbSession, child, parent1);
168
169     // Set parent 2 through WS
170     ws.newRequest()
171       .setMethod("POST")
172       .setParam(PARAM_LANGUAGE, child.getLanguage())
173       .setParam(PARAM_QUALITY_PROFILE, child.getName())
174       .setParam(PARAM_PARENT_QUALITY_PROFILE, parent2.getName())
175       .execute();
176
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());
181
182     assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).hasSize(1);
183   }
184
185   @Test
186   public void remove_parent() {
187     QProfileDto parent = createProfile();
188     QProfileDto child = createProfile();
189
190     RuleDefinitionDto rule1 = createRule();
191     createActiveRule(rule1, parent);
192     ruleIndexer.commitAndIndex(dbSession, rule1.getUuid());
193     activeRuleIndexer.indexAll();
194
195     // Set parent
196     qProfileTree.setParentAndCommit(dbSession, child, parent);
197
198     // Remove parent through WS
199     ws.newRequest()
200       .setMethod("POST")
201       .setParam(PARAM_LANGUAGE, child.getLanguage())
202       .setParam(PARAM_QUALITY_PROFILE, child.getName())
203       .execute();
204
205     // Check no rule enabled
206     assertThat(dbClient.activeRuleDao().selectByProfile(dbSession, child)).isEmpty();
207
208     assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).isEmpty();
209   }
210
211   @Test
212   public void change_parent_with_names() {
213     QProfileDto parent1 = createProfile();
214     QProfileDto parent2 = createProfile();
215     QProfileDto child = createProfile();
216
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();
223
224     assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, child.getKee())).isEmpty();
225
226     // 1. Set parent 1
227     ws.newRequest()
228       .setMethod("POST")
229       .setParam(PARAM_LANGUAGE, child.getLanguage())
230       .setParam(PARAM_QUALITY_PROFILE, child.getName())
231       .setParam(PARAM_PARENT_QUALITY_PROFILE, parent1.getName())
232       .execute();
233
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);
239
240     // 2. Set parent 2
241     ws.newRequest()
242       .setMethod("POST")
243       .setParam(PARAM_LANGUAGE, child.getLanguage())
244       .setParam(PARAM_QUALITY_PROFILE, child.getName())
245       .setParam(QualityProfileWsParameters.PARAM_PARENT_QUALITY_PROFILE, parent2.getName())
246       .execute();
247
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());
252
253     // 3. Remove parent
254     ws.newRequest()
255       .setMethod("POST")
256       .setParam(PARAM_LANGUAGE, child.getLanguage())
257       .setParam(PARAM_QUALITY_PROFILE, child.getName())
258       .setParam(QualityProfileWsParameters.PARAM_PARENT_QUALITY_PROFILE, "")
259       .execute();
260
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();
265   }
266
267   @Test
268   public void remove_parent_with_empty_key() {
269     QProfileDto parent = createProfile();
270     QProfileDto child = createProfile();
271
272     RuleDefinitionDto rule1 = createRule();
273     createActiveRule(rule1, parent);
274     ruleIndexer.commitAndIndex(dbSession, rule1.getUuid());
275     activeRuleIndexer.indexAll();
276
277     assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, child.getKee())).isEmpty();
278
279     // Set parent
280     qProfileTree.setParentAndCommit(dbSession, child, parent);
281
282     // Remove parent
283     ws.newRequest()
284       .setMethod("POST")
285       .setParam(PARAM_LANGUAGE, child.getLanguage())
286       .setParam(PARAM_QUALITY_PROFILE, child.getName())
287       .setParam(PARAM_PARENT_QUALITY_PROFILE, "")
288       .execute();
289
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();
293   }
294
295   @Test
296   public void as_qprofile_editor() {
297     QProfileDto parent1 = createProfile();
298     QProfileDto parent2 = createProfile();
299     QProfileDto child = createProfile();
300
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();
307     // Set parent 1
308     qProfileTree.setParentAndCommit(dbSession, child, parent1);
309     UserDto user = db.users().insertUser();
310     db.qualityProfiles().addUserPermission(child, user);
311     userSession.logIn(user);
312
313     ws.newRequest()
314       .setMethod("POST")
315       .setParam(PARAM_LANGUAGE, child.getLanguage())
316       .setParam(PARAM_QUALITY_PROFILE, child.getName())
317       .setParam(PARAM_PARENT_QUALITY_PROFILE, parent2.getName())
318       .execute();
319
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());
323
324     assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).hasSize(1);
325   }
326
327   @Test
328   public void fail_if_built_in_profile() {
329     QProfileDto child = db.qualityProfiles().insert(p -> p
330       .setLanguage(language.getKey())
331       .setIsBuiltIn(true));
332
333     assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, child.getKee())).isEmpty();
334     assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).isEmpty();
335
336     TestRequest request = ws.newRequest()
337       .setMethod("POST")
338       .setParam(PARAM_LANGUAGE, child.getLanguage())
339       .setParam(PARAM_QUALITY_PROFILE, child.getName())
340       .setParam(PARAM_PARENT_QUALITY_PROFILE, "palap");
341
342     assertThatThrownBy(request::execute)
343       .isInstanceOf(BadRequestException.class);
344   }
345
346   @Test
347   public void fail_if_missing_permission() {
348     userSession.logIn(db.users().insertUser());
349
350     QProfileDto child = createProfile();
351
352     TestRequest request = ws.newRequest()
353       .setMethod("POST")
354       .setParam(PARAM_LANGUAGE, child.getLanguage())
355       .setParam(PARAM_QUALITY_PROFILE, child.getName());
356
357     assertThatThrownBy(request::execute)
358       .isInstanceOf(ForbiddenException.class)
359       .hasMessage("Insufficient privileges");
360   }
361
362   private QProfileDto createProfile() {
363     QProfileDto profile = QualityProfileTesting.newQualityProfileDto()
364       .setLanguage(language.getKey());
365     dbClient.qualityProfileDao().insert(dbSession, profile);
366     dbSession.commit();
367     return profile;
368   }
369
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);
376     dbSession.commit();
377     return rule;
378   }
379
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);
384     dbSession.commit();
385     return activeRule;
386   }
387 }