]> source.dussan.org Git - sonarqube.git/blob
9edd790d12f36a78e17c287042b93b3608fc44ee
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2022 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
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;
59
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;
81
82 public class SearchActionComponentsTest {
83
84   @Rule
85   public UserSessionRule userSession = UserSessionRule.standalone();
86   @Rule
87   public DbTester db = DbTester.create();
88   @Rule
89   public EsTester es = EsTester.create();
90
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);
103
104   private IssueIndexSyncProgressChecker issueIndexSyncProgressChecker = new IssueIndexSyncProgressChecker(db.getDbClient());
105
106   private WsActionTester ws = new WsActionTester(
107     new SearchAction(userSession, issueIndex, issueQueryFactory, issueIndexSyncProgressChecker, searchResponseLoader, searchResponseFormat,
108       System2.INSTANCE, dbClient));
109
110   @Test
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);
117     indexIssues();
118
119     SearchWsResponse result = ws.newRequest().executeProtobuf(SearchWsResponse.class);
120
121     assertThat(result.getIssuesList()).extracting(Issues.Issue::getKey)
122       .containsExactlyInAnyOrder(issue.getKey());
123   }
124
125   @Test
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);
135     indexIssues();
136
137     SearchWsResponse response = ws.newRequest().executeProtobuf(SearchWsResponse.class);
138
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));
147   }
148
149   @Test
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);
160     indexIssues();
161
162     assertThat(ws.newRequest()
163       .setParam(PARAM_COMPONENT_KEYS, module1.getKey())
164       .executeProtobuf(SearchWsResponse.class).getIssuesList()).extracting(Issue::getKey)
165         .containsExactlyInAnyOrder(issue1.getKey());
166   }
167
168   @Test
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);
181     indexIssues();
182
183     ws.newRequest()
184       .setParam(PARAM_COMPONENT_KEYS, project.getDbKey())
185       .setParam(PARAM_SINCE_LEAK_PERIOD, "true")
186       .execute()
187       .assertJson(this.getClass(), "search_since_leak_period.json");
188   }
189
190   @Test
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);
204     indexIssues();
205
206     ws.newRequest()
207       .setParam(PARAM_COMPONENT_KEYS, project.getDbKey())
208       .setParam(PARAM_FILES, file.path())
209       .setParam(PARAM_SINCE_LEAK_PERIOD, "true")
210       .execute()
211       .assertJson(this.getClass(), "search_since_leak_period.json");
212   }
213
214   @Test
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);
221     indexIssues();
222
223     ws.newRequest()
224       .setParam(PARAM_FILES, file.path())
225       .execute()
226       .assertJson(this.getClass(), "search_by_file_uuid.json");
227
228     ws.newRequest()
229       .setParam(PARAM_FILES, "unknown")
230       .execute()
231       .assertJson(this.getClass(), "no_issue.json");
232   }
233
234   @Test
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);
243     indexIssues();
244
245     ws.newRequest()
246       .setParam(PARAM_COMPONENT_KEYS, file.getKey())
247       .execute()
248       .assertJson(this.getClass(), "search_by_file_key.json");
249
250     ws.newRequest()
251       .setParam(PARAM_COMPONENT_KEYS, unitTest.getKey())
252       .execute()
253       .assertJson(this.getClass(), "search_by_test_key.json");
254   }
255
256   @Test
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);
264     indexIssues();
265
266     ws.newRequest()
267       .setParam(PARAM_COMPONENT_KEYS, directory.getKey())
268       .execute()
269       .assertJson(this.getClass(), "search_by_file_uuid.json");
270
271     ws.newRequest()
272       .setParam(PARAM_DIRECTORIES, "unknown")
273       .execute()
274       .assertJson(this.getClass(), "no_issue.json");
275
276     ws.newRequest()
277       .setParam(PARAM_DIRECTORIES, "src/main/java/dir")
278       .execute()
279       .assertJson(this.getClass(), "search_by_file_uuid.json");
280
281     ws.newRequest()
282       .setParam(PARAM_DIRECTORIES, "src/main/java")
283       .execute()
284       .assertJson(this.getClass(), "no_issue.json");
285   }
286
287   @Test
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();
297
298     ws.newRequest()
299       .setParam(PARAM_COMPONENT_KEYS, view.getKey())
300       .execute()
301       .assertJson(this.getClass(), "search_by_view_uuid.json");
302   }
303
304   @Test
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();
315
316     ws.newRequest()
317       .setParam(PARAM_COMPONENT_KEYS, subView.getKey())
318       .execute()
319       .assertJson(this.getClass(), "search_by_view_uuid.json");
320   }
321
322   @Test
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();
334
335     ws.newRequest()
336       .setParam(PARAM_COMPONENT_KEYS, subView.getKey())
337       .execute()
338       .assertJson(this.getClass(), "no_issue.json");
339   }
340
341   @Test
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();
354
355     SearchWsResponse result = ws.newRequest()
356       .setParam(PARAM_COMPONENT_KEYS, application.getDbKey())
357       .executeProtobuf(SearchWsResponse.class);
358
359     assertThat(result.getIssuesList()).extracting(Issue::getKey)
360       .containsExactlyInAnyOrder(issue1.getKey(), issue2.getKey());
361   }
362
363   @Test
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));
376
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();
389
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));
400
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()));
411   }
412
413   @Test
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();
422
423     SearchWsResponse result = ws.newRequest()
424       .setParam(PARAM_COMPONENT_KEYS, application.getDbKey())
425       .executeProtobuf(SearchWsResponse.class);
426
427     assertThat(result.getIssuesList()).isEmpty();
428   }
429
430   @Test
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();
438
439     SearchWsResponse result = ws.newRequest()
440       .setParam(PARAM_COMPONENT_KEYS, application.getDbKey())
441       .executeProtobuf(SearchWsResponse.class);
442
443     assertThat(result.getIssuesList()).isEmpty();
444   }
445
446   @Test
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();
451     // Project 1
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)));
457     // Project 2
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();
466
467     SearchWsResponse result = ws.newRequest()
468       .setParam(PARAM_COMPONENT_KEYS, application.getDbKey())
469       .setParam(PARAM_SINCE_LEAK_PERIOD, "true")
470       .executeProtobuf(SearchWsResponse.class);
471
472     assertThat(result.getIssuesList()).extracting(Issue::getKey)
473       .containsExactlyInAnyOrder(project1Issue1.getKey(), project2Issue1.getKey())
474       .doesNotContain(project1Issue2.getKey(), project2Issue2.getKey());
475   }
476
477   @Test
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();
489
490     SearchWsResponse result = ws.newRequest()
491       .setParam(PARAM_COMPONENT_KEYS, application.getDbKey())
492       .setParam(PARAM_PROJECTS, project1.getDbKey())
493       .executeProtobuf(SearchWsResponse.class);
494
495     assertThat(result.getIssuesList()).extracting(Issue::getKey)
496       .containsExactlyInAnyOrder(issue1.getKey())
497       .doesNotContain(issue2.getKey());
498   }
499
500   @Test
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();
505     // Project 1
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)));
511     // Project 2
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();
520
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);
526
527     assertThat(result.getIssuesList()).extracting(Issue::getKey)
528       .containsExactlyInAnyOrder(project1Issue1.getKey())
529       .doesNotContain(project1Issue2.getKey(), project2Issue1.getKey(), project2Issue2.getKey());
530   }
531
532   @Test
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();
537     // Project 1
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();
552
553     SearchWsResponse result = ws.newRequest()
554       .setParam(PARAM_COMPONENT_KEYS, application.getDbKey())
555       .setParam(PARAM_SINCE_LEAK_PERIOD, "true")
556       .executeProtobuf(SearchWsResponse.class);
557
558     assertThat(result.getIssuesList()).extracting(Issue::getKey)
559       .containsExactlyInAnyOrder(project1Issue1.getKey())
560       .doesNotContain(project1Issue2.getKey(), project2Issue1.getKey(), project2Issue2.getKey());
561   }
562
563   @Test
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);
569
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();
575
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()));
583
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()));
598   }
599
600   @Test
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();
611
612     SearchWsResponse result = ws.newRequest()
613       .setParam(PARAM_COMPONENT_KEYS, branch.getKey())
614       .setParam(PARAM_BRANCH, branch.getBranch())
615       .executeProtobuf(SearchWsResponse.class);
616
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()));
622   }
623
624   @Test
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();
635
636     SearchWsResponse result = ws.newRequest()
637       .setParam(PARAM_COMPONENT_KEYS, pullRequest.getKey())
638       .setParam(PARAM_PULL_REQUEST, pullRequest.getPullRequest())
639       .executeProtobuf(SearchWsResponse.class);
640
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()));
649   }
650
651   @Test
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();
659
660     SearchWsResponse result = ws.newRequest()
661       .setParam(PARAM_COMPONENT_KEYS, project.getKey())
662       .setParam(PARAM_BRANCH, "master")
663       .executeProtobuf(SearchWsResponse.class);
664
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));
673   }
674
675   @Test
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();
686
687     SearchWsResponse result = ws.newRequest().executeProtobuf(SearchWsResponse.class);
688
689     assertThat(result.getIssuesList()).extracting(Issue::getKey)
690       .containsExactlyInAnyOrder(projectIssue.getKey())
691       .doesNotContain(branchIssue.getKey());
692   }
693
694   @Test
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);
704     indexIssues();
705
706     SearchWsResponse result = ws.newRequest()
707       .setParam(PARAM_COMPONENT_KEYS, branch.getDbKey())
708       .executeProtobuf(SearchWsResponse.class);
709
710     assertThat(result.getIssuesList()).isEmpty();
711   }
712
713   private void allowAnyoneOnProjects(ComponentDto... projects) {
714     userSession.registerComponents(projects);
715     Arrays.stream(projects).forEach(p -> permissionIndexer.allowOnlyAnyone(p));
716   }
717
718   private void allowAnyoneOnApplication(ComponentDto application, ComponentDto... projects) {
719     userSession.registerApplication(application);
720     Arrays.stream(projects).forEach(p -> permissionIndexer.allowOnlyAnyone(p));
721   }
722
723   private void indexIssues() {
724     issueIndexer.indexAllIssues();
725   }
726
727   private void indexIssuesAndViews() {
728     indexIssues();
729     viewIndexer.indexAll();
730   }
731 }