You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

QProfileExportersTest.java 10.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  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;
  21. import java.io.IOException;
  22. import java.io.Reader;
  23. import java.io.StringWriter;
  24. import java.io.Writer;
  25. import java.util.Collection;
  26. import org.junit.Before;
  27. import org.junit.Test;
  28. import org.junit.rules.ExpectedException;
  29. import org.mockito.ArgumentCaptor;
  30. import org.sonar.api.profiles.ProfileExporter;
  31. import org.sonar.api.profiles.ProfileImporter;
  32. import org.sonar.api.profiles.RulesProfile;
  33. import org.sonar.api.rules.Rule;
  34. import org.sonar.api.rules.RuleFinder;
  35. import org.sonar.api.rules.RulePriority;
  36. import org.sonar.api.utils.System2;
  37. import org.sonar.api.utils.ValidationMessages;
  38. import org.sonar.api.utils.internal.AlwaysIncreasingSystem2;
  39. import org.sonar.db.DbSession;
  40. import org.sonar.db.DbTester;
  41. import org.sonar.db.qualityprofile.QProfileDto;
  42. import org.sonar.db.rule.RuleDefinitionDto;
  43. import org.sonar.server.exceptions.BadRequestException;
  44. import org.sonar.server.exceptions.NotFoundException;
  45. import org.sonar.server.organization.DefaultOrganizationProvider;
  46. import org.sonar.server.organization.TestDefaultOrganizationProvider;
  47. import org.sonar.server.rule.DefaultRuleFinder;
  48. import org.sonar.server.tester.UserSessionRule;
  49. import static java.nio.charset.StandardCharsets.UTF_8;
  50. import static org.apache.commons.io.IOUtils.toInputStream;
  51. import static org.assertj.core.api.Assertions.assertThat;
  52. import static org.junit.Assert.fail;
  53. import static org.mockito.ArgumentMatchers.any;
  54. import static org.mockito.Mockito.mock;
  55. import static org.mockito.Mockito.verify;
  56. public class QProfileExportersTest {
  57. @org.junit.Rule
  58. public UserSessionRule userSessionRule = UserSessionRule.standalone();
  59. private System2 system2 = new AlwaysIncreasingSystem2();
  60. @org.junit.Rule
  61. public ExpectedException expectedException = ExpectedException.none();
  62. @org.junit.Rule
  63. public DbTester db = DbTester.create(system2);
  64. public DefaultOrganizationProvider defaultOrganizationProvider = TestDefaultOrganizationProvider.from(db);
  65. private RuleFinder ruleFinder = new DefaultRuleFinder(db.getDbClient(), defaultOrganizationProvider);
  66. private ProfileExporter[] exporters = new ProfileExporter[] {
  67. new StandardExporter(), new XooExporter()};
  68. private ProfileImporter[] importers = new ProfileImporter[] {
  69. new XooProfileImporter(), new XooProfileImporterWithMessages(), new XooProfileImporterWithError()};
  70. private RuleDefinitionDto rule;
  71. private QProfileRules qProfileRules = mock(QProfileRules.class);
  72. private QProfileExporters underTest = new QProfileExporters(db.getDbClient(), ruleFinder, qProfileRules, exporters, importers);
  73. @Before
  74. public void setUp() {
  75. rule = db.rules().insert(r -> r.setLanguage("xoo").setRepositoryKey("SonarXoo").setRuleKey("R1"));
  76. }
  77. @Test
  78. public void exportersForLanguage() {
  79. assertThat(underTest.exportersForLanguage("xoo")).hasSize(2);
  80. assertThat(underTest.exportersForLanguage("java")).hasSize(1);
  81. assertThat(underTest.exportersForLanguage("java").get(0)).isInstanceOf(StandardExporter.class);
  82. }
  83. @Test
  84. public void mimeType() {
  85. assertThat(underTest.mimeType("xootool")).isEqualTo("plain/custom");
  86. // default mime type
  87. assertThat(underTest.mimeType("standard")).isEqualTo("text/plain");
  88. }
  89. @Test
  90. public void import_xml() {
  91. QProfileDto profile = createProfile();
  92. underTest.importXml(profile, "XooProfileImporter", toInputStream("<xml/>", UTF_8), db.getSession());
  93. ArgumentCaptor<QProfileDto> profileCapture = ArgumentCaptor.forClass(QProfileDto.class);
  94. Class<Collection<RuleActivation>> collectionClass = (Class<Collection<RuleActivation>>) (Class) Collection.class;
  95. ArgumentCaptor<Collection<RuleActivation>> activationCapture = ArgumentCaptor.forClass(collectionClass);
  96. verify(qProfileRules).activateAndCommit(any(DbSession.class), profileCapture.capture(), activationCapture.capture());
  97. assertThat(profileCapture.getValue().getKee()).isEqualTo(profile.getKee());
  98. Collection<RuleActivation> activations = activationCapture.getValue();
  99. assertThat(activations).hasSize(1);
  100. RuleActivation activation = activations.iterator().next();
  101. assertThat(activation.getRuleId()).isEqualTo(rule.getId());
  102. assertThat(activation.getSeverity()).isEqualTo("CRITICAL");
  103. }
  104. @Test
  105. public void import_xml_return_messages() {
  106. QProfileDto profile = createProfile();
  107. QProfileResult result = underTest.importXml(profile, "XooProfileImporterWithMessages", toInputStream("<xml/>", UTF_8), db.getSession());
  108. assertThat(result.infos()).containsOnly("an info");
  109. assertThat(result.warnings()).containsOnly("a warning");
  110. }
  111. @Test
  112. public void fail_to_import_xml_when_error_in_importer() {
  113. try {
  114. underTest.importXml(QProfileTesting.newXooP1("org-123"), "XooProfileImporterWithError", toInputStream("<xml/>", UTF_8), db.getSession());
  115. fail();
  116. } catch (BadRequestException e) {
  117. assertThat(e).hasMessage("error!");
  118. }
  119. }
  120. @Test
  121. public void fail_to_import_xml_on_unknown_importer() {
  122. try {
  123. underTest.importXml(QProfileTesting.newXooP1("org-123"), "Unknown", toInputStream("<xml/>", UTF_8), db.getSession());
  124. fail();
  125. } catch (BadRequestException e) {
  126. assertThat(e).hasMessage("No such importer : Unknown");
  127. }
  128. }
  129. @Test
  130. public void export_empty_profile() {
  131. QProfileDto profile = createProfile();
  132. StringWriter writer = new StringWriter();
  133. underTest.export(db.getSession(), profile, "standard", writer);
  134. assertThat(writer.toString()).isEqualTo("standard -> " + profile.getName() + " -> 0");
  135. writer = new StringWriter();
  136. underTest.export(db.getSession(), profile, "xootool", writer);
  137. assertThat(writer.toString()).isEqualTo("xoo -> " + profile.getName() + " -> 0");
  138. }
  139. @Test
  140. public void export_profile() {
  141. QProfileDto profile = createProfile();
  142. db.qualityProfiles().activateRule(profile, rule);
  143. StringWriter writer = new StringWriter();
  144. underTest.export(db.getSession(), profile, "standard", writer);
  145. assertThat(writer.toString()).isEqualTo("standard -> " + profile.getName() + " -> 1");
  146. writer = new StringWriter();
  147. underTest.export(db.getSession(), profile, "xootool", writer);
  148. assertThat(writer.toString()).isEqualTo("xoo -> " + profile.getName() + " -> 1");
  149. }
  150. @Test
  151. public void export_throws_NotFoundException_if_exporter_does_not_exist() {
  152. QProfileDto profile = createProfile();
  153. expectedException.expect(NotFoundException.class);
  154. expectedException.expectMessage("Unknown quality profile exporter: does_not_exist");
  155. underTest.export(db.getSession(), profile, "does_not_exist", new StringWriter());
  156. }
  157. private QProfileDto createProfile() {
  158. return db.qualityProfiles().insert(db.getDefaultOrganization(), p -> p.setLanguage(rule.getLanguage()));
  159. }
  160. public static class XooExporter extends ProfileExporter {
  161. public XooExporter() {
  162. super("xootool", "Xoo Tool");
  163. }
  164. @Override
  165. public String[] getSupportedLanguages() {
  166. return new String[] {"xoo"};
  167. }
  168. @Override
  169. public String getMimeType() {
  170. return "plain/custom";
  171. }
  172. @Override
  173. public void exportProfile(RulesProfile profile, Writer writer) {
  174. try {
  175. writer.write("xoo -> " + profile.getName() + " -> " + profile.getActiveRules().size());
  176. } catch (IOException e) {
  177. throw new IllegalStateException(e);
  178. }
  179. }
  180. }
  181. public static class StandardExporter extends ProfileExporter {
  182. public StandardExporter() {
  183. super("standard", "Standard");
  184. }
  185. @Override
  186. public void exportProfile(RulesProfile profile, Writer writer) {
  187. try {
  188. writer.write("standard -> " + profile.getName() + " -> " + profile.getActiveRules().size());
  189. } catch (IOException e) {
  190. throw new IllegalStateException(e);
  191. }
  192. }
  193. }
  194. public class XooProfileImporter extends ProfileImporter {
  195. public XooProfileImporter() {
  196. super("XooProfileImporter", "Xoo Profile Importer");
  197. }
  198. @Override
  199. public String[] getSupportedLanguages() {
  200. return new String[] {"xoo"};
  201. }
  202. @Override
  203. public RulesProfile importProfile(Reader reader, ValidationMessages messages) {
  204. RulesProfile rulesProfile = RulesProfile.create();
  205. rulesProfile.activateRule(Rule.create(rule.getRepositoryKey(), rule.getRuleKey()), RulePriority.CRITICAL);
  206. return rulesProfile;
  207. }
  208. }
  209. public static class XooProfileImporterWithMessages extends ProfileImporter {
  210. public XooProfileImporterWithMessages() {
  211. super("XooProfileImporterWithMessages", "Xoo Profile Importer With Message");
  212. }
  213. @Override
  214. public String[] getSupportedLanguages() {
  215. return new String[] {};
  216. }
  217. @Override
  218. public RulesProfile importProfile(Reader reader, ValidationMessages messages) {
  219. messages.addWarningText("a warning");
  220. messages.addInfoText("an info");
  221. return RulesProfile.create();
  222. }
  223. }
  224. public static class XooProfileImporterWithError extends ProfileImporter {
  225. public XooProfileImporterWithError() {
  226. super("XooProfileImporterWithError", "Xoo Profile Importer With Error");
  227. }
  228. @Override
  229. public RulesProfile importProfile(Reader reader, ValidationMessages messages) {
  230. messages.addErrorText("error!");
  231. return RulesProfile.create();
  232. }
  233. }
  234. }