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.RuleDto;
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 RuleDto 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 RuleDto 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 RuleDto 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 search_since_leak_period_on_project() {
170 ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
171 ComponentDto file = db.components().insertComponent(newFileDto(project, null, "F1").setDbKey("FK1"));
172 db.components().insertSnapshot(project, a -> a.setPeriodDate(parseDateTime("2015-09-03T00:00:00+0100").getTime()));
173 RuleDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
174 IssueDto issueAfterLeak = db.issues().insertIssue(rule, project, file, i -> i.setKee(UUID_EXAMPLE_01)
175 .setIssueCreationDate(parseDateTime("2015-09-04T00:00:00+0100"))
176 .setIssueUpdateDate(parseDateTime("2015-10-04T00:00:00+0100")));
177 IssueDto issueBeforeLeak = db.issues().insertIssue(rule, project, file, i -> i.setKee(UUID_EXAMPLE_02)
178 .setIssueCreationDate(parseDateTime("2014-09-04T00:00:00+0100"))
179 .setIssueUpdateDate(parseDateTime("2015-10-04T00:00:00+0100")));
180 allowAnyoneOnProjects(project);
184 .setParam(PARAM_COMPONENT_KEYS, project.getDbKey())
185 .setParam(PARAM_SINCE_LEAK_PERIOD, "true")
187 .assertJson(this.getClass(), "search_since_leak_period.json");
191 public void search_since_leak_period_on_file_in_module_project() {
192 ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
193 ComponentDto module = db.components().insertComponent(newModuleDto(project));
194 ComponentDto file = db.components().insertComponent(newFileDto(module, null, "F1").setDbKey("FK1"));
195 db.components().insertSnapshot(project, a -> a.setPeriodDate(parseDateTime("2015-09-03T00:00:00+0100").getTime()));
196 RuleDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
197 IssueDto issueAfterLeak = db.issues().insertIssue(rule, project, file, i -> i.setKee(UUID_EXAMPLE_01)
198 .setIssueCreationDate(parseDateTime("2015-09-04T00:00:00+0100"))
199 .setIssueUpdateDate(parseDateTime("2015-10-04T00:00:00+0100")));
200 IssueDto issueBeforeLeak = db.issues().insertIssue(rule, project, file, i -> i.setKee(UUID_EXAMPLE_02)
201 .setIssueCreationDate(parseDateTime("2014-09-04T00:00:00+0100"))
202 .setIssueUpdateDate(parseDateTime("2015-10-04T00:00:00+0100")));
203 allowAnyoneOnProjects(project);
207 .setParam(PARAM_COMPONENT_KEYS, project.getDbKey())
208 .setParam(PARAM_FILES, file.path())
209 .setParam(PARAM_SINCE_LEAK_PERIOD, "true")
211 .assertJson(this.getClass(), "search_since_leak_period.json");
215 public void search_by_file_uuid() {
216 ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
217 ComponentDto file = db.components().insertComponent(newFileDto(project, null, "F1").setDbKey("FK1"));
218 RuleDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
219 IssueDto issue = db.issues().insertIssue(rule, project, file, i -> i.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"));
220 allowAnyoneOnProjects(project);
224 .setParam(PARAM_FILES, file.path())
226 .assertJson(this.getClass(), "search_by_file_uuid.json");
229 .setParam(PARAM_FILES, "unknown")
231 .assertJson(this.getClass(), "no_issue.json");
235 public void search_by_file_key() {
236 ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
237 ComponentDto file = db.components().insertComponent(newFileDto(project, null, "F1").setDbKey("FK1"));
238 ComponentDto unitTest = db.components().insertComponent(newFileDto(project, null, "F2").setQualifier(Qualifiers.UNIT_TEST_FILE).setDbKey("FK2"));
239 RuleDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
240 IssueDto issueOnFile = db.issues().insertIssue(rule, project, file, i -> i.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"));
241 IssueDto issueOnTest = db.issues().insertIssue(rule, project, unitTest, i -> i.setKee("2bd4eac2-b650-4037-80bc-7b1182fd47d4"));
242 allowAnyoneOnProjects(project);
246 .setParam(PARAM_COMPONENT_KEYS, file.getKey())
248 .assertJson(this.getClass(), "search_by_file_key.json");
251 .setParam(PARAM_COMPONENT_KEYS, unitTest.getKey())
253 .assertJson(this.getClass(), "search_by_test_key.json");
257 public void search_by_directory_path() {
258 ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
259 ComponentDto directory = db.components().insertComponent(newDirectory(project, "D1", "src/main/java/dir"));
260 ComponentDto file = db.components().insertComponent(newFileDto(project, null, "F1").setDbKey("FK1").setPath(directory.path() + "/MyComponent.java"));
261 RuleDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
262 db.issues().insertIssue(rule, project, file, i -> i.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"));
263 allowAnyoneOnProjects(project);
267 .setParam(PARAM_COMPONENT_KEYS, directory.getKey())
269 .assertJson(this.getClass(), "search_by_file_uuid.json");
272 .setParam(PARAM_DIRECTORIES, "unknown")
274 .assertJson(this.getClass(), "no_issue.json");
277 .setParam(PARAM_DIRECTORIES, "src/main/java/dir")
279 .assertJson(this.getClass(), "search_by_file_uuid.json");
282 .setParam(PARAM_DIRECTORIES, "src/main/java")
284 .assertJson(this.getClass(), "no_issue.json");
288 public void search_by_view_uuid() {
289 ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
290 ComponentDto file = db.components().insertComponent(newFileDto(project, null, "F1").setDbKey("FK1"));
291 ComponentDto view = db.components().insertComponent(ComponentTesting.newPortfolio("V1").setDbKey("MyView"));
292 db.components().insertComponent(newProjectCopy(project, view));
293 RuleDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
294 db.issues().insertIssue(rule, project, file, i -> i.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"));
295 allowAnyoneOnProjects(project, view);
296 indexIssuesAndViews();
299 .setParam(PARAM_COMPONENT_KEYS, view.getKey())
301 .assertJson(this.getClass(), "search_by_view_uuid.json");
305 public void search_by_sub_view_uuid() {
306 ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
307 ComponentDto file = db.components().insertComponent(newFileDto(project, null, "F1").setDbKey("FK1"));
308 RuleDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
309 db.issues().insertIssue(rule, project, file, i -> i.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"));
310 ComponentDto view = db.components().insertComponent(ComponentTesting.newPortfolio("V1").setDbKey("MyView"));
311 ComponentDto subView = db.components().insertComponent(ComponentTesting.newSubPortfolio(view, "SV1", "MySubView"));
312 db.components().insertComponent(newProjectCopy(project, subView));
313 allowAnyoneOnProjects(project, view, subView);
314 indexIssuesAndViews();
317 .setParam(PARAM_COMPONENT_KEYS, subView.getKey())
319 .assertJson(this.getClass(), "search_by_view_uuid.json");
323 public void search_by_sub_view_uuid_return_only_authorized_view() {
324 ComponentDto project = db.components().insertPublicProject(p -> p.setDbKey("PK1"));
325 ComponentDto file = db.components().insertComponent(newFileDto(project, null, "F1").setDbKey("FK1"));
326 RuleDto rule = db.rules().insertIssueRule(r -> r.setRuleKey(RuleKey.of("xoo", "x1")));
327 db.issues().insertIssue(rule, project, file, i -> i.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"));
328 ComponentDto view = db.components().insertComponent(ComponentTesting.newPortfolio("V1").setDbKey("MyView"));
329 ComponentDto subView = db.components().insertComponent(ComponentTesting.newSubPortfolio(view, "SV1", "MySubView"));
330 db.components().insertComponent(newProjectCopy(project, subView));
331 // User has no permission on the view, no issue will be returned
332 allowAnyoneOnProjects(project);
333 indexIssuesAndViews();
336 .setParam(PARAM_COMPONENT_KEYS, subView.getKey())
338 .assertJson(this.getClass(), "no_issue.json");
342 public void search_by_application_key() {
343 ComponentDto application = db.components().insertPrivateApplication();
344 ComponentDto project1 = db.components().insertPrivateProject();
345 ComponentDto project2 = db.components().insertPrivateProject();
346 db.components().insertComponents(newProjectCopy(project1, application));
347 db.components().insertComponents(newProjectCopy(project2, application));
348 RuleDto rule = db.rules().insertIssueRule();
349 IssueDto issue1 = db.issues().insertIssue(rule, project1, project1);
350 IssueDto issue2 = db.issues().insertIssue(rule, project2, project2);
351 allowAnyoneOnApplication(application, project1, project2);
352 userSession.addProjectPermission(USER, application);
353 indexIssuesAndViews();
355 SearchWsResponse result = ws.newRequest()
356 .setParam(PARAM_COMPONENT_KEYS, application.getDbKey())
357 .executeProtobuf(SearchWsResponse.class);
359 assertThat(result.getIssuesList()).extracting(Issue::getKey)
360 .containsExactlyInAnyOrder(issue1.getKey(), issue2.getKey());
364 public void search_by_application_key_and_branch() {
365 ComponentDto application = db.components().insertPrivateProject(c -> c.setQualifier(APP).setDbKey("app"));
366 ComponentDto applicationBranch1 = db.components().insertProjectBranch(application, a -> a.setKey("app-branch1"));
367 ComponentDto applicationBranch2 = db.components().insertProjectBranch(application, a -> a.setKey("app-branch2"));
368 ComponentDto project1 = db.components().insertPrivateProject(p -> p.setDbKey("prj1"));
369 ComponentDto project1Branch1 = db.components().insertProjectBranch(project1);
370 ComponentDto fileOnProject1Branch1 = db.components().insertComponent(newFileDto(project1Branch1));
371 ComponentDto project1Branch2 = db.components().insertProjectBranch(project1);
372 ComponentDto project2 = db.components().insertPrivateProject(p -> p.setDbKey("prj2"));
373 db.components().insertComponents(newProjectCopy(project1Branch1, applicationBranch1));
374 db.components().insertComponents(newProjectCopy(project2, applicationBranch1));
375 db.components().insertComponents(newProjectCopy(project1Branch2, applicationBranch2));
377 RuleDto issueRule = db.rules().insertIssueRule();
378 RuleDto hotspotRule = db.rules().insertHotspotRule();
379 IssueDto issueOnProject1 = db.issues().insertIssue(issueRule, project1, project1);
380 IssueDto issueOnProject1Branch1 = db.issues().insertIssue(issueRule, project1Branch1, project1Branch1);
381 db.issues().insertHotspot(hotspotRule, project1Branch1, project1Branch1);
382 IssueDto issueOnFileOnProject1Branch1 = db.issues().insertIssue(issueRule, project1Branch1, fileOnProject1Branch1);
383 IssueDto issueOnProject1Branch2 = db.issues().insertIssue(issueRule, project1Branch2, project1Branch2);
384 IssueDto issueOnProject2 = db.issues().insertIssue(issueRule, project2, project2);
385 db.issues().insertHotspot(hotspotRule, project2, project2);
386 allowAnyoneOnProjects(project1, project2, application);
387 userSession.addProjectPermission(USER, application);
388 indexIssuesAndViews();
390 // All issues on applicationBranch1
391 assertThat(ws.newRequest()
392 .setParam(PARAM_COMPONENT_KEYS, applicationBranch1.getKey())
393 .setParam(PARAM_BRANCH, applicationBranch1.getBranch())
394 .executeProtobuf(SearchWsResponse.class).getIssuesList())
395 .extracting(Issue::getKey, Issue::getComponent, Issue::getProject, Issue::getBranch, Issue::hasBranch)
396 .containsExactlyInAnyOrder(
397 tuple(issueOnProject1Branch1.getKey(), project1Branch1.getKey(), project1Branch1.getKey(), project1Branch1.getBranch(), true),
398 tuple(issueOnFileOnProject1Branch1.getKey(), fileOnProject1Branch1.getKey(), project1Branch1.getKey(), project1Branch1.getBranch(), true),
399 tuple(issueOnProject2.getKey(), project2.getKey(), project2.getKey(), "", false));
401 // Issues on project1Branch1
402 assertThat(ws.newRequest()
403 .setParam(PARAM_COMPONENT_KEYS, applicationBranch1.getKey())
404 .setParam(PARAM_PROJECTS, project1.getKey())
405 .setParam(PARAM_BRANCH, applicationBranch1.getBranch())
406 .executeProtobuf(SearchWsResponse.class).getIssuesList())
407 .extracting(Issue::getKey, Issue::getComponent, Issue::getBranch)
408 .containsExactlyInAnyOrder(
409 tuple(issueOnProject1Branch1.getKey(), project1Branch1.getKey(), project1Branch1.getBranch()),
410 tuple(issueOnFileOnProject1Branch1.getKey(), fileOnProject1Branch1.getKey(), project1Branch1.getBranch()));
414 public void ignore_application_without_browse_permission() {
415 ComponentDto project = db.components().insertPublicProject();
416 ComponentDto application = db.components().insertPublicApplication();
417 db.components().insertComponents(newProjectCopy("PC1", project, application));
418 RuleDto rule = db.rules().insertIssueRule();
419 db.issues().insertIssue(rule, project, project);
420 allowAnyoneOnProjects(project);
421 indexIssuesAndViews();
423 SearchWsResponse result = ws.newRequest()
424 .setParam(PARAM_COMPONENT_KEYS, application.getDbKey())
425 .executeProtobuf(SearchWsResponse.class);
427 assertThat(result.getIssuesList()).isEmpty();
431 public void search_application_without_projects() {
432 ComponentDto project = db.components().insertPublicProject();
433 ComponentDto application = db.components().insertPublicApplication();
434 RuleDto rule = db.rules().insertIssueRule();
435 db.issues().insertIssue(rule, project, project);
436 allowAnyoneOnProjects(project, application);
437 indexIssuesAndViews();
439 SearchWsResponse result = ws.newRequest()
440 .setParam(PARAM_COMPONENT_KEYS, application.getDbKey())
441 .executeProtobuf(SearchWsResponse.class);
443 assertThat(result.getIssuesList()).isEmpty();
447 public void search_by_application_and_by_leak() {
448 Date now = new Date();
449 RuleDto rule = db.rules().insertIssueRule();
450 ComponentDto application = db.components().insertPublicApplication();
452 ComponentDto project1 = db.components().insertPublicProject();
453 db.components().insertSnapshot(project1, s -> s.setPeriodDate(addDays(now, -14).getTime()));
454 db.components().insertComponents(newProjectCopy("PC1", project1, application));
455 IssueDto project1Issue1 = db.issues().insertIssue(rule, project1, project1, i -> i.setIssueCreationDate(addDays(now, -10)));
456 IssueDto project1Issue2 = db.issues().insertIssue(rule, project1, project1, i -> i.setIssueCreationDate(addDays(now, -20)));
458 ComponentDto project2 = db.components().insertPublicProject();
459 db.components().insertSnapshot(project2, s -> s.setPeriodDate(addDays(now, -25).getTime()));
460 db.components().insertComponents(newProjectCopy("PC2", project2, application));
461 IssueDto project2Issue1 = db.issues().insertIssue(rule, project2, project2, i -> i.setIssueCreationDate(addDays(now, -15)));
462 IssueDto project2Issue2 = db.issues().insertIssue(rule, project2, project2, i -> i.setIssueCreationDate(addDays(now, -30)));
463 // Permissions and index
464 allowAnyoneOnApplication(application, project1, project2);
465 indexIssuesAndViews();
467 SearchWsResponse result = ws.newRequest()
468 .setParam(PARAM_COMPONENT_KEYS, application.getDbKey())
469 .setParam(PARAM_SINCE_LEAK_PERIOD, "true")
470 .executeProtobuf(SearchWsResponse.class);
472 assertThat(result.getIssuesList()).extracting(Issue::getKey)
473 .containsExactlyInAnyOrder(project1Issue1.getKey(), project2Issue1.getKey())
474 .doesNotContain(project1Issue2.getKey(), project2Issue2.getKey());
478 public void search_by_application_and_project() {
479 ComponentDto project1 = db.components().insertPublicProject();
480 ComponentDto project2 = db.components().insertPublicProject();
481 ComponentDto application = db.components().insertPublicApplication();
482 db.components().insertComponents(newProjectCopy("PC1", project1, application));
483 db.components().insertComponents(newProjectCopy("PC2", project2, application));
484 RuleDto rule = db.rules().insertIssueRule();
485 IssueDto issue1 = db.issues().insertIssue(rule, project1, project1);
486 IssueDto issue2 = db.issues().insertIssue(rule, project2, project2);
487 allowAnyoneOnApplication(application, project1, project2);
488 indexIssuesAndViews();
490 SearchWsResponse result = ws.newRequest()
491 .setParam(PARAM_COMPONENT_KEYS, application.getDbKey())
492 .setParam(PARAM_PROJECTS, project1.getDbKey())
493 .executeProtobuf(SearchWsResponse.class);
495 assertThat(result.getIssuesList()).extracting(Issue::getKey)
496 .containsExactlyInAnyOrder(issue1.getKey())
497 .doesNotContain(issue2.getKey());
501 public void search_by_application_and_project_and_leak() {
502 Date now = new Date();
503 RuleDto rule = db.rules().insertIssueRule();
504 ComponentDto application = db.components().insertPublicApplication();
506 ComponentDto project1 = db.components().insertPublicProject();
507 db.components().insertSnapshot(project1, s -> s.setPeriodDate(addDays(now, -14).getTime()));
508 db.components().insertComponents(newProjectCopy("PC1", project1, application));
509 IssueDto project1Issue1 = db.issues().insertIssue(rule, project1, project1, i -> i.setIssueCreationDate(addDays(now, -10)));
510 IssueDto project1Issue2 = db.issues().insertIssue(rule, project1, project1, i -> i.setIssueCreationDate(addDays(now, -20)));
512 ComponentDto project2 = db.components().insertPublicProject();
513 db.components().insertSnapshot(project2, s -> s.setPeriodDate(addDays(now, -25).getTime()));
514 db.components().insertComponents(newProjectCopy("PC2", project2, application));
515 IssueDto project2Issue1 = db.issues().insertIssue(rule, project2, project2, i -> i.setIssueCreationDate(addDays(now, -15)));
516 IssueDto project2Issue2 = db.issues().insertIssue(rule, project2, project2, i -> i.setIssueCreationDate(addDays(now, -30)));
517 // Permissions and index
518 allowAnyoneOnApplication(application, project1, project2);
519 indexIssuesAndViews();
521 SearchWsResponse result = ws.newRequest()
522 .setParam(PARAM_COMPONENT_KEYS, application.getDbKey())
523 .setParam(PARAM_PROJECTS, project1.getDbKey())
524 .setParam(PARAM_SINCE_LEAK_PERIOD, "true")
525 .executeProtobuf(SearchWsResponse.class);
527 assertThat(result.getIssuesList()).extracting(Issue::getKey)
528 .containsExactlyInAnyOrder(project1Issue1.getKey())
529 .doesNotContain(project1Issue2.getKey(), project2Issue1.getKey(), project2Issue2.getKey());
533 public void search_by_application_and_by_leak_when_one_project_has_no_leak() {
534 Date now = new Date();
535 RuleDto rule = db.rules().insertIssueRule();
536 ComponentDto application = db.components().insertPublicApplication();
538 ComponentDto project1 = db.components().insertPublicProject();
539 db.components().insertSnapshot(project1, s -> s.setPeriodDate(addDays(now, -14).getTime()));
540 db.components().insertComponents(newProjectCopy("PC1", project1, application));
541 IssueDto project1Issue1 = db.issues().insertIssue(rule, project1, project1, i -> i.setIssueCreationDate(addDays(now, -10)));
542 IssueDto project1Issue2 = db.issues().insertIssue(rule, project1, project1, i -> i.setIssueCreationDate(addDays(now, -20)));
543 // Project 2, without leak => no issue form it should be returned
544 ComponentDto project2 = db.components().insertPublicProject();
545 db.components().insertSnapshot(project2, s -> s.setPeriodDate(null));
546 db.components().insertComponents(newProjectCopy("PC2", project2, application));
547 IssueDto project2Issue1 = db.issues().insertIssue(rule, project2, project2, i -> i.setIssueCreationDate(addDays(now, -15)));
548 IssueDto project2Issue2 = db.issues().insertIssue(rule, project2, project2, i -> i.setIssueCreationDate(addDays(now, -30)));
549 // Permissions and index
550 allowAnyoneOnApplication(application, project1, project2);
551 indexIssuesAndViews();
553 SearchWsResponse result = ws.newRequest()
554 .setParam(PARAM_COMPONENT_KEYS, application.getDbKey())
555 .setParam(PARAM_SINCE_LEAK_PERIOD, "true")
556 .executeProtobuf(SearchWsResponse.class);
558 assertThat(result.getIssuesList()).extracting(Issue::getKey)
559 .containsExactlyInAnyOrder(project1Issue1.getKey())
560 .doesNotContain(project1Issue2.getKey(), project2Issue1.getKey(), project2Issue2.getKey());
564 public void search_by_branch() {
565 RuleDto rule = db.rules().insertIssueRule();
566 ComponentDto project = db.components().insertPublicProject();
567 ComponentDto file = db.components().insertComponent(newFileDto(project));
568 IssueDto issue = db.issues().insertIssue(rule, project, file);
570 ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setBranchType(BRANCH));
571 ComponentDto branchFile = db.components().insertComponent(newFileDto(branch));
572 IssueDto branchIssue = db.issues().insertIssue(rule, branch, branchFile);
573 allowAnyoneOnProjects(project);
574 indexIssuesAndViews();
576 // On component key + branch
577 assertThat(ws.newRequest()
578 .setParam(PARAM_COMPONENT_KEYS, project.getKey())
579 .setParam(PARAM_BRANCH, branch.getBranch())
580 .executeProtobuf(SearchWsResponse.class).getIssuesList())
581 .extracting(Issue::getKey, Issue::getComponent, Issue::getBranch)
582 .containsExactlyInAnyOrder(tuple(branchIssue.getKey(), branchFile.getKey(), branchFile.getBranch()));
584 // On project key + branch
585 assertThat(ws.newRequest()
586 .setParam(PARAM_PROJECTS, project.getKey())
587 .setParam(PARAM_BRANCH, branch.getBranch())
588 .executeProtobuf(SearchWsResponse.class).getIssuesList())
589 .extracting(Issue::getKey, Issue::getComponent, Issue::getBranch)
590 .containsExactlyInAnyOrder(tuple(branchIssue.getKey(), branchFile.getKey(), branchFile.getBranch()));
591 // On file key + branch
592 assertThat(ws.newRequest()
593 .setParam(PARAM_COMPONENT_KEYS, branchFile.getKey())
594 .setParam(PARAM_BRANCH, branch.getBranch())
595 .executeProtobuf(SearchWsResponse.class).getIssuesList())
596 .extracting(Issue::getKey, Issue::getComponent, Issue::getBranch)
597 .containsExactlyInAnyOrder(tuple(branchIssue.getKey(), branchFile.getKey(), branchFile.getBranch()));
601 public void return_branch_in_component_list() {
602 RuleDto rule = db.rules().insertIssueRule();
603 ComponentDto project = db.components().insertPrivateProject();
604 ComponentDto projectFile = db.components().insertComponent(newFileDto(project));
605 IssueDto projectIssue = db.issues().insertIssue(rule, project, projectFile);
606 ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setBranchType(BRANCH));
607 ComponentDto branchFile = db.components().insertComponent(newFileDto(branch));
608 IssueDto branchIssue = db.issues().insertIssue(rule, branch, branchFile);
609 allowAnyoneOnProjects(project);
610 indexIssuesAndViews();
612 SearchWsResponse result = ws.newRequest()
613 .setParam(PARAM_COMPONENT_KEYS, branch.getKey())
614 .setParam(PARAM_BRANCH, branch.getBranch())
615 .executeProtobuf(SearchWsResponse.class);
617 assertThat(result.getComponentsList())
618 .extracting(Issues.Component::getKey, Issues.Component::getBranch)
619 .containsExactlyInAnyOrder(
620 tuple(branchFile.getKey(), branchFile.getBranch()),
621 tuple(branch.getKey(), branch.getBranch()));
625 public void search_by_pull_request() {
626 RuleDto rule = db.rules().insertIssueRule();
627 ComponentDto project = db.components().insertPrivateProject();
628 ComponentDto projectFile = db.components().insertComponent(newFileDto(project));
629 IssueDto projectIssue = db.issues().insertIssue(rule, project, projectFile);
630 ComponentDto pullRequest = db.components().insertProjectBranch(project, b -> b.setBranchType(PULL_REQUEST));
631 ComponentDto pullRequestFile = db.components().insertComponent(newFileDto(pullRequest));
632 IssueDto pullRequestIssue = db.issues().insertIssue(rule, pullRequest, pullRequestFile);
633 allowAnyoneOnProjects(project);
634 indexIssuesAndViews();
636 SearchWsResponse result = ws.newRequest()
637 .setParam(PARAM_COMPONENT_KEYS, pullRequest.getKey())
638 .setParam(PARAM_PULL_REQUEST, pullRequest.getPullRequest())
639 .executeProtobuf(SearchWsResponse.class);
641 assertThat(result.getIssuesList())
642 .extracting(Issue::getKey, Issue::getComponent, Issue::getPullRequest)
643 .containsExactlyInAnyOrder(tuple(pullRequestIssue.getKey(), pullRequestFile.getKey(), pullRequestFile.getPullRequest()));
644 assertThat(result.getComponentsList())
645 .extracting(Issues.Component::getKey, Issues.Component::getPullRequest)
646 .containsExactlyInAnyOrder(
647 tuple(pullRequestFile.getKey(), pullRequestFile.getPullRequest()),
648 tuple(pullRequest.getKey(), pullRequest.getPullRequest()));
652 public void search_using_main_branch_name() {
653 RuleDto rule = db.rules().insertIssueRule();
654 ComponentDto project = db.components().insertPublicProject();
655 ComponentDto projectFile = db.components().insertComponent(newFileDto(project));
656 IssueDto projectIssue = db.issues().insertIssue(rule, project, projectFile);
657 allowAnyoneOnProjects(project);
658 indexIssuesAndViews();
660 SearchWsResponse result = ws.newRequest()
661 .setParam(PARAM_COMPONENT_KEYS, project.getKey())
662 .setParam(PARAM_BRANCH, "master")
663 .executeProtobuf(SearchWsResponse.class);
665 assertThat(result.getIssuesList())
666 .extracting(Issue::getKey, Issue::getComponent, Issue::hasBranch)
667 .containsExactlyInAnyOrder(tuple(projectIssue.getKey(), projectFile.getKey(), false));
668 assertThat(result.getComponentsList())
669 .extracting(Issues.Component::getKey, Issues.Component::hasBranch)
670 .containsExactlyInAnyOrder(
671 tuple(projectFile.getKey(), false),
672 tuple(project.getKey(), false));
676 public void does_not_return_branch_issues_on_not_contextualized_search() {
677 RuleDto rule = db.rules().insertIssueRule();
678 ComponentDto project = db.components().insertPrivateProject();
679 ComponentDto projectFile = db.components().insertComponent(newFileDto(project));
680 IssueDto projectIssue = db.issues().insertIssue(rule, project, projectFile);
681 ComponentDto branch = db.components().insertProjectBranch(project);
682 ComponentDto branchFile = db.components().insertComponent(newFileDto(branch));
683 IssueDto branchIssue = db.issues().insertIssue(rule, branch, branchFile);
684 allowAnyoneOnProjects(project);
685 indexIssuesAndViews();
687 SearchWsResponse result = ws.newRequest().executeProtobuf(SearchWsResponse.class);
689 assertThat(result.getIssuesList()).extracting(Issue::getKey)
690 .containsExactlyInAnyOrder(projectIssue.getKey())
691 .doesNotContain(branchIssue.getKey());
695 public void does_not_return_branch_issues_when_using_db_key() {
696 RuleDto rule = db.rules().insertIssueRule();
697 ComponentDto project = db.components().insertPrivateProject();
698 ComponentDto projectFile = db.components().insertComponent(newFileDto(project));
699 IssueDto projectIssue = db.issues().insertIssue(rule, project, projectFile);
700 ComponentDto branch = db.components().insertProjectBranch(project);
701 ComponentDto branchFile = db.components().insertComponent(newFileDto(branch));
702 IssueDto branchIssue = db.issues().insertIssue(rule, branch, branchFile);
703 allowAnyoneOnProjects(project);
706 SearchWsResponse result = ws.newRequest()
707 .setParam(PARAM_COMPONENT_KEYS, branch.getDbKey())
708 .executeProtobuf(SearchWsResponse.class);
710 assertThat(result.getIssuesList()).isEmpty();
713 private void allowAnyoneOnProjects(ComponentDto... projects) {
714 userSession.registerComponents(projects);
715 Arrays.stream(projects).forEach(p -> permissionIndexer.allowOnlyAnyone(p));
718 private void allowAnyoneOnApplication(ComponentDto application, ComponentDto... projects) {
719 userSession.registerApplication(application);
720 Arrays.stream(projects).forEach(p -> permissionIndexer.allowOnlyAnyone(p));
723 private void indexIssues() {
724 issueIndexer.indexAllIssues();
727 private void indexIssuesAndViews() {
729 viewIndexer.indexAll();