]> source.dussan.org Git - sonarqube.git/blob
c7ca17f19eb0bf96e89ceb93e671b93a05a103df
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2024 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.notification;
21
22 import com.google.common.collect.ImmutableSet;
23 import com.google.common.collect.Lists;
24 import java.util.Collections;
25 import java.util.List;
26 import java.util.Optional;
27 import java.util.Random;
28 import java.util.stream.IntStream;
29 import java.util.stream.Stream;
30 import javax.annotation.CheckForNull;
31 import org.junit.Test;
32 import org.sonar.api.issue.Issue;
33 import org.sonar.api.rule.RuleKey;
34 import org.sonar.api.rules.RuleType;
35 import org.sonar.api.utils.Duration;
36 import org.sonar.core.issue.DefaultIssue;
37 import org.sonar.server.issue.notification.NewIssuesStatistics.Metric;
38
39 import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
40 import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
41 import static org.assertj.core.api.Assertions.assertThat;
42
43 public class NewIssuesStatisticsTest {
44
45   private final Random random = new Random();
46   private RuleType randomRuleTypeExceptHotspot = RuleType.values()[random.nextInt(RuleType.values().length - 1)];
47   private NewIssuesStatistics underTest = new NewIssuesStatistics(Issue::isNew);
48
49   @Test
50   public void add_issues_with_correct_global_statistics() {
51     DefaultIssue issue = new DefaultIssue()
52       .setAssigneeUuid("maynard")
53       .setComponentUuid("file-uuid")
54       .setNew(true)
55       .setRuleKey(RuleKey.of("SonarQube", "rule-the-world"))
56       .setTags(Lists.newArrayList("bug", "owasp"))
57       .setEffort(Duration.create(5L));
58
59     underTest.add(issue);
60     underTest.add(issue.setAssigneeUuid("james"));
61     underTest.add(issue.setAssigneeUuid("keenan"));
62
63     assertThat(countDistributionTotal(Metric.ASSIGNEE, "maynard")).isOne();
64     assertThat(countDistributionTotal(Metric.ASSIGNEE, "james")).isOne();
65     assertThat(countDistributionTotal(Metric.ASSIGNEE, "keenan")).isOne();
66     assertThat(countDistributionTotal(Metric.ASSIGNEE, "wrong.login")).isNull();
67     assertThat(countDistributionTotal(Metric.COMPONENT, "file-uuid")).isEqualTo(3);
68     assertThat(countDistributionTotal(Metric.COMPONENT, "wrong-uuid")).isNull();
69     assertThat(countDistributionTotal(Metric.TAG, "owasp")).isEqualTo(3);
70     assertThat(countDistributionTotal(Metric.TAG, "wrong-tag")).isNull();
71     assertThat(countDistributionTotal(Metric.RULE, "SonarQube:rule-the-world")).isEqualTo(3);
72     assertThat(countDistributionTotal(Metric.RULE, "SonarQube:has-a-fake-rule")).isNull();
73     assertThat(underTest.globalStatistics().getIssueCount().getTotal()).isEqualTo(3);
74     assertThat(underTest.globalStatistics().hasIssues()).isTrue();
75     assertThat(underTest.hasIssues()).isTrue();
76     assertThat(underTest.getAssigneesStatistics().get("maynard").hasIssues()).isTrue();
77   }
78
79   @Test
80   public void add_counts_issues_on_current_analysis_globally_and_per_assignee() {
81     String assignee = randomAlphanumeric(10);
82     IntStream.range(0, 10)
83       .mapToObj(i -> new DefaultIssue().setAssigneeUuid(assignee).setNew(true))
84       .forEach(underTest::add);
85
86     MetricStatsInt globalIssueCount = underTest.globalStatistics().getIssueCount();
87     MetricStatsInt assigneeIssueCount = underTest.getAssigneesStatistics().get(assignee).getIssueCount();
88     assertThat(globalIssueCount.getOnCurrentAnalysis()).isEqualTo(10);
89     assertThat(globalIssueCount.getTotal()).isEqualTo(10);
90     assertThat(assigneeIssueCount.getOnCurrentAnalysis()).isEqualTo(10);
91     assertThat(assigneeIssueCount.getTotal()).isEqualTo(10);
92   }
93
94   @Test
95   public void add_counts_issues_off_current_analysis_globally_and_per_assignee() {
96     String assignee = randomAlphanumeric(10);
97     IntStream.range(0, 10)
98       .mapToObj(i -> new DefaultIssue().setAssigneeUuid(assignee).setNew(false))
99       .forEach(underTest::add);
100
101     MetricStatsInt globalIssueCount = underTest.globalStatistics().getIssueCount();
102     MetricStatsInt assigneeIssueCount = underTest.getAssigneesStatistics().get(assignee).getIssueCount();
103     assertThat(globalIssueCount.getOnCurrentAnalysis()).isZero();
104     assertThat(globalIssueCount.getTotal()).isEqualTo(10);
105     assertThat(assigneeIssueCount.getOnCurrentAnalysis()).isZero();
106     assertThat(assigneeIssueCount.getTotal()).isEqualTo(10);
107   }
108
109   @Test
110   public void add_counts_issue_per_component_on_current_analysis_globally_and_per_assignee() {
111     List<String> componentUuids = IntStream.range(0, 1 + new Random().nextInt(10)).mapToObj(i -> randomAlphabetic(3)).toList();
112     String assignee = randomAlphanumeric(10);
113     componentUuids.stream()
114       .map(componentUuid -> new DefaultIssue().setType(randomRuleTypeExceptHotspot).setComponentUuid(componentUuid).setAssigneeUuid(assignee).setNew(true))
115       .forEach(underTest::add);
116
117     DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.COMPONENT);
118     DistributedMetricStatsInt assigneeDistribution = underTest.getAssigneesStatistics().get(assignee).getDistributedMetricStats(Metric.COMPONENT);
119     Stream.of(globalDistribution, assigneeDistribution)
120       .forEach(distribution -> componentUuids.forEach(componentUuid -> assertStats(distribution, componentUuid, 1, 1)));
121   }
122
123   @Test
124   public void add_counts_issue_per_component_off_current_analysis_globally_and_per_assignee() {
125     List<String> componentUuids = IntStream.range(0, 1 + new Random().nextInt(10)).mapToObj(i -> randomAlphabetic(3)).toList();
126     String assignee = randomAlphanumeric(10);
127     componentUuids.stream()
128       .map(componentUuid -> new DefaultIssue().setType(randomRuleTypeExceptHotspot).setComponentUuid(componentUuid).setAssigneeUuid(assignee).setNew(false))
129       .forEach(underTest::add);
130
131     DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.COMPONENT);
132     NewIssuesStatistics.Stats stats = underTest.getAssigneesStatistics().get(assignee);
133     DistributedMetricStatsInt assigneeDistribution = stats.getDistributedMetricStats(Metric.COMPONENT);
134     Stream.of(globalDistribution, assigneeDistribution)
135       .forEach(distribution -> componentUuids.forEach(componentUuid -> assertStats(distribution, componentUuid, 0, 1)));
136   }
137
138   @Test
139   public void add_does_not_count_component_if_null_neither_globally_nor_per_assignee() {
140     String assignee = randomAlphanumeric(10);
141     underTest.add(new DefaultIssue().setType(randomRuleTypeExceptHotspot).setComponentUuid(null).setAssigneeUuid(assignee).setNew(new Random().nextBoolean()));
142
143     DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.COMPONENT);
144     DistributedMetricStatsInt assigneeDistribution = underTest.getAssigneesStatistics().get(assignee).getDistributedMetricStats(Metric.COMPONENT);
145     Stream.of(globalDistribution, assigneeDistribution)
146       .forEach(distribution -> {
147         assertThat(distribution.getTotal()).isZero();
148         assertThat(distribution.getForLabel(null)).isEmpty();
149       });
150   }
151
152   @Test
153   public void add_counts_issue_per_ruleKey_on_current_analysis_globally_and_per_assignee() {
154     String repository = randomAlphanumeric(3);
155     List<String> ruleKeys = IntStream.range(0, 1 + new Random().nextInt(10)).mapToObj(i -> randomAlphabetic(3)).toList();
156     String assignee = randomAlphanumeric(10);
157     ruleKeys.stream()
158       .map(ruleKey -> new DefaultIssue().setType(randomRuleTypeExceptHotspot).setRuleKey(RuleKey.of(repository, ruleKey)).setAssigneeUuid(assignee).setNew(true))
159       .forEach(underTest::add);
160
161     DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.RULE);
162     NewIssuesStatistics.Stats stats = underTest.getAssigneesStatistics().get(assignee);
163     DistributedMetricStatsInt assigneeDistribution = stats.getDistributedMetricStats(Metric.RULE);
164     Stream.of(globalDistribution, assigneeDistribution)
165       .forEach(distribution -> ruleKeys.forEach(ruleKey -> assertStats(distribution, RuleKey.of(repository, ruleKey).toString(), 1, 1)));
166   }
167
168   @Test
169   public void add_counts_issue_per_ruleKey_off_current_analysis_globally_and_per_assignee() {
170     String repository = randomAlphanumeric(3);
171     List<String> ruleKeys = IntStream.range(0, 1 + new Random().nextInt(10)).mapToObj(i -> randomAlphabetic(3)).toList();
172     String assignee = randomAlphanumeric(10);
173     ruleKeys.stream()
174       .map(ruleKey -> new DefaultIssue().setType(randomRuleTypeExceptHotspot).setRuleKey(RuleKey.of(repository, ruleKey)).setAssigneeUuid(assignee).setNew(false))
175       .forEach(underTest::add);
176
177     DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.RULE);
178     DistributedMetricStatsInt assigneeDistribution = underTest.getAssigneesStatistics().get(assignee).getDistributedMetricStats(Metric.RULE);
179     Stream.of(globalDistribution, assigneeDistribution)
180       .forEach(distribution -> ruleKeys.forEach(ruleKey -> assertStats(distribution, RuleKey.of(repository, ruleKey).toString(), 0, 1)));
181   }
182
183   @Test
184   public void add_does_not_count_ruleKey_if_null_neither_globally_nor_per_assignee() {
185     String assignee = randomAlphanumeric(10);
186     underTest.add(new DefaultIssue().setType(randomRuleTypeExceptHotspot).setRuleKey(null).setAssigneeUuid(assignee).setNew(new Random().nextBoolean()));
187
188     DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.RULE);
189     DistributedMetricStatsInt assigneeDistribution = underTest.getAssigneesStatistics().get(assignee).getDistributedMetricStats(Metric.RULE);
190     Stream.of(globalDistribution, assigneeDistribution)
191       .forEach(distribution -> {
192         assertThat(distribution.getTotal()).isZero();
193         assertThat(distribution.getForLabel(null)).isEmpty();
194       });
195   }
196
197   @Test
198   public void add_counts_issue_per_assignee_on_current_analysis_globally_and_per_assignee() {
199     List<String> assignees = IntStream.range(0, 1 + new Random().nextInt(10)).mapToObj(i -> randomAlphabetic(3)).toList();
200     assignees.stream()
201       .map(assignee -> new DefaultIssue().setType(randomRuleTypeExceptHotspot).setAssigneeUuid(assignee).setNew(true))
202       .forEach(underTest::add);
203
204     DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.ASSIGNEE);
205     assignees.forEach(assignee -> assertStats(globalDistribution, assignee, 1, 1));
206     assignees.forEach(assignee -> {
207       NewIssuesStatistics.Stats stats = underTest.getAssigneesStatistics().get(assignee);
208       DistributedMetricStatsInt assigneeStats = stats.getDistributedMetricStats(Metric.ASSIGNEE);
209       assertThat(assigneeStats.getOnCurrentAnalysis()).isOne();
210       assertThat(assigneeStats.getTotal()).isOne();
211       assignees.forEach(s -> {
212         Optional<MetricStatsInt> forLabelOpts = assigneeStats.getForLabel(s);
213         if (s.equals(assignee)) {
214           assertThat(forLabelOpts).isPresent();
215           MetricStatsInt forLabel = forLabelOpts.get();
216           assertThat(forLabel.getOnCurrentAnalysis()).isOne();
217           assertThat(forLabel.getTotal()).isOne();
218         } else {
219           assertThat(forLabelOpts).isEmpty();
220         }
221       });
222     });
223   }
224
225   @Test
226   public void add_counts_issue_per_assignee_off_current_analysis_globally_and_per_assignee() {
227     List<String> assignees = IntStream.range(0, 1 + new Random().nextInt(10)).mapToObj(i -> randomAlphabetic(3)).toList();
228     assignees.stream()
229       .map(assignee -> new DefaultIssue().setType(randomRuleTypeExceptHotspot).setAssigneeUuid(assignee).setNew(false))
230       .forEach(underTest::add);
231
232     DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.ASSIGNEE);
233     assignees.forEach(assignee -> assertStats(globalDistribution, assignee, 0, 1));
234     assignees.forEach(assignee -> {
235       NewIssuesStatistics.Stats stats = underTest.getAssigneesStatistics().get(assignee);
236       DistributedMetricStatsInt assigneeStats = stats.getDistributedMetricStats(Metric.ASSIGNEE);
237       assertThat(assigneeStats.getOnCurrentAnalysis()).isZero();
238       assertThat(assigneeStats.getTotal()).isOne();
239       assignees.forEach(s -> {
240         Optional<MetricStatsInt> forLabelOpts = assigneeStats.getForLabel(s);
241         if (s.equals(assignee)) {
242           assertThat(forLabelOpts).isPresent();
243           MetricStatsInt forLabel = forLabelOpts.get();
244           assertThat(forLabel.getOnCurrentAnalysis()).isZero();
245           assertThat(forLabel.getTotal()).isOne();
246         } else {
247           assertThat(forLabelOpts).isEmpty();
248         }
249       });
250     });
251   }
252
253   @Test
254   public void add_does_not_assignee_if_empty_neither_globally_nor_per_assignee() {
255     underTest.add(new DefaultIssue().setType(randomRuleTypeExceptHotspot).setAssigneeUuid(null).setNew(new Random().nextBoolean()));
256
257     DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.ASSIGNEE);
258     assertThat(globalDistribution.getTotal()).isZero();
259     assertThat(globalDistribution.getForLabel(null)).isEmpty();
260     assertThat(underTest.getAssigneesStatistics()).isEmpty();
261   }
262
263   @Test
264   public void add_counts_issue_per_tags_on_current_analysis_globally_and_per_assignee() {
265     List<String> tags = IntStream.range(0, 1 + new Random().nextInt(10)).mapToObj(i -> randomAlphabetic(3)).toList();
266     String assignee = randomAlphanumeric(10);
267     underTest.add(new DefaultIssue().setType(randomRuleTypeExceptHotspot).setTags(tags).setAssigneeUuid(assignee).setNew(true));
268
269     DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.TAG);
270     DistributedMetricStatsInt assigneeDistribution = underTest.getAssigneesStatistics().get(assignee).getDistributedMetricStats(Metric.TAG);
271     Stream.of(globalDistribution, assigneeDistribution)
272       .forEach(distribution -> tags.forEach(tag -> assertStats(distribution, tag, 1, 1)));
273   }
274
275   @Test
276   public void add_counts_issue_per_tags_off_current_analysis_globally_and_per_assignee() {
277     List<String> tags = IntStream.range(0, 1 + new Random().nextInt(10)).mapToObj(i -> randomAlphabetic(3)).toList();
278     String assignee = randomAlphanumeric(10);
279     underTest.add(new DefaultIssue().setType(randomRuleTypeExceptHotspot).setTags(tags).setAssigneeUuid(assignee).setNew(false));
280
281     DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.TAG);
282     DistributedMetricStatsInt assigneeDistribution = underTest.getAssigneesStatistics().get(assignee).getDistributedMetricStats(Metric.TAG);
283     Stream.of(globalDistribution, assigneeDistribution)
284       .forEach(distribution -> tags.forEach(tag -> assertStats(distribution, tag, 0, 1)));
285   }
286
287   @Test
288   public void add_does_not_count_tags_if_empty_neither_globally_nor_per_assignee() {
289     String assignee = randomAlphanumeric(10);
290     underTest.add(new DefaultIssue().setType(randomRuleTypeExceptHotspot).setTags(Collections.emptyList()).setAssigneeUuid(assignee).setNew(new Random().nextBoolean()));
291
292     DistributedMetricStatsInt globalDistribution = underTest.globalStatistics().getDistributedMetricStats(Metric.TAG);
293     DistributedMetricStatsInt assigneeDistribution = underTest.getAssigneesStatistics().get(assignee).getDistributedMetricStats(Metric.TAG);
294     Stream.of(globalDistribution, assigneeDistribution)
295       .forEach(distribution -> {
296         assertThat(distribution.getTotal()).isZero();
297         assertThat(distribution.getForLabel(null)).isEmpty();
298       });
299   }
300
301   @Test
302   public void do_not_have_issues_when_no_issue_added() {
303     assertThat(underTest.globalStatistics().hasIssues()).isFalse();
304   }
305
306   @Test
307   public void verify_toString() {
308     String componentUuid = randomAlphanumeric(2);
309     String tag = randomAlphanumeric(3);
310     String assignee = randomAlphanumeric(4);
311     int effort = 10 + new Random().nextInt(5);
312     RuleKey ruleKey = RuleKey.of(randomAlphanumeric(5), randomAlphanumeric(6));
313     underTest.add(new DefaultIssue()
314       .setType(randomRuleTypeExceptHotspot)
315       .setComponentUuid(componentUuid)
316       .setTags(ImmutableSet.of(tag))
317       .setAssigneeUuid(assignee)
318       .setRuleKey(ruleKey)
319       .setEffort(Duration.create(effort)));
320
321     assertThat(underTest)
322       .hasToString("NewIssuesStatistics{" +
323         "assigneesStatistics={" + assignee + "=" +
324         "Stats{distributions={" +
325         "TAG=DistributedMetricStatsInt{globalStats=MetricStatsInt{on=1, off=0}, " +
326         "statsPerLabel={" + tag + "=MetricStatsInt{on=1, off=0}}}, " +
327         "COMPONENT=DistributedMetricStatsInt{globalStats=MetricStatsInt{on=1, off=0}, " +
328         "statsPerLabel={" + componentUuid + "=MetricStatsInt{on=1, off=0}}}, " +
329         "ASSIGNEE=DistributedMetricStatsInt{globalStats=MetricStatsInt{on=1, off=0}, " +
330         "statsPerLabel={" + assignee + "=MetricStatsInt{on=1, off=0}}}, " +
331         "RULE=DistributedMetricStatsInt{globalStats=MetricStatsInt{on=1, off=0}, " +
332         "statsPerLabel={" + ruleKey.toString() + "=MetricStatsInt{on=1, off=0}}}}, " +
333         "issueCount=MetricStatsInt{on=1, off=0}}}, " +
334         "globalStatistics=Stats{distributions={" +
335         "TAG=DistributedMetricStatsInt{globalStats=MetricStatsInt{on=1, off=0}, " +
336         "statsPerLabel={" + tag + "=MetricStatsInt{on=1, off=0}}}, " +
337         "COMPONENT=DistributedMetricStatsInt{globalStats=MetricStatsInt{on=1, off=0}, " +
338         "statsPerLabel={" + componentUuid + "=MetricStatsInt{on=1, off=0}}}, " +
339         "ASSIGNEE=DistributedMetricStatsInt{globalStats=MetricStatsInt{on=1, off=0}, " +
340         "statsPerLabel={" + assignee + "=MetricStatsInt{on=1, off=0}}}, " +
341         "RULE=DistributedMetricStatsInt{globalStats=MetricStatsInt{on=1, off=0}, " +
342         "statsPerLabel={" + ruleKey.toString() + "=MetricStatsInt{on=1, off=0}}}}, " +
343         "issueCount=MetricStatsInt{on=1, off=0}}}");
344   }
345
346   @CheckForNull
347   private Integer countDistributionTotal(Metric metric, String label) {
348     return underTest.globalStatistics()
349       .getDistributedMetricStats(metric)
350       .getForLabel(label)
351       .map(MetricStatsInt::getTotal)
352       .orElse(null);
353   }
354
355   private void assertStats(DistributedMetricStatsInt distribution, String label, int onCurrentAnalysis, int total) {
356     Optional<MetricStatsInt> statsOption = distribution.getForLabel(label);
357     assertThat(statsOption.isPresent()).describedAs("distribution for label %s not found", label).isTrue();
358     MetricStatsInt stats = statsOption.get();
359     assertThat(stats.getOnCurrentAnalysis()).isEqualTo(onCurrentAnalysis);
360     assertThat(stats.getTotal()).isEqualTo(total);
361   }
362
363 }