]> source.dussan.org Git - sonarqube.git/blob
2f0413de2e9f8649467fc3b3c0b2b75a60e1d119
[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.measure.live;
21
22 import java.util.Date;
23 import java.util.List;
24 import java.util.Set;
25 import org.junit.Before;
26 import org.junit.Rule;
27 import org.junit.Test;
28 import org.sonar.api.config.Configuration;
29 import org.sonar.api.config.internal.MapSettings;
30 import org.sonar.api.measures.Metric;
31 import org.sonar.db.DbTester;
32 import org.sonar.db.component.BranchDto;
33 import org.sonar.db.component.BranchType;
34 import org.sonar.db.component.ComponentDto;
35 import org.sonar.db.component.ComponentTesting;
36 import org.sonar.db.component.SnapshotDto;
37 import org.sonar.db.issue.IssueDto;
38 import org.sonar.db.measure.LiveMeasureDto;
39 import org.sonar.db.metric.MetricDto;
40 import org.sonar.db.newcodeperiod.NewCodePeriodType;
41 import org.sonar.db.rule.RuleDto;
42
43 import static org.assertj.core.api.Assertions.assertThat;
44 import static org.mockito.ArgumentMatchers.any;
45 import static org.mockito.ArgumentMatchers.eq;
46 import static org.mockito.Mockito.mock;
47 import static org.mockito.Mockito.verify;
48 import static org.sonar.api.CoreProperties.RATING_GRID;
49
50 public class LiveMeasureTreeUpdaterImplTest {
51   @Rule
52   public DbTester db = DbTester.create();
53
54   private final Configuration config = new MapSettings().setProperty(RATING_GRID, "0.05,0.1,0.2,0.5").asConfig();
55   private final HotspotMeasureUpdater hotspotMeasureUpdater = mock(HotspotMeasureUpdater.class);
56   private LiveMeasureTreeUpdaterImpl treeUpdater;
57   private ComponentIndexImpl componentIndex;
58   private MeasureMatrix matrix;
59   private MetricDto metricDto;
60   private Metric metric;
61   private ComponentDto project;
62   private BranchDto branch;
63   private ComponentDto dir;
64   private ComponentDto file1;
65   private ComponentDto file2;
66   private SnapshotDto snapshot;
67
68   @Before
69   public void setUp() {
70     // insert project and file structure
71     project = db.components().insertPrivateProject();
72     branch = db.getDbClient().branchDao().selectByUuid(db.getSession(), project.uuid()).get();
73     dir = db.components().insertComponent(ComponentTesting.newDirectory(project, "src/main/java"));
74     file1 = db.components().insertComponent(ComponentTesting.newFileDto(project, dir));
75     file2 = db.components().insertComponent(ComponentTesting.newFileDto(project, dir));
76
77     // other needed data
78     metricDto = db.measures().insertMetric(m -> m.setValueType(Metric.ValueType.INT.name()));
79     metric = new Metric.Builder(metricDto.getKey(), metricDto.getShortName(), Metric.ValueType.valueOf(metricDto.getValueType())).create();
80     matrix = new MeasureMatrix(List.of(project, dir, file1, file2), List.of(metricDto), List.of());
81     componentIndex = new ComponentIndexImpl(db.getDbClient());
82   }
83
84   @Test
85   public void should_aggregate_values_up_the_hierarchy() {
86     snapshot = db.components().insertSnapshot(project);
87     treeUpdater = new LiveMeasureTreeUpdaterImpl(db.getDbClient(), new AggregateValuesFormula(), hotspotMeasureUpdater);
88
89     componentIndex.load(db.getSession(), List.of(file1));
90     List<LiveMeasureDto> initialValues = List.of(
91       new LiveMeasureDto().setComponentUuid(file1.uuid()).setValue(1d).setMetricUuid(metricDto.getUuid()),
92       new LiveMeasureDto().setComponentUuid(file2.uuid()).setValue(1d).setMetricUuid(metricDto.getUuid()),
93       new LiveMeasureDto().setComponentUuid(dir.uuid()).setValue(1d).setMetricUuid(metricDto.getUuid()),
94       new LiveMeasureDto().setComponentUuid(project.uuid()).setValue(1d).setMetricUuid(metricDto.getUuid())
95     );
96     matrix = new MeasureMatrix(List.of(project, dir, file1, file2), List.of(metricDto), initialValues);
97     treeUpdater.update(db.getSession(), snapshot, config, componentIndex, branch, matrix);
98
99     assertThat(matrix.getChanged()).extracting(LiveMeasureDto::getComponentUuid).containsOnly(project.uuid(), dir.uuid());
100     assertThat(matrix.getMeasure(project, metric.getKey()).get().getValue()).isEqualTo(4d);
101     assertThat(matrix.getMeasure(dir, metric.getKey()).get().getValue()).isEqualTo(3d);
102     assertThat(matrix.getMeasure(file1, metric.getKey()).get().getValue()).isEqualTo(1d);
103     assertThat(matrix.getMeasure(file2, metric.getKey()).get().getValue()).isEqualTo(1d);
104   }
105
106   @Test
107   public void should_set_values_up_the_hierarchy() {
108     snapshot = db.components().insertSnapshot(project);
109     treeUpdater = new LiveMeasureTreeUpdaterImpl(db.getDbClient(), new SetValuesFormula(), hotspotMeasureUpdater);
110
111     componentIndex.load(db.getSession(), List.of(file1));
112     treeUpdater.update(db.getSession(), snapshot, config, componentIndex, branch, matrix);
113
114     assertThat(matrix.getChanged()).extracting(LiveMeasureDto::getComponentUuid).containsOnly(project.uuid(), dir.uuid(), file1.uuid());
115     assertThat(matrix.getMeasure(project, metric.getKey()).get().getValue()).isEqualTo(1d);
116     assertThat(matrix.getMeasure(dir, metric.getKey()).get().getValue()).isEqualTo(1d);
117     assertThat(matrix.getMeasure(file1, metric.getKey()).get().getValue()).isEqualTo(1d);
118     assertThat(matrix.getMeasure(file2, metric.getKey())).isEmpty();
119   }
120
121   @Test
122   public void dont_use_leak_formulas_if_no_period() {
123     snapshot = db.components().insertSnapshot(project, s -> s.setPeriodDate(null));
124     treeUpdater = new LiveMeasureTreeUpdaterImpl(db.getDbClient(), new CountUnresolvedInLeak(), hotspotMeasureUpdater);
125
126     componentIndex.load(db.getSession(), List.of(file1));
127     treeUpdater.update(db.getSession(), snapshot, config, componentIndex, branch, matrix);
128
129     assertThat(matrix.getChanged()).extracting(LiveMeasureDto::getComponentUuid).isEmpty();
130   }
131
132   @Test
133   public void use_leak_formulas_if_pr() {
134     snapshot = db.components().insertSnapshot(project, s -> s.setPeriodDate(null));
135     branch.setBranchType(BranchType.PULL_REQUEST);
136     treeUpdater = new LiveMeasureTreeUpdaterImpl(db.getDbClient(), new CountUnresolvedInLeak(), hotspotMeasureUpdater);
137
138     componentIndex.load(db.getSession(), List.of(file1));
139     treeUpdater.update(db.getSession(), snapshot, config, componentIndex, branch, matrix);
140
141     assertThat(matrix.getChanged()).extracting(LiveMeasureDto::getComponentUuid).containsOnly(project.uuid(), dir.uuid(), file1.uuid());
142   }
143
144   @Test
145   public void calculate_new_metrics_if_using_new_code_branch_reference() {
146     snapshot = db.components().insertSnapshot(project, s -> s.setPeriodMode(NewCodePeriodType.REFERENCE_BRANCH.name()));
147     treeUpdater = new LiveMeasureTreeUpdaterImpl(db.getDbClient(), new CountUnresolvedInLeak(), hotspotMeasureUpdater);
148
149     componentIndex.load(db.getSession(), List.of(file1));
150     treeUpdater.update(db.getSession(), snapshot, config, componentIndex, branch, matrix);
151
152     assertThat(matrix.getChanged()).extracting(LiveMeasureDto::getComponentUuid).containsOnly(project.uuid(), dir.uuid(), file1.uuid());
153   }
154
155   @Test
156   public void issue_counter_based_on_new_code_branch_reference() {
157     snapshot = db.components().insertSnapshot(project, s -> s.setPeriodMode(NewCodePeriodType.REFERENCE_BRANCH.name()));
158     treeUpdater = new LiveMeasureTreeUpdaterImpl(db.getDbClient(), new CountUnresolvedInLeak(), hotspotMeasureUpdater);
159
160     RuleDto rule = db.rules().insert();
161     IssueDto issue1 = db.issues().insertIssue(rule, project, file1);
162     IssueDto issue2 = db.issues().insertIssue(rule, project, file1);
163     db.issues().insertNewCodeReferenceIssue(issue1);
164
165     componentIndex.load(db.getSession(), List.of(file1));
166     treeUpdater.update(db.getSession(), snapshot, config, componentIndex, branch, matrix);
167     assertThat(matrix.getMeasure(file1, metric.getKey()).get().getVariation()).isEqualTo(1d);
168   }
169
170   @Test
171   public void issue_counter_uses_begin_of_leak() {
172     snapshot = db.components().insertSnapshot(project, s -> s.setPeriodDate(1000L));
173     treeUpdater = new LiveMeasureTreeUpdaterImpl(db.getDbClient(), new CountUnresolvedInLeak(), hotspotMeasureUpdater);
174
175     db.issues().insertIssue(i -> i.setIssueCreationDate(new Date(999)).setComponentUuid(file1.uuid()));
176     db.issues().insertIssue(i -> i.setIssueCreationDate(new Date(1001)).setComponentUuid(file1.uuid()));
177     db.issues().insertIssue(i -> i.setIssueCreationDate(new Date(1002)).setComponentUuid(file1.uuid()));
178
179     componentIndex.load(db.getSession(), List.of(file1));
180     treeUpdater.update(db.getSession(), snapshot, config, componentIndex, branch, matrix);
181
182     assertThat(matrix.getMeasure(file1, metric.getKey()).get().getVariation()).isEqualTo(2d);
183   }
184
185   @Test
186   public void calls_hotspot_updater() {
187     snapshot = db.components().insertSnapshot(project, s -> s.setPeriodDate(1000L));
188
189     componentIndex.load(db.getSession(), List.of(file1));
190     treeUpdater = new LiveMeasureTreeUpdaterImpl(db.getDbClient(), new CountUnresolvedInLeak(), hotspotMeasureUpdater);
191     treeUpdater.update(db.getSession(), snapshot, config, componentIndex, branch, matrix);
192     verify(hotspotMeasureUpdater).apply(eq(db.getSession()), any(), eq(componentIndex), eq(true), eq(1000L));
193   }
194
195   private class AggregateValuesFormula implements MeasureUpdateFormulaFactory {
196     @Override
197     public List<MeasureUpdateFormula> getFormulas() {
198       return List.of(new MeasureUpdateFormula(metric, false, new MeasureUpdateFormulaFactoryImpl.AddChildren(), (c, i) -> {
199       }));
200     }
201
202     @Override
203     public Set<Metric> getFormulaMetrics() {
204       return Set.of(metric);
205     }
206   }
207
208   private class SetValuesFormula implements MeasureUpdateFormulaFactory {
209     @Override
210     public List<MeasureUpdateFormula> getFormulas() {
211       return List.of(new MeasureUpdateFormula(metric, false, (c, m) -> {
212       }, (c, i) -> c.setValue(1d)));
213     }
214
215     @Override
216     public Set<Metric> getFormulaMetrics() {
217       return Set.of(metric);
218     }
219   }
220
221   private class CountUnresolvedInLeak implements MeasureUpdateFormulaFactory {
222     @Override
223     public List<MeasureUpdateFormula> getFormulas() {
224       return List.of(new MeasureUpdateFormula(metric, true, (c, m) -> {
225       }, (c, i) -> c.setLeakValue(i.countUnresolved(true))));
226     }
227
228     @Override
229     public Set<Metric> getFormulaMetrics() {
230       return Set.of(metric);
231     }
232   }
233 }