]> source.dussan.org Git - sonarqube.git/blob
258571a4a4ad9d9ed807f4c7b4f65f644c2715ae
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2020 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.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;
64
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;
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   @Rule
83   public ExpectedException expectedException = ExpectedException.none();
84
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;
94
95   @Before
96   public void setUp() {
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(
107       dbClient,
108       qProfileTree,
109       new Languages(),
110       new QProfileWsSupport(
111         dbClient,
112         userSession,
113         TestDefaultOrganizationProvider.from(db)),
114       userSession);
115
116     ws = new WsActionTester(underTest);
117     userSession.logIn().addPermission(ADMINISTER_QUALITY_PROFILES);
118   }
119
120   @Test
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");
126   }
127
128   @Test
129   public void change_parent_with_no_parent_before() {
130     QProfileDto parent1 = createProfile();
131     QProfileDto child = createProfile();
132
133     RuleDefinitionDto rule1 = createRule();
134     createActiveRule(rule1, parent1);
135     ruleIndexer.commitAndIndex(dbSession, rule1.getUuid());
136     activeRuleIndexer.indexOnStartup(emptySet());
137
138     assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, child.getKee())).isEmpty();
139
140     // Set parent
141     ws.newRequest()
142       .setMethod("POST")
143       .setParam(PARAM_LANGUAGE, child.getLanguage())
144       .setParam(PARAM_QUALITY_PROFILE, child.getName())
145       .setParam(PARAM_PARENT_QUALITY_PROFILE, parent1.getName())
146       .execute();
147
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());
152
153     assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).hasSize(1);
154   }
155
156   @Test
157   public void replace_existing_parent() {
158     QProfileDto parent1 = createProfile();
159     QProfileDto parent2 = createProfile();
160     QProfileDto child = createProfile();
161
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());
168
169     // Set parent 1
170     qProfileTree.setParentAndCommit(dbSession, child, parent1);
171
172     // Set parent 2 through WS
173     ws.newRequest()
174       .setMethod("POST")
175       .setParam(PARAM_LANGUAGE, child.getLanguage())
176       .setParam(PARAM_QUALITY_PROFILE, child.getName())
177       .setParam(PARAM_PARENT_QUALITY_PROFILE, parent2.getName())
178       .execute();
179
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());
184
185     assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).hasSize(1);
186   }
187
188   @Test
189   public void remove_parent() {
190     QProfileDto parent = createProfile();
191     QProfileDto child = createProfile();
192
193     RuleDefinitionDto rule1 = createRule();
194     createActiveRule(rule1, parent);
195     ruleIndexer.commitAndIndex(dbSession, rule1.getUuid());
196     activeRuleIndexer.indexOnStartup(emptySet());
197
198     // Set parent
199     qProfileTree.setParentAndCommit(dbSession, child, parent);
200
201     // Remove parent through WS
202     ws.newRequest()
203       .setMethod("POST")
204       .setParam(PARAM_LANGUAGE, child.getLanguage())
205       .setParam(PARAM_QUALITY_PROFILE, child.getName())
206       .execute();
207
208     // Check no rule enabled
209     assertThat(dbClient.activeRuleDao().selectByProfile(dbSession, child)).isEmpty();
210
211     assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).isEmpty();
212   }
213
214   @Test
215   public void change_parent_with_names() {
216     QProfileDto parent1 = createProfile();
217     QProfileDto parent2 = createProfile();
218     QProfileDto child = createProfile();
219
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());
226
227     assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, child.getKee())).isEmpty();
228
229     // 1. Set parent 1
230     ws.newRequest()
231       .setMethod("POST")
232       .setParam(PARAM_LANGUAGE, child.getLanguage())
233       .setParam(PARAM_QUALITY_PROFILE, child.getName())
234       .setParam(PARAM_PARENT_QUALITY_PROFILE, parent1.getName())
235       .execute();
236
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);
242
243     // 2. Set parent 2
244     ws.newRequest()
245       .setMethod("POST")
246       .setParam(PARAM_LANGUAGE, child.getLanguage())
247       .setParam(PARAM_QUALITY_PROFILE, child.getName())
248       .setParam(QualityProfileWsParameters.PARAM_PARENT_QUALITY_PROFILE, parent2.getName())
249       .execute();
250
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());
255
256     // 3. Remove parent
257     ws.newRequest()
258       .setMethod("POST")
259       .setParam(PARAM_LANGUAGE, child.getLanguage())
260       .setParam(PARAM_QUALITY_PROFILE, child.getName())
261       .setParam(QualityProfileWsParameters.PARAM_PARENT_QUALITY_PROFILE, "")
262       .execute();
263
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();
268   }
269
270   @Test
271   public void remove_parent_with_empty_key() {
272     QProfileDto parent = createProfile();
273     QProfileDto child = createProfile();
274
275     RuleDefinitionDto rule1 = createRule();
276     createActiveRule(rule1, parent);
277     ruleIndexer.commitAndIndex(dbSession, rule1.getUuid());
278     activeRuleIndexer.indexOnStartup(emptySet());
279
280     assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, child.getKee())).isEmpty();
281
282     // Set parent
283     qProfileTree.setParentAndCommit(dbSession, child, parent);
284
285     // Remove parent
286     ws.newRequest()
287       .setMethod("POST")
288       .setParam(PARAM_LANGUAGE, child.getLanguage())
289       .setParam(PARAM_QUALITY_PROFILE, child.getName())
290       .setParam(PARAM_PARENT_QUALITY_PROFILE, "")
291       .execute();
292
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();
296   }
297
298   @Test
299   public void as_qprofile_editor() {
300     QProfileDto parent1 = createProfile();
301     QProfileDto parent2 = createProfile();
302     QProfileDto child = createProfile();
303
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());
310     // Set parent 1
311     qProfileTree.setParentAndCommit(dbSession, child, parent1);
312     UserDto user = db.users().insertUser();
313     db.qualityProfiles().addUserPermission(child, user);
314     userSession.logIn(user);
315
316     ws.newRequest()
317       .setMethod("POST")
318       .setParam(PARAM_LANGUAGE, child.getLanguage())
319       .setParam(PARAM_QUALITY_PROFILE, child.getName())
320       .setParam(PARAM_PARENT_QUALITY_PROFILE, parent2.getName())
321       .execute();
322
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());
326
327     assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).hasSize(1);
328   }
329
330   @Test
331   public void fail_if_built_in_profile() {
332     QProfileDto child = db.qualityProfiles().insert(p -> p
333       .setLanguage(language.getKey())
334       .setIsBuiltIn(true));
335
336     assertThat(dbClient.activeRuleDao().selectByProfileUuid(dbSession, child.getKee())).isEmpty();
337     assertThat(ruleIndex.search(new RuleQuery().setActivation(true).setQProfile(child), new SearchOptions()).getUuids()).isEmpty();
338
339     TestRequest request = ws.newRequest()
340       .setMethod("POST")
341       .setParam(PARAM_LANGUAGE, child.getLanguage())
342       .setParam(PARAM_QUALITY_PROFILE, child.getName())
343       .setParam(PARAM_PARENT_QUALITY_PROFILE, "palap");
344
345     expectedException.expect(BadRequestException.class);
346
347     request.execute();
348   }
349
350   @Test
351   public void fail_if_missing_permission() {
352     userSession.logIn(db.users().insertUser());
353
354     QProfileDto child = createProfile();
355
356     TestRequest request = ws.newRequest()
357       .setMethod("POST")
358       .setParam(PARAM_LANGUAGE, child.getLanguage())
359       .setParam(PARAM_QUALITY_PROFILE, child.getName());
360
361     expectedException.expect(ForbiddenException.class);
362     expectedException.expectMessage("Insufficient privileges");
363     request.execute();
364   }
365
366   private QProfileDto createProfile() {
367     QProfileDto profile = QualityProfileTesting.newQualityProfileDto()
368       .setLanguage(language.getKey());
369     dbClient.qualityProfileDao().insert(dbSession, profile);
370     dbSession.commit();
371     return profile;
372   }
373
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);
380     dbSession.commit();
381     return rule;
382   }
383
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);
388     dbSession.commit();
389     return activeRule;
390   }
391 }