]> source.dussan.org Git - sonarqube.git/blob
6c2cc25845f99bf00d1ed5cbec6ea9c2ca07d176
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2019 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.List;
23 import org.junit.Rule;
24 import org.junit.Test;
25 import org.junit.rules.ExpectedException;
26 import org.sonar.api.resources.Language;
27 import org.sonar.api.resources.Languages;
28 import org.sonar.api.server.ws.Change;
29 import org.sonar.api.server.ws.WebService;
30 import org.sonar.api.utils.DateUtils;
31 import org.sonar.api.utils.System2;
32 import org.sonar.core.util.stream.MoreCollectors;
33 import org.sonar.db.DbClient;
34 import org.sonar.db.DbTester;
35 import org.sonar.db.component.ComponentDto;
36 import org.sonar.db.organization.OrganizationDto;
37 import org.sonar.db.permission.OrganizationPermission;
38 import org.sonar.db.qualityprofile.QProfileDto;
39 import org.sonar.db.qualityprofile.QualityProfileDbTester;
40 import org.sonar.db.rule.RuleDefinitionDto;
41 import org.sonar.db.user.GroupDto;
42 import org.sonar.db.user.UserDto;
43 import org.sonar.server.component.ComponentFinder;
44 import org.sonar.server.exceptions.ForbiddenException;
45 import org.sonar.server.exceptions.NotFoundException;
46 import org.sonar.server.organization.DefaultOrganizationProvider;
47 import org.sonar.server.organization.TestDefaultOrganizationProvider;
48 import org.sonar.server.tester.UserSessionRule;
49 import org.sonar.server.ws.TestRequest;
50 import org.sonar.server.ws.WsActionTester;
51 import org.sonarqube.ws.MediaTypes;
52 import org.sonarqube.ws.Qualityprofiles.SearchWsResponse;
53 import org.sonarqube.ws.Qualityprofiles.SearchWsResponse.QualityProfile;
54
55 import static java.lang.String.format;
56 import static java.util.stream.IntStream.range;
57 import static org.assertj.core.api.Assertions.assertThat;
58 import static org.assertj.core.api.Assertions.tuple;
59 import static org.sonar.api.rule.RuleStatus.DEPRECATED;
60 import static org.sonar.api.utils.DateUtils.parseDateTime;
61 import static org.sonar.db.component.ComponentTesting.newModuleDto;
62 import static org.sonar.db.organization.OrganizationDto.Subscription.FREE;
63 import static org.sonar.db.organization.OrganizationDto.Subscription.PAID;
64 import static org.sonar.db.qualityprofile.QualityProfileTesting.newQualityProfileDto;
65 import static org.sonar.server.language.LanguageTesting.newLanguage;
66 import static org.sonar.test.JsonAssert.assertJson;
67 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_DEFAULTS;
68 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LANGUAGE;
69 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_ORGANIZATION;
70 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_PROJECT_KEY;
71 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_QUALITY_PROFILE;
72
73 public class SearchActionTest {
74
75   private static Language XOO1 = newLanguage("xoo1");
76   private static Language XOO2 = newLanguage("xoo2");
77   private static Languages LANGUAGES = new Languages(XOO1, XOO2);
78
79   @Rule
80   public DbTester db = DbTester.create(System2.INSTANCE);
81   @Rule
82   public UserSessionRule userSession = UserSessionRule.standalone();
83   @Rule
84   public ExpectedException expectedException = ExpectedException.none();
85   private QualityProfileDbTester qualityProfileDb = db.qualityProfiles();
86   private DbClient dbClient = db.getDbClient();
87   private DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db);
88   private QProfileWsSupport qProfileWsSupport = new QProfileWsSupport(dbClient, userSession, defaultOrganizationProvider);
89
90   private SearchAction underTest = new SearchAction(userSession, LANGUAGES, dbClient, qProfileWsSupport, new ComponentFinder(dbClient, null));
91   private WsActionTester ws = new WsActionTester(underTest);
92
93   @Test
94   public void no_profile() {
95     SearchWsResponse result = call(ws.newRequest());
96
97     assertThat(result.getProfilesList()).isEmpty();
98   }
99
100   @Test
101   public void empty_when_no_language_installed() {
102     WsActionTester ws = new WsActionTester(new SearchAction(userSession, new Languages(), dbClient, qProfileWsSupport, new ComponentFinder(dbClient, null)));
103     db.qualityProfiles().insert(db.getDefaultOrganization());
104
105     SearchWsResponse result = call(ws.newRequest());
106
107     assertThat(result.getProfilesList()).isEmpty();
108   }
109
110   @Test
111   public void default_organization() {
112     OrganizationDto defaultOrganization = db.getDefaultOrganization();
113     OrganizationDto anotherOrganization = db.organizations().insert();
114     QProfileDto profile1OnDefaultOrg = db.qualityProfiles().insert(defaultOrganization, p -> p.setLanguage(XOO1.getKey()));
115     QProfileDto profile2OnDefaultOrg = db.qualityProfiles().insert(defaultOrganization, p -> p.setLanguage(XOO2.getKey()));
116     QProfileDto profileOnAnotherOrg = db.qualityProfiles().insert(anotherOrganization, p -> p.setLanguage(XOO1.getKey()));
117
118     SearchWsResponse result = call(ws.newRequest());
119
120     assertThat(result.getProfilesList()).extracting(QualityProfile::getKey)
121       .containsExactlyInAnyOrder(profile1OnDefaultOrg.getKee(), profile2OnDefaultOrg.getKee())
122       .doesNotContain(profileOnAnotherOrg.getKee());
123   }
124
125   @Test
126   public void specific_organization() {
127     OrganizationDto defaultOrganization = db.getDefaultOrganization();
128     OrganizationDto specificOrganization = db.organizations().insert();
129     QProfileDto profile1OnSpecificOrg = db.qualityProfiles().insert(specificOrganization, p -> p.setLanguage(XOO1.getKey()));
130     QProfileDto profile2OnSpecificOrg = db.qualityProfiles().insert(specificOrganization, p -> p.setLanguage(XOO2.getKey()));
131     QProfileDto profileOnDefaultOrg = db.qualityProfiles().insert(defaultOrganization, p -> p.setLanguage(XOO1.getKey()));
132
133     SearchWsResponse result = call(ws.newRequest().setParam(PARAM_ORGANIZATION, specificOrganization.getKey()));
134
135     assertThat(result.getProfilesList()).extracting(QualityProfile::getKey)
136       .containsExactlyInAnyOrder(profile1OnSpecificOrg.getKee(), profile2OnSpecificOrg.getKee())
137       .doesNotContain(profileOnDefaultOrg.getKee());
138   }
139
140   @Test
141   public void filter_on_default_profile() {
142     QProfileDto defaultProfile1 = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(XOO1.getKey()));
143     QProfileDto defaultProfile2 = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(XOO2.getKey()));
144     QProfileDto nonDefaultProfile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(XOO1.getKey()));
145     db.qualityProfiles().setAsDefault(defaultProfile1, defaultProfile2);
146
147     SearchWsResponse result = call(ws.newRequest().setParam(PARAM_DEFAULTS, "true"));
148
149     assertThat(result.getProfilesList()).extracting(QualityProfile::getKey)
150       .containsExactlyInAnyOrder(defaultProfile1.getKee(), defaultProfile2.getKee())
151       .doesNotContain(nonDefaultProfile.getKee());
152   }
153
154   @Test
155   public void does_not_filter_when_defaults_is_false() {
156     QProfileDto defaultProfile1 = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(XOO1.getKey()));
157     QProfileDto defaultProfile2 = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(XOO2.getKey()));
158     QProfileDto nonDefaultProfile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(XOO1.getKey()));
159     db.qualityProfiles().setAsDefault(defaultProfile1, defaultProfile2);
160
161     SearchWsResponse result = call(ws.newRequest().setParam(PARAM_DEFAULTS, "false"));
162
163     assertThat(result.getProfilesList()).extracting(QualityProfile::getKey)
164       .containsExactlyInAnyOrder(defaultProfile1.getKee(), defaultProfile2.getKee(), nonDefaultProfile.getKee());
165   }
166
167   @Test
168   public void filter_on_language() {
169     QProfileDto profile1OnXoo1 = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(XOO1.getKey()));
170     QProfileDto profile2OnXoo1 = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(XOO1.getKey()));
171     QProfileDto profileOnXoo2 = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(XOO2.getKey()));
172
173     SearchWsResponse result = call(ws.newRequest().setParam(PARAM_LANGUAGE, XOO1.getKey()));
174
175     assertThat(result.getProfilesList()).extracting(QualityProfile::getKey)
176       .containsExactlyInAnyOrder(profile1OnXoo1.getKee(), profile2OnXoo1.getKee())
177       .doesNotContain(profileOnXoo2.getKee());
178   }
179
180   @Test
181   public void ignore_profiles_on_unknown_language() {
182     QProfileDto profile1OnXoo1 = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(XOO1.getKey()));
183     QProfileDto profile2OnXoo1 = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(XOO2.getKey()));
184     QProfileDto profileOnUnknownLanguage = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage("unknown"));
185
186     SearchWsResponse result = call(ws.newRequest());
187
188     assertThat(result.getProfilesList()).extracting(QualityProfile::getKey)
189       .containsExactlyInAnyOrder(profile1OnXoo1.getKee(), profile2OnXoo1.getKee())
190       .doesNotContain(profileOnUnknownLanguage.getKee());
191   }
192
193   @Test
194   public void filter_on_profile_name() {
195     QProfileDto sonarWayOnXoo1 = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setName("Sonar way").setLanguage(XOO1.getKey()));
196     QProfileDto sonarWayOnXoo2 = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setName("Sonar way").setLanguage(XOO1.getKey()));
197     QProfileDto sonarWayInCamelCase = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setName("Sonar Way").setLanguage(XOO2.getKey()));
198     QProfileDto anotherProfile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setName("Another").setLanguage(XOO2.getKey()));
199
200     SearchWsResponse result = call(ws.newRequest().setParam(PARAM_QUALITY_PROFILE, "Sonar way"));
201
202     assertThat(result.getProfilesList()).extracting(QualityProfile::getKey)
203       .containsExactlyInAnyOrder(sonarWayOnXoo1.getKee(), sonarWayOnXoo2.getKee())
204       .doesNotContain(anotherProfile.getKee(), sonarWayInCamelCase.getKee());
205   }
206
207   @Test
208   public void filter_on_defaults_and_name() {
209     QProfileDto sonarWayOnXoo1 = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setName("Sonar way").setLanguage(XOO1.getKey()));
210     QProfileDto sonarWayOnXoo2 = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setName("Sonar way").setLanguage(XOO2.getKey()));
211     QProfileDto anotherProfile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setName("Another").setLanguage(XOO2.getKey()));
212     db.qualityProfiles().setAsDefault(sonarWayOnXoo1, anotherProfile);
213
214     SearchWsResponse result = call(ws.newRequest()
215       .setParam(PARAM_DEFAULTS, "true")
216       .setParam(PARAM_QUALITY_PROFILE, "Sonar way"));
217
218     assertThat(result.getProfilesList()).extracting(QualityProfile::getKey)
219       .containsExactlyInAnyOrder(sonarWayOnXoo1.getKee())
220       .doesNotContain(sonarWayOnXoo2.getKee(), anotherProfile.getKee());
221   }
222
223   @Test
224   public void filter_on_project_key() {
225     ComponentDto project = db.components().insertPrivateProject();
226     QProfileDto profileOnXoo1 = db.qualityProfiles().insert(db.getDefaultOrganization(), q -> q.setLanguage(XOO1.getKey()));
227     QProfileDto defaultProfileOnXoo1 = db.qualityProfiles().insert(db.getDefaultOrganization(), q -> q.setLanguage(XOO1.getKey()));
228     QProfileDto defaultProfileOnXoo2 = db.qualityProfiles().insert(db.getDefaultOrganization(), q -> q.setLanguage(XOO2.getKey()));
229     db.qualityProfiles().associateWithProject(project, profileOnXoo1);
230     db.qualityProfiles().setAsDefault(defaultProfileOnXoo1, defaultProfileOnXoo2);
231
232     SearchWsResponse result = call(ws.newRequest().setParam(PARAM_PROJECT_KEY, project.getDbKey()));
233
234     assertThat(result.getProfilesList())
235       .extracting(QualityProfile::getKey)
236       .containsExactlyInAnyOrder(profileOnXoo1.getKee(), defaultProfileOnXoo2.getKee())
237       .doesNotContain(defaultProfileOnXoo1.getKee());
238   }
239
240   @Test
241   public void filter_on_module_key() {
242     ComponentDto project = db.components().insertPrivateProject();
243     ComponentDto module = db.components().insertComponent(newModuleDto(project));
244     QProfileDto profileOnXoo1 = db.qualityProfiles().insert(db.getDefaultOrganization(), q -> q.setLanguage(XOO1.getKey()));
245     QProfileDto defaultProfileOnXoo1 = db.qualityProfiles().insert(db.getDefaultOrganization(), q -> q.setLanguage(XOO1.getKey()));
246     QProfileDto defaultProfileOnXoo2 = db.qualityProfiles().insert(db.getDefaultOrganization(), q -> q.setLanguage(XOO2.getKey()));
247     db.qualityProfiles().associateWithProject(project, profileOnXoo1);
248     db.qualityProfiles().setAsDefault(defaultProfileOnXoo1, defaultProfileOnXoo2);
249
250     SearchWsResponse result = call(ws.newRequest().setParam(PARAM_PROJECT_KEY, module.getDbKey()));
251
252     assertThat(result.getProfilesList())
253       .extracting(QualityProfile::getKey)
254       .containsExactlyInAnyOrder(profileOnXoo1.getKee(), defaultProfileOnXoo2.getKee())
255       .doesNotContain(defaultProfileOnXoo1.getKee());
256   }
257
258   @Test
259   public void filter_on_project_key_and_default() {
260     ComponentDto project = db.components().insertPrivateProject();
261     QProfileDto profileOnXoo1 = db.qualityProfiles().insert(db.getDefaultOrganization(), q -> q.setLanguage(XOO1.getKey()));
262     QProfileDto defaultProfileOnXoo1 = db.qualityProfiles().insert(db.getDefaultOrganization(), q -> q.setLanguage(XOO1.getKey()));
263     QProfileDto defaultProfileOnXoo2 = db.qualityProfiles().insert(db.getDefaultOrganization(), q -> q.setLanguage(XOO2.getKey()));
264     db.qualityProfiles().associateWithProject(project, profileOnXoo1);
265     db.qualityProfiles().setAsDefault(defaultProfileOnXoo1, defaultProfileOnXoo2);
266
267     SearchWsResponse result = call(ws.newRequest()
268       .setParam(PARAM_PROJECT_KEY, project.getDbKey())
269       .setParam(PARAM_DEFAULTS, "true"));
270
271     assertThat(result.getProfilesList())
272       .extracting(QualityProfile::getKey)
273       .containsExactlyInAnyOrder(defaultProfileOnXoo2.getKee())
274       .doesNotContain(defaultProfileOnXoo1.getKee(), profileOnXoo1.getKee());
275   }
276
277   @Test
278   public void empty_when_filtering_on_project_and_no_language_installed() {
279     WsActionTester ws = new WsActionTester(new SearchAction(userSession, new Languages(), dbClient, qProfileWsSupport, new ComponentFinder(dbClient, null)));
280     db.qualityProfiles().insert(db.getDefaultOrganization());
281     ComponentDto project = db.components().insertPrivateProject();
282     QProfileDto profileOnXoo1 = db.qualityProfiles().insert(db.getDefaultOrganization(), q -> q.setLanguage(XOO1.getKey()));
283     db.qualityProfiles().associateWithProject(project, profileOnXoo1);
284
285     SearchWsResponse result = call(ws.newRequest()
286       .setParam(PARAM_PROJECT_KEY, project.getDbKey())
287       .setParam(PARAM_DEFAULTS, "true"));
288
289     assertThat(result.getProfilesList()).isEmpty();
290   }
291
292   @Test
293   public void actions_when_user_is_global_qprofile_administer() {
294     OrganizationDto organization = db.organizations().insert();
295     QProfileDto customProfile = db.qualityProfiles().insert(organization, p -> p.setLanguage(XOO1.getKey()));
296     QProfileDto builtInProfile = db.qualityProfiles().insert(organization, p -> p.setLanguage(XOO1.getKey()).setIsBuiltIn(true));
297     QProfileDto defaultProfile = db.qualityProfiles().insert(organization, p -> p.setLanguage(XOO1.getKey()));
298     db.qualityProfiles().setAsDefault(defaultProfile);
299     UserDto user = db.users().insertUser();
300     userSession.logIn(user).addPermission(OrganizationPermission.ADMINISTER_QUALITY_PROFILES, organization);
301
302     SearchWsResponse result = call(ws.newRequest()
303       .setParam(PARAM_ORGANIZATION, organization.getKey()));
304
305     assertThat(result.getProfilesList())
306       .extracting(QualityProfile::getKey, qp -> qp.getActions().getEdit(), qp -> qp.getActions().getCopy(), qp -> qp.getActions().getSetAsDefault(),
307         qp -> qp.getActions().getDelete(), qp -> qp.getActions().getAssociateProjects())
308       .containsExactlyInAnyOrder(
309         tuple(customProfile.getKee(), true, true, true, true, true),
310         tuple(builtInProfile.getKee(), false, true, true, false, true),
311         tuple(defaultProfile.getKee(), true, true, false, false, false));
312     assertThat(result.getActions().getCreate()).isTrue();
313   }
314
315   @Test
316   public void actions_when_user_can_edit_profile() {
317     OrganizationDto organization = db.organizations().insert();
318     QProfileDto profile1 = db.qualityProfiles().insert(organization, p -> p.setLanguage(XOO1.getKey()));
319     QProfileDto profile2 = db.qualityProfiles().insert(organization, p -> p.setLanguage(XOO2.getKey()));
320     QProfileDto profile3 = db.qualityProfiles().insert(organization, p -> p.setLanguage(XOO2.getKey()));
321     QProfileDto builtInProfile = db.qualityProfiles().insert(organization, p -> p.setLanguage(XOO2.getKey()).setIsBuiltIn(true));
322     UserDto user = db.users().insertUser();
323     GroupDto group = db.users().insertGroup(organization);
324     db.qualityProfiles().addUserPermission(profile1, user);
325     db.qualityProfiles().addGroupPermission(profile3, group);
326     userSession.logIn(user).setGroups(group);
327
328     SearchWsResponse result = call(ws.newRequest()
329       .setParam(PARAM_ORGANIZATION, organization.getKey()));
330
331     assertThat(result.getProfilesList())
332       .extracting(QualityProfile::getKey, qp -> qp.getActions().getEdit(), qp -> qp.getActions().getCopy(), qp -> qp.getActions().getSetAsDefault(),
333         qp -> qp.getActions().getDelete(), qp -> qp.getActions().getAssociateProjects())
334       .containsExactlyInAnyOrder(
335         tuple(profile1.getKee(), true, false, false, true, true),
336         tuple(profile2.getKee(), false, false, false, false, false),
337         tuple(profile3.getKee(), true, false, false, true, true),
338         tuple(builtInProfile.getKee(), false, false, false, false, false));
339     assertThat(result.getActions().getCreate()).isFalse();
340   }
341
342   @Test
343   public void actions_when_not_logged_in() {
344     OrganizationDto organization = db.organizations().insert();
345     QProfileDto profile = db.qualityProfiles().insert(organization, p -> p.setLanguage(XOO1.getKey()));
346     userSession.anonymous();
347
348     SearchWsResponse result = call(ws.newRequest()
349       .setParam(PARAM_ORGANIZATION, organization.getKey()));
350
351     assertThat(result.getProfilesList())
352       .extracting(QualityProfile::getKey, qp -> qp.getActions().getEdit(), qp -> qp.getActions().getCopy(), qp -> qp.getActions().getSetAsDefault(),
353         qp -> qp.getActions().getDelete(), qp -> qp.getActions().getAssociateProjects())
354       .containsExactlyInAnyOrder(tuple(profile.getKee(), false, false, false, false, false));
355     assertThat(result.getActions().getCreate()).isFalse();
356   }
357
358   @Test
359   public void statistics_on_active_rules() {
360     QProfileDto profile = db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(XOO1.getKey()));
361     RuleDefinitionDto rule = db.rules().insertRule(r -> r.setLanguage(XOO1.getKey())).getDefinition();
362     RuleDefinitionDto deprecatedRule1 = db.rules().insertRule(r -> r.setStatus(DEPRECATED)).getDefinition();
363     RuleDefinitionDto deprecatedRule2 = db.rules().insertRule(r -> r.setStatus(DEPRECATED)).getDefinition();
364     RuleDefinitionDto inactiveRule = db.rules().insertRule(r -> r.setLanguage(XOO1.getKey())).getDefinition();
365     db.qualityProfiles().activateRule(profile, rule);
366     db.qualityProfiles().activateRule(profile, deprecatedRule1);
367     db.qualityProfiles().activateRule(profile, deprecatedRule2);
368
369     SearchWsResponse result = call(ws.newRequest());
370
371     assertThat(result.getProfilesList())
372       .extracting(QualityProfile::getActiveRuleCount, QualityProfile::getActiveDeprecatedRuleCount)
373       .containsExactlyInAnyOrder(tuple(3L, 2L));
374   }
375
376   @Test
377   public void statistics_on_projects() {
378     ComponentDto project1 = db.components().insertPrivateProject();
379     ComponentDto project2 = db.components().insertPrivateProject();
380     QProfileDto profileOnXoo1 = db.qualityProfiles().insert(db.getDefaultOrganization(), q -> q.setLanguage(XOO1.getKey()));
381     QProfileDto defaultProfileOnXoo1 = db.qualityProfiles().insert(db.getDefaultOrganization(), q -> q.setLanguage(XOO1.getKey()));
382     db.qualityProfiles().associateWithProject(project1, profileOnXoo1);
383     db.qualityProfiles().associateWithProject(project2, profileOnXoo1);
384     db.qualityProfiles().setAsDefault(defaultProfileOnXoo1);
385
386     SearchWsResponse result = call(ws.newRequest());
387
388     assertThat(result.getProfilesList())
389       .extracting(QualityProfile::hasProjectCount, QualityProfile::getProjectCount)
390       .containsExactlyInAnyOrder(tuple(true, 2L), tuple(false, 0L));
391   }
392
393   @Test
394   public void map_dates() {
395     long time = DateUtils.parseDateTime("2016-12-22T19:10:03+0100").getTime();
396     qualityProfileDb.insert(newQualityProfileDto()
397       .setOrganizationUuid(defaultOrganizationProvider.get().getUuid())
398       .setLanguage(XOO1.getKey())
399       .setRulesUpdatedAt("2016-12-21T19:10:03+0100")
400       .setLastUsed(time)
401       .setUserUpdatedAt(time));
402
403     SearchWsResponse result = call(ws.newRequest());
404
405     assertThat(result.getProfilesCount()).isEqualTo(1);
406     assertThat(result.getProfiles(0).getRulesUpdatedAt()).isEqualTo("2016-12-21T19:10:03+0100");
407     assertThat(parseDateTime(result.getProfiles(0).getLastUsed()).getTime()).isEqualTo(time);
408     assertThat(parseDateTime(result.getProfiles(0).getUserUpdatedAt()).getTime()).isEqualTo(time);
409   }
410
411   @Test
412   public void return_qprofile_on_free_organization() {
413     OrganizationDto organization = db.organizations().insert(o -> o.setSubscription(FREE));
414     QProfileDto qProfile = db.qualityProfiles().insert(organization, p -> p.setLanguage(XOO1.getKey()));
415
416     SearchWsResponse result = call(ws.newRequest().setParam(PARAM_ORGANIZATION, organization.getKey()));
417
418     assertThat(result.getProfilesList()).extracting(QualityProfile::getKey)
419       .containsExactlyInAnyOrder(qProfile.getKee());
420   }
421
422   @Test
423   public void return_qprofile_on_paid_organization_when_user_is_member() {
424     OrganizationDto organization = db.organizations().insert(o -> o.setSubscription(PAID));
425     QProfileDto qProfile = db.qualityProfiles().insert(organization, p -> p.setLanguage(XOO1.getKey()));
426     UserDto user = db.users().insertUser();
427     userSession.logIn(user).addMembership(organization);
428
429     SearchWsResponse result = call(ws.newRequest().setParam(PARAM_ORGANIZATION, organization.getKey()));
430
431     assertThat(result.getProfilesList()).extracting(QualityProfile::getKey)
432       .containsExactlyInAnyOrder(qProfile.getKee());
433   }
434
435   @Test
436   public void fail_if_project_does_not_exist() {
437     expectedException.expect(NotFoundException.class);
438     expectedException.expectMessage("Component key 'unknown-project' not found");
439
440     call(ws.newRequest().setParam(PARAM_PROJECT_KEY, "unknown-project"));
441   }
442
443   @Test
444   public void fail_if_project_of_module_does_not_exist() {
445     ComponentDto project = db.components().insertPrivateProject();
446     ComponentDto module = db.components().insertComponent(newModuleDto(project).setProjectUuid("unknown"));
447
448     expectedException.expect(IllegalStateException.class);
449     expectedException.expectMessage(format("Project uuid of component uuid '%s' does not exist", module.uuid()));
450
451     call(ws.newRequest().setParam(PARAM_PROJECT_KEY, module.getDbKey()));
452   }
453
454   @Test
455   public void fail_if_project_is_on_another_organization() {
456     OrganizationDto organization = db.organizations().insert();
457     OrganizationDto anotherOrganization = db.organizations().insert();
458     ComponentDto project = db.components().insertPrivateProject(anotherOrganization);
459
460     expectedException.expect(NotFoundException.class);
461     expectedException.expectMessage(format("Component key '%s' not found", project.getDbKey()));
462
463     call(ws.newRequest()
464       .setParam(PARAM_ORGANIZATION, organization.getKey())
465       .setParam(PARAM_PROJECT_KEY, project.getDbKey()));
466   }
467
468   @Test
469   public void fail_if_organization_does_not_exist() {
470     expectedException.expect(NotFoundException.class);
471     expectedException.expectMessage("No organization with key 'unknown-organization'");
472
473     call(ws.newRequest().setParam(PARAM_ORGANIZATION, "unknown-organization"));
474   }
475
476   @Test
477   public void fail_on_paid_organization_when_not_member() {
478     OrganizationDto organization = db.organizations().insert(o -> o.setSubscription(PAID));
479     userSession.logIn();
480
481     expectedException.expect(ForbiddenException.class);
482     expectedException.expectMessage(format("You're not member of organization '%s'", organization.getKey()));
483
484     call(ws.newRequest().setParam(PARAM_ORGANIZATION, organization.getKey()));
485   }
486
487   @Test
488   public void json_example() {
489     OrganizationDto organization = db.organizations().insertForKey("My Organization");
490     // languages
491     Language cs = newLanguage("cs", "C#");
492     Language java = newLanguage("java", "Java");
493     Language python = newLanguage("py", "Python");
494     // profiles
495     QProfileDto sonarWayCs = db.qualityProfiles().insert(organization,
496       p -> p.setName("Sonar way").setKee("AU-TpxcA-iU5OvuD2FL3").setIsBuiltIn(true).setLanguage(cs.getKey()));
497     QProfileDto myCompanyProfile = db.qualityProfiles().insert(organization,
498       p -> p.setName("My Company Profile").setKee("iU5OvuD2FLz").setLanguage(java.getKey()));
499     QProfileDto myBuProfile = db.qualityProfiles().insert(organization,
500       p -> p.setName("My BU Profile").setKee("AU-TpxcA-iU5OvuD2FL1").setParentKee(myCompanyProfile.getKee()).setLanguage(java.getKey()));
501     QProfileDto sonarWayPython = db.qualityProfiles().insert(organization,
502       p -> p.setName("Sonar way").setKee("AU-TpxcB-iU5OvuD2FL7").setIsBuiltIn(true).setLanguage(python.getKey()));
503     db.qualityProfiles().setAsDefault(sonarWayCs, myCompanyProfile, sonarWayPython);
504     // rules
505     List<RuleDefinitionDto> javaRules = range(0, 10).mapToObj(i -> db.rules().insertRule(r -> r.setLanguage(java.getKey())).getDefinition())
506       .collect(MoreCollectors.toList());
507     List<RuleDefinitionDto> deprecatedJavaRules = range(0, 5)
508       .mapToObj(i -> db.rules().insertRule(r -> r.setLanguage(java.getKey()).setStatus(DEPRECATED)).getDefinition())
509       .collect(MoreCollectors.toList());
510     range(0, 7).forEach(i -> db.qualityProfiles().activateRule(myCompanyProfile, javaRules.get(i)));
511     range(0, 2).forEach(i -> db.qualityProfiles().activateRule(myCompanyProfile, deprecatedJavaRules.get(i)));
512     range(0, 10).forEach(i -> db.qualityProfiles().activateRule(myBuProfile, javaRules.get(i)));
513     range(0, 5).forEach(i -> db.qualityProfiles().activateRule(myBuProfile, deprecatedJavaRules.get(i)));
514     range(0, 2)
515       .mapToObj(i -> db.rules().insertRule(r -> r.setLanguage(python.getKey())).getDefinition())
516       .forEach(rule -> db.qualityProfiles().activateRule(sonarWayPython, rule));
517     range(0, 3)
518       .mapToObj(i -> db.rules().insertRule(r -> r.setLanguage(cs.getKey())).getDefinition())
519       .forEach(rule -> db.qualityProfiles().activateRule(sonarWayCs, rule));
520     // project
521     range(0, 7)
522       .mapToObj(i -> db.components().insertPrivateProject(organization))
523       .forEach(project -> db.qualityProfiles().associateWithProject(project, myBuProfile));
524     // User
525     UserDto user = db.users().insertUser();
526     db.qualityProfiles().addUserPermission(myCompanyProfile, user);
527     db.qualityProfiles().addUserPermission(myBuProfile, user);
528     userSession.logIn(user);
529
530     underTest = new SearchAction(userSession, new Languages(cs, java, python), dbClient, qProfileWsSupport, new ComponentFinder(dbClient, null));
531     ws = new WsActionTester(underTest);
532     String result = ws.newRequest().setParam(PARAM_ORGANIZATION, organization.getKey()).execute().getInput();
533     assertJson(result).ignoreFields("ruleUpdatedAt", "lastUsed", "userUpdatedAt")
534       .isSimilarTo(ws.getDef().responseExampleAsString());
535   }
536
537   @Test
538   public void definition() {
539     WebService.Action definition = ws.getDef();
540
541     assertThat(definition.key()).isEqualTo("search");
542     assertThat(definition.responseExampleAsString()).isNotEmpty();
543     assertThat(definition.isPost()).isFalse();
544
545     assertThat(definition.changelog())
546       .extracting(Change::getVersion, Change::getDescription)
547       .containsExactlyInAnyOrder(
548         tuple("6.5", "The parameters 'defaults', 'project' and 'language' can be combined without any constraint"),
549         tuple("6.6", "Add available actions 'edit', 'copy' and 'setAsDefault' and global action 'create'"),
550         tuple("7.0", "Add available actions 'delete' and 'associateProjects'"));
551
552     WebService.Param organization = definition.param("organization");
553     assertThat(organization).isNotNull();
554     assertThat(organization.isRequired()).isFalse();
555     assertThat(organization.isInternal()).isTrue();
556     assertThat(organization.description()).isNotEmpty();
557     assertThat(organization.since()).isEqualTo("6.4");
558
559     WebService.Param defaults = definition.param("defaults");
560     assertThat(defaults.defaultValue()).isEqualTo("false");
561     assertThat(defaults.description()).isEqualTo("If set to true, return only the quality profiles marked as default for each language");
562
563     WebService.Param projectKey = definition.param("project");
564     assertThat(projectKey.description()).isEqualTo("Project key");
565     assertThat(projectKey.deprecatedKey()).isEqualTo("projectKey");
566
567     WebService.Param language = definition.param("language");
568     assertThat(language.possibleValues()).containsExactly("xoo1", "xoo2");
569     assertThat(language.deprecatedSince()).isNull();
570     assertThat(language.description()).isEqualTo("Language key. If provided, only profiles for the given language are returned.");
571
572     WebService.Param profileName = definition.param("qualityProfile");
573     assertThat(profileName.deprecatedSince()).isNull();
574     assertThat(profileName.description()).isEqualTo("Quality profile name");
575   }
576
577   private SearchWsResponse call(TestRequest request) {
578     TestRequest wsRequest = request.setMediaType(MediaTypes.PROTOBUF);
579
580     return wsRequest.executeProtobuf(SearchWsResponse.class);
581   }
582 }