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.

IssueJsonReportTest.java 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2017 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 it.analysis;
  21. import com.sonar.orchestrator.Orchestrator;
  22. import com.sonar.orchestrator.build.BuildResult;
  23. import com.sonar.orchestrator.build.SonarScanner;
  24. import com.sonar.orchestrator.locator.FileLocation;
  25. import com.sonar.orchestrator.locator.ResourceLocation;
  26. import it.Category3Suite;
  27. import java.io.File;
  28. import java.io.FileNotFoundException;
  29. import java.io.IOException;
  30. import java.io.InputStream;
  31. import java.util.ArrayList;
  32. import java.util.List;
  33. import java.util.regex.Pattern;
  34. import org.apache.commons.io.FileUtils;
  35. import org.apache.commons.io.IOUtils;
  36. import org.json.simple.JSONArray;
  37. import org.json.simple.JSONObject;
  38. import org.junit.Before;
  39. import org.junit.ClassRule;
  40. import org.junit.Rule;
  41. import org.junit.Test;
  42. import org.junit.rules.TemporaryFolder;
  43. import org.skyscreamer.jsonassert.JSONAssert;
  44. import util.ItUtils;
  45. import static org.assertj.core.api.Assertions.assertThat;
  46. public class IssueJsonReportTest {
  47. private static final String SONAR_VERSION_PLACEHOLDER = "<SONAR_VERSION>";
  48. @ClassRule
  49. public static Orchestrator orchestrator = Category3Suite.ORCHESTRATOR;
  50. @Rule
  51. public TemporaryFolder temp = new TemporaryFolder();
  52. @Before
  53. public void resetData() {
  54. orchestrator.resetData();
  55. }
  56. @Test
  57. public void issue_line() throws IOException {
  58. orchestrator.getServer().restoreProfile(getResource("one-issue-per-line.xml"));
  59. orchestrator.getServer().provisionProject("sample", "xoo-sample");
  60. orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line");
  61. File projectDir = ItUtils.projectDir("shared/xoo-sample");
  62. SonarScanner runner = SonarScanner.create(projectDir,
  63. "sonar.analysis.mode", "issues",
  64. "sonar.verbose", "true",
  65. "sonar.report.export.path", "sonar-report.json");
  66. BuildResult result = orchestrator.executeBuild(runner);
  67. assertThat(ItUtils.countIssuesInJsonReport(result, true)).isEqualTo(17);
  68. JSONObject obj = ItUtils.getJSONReport(result);
  69. JSONArray issues = (JSONArray) obj.get("issues");
  70. for (Object issue : issues) {
  71. JSONObject jsonIssue = (JSONObject) issue;
  72. assertThat(jsonIssue.get("startLine")).isNotNull();
  73. assertThat(jsonIssue.get("line")).isEqualTo(jsonIssue.get("startLine"));
  74. assertThat(jsonIssue.get("endLine")).isEqualTo(jsonIssue.get("startLine"));
  75. assertThat(jsonIssue.get("endOffset")).isNotNull();
  76. assertThat(jsonIssue.get("startOffset")).isNotNull();
  77. }
  78. List<Long> lineNumbers = new ArrayList<>(16);
  79. for (long i = 1L; i < 18; i++) {
  80. lineNumbers.add(i);
  81. }
  82. assertThat(issues).extracting("startLine").containsAll(lineNumbers);
  83. assertThat(issues).extracting("endLine").containsAll(lineNumbers);
  84. }
  85. @Test
  86. public void precise_issue_location() throws IOException {
  87. orchestrator.getServer().restoreProfile(getResource("multiline.xml"));
  88. orchestrator.getServer().provisionProject("sample-multiline", "xoo-sample");
  89. orchestrator.getServer().associateProjectToQualityProfile("sample-multiline", "xoo", "multiline");
  90. File projectDir = ItUtils.projectDir("shared/xoo-precise-issues");
  91. SonarScanner runner = SonarScanner.create(projectDir,
  92. "sonar.analysis.mode", "issues",
  93. "sonar.verbose", "true",
  94. "sonar.report.export.path", "sonar-report.json");
  95. BuildResult result = orchestrator.executeBuild(runner);
  96. assertThat(ItUtils.countIssuesInJsonReport(result, true)).isEqualTo(2);
  97. JSONObject obj = ItUtils.getJSONReport(result);
  98. JSONArray issues = (JSONArray) obj.get("issues");
  99. JSONObject issue1 = (JSONObject) issues.get(0);
  100. JSONObject issue2 = (JSONObject) issues.get(1);
  101. assertThat(issue1.get("startLine")).isIn(6L);
  102. assertThat(issue1.get("line")).isIn(6L);
  103. assertThat(issue1.get("endLine")).isIn(6L);
  104. assertThat(issue1.get("startOffset")).isIn(27L);
  105. assertThat(issue1.get("endOffset")).isIn(32L);
  106. assertThat(issue2.get("startLine")).isIn(9L);
  107. assertThat(issue2.get("line")).isIn(9L);
  108. assertThat(issue2.get("endLine")).isIn(15L);
  109. assertThat(issue2.get("startOffset")).isIn(20L);
  110. assertThat(issue2.get("endOffset")).isIn(2L);
  111. }
  112. @Test
  113. public void test_json_report_no_server_analysis() throws Exception {
  114. orchestrator.getServer().restoreProfile(getResource("one-issue-per-line.xml"));
  115. orchestrator.getServer().provisionProject("sample", "tracking");
  116. orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line");
  117. File projectDir = ItUtils.projectDir("analysis/tracking/v1");
  118. SonarScanner issuesModeScan = SonarScanner.create(projectDir)
  119. .setProperty("sonar.analysis.mode", "issues")
  120. .setProperty("sonar.userHome", temp.newFolder().getAbsolutePath())
  121. .setProperty("sonar.report.export.path", "sonar-report.json")
  122. .setProperty("sonar.projectDate", "2013-05-02");
  123. orchestrator.executeBuild(issuesModeScan);
  124. File report = new File(projectDir, ".sonar/sonar-report.json");
  125. assertThat(report).isFile().exists();
  126. String json = sanitize(FileUtils.readFileToString(report));
  127. String expectedJson = expected("no-server-analysis.json");
  128. JSONAssert.assertEquals(expectedJson, json, false);
  129. }
  130. @Test
  131. public void test_json_report() throws Exception {
  132. orchestrator.getServer().restoreProfile(getResource("one-issue-per-line.xml"));
  133. orchestrator.getServer().provisionProject("sample", "tracking");
  134. orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line");
  135. SonarScanner scan = SonarScanner.create(ItUtils.projectDir("analysis/tracking/v1"))
  136. .setProperty("sonar.projectDate", "2013-05-01");
  137. orchestrator.executeBuild(scan);
  138. // Issues mode scan -> 2 new issues and 13 existing issues
  139. File projectDir = ItUtils.projectDir("analysis/tracking/v2");
  140. SonarScanner issuesModeScan = SonarScanner.create(projectDir)
  141. .setProperty("sonar.analysis.mode", "issues")
  142. .setProperty("sonar.userHome", temp.newFolder().getAbsolutePath())
  143. .setProperty("sonar.report.export.path", "sonar-report.json")
  144. .setProperty("sonar.projectDate", "2013-05-02");
  145. orchestrator.executeBuild(issuesModeScan);
  146. File report = new File(projectDir, ".sonar/sonar-report.json");
  147. assertThat(report).isFile().exists();
  148. String json = sanitize(FileUtils.readFileToString(report));
  149. String expectedJson = expected("report-on-single-module.json");
  150. JSONAssert.assertEquals(expectedJson, json, false);
  151. }
  152. @Test
  153. public void test_json_report_on_branch() throws Exception {
  154. orchestrator.getServer().restoreProfile(getResource("one-issue-per-line.xml"));
  155. orchestrator.getServer().provisionProject("sample:mybranch", "Sample");
  156. orchestrator.getServer().associateProjectToQualityProfile("sample:mybranch", "xoo", "one-issue-per-line");
  157. SonarScanner scan = SonarScanner.create(ItUtils.projectDir("analysis/tracking/v1"))
  158. .setProperty("sonar.projectDate", "2013-05-01")
  159. .setProperty("sonar.branch", "mybranch");
  160. orchestrator.executeBuild(scan);
  161. // issues mode scan -> 2 new issues and 13 existing issues
  162. File projectDir = ItUtils.projectDir("analysis/tracking/v2");
  163. SonarScanner issuesModeScan = SonarScanner.create(projectDir)
  164. .setProperty("sonar.analysis.mode", "issues")
  165. .setProperty("sonar.userHome", temp.newFolder().getAbsolutePath())
  166. .setProperty("sonar.report.export.path", "sonar-report.json")
  167. .setProperty("sonar.issuesReport.console.enable", "true")
  168. .setProperty("sonar.projectDate", "2013-05-02")
  169. .setProperty("sonar.verbose", "true")
  170. .setProperty("sonar.branch", "mybranch");
  171. orchestrator.executeBuild(issuesModeScan);
  172. File report = new File(projectDir, ".sonar/sonar-report.json");
  173. assertThat(report).isFile().exists();
  174. String json = sanitize(FileUtils.readFileToString(report));
  175. String expectedJson = expected("report-on-single-module-branch.json");
  176. JSONAssert.assertEquals(expectedJson, json, false);
  177. }
  178. /**
  179. * Multi-modules project but Eclipse scans only a single module
  180. */
  181. @Test
  182. public void test_json_report_on_sub_module() throws Exception {
  183. orchestrator.getServer().restoreProfile(getResource("one-issue-per-line.xml"));
  184. orchestrator.getServer().provisionProject("com.sonarsource.it.samples:multi-modules-sample", "Multi-module sample");
  185. orchestrator.getServer().associateProjectToQualityProfile("com.sonarsource.it.samples:multi-modules-sample", "xoo", "one-issue-per-line");
  186. File rootDir = ItUtils.projectDir("shared/xoo-multi-modules-sample");
  187. SonarScanner scan = SonarScanner.create(rootDir)
  188. .setProperty("sonar.projectDate", "2013-05-01");
  189. orchestrator.executeBuild(scan);
  190. // Issues mode scan on a module -> no new issues
  191. File moduleDir = ItUtils.projectDir("shared/xoo-multi-modules-sample/module_a/module_a1");
  192. SonarScanner issuesModeScan = SonarScanner.create(moduleDir)
  193. .setProperty("sonar.projectKey", "com.sonarsource.it.samples:multi-modules-sample:module_a:module_a1")
  194. .setProperty("sonar.projectVersion", "1.0-SNAPSHOT")
  195. .setProperty("sonar.projectName", "ModuleA1")
  196. .setProperty("sonar.sources", "src/main/xoo")
  197. .setProperty("sonar.language", "xoo")
  198. .setProperty("sonar.analysis.mode", "issues")
  199. .setProperty("sonar.userHome", temp.newFolder().getAbsolutePath())
  200. .setProperty("sonar.report.export.path", "sonar-report.json")
  201. .setProperty("sonar.projectDate", "2013-05-02");
  202. orchestrator.executeBuild(issuesModeScan);
  203. File report = new File(moduleDir, ".sonar/sonar-report.json");
  204. assertThat(report).isFile().exists();
  205. String json = sanitize(FileUtils.readFileToString(report));
  206. // SONAR-5218 All issues are updated as their root project id has changed (it's now the sub module)
  207. String expectedJson = expected("report-on-sub-module.json");
  208. JSONAssert.assertEquals(expectedJson, json, false);
  209. }
  210. /**
  211. * Multi-modules project
  212. */
  213. @Test
  214. public void test_json_report_on_root_module() throws Exception {
  215. orchestrator.getServer().restoreProfile(getResource("/one-issue-per-line.xml"));
  216. orchestrator.getServer().provisionProject("com.sonarsource.it.samples:multi-modules-sample", "Sonar :: Integration Tests :: Multi-modules Sample");
  217. orchestrator.getServer().associateProjectToQualityProfile("com.sonarsource.it.samples:multi-modules-sample", "xoo", "one-issue-per-line");
  218. File rootDir = ItUtils.projectDir("shared/xoo-multi-modules-sample");
  219. SonarScanner scan = SonarScanner.create(rootDir)
  220. .setProperty("sonar.projectDate", "2013-05-01");
  221. orchestrator.executeBuild(scan);
  222. // issues mode scan -> no new issues
  223. SonarScanner issuesModeScan = SonarScanner.create(rootDir)
  224. .setProperty("sonar.analysis.mode", "issues")
  225. .setProperty("sonar.userHome", temp.newFolder().getAbsolutePath())
  226. .setProperty("sonar.report.export.path", "sonar-report.json")
  227. .setProperty("sonar.projectDate", "2013-05-02");
  228. orchestrator.executeBuild(issuesModeScan);
  229. File report = new File(rootDir, ".sonar/sonar-report.json");
  230. assertThat(report).isFile().exists();
  231. String json = sanitize(FileUtils.readFileToString(report));
  232. String expectedJson = expected("report-on-root-module.json");
  233. JSONAssert.assertEquals(expectedJson, json, false);
  234. }
  235. private String expected(String path) throws IOException, FileNotFoundException {
  236. return sanitize(IOUtils.toString(getResourceInputStream(path)))
  237. .replaceAll(Pattern.quote(SONAR_VERSION_PLACEHOLDER), orchestrator.getServer().version().toString());
  238. }
  239. @Test
  240. public void issueSanityCheck() {
  241. assertThat(sanitize("s\"0150F1EBDB8E000003\"f")).isEqualTo("s<ISSUE_KEY>f");
  242. }
  243. private static String sanitize(String s) {
  244. // sanitize issue uuid keys
  245. s = s.replaceAll("\"[a-zA-Z_0-9\\-]{15,20}\"", "<ISSUE_KEY>");
  246. return ItUtils.sanitizeTimezones(s);
  247. }
  248. private InputStream getResourceInputStream(String resource) throws FileNotFoundException {
  249. ResourceLocation res = getResource(resource);
  250. return getClass().getResourceAsStream(res.getPath());
  251. }
  252. private ResourceLocation getResource(String resource) {
  253. return FileLocation.ofClasspath("/analysis/IssueJsonReportTest/" + resource);
  254. }
  255. }