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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2023 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.hotspot.ws;
  21. import com.tngtech.java.junit.dataprovider.DataProvider;
  22. import com.tngtech.java.junit.dataprovider.DataProviderRunner;
  23. import com.tngtech.java.junit.dataprovider.UseDataProvider;
  24. import java.time.Clock;
  25. import java.util.List;
  26. import java.util.stream.IntStream;
  27. import org.junit.Rule;
  28. import org.junit.Test;
  29. import org.junit.runner.RunWith;
  30. import org.sonar.api.rule.RuleKey;
  31. import org.sonar.api.rule.RuleStatus;
  32. import org.sonar.api.rules.RuleType;
  33. import org.sonar.core.util.UuidFactoryFast;
  34. import org.sonar.db.DbClient;
  35. import org.sonar.db.DbTester;
  36. import org.sonar.db.component.ComponentDto;
  37. import org.sonar.db.component.ProjectData;
  38. import org.sonar.db.issue.IssueDto;
  39. import org.sonar.db.metric.MetricDto;
  40. import org.sonar.db.protobuf.DbIssues;
  41. import org.sonar.db.rule.RuleDto;
  42. import org.sonar.db.user.UserDto;
  43. import org.sonar.server.component.ComponentFinder;
  44. import org.sonar.server.component.TestComponentFinder;
  45. import org.sonar.server.exceptions.ForbiddenException;
  46. import org.sonar.server.issue.NewCodePeriodResolver;
  47. import org.sonar.server.issue.TextRangeResponseFormatter;
  48. import org.sonar.server.tester.UserSessionRule;
  49. import org.sonar.server.ws.MessageFormattingUtils;
  50. import org.sonar.server.ws.TestRequest;
  51. import org.sonar.server.ws.WsActionTester;
  52. import org.sonarqube.ws.Common;
  53. import org.sonarqube.ws.Hotspots;
  54. import static java.util.Arrays.asList;
  55. import static org.assertj.core.api.Assertions.assertThat;
  56. import static org.assertj.core.api.Assertions.assertThatThrownBy;
  57. import static org.assertj.core.api.AssertionsForClassTypes.tuple;
  58. import static org.sonar.api.issue.Issue.RESOLUTION_ACKNOWLEDGED;
  59. import static org.sonar.api.issue.Issue.RESOLUTION_FIXED;
  60. import static org.sonar.api.issue.Issue.RESOLUTION_SAFE;
  61. import static org.sonar.api.issue.Issue.RESOLUTION_WONT_FIX;
  62. import static org.sonar.api.issue.Issue.STATUS_RESOLVED;
  63. import static org.sonar.api.issue.Issue.STATUS_REVIEWED;
  64. import static org.sonar.api.issue.Issue.STATUS_TO_REVIEW;
  65. import static org.sonar.api.measures.CoreMetrics.ANALYSIS_FROM_SONARQUBE_9_4_KEY;
  66. import static org.sonar.api.utils.DateUtils.formatDateTime;
  67. import static org.sonar.api.utils.DateUtils.parseDate;
  68. import static org.sonar.api.utils.DateUtils.parseDateTime;
  69. import static org.sonar.db.component.ComponentTesting.newFileDto;
  70. import static org.sonar.db.newcodeperiod.NewCodePeriodType.REFERENCE_BRANCH;
  71. import static org.sonar.db.protobuf.DbIssues.MessageFormattingType.CODE;
  72. import static org.sonar.db.rule.RuleDescriptionSectionDto.createDefaultRuleDescriptionSection;
  73. import static org.sonar.db.rule.RuleTesting.XOO_X1;
  74. import static org.sonar.db.rule.RuleTesting.XOO_X2;
  75. import static org.sonar.db.rule.RuleTesting.newRule;
  76. import static org.sonar.server.tester.UserSessionRule.standalone;
  77. @RunWith(DataProviderRunner.class)
  78. public class ListActionIT {
  79. public static final DbIssues.MessageFormatting MESSAGE_FORMATTING = DbIssues.MessageFormatting.newBuilder()
  80. .setStart(0).setEnd(11).setType(CODE).build();
  81. private final UuidFactoryFast uuidFactory = UuidFactoryFast.getInstance();
  82. @Rule
  83. public UserSessionRule userSession = standalone();
  84. @Rule
  85. public DbTester db = DbTester.create();
  86. private final DbClient dbClient = db.getDbClient();
  87. private final TextRangeResponseFormatter textRangeResponseFormatter = new TextRangeResponseFormatter();
  88. private final HotspotWsResponseFormatter hotspotWsResponseFormatter = new HotspotWsResponseFormatter(textRangeResponseFormatter);
  89. private final ComponentFinder componentFinder = TestComponentFinder.from(db);
  90. private final WsActionTester ws = new WsActionTester(
  91. new ListAction(dbClient, userSession, hotspotWsResponseFormatter, new NewCodePeriodResolver(dbClient, Clock.systemUTC()), componentFinder));
  92. @Test
  93. public void whenNoProjectProvided_shouldFailWithMessage() {
  94. TestRequest request = ws.newRequest();
  95. assertThatThrownBy(() -> request.executeProtobuf(Hotspots.ListWsResponse.class))
  96. .isInstanceOf(IllegalArgumentException.class)
  97. .hasMessage("The 'project' parameter is missing");
  98. }
  99. @Test
  100. public void whenBranchAndPullRequestProvided_shouldFailWithMessage() {
  101. TestRequest request = ws.newRequest()
  102. .setParam("project", "some-project")
  103. .setParam("branch", "some-branch")
  104. .setParam("pullRequest", "some-pr");
  105. assertThatThrownBy(() -> request.executeProtobuf(Hotspots.ListWsResponse.class))
  106. .isInstanceOf(IllegalArgumentException.class)
  107. .hasMessage("Only one of parameters 'branch' and 'pullRequest' can be provided");
  108. }
  109. @Test
  110. public void whenAnonymousUser_shouldFailIfInsufficientPrivileges() {
  111. UserDto user = db.users().insertUser();
  112. ProjectData projectData = db.components().insertPrivateProject();
  113. ComponentDto project = projectData.getMainBranchComponent();
  114. ComponentDto file = db.components().insertComponent(newFileDto(project));
  115. UserDto simon = db.users().insertUser();
  116. RuleDto rule = newHotspotRule();
  117. db.issues().insertHotspot(rule, project, file, i -> i
  118. .setEffort(10L)
  119. .setLine(42)
  120. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  121. .setMessage("the message")
  122. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  123. .setStatus(STATUS_RESOLVED)
  124. .setResolution(RESOLUTION_FIXED)
  125. .setSeverity("MAJOR")
  126. .setAuthorLogin("John")
  127. .setAssigneeUuid(simon.getUuid())
  128. .setTags(asList("bug", "owasp"))
  129. .setIssueCreationDate(parseDate("2014-09-03"))
  130. .setIssueUpdateDate(parseDate("2017-12-04"))
  131. .setCodeVariants(List.of("variant1", "variant2")));
  132. userSession
  133. .logIn(user)
  134. .registerProjects(projectData.getProjectDto());
  135. TestRequest request = ws.newRequest()
  136. .setParam("project", projectData.projectKey())
  137. .setParam("branch", projectData.getMainBranchDto().getKey());
  138. assertThatThrownBy(() -> request.executeProtobuf(Hotspots.ListWsResponse.class))
  139. .isInstanceOf(ForbiddenException.class)
  140. .hasMessage("Insufficient privileges");
  141. }
  142. @Test
  143. public void whenListHotspotsByProject_shouldReturnAllFields() {
  144. UserDto user = db.users().insertUser();
  145. ProjectData projectData = db.components().insertPublicProject();
  146. ComponentDto project = projectData.getMainBranchComponent();
  147. ComponentDto file = db.components().insertComponent(newFileDto(project));
  148. UserDto simon = db.users().insertUser();
  149. RuleDto rule = newHotspotRule();
  150. IssueDto hotspot = db.issues().insertHotspot(rule, project, file, i -> i
  151. .setEffort(10L)
  152. .setLine(42)
  153. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  154. .setMessage("the message")
  155. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  156. .setStatus(STATUS_TO_REVIEW)
  157. .setResolution(null)
  158. .setSeverity("MAJOR")
  159. .setAuthorLogin("John")
  160. .setAssigneeUuid(simon.getUuid())
  161. .setTags(asList("bug", "owasp"))
  162. .setIssueCreationDate(parseDate("2014-09-03"))
  163. .setIssueUpdateDate(parseDate("2017-12-04")));
  164. ComponentDto anotherBranch = db.components().insertProjectBranch(project, b -> b.setKey("branch1"));
  165. ComponentDto fileFromAnotherBranch = db.components().insertComponent(newFileDto(anotherBranch));
  166. db.issues().insertHotspot(rule, anotherBranch, fileFromAnotherBranch, i -> i
  167. .setEffort(10L)
  168. .setLine(42)
  169. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  170. .setMessage("the message")
  171. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  172. .setStatus(STATUS_REVIEWED)
  173. .setResolution(RESOLUTION_FIXED)
  174. .setSeverity("MAJOR")
  175. .setAuthorLogin("John")
  176. .setAssigneeUuid(simon.getUuid())
  177. .setTags(asList("bug", "owasp"))
  178. .setIssueCreationDate(parseDate("2014-09-03"))
  179. .setIssueUpdateDate(parseDate("2017-12-04")));
  180. userSession
  181. .logIn(user)
  182. .registerProjects(projectData.getProjectDto());
  183. Hotspots.ListWsResponse response = ws.newRequest()
  184. .setParam("project", projectData.projectKey())
  185. .executeProtobuf(Hotspots.ListWsResponse.class);
  186. assertThat(response.getHotspotsList())
  187. .extracting(
  188. Hotspots.SearchWsResponse.Hotspot::getKey, Hotspots.SearchWsResponse.Hotspot::getRuleKey, Hotspots.SearchWsResponse.Hotspot::getSecurityCategory,
  189. Hotspots.SearchWsResponse.Hotspot::getComponent, Hotspots.SearchWsResponse.Hotspot::getResolution, Hotspots.SearchWsResponse.Hotspot::getStatus,
  190. Hotspots.SearchWsResponse.Hotspot::getMessage, Hotspots.SearchWsResponse.Hotspot::getMessageFormattingsList,
  191. Hotspots.SearchWsResponse.Hotspot::getAssignee, Hotspots.SearchWsResponse.Hotspot::getAuthor, Hotspots.SearchWsResponse.Hotspot::getLine,
  192. Hotspots.SearchWsResponse.Hotspot::getCreationDate, Hotspots.SearchWsResponse.Hotspot::getUpdateDate)
  193. .containsExactlyInAnyOrder(
  194. tuple(hotspot.getKey(), rule.getKey().toString(), "others", file.getKey(), "", STATUS_TO_REVIEW, "the message",
  195. MessageFormattingUtils.dbMessageFormattingListToWs(List.of(MESSAGE_FORMATTING)), simon.getUuid(), "John", 42,
  196. formatDateTime(hotspot.getIssueCreationDate()), formatDateTime(hotspot.getIssueUpdateDate())));
  197. }
  198. @Test
  199. public void whenListHotspotsByResolution_shouldReturnValidHotspots() {
  200. UserDto user = db.users().insertUser();
  201. ProjectData projectData = db.components().insertPublicProject();
  202. ComponentDto project = projectData.getMainBranchComponent();
  203. ComponentDto file = db.components().insertComponent(newFileDto(project));
  204. UserDto simon = db.users().insertUser();
  205. RuleDto rule = newHotspotRule();
  206. IssueDto hotspot1 = db.issues().insertHotspot(rule, project, file, i -> i
  207. .setEffort(10L)
  208. .setLine(42)
  209. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  210. .setMessage("the message")
  211. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  212. .setStatus(STATUS_REVIEWED)
  213. .setResolution(RESOLUTION_FIXED)
  214. .setSeverity("MAJOR")
  215. .setAuthorLogin("John")
  216. .setAssigneeUuid(simon.getUuid())
  217. .setTags(asList("bug", "owasp"))
  218. .setIssueCreationDate(parseDate("2014-09-03"))
  219. .setIssueUpdateDate(parseDate("2017-12-04")));
  220. IssueDto hotspot2 = db.issues().insertHotspot(rule, project, file, i -> i
  221. .setEffort(10L)
  222. .setLine(42)
  223. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  224. .setMessage("the message")
  225. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  226. .setStatus(STATUS_REVIEWED)
  227. .setResolution(RESOLUTION_FIXED)
  228. .setSeverity("MAJOR")
  229. .setAuthorLogin("John")
  230. .setAssigneeUuid(simon.getUuid())
  231. .setTags(asList("bug", "owasp"))
  232. .setIssueCreationDate(parseDate("2014-09-03"))
  233. .setIssueUpdateDate(parseDate("2017-12-04")));
  234. IssueDto hotspot3 = db.issues().insertHotspot(rule, project, file, i -> i
  235. .setEffort(10L)
  236. .setLine(42)
  237. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  238. .setMessage("the message")
  239. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  240. .setStatus(STATUS_REVIEWED)
  241. .setResolution(RESOLUTION_SAFE)
  242. .setSeverity("MAJOR")
  243. .setAuthorLogin("John")
  244. .setAssigneeUuid(simon.getUuid())
  245. .setTags(asList("bug", "owasp"))
  246. .setIssueCreationDate(parseDate("2014-09-03"))
  247. .setIssueUpdateDate(parseDate("2017-12-04")));
  248. RuleDto vulnerabilityRule = newIssueRule(XOO_X2, RuleType.VULNERABILITY);
  249. IssueDto vulnerabilityIssue = db.issues().insertIssue(vulnerabilityRule, project, file, i -> i
  250. .setType(RuleType.VULNERABILITY)
  251. .setEffort(10L)
  252. .setLine(42)
  253. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  254. .setMessage("the message")
  255. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  256. .setStatus(STATUS_RESOLVED)
  257. .setResolution(RESOLUTION_WONT_FIX)
  258. .setSeverity("MAJOR")
  259. .setAuthorLogin("John")
  260. .setAssigneeUuid(simon.getUuid())
  261. .setTags(asList("bug", "owasp"))
  262. .setIssueCreationDate(parseDate("2014-09-03"))
  263. .setIssueUpdateDate(parseDate("2017-12-04"))
  264. .setCodeVariants(List.of("variant1", "variant2")));
  265. userSession
  266. .logIn(user)
  267. .registerProjects(projectData.getProjectDto());
  268. Hotspots.ListWsResponse response = ws.newRequest()
  269. .setParam("project", projectData.getProjectDto().getKey())
  270. .setParam("branch", projectData.getMainBranchDto().getKey())
  271. .setParam("resolution", RESOLUTION_FIXED)
  272. .executeProtobuf(Hotspots.ListWsResponse.class);
  273. assertThat(response.getHotspotsList())
  274. .extracting(Hotspots.SearchWsResponse.Hotspot::getKey)
  275. .containsExactlyInAnyOrder(hotspot1.getKey(), hotspot2.getKey())
  276. .doesNotContain(hotspot3.getKey(), vulnerabilityIssue.getKey());
  277. response = ws.newRequest()
  278. .setParam("project", projectData.getProjectDto().getKey())
  279. .setParam("branch", projectData.getMainBranchDto().getKey())
  280. .setParam("resolution", RESOLUTION_SAFE)
  281. .executeProtobuf(Hotspots.ListWsResponse.class);
  282. assertThat(response.getHotspotsList())
  283. .extracting(Hotspots.SearchWsResponse.Hotspot::getKey)
  284. .containsExactlyInAnyOrder(hotspot3.getKey())
  285. .doesNotContain(hotspot1.getKey(), hotspot2.getKey(), vulnerabilityIssue.getKey());
  286. response = ws.newRequest()
  287. .setParam("project", projectData.getProjectDto().getKey())
  288. .setParam("branch", projectData.getMainBranchDto().getKey())
  289. .setParam("resolution", RESOLUTION_ACKNOWLEDGED)
  290. .executeProtobuf(Hotspots.ListWsResponse.class);
  291. assertThat(response.getHotspotsList()).isEmpty();
  292. }
  293. @Test
  294. public void whenListHotspotsByNewCodePeriodDate_shouldReturnHotspots() {
  295. UserDto user = db.users().insertUser();
  296. ProjectData projectData = db.components().insertPublicProject();
  297. ComponentDto project = projectData.getMainBranchComponent();
  298. ComponentDto file = db.components().insertComponent(newFileDto(project));
  299. UserDto simon = db.users().insertUser();
  300. RuleDto rule = newHotspotRule();
  301. db.components().insertSnapshot(project, s -> s.setLast(true).setPeriodDate(parseDateTime("2014-09-05T00:00:00+0100").getTime()));
  302. List<String> beforeNewCodePeriod = IntStream.range(0, 10).mapToObj(number -> db.issues().insertHotspot(rule, project, file, i -> i
  303. .setEffort(10L)
  304. .setLine(42)
  305. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  306. .setMessage("the message")
  307. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  308. .setStatus(STATUS_TO_REVIEW)
  309. .setResolution(null)
  310. .setSeverity("MAJOR")
  311. .setAuthorLogin("John")
  312. .setAssigneeUuid(simon.getUuid())
  313. .setTags(asList("bug", "owasp"))
  314. .setIssueCreationDate(parseDate("2014-09-03"))
  315. .setIssueUpdateDate(parseDate("2017-12-04"))
  316. .setCodeVariants(List.of("variant1", "variant2"))))
  317. .map(IssueDto::getKey)
  318. .toList();
  319. List<String> afterNewCodePeriod = IntStream.range(0, 5).mapToObj(number -> db.issues().insertHotspot(rule, project, file, i -> i
  320. .setEffort(10L)
  321. .setLine(42)
  322. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  323. .setMessage("the message")
  324. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  325. .setStatus(STATUS_TO_REVIEW)
  326. .setResolution(null)
  327. .setSeverity("MAJOR")
  328. .setAuthorLogin("John")
  329. .setAssigneeUuid(simon.getUuid())
  330. .setTags(asList("bug", "owasp"))
  331. .setIssueCreationDate(parseDate("2015-01-02"))
  332. .setIssueUpdateDate(parseDate("2017-12-04"))
  333. .setCodeVariants(List.of("variant1", "variant2"))))
  334. .map(IssueDto::getKey)
  335. .toList();
  336. userSession
  337. .logIn(user)
  338. .registerProjects(projectData.getProjectDto());
  339. Hotspots.ListWsResponse response = ws.newRequest()
  340. .setParam("project", projectData.projectKey())
  341. .setParam("branch", projectData.getMainBranchDto().getKey())
  342. .setParam("inNewCodePeriod", "true")
  343. .executeProtobuf(Hotspots.ListWsResponse.class);
  344. assertThat(response.getHotspotsList())
  345. .extracting(Hotspots.SearchWsResponse.Hotspot::getKey)
  346. .containsExactlyInAnyOrderElementsOf(afterNewCodePeriod)
  347. .doesNotContainAnyElementsOf(beforeNewCodePeriod);
  348. }
  349. @Test
  350. public void whenListHotspotsByNewCodePeriodReferenceBranch_shouldReturnHotspots() {
  351. UserDto user = db.users().insertUser();
  352. ProjectData projectData = db.components().insertPublicProject();
  353. ComponentDto project = projectData.getMainBranchComponent();
  354. ComponentDto file = db.components().insertComponent(newFileDto(project));
  355. UserDto simon = db.users().insertUser();
  356. RuleDto rule = newHotspotRule();
  357. db.components().insertSnapshot(project, s -> s.setLast(true).setPeriodMode(REFERENCE_BRANCH.name()));
  358. MetricDto metric = db.measures().insertMetric(metricDto -> metricDto.setKey(ANALYSIS_FROM_SONARQUBE_9_4_KEY));
  359. db.measures().insertLiveMeasure(project, metric);
  360. List<String> beforeNewCodePeriod = IntStream.range(0, 10).mapToObj(number -> db.issues().insertHotspot(rule, project, file, i -> i
  361. .setEffort(10L)
  362. .setLine(42)
  363. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  364. .setMessage("the message")
  365. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  366. .setStatus(STATUS_TO_REVIEW)
  367. .setResolution(null)
  368. .setSeverity("MAJOR")
  369. .setAuthorLogin("John")
  370. .setAssigneeUuid(simon.getUuid())
  371. .setTags(asList("bug", "owasp"))
  372. .setIssueCreationDate(parseDate("2014-09-03"))
  373. .setIssueUpdateDate(parseDate("2017-12-04"))
  374. .setCodeVariants(List.of("variant1", "variant2"))))
  375. .map(IssueDto::getKey)
  376. .toList();
  377. List<String> afterNewCodePeriod = IntStream.range(0, 5).mapToObj(number -> db.issues().insertHotspot(rule, project, file, i -> i
  378. .setEffort(10L)
  379. .setLine(42)
  380. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  381. .setMessage("the message")
  382. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  383. .setStatus(STATUS_TO_REVIEW)
  384. .setResolution(null)
  385. .setSeverity("MAJOR")
  386. .setAuthorLogin("John")
  387. .setAssigneeUuid(simon.getUuid())
  388. .setTags(asList("bug", "owasp"))
  389. .setIssueCreationDate(parseDate("2015-01-02"))
  390. .setIssueUpdateDate(parseDate("2017-12-04"))
  391. .setCodeVariants(List.of("variant1", "variant2"))))
  392. .peek(issueDto -> db.issues().insertNewCodeReferenceIssue(issueDto))
  393. .map(IssueDto::getKey)
  394. .toList();
  395. userSession
  396. .logIn(user)
  397. .registerProjects(projectData.getProjectDto());
  398. Hotspots.ListWsResponse response = ws.newRequest()
  399. .setParam("project", projectData.projectKey())
  400. .setParam("branch", projectData.getMainBranchDto().getKey())
  401. .setParam("inNewCodePeriod", "true")
  402. .executeProtobuf(Hotspots.ListWsResponse.class);
  403. assertThat(response.getHotspotsList())
  404. .extracting(Hotspots.SearchWsResponse.Hotspot::getKey)
  405. .containsExactlyInAnyOrderElementsOf(afterNewCodePeriod)
  406. .doesNotContainAnyElementsOf(beforeNewCodePeriod);
  407. }
  408. @Test
  409. @UseDataProvider("pages")
  410. public void whenUsingPagination_shouldReturnPaginatedResults(String page, int expectedNumberOfIssues) {
  411. UserDto user = db.users().insertUser();
  412. ProjectData projectData = db.components().insertPublicProject();
  413. ComponentDto project = projectData.getMainBranchComponent();
  414. ComponentDto file = db.components().insertComponent(newFileDto(project));
  415. UserDto simon = db.users().insertUser();
  416. RuleDto rule = newHotspotRule();
  417. IntStream.range(0, 10).forEach(number -> db.issues().insertHotspot(rule, project, file, i -> i
  418. .setEffort(10L)
  419. .setLine(42)
  420. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  421. .setMessage("the message")
  422. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  423. .setStatus(STATUS_TO_REVIEW)
  424. .setResolution(null)
  425. .setSeverity("MAJOR")
  426. .setAuthorLogin("John")
  427. .setAssigneeUuid(simon.getUuid())
  428. .setTags(asList("bug", "owasp"))
  429. .setIssueCreationDate(parseDate("2014-09-03"))
  430. .setIssueUpdateDate(parseDate("2017-12-04"))
  431. .setCodeVariants(List.of("variant1", "variant2"))));
  432. userSession
  433. .logIn(user)
  434. .registerProjects(projectData.getProjectDto());
  435. Hotspots.ListWsResponse response = ws.newRequest()
  436. .setParam("project", projectData.projectKey())
  437. .setParam("branch", projectData.getMainBranchDto().getKey())
  438. .setParam("p", page)
  439. .setParam("ps", "3")
  440. .executeProtobuf(Hotspots.ListWsResponse.class);
  441. assertThat(response.getHotspotsList()).hasSize(expectedNumberOfIssues);
  442. assertThat(response.getPaging())
  443. .extracting(Common.Paging::getPageIndex, Common.Paging::getPageSize, Common.Paging::getTotal)
  444. .containsExactly(Integer.parseInt(page), expectedNumberOfIssues, 0);
  445. }
  446. private RuleDto newHotspotRule() {
  447. return newIssueRule(XOO_X1, RuleType.SECURITY_HOTSPOT);
  448. }
  449. private RuleDto newIssueRule(RuleKey ruleKey, RuleType ruleType) {
  450. RuleDto rule = newRule(ruleKey, createDefaultRuleDescriptionSection(uuidFactory.create(), "Rule desc"))
  451. .setLanguage("xoo")
  452. .setName("Rule name")
  453. .setType(ruleType)
  454. .setStatus(RuleStatus.READY);
  455. db.rules().insert(rule);
  456. return rule;
  457. }
  458. @DataProvider
  459. public static Object[][] pages() {
  460. return new Object[][] {
  461. {"1", 3},
  462. {"2", 3},
  463. {"3", 3},
  464. {"4", 1},
  465. };
  466. }
  467. }