3 * Copyright (C) 2009-2020 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;
22 import java.io.IOException;
23 import java.io.Reader;
24 import java.io.StringWriter;
25 import java.io.Writer;
26 import java.util.Collection;
27 import org.junit.Before;
28 import org.junit.Test;
29 import org.junit.rules.ExpectedException;
30 import org.mockito.ArgumentCaptor;
31 import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
32 import org.sonar.api.profiles.ProfileExporter;
33 import org.sonar.api.profiles.ProfileImporter;
34 import org.sonar.api.profiles.RulesProfile;
35 import org.sonar.api.rules.Rule;
36 import org.sonar.api.rules.RuleFinder;
37 import org.sonar.api.rules.RulePriority;
38 import org.sonar.api.utils.System2;
39 import org.sonar.api.utils.ValidationMessages;
40 import org.sonar.db.DbSession;
41 import org.sonar.db.DbTester;
42 import org.sonar.db.qualityprofile.QProfileDto;
43 import org.sonar.db.rule.RuleDefinitionDto;
44 import org.sonar.server.exceptions.BadRequestException;
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.rule.DefaultRuleFinder;
49 import org.sonar.server.tester.UserSessionRule;
51 import static java.nio.charset.StandardCharsets.UTF_8;
52 import static org.apache.commons.io.IOUtils.toInputStream;
53 import static org.assertj.core.api.Assertions.assertThat;
54 import static org.junit.Assert.fail;
55 import static org.mockito.ArgumentMatchers.any;
56 import static org.mockito.Mockito.mock;
57 import static org.mockito.Mockito.verify;
59 public class QProfileExportersTest {
62 public UserSessionRule userSessionRule = UserSessionRule.standalone();
64 private System2 system2 = new AlwaysIncreasingSystem2();
67 public ExpectedException expectedException = ExpectedException.none();
69 public DbTester db = DbTester.create(system2);
71 private RuleFinder ruleFinder = new DefaultRuleFinder(db.getDbClient());
72 private ProfileExporter[] exporters = new ProfileExporter[] {
73 new StandardExporter(), new XooExporter()};
74 private ProfileImporter[] importers = new ProfileImporter[] {
75 new XooProfileImporter(), new XooProfileImporterWithMessages(), new XooProfileImporterWithError()};
76 private RuleDefinitionDto rule;
77 private QProfileRules qProfileRules = mock(QProfileRules.class);
78 private QProfileExporters underTest = new QProfileExporters(db.getDbClient(), ruleFinder, qProfileRules, exporters, importers);
82 rule = db.rules().insert(r -> r.setLanguage("xoo").setRepositoryKey("SonarXoo").setRuleKey("R1"));
86 public void exportersForLanguage() {
87 assertThat(underTest.exportersForLanguage("xoo")).hasSize(2);
88 assertThat(underTest.exportersForLanguage("java")).hasSize(1);
89 assertThat(underTest.exportersForLanguage("java").get(0)).isInstanceOf(StandardExporter.class);
93 public void mimeType() {
94 assertThat(underTest.mimeType("xootool")).isEqualTo("plain/custom");
97 assertThat(underTest.mimeType("standard")).isEqualTo("text/plain");
101 public void import_xml() {
102 QProfileDto profile = createProfile();
105 underTest.importXml(profile, "XooProfileImporter", toInputStream("<xml/>", UTF_8), db.getSession());
107 ArgumentCaptor<QProfileDto> profileCapture = ArgumentCaptor.forClass(QProfileDto.class);
108 Class<Collection<RuleActivation>> collectionClass = (Class<Collection<RuleActivation>>) (Class) Collection.class;
109 ArgumentCaptor<Collection<RuleActivation>> activationCapture = ArgumentCaptor.forClass(collectionClass);
110 verify(qProfileRules).activateAndCommit(any(DbSession.class), profileCapture.capture(), activationCapture.capture());
112 assertThat(profileCapture.getValue().getKee()).isEqualTo(profile.getKee());
113 Collection<RuleActivation> activations = activationCapture.getValue();
114 assertThat(activations).hasSize(1);
115 RuleActivation activation = activations.iterator().next();
116 assertThat(activation.getRuleUuid()).isEqualTo(rule.getUuid());
117 assertThat(activation.getSeverity()).isEqualTo("CRITICAL");
121 public void import_xml_return_messages() {
122 QProfileDto profile = createProfile();
124 QProfileResult result = underTest.importXml(profile, "XooProfileImporterWithMessages", toInputStream("<xml/>", UTF_8), db.getSession());
126 assertThat(result.infos()).containsOnly("an info");
127 assertThat(result.warnings()).containsOnly("a warning");
131 public void fail_to_import_xml_when_error_in_importer() {
133 underTest.importXml(QProfileTesting.newXooP1(), "XooProfileImporterWithError", toInputStream("<xml/>", UTF_8), db.getSession());
135 } catch (BadRequestException e) {
136 assertThat(e).hasMessage("error!");
141 public void fail_to_import_xml_on_unknown_importer() {
143 underTest.importXml(QProfileTesting.newXooP1(), "Unknown", toInputStream("<xml/>", UTF_8), db.getSession());
145 } catch (BadRequestException e) {
146 assertThat(e).hasMessage("No such importer : Unknown");
151 public void export_empty_profile() {
152 QProfileDto profile = createProfile();
154 StringWriter writer = new StringWriter();
155 underTest.export(db.getSession(), profile, "standard", writer);
156 assertThat(writer.toString()).isEqualTo("standard -> " + profile.getName() + " -> 0");
158 writer = new StringWriter();
159 underTest.export(db.getSession(), profile, "xootool", writer);
160 assertThat(writer.toString()).isEqualTo("xoo -> " + profile.getName() + " -> 0");
164 public void export_profile() {
165 QProfileDto profile = createProfile();
166 db.qualityProfiles().activateRule(profile, rule);
168 StringWriter writer = new StringWriter();
169 underTest.export(db.getSession(), profile, "standard", writer);
170 assertThat(writer.toString()).isEqualTo("standard -> " + profile.getName() + " -> 1");
172 writer = new StringWriter();
173 underTest.export(db.getSession(), profile, "xootool", writer);
174 assertThat(writer.toString()).isEqualTo("xoo -> " + profile.getName() + " -> 1");
178 public void export_throws_NotFoundException_if_exporter_does_not_exist() {
179 QProfileDto profile = createProfile();
181 expectedException.expect(NotFoundException.class);
182 expectedException.expectMessage("Unknown quality profile exporter: does_not_exist");
184 underTest.export(db.getSession(), profile, "does_not_exist", new StringWriter());
188 private QProfileDto createProfile() {
189 return db.qualityProfiles().insert(p -> p.setLanguage(rule.getLanguage()));
192 public static class XooExporter extends ProfileExporter {
193 public XooExporter() {
194 super("xootool", "Xoo Tool");
198 public String[] getSupportedLanguages() {
199 return new String[] {"xoo"};
203 public String getMimeType() {
204 return "plain/custom";
208 public void exportProfile(RulesProfile profile, Writer writer) {
210 writer.write("xoo -> " + profile.getName() + " -> " + profile.getActiveRules().size());
211 } catch (IOException e) {
212 throw new IllegalStateException(e);
217 public static class StandardExporter extends ProfileExporter {
218 public StandardExporter() {
219 super("standard", "Standard");
223 public void exportProfile(RulesProfile profile, Writer writer) {
225 writer.write("standard -> " + profile.getName() + " -> " + profile.getActiveRules().size());
226 } catch (IOException e) {
227 throw new IllegalStateException(e);
232 public class XooProfileImporter extends ProfileImporter {
233 public XooProfileImporter() {
234 super("XooProfileImporter", "Xoo Profile Importer");
238 public String[] getSupportedLanguages() {
239 return new String[] {"xoo"};
243 public RulesProfile importProfile(Reader reader, ValidationMessages messages) {
244 RulesProfile rulesProfile = RulesProfile.create();
245 rulesProfile.activateRule(Rule.create(rule.getRepositoryKey(), rule.getRuleKey()), RulePriority.CRITICAL);
250 public static class XooProfileImporterWithMessages extends ProfileImporter {
251 public XooProfileImporterWithMessages() {
252 super("XooProfileImporterWithMessages", "Xoo Profile Importer With Message");
256 public String[] getSupportedLanguages() {
257 return new String[] {};
261 public RulesProfile importProfile(Reader reader, ValidationMessages messages) {
262 messages.addWarningText("a warning");
263 messages.addInfoText("an info");
264 return RulesProfile.create();
268 public static class XooProfileImporterWithError extends ProfileImporter {
269 public XooProfileImporterWithError() {
270 super("XooProfileImporterWithError", "Xoo Profile Importer With Error");
274 public RulesProfile importProfile(Reader reader, ValidationMessages messages) {
275 messages.addErrorText("error!");
276 return RulesProfile.create();