3 * Copyright (C) 2009-2024 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.index;
22 import java.util.Date;
23 import java.util.List;
24 import org.junit.Test;
25 import org.sonar.api.issue.Issue;
26 import org.sonar.db.component.ComponentDto;
28 import static java.util.Arrays.asList;
29 import static java.util.Collections.emptyList;
30 import static java.util.Collections.singletonList;
31 import static org.apache.commons.lang3.RandomStringUtils.randomAlphanumeric;
32 import static org.assertj.core.api.Assertions.assertThat;
33 import static org.assertj.core.api.Assertions.tuple;
34 import static org.sonar.db.component.ComponentTesting.newBranchComponent;
35 import static org.sonar.db.component.ComponentTesting.newBranchDto;
36 import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto;
37 import static org.sonar.server.issue.IssueDocTesting.newDoc;
38 import static org.sonar.server.issue.IssueDocTesting.newDocForProject;
40 public class IssueIndexProjectStatisticsTest extends IssueIndexTestCommon {
43 public void searchProjectStatistics_returns_empty_list_if_no_input() {
44 List<ProjectStatistics> result = underTest.searchProjectStatistics(emptyList(), emptyList(), "unknownUser");
45 assertThat(result).isEmpty();
49 public void searchProjectStatistics_returns_empty_list_if_the_input_does_not_match_anything() {
50 List<ProjectStatistics> result = underTest.searchProjectStatistics(singletonList("unknownProjectUuid"), singletonList(1_111_234_567_890L), "unknownUser");
51 assertThat(result).isEmpty();
55 public void searchProjectStatistics_returns_something() {
56 ComponentDto project = newPrivateProjectDto();
57 String userUuid = randomAlphanumeric(40);
58 long from = 1_111_234_567_890L;
59 indexIssues(newDocForProject("issue1", project).setAssigneeUuid(userUuid).setFuncCreationDate(new Date(from + 1L)));
61 List<ProjectStatistics> result = underTest.searchProjectStatistics(singletonList(project.uuid()), singletonList(from), userUuid);
63 assertThat(result).extracting(ProjectStatistics::getProjectUuid).containsExactly(project.uuid());
67 public void searchProjectStatistics_does_not_return_results_if_assignee_does_not_match() {
68 ComponentDto project = newPrivateProjectDto();
69 String user1Uuid = randomAlphanumeric(40);
70 String user2Uuid = randomAlphanumeric(40);
71 long from = 1_111_234_567_890L;
72 indexIssues(newDocForProject("issue1", project).setAssigneeUuid(user1Uuid).setFuncCreationDate(new Date(from + 1L)));
74 List<ProjectStatistics> result = underTest.searchProjectStatistics(singletonList(project.uuid()), singletonList(from), user2Uuid);
76 assertThat(result).isEmpty();
80 public void searchProjectStatistics_returns_results_if_assignee_matches() {
81 ComponentDto project = newPrivateProjectDto();
82 String user1Uuid = randomAlphanumeric(40);
83 long from = 1_111_234_567_890L;
84 indexIssues(newDocForProject("issue1", project).setAssigneeUuid(user1Uuid).setFuncCreationDate(new Date(from + 1L)));
86 List<ProjectStatistics> result = underTest.searchProjectStatistics(singletonList(project.uuid()), singletonList(from), user1Uuid);
88 assertThat(result).extracting(ProjectStatistics::getProjectUuid).containsExactly(project.uuid());
92 public void searchProjectStatistics_returns_results_if_functional_date_is_strictly_after_from_date() {
93 ComponentDto project = newPrivateProjectDto();
94 String userUuid = randomAlphanumeric(40);
95 long from = 1_111_234_567_890L;
96 indexIssues(newDocForProject("issue1", project).setAssigneeUuid(userUuid).setFuncCreationDate(new Date(from + 1L)));
98 List<ProjectStatistics> result = underTest.searchProjectStatistics(singletonList(project.uuid()), singletonList(from), userUuid);
100 assertThat(result).extracting(ProjectStatistics::getProjectUuid).containsExactly(project.uuid());
104 public void searchProjectStatistics_does_not_return_results_if_functional_date_is_same_as_from_date() {
105 ComponentDto project = newPrivateProjectDto();
106 String userUuid = randomAlphanumeric(40);
107 long from = 1_111_234_567_890L;
108 indexIssues(newDocForProject("issue1", project).setAssigneeUuid(userUuid).setFuncCreationDate(new Date(from)));
110 List<ProjectStatistics> result = underTest.searchProjectStatistics(singletonList(project.uuid()), singletonList(from), userUuid);
112 assertThat(result).extracting(ProjectStatistics::getProjectUuid).containsExactly(project.uuid());
116 public void searchProjectStatistics_does_not_return_resolved_issues() {
117 ComponentDto project = newPrivateProjectDto();
118 String userUuid = randomAlphanumeric(40);
119 long from = 1_111_234_567_890L;
121 newDocForProject("issue1", project).setAssigneeUuid(userUuid).setFuncCreationDate(new Date(from + 1L)).setResolution(Issue.RESOLUTION_FALSE_POSITIVE),
122 newDocForProject("issue1", project).setAssigneeUuid(userUuid).setFuncCreationDate(new Date(from + 1L)).setResolution(Issue.RESOLUTION_FIXED),
123 newDocForProject("issue1", project).setAssigneeUuid(userUuid).setFuncCreationDate(new Date(from + 1L)).setResolution(Issue.RESOLUTION_REMOVED),
124 newDocForProject("issue1", project).setAssigneeUuid(userUuid).setFuncCreationDate(new Date(from + 1L)).setResolution(Issue.RESOLUTION_WONT_FIX));
126 List<ProjectStatistics> result = underTest.searchProjectStatistics(singletonList(project.uuid()), singletonList(from), userUuid);
128 assertThat(result).isEmpty();
132 public void searchProjectStatistics_does_not_return_results_if_functional_date_is_before_from_date() {
133 ComponentDto project = newPrivateProjectDto();
134 String userUuid = randomAlphanumeric(40);
135 long from = 1_111_234_567_890L;
136 indexIssues(newDocForProject("issue1", project).setAssigneeUuid(userUuid).setFuncCreationDate(new Date(from - 1000L)));
138 List<ProjectStatistics> result = underTest.searchProjectStatistics(singletonList(project.uuid()), singletonList(from), userUuid);
140 assertThat(result).isEmpty();
144 public void searchProjectStatistics_returns_issue_count() {
145 ComponentDto project = newPrivateProjectDto();
146 String userUuid = randomAlphanumeric(40);
147 long from = 1_111_234_567_890L;
149 newDocForProject("issue1", project).setAssigneeUuid(userUuid).setFuncCreationDate(new Date(from + 1L)),
150 newDocForProject("issue2", project).setAssigneeUuid(userUuid).setFuncCreationDate(new Date(from + 1L)),
151 newDocForProject("issue3", project).setAssigneeUuid(userUuid).setFuncCreationDate(new Date(from + 1L)));
153 List<ProjectStatistics> result = underTest.searchProjectStatistics(singletonList(project.uuid()), singletonList(from), userUuid);
155 assertThat(result).extracting(ProjectStatistics::getIssueCount).containsExactly(3L);
159 public void searchProjectStatistics_returns_issue_count_for_multiple_projects() {
160 ComponentDto project1 = newPrivateProjectDto();
161 ComponentDto project2 = newPrivateProjectDto();
162 ComponentDto project3 = newPrivateProjectDto();
163 String userUuid = randomAlphanumeric(40);
164 long from = 1_111_234_567_890L;
166 newDocForProject("issue1", project1).setAssigneeUuid(userUuid).setFuncCreationDate(new Date(from + 1L)),
167 newDocForProject("issue2", project1).setAssigneeUuid(userUuid).setFuncCreationDate(new Date(from + 1L)),
168 newDocForProject("issue3", project1).setAssigneeUuid(userUuid).setFuncCreationDate(new Date(from + 1L)),
170 newDocForProject("issue4", project3).setAssigneeUuid(userUuid).setFuncCreationDate(new Date(from + 1L)),
171 newDocForProject("issue5", project3).setAssigneeUuid(userUuid).setFuncCreationDate(new Date(from + 1L)));
173 List<ProjectStatistics> result = underTest.searchProjectStatistics(
174 asList(project1.uuid(), project2.uuid(), project3.uuid()),
175 asList(from, from, from),
179 .extracting(ProjectStatistics::getProjectUuid, ProjectStatistics::getIssueCount)
180 .containsExactlyInAnyOrder(
181 tuple(project1.uuid(), 3L),
182 tuple(project3.uuid(), 2L));
186 public void searchProjectStatistics_returns_max_date_for_multiple_projects() {
187 ComponentDto project1 = newPrivateProjectDto();
188 ComponentDto project2 = newPrivateProjectDto();
189 ComponentDto project3 = newPrivateProjectDto();
190 String userUuid = randomAlphanumeric(40);
191 long from = 1_111_234_567_000L;
193 newDocForProject("issue1", project1).setAssigneeUuid(userUuid).setFuncCreationDate(new Date(from + 1_000L)),
194 newDocForProject("issue2", project1).setAssigneeUuid(userUuid).setFuncCreationDate(new Date(from + 2_000L)),
195 newDocForProject("issue3", project1).setAssigneeUuid(userUuid).setFuncCreationDate(new Date(from + 3_000L)),
197 newDocForProject("issue4", project3).setAssigneeUuid(userUuid).setFuncCreationDate(new Date(from + 4_000L)),
198 newDocForProject("issue5", project3).setAssigneeUuid(userUuid).setFuncCreationDate(new Date(from + 5_000L)));
200 List<ProjectStatistics> result = underTest.searchProjectStatistics(
201 asList(project1.uuid(), project2.uuid(), project3.uuid()),
202 asList(from, from, from),
206 .extracting(ProjectStatistics::getProjectUuid, ProjectStatistics::getLastIssueDate)
207 .containsExactlyInAnyOrder(
208 tuple(project1.uuid(), from + 3_000L),
209 tuple(project3.uuid(), from + 5_000L));
213 public void searchProjectStatistics_return_branch_issues() {
214 ComponentDto project = newPrivateProjectDto();
215 ComponentDto branch = newBranchComponent(project, newBranchDto(project).setKey("branch"));
216 String userUuid = randomAlphanumeric(40);
217 long from = 1_111_234_567_890L;
219 newDoc("issue1", project.uuid(), branch).setAssigneeUuid(userUuid).setFuncCreationDate(new Date(from + 1L)),
220 newDoc("issue2", project.uuid(), branch).setAssigneeUuid(userUuid).setFuncCreationDate(new Date(from + 2L)),
221 newDocForProject("issue3", project).setAssigneeUuid(userUuid).setFuncCreationDate(new Date(from + 1L)));
223 List<ProjectStatistics> result = underTest.searchProjectStatistics(singletonList(project.uuid()), singletonList(from), userUuid);
226 .extracting(ProjectStatistics::getIssueCount, ProjectStatistics::getProjectUuid, ProjectStatistics::getLastIssueDate)
228 tuple(2L, branch.uuid(), from + 2L),
229 tuple(1L, project.uuid(), from + 1L));