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.

ListActionIT.java 32KB

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