]> source.dussan.org Git - sonarqube.git/blob
7b7fdb5db591ed2ba7fc843cba6285a1fc4312ea
[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.io.IOException;
23 import java.io.Reader;
24 import java.io.Writer;
25 import javax.annotation.Nullable;
26 import org.apache.commons.lang.StringUtils;
27 import org.junit.Rule;
28 import org.junit.Test;
29 import org.junit.rules.ExpectedException;
30 import org.sonar.api.profiles.ProfileExporter;
31 import org.sonar.api.profiles.RulesProfile;
32 import org.sonar.api.server.ws.WebService;
33 import org.sonar.api.utils.System2;
34 import org.sonar.db.DbClient;
35 import org.sonar.db.DbSession;
36 import org.sonar.db.DbTester;
37 import org.sonar.db.organization.OrganizationDto;
38 import org.sonar.db.qualityprofile.QProfileDto;
39 import org.sonar.db.user.UserDto;
40 import org.sonar.server.exceptions.BadRequestException;
41 import org.sonar.server.exceptions.ForbiddenException;
42 import org.sonar.server.exceptions.NotFoundException;
43 import org.sonar.server.language.LanguageTesting;
44 import org.sonar.server.organization.TestDefaultOrganizationProvider;
45 import org.sonar.server.qualityprofile.QProfileBackuper;
46 import org.sonar.server.qualityprofile.QProfileExporters;
47 import org.sonar.server.qualityprofile.QProfileRestoreSummary;
48 import org.sonar.server.tester.UserSessionRule;
49 import org.sonar.server.ws.WsActionTester;
50
51 import static java.lang.String.format;
52 import static org.assertj.core.api.Assertions.assertThat;
53 import static org.sonar.db.organization.OrganizationDto.Subscription.PAID;
54 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_KEY;
55 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LANGUAGE;
56 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_ORGANIZATION;
57 import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_QUALITY_PROFILE;
58
59 public class ExportActionTest {
60
61   private static final String XOO_LANGUAGE = "xoo";
62   private static final String JAVA_LANGUAGE = "java";
63
64   @Rule
65   public DbTester db = DbTester.create(System2.INSTANCE);
66   @Rule
67   public UserSessionRule userSession = UserSessionRule.standalone();
68   @Rule
69   public ExpectedException expectedException = ExpectedException.none();
70
71   private DbClient dbClient = db.getDbClient();
72   private QProfileBackuper backuper = new TestBackuper();
73   private QProfileWsSupport wsSupport = new QProfileWsSupport(dbClient, userSession, TestDefaultOrganizationProvider.from(db));
74
75   @Test
76   public void export_profile_with_key() {
77     QProfileDto profile = createProfile(db.getDefaultOrganization(), false);
78
79     WsActionTester tester = newWsActionTester(newExporter("polop"), newExporter("palap"));
80     String result = tester.newRequest()
81       .setParam(PARAM_KEY, profile.getKee())
82       .setParam("exporterKey", "polop")
83       .execute()
84       .getInput();
85
86     assertThat(result).isEqualTo("Profile " + profile.getLanguage() + "/" + profile.getName() + " exported by polop");
87   }
88
89   @Test
90   public void export_profile_in_default_organization() {
91     QProfileDto profile = createProfile(db.getDefaultOrganization(), false);
92
93     WsActionTester tester = newWsActionTester(newExporter("polop"), newExporter("palap"));
94     String result = tester.newRequest()
95       .setParam("language", profile.getLanguage())
96       .setParam("qualityProfile", profile.getName())
97       .setParam("exporterKey", "polop").execute()
98       .getInput();
99
100     assertThat(result).isEqualTo("Profile " + profile.getLanguage() + "/" + profile.getName() + " exported by polop");
101   }
102
103   @Test
104   public void export_profile_in_specified_organization() {
105     OrganizationDto organization = db.organizations().insert();
106     QProfileDto profile = createProfile(organization, false);
107
108     WsActionTester tester = newWsActionTester(newExporter("polop"), newExporter("palap"));
109     String result = tester.newRequest()
110       .setParam("organization", organization.getKey())
111       .setParam("language", profile.getLanguage())
112       .setParam("qualityProfile", profile.getName())
113       .setParam("exporterKey", "polop").execute()
114       .getInput();
115
116     assertThat(result).isEqualTo("Profile " + profile.getLanguage() + "/" + profile.getName() + " exported by polop");
117   }
118
119   @Test
120   public void export_default_profile() {
121     QProfileDto nonDefaultProfile = createProfile(db.getDefaultOrganization(), false);
122     QProfileDto defaultProfile = createProfile(db.getDefaultOrganization(), true);
123
124     WsActionTester tester = newWsActionTester(newExporter("polop"), newExporter("palap"));
125     String result = tester.newRequest()
126       .setParam("language", XOO_LANGUAGE)
127       .setParam("exporterKey", "polop")
128       .execute()
129       .getInput();
130
131     assertThat(result).isEqualTo("Profile " + defaultProfile.getLanguage() + "/" + defaultProfile.getName() + " exported by polop");
132   }
133
134   @Test
135   public void return_backup_when_exporter_is_not_specified() {
136     OrganizationDto organization = db.getDefaultOrganization();
137     QProfileDto profile = createProfile(organization, false);
138
139     String result = newWsActionTester(newExporter("polop")).newRequest()
140       .setParam("language", profile.getLanguage())
141       .setParam("qualityProfile", profile.getName())
142       .execute()
143       .getInput();
144
145     assertThat(result).isEqualTo("Backup of " + profile.getLanguage() + "/" + profile.getKee());
146   }
147
148   @Test
149   public void do_not_mismatch_profiles_with_other_organizations_and_languages() {
150     OrganizationDto org1 = db.organizations().insert();
151     OrganizationDto org2 = db.organizations().insert();
152     QProfileDto defaultJavaInOrg1 = db.qualityProfiles().insert(org1, p -> p.setLanguage(JAVA_LANGUAGE).setName("Sonar Way"));
153     QProfileDto nonDefaultJavaInOrg1 = db.qualityProfiles().insert(org1, p -> p.setLanguage(JAVA_LANGUAGE).setName("My Way"));
154     QProfileDto defaultXooInOrg1 = db.qualityProfiles().insert(org1, p -> p.setLanguage(XOO_LANGUAGE).setName("Sonar Way"));
155     QProfileDto nonDefaultXooInOrg1 = db.qualityProfiles().insert(org1, p -> p.setLanguage(XOO_LANGUAGE).setName("My Way"));
156     QProfileDto defaultJavaInOrg2 = db.qualityProfiles().insert(org2, p -> p.setLanguage(JAVA_LANGUAGE).setName("Sonar Way"));
157     QProfileDto nonDefaultJavaInOrg2 = db.qualityProfiles().insert(org2, p -> p.setLanguage(JAVA_LANGUAGE).setName("My Way"));
158     QProfileDto defaultXooInOrg2 = db.qualityProfiles().insert(org2, p -> p.setLanguage(XOO_LANGUAGE).setName("Sonar Way"));
159     QProfileDto nonDefaultXooInOrg2 = db.qualityProfiles().insert(org2, p -> p.setLanguage(XOO_LANGUAGE).setName("My Way"));
160     db.qualityProfiles().setAsDefault(defaultJavaInOrg1, defaultJavaInOrg2, defaultXooInOrg1, defaultXooInOrg2);
161
162     WsActionTester tester = newWsActionTester();
163
164     // default profile for specified organization and language
165     assertThat(tester.newRequest()
166       .setParam("organization", org1.getKey())
167       .setParam("language", defaultJavaInOrg1.getLanguage())
168       .execute()
169       .getInput())
170         .isEqualTo("Backup of java/" + defaultJavaInOrg1.getKee());
171
172     // profile for specified organization, language and name --> do not mix with Xoo profile or profile with same lang/name on other
173     // organization
174     assertThat(tester.newRequest()
175       .setParam("organization", org1.getKey())
176       .setParam("language", defaultJavaInOrg1.getLanguage())
177       .setParam("name", defaultJavaInOrg1.getName())
178       .execute()
179       .getInput())
180         .isEqualTo("Backup of java/" + defaultJavaInOrg1.getKee());
181   }
182
183   @Test
184   public void export_profile_in_paid_organization() {
185     OrganizationDto organization = db.organizations().insert(o -> o.setSubscription(PAID));
186     QProfileDto profile = createProfile(organization, false);
187     UserDto user = db.users().insertUser();
188     userSession.logIn(user).addMembership(organization);
189
190     WsActionTester tester = newWsActionTester(newExporter("polop"));
191     String result = tester.newRequest()
192       .setParam("organization", organization.getKey())
193       .setParam("language", profile.getLanguage())
194       .setParam("qualityProfile", profile.getName())
195       .setParam("exporterKey", "polop").execute()
196       .getInput();
197
198     assertThat(result).isEqualTo("Profile " + profile.getLanguage() + "/" + profile.getName() + " exported by polop");
199   }
200
201   @Test
202   public void throw_NotFoundException_if_profile_with_specified_name_does_not_exist_in_default_organization() {
203     expectedException.expect(NotFoundException.class);
204
205     newWsActionTester().newRequest()
206       .setParam("language", XOO_LANGUAGE)
207       .setParam("exporterKey", "polop").execute();
208   }
209
210   @Test
211   public void throw_IAE_if_export_with_specified_key_does_not_exist() {
212     QProfileDto profile = createProfile(db.getDefaultOrganization(), true);
213
214     expectedException.expect(IllegalArgumentException.class);
215     expectedException.expectMessage("Value of parameter 'exporterKey' (unknown) must be one of: [polop, palap]");
216
217     newWsActionTester(newExporter("polop"), newExporter("palap")).newRequest()
218       .setParam("language", XOO_LANGUAGE)
219       .setParam("exporterKey", "unknown").execute();
220   }
221
222   @Test
223   public void throw_NotFoundException_if_specified_organization_does_not_exist() {
224     WsActionTester tester = newWsActionTester(newExporter("foo"));
225
226     expectedException.expect(NotFoundException.class);
227     expectedException.expectMessage("No organization with key 'does_not_exist'");
228
229     tester.newRequest()
230       .setParam("organization", "does_not_exist")
231       .setParam("language", XOO_LANGUAGE)
232       .setParam("name", "bar")
233       .setParam("exporterKey", "foo")
234       .execute();
235   }
236
237   @Test
238   public void fail_if_profile_key_is_unknown() {
239     expectedException.expect(NotFoundException.class);
240     expectedException.expectMessage("Could not find profile with key 'PROFILE-KEY-404'");
241
242     WsActionTester ws = newWsActionTester(newExporter("polop"), newExporter("palap"));
243     ws.newRequest()
244       .setParam(PARAM_KEY, "PROFILE-KEY-404")
245       .setParam("exporterKey", "polop").execute()
246       .getInput();
247   }
248
249   @Test
250   public void fail_if_profile_key_and_language_provided() {
251     QProfileDto profile = createProfile(db.getDefaultOrganization(), false);
252
253     expectedException.expect(BadRequestException.class);
254     expectedException.expectMessage("Either 'key' or 'language' must be provided");
255
256     WsActionTester ws = newWsActionTester(newExporter("polop"), newExporter("palap"));
257     ws.newRequest()
258       .setParam(PARAM_KEY, profile.getKee())
259       .setParam(PARAM_LANGUAGE, profile.getLanguage())
260       .setParam("exporterKey", "polop").execute()
261       .getInput();
262   }
263
264   @Test
265   public void fail_on_paid_organization_when_not_member() {
266     WsActionTester tester = newWsActionTester(newExporter("foo"));
267     OrganizationDto organization = db.organizations().insert(o -> o.setSubscription(PAID));
268     QProfileDto qualityProfile = db.qualityProfiles().insert(organization, p -> p.setLanguage(XOO_LANGUAGE));
269
270     expectedException.expect(ForbiddenException.class);
271     expectedException.expectMessage(format("You're not member of organization '%s'", organization.getKey()));
272
273     tester.newRequest()
274       .setParam(PARAM_ORGANIZATION, organization.getKey())
275       .setParam(PARAM_QUALITY_PROFILE, qualityProfile.getName())
276       .setParam(PARAM_LANGUAGE, XOO_LANGUAGE)
277       .setParam("exporterKey", "foo")
278       .execute();
279   }
280
281   @Test
282   public void definition_without_exporters() {
283     WebService.Action definition = newWsActionTester().getDef();
284
285     assertThat(definition.isPost()).isFalse();
286     assertThat(definition.isInternal()).isFalse();
287     assertThat(definition.params()).extracting(WebService.Param::key).containsExactlyInAnyOrder("key", "language", "qualityProfile", "organization");
288
289     WebService.Param organizationParam = definition.param("organization");
290     assertThat(organizationParam.since()).isEqualTo("6.4");
291     assertThat(organizationParam.isInternal()).isTrue();
292
293     WebService.Param key = definition.param("key");
294     assertThat(key.since()).isEqualTo("6.5");
295     assertThat(key.deprecatedSince()).isEqualTo("6.6");
296
297     WebService.Param name = definition.param("qualityProfile");
298     assertThat(name.deprecatedSince()).isNullOrEmpty();
299     assertThat(name.deprecatedKey()).isEqualTo("name");
300
301     WebService.Param language = definition.param("language");
302     assertThat(language.deprecatedSince()).isNullOrEmpty();
303   }
304
305   @Test
306   public void definition_with_exporters() {
307     WebService.Action definition = newWsActionTester(newExporter("polop"), newExporter("palap")).getDef();
308
309     assertThat(definition.isPost()).isFalse();
310     assertThat(definition.isInternal()).isFalse();
311     assertThat(definition.params()).extracting("key").containsExactlyInAnyOrder("key", "language", "qualityProfile", "organization", "exporterKey");
312     WebService.Param exportersParam = definition.param("exporterKey");
313     assertThat(exportersParam.possibleValues()).containsOnly("polop", "palap");
314     assertThat(exportersParam.deprecatedKey()).isEqualTo("format");
315     assertThat(exportersParam.deprecatedKeySince()).isEqualTo("6.3");
316     assertThat(exportersParam.isInternal()).isFalse();
317   }
318
319   private QProfileDto createProfile(OrganizationDto organization, boolean isDefault) {
320     QProfileDto profile = db.qualityProfiles().insert(organization, p -> p.setLanguage(XOO_LANGUAGE));
321     if (isDefault) {
322       db.qualityProfiles().setAsDefault(profile);
323     }
324     return profile;
325   }
326
327   private WsActionTester newWsActionTester(ProfileExporter... profileExporters) {
328     QProfileExporters exporters = new QProfileExporters(dbClient, null, null, profileExporters, null);
329     return new WsActionTester(new ExportAction(dbClient, backuper, exporters, LanguageTesting.newLanguages(XOO_LANGUAGE, JAVA_LANGUAGE), wsSupport));
330   }
331
332   private static ProfileExporter newExporter(String key) {
333     return new ProfileExporter(key, StringUtils.capitalize(key)) {
334       @Override
335       public String getMimeType() {
336         return "text/plain+" + key;
337       }
338
339       @Override
340       public void exportProfile(RulesProfile profile, Writer writer) {
341         try {
342           writer.write(format("Profile %s/%s exported by %s", profile.getLanguage(), profile.getName(), key));
343         } catch (IOException ioe) {
344           throw new RuntimeException(ioe);
345         }
346       }
347     };
348   }
349
350   private static class TestBackuper implements QProfileBackuper {
351
352     @Override
353     public void backup(DbSession dbSession, QProfileDto profile, Writer backupWriter) {
354       try {
355         backupWriter.write(format("Backup of %s/%s", profile.getLanguage(), profile.getKee()));
356       } catch (IOException e) {
357         throw new IllegalStateException(e);
358       }
359     }
360
361     @Override
362     public QProfileRestoreSummary restore(DbSession dbSession, Reader backup, OrganizationDto organization, @Nullable String overriddenProfileName) {
363       throw new UnsupportedOperationException();
364     }
365
366     @Override
367     public QProfileRestoreSummary restore(DbSession dbSession, Reader backup, QProfileDto profile) {
368       throw new UnsupportedOperationException();
369     }
370
371     @Override public QProfileRestoreSummary copy(DbSession dbSession, QProfileDto from, QProfileDto to) {
372       throw new UnsupportedOperationException();
373     }
374   }
375 }