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.

SearchActionComponentsTest.java 40KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2021 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 java.time.Clock;
  22. import java.util.Arrays;
  23. import java.util.Date;
  24. import org.junit.Rule;
  25. import org.junit.Test;
  26. import org.junit.rules.ExpectedException;
  27. import org.sonar.api.resources.Languages;
  28. import org.sonar.api.resources.Qualifiers;
  29. import org.sonar.api.rule.RuleKey;
  30. import org.sonar.api.utils.Durations;
  31. import org.sonar.api.utils.System2;
  32. import org.sonar.db.DbClient;
  33. import org.sonar.db.DbTester;
  34. import org.sonar.db.component.ComponentDto;
  35. import org.sonar.db.component.ComponentTesting;
  36. import org.sonar.db.issue.IssueDto;
  37. import org.sonar.db.rule.RuleDefinitionDto;
  38. import org.sonar.server.es.EsTester;
  39. import org.sonar.server.issue.AvatarResolverImpl;
  40. import org.sonar.server.issue.IssueFieldsSetter;
  41. import org.sonar.server.issue.TextRangeResponseFormatter;
  42. import org.sonar.server.issue.TransitionService;
  43. import org.sonar.server.issue.index.IssueIndex;
  44. import org.sonar.server.issue.index.IssueIndexSyncProgressChecker;
  45. import org.sonar.server.issue.index.IssueIndexer;
  46. import org.sonar.server.issue.index.IssueIteratorFactory;
  47. import org.sonar.server.issue.index.IssueQueryFactory;
  48. import org.sonar.server.issue.workflow.FunctionExecutor;
  49. import org.sonar.server.issue.workflow.IssueWorkflow;
  50. import org.sonar.server.permission.index.PermissionIndexerTester;
  51. import org.sonar.server.permission.index.WebAuthorizationTypeSupport;
  52. import org.sonar.server.tester.UserSessionRule;
  53. import org.sonar.server.view.index.ViewIndexer;
  54. import org.sonar.server.ws.WsActionTester;
  55. import org.sonarqube.ws.Issues;
  56. import org.sonarqube.ws.Issues.Component;
  57. import org.sonarqube.ws.Issues.Issue;
  58. import org.sonarqube.ws.Issues.SearchWsResponse;
  59. import static org.assertj.core.api.Assertions.assertThat;
  60. import static org.assertj.core.api.Assertions.tuple;
  61. import static org.sonar.api.resources.Qualifiers.APP;
  62. import static org.sonar.api.utils.DateUtils.addDays;
  63. import static org.sonar.api.utils.DateUtils.parseDateTime;
  64. import static org.sonar.api.web.UserRole.USER;
  65. import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01;
  66. import static org.sonar.core.util.Uuids.UUID_EXAMPLE_02;
  67. import static org.sonar.db.component.BranchType.BRANCH;
  68. import static org.sonar.db.component.BranchType.PULL_REQUEST;
  69. import static org.sonar.db.component.ComponentTesting.newDirectory;
  70. import static org.sonar.db.component.ComponentTesting.newFileDto;
  71. import static org.sonar.db.component.ComponentTesting.newModuleDto;
  72. import static org.sonar.db.component.ComponentTesting.newProjectCopy;
  73. import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_BRANCH;
  74. import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_KEYS;
  75. import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_DIRECTORIES;
  76. import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_FILES;
  77. import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_PROJECTS;
  78. import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_PULL_REQUEST;
  79. import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_SINCE_LEAK_PERIOD;
  80. public class SearchActionComponentsTest {
  81. @Rule
  82. public ExpectedException expectedException = ExpectedException.none();
  83. @Rule
  84. public UserSessionRule userSession = UserSessionRule.standalone();
  85. @Rule
  86. public DbTester db = DbTester.create();
  87. @Rule
  88. public EsTester es = EsTester.create();
  89. private DbClient dbClient = db.getDbClient();
  90. private IssueIndex issueIndex = new IssueIndex(es.client(), System2.INSTANCE, userSession, new WebAuthorizationTypeSupport(userSession));
  91. private IssueIndexer issueIndexer = new IssueIndexer(es.client(), dbClient, new IssueIteratorFactory(dbClient), null);
  92. private ViewIndexer viewIndexer = new ViewIndexer(dbClient, es.client());
  93. private IssueQueryFactory issueQueryFactory = new IssueQueryFactory(dbClient, Clock.systemUTC(), userSession);
  94. private IssueFieldsSetter issueFieldsSetter = new IssueFieldsSetter();
  95. private IssueWorkflow issueWorkflow = new IssueWorkflow(new FunctionExecutor(issueFieldsSetter), issueFieldsSetter);
  96. private SearchResponseLoader searchResponseLoader = new SearchResponseLoader(userSession, dbClient, new TransitionService(userSession, issueWorkflow));
  97. private Languages languages = new Languages();
  98. private UserResponseFormatter userFormatter = new UserResponseFormatter(new AvatarResolverImpl());
  99. private SearchResponseFormat searchResponseFormat = new SearchResponseFormat(new Durations(), languages, new TextRangeResponseFormatter(), userFormatter);
  100. private PermissionIndexerTester permissionIndexer = new PermissionIndexerTester(es, issueIndexer);
  101. private IssueIndexSyncProgressChecker issueIndexSyncProgressChecker = new IssueIndexSyncProgressChecker(db.getDbClient());
  102. private WsActionTester ws = new WsActionTester(
  103. new SearchAction(userSession, issueIndex, issueQueryFactory, issueIndexSyncProgressChecker, searchResponseLoader, searchResponseFormat,
  104. System2.INSTANCE, dbClient));
  105. @Test
  106. public void search_all_issues_when_no_parameter() {
  107. RuleDefinitionDto rule = db.rules().insertIssueRule();
  108. ComponentDto project = db.components().insertPublicProject();
  109. ComponentDto projectFile = db.components().insertComponent(newFileDto(project));
  110. IssueDto issue = db.issues().insertIssue(rule, project, projectFile);
  111. allowAnyoneOnProjects(project);
  112. indexIssues();
  113. SearchWsResponse result = ws.newRequest().executeProtobuf(SearchWsResponse.class);
  114. assertThat(result.getIssuesList()).extracting(Issues.Issue::getKey)
  115. .containsExactlyInAnyOrder(issue.getKey());
  116. }
  117. @Test
  118. public void issues_on_different_projects() {
  119. RuleDefinitionDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
  120. ComponentDto project = db.components().insertPublicProject();
  121. ComponentDto file = db.components().insertComponent(newFileDto(project));
  122. IssueDto issue1 = db.issues().insertIssue(rule, project, file);
  123. ComponentDto project2 = db.components().insertPublicProject();
  124. ComponentDto file2 = db.components().insertComponent(newFileDto(project2));
  125. IssueDto issue2 = db.issues().insertIssue(rule, project2, file2);
  126. allowAnyoneOnProjects(project, project2);
  127. indexIssues();
  128. SearchWsResponse response = ws.newRequest().executeProtobuf(SearchWsResponse.class);
  129. assertThat(response.getIssuesList())
  130. .extracting(Issue::getKey, Issue::getComponent, Issue::getProject)
  131. .containsExactlyInAnyOrder(
  132. tuple(issue1.getKey(), file.getKey(), project.getKey()),
  133. tuple(issue2.getKey(), file2.getKey(), project2.getKey()));
  134. assertThat(response.getComponentsList())
  135. .extracting(Component::getKey, Component::getEnabled)
  136. .containsExactlyInAnyOrder(tuple(project.getKey(), true), tuple(file.getKey(), true), tuple(project2.getKey(), true), tuple(file2.getKey(), true));
  137. }
  138. @Test
  139. public void search_by_module() {
  140. ComponentDto project = db.components().insertPublicProject();
  141. ComponentDto module1 = db.components().insertComponent(newModuleDto(project));
  142. ComponentDto file1 = db.components().insertComponent(newFileDto(module1));
  143. ComponentDto module2 = db.components().insertComponent(newModuleDto(project));
  144. ComponentDto file2 = db.components().insertComponent(newFileDto(module2));
  145. RuleDefinitionDto rule = db.rules().insertIssueRule();
  146. IssueDto issue1 = db.issues().insertIssue(rule, project, file1);
  147. IssueDto issue2 = db.issues().insertIssue(rule, project, file2);
  148. allowAnyoneOnProjects(project);
  149. indexIssues();
  150. assertThat(ws.newRequest()
  151. .setParam(PARAM_COMPONENT_KEYS, module1.getKey())
  152. .executeProtobuf(SearchWsResponse.class).getIssuesList()).extracting(Issue::getKey)
  153. .containsExactlyInAnyOrder(issue1.getKey());
  154. }
  155. @Test
  156. public void do_not_return_module_key_on_single_module_projects() {
  157. ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
  158. ComponentDto module = db.components().insertComponent(newModuleDto("M1", project).setDbKey("MK1"));
  159. ComponentDto file = db.components().insertComponent(newFileDto(module, null, "F1").setDbKey("FK1"));
  160. RuleDefinitionDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
  161. db.issues().insertIssue(rule, project, file, i -> i.setKee("ISSUE_IN_MODULE"));
  162. db.issues().insertIssue(rule, project, project, i -> i.setKee("ISSUE_IN_ROOT_MODULE"));
  163. allowAnyoneOnProjects(project);
  164. indexIssues();
  165. SearchWsResponse searchResponse = ws.newRequest().executeProtobuf(SearchWsResponse.class);
  166. assertThat(searchResponse.getIssuesCount()).isEqualTo(2);
  167. for (Issue issue : searchResponse.getIssuesList()) {
  168. assertThat(issue.getProject()).isEqualTo("PK1");
  169. if (issue.getKey().equals("ISSUE_IN_MODULE")) {
  170. assertThat(issue.getSubProject()).isEqualTo("MK1");
  171. } else if (issue.getKey().equals("ISSUE_IN_ROOT_MODULE")) {
  172. assertThat(issue.hasSubProject()).isFalse();
  173. }
  174. }
  175. }
  176. @Test
  177. public void search_since_leak_period_on_project() {
  178. ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
  179. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "F1").setDbKey("FK1"));
  180. db.components().insertSnapshot(project, a -> a.setPeriodDate(parseDateTime("2015-09-03T00:00:00+0100").getTime()));
  181. RuleDefinitionDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
  182. IssueDto issueAfterLeak = db.issues().insertIssue(rule, project, file, i -> i.setKee(UUID_EXAMPLE_01)
  183. .setIssueCreationDate(parseDateTime("2015-09-04T00:00:00+0100"))
  184. .setIssueUpdateDate(parseDateTime("2015-10-04T00:00:00+0100")));
  185. IssueDto issueBeforeLeak = db.issues().insertIssue(rule, project, file, i -> i.setKee(UUID_EXAMPLE_02)
  186. .setIssueCreationDate(parseDateTime("2014-09-04T00:00:00+0100"))
  187. .setIssueUpdateDate(parseDateTime("2015-10-04T00:00:00+0100")));
  188. allowAnyoneOnProjects(project);
  189. indexIssues();
  190. ws.newRequest()
  191. .setParam(PARAM_COMPONENT_KEYS, project.getDbKey())
  192. .setParam(PARAM_SINCE_LEAK_PERIOD, "true")
  193. .execute()
  194. .assertJson(this.getClass(), "search_since_leak_period.json");
  195. }
  196. @Test
  197. public void search_since_leak_period_on_file_in_module_project() {
  198. ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
  199. ComponentDto module = db.components().insertComponent(newModuleDto(project));
  200. ComponentDto file = db.components().insertComponent(newFileDto(module, null, "F1").setDbKey("FK1"));
  201. db.components().insertSnapshot(project, a -> a.setPeriodDate(parseDateTime("2015-09-03T00:00:00+0100").getTime()));
  202. RuleDefinitionDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
  203. IssueDto issueAfterLeak = db.issues().insertIssue(rule, project, file, i -> i.setKee(UUID_EXAMPLE_01)
  204. .setIssueCreationDate(parseDateTime("2015-09-04T00:00:00+0100"))
  205. .setIssueUpdateDate(parseDateTime("2015-10-04T00:00:00+0100")));
  206. IssueDto issueBeforeLeak = db.issues().insertIssue(rule, project, file, i -> i.setKee(UUID_EXAMPLE_02)
  207. .setIssueCreationDate(parseDateTime("2014-09-04T00:00:00+0100"))
  208. .setIssueUpdateDate(parseDateTime("2015-10-04T00:00:00+0100")));
  209. allowAnyoneOnProjects(project);
  210. indexIssues();
  211. ws.newRequest()
  212. .setParam(PARAM_COMPONENT_KEYS, project.getDbKey())
  213. .setParam(PARAM_FILES, file.path())
  214. .setParam(PARAM_SINCE_LEAK_PERIOD, "true")
  215. .execute()
  216. .assertJson(this.getClass(), "search_since_leak_period.json");
  217. }
  218. @Test
  219. public void search_by_file_uuid() {
  220. ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
  221. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "F1").setDbKey("FK1"));
  222. RuleDefinitionDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
  223. IssueDto issue = db.issues().insertIssue(rule, project, file, i -> i.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"));
  224. allowAnyoneOnProjects(project);
  225. indexIssues();
  226. ws.newRequest()
  227. .setParam(PARAM_FILES, file.path())
  228. .execute()
  229. .assertJson(this.getClass(), "search_by_file_uuid.json");
  230. ws.newRequest()
  231. .setParam(PARAM_FILES, "unknown")
  232. .execute()
  233. .assertJson(this.getClass(), "no_issue.json");
  234. }
  235. @Test
  236. public void search_by_file_key() {
  237. ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
  238. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "F1").setDbKey("FK1"));
  239. ComponentDto unitTest = db.components().insertComponent(newFileDto(project, null, "F2").setQualifier(Qualifiers.UNIT_TEST_FILE).setDbKey("FK2"));
  240. RuleDefinitionDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
  241. IssueDto issueOnFile = db.issues().insertIssue(rule, project, file, i -> i.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"));
  242. IssueDto issueOnTest = db.issues().insertIssue(rule, project, unitTest, i -> i.setKee("2bd4eac2-b650-4037-80bc-7b1182fd47d4"));
  243. allowAnyoneOnProjects(project);
  244. indexIssues();
  245. ws.newRequest()
  246. .setParam(PARAM_COMPONENT_KEYS, file.getKey())
  247. .execute()
  248. .assertJson(this.getClass(), "search_by_file_key.json");
  249. ws.newRequest()
  250. .setParam(PARAM_COMPONENT_KEYS, unitTest.getKey())
  251. .execute()
  252. .assertJson(this.getClass(), "search_by_test_key.json");
  253. }
  254. @Test
  255. public void search_by_directory_path() {
  256. ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
  257. ComponentDto directory = db.components().insertComponent(newDirectory(project, "D1", "src/main/java/dir"));
  258. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "F1").setDbKey("FK1").setPath(directory.path() + "/MyComponent.java"));
  259. RuleDefinitionDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
  260. db.issues().insertIssue(rule, project, file, i -> i.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"));
  261. allowAnyoneOnProjects(project);
  262. indexIssues();
  263. ws.newRequest()
  264. .setParam(PARAM_COMPONENT_KEYS, directory.getKey())
  265. .execute()
  266. .assertJson(this.getClass(), "search_by_file_uuid.json");
  267. ws.newRequest()
  268. .setParam(PARAM_DIRECTORIES, "unknown")
  269. .execute()
  270. .assertJson(this.getClass(), "no_issue.json");
  271. ws.newRequest()
  272. .setParam(PARAM_DIRECTORIES, "src/main/java/dir")
  273. .execute()
  274. .assertJson(this.getClass(), "search_by_file_uuid.json");
  275. ws.newRequest()
  276. .setParam(PARAM_DIRECTORIES, "src/main/java")
  277. .execute()
  278. .assertJson(this.getClass(), "no_issue.json");
  279. }
  280. @Test
  281. public void search_by_directory_path_in_different_modules() {
  282. ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
  283. ComponentDto module1 = db.components().insertComponent(newModuleDto("M1", project).setDbKey("MK1"));
  284. ComponentDto module2 = db.components().insertComponent(newModuleDto("M2", project).setDbKey("MK2"));
  285. ComponentDto directory1 = db.components().insertComponent(newDirectory(module1, "D1", "src/main/java/dir"));
  286. ComponentDto directory2 = db.components().insertComponent(newDirectory(module2, "D2", "src/main/java/dir"));
  287. ComponentDto file1 = db.components().insertComponent(newFileDto(module1, directory1, "F1").setDbKey("FK1").setPath(directory1.path() + "/MyComponent.java"));
  288. db.components().insertComponent(newFileDto(module2, directory2, "F2").setDbKey("FK2").setPath(directory2.path() + "/MyComponent.java"));
  289. RuleDefinitionDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
  290. db.issues().insertIssue(rule, project, file1, i -> i.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"));
  291. allowAnyoneOnProjects(project);
  292. indexIssues();
  293. ws.newRequest()
  294. .setParam(PARAM_COMPONENT_KEYS, directory1.getKey())
  295. .execute()
  296. .assertJson(this.getClass(), "search_by_directory_uuid.json");
  297. ws.newRequest()
  298. .setParam(PARAM_COMPONENT_KEYS, directory2.getKey())
  299. .execute()
  300. .assertJson(this.getClass(), "no_issue.json");
  301. ws.newRequest()
  302. .setParam(PARAM_DIRECTORIES, "src/main/java/dir")
  303. .execute()
  304. .assertJson(this.getClass(), "search_by_directory_uuid.json");
  305. ws.newRequest()
  306. .setParam(PARAM_DIRECTORIES, "src/main/java")
  307. .execute()
  308. .assertJson(this.getClass(), "no_issue.json");
  309. }
  310. @Test
  311. public void search_by_view_uuid() {
  312. ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
  313. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "F1").setDbKey("FK1"));
  314. ComponentDto view = db.components().insertComponent(ComponentTesting.newPortfolio("V1").setDbKey("MyView"));
  315. db.components().insertComponent(newProjectCopy(project, view));
  316. RuleDefinitionDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
  317. db.issues().insertIssue(rule, project, file, i -> i.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"));
  318. allowAnyoneOnProjects(project, view);
  319. indexIssuesAndViews();
  320. ws.newRequest()
  321. .setParam(PARAM_COMPONENT_KEYS, view.getKey())
  322. .execute()
  323. .assertJson(this.getClass(), "search_by_view_uuid.json");
  324. }
  325. @Test
  326. public void search_by_sub_view_uuid() {
  327. ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
  328. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "F1").setDbKey("FK1"));
  329. RuleDefinitionDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
  330. db.issues().insertIssue(rule, project, file, i -> i.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"));
  331. ComponentDto view = db.components().insertComponent(ComponentTesting.newPortfolio("V1").setDbKey("MyView"));
  332. ComponentDto subView = db.components().insertComponent(ComponentTesting.newSubPortfolio(view, "SV1", "MySubView"));
  333. db.components().insertComponent(newProjectCopy(project, subView));
  334. allowAnyoneOnProjects(project, view, subView);
  335. indexIssuesAndViews();
  336. ws.newRequest()
  337. .setParam(PARAM_COMPONENT_KEYS, subView.getKey())
  338. .execute()
  339. .assertJson(this.getClass(), "search_by_view_uuid.json");
  340. }
  341. @Test
  342. public void search_by_sub_view_uuid_return_only_authorized_view() {
  343. ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
  344. ComponentDto file = db.components().insertComponent(newFileDto(project, null, "F1").setDbKey("FK1"));
  345. RuleDefinitionDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
  346. db.issues().insertIssue(rule, project, file, i -> i.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"));
  347. ComponentDto view = db.components().insertComponent(ComponentTesting.newPortfolio("V1").setDbKey("MyView"));
  348. ComponentDto subView = db.components().insertComponent(ComponentTesting.newSubPortfolio(view, "SV1", "MySubView"));
  349. db.components().insertComponent(newProjectCopy(project, subView));
  350. // User has no permission on the view, no issue will be returned
  351. allowAnyoneOnProjects(project);
  352. indexIssuesAndViews();
  353. ws.newRequest()
  354. .setParam(PARAM_COMPONENT_KEYS, subView.getKey())
  355. .execute()
  356. .assertJson(this.getClass(), "no_issue.json");
  357. }
  358. @Test
  359. public void search_by_application_key() {
  360. ComponentDto application = db.components().insertPrivateApplication();
  361. ComponentDto project1 = db.components().insertPrivateProject();
  362. ComponentDto project2 = db.components().insertPrivateProject();
  363. db.components().insertComponents(newProjectCopy(project1, application));
  364. db.components().insertComponents(newProjectCopy(project2, application));
  365. RuleDefinitionDto rule = db.rules().insertIssueRule();
  366. IssueDto issue1 = db.issues().insertIssue(rule, project1, project1);
  367. IssueDto issue2 = db.issues().insertIssue(rule, project2, project2);
  368. allowAnyoneOnProjects(project1, project2, application);
  369. userSession.addProjectPermission(USER, application);
  370. indexIssuesAndViews();
  371. SearchWsResponse result = ws.newRequest()
  372. .setParam(PARAM_COMPONENT_KEYS, application.getDbKey())
  373. .executeProtobuf(SearchWsResponse.class);
  374. assertThat(result.getIssuesList()).extracting(Issue::getKey)
  375. .containsExactlyInAnyOrder(issue1.getKey(), issue2.getKey());
  376. }
  377. @Test
  378. public void search_by_application_key_and_branch() {
  379. ComponentDto application = db.components().insertPrivateProject(c -> c.setQualifier(APP).setDbKey("app"));
  380. ComponentDto applicationBranch1 = db.components().insertProjectBranch(application, a -> a.setKey("app-branch1"));
  381. ComponentDto applicationBranch2 = db.components().insertProjectBranch(application, a -> a.setKey("app-branch2"));
  382. ComponentDto project1 = db.components().insertPrivateProject(p -> p.setDbKey("prj1"));
  383. ComponentDto project1Branch1 = db.components().insertProjectBranch(project1);
  384. ComponentDto fileOnProject1Branch1 = db.components().insertComponent(newFileDto(project1Branch1));
  385. ComponentDto project1Branch2 = db.components().insertProjectBranch(project1);
  386. ComponentDto project2 = db.components().insertPrivateProject(p -> p.setDbKey("prj2"));
  387. db.components().insertComponents(newProjectCopy(project1Branch1, applicationBranch1));
  388. db.components().insertComponents(newProjectCopy(project2, applicationBranch1));
  389. db.components().insertComponents(newProjectCopy(project1Branch2, applicationBranch2));
  390. RuleDefinitionDto issueRule = db.rules().insertIssueRule();
  391. RuleDefinitionDto hotspotRule = db.rules().insertHotspotRule();
  392. IssueDto issueOnProject1 = db.issues().insertIssue(issueRule, project1, project1);
  393. IssueDto issueOnProject1Branch1 = db.issues().insertIssue(issueRule, project1Branch1, project1Branch1);
  394. db.issues().insertHotspot(hotspotRule, project1Branch1, project1Branch1);
  395. IssueDto issueOnFileOnProject1Branch1 = db.issues().insertIssue(issueRule, project1Branch1, fileOnProject1Branch1);
  396. IssueDto issueOnProject1Branch2 = db.issues().insertIssue(issueRule, project1Branch2, project1Branch2);
  397. IssueDto issueOnProject2 = db.issues().insertIssue(issueRule, project2, project2);
  398. db.issues().insertHotspot(hotspotRule, project2, project2);
  399. allowAnyoneOnProjects(project1, project2, application);
  400. userSession.addProjectPermission(USER, application);
  401. indexIssuesAndViews();
  402. // All issues on applicationBranch1
  403. assertThat(ws.newRequest()
  404. .setParam(PARAM_COMPONENT_KEYS, applicationBranch1.getKey())
  405. .setParam(PARAM_BRANCH, applicationBranch1.getBranch())
  406. .executeProtobuf(SearchWsResponse.class).getIssuesList())
  407. .extracting(Issue::getKey, Issue::getComponent, Issue::getProject, Issue::getBranch, Issue::hasBranch)
  408. .containsExactlyInAnyOrder(
  409. tuple(issueOnProject1Branch1.getKey(), project1Branch1.getKey(), project1Branch1.getKey(), project1Branch1.getBranch(), true),
  410. tuple(issueOnFileOnProject1Branch1.getKey(), fileOnProject1Branch1.getKey(), project1Branch1.getKey(), project1Branch1.getBranch(), true),
  411. tuple(issueOnProject2.getKey(), project2.getKey(), project2.getKey(), "", false));
  412. // Issues on project1Branch1
  413. assertThat(ws.newRequest()
  414. .setParam(PARAM_COMPONENT_KEYS, applicationBranch1.getKey())
  415. .setParam(PARAM_PROJECTS, project1.getKey())
  416. .setParam(PARAM_BRANCH, applicationBranch1.getBranch())
  417. .executeProtobuf(SearchWsResponse.class).getIssuesList())
  418. .extracting(Issue::getKey, Issue::getComponent, Issue::getBranch)
  419. .containsExactlyInAnyOrder(
  420. tuple(issueOnProject1Branch1.getKey(), project1Branch1.getKey(), project1Branch1.getBranch()),
  421. tuple(issueOnFileOnProject1Branch1.getKey(), fileOnProject1Branch1.getKey(), project1Branch1.getBranch()));
  422. }
  423. @Test
  424. public void ignore_application_without_browse_permission() {
  425. ComponentDto project = db.components().insertPublicProject();
  426. ComponentDto application = db.components().insertPublicApplication();
  427. db.components().insertComponents(newProjectCopy("PC1", project, application));
  428. RuleDefinitionDto rule = db.rules().insertIssueRule();
  429. db.issues().insertIssue(rule, project, project);
  430. allowAnyoneOnProjects(project);
  431. indexIssuesAndViews();
  432. SearchWsResponse result = ws.newRequest()
  433. .setParam(PARAM_COMPONENT_KEYS, application.getDbKey())
  434. .executeProtobuf(SearchWsResponse.class);
  435. assertThat(result.getIssuesList()).isEmpty();
  436. }
  437. @Test
  438. public void search_application_without_projects() {
  439. ComponentDto project = db.components().insertPublicProject();
  440. ComponentDto application = db.components().insertPublicApplication();
  441. RuleDefinitionDto rule = db.rules().insertIssueRule();
  442. db.issues().insertIssue(rule, project, project);
  443. allowAnyoneOnProjects(project, application);
  444. indexIssuesAndViews();
  445. SearchWsResponse result = ws.newRequest()
  446. .setParam(PARAM_COMPONENT_KEYS, application.getDbKey())
  447. .executeProtobuf(SearchWsResponse.class);
  448. assertThat(result.getIssuesList()).isEmpty();
  449. }
  450. @Test
  451. public void search_by_application_and_by_leak() {
  452. Date now = new Date();
  453. RuleDefinitionDto rule = db.rules().insertIssueRule();
  454. ComponentDto application = db.components().insertPublicApplication();
  455. // Project 1
  456. ComponentDto project1 = db.components().insertPublicProject();
  457. db.components().insertSnapshot(project1, s -> s.setPeriodDate(addDays(now, -14).getTime()));
  458. db.components().insertComponents(newProjectCopy("PC1", project1, application));
  459. IssueDto project1Issue1 = db.issues().insertIssue(rule, project1, project1, i -> i.setIssueCreationDate(addDays(now, -10)));
  460. IssueDto project1Issue2 = db.issues().insertIssue(rule, project1, project1, i -> i.setIssueCreationDate(addDays(now, -20)));
  461. // Project 2
  462. ComponentDto project2 = db.components().insertPublicProject();
  463. db.components().insertSnapshot(project2, s -> s.setPeriodDate(addDays(now, -25).getTime()));
  464. db.components().insertComponents(newProjectCopy("PC2", project2, application));
  465. IssueDto project2Issue1 = db.issues().insertIssue(rule, project2, project2, i -> i.setIssueCreationDate(addDays(now, -15)));
  466. IssueDto project2Issue2 = db.issues().insertIssue(rule, project2, project2, i -> i.setIssueCreationDate(addDays(now, -30)));
  467. // Permissions and index
  468. allowAnyoneOnProjects(project1, project2, application);
  469. indexIssuesAndViews();
  470. SearchWsResponse result = ws.newRequest()
  471. .setParam(PARAM_COMPONENT_KEYS, application.getDbKey())
  472. .setParam(PARAM_SINCE_LEAK_PERIOD, "true")
  473. .executeProtobuf(SearchWsResponse.class);
  474. assertThat(result.getIssuesList()).extracting(Issue::getKey)
  475. .containsExactlyInAnyOrder(project1Issue1.getKey(), project2Issue1.getKey())
  476. .doesNotContain(project1Issue2.getKey(), project2Issue2.getKey());
  477. }
  478. @Test
  479. public void search_by_application_and_project() {
  480. ComponentDto project1 = db.components().insertPublicProject();
  481. ComponentDto project2 = db.components().insertPublicProject();
  482. ComponentDto application = db.components().insertPublicApplication();
  483. db.components().insertComponents(newProjectCopy("PC1", project1, application));
  484. db.components().insertComponents(newProjectCopy("PC2", project2, application));
  485. RuleDefinitionDto rule = db.rules().insertIssueRule();
  486. IssueDto issue1 = db.issues().insertIssue(rule, project1, project1);
  487. IssueDto issue2 = db.issues().insertIssue(rule, project2, project2);
  488. allowAnyoneOnProjects(project1, project2, application);
  489. indexIssuesAndViews();
  490. SearchWsResponse result = ws.newRequest()
  491. .setParam(PARAM_COMPONENT_KEYS, application.getDbKey())
  492. .setParam(PARAM_PROJECTS, project1.getDbKey())
  493. .executeProtobuf(SearchWsResponse.class);
  494. assertThat(result.getIssuesList()).extracting(Issue::getKey)
  495. .containsExactlyInAnyOrder(issue1.getKey())
  496. .doesNotContain(issue2.getKey());
  497. }
  498. @Test
  499. public void search_by_application_and_project_and_leak() {
  500. Date now = new Date();
  501. RuleDefinitionDto rule = db.rules().insertIssueRule();
  502. ComponentDto application = db.components().insertPublicApplication();
  503. // Project 1
  504. ComponentDto project1 = db.components().insertPublicProject();
  505. db.components().insertSnapshot(project1, s -> s.setPeriodDate(addDays(now, -14).getTime()));
  506. db.components().insertComponents(newProjectCopy("PC1", project1, application));
  507. IssueDto project1Issue1 = db.issues().insertIssue(rule, project1, project1, i -> i.setIssueCreationDate(addDays(now, -10)));
  508. IssueDto project1Issue2 = db.issues().insertIssue(rule, project1, project1, i -> i.setIssueCreationDate(addDays(now, -20)));
  509. // Project 2
  510. ComponentDto project2 = db.components().insertPublicProject();
  511. db.components().insertSnapshot(project2, s -> s.setPeriodDate(addDays(now, -25).getTime()));
  512. db.components().insertComponents(newProjectCopy("PC2", project2, application));
  513. IssueDto project2Issue1 = db.issues().insertIssue(rule, project2, project2, i -> i.setIssueCreationDate(addDays(now, -15)));
  514. IssueDto project2Issue2 = db.issues().insertIssue(rule, project2, project2, i -> i.setIssueCreationDate(addDays(now, -30)));
  515. // Permissions and index
  516. allowAnyoneOnProjects(project1, project2, application);
  517. indexIssuesAndViews();
  518. SearchWsResponse result = ws.newRequest()
  519. .setParam(PARAM_COMPONENT_KEYS, application.getDbKey())
  520. .setParam(PARAM_PROJECTS, project1.getDbKey())
  521. .setParam(PARAM_SINCE_LEAK_PERIOD, "true")
  522. .executeProtobuf(SearchWsResponse.class);
  523. assertThat(result.getIssuesList()).extracting(Issue::getKey)
  524. .containsExactlyInAnyOrder(project1Issue1.getKey())
  525. .doesNotContain(project1Issue2.getKey(), project2Issue1.getKey(), project2Issue2.getKey());
  526. }
  527. @Test
  528. public void search_by_application_and_by_leak_when_one_project_has_no_leak() {
  529. Date now = new Date();
  530. RuleDefinitionDto rule = db.rules().insertIssueRule();
  531. ComponentDto application = db.components().insertPublicApplication();
  532. // Project 1
  533. ComponentDto project1 = db.components().insertPublicProject();
  534. db.components().insertSnapshot(project1, s -> s.setPeriodDate(addDays(now, -14).getTime()));
  535. db.components().insertComponents(newProjectCopy("PC1", project1, application));
  536. IssueDto project1Issue1 = db.issues().insertIssue(rule, project1, project1, i -> i.setIssueCreationDate(addDays(now, -10)));
  537. IssueDto project1Issue2 = db.issues().insertIssue(rule, project1, project1, i -> i.setIssueCreationDate(addDays(now, -20)));
  538. // Project 2, without leak => no issue form it should be returned
  539. ComponentDto project2 = db.components().insertPublicProject();
  540. db.components().insertSnapshot(project2, s -> s.setPeriodDate(null));
  541. db.components().insertComponents(newProjectCopy("PC2", project2, application));
  542. IssueDto project2Issue1 = db.issues().insertIssue(rule, project2, project2, i -> i.setIssueCreationDate(addDays(now, -15)));
  543. IssueDto project2Issue2 = db.issues().insertIssue(rule, project2, project2, i -> i.setIssueCreationDate(addDays(now, -30)));
  544. // Permissions and index
  545. allowAnyoneOnProjects(project1, project2, application);
  546. indexIssuesAndViews();
  547. SearchWsResponse result = ws.newRequest()
  548. .setParam(PARAM_COMPONENT_KEYS, application.getDbKey())
  549. .setParam(PARAM_SINCE_LEAK_PERIOD, "true")
  550. .executeProtobuf(SearchWsResponse.class);
  551. assertThat(result.getIssuesList()).extracting(Issue::getKey)
  552. .containsExactlyInAnyOrder(project1Issue1.getKey())
  553. .doesNotContain(project1Issue2.getKey(), project2Issue1.getKey(), project2Issue2.getKey());
  554. }
  555. @Test
  556. public void search_by_branch() {
  557. RuleDefinitionDto rule = db.rules().insertIssueRule();
  558. ComponentDto project = db.components().insertPublicProject();
  559. ComponentDto file = db.components().insertComponent(newFileDto(project));
  560. IssueDto issue = db.issues().insertIssue(rule, project, file);
  561. ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setBranchType(BRANCH));
  562. ComponentDto branchFile = db.components().insertComponent(newFileDto(branch));
  563. IssueDto branchIssue = db.issues().insertIssue(rule, branch, branchFile);
  564. allowAnyoneOnProjects(project);
  565. indexIssuesAndViews();
  566. // On component key + branch
  567. assertThat(ws.newRequest()
  568. .setParam(PARAM_COMPONENT_KEYS, project.getKey())
  569. .setParam(PARAM_BRANCH, branch.getBranch())
  570. .executeProtobuf(SearchWsResponse.class).getIssuesList())
  571. .extracting(Issue::getKey, Issue::getComponent, Issue::getBranch)
  572. .containsExactlyInAnyOrder(tuple(branchIssue.getKey(), branchFile.getKey(), branchFile.getBranch()));
  573. // On project key + branch
  574. assertThat(ws.newRequest()
  575. .setParam(PARAM_PROJECTS, project.getKey())
  576. .setParam(PARAM_BRANCH, branch.getBranch())
  577. .executeProtobuf(SearchWsResponse.class).getIssuesList())
  578. .extracting(Issue::getKey, Issue::getComponent, Issue::getBranch)
  579. .containsExactlyInAnyOrder(tuple(branchIssue.getKey(), branchFile.getKey(), branchFile.getBranch()));
  580. // On file key + branch
  581. assertThat(ws.newRequest()
  582. .setParam(PARAM_COMPONENT_KEYS, branchFile.getKey())
  583. .setParam(PARAM_BRANCH, branch.getBranch())
  584. .executeProtobuf(SearchWsResponse.class).getIssuesList())
  585. .extracting(Issue::getKey, Issue::getComponent, Issue::getBranch)
  586. .containsExactlyInAnyOrder(tuple(branchIssue.getKey(), branchFile.getKey(), branchFile.getBranch()));
  587. }
  588. @Test
  589. public void return_branch_in_component_list() {
  590. RuleDefinitionDto rule = db.rules().insertIssueRule();
  591. ComponentDto project = db.components().insertPrivateProject();
  592. ComponentDto projectFile = db.components().insertComponent(newFileDto(project));
  593. IssueDto projectIssue = db.issues().insertIssue(rule, project, projectFile);
  594. ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setBranchType(BRANCH));
  595. ComponentDto branchFile = db.components().insertComponent(newFileDto(branch));
  596. IssueDto branchIssue = db.issues().insertIssue(rule, branch, branchFile);
  597. allowAnyoneOnProjects(project);
  598. indexIssuesAndViews();
  599. SearchWsResponse result = ws.newRequest()
  600. .setParam(PARAM_COMPONENT_KEYS, branch.getKey())
  601. .setParam(PARAM_BRANCH, branch.getBranch())
  602. .executeProtobuf(SearchWsResponse.class);
  603. assertThat(result.getComponentsList())
  604. .extracting(Issues.Component::getKey, Issues.Component::getBranch)
  605. .containsExactlyInAnyOrder(
  606. tuple(branchFile.getKey(), branchFile.getBranch()),
  607. tuple(branch.getKey(), branch.getBranch()));
  608. }
  609. @Test
  610. public void search_by_pull_request() {
  611. RuleDefinitionDto rule = db.rules().insertIssueRule();
  612. ComponentDto project = db.components().insertPrivateProject();
  613. ComponentDto projectFile = db.components().insertComponent(newFileDto(project));
  614. IssueDto projectIssue = db.issues().insertIssue(rule, project, projectFile);
  615. ComponentDto pullRequest = db.components().insertProjectBranch(project, b -> b.setBranchType(PULL_REQUEST));
  616. ComponentDto pullRequestFile = db.components().insertComponent(newFileDto(pullRequest));
  617. IssueDto pullRequestIssue = db.issues().insertIssue(rule, pullRequest, pullRequestFile);
  618. allowAnyoneOnProjects(project);
  619. indexIssuesAndViews();
  620. SearchWsResponse result = ws.newRequest()
  621. .setParam(PARAM_COMPONENT_KEYS, pullRequest.getKey())
  622. .setParam(PARAM_PULL_REQUEST, pullRequest.getPullRequest())
  623. .executeProtobuf(SearchWsResponse.class);
  624. assertThat(result.getIssuesList())
  625. .extracting(Issue::getKey, Issue::getComponent, Issue::getPullRequest)
  626. .containsExactlyInAnyOrder(tuple(pullRequestIssue.getKey(), pullRequestFile.getKey(), pullRequestFile.getPullRequest()));
  627. assertThat(result.getComponentsList())
  628. .extracting(Issues.Component::getKey, Issues.Component::getPullRequest)
  629. .containsExactlyInAnyOrder(
  630. tuple(pullRequestFile.getKey(), pullRequestFile.getPullRequest()),
  631. tuple(pullRequest.getKey(), pullRequest.getPullRequest()));
  632. }
  633. @Test
  634. public void search_using_main_branch_name() {
  635. RuleDefinitionDto rule = db.rules().insertIssueRule();
  636. ComponentDto project = db.components().insertPublicProject();
  637. ComponentDto projectFile = db.components().insertComponent(newFileDto(project));
  638. IssueDto projectIssue = db.issues().insertIssue(rule, project, projectFile);
  639. allowAnyoneOnProjects(project);
  640. indexIssuesAndViews();
  641. SearchWsResponse result = ws.newRequest()
  642. .setParam(PARAM_COMPONENT_KEYS, project.getKey())
  643. .setParam(PARAM_BRANCH, "master")
  644. .executeProtobuf(SearchWsResponse.class);
  645. assertThat(result.getIssuesList())
  646. .extracting(Issue::getKey, Issue::getComponent, Issue::hasBranch)
  647. .containsExactlyInAnyOrder(tuple(projectIssue.getKey(), projectFile.getKey(), false));
  648. assertThat(result.getComponentsList())
  649. .extracting(Issues.Component::getKey, Issues.Component::hasBranch)
  650. .containsExactlyInAnyOrder(
  651. tuple(projectFile.getKey(), false),
  652. tuple(project.getKey(), false));
  653. }
  654. @Test
  655. public void does_not_return_branch_issues_on_not_contextualized_search() {
  656. RuleDefinitionDto rule = db.rules().insertIssueRule();
  657. ComponentDto project = db.components().insertPrivateProject();
  658. ComponentDto projectFile = db.components().insertComponent(newFileDto(project));
  659. IssueDto projectIssue = db.issues().insertIssue(rule, project, projectFile);
  660. ComponentDto branch = db.components().insertProjectBranch(project);
  661. ComponentDto branchFile = db.components().insertComponent(newFileDto(branch));
  662. IssueDto branchIssue = db.issues().insertIssue(rule, branch, branchFile);
  663. allowAnyoneOnProjects(project);
  664. indexIssuesAndViews();
  665. SearchWsResponse result = ws.newRequest().executeProtobuf(SearchWsResponse.class);
  666. assertThat(result.getIssuesList()).extracting(Issue::getKey)
  667. .containsExactlyInAnyOrder(projectIssue.getKey())
  668. .doesNotContain(branchIssue.getKey());
  669. }
  670. @Test
  671. public void does_not_return_branch_issues_when_using_db_key() {
  672. RuleDefinitionDto rule = db.rules().insertIssueRule();
  673. ComponentDto project = db.components().insertPrivateProject();
  674. ComponentDto projectFile = db.components().insertComponent(newFileDto(project));
  675. IssueDto projectIssue = db.issues().insertIssue(rule, project, projectFile);
  676. ComponentDto branch = db.components().insertProjectBranch(project);
  677. ComponentDto branchFile = db.components().insertComponent(newFileDto(branch));
  678. IssueDto branchIssue = db.issues().insertIssue(rule, branch, branchFile);
  679. allowAnyoneOnProjects(project);
  680. indexIssues();
  681. SearchWsResponse result = ws.newRequest()
  682. .setParam(PARAM_COMPONENT_KEYS, branch.getDbKey())
  683. .executeProtobuf(SearchWsResponse.class);
  684. assertThat(result.getIssuesList()).isEmpty();
  685. }
  686. private void allowAnyoneOnProjects(ComponentDto... projects) {
  687. userSession.registerComponents(projects);
  688. Arrays.stream(projects).forEach(p -> permissionIndexer.allowOnlyAnyone(p));
  689. }
  690. private void indexIssues() {
  691. issueIndexer.indexAllIssues();
  692. }
  693. private void indexIssuesAndViews() {
  694. indexIssues();
  695. viewIndexer.indexAll();
  696. }
  697. }