3 * Copyright (C) 2009-2022 SonarSource SA
4 * mailto:info AT sonarsource DOT com
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.
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.
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.
20 package org.sonar.server.issue.ws;
22 import java.time.Clock;
23 import java.util.Arrays;
24 import java.util.Date;
25 import org.junit.Rule;
26 import org.junit.Test;
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;
60 import static org.assertj.core.api.Assertions.assertThat;
61 import static org.assertj.core.api.Assertions.tuple;
62 import static org.sonar.api.resources.Qualifiers.APP;
63 import static org.sonar.api.utils.DateUtils.addDays;
64 import static org.sonar.api.utils.DateUtils.parseDateTime;
65 import static org.sonar.api.web.UserRole.USER;
66 import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01;
67 import static org.sonar.core.util.Uuids.UUID_EXAMPLE_02;
68 import static org.sonar.db.component.BranchType.BRANCH;
69 import static org.sonar.db.component.BranchType.PULL_REQUEST;
70 import static org.sonar.db.component.ComponentTesting.newDirectory;
71 import static org.sonar.db.component.ComponentTesting.newFileDto;
72 import static org.sonar.db.component.ComponentTesting.newModuleDto;
73 import static org.sonar.db.component.ComponentTesting.newProjectCopy;
74 import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_BRANCH;
75 import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_KEYS;
76 import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_DIRECTORIES;
77 import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_FILES;
78 import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_PROJECTS;
79 import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_PULL_REQUEST;
80 import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_SINCE_LEAK_PERIOD;
82 public class SearchActionComponentsTest {
85 public UserSessionRule userSession = UserSessionRule.standalone();
87 public DbTester db = DbTester.create();
89 public EsTester es = EsTester.create();
91 private DbClient dbClient = db.getDbClient();
92 private IssueIndex issueIndex = new IssueIndex(es.client(), System2.INSTANCE, userSession, new WebAuthorizationTypeSupport(userSession));
93 private IssueIndexer issueIndexer = new IssueIndexer(es.client(), dbClient, new IssueIteratorFactory(dbClient), null);
94 private ViewIndexer viewIndexer = new ViewIndexer(dbClient, es.client());
95 private IssueQueryFactory issueQueryFactory = new IssueQueryFactory(dbClient, Clock.systemUTC(), userSession);
96 private IssueFieldsSetter issueFieldsSetter = new IssueFieldsSetter();
97 private IssueWorkflow issueWorkflow = new IssueWorkflow(new FunctionExecutor(issueFieldsSetter), issueFieldsSetter);
98 private SearchResponseLoader searchResponseLoader = new SearchResponseLoader(userSession, dbClient, new TransitionService(userSession, issueWorkflow));
99 private Languages languages = new Languages();
100 private UserResponseFormatter userFormatter = new UserResponseFormatter(new AvatarResolverImpl());
101 private SearchResponseFormat searchResponseFormat = new SearchResponseFormat(new Durations(), languages, new TextRangeResponseFormatter(), userFormatter);
102 private PermissionIndexerTester permissionIndexer = new PermissionIndexerTester(es, issueIndexer);
104 private IssueIndexSyncProgressChecker issueIndexSyncProgressChecker = new IssueIndexSyncProgressChecker(db.getDbClient());
106 private WsActionTester ws = new WsActionTester(
107 new SearchAction(userSession, issueIndex, issueQueryFactory, issueIndexSyncProgressChecker, searchResponseLoader, searchResponseFormat,
108 System2.INSTANCE, dbClient));
111 public void search_all_issues_when_no_parameter() {
112 RuleDefinitionDto rule = db.rules().insertIssueRule();
113 ComponentDto project = db.components().insertPublicProject();
114 ComponentDto projectFile = db.components().insertComponent(newFileDto(project));
115 IssueDto issue = db.issues().insertIssue(rule, project, projectFile);
116 allowAnyoneOnProjects(project);
119 SearchWsResponse result = ws.newRequest().executeProtobuf(SearchWsResponse.class);
121 assertThat(result.getIssuesList()).extracting(Issues.Issue::getKey)
122 .containsExactlyInAnyOrder(issue.getKey());
126 public void issues_on_different_projects() {
127 RuleDefinitionDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
128 ComponentDto project = db.components().insertPublicProject();
129 ComponentDto file = db.components().insertComponent(newFileDto(project));
130 IssueDto issue1 = db.issues().insertIssue(rule, project, file);
131 ComponentDto project2 = db.components().insertPublicProject();
132 ComponentDto file2 = db.components().insertComponent(newFileDto(project2));
133 IssueDto issue2 = db.issues().insertIssue(rule, project2, file2);
134 allowAnyoneOnProjects(project, project2);
137 SearchWsResponse response = ws.newRequest().executeProtobuf(SearchWsResponse.class);
139 assertThat(response.getIssuesList())
140 .extracting(Issue::getKey, Issue::getComponent, Issue::getProject)
141 .containsExactlyInAnyOrder(
142 tuple(issue1.getKey(), file.getKey(), project.getKey()),
143 tuple(issue2.getKey(), file2.getKey(), project2.getKey()));
144 assertThat(response.getComponentsList())
145 .extracting(Component::getKey, Component::getEnabled)
146 .containsExactlyInAnyOrder(tuple(project.getKey(), true), tuple(file.getKey(), true), tuple(project2.getKey(), true), tuple(file2.getKey(), true));
150 public void search_by_module() {
151 ComponentDto project = db.components().insertPublicProject();
152 ComponentDto module1 = db.components().insertComponent(newModuleDto(project));
153 ComponentDto file1 = db.components().insertComponent(newFileDto(module1));
154 ComponentDto module2 = db.components().insertComponent(newModuleDto(project));
155 ComponentDto file2 = db.components().insertComponent(newFileDto(module2));
156 RuleDefinitionDto rule = db.rules().insertIssueRule();
157 IssueDto issue1 = db.issues().insertIssue(rule, project, file1);
158 IssueDto issue2 = db.issues().insertIssue(rule, project, file2);
159 allowAnyoneOnProjects(project);
162 assertThat(ws.newRequest()
163 .setParam(PARAM_COMPONENT_KEYS, module1.getKey())
164 .executeProtobuf(SearchWsResponse.class).getIssuesList()).extracting(Issue::getKey)
165 .containsExactlyInAnyOrder(issue1.getKey());
169 public void do_not_return_module_key_on_single_module_projects() {
170 ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
171 ComponentDto module = db.components().insertComponent(newModuleDto("M1", project).setDbKey("MK1"));
172 ComponentDto file = db.components().insertComponent(newFileDto(module, null, "F1").setDbKey("FK1"));
173 RuleDefinitionDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
174 db.issues().insertIssue(rule, project, file, i -> i.setKee("ISSUE_IN_MODULE"));
175 db.issues().insertIssue(rule, project, project, i -> i.setKee("ISSUE_IN_ROOT_MODULE"));
176 allowAnyoneOnProjects(project);
179 SearchWsResponse searchResponse = ws.newRequest().executeProtobuf(SearchWsResponse.class);
180 assertThat(searchResponse.getIssuesCount()).isEqualTo(2);
182 for (Issue issue : searchResponse.getIssuesList()) {
183 assertThat(issue.getProject()).isEqualTo("PK1");
184 if (issue.getKey().equals("ISSUE_IN_MODULE")) {
185 assertThat(issue.getSubProject()).isEqualTo("MK1");
186 } else if (issue.getKey().equals("ISSUE_IN_ROOT_MODULE")) {
187 assertThat(issue.hasSubProject()).isFalse();
193 public void search_since_leak_period_on_project() {
194 ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
195 ComponentDto file = db.components().insertComponent(newFileDto(project, null, "F1").setDbKey("FK1"));
196 db.components().insertSnapshot(project, a -> a.setPeriodDate(parseDateTime("2015-09-03T00:00:00+0100").getTime()));
197 RuleDefinitionDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
198 IssueDto issueAfterLeak = db.issues().insertIssue(rule, project, file, i -> i.setKee(UUID_EXAMPLE_01)
199 .setIssueCreationDate(parseDateTime("2015-09-04T00:00:00+0100"))
200 .setIssueUpdateDate(parseDateTime("2015-10-04T00:00:00+0100")));
201 IssueDto issueBeforeLeak = db.issues().insertIssue(rule, project, file, i -> i.setKee(UUID_EXAMPLE_02)
202 .setIssueCreationDate(parseDateTime("2014-09-04T00:00:00+0100"))
203 .setIssueUpdateDate(parseDateTime("2015-10-04T00:00:00+0100")));
204 allowAnyoneOnProjects(project);
208 .setParam(PARAM_COMPONENT_KEYS, project.getDbKey())
209 .setParam(PARAM_SINCE_LEAK_PERIOD, "true")
211 .assertJson(this.getClass(), "search_since_leak_period.json");
215 public void search_since_leak_period_on_file_in_module_project() {
216 ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
217 ComponentDto module = db.components().insertComponent(newModuleDto(project));
218 ComponentDto file = db.components().insertComponent(newFileDto(module, null, "F1").setDbKey("FK1"));
219 db.components().insertSnapshot(project, a -> a.setPeriodDate(parseDateTime("2015-09-03T00:00:00+0100").getTime()));
220 RuleDefinitionDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
221 IssueDto issueAfterLeak = db.issues().insertIssue(rule, project, file, i -> i.setKee(UUID_EXAMPLE_01)
222 .setIssueCreationDate(parseDateTime("2015-09-04T00:00:00+0100"))
223 .setIssueUpdateDate(parseDateTime("2015-10-04T00:00:00+0100")));
224 IssueDto issueBeforeLeak = db.issues().insertIssue(rule, project, file, i -> i.setKee(UUID_EXAMPLE_02)
225 .setIssueCreationDate(parseDateTime("2014-09-04T00:00:00+0100"))
226 .setIssueUpdateDate(parseDateTime("2015-10-04T00:00:00+0100")));
227 allowAnyoneOnProjects(project);
231 .setParam(PARAM_COMPONENT_KEYS, project.getDbKey())
232 .setParam(PARAM_FILES, file.path())
233 .setParam(PARAM_SINCE_LEAK_PERIOD, "true")
235 .assertJson(this.getClass(), "search_since_leak_period.json");
239 public void search_by_file_uuid() {
240 ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
241 ComponentDto file = db.components().insertComponent(newFileDto(project, null, "F1").setDbKey("FK1"));
242 RuleDefinitionDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
243 IssueDto issue = db.issues().insertIssue(rule, project, file, i -> i.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"));
244 allowAnyoneOnProjects(project);
248 .setParam(PARAM_FILES, file.path())
250 .assertJson(this.getClass(), "search_by_file_uuid.json");
253 .setParam(PARAM_FILES, "unknown")
255 .assertJson(this.getClass(), "no_issue.json");
259 public void search_by_file_key() {
260 ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
261 ComponentDto file = db.components().insertComponent(newFileDto(project, null, "F1").setDbKey("FK1"));
262 ComponentDto unitTest = db.components().insertComponent(newFileDto(project, null, "F2").setQualifier(Qualifiers.UNIT_TEST_FILE).setDbKey("FK2"));
263 RuleDefinitionDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
264 IssueDto issueOnFile = db.issues().insertIssue(rule, project, file, i -> i.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"));
265 IssueDto issueOnTest = db.issues().insertIssue(rule, project, unitTest, i -> i.setKee("2bd4eac2-b650-4037-80bc-7b1182fd47d4"));
266 allowAnyoneOnProjects(project);
270 .setParam(PARAM_COMPONENT_KEYS, file.getKey())
272 .assertJson(this.getClass(), "search_by_file_key.json");
275 .setParam(PARAM_COMPONENT_KEYS, unitTest.getKey())
277 .assertJson(this.getClass(), "search_by_test_key.json");
281 public void search_by_directory_path() {
282 ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
283 ComponentDto directory = db.components().insertComponent(newDirectory(project, "D1", "src/main/java/dir"));
284 ComponentDto file = db.components().insertComponent(newFileDto(project, null, "F1").setDbKey("FK1").setPath(directory.path() + "/MyComponent.java"));
285 RuleDefinitionDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
286 db.issues().insertIssue(rule, project, file, i -> i.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"));
287 allowAnyoneOnProjects(project);
291 .setParam(PARAM_COMPONENT_KEYS, directory.getKey())
293 .assertJson(this.getClass(), "search_by_file_uuid.json");
296 .setParam(PARAM_DIRECTORIES, "unknown")
298 .assertJson(this.getClass(), "no_issue.json");
301 .setParam(PARAM_DIRECTORIES, "src/main/java/dir")
303 .assertJson(this.getClass(), "search_by_file_uuid.json");
306 .setParam(PARAM_DIRECTORIES, "src/main/java")
308 .assertJson(this.getClass(), "no_issue.json");
312 public void search_by_directory_path_in_different_modules() {
313 ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
314 ComponentDto module1 = db.components().insertComponent(newModuleDto("M1", project).setDbKey("MK1"));
315 ComponentDto module2 = db.components().insertComponent(newModuleDto("M2", project).setDbKey("MK2"));
316 ComponentDto directory1 = db.components().insertComponent(newDirectory(module1, "D1", "src/main/java/dir"));
317 ComponentDto directory2 = db.components().insertComponent(newDirectory(module2, "D2", "src/main/java/dir"));
318 ComponentDto file1 = db.components().insertComponent(newFileDto(module1, directory1, "F1").setDbKey("FK1").setPath(directory1.path() + "/MyComponent.java"));
319 db.components().insertComponent(newFileDto(module2, directory2, "F2").setDbKey("FK2").setPath(directory2.path() + "/MyComponent.java"));
320 RuleDefinitionDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
321 db.issues().insertIssue(rule, project, file1, i -> i.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"));
322 allowAnyoneOnProjects(project);
326 .setParam(PARAM_COMPONENT_KEYS, directory1.getKey())
328 .assertJson(this.getClass(), "search_by_directory_uuid.json");
331 .setParam(PARAM_COMPONENT_KEYS, directory2.getKey())
333 .assertJson(this.getClass(), "no_issue.json");
336 .setParam(PARAM_DIRECTORIES, "src/main/java/dir")
338 .assertJson(this.getClass(), "search_by_directory_uuid.json");
341 .setParam(PARAM_DIRECTORIES, "src/main/java")
343 .assertJson(this.getClass(), "no_issue.json");
347 public void search_by_view_uuid() {
348 ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
349 ComponentDto file = db.components().insertComponent(newFileDto(project, null, "F1").setDbKey("FK1"));
350 ComponentDto view = db.components().insertComponent(ComponentTesting.newPortfolio("V1").setDbKey("MyView"));
351 db.components().insertComponent(newProjectCopy(project, view));
352 RuleDefinitionDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
353 db.issues().insertIssue(rule, project, file, i -> i.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"));
354 allowAnyoneOnProjects(project, view);
355 indexIssuesAndViews();
358 .setParam(PARAM_COMPONENT_KEYS, view.getKey())
360 .assertJson(this.getClass(), "search_by_view_uuid.json");
364 public void search_by_sub_view_uuid() {
365 ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
366 ComponentDto file = db.components().insertComponent(newFileDto(project, null, "F1").setDbKey("FK1"));
367 RuleDefinitionDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
368 db.issues().insertIssue(rule, project, file, i -> i.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"));
369 ComponentDto view = db.components().insertComponent(ComponentTesting.newPortfolio("V1").setDbKey("MyView"));
370 ComponentDto subView = db.components().insertComponent(ComponentTesting.newSubPortfolio(view, "SV1", "MySubView"));
371 db.components().insertComponent(newProjectCopy(project, subView));
372 allowAnyoneOnProjects(project, view, subView);
373 indexIssuesAndViews();
376 .setParam(PARAM_COMPONENT_KEYS, subView.getKey())
378 .assertJson(this.getClass(), "search_by_view_uuid.json");
382 public void search_by_sub_view_uuid_return_only_authorized_view() {
383 ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
384 ComponentDto file = db.components().insertComponent(newFileDto(project, null, "F1").setDbKey("FK1"));
385 RuleDefinitionDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
386 db.issues().insertIssue(rule, project, file, i -> i.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"));
387 ComponentDto view = db.components().insertComponent(ComponentTesting.newPortfolio("V1").setDbKey("MyView"));
388 ComponentDto subView = db.components().insertComponent(ComponentTesting.newSubPortfolio(view, "SV1", "MySubView"));
389 db.components().insertComponent(newProjectCopy(project, subView));
390 // User has no permission on the view, no issue will be returned
391 allowAnyoneOnProjects(project);
392 indexIssuesAndViews();
395 .setParam(PARAM_COMPONENT_KEYS, subView.getKey())
397 .assertJson(this.getClass(), "no_issue.json");
401 public void search_by_application_key() {
402 ComponentDto application = db.components().insertPrivateApplication();
403 ComponentDto project1 = db.components().insertPrivateProject();
404 ComponentDto project2 = db.components().insertPrivateProject();
405 db.components().insertComponents(newProjectCopy(project1, application));
406 db.components().insertComponents(newProjectCopy(project2, application));
407 RuleDefinitionDto rule = db.rules().insertIssueRule();
408 IssueDto issue1 = db.issues().insertIssue(rule, project1, project1);
409 IssueDto issue2 = db.issues().insertIssue(rule, project2, project2);
410 allowAnyoneOnApplication(application, project1, project2);
411 userSession.addProjectPermission(USER, application);
412 indexIssuesAndViews();
414 SearchWsResponse result = ws.newRequest()
415 .setParam(PARAM_COMPONENT_KEYS, application.getDbKey())
416 .executeProtobuf(SearchWsResponse.class);
418 assertThat(result.getIssuesList()).extracting(Issue::getKey)
419 .containsExactlyInAnyOrder(issue1.getKey(), issue2.getKey());
423 public void search_by_application_key_and_branch() {
424 ComponentDto application = db.components().insertPrivateProject(c -> c.setQualifier(APP).setDbKey("app"));
425 ComponentDto applicationBranch1 = db.components().insertProjectBranch(application, a -> a.setKey("app-branch1"));
426 ComponentDto applicationBranch2 = db.components().insertProjectBranch(application, a -> a.setKey("app-branch2"));
427 ComponentDto project1 = db.components().insertPrivateProject(p -> p.setDbKey("prj1"));
428 ComponentDto project1Branch1 = db.components().insertProjectBranch(project1);
429 ComponentDto fileOnProject1Branch1 = db.components().insertComponent(newFileDto(project1Branch1));
430 ComponentDto project1Branch2 = db.components().insertProjectBranch(project1);
431 ComponentDto project2 = db.components().insertPrivateProject(p -> p.setDbKey("prj2"));
432 db.components().insertComponents(newProjectCopy(project1Branch1, applicationBranch1));
433 db.components().insertComponents(newProjectCopy(project2, applicationBranch1));
434 db.components().insertComponents(newProjectCopy(project1Branch2, applicationBranch2));
436 RuleDefinitionDto issueRule = db.rules().insertIssueRule();
437 RuleDefinitionDto hotspotRule = db.rules().insertHotspotRule();
438 IssueDto issueOnProject1 = db.issues().insertIssue(issueRule, project1, project1);
439 IssueDto issueOnProject1Branch1 = db.issues().insertIssue(issueRule, project1Branch1, project1Branch1);
440 db.issues().insertHotspot(hotspotRule, project1Branch1, project1Branch1);
441 IssueDto issueOnFileOnProject1Branch1 = db.issues().insertIssue(issueRule, project1Branch1, fileOnProject1Branch1);
442 IssueDto issueOnProject1Branch2 = db.issues().insertIssue(issueRule, project1Branch2, project1Branch2);
443 IssueDto issueOnProject2 = db.issues().insertIssue(issueRule, project2, project2);
444 db.issues().insertHotspot(hotspotRule, project2, project2);
445 allowAnyoneOnProjects(project1, project2, application);
446 userSession.addProjectPermission(USER, application);
447 indexIssuesAndViews();
449 // All issues on applicationBranch1
450 assertThat(ws.newRequest()
451 .setParam(PARAM_COMPONENT_KEYS, applicationBranch1.getKey())
452 .setParam(PARAM_BRANCH, applicationBranch1.getBranch())
453 .executeProtobuf(SearchWsResponse.class).getIssuesList())
454 .extracting(Issue::getKey, Issue::getComponent, Issue::getProject, Issue::getBranch, Issue::hasBranch)
455 .containsExactlyInAnyOrder(
456 tuple(issueOnProject1Branch1.getKey(), project1Branch1.getKey(), project1Branch1.getKey(), project1Branch1.getBranch(), true),
457 tuple(issueOnFileOnProject1Branch1.getKey(), fileOnProject1Branch1.getKey(), project1Branch1.getKey(), project1Branch1.getBranch(), true),
458 tuple(issueOnProject2.getKey(), project2.getKey(), project2.getKey(), "", false));
460 // Issues on project1Branch1
461 assertThat(ws.newRequest()
462 .setParam(PARAM_COMPONENT_KEYS, applicationBranch1.getKey())
463 .setParam(PARAM_PROJECTS, project1.getKey())
464 .setParam(PARAM_BRANCH, applicationBranch1.getBranch())
465 .executeProtobuf(SearchWsResponse.class).getIssuesList())
466 .extracting(Issue::getKey, Issue::getComponent, Issue::getBranch)
467 .containsExactlyInAnyOrder(
468 tuple(issueOnProject1Branch1.getKey(), project1Branch1.getKey(), project1Branch1.getBranch()),
469 tuple(issueOnFileOnProject1Branch1.getKey(), fileOnProject1Branch1.getKey(), project1Branch1.getBranch()));
473 public void ignore_application_without_browse_permission() {
474 ComponentDto project = db.components().insertPublicProject();
475 ComponentDto application = db.components().insertPublicApplication();
476 db.components().insertComponents(newProjectCopy("PC1", project, application));
477 RuleDefinitionDto rule = db.rules().insertIssueRule();
478 db.issues().insertIssue(rule, project, project);
479 allowAnyoneOnProjects(project);
480 indexIssuesAndViews();
482 SearchWsResponse result = ws.newRequest()
483 .setParam(PARAM_COMPONENT_KEYS, application.getDbKey())
484 .executeProtobuf(SearchWsResponse.class);
486 assertThat(result.getIssuesList()).isEmpty();
490 public void search_application_without_projects() {
491 ComponentDto project = db.components().insertPublicProject();
492 ComponentDto application = db.components().insertPublicApplication();
493 RuleDefinitionDto rule = db.rules().insertIssueRule();
494 db.issues().insertIssue(rule, project, project);
495 allowAnyoneOnProjects(project, application);
496 indexIssuesAndViews();
498 SearchWsResponse result = ws.newRequest()
499 .setParam(PARAM_COMPONENT_KEYS, application.getDbKey())
500 .executeProtobuf(SearchWsResponse.class);
502 assertThat(result.getIssuesList()).isEmpty();
506 public void search_by_application_and_by_leak() {
507 Date now = new Date();
508 RuleDefinitionDto rule = db.rules().insertIssueRule();
509 ComponentDto application = db.components().insertPublicApplication();
511 ComponentDto project1 = db.components().insertPublicProject();
512 db.components().insertSnapshot(project1, s -> s.setPeriodDate(addDays(now, -14).getTime()));
513 db.components().insertComponents(newProjectCopy("PC1", project1, application));
514 IssueDto project1Issue1 = db.issues().insertIssue(rule, project1, project1, i -> i.setIssueCreationDate(addDays(now, -10)));
515 IssueDto project1Issue2 = db.issues().insertIssue(rule, project1, project1, i -> i.setIssueCreationDate(addDays(now, -20)));
517 ComponentDto project2 = db.components().insertPublicProject();
518 db.components().insertSnapshot(project2, s -> s.setPeriodDate(addDays(now, -25).getTime()));
519 db.components().insertComponents(newProjectCopy("PC2", project2, application));
520 IssueDto project2Issue1 = db.issues().insertIssue(rule, project2, project2, i -> i.setIssueCreationDate(addDays(now, -15)));
521 IssueDto project2Issue2 = db.issues().insertIssue(rule, project2, project2, i -> i.setIssueCreationDate(addDays(now, -30)));
522 // Permissions and index
523 allowAnyoneOnApplication(application, project1, project2);
524 indexIssuesAndViews();
526 SearchWsResponse result = ws.newRequest()
527 .setParam(PARAM_COMPONENT_KEYS, application.getDbKey())
528 .setParam(PARAM_SINCE_LEAK_PERIOD, "true")
529 .executeProtobuf(SearchWsResponse.class);
531 assertThat(result.getIssuesList()).extracting(Issue::getKey)
532 .containsExactlyInAnyOrder(project1Issue1.getKey(), project2Issue1.getKey())
533 .doesNotContain(project1Issue2.getKey(), project2Issue2.getKey());
537 public void search_by_application_and_project() {
538 ComponentDto project1 = db.components().insertPublicProject();
539 ComponentDto project2 = db.components().insertPublicProject();
540 ComponentDto application = db.components().insertPublicApplication();
541 db.components().insertComponents(newProjectCopy("PC1", project1, application));
542 db.components().insertComponents(newProjectCopy("PC2", project2, application));
543 RuleDefinitionDto rule = db.rules().insertIssueRule();
544 IssueDto issue1 = db.issues().insertIssue(rule, project1, project1);
545 IssueDto issue2 = db.issues().insertIssue(rule, project2, project2);
546 allowAnyoneOnApplication(application, project1, project2);
547 indexIssuesAndViews();
549 SearchWsResponse result = ws.newRequest()
550 .setParam(PARAM_COMPONENT_KEYS, application.getDbKey())
551 .setParam(PARAM_PROJECTS, project1.getDbKey())
552 .executeProtobuf(SearchWsResponse.class);
554 assertThat(result.getIssuesList()).extracting(Issue::getKey)
555 .containsExactlyInAnyOrder(issue1.getKey())
556 .doesNotContain(issue2.getKey());
560 public void search_by_application_and_project_and_leak() {
561 Date now = new Date();
562 RuleDefinitionDto rule = db.rules().insertIssueRule();
563 ComponentDto application = db.components().insertPublicApplication();
565 ComponentDto project1 = db.components().insertPublicProject();
566 db.components().insertSnapshot(project1, s -> s.setPeriodDate(addDays(now, -14).getTime()));
567 db.components().insertComponents(newProjectCopy("PC1", project1, application));
568 IssueDto project1Issue1 = db.issues().insertIssue(rule, project1, project1, i -> i.setIssueCreationDate(addDays(now, -10)));
569 IssueDto project1Issue2 = db.issues().insertIssue(rule, project1, project1, i -> i.setIssueCreationDate(addDays(now, -20)));
571 ComponentDto project2 = db.components().insertPublicProject();
572 db.components().insertSnapshot(project2, s -> s.setPeriodDate(addDays(now, -25).getTime()));
573 db.components().insertComponents(newProjectCopy("PC2", project2, application));
574 IssueDto project2Issue1 = db.issues().insertIssue(rule, project2, project2, i -> i.setIssueCreationDate(addDays(now, -15)));
575 IssueDto project2Issue2 = db.issues().insertIssue(rule, project2, project2, i -> i.setIssueCreationDate(addDays(now, -30)));
576 // Permissions and index
577 allowAnyoneOnApplication(application, project1, project2);
578 indexIssuesAndViews();
580 SearchWsResponse result = ws.newRequest()
581 .setParam(PARAM_COMPONENT_KEYS, application.getDbKey())
582 .setParam(PARAM_PROJECTS, project1.getDbKey())
583 .setParam(PARAM_SINCE_LEAK_PERIOD, "true")
584 .executeProtobuf(SearchWsResponse.class);
586 assertThat(result.getIssuesList()).extracting(Issue::getKey)
587 .containsExactlyInAnyOrder(project1Issue1.getKey())
588 .doesNotContain(project1Issue2.getKey(), project2Issue1.getKey(), project2Issue2.getKey());
592 public void search_by_application_and_by_leak_when_one_project_has_no_leak() {
593 Date now = new Date();
594 RuleDefinitionDto rule = db.rules().insertIssueRule();
595 ComponentDto application = db.components().insertPublicApplication();
597 ComponentDto project1 = db.components().insertPublicProject();
598 db.components().insertSnapshot(project1, s -> s.setPeriodDate(addDays(now, -14).getTime()));
599 db.components().insertComponents(newProjectCopy("PC1", project1, application));
600 IssueDto project1Issue1 = db.issues().insertIssue(rule, project1, project1, i -> i.setIssueCreationDate(addDays(now, -10)));
601 IssueDto project1Issue2 = db.issues().insertIssue(rule, project1, project1, i -> i.setIssueCreationDate(addDays(now, -20)));
602 // Project 2, without leak => no issue form it should be returned
603 ComponentDto project2 = db.components().insertPublicProject();
604 db.components().insertSnapshot(project2, s -> s.setPeriodDate(null));
605 db.components().insertComponents(newProjectCopy("PC2", project2, application));
606 IssueDto project2Issue1 = db.issues().insertIssue(rule, project2, project2, i -> i.setIssueCreationDate(addDays(now, -15)));
607 IssueDto project2Issue2 = db.issues().insertIssue(rule, project2, project2, i -> i.setIssueCreationDate(addDays(now, -30)));
608 // Permissions and index
609 allowAnyoneOnApplication(application, project1, project2);
610 indexIssuesAndViews();
612 SearchWsResponse result = ws.newRequest()
613 .setParam(PARAM_COMPONENT_KEYS, application.getDbKey())
614 .setParam(PARAM_SINCE_LEAK_PERIOD, "true")
615 .executeProtobuf(SearchWsResponse.class);
617 assertThat(result.getIssuesList()).extracting(Issue::getKey)
618 .containsExactlyInAnyOrder(project1Issue1.getKey())
619 .doesNotContain(project1Issue2.getKey(), project2Issue1.getKey(), project2Issue2.getKey());
623 public void search_by_branch() {
624 RuleDefinitionDto rule = db.rules().insertIssueRule();
625 ComponentDto project = db.components().insertPublicProject();
626 ComponentDto file = db.components().insertComponent(newFileDto(project));
627 IssueDto issue = db.issues().insertIssue(rule, project, file);
629 ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setBranchType(BRANCH));
630 ComponentDto branchFile = db.components().insertComponent(newFileDto(branch));
631 IssueDto branchIssue = db.issues().insertIssue(rule, branch, branchFile);
632 allowAnyoneOnProjects(project);
633 indexIssuesAndViews();
635 // On component key + branch
636 assertThat(ws.newRequest()
637 .setParam(PARAM_COMPONENT_KEYS, project.getKey())
638 .setParam(PARAM_BRANCH, branch.getBranch())
639 .executeProtobuf(SearchWsResponse.class).getIssuesList())
640 .extracting(Issue::getKey, Issue::getComponent, Issue::getBranch)
641 .containsExactlyInAnyOrder(tuple(branchIssue.getKey(), branchFile.getKey(), branchFile.getBranch()));
643 // On project key + branch
644 assertThat(ws.newRequest()
645 .setParam(PARAM_PROJECTS, project.getKey())
646 .setParam(PARAM_BRANCH, branch.getBranch())
647 .executeProtobuf(SearchWsResponse.class).getIssuesList())
648 .extracting(Issue::getKey, Issue::getComponent, Issue::getBranch)
649 .containsExactlyInAnyOrder(tuple(branchIssue.getKey(), branchFile.getKey(), branchFile.getBranch()));
650 // On file key + branch
651 assertThat(ws.newRequest()
652 .setParam(PARAM_COMPONENT_KEYS, branchFile.getKey())
653 .setParam(PARAM_BRANCH, branch.getBranch())
654 .executeProtobuf(SearchWsResponse.class).getIssuesList())
655 .extracting(Issue::getKey, Issue::getComponent, Issue::getBranch)
656 .containsExactlyInAnyOrder(tuple(branchIssue.getKey(), branchFile.getKey(), branchFile.getBranch()));
660 public void return_branch_in_component_list() {
661 RuleDefinitionDto rule = db.rules().insertIssueRule();
662 ComponentDto project = db.components().insertPrivateProject();
663 ComponentDto projectFile = db.components().insertComponent(newFileDto(project));
664 IssueDto projectIssue = db.issues().insertIssue(rule, project, projectFile);
665 ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setBranchType(BRANCH));
666 ComponentDto branchFile = db.components().insertComponent(newFileDto(branch));
667 IssueDto branchIssue = db.issues().insertIssue(rule, branch, branchFile);
668 allowAnyoneOnProjects(project);
669 indexIssuesAndViews();
671 SearchWsResponse result = ws.newRequest()
672 .setParam(PARAM_COMPONENT_KEYS, branch.getKey())
673 .setParam(PARAM_BRANCH, branch.getBranch())
674 .executeProtobuf(SearchWsResponse.class);
676 assertThat(result.getComponentsList())
677 .extracting(Issues.Component::getKey, Issues.Component::getBranch)
678 .containsExactlyInAnyOrder(
679 tuple(branchFile.getKey(), branchFile.getBranch()),
680 tuple(branch.getKey(), branch.getBranch()));
684 public void search_by_pull_request() {
685 RuleDefinitionDto rule = db.rules().insertIssueRule();
686 ComponentDto project = db.components().insertPrivateProject();
687 ComponentDto projectFile = db.components().insertComponent(newFileDto(project));
688 IssueDto projectIssue = db.issues().insertIssue(rule, project, projectFile);
689 ComponentDto pullRequest = db.components().insertProjectBranch(project, b -> b.setBranchType(PULL_REQUEST));
690 ComponentDto pullRequestFile = db.components().insertComponent(newFileDto(pullRequest));
691 IssueDto pullRequestIssue = db.issues().insertIssue(rule, pullRequest, pullRequestFile);
692 allowAnyoneOnProjects(project);
693 indexIssuesAndViews();
695 SearchWsResponse result = ws.newRequest()
696 .setParam(PARAM_COMPONENT_KEYS, pullRequest.getKey())
697 .setParam(PARAM_PULL_REQUEST, pullRequest.getPullRequest())
698 .executeProtobuf(SearchWsResponse.class);
700 assertThat(result.getIssuesList())
701 .extracting(Issue::getKey, Issue::getComponent, Issue::getPullRequest)
702 .containsExactlyInAnyOrder(tuple(pullRequestIssue.getKey(), pullRequestFile.getKey(), pullRequestFile.getPullRequest()));
703 assertThat(result.getComponentsList())
704 .extracting(Issues.Component::getKey, Issues.Component::getPullRequest)
705 .containsExactlyInAnyOrder(
706 tuple(pullRequestFile.getKey(), pullRequestFile.getPullRequest()),
707 tuple(pullRequest.getKey(), pullRequest.getPullRequest()));
711 public void search_using_main_branch_name() {
712 RuleDefinitionDto rule = db.rules().insertIssueRule();
713 ComponentDto project = db.components().insertPublicProject();
714 ComponentDto projectFile = db.components().insertComponent(newFileDto(project));
715 IssueDto projectIssue = db.issues().insertIssue(rule, project, projectFile);
716 allowAnyoneOnProjects(project);
717 indexIssuesAndViews();
719 SearchWsResponse result = ws.newRequest()
720 .setParam(PARAM_COMPONENT_KEYS, project.getKey())
721 .setParam(PARAM_BRANCH, "master")
722 .executeProtobuf(SearchWsResponse.class);
724 assertThat(result.getIssuesList())
725 .extracting(Issue::getKey, Issue::getComponent, Issue::hasBranch)
726 .containsExactlyInAnyOrder(tuple(projectIssue.getKey(), projectFile.getKey(), false));
727 assertThat(result.getComponentsList())
728 .extracting(Issues.Component::getKey, Issues.Component::hasBranch)
729 .containsExactlyInAnyOrder(
730 tuple(projectFile.getKey(), false),
731 tuple(project.getKey(), false));
735 public void does_not_return_branch_issues_on_not_contextualized_search() {
736 RuleDefinitionDto rule = db.rules().insertIssueRule();
737 ComponentDto project = db.components().insertPrivateProject();
738 ComponentDto projectFile = db.components().insertComponent(newFileDto(project));
739 IssueDto projectIssue = db.issues().insertIssue(rule, project, projectFile);
740 ComponentDto branch = db.components().insertProjectBranch(project);
741 ComponentDto branchFile = db.components().insertComponent(newFileDto(branch));
742 IssueDto branchIssue = db.issues().insertIssue(rule, branch, branchFile);
743 allowAnyoneOnProjects(project);
744 indexIssuesAndViews();
746 SearchWsResponse result = ws.newRequest().executeProtobuf(SearchWsResponse.class);
748 assertThat(result.getIssuesList()).extracting(Issue::getKey)
749 .containsExactlyInAnyOrder(projectIssue.getKey())
750 .doesNotContain(branchIssue.getKey());
754 public void does_not_return_branch_issues_when_using_db_key() {
755 RuleDefinitionDto rule = db.rules().insertIssueRule();
756 ComponentDto project = db.components().insertPrivateProject();
757 ComponentDto projectFile = db.components().insertComponent(newFileDto(project));
758 IssueDto projectIssue = db.issues().insertIssue(rule, project, projectFile);
759 ComponentDto branch = db.components().insertProjectBranch(project);
760 ComponentDto branchFile = db.components().insertComponent(newFileDto(branch));
761 IssueDto branchIssue = db.issues().insertIssue(rule, branch, branchFile);
762 allowAnyoneOnProjects(project);
765 SearchWsResponse result = ws.newRequest()
766 .setParam(PARAM_COMPONENT_KEYS, branch.getDbKey())
767 .executeProtobuf(SearchWsResponse.class);
769 assertThat(result.getIssuesList()).isEmpty();
772 private void allowAnyoneOnProjects(ComponentDto... projects) {
773 userSession.registerComponents(projects);
774 Arrays.stream(projects).forEach(p -> permissionIndexer.allowOnlyAnyone(p));
777 private void allowAnyoneOnApplication(ComponentDto application, ComponentDto... projects) {
778 userSession.registerApplication(application);
779 Arrays.stream(projects).forEach(p -> permissionIndexer.allowOnlyAnyone(p));
782 private void indexIssues() {
783 issueIndexer.indexAllIssues();
786 private void indexIssuesAndViews() {
788 viewIndexer.indexAll();