Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

ListActionIT.java 31KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  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.issue.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.Before;
  28. import org.junit.Rule;
  29. import org.junit.Test;
  30. import org.junit.runner.RunWith;
  31. import org.sonar.api.resources.Languages;
  32. import org.sonar.api.rule.RuleKey;
  33. import org.sonar.api.rule.RuleStatus;
  34. import org.sonar.api.rules.RuleType;
  35. import org.sonar.api.utils.Durations;
  36. import org.sonar.core.util.UuidFactoryFast;
  37. import org.sonar.db.DbClient;
  38. import org.sonar.db.DbTester;
  39. import org.sonar.db.component.BranchType;
  40. import org.sonar.db.component.ComponentDto;
  41. import org.sonar.db.component.ProjectData;
  42. import org.sonar.db.issue.IssueDto;
  43. import org.sonar.db.metric.MetricDto;
  44. import org.sonar.db.protobuf.DbIssues;
  45. import org.sonar.db.rule.RuleDto;
  46. import org.sonar.db.user.UserDto;
  47. import org.sonar.server.component.ComponentFinder;
  48. import org.sonar.server.component.TestComponentFinder;
  49. import org.sonar.server.exceptions.ForbiddenException;
  50. import org.sonar.server.issue.AvatarResolverImpl;
  51. import org.sonar.server.issue.IssueFieldsSetter;
  52. import org.sonar.server.issue.TextRangeResponseFormatter;
  53. import org.sonar.server.issue.TransitionService;
  54. import org.sonar.server.issue.workflow.FunctionExecutor;
  55. import org.sonar.server.issue.workflow.IssueWorkflow;
  56. import org.sonar.server.tester.UserSessionRule;
  57. import org.sonar.server.ws.MessageFormattingUtils;
  58. import org.sonar.server.ws.TestRequest;
  59. import org.sonar.server.ws.WsActionTester;
  60. import org.sonarqube.ws.Common.Severity;
  61. import org.sonarqube.ws.Issues;
  62. import org.sonarqube.ws.Issues.Issue;
  63. import static java.util.Arrays.asList;
  64. import static org.assertj.core.api.Assertions.assertThat;
  65. import static org.assertj.core.api.Assertions.assertThatThrownBy;
  66. import static org.assertj.core.groups.Tuple.tuple;
  67. import static org.sonar.api.issue.Issue.RESOLUTION_FIXED;
  68. import static org.sonar.api.issue.Issue.RESOLUTION_WONT_FIX;
  69. import static org.sonar.api.issue.Issue.STATUS_CLOSED;
  70. import static org.sonar.api.issue.Issue.STATUS_OPEN;
  71. import static org.sonar.api.issue.Issue.STATUS_RESOLVED;
  72. import static org.sonar.api.measures.CoreMetrics.ANALYSIS_FROM_SONARQUBE_9_4_KEY;
  73. import static org.sonar.api.utils.DateUtils.formatDateTime;
  74. import static org.sonar.api.utils.DateUtils.parseDate;
  75. import static org.sonar.api.utils.DateUtils.parseDateTime;
  76. import static org.sonar.db.component.ComponentTesting.newFileDto;
  77. import static org.sonar.db.newcodeperiod.NewCodePeriodType.REFERENCE_BRANCH;
  78. import static org.sonar.db.protobuf.DbIssues.MessageFormattingType.CODE;
  79. import static org.sonar.db.rule.RuleDescriptionSectionDto.createDefaultRuleDescriptionSection;
  80. import static org.sonar.db.rule.RuleTesting.XOO_X1;
  81. import static org.sonar.db.rule.RuleTesting.XOO_X2;
  82. import static org.sonar.db.rule.RuleTesting.newRule;
  83. import static org.sonar.server.tester.UserSessionRule.standalone;
  84. @RunWith(DataProviderRunner.class)
  85. public class ListActionIT {
  86. public static final DbIssues.MessageFormatting MESSAGE_FORMATTING = DbIssues.MessageFormatting.newBuilder()
  87. .setStart(0).setEnd(11).setType(CODE).build();
  88. private final UuidFactoryFast uuidFactory = UuidFactoryFast.getInstance();
  89. @Rule
  90. public UserSessionRule userSession = standalone();
  91. @Rule
  92. public DbTester db = DbTester.create();
  93. private final DbClient dbClient = db.getDbClient();
  94. private final IssueFieldsSetter issueFieldsSetter = new IssueFieldsSetter();
  95. private final IssueWorkflow issueWorkflow = new IssueWorkflow(new FunctionExecutor(issueFieldsSetter), issueFieldsSetter);
  96. private final SearchResponseLoader searchResponseLoader = new SearchResponseLoader(userSession, dbClient, new TransitionService(userSession, issueWorkflow));
  97. private final Languages languages = new Languages();
  98. private final UserResponseFormatter userFormatter = new UserResponseFormatter(new AvatarResolverImpl());
  99. private final SearchResponseFormat searchResponseFormat = new SearchResponseFormat(new Durations(), languages, new TextRangeResponseFormatter(), userFormatter);
  100. private final ComponentFinder componentFinder = TestComponentFinder.from(db);
  101. private final WsActionTester ws = new WsActionTester(
  102. new ListAction(userSession, dbClient, Clock.systemUTC(), searchResponseLoader, searchResponseFormat, componentFinder));
  103. @Before
  104. public void setUp() {
  105. issueWorkflow.start();
  106. }
  107. @Test
  108. public void whenNoComponentOrProjectProvided_shouldFailWithMessage() {
  109. TestRequest request = ws.newRequest();
  110. assertThatThrownBy(() -> request.executeProtobuf(Issues.ListWsResponse.class))
  111. .isInstanceOf(IllegalArgumentException.class)
  112. .hasMessage("Either 'project' or 'component' parameter must be provided");
  113. }
  114. @Test
  115. public void whenBranchAndPullRequestProvided_shouldFailWithMessage() {
  116. TestRequest request = ws.newRequest()
  117. .setParam("project", "some-project")
  118. .setParam("branch", "some-branch")
  119. .setParam("pullRequest", "some-pr");
  120. assertThatThrownBy(() -> request.executeProtobuf(Issues.ListWsResponse.class))
  121. .isInstanceOf(IllegalArgumentException.class)
  122. .hasMessage("Only one of parameters 'branch' and 'pullRequest' can be provided");
  123. }
  124. @Test
  125. public void whenAnonymousUser_shouldFailIfInsufficientPrivileges() {
  126. UserDto user = db.users().insertUser();
  127. ProjectData projectData = db.components().insertPrivateProject();
  128. ComponentDto project = projectData.getMainBranchComponent();
  129. ComponentDto file = db.components().insertComponent(newFileDto(project));
  130. UserDto simon = db.users().insertUser();
  131. RuleDto rule = newIssueRule();
  132. db.issues().insertIssue(rule, project, file, i -> i
  133. .setEffort(10L)
  134. .setLine(42)
  135. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  136. .setMessage("the message")
  137. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  138. .setStatus(STATUS_RESOLVED)
  139. .setResolution(RESOLUTION_FIXED)
  140. .setSeverity("MAJOR")
  141. .setAuthorLogin("John")
  142. .setAssigneeUuid(simon.getUuid())
  143. .setTags(asList("bug", "owasp"))
  144. .setIssueCreationDate(parseDate("2014-09-03"))
  145. .setIssueUpdateDate(parseDate("2017-12-04"))
  146. .setCodeVariants(List.of("variant1", "variant2")));
  147. userSession
  148. .logIn(user)
  149. .registerProjects(projectData.getProjectDto());
  150. TestRequest request = ws.newRequest()
  151. .setParam("project", projectData.projectKey())
  152. .setParam("branch", projectData.getMainBranchDto().getKey());
  153. assertThatThrownBy(() -> request.executeProtobuf(Issues.ListWsResponse.class))
  154. .isInstanceOf(ForbiddenException.class)
  155. .hasMessage("Insufficient privileges");
  156. }
  157. @Test
  158. public void whenNoProjectOrComponent_shouldFail() {
  159. TestRequest request = ws.newRequest()
  160. .setParam("branch", "test-branch");
  161. assertThatThrownBy(() -> request.executeProtobuf(Issues.ListWsResponse.class))
  162. .isInstanceOf(IllegalArgumentException.class)
  163. .hasMessage("Either 'project' or 'component' parameter must be provided");
  164. }
  165. @Test
  166. public void whenListIssuesByProjectAndBranch_shouldReturnAllFields() {
  167. UserDto user = db.users().insertUser();
  168. ProjectData projectData = db.components().insertPublicProject();
  169. ComponentDto project = projectData.getMainBranchComponent();
  170. ComponentDto file = db.components().insertComponent(newFileDto(project));
  171. UserDto simon = db.users().insertUser();
  172. RuleDto rule = newIssueRule();
  173. IssueDto issue = db.issues().insertIssue(rule, project, file, i -> i
  174. .setEffort(10L)
  175. .setLine(42)
  176. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  177. .setMessage("the message")
  178. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  179. .setStatus(STATUS_OPEN)
  180. .setResolution(null)
  181. .setSeverity("MAJOR")
  182. .setAuthorLogin("John")
  183. .setAssigneeUuid(simon.getUuid())
  184. .setTags(asList("bug", "owasp"))
  185. .setIssueCreationDate(parseDate("2014-09-03"))
  186. .setIssueUpdateDate(parseDate("2017-12-04"))
  187. .setCodeVariants(List.of("variant1", "variant2")));
  188. userSession
  189. .logIn(user)
  190. .registerProjects(projectData.getProjectDto());
  191. Issues.ListWsResponse response = ws.newRequest()
  192. .setParam("project", projectData.projectKey())
  193. .setParam("branch", projectData.getMainBranchDto().getKey())
  194. .executeProtobuf(Issues.ListWsResponse.class);
  195. assertThat(response.getIssuesList())
  196. .extracting(
  197. Issue::getKey, Issue::getRule, Issue::getSeverity, Issue::getComponent, Issue::getResolution, Issue::getStatus, Issue::getMessage, Issue::getMessageFormattingsList,
  198. Issue::getEffort, Issue::getAssignee, Issue::getAuthor, Issue::getLine, Issue::getHash, Issue::getTagsList, Issue::getCreationDate, Issue::getUpdateDate,
  199. Issue::getQuickFixAvailable, Issue::getCodeVariantsList)
  200. .containsExactlyInAnyOrder(
  201. tuple(issue.getKey(), rule.getKey().toString(), Severity.MAJOR, file.getKey(), "", STATUS_OPEN, "the message",
  202. MessageFormattingUtils.dbMessageFormattingListToWs(List.of(MESSAGE_FORMATTING)), "10min",
  203. simon.getLogin(), "John", 42, "a227e508d6646b55a086ee11d63b21e9", asList("bug", "owasp"), formatDateTime(issue.getIssueCreationDate()),
  204. formatDateTime(issue.getIssueUpdateDate()), false, List.of("variant1", "variant2")));
  205. }
  206. @Test
  207. public void whenListIssuesByProject_shouldReturnIssuesFromMainBranch() {
  208. UserDto user = db.users().insertUser();
  209. ProjectData projectData = db.components().insertPublicProject();
  210. ComponentDto project = projectData.getMainBranchComponent();
  211. ComponentDto file = db.components().insertComponent(newFileDto(project));
  212. UserDto simon = db.users().insertUser();
  213. RuleDto rule = newIssueRule();
  214. IssueDto issue = db.issues().insertIssue(rule, project, file, i -> i
  215. .setEffort(10L)
  216. .setLine(42)
  217. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  218. .setMessage("the message")
  219. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  220. .setStatus(STATUS_OPEN)
  221. .setResolution(null)
  222. .setSeverity("MAJOR")
  223. .setAuthorLogin("John")
  224. .setAssigneeUuid(simon.getUuid())
  225. .setTags(asList("bug", "owasp"))
  226. .setIssueCreationDate(parseDate("2014-09-03"))
  227. .setIssueUpdateDate(parseDate("2017-12-04"))
  228. .setCodeVariants(List.of("variant1", "variant2")));
  229. ComponentDto anotherBranch = db.components().insertProjectBranch(project, b -> b.setKey("branch1"));
  230. ComponentDto fileFromAnotherBranch = db.components().insertComponent(newFileDto(anotherBranch));
  231. IssueDto issueFromAnotherBranch = db.issues().insertIssue(rule, anotherBranch, fileFromAnotherBranch, i -> i
  232. .setEffort(10L)
  233. .setLine(42)
  234. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  235. .setMessage("the message")
  236. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  237. .setStatus(STATUS_OPEN)
  238. .setResolution(null)
  239. .setSeverity("MAJOR")
  240. .setAuthorLogin("John")
  241. .setAssigneeUuid(simon.getUuid())
  242. .setTags(asList("bug", "owasp"))
  243. .setIssueCreationDate(parseDate("2014-09-03"))
  244. .setIssueUpdateDate(parseDate("2017-12-04"))
  245. .setCodeVariants(List.of("variant1", "variant2")));
  246. userSession
  247. .logIn(user)
  248. .registerProjects(projectData.getProjectDto());
  249. Issues.ListWsResponse response = ws.newRequest()
  250. .setParam("project", projectData.projectKey())
  251. .executeProtobuf(Issues.ListWsResponse.class);
  252. assertThat(response.getIssuesList())
  253. .extracting(Issue::getKey)
  254. .containsExactlyInAnyOrder(issue.getKey())
  255. .doesNotContain(issueFromAnotherBranch.getKey());
  256. }
  257. @Test
  258. public void whenListIssuesByProjectAndPullRequest_shouldIssuesForPullRequestOnly() {
  259. UserDto user = db.users().insertUser();
  260. ProjectData projectData = db.components().insertPublicProject();
  261. ComponentDto project = projectData.getMainBranchComponent();
  262. String pullRequestId = "42";
  263. ComponentDto pullRequest = db.components().insertProjectBranch(project, branchDto -> branchDto.setKey(pullRequestId).setBranchType(BranchType.PULL_REQUEST));
  264. ComponentDto file = db.components().insertComponent(newFileDto(pullRequest));
  265. UserDto simon = db.users().insertUser();
  266. RuleDto rule = newIssueRule();
  267. IssueDto issue = db.issues().insertIssue(rule, pullRequest, file, i -> i
  268. .setEffort(10L)
  269. .setLine(42)
  270. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  271. .setMessage("the message")
  272. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  273. .setStatus(STATUS_OPEN)
  274. .setResolution(null)
  275. .setSeverity("MAJOR")
  276. .setAuthorLogin("John")
  277. .setAssigneeUuid(simon.getUuid())
  278. .setTags(asList("bug", "owasp"))
  279. .setIssueCreationDate(parseDate("2014-09-03"))
  280. .setIssueUpdateDate(parseDate("2017-12-04"))
  281. .setCodeVariants(List.of("variant1", "variant2")));
  282. userSession
  283. .logIn(user)
  284. .registerProjects(projectData.getProjectDto());
  285. Issues.ListWsResponse response = ws.newRequest()
  286. .setParam("project", projectData.projectKey())
  287. .setParam("pullRequest", pullRequestId)
  288. .executeProtobuf(Issues.ListWsResponse.class);
  289. assertThat(response.getIssuesList())
  290. .extracting(Issue::getKey)
  291. .containsExactlyInAnyOrder(issue.getKey());
  292. }
  293. @Test
  294. public void whenListIssuesByProjectOnly_shouldReturnIssuesForMainBranchOnly() {
  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 = newIssueRule();
  301. IssueDto issue = db.issues().insertIssue(rule, project, file, i -> i
  302. .setEffort(10L)
  303. .setLine(42)
  304. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  305. .setMessage("the message")
  306. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  307. .setStatus(STATUS_OPEN)
  308. .setResolution(null)
  309. .setSeverity("MAJOR")
  310. .setAuthorLogin("John")
  311. .setAssigneeUuid(simon.getUuid())
  312. .setTags(asList("bug", "owasp"))
  313. .setIssueCreationDate(parseDate("2014-09-03"))
  314. .setIssueUpdateDate(parseDate("2017-12-04"))
  315. .setCodeVariants(List.of("variant1", "variant2")));
  316. userSession
  317. .logIn(user)
  318. .registerProjects(projectData.getProjectDto());
  319. Issues.ListWsResponse response = ws.newRequest()
  320. .setParam("project", projectData.projectKey())
  321. .executeProtobuf(Issues.ListWsResponse.class);
  322. assertThat(response.getIssuesList())
  323. .extracting(Issue::getKey)
  324. .containsExactlyInAnyOrder(issue.getKey());
  325. }
  326. @Test
  327. public void whenListIssuesByComponent_shouldReturnIssues() {
  328. UserDto user = db.users().insertUser();
  329. ProjectData projectData = db.components().insertPublicProject();
  330. ComponentDto project = projectData.getMainBranchComponent();
  331. ComponentDto file = db.components().insertComponent(newFileDto(project));
  332. UserDto simon = db.users().insertUser();
  333. RuleDto rule = newIssueRule();
  334. IssueDto issue = db.issues().insertIssue(rule, project, file, i -> i
  335. .setEffort(10L)
  336. .setLine(42)
  337. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  338. .setMessage("the message")
  339. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  340. .setStatus(STATUS_OPEN)
  341. .setResolution(null)
  342. .setSeverity("MAJOR")
  343. .setAuthorLogin("John")
  344. .setAssigneeUuid(simon.getUuid())
  345. .setTags(asList("bug", "owasp"))
  346. .setIssueCreationDate(parseDate("2014-09-03"))
  347. .setIssueUpdateDate(parseDate("2017-12-04"))
  348. .setCodeVariants(List.of("variant1", "variant2")));
  349. userSession
  350. .logIn(user)
  351. .registerProjects(projectData.getProjectDto());
  352. Issues.ListWsResponse response = ws.newRequest()
  353. .setParam("component", file.getKey())
  354. .setParam("branch", projectData.getMainBranchDto().getKey())
  355. .executeProtobuf(Issues.ListWsResponse.class);
  356. assertThat(response.getIssuesList())
  357. .extracting(Issue::getKey)
  358. .containsExactlyInAnyOrder(issue.getKey());
  359. }
  360. @Test
  361. public void whenListIssuesByTypes_shouldReturnIssuesWithSpecifiedTypes() {
  362. UserDto user = db.users().insertUser();
  363. ProjectData projectData = db.components().insertPublicProject();
  364. ComponentDto project = projectData.getMainBranchComponent();
  365. ComponentDto file = db.components().insertComponent(newFileDto(project));
  366. UserDto simon = db.users().insertUser();
  367. RuleDto rule = newIssueRule();
  368. IssueDto issue = db.issues().insertIssue(rule, project, file, i -> i
  369. .setType(RuleType.CODE_SMELL)
  370. .setEffort(10L)
  371. .setLine(42)
  372. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  373. .setMessage("the message")
  374. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  375. .setStatus(STATUS_OPEN)
  376. .setResolution(null)
  377. .setSeverity("MAJOR")
  378. .setAuthorLogin("John")
  379. .setAssigneeUuid(simon.getUuid())
  380. .setTags(asList("bug", "owasp"))
  381. .setIssueCreationDate(parseDate("2014-09-03"))
  382. .setIssueUpdateDate(parseDate("2017-12-04"))
  383. .setCodeVariants(List.of("variant1", "variant2")));
  384. RuleDto bugRule = newIssueRule(XOO_X2, RuleType.BUG);
  385. IssueDto bugIssue = db.issues().insertIssue(bugRule, project, file, i -> i
  386. .setType(RuleType.BUG)
  387. .setEffort(10L)
  388. .setLine(42)
  389. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  390. .setMessage("the message")
  391. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  392. .setStatus(STATUS_OPEN)
  393. .setResolution(null)
  394. .setSeverity("MAJOR")
  395. .setAuthorLogin("John")
  396. .setAssigneeUuid(simon.getUuid())
  397. .setTags(asList("bug", "owasp"))
  398. .setIssueCreationDate(parseDate("2014-09-03"))
  399. .setIssueUpdateDate(parseDate("2017-12-04"))
  400. .setCodeVariants(List.of("variant1", "variant2")));
  401. userSession
  402. .logIn(user)
  403. .registerProjects(projectData.getProjectDto());
  404. Issues.ListWsResponse response = ws.newRequest()
  405. .setParam("project", projectData.getProjectDto().getKey())
  406. .setParam("branch", projectData.getMainBranchDto().getKey())
  407. .setParam("types", RuleType.BUG.name())
  408. .executeProtobuf(Issues.ListWsResponse.class);
  409. assertThat(response.getIssuesList())
  410. .extracting(Issue::getKey)
  411. .containsExactlyInAnyOrder(bugIssue.getKey())
  412. .doesNotContain(issue.getKey());
  413. }
  414. @Test
  415. public void whenListIssuesByResolved_shouldReturnResolvedIssues() {
  416. UserDto user = db.users().insertUser();
  417. ProjectData projectData = db.components().insertPublicProject();
  418. ComponentDto project = projectData.getMainBranchComponent();
  419. ComponentDto file = db.components().insertComponent(newFileDto(project));
  420. UserDto simon = db.users().insertUser();
  421. RuleDto rule = newIssueRule();
  422. IssueDto issue = db.issues().insertIssue(rule, project, file, i -> i
  423. .setType(RuleType.CODE_SMELL)
  424. .setEffort(10L)
  425. .setLine(42)
  426. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  427. .setMessage("the message")
  428. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  429. .setStatus(STATUS_CLOSED)
  430. .setResolution(RESOLUTION_FIXED)
  431. .setSeverity("MAJOR")
  432. .setAuthorLogin("John")
  433. .setAssigneeUuid(simon.getUuid())
  434. .setTags(asList("bug", "owasp"))
  435. .setIssueCreationDate(parseDate("2014-09-03"))
  436. .setIssueUpdateDate(parseDate("2017-12-04"))
  437. .setCodeVariants(List.of("variant1", "variant2")));
  438. RuleDto bugRule = newIssueRule(XOO_X2, RuleType.BUG);
  439. IssueDto bugIssue = db.issues().insertIssue(bugRule, project, file, i -> i
  440. .setType(RuleType.BUG)
  441. .setEffort(10L)
  442. .setLine(42)
  443. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  444. .setMessage("the message")
  445. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  446. .setStatus(STATUS_RESOLVED)
  447. .setResolution(RESOLUTION_WONT_FIX)
  448. .setSeverity("MAJOR")
  449. .setAuthorLogin("John")
  450. .setAssigneeUuid(simon.getUuid())
  451. .setTags(asList("bug", "owasp"))
  452. .setIssueCreationDate(parseDate("2014-09-03"))
  453. .setIssueUpdateDate(parseDate("2017-12-04"))
  454. .setCodeVariants(List.of("variant1", "variant2")));
  455. IssueDto vulnerabilityIssue = db.issues().insertIssue(rule, project, file, i -> i
  456. .setType(RuleType.VULNERABILITY)
  457. .setEffort(10L)
  458. .setLine(42)
  459. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  460. .setMessage("the message")
  461. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  462. .setStatus(STATUS_OPEN)
  463. .setResolution(null)
  464. .setSeverity("MAJOR")
  465. .setAuthorLogin("John")
  466. .setAssigneeUuid(simon.getUuid())
  467. .setTags(asList("bug", "owasp"))
  468. .setIssueCreationDate(parseDate("2014-09-03"))
  469. .setIssueUpdateDate(parseDate("2017-12-04"))
  470. .setCodeVariants(List.of("variant1", "variant2")));
  471. userSession
  472. .logIn(user)
  473. .registerProjects(projectData.getProjectDto());
  474. Issues.ListWsResponse response = ws.newRequest()
  475. .setParam("project", projectData.getProjectDto().getKey())
  476. .setParam("branch", projectData.getMainBranchDto().getKey())
  477. .setParam("resolved", "true")
  478. .executeProtobuf(Issues.ListWsResponse.class);
  479. assertThat(response.getIssuesList())
  480. .extracting(Issue::getKey)
  481. .containsExactlyInAnyOrder(issue.getKey(), bugIssue.getKey())
  482. .doesNotContain(vulnerabilityIssue.getKey());
  483. response = ws.newRequest()
  484. .setParam("project", projectData.getProjectDto().getKey())
  485. .setParam("branch", projectData.getMainBranchDto().getKey())
  486. .setParam("resolved", "false")
  487. .executeProtobuf(Issues.ListWsResponse.class);
  488. assertThat(response.getIssuesList())
  489. .extracting(Issue::getKey)
  490. .containsExactlyInAnyOrder(vulnerabilityIssue.getKey())
  491. .doesNotContain(issue.getKey(), bugIssue.getKey());
  492. response = ws.newRequest()
  493. .setParam("project", projectData.getProjectDto().getKey())
  494. .setParam("branch", projectData.getMainBranchDto().getKey())
  495. .executeProtobuf(Issues.ListWsResponse.class);
  496. assertThat(response.getIssuesList())
  497. .extracting(Issue::getKey)
  498. .containsExactlyInAnyOrder(vulnerabilityIssue.getKey(), issue.getKey(), bugIssue.getKey());
  499. }
  500. @Test
  501. public void whenListIssuesByNewCodePeriodDate_shouldReturnIssues() {
  502. UserDto user = db.users().insertUser();
  503. ProjectData projectData = db.components().insertPublicProject();
  504. ComponentDto project = projectData.getMainBranchComponent();
  505. ComponentDto file = db.components().insertComponent(newFileDto(project));
  506. UserDto simon = db.users().insertUser();
  507. RuleDto rule = newIssueRule();
  508. db.components().insertSnapshot(project, s -> s.setLast(true).setPeriodDate(parseDateTime("2014-09-05T00:00:00+0100").getTime()));
  509. List<String> beforeNewCodePeriod = IntStream.range(0, 10).mapToObj(number -> db.issues().insertIssue(rule, project, file, i -> i
  510. .setEffort(10L)
  511. .setLine(42)
  512. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  513. .setMessage("the message")
  514. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  515. .setStatus(STATUS_OPEN)
  516. .setResolution(null)
  517. .setSeverity("MAJOR")
  518. .setAuthorLogin("John")
  519. .setAssigneeUuid(simon.getUuid())
  520. .setTags(asList("bug", "owasp"))
  521. .setIssueCreationDate(parseDate("2014-09-03"))
  522. .setIssueUpdateDate(parseDate("2017-12-04"))
  523. .setCodeVariants(List.of("variant1", "variant2"))))
  524. .map(IssueDto::getKey)
  525. .toList();
  526. List<String> afterNewCodePeriod = IntStream.range(0, 5).mapToObj(number -> db.issues().insertIssue(rule, project, file, i -> i
  527. .setEffort(10L)
  528. .setLine(42)
  529. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  530. .setMessage("the message")
  531. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  532. .setStatus(STATUS_OPEN)
  533. .setResolution(null)
  534. .setSeverity("MAJOR")
  535. .setAuthorLogin("John")
  536. .setAssigneeUuid(simon.getUuid())
  537. .setTags(asList("bug", "owasp"))
  538. .setIssueCreationDate(parseDate("2015-01-02"))
  539. .setIssueUpdateDate(parseDate("2017-12-04"))
  540. .setCodeVariants(List.of("variant1", "variant2"))))
  541. .map(IssueDto::getKey)
  542. .toList();
  543. userSession
  544. .logIn(user)
  545. .registerProjects(projectData.getProjectDto());
  546. Issues.ListWsResponse response = ws.newRequest()
  547. .setParam("project", projectData.projectKey())
  548. .setParam("inNewCodePeriod", "true")
  549. .setParam("branch", projectData.getMainBranchDto().getKey())
  550. .executeProtobuf(Issues.ListWsResponse.class);
  551. assertThat(response.getIssuesList())
  552. .extracting(Issue::getKey)
  553. .containsExactlyInAnyOrderElementsOf(afterNewCodePeriod)
  554. .doesNotContainAnyElementsOf(beforeNewCodePeriod);
  555. }
  556. @Test
  557. public void whenListIssuesByNewCodePeriodReferenceBranch_shouldReturnIssues() {
  558. UserDto user = db.users().insertUser();
  559. ProjectData projectData = db.components().insertPublicProject();
  560. ComponentDto project = projectData.getMainBranchComponent();
  561. ComponentDto file = db.components().insertComponent(newFileDto(project));
  562. UserDto simon = db.users().insertUser();
  563. RuleDto rule = newIssueRule();
  564. db.components().insertSnapshot(project, s -> s.setLast(true).setPeriodMode(REFERENCE_BRANCH.name()));
  565. MetricDto metric = db.measures().insertMetric(metricDto -> metricDto.setKey(ANALYSIS_FROM_SONARQUBE_9_4_KEY));
  566. db.measures().insertLiveMeasure(project, metric);
  567. List<String> beforeNewCodePeriod = IntStream.range(0, 10).mapToObj(number -> db.issues().insertIssue(rule, project, file, i -> i
  568. .setEffort(10L)
  569. .setLine(42)
  570. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  571. .setMessage("the message")
  572. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  573. .setStatus(STATUS_OPEN)
  574. .setResolution(null)
  575. .setSeverity("MAJOR")
  576. .setAuthorLogin("John")
  577. .setAssigneeUuid(simon.getUuid())
  578. .setTags(asList("bug", "owasp"))
  579. .setIssueCreationDate(parseDate("2014-09-03"))
  580. .setIssueUpdateDate(parseDate("2017-12-04"))
  581. .setCodeVariants(List.of("variant1", "variant2"))))
  582. .map(IssueDto::getKey)
  583. .toList();
  584. List<String> afterNewCodePeriod = IntStream.range(0, 5).mapToObj(number -> db.issues().insertIssue(rule, project, file, i -> i
  585. .setEffort(10L)
  586. .setLine(42)
  587. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  588. .setMessage("the message")
  589. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  590. .setStatus(STATUS_OPEN)
  591. .setResolution(null)
  592. .setSeverity("MAJOR")
  593. .setAuthorLogin("John")
  594. .setAssigneeUuid(simon.getUuid())
  595. .setTags(asList("bug", "owasp"))
  596. .setIssueCreationDate(parseDate("2015-01-02"))
  597. .setIssueUpdateDate(parseDate("2017-12-04"))
  598. .setCodeVariants(List.of("variant1", "variant2"))))
  599. .peek(issueDto -> db.issues().insertNewCodeReferenceIssue(issueDto))
  600. .map(IssueDto::getKey)
  601. .toList();
  602. userSession
  603. .logIn(user)
  604. .registerProjects(projectData.getProjectDto());
  605. Issues.ListWsResponse response = ws.newRequest()
  606. .setParam("project", projectData.projectKey())
  607. .setParam("inNewCodePeriod", "true")
  608. .setParam("branch", projectData.getMainBranchDto().getKey())
  609. .executeProtobuf(Issues.ListWsResponse.class);
  610. assertThat(response.getIssuesList())
  611. .extracting(Issue::getKey)
  612. .containsExactlyInAnyOrderElementsOf(afterNewCodePeriod)
  613. .doesNotContainAnyElementsOf(beforeNewCodePeriod);
  614. }
  615. @Test
  616. @UseDataProvider("pages")
  617. public void whenUsingPagination_shouldReturnPaginatedResults(String page, int expectedNumberOfIssues) {
  618. UserDto user = db.users().insertUser();
  619. ProjectData projectData = db.components().insertPublicProject();
  620. ComponentDto project = projectData.getMainBranchComponent();
  621. ComponentDto file = db.components().insertComponent(newFileDto(project));
  622. UserDto simon = db.users().insertUser();
  623. RuleDto rule = newIssueRule();
  624. IntStream.range(0, 10).forEach(number -> db.issues().insertIssue(rule, project, file, i -> i
  625. .setEffort(10L)
  626. .setLine(42)
  627. .setChecksum("a227e508d6646b55a086ee11d63b21e9")
  628. .setMessage("the message")
  629. .setMessageFormattings(DbIssues.MessageFormattings.newBuilder().addMessageFormatting(MESSAGE_FORMATTING).build())
  630. .setStatus(STATUS_OPEN)
  631. .setResolution(null)
  632. .setSeverity("MAJOR")
  633. .setAuthorLogin("John")
  634. .setAssigneeUuid(simon.getUuid())
  635. .setTags(asList("bug", "owasp"))
  636. .setIssueCreationDate(parseDate("2014-09-03"))
  637. .setIssueUpdateDate(parseDate("2017-12-04"))
  638. .setCodeVariants(List.of("variant1", "variant2"))));
  639. userSession
  640. .logIn(user)
  641. .registerProjects(projectData.getProjectDto());
  642. Issues.ListWsResponse response = ws.newRequest()
  643. .setParam("project", projectData.projectKey())
  644. .setParam("branch", projectData.getMainBranchDto().getKey())
  645. .setParam("p", page)
  646. .setParam("ps", "3")
  647. .executeProtobuf(Issues.ListWsResponse.class);
  648. assertThat(response.getIssuesList()).hasSize(expectedNumberOfIssues);
  649. }
  650. private RuleDto newIssueRule() {
  651. return newIssueRule(XOO_X1, RuleType.CODE_SMELL);
  652. }
  653. private RuleDto newIssueRule(RuleKey ruleKey, RuleType ruleType) {
  654. RuleDto rule = newRule(ruleKey, createDefaultRuleDescriptionSection(uuidFactory.create(), "Rule desc"))
  655. .setLanguage("xoo")
  656. .setName("Rule name")
  657. .setType(ruleType)
  658. .setStatus(RuleStatus.READY);
  659. db.rules().insert(rule);
  660. return rule;
  661. }
  662. @DataProvider
  663. public static Object[][] pages() {
  664. return new Object[][] {
  665. {"1", 3},
  666. {"2", 3},
  667. {"3", 3},
  668. {"4", 1},
  669. };
  670. }
  671. }