]> source.dussan.org Git - sonarqube.git/blob
a86892f28a6333ad216b207d56988d316f517b5e
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2017 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.computation.task.projectanalysis.api.measurecomputer;
21
22 import com.google.common.base.Optional;
23 import java.util.Arrays;
24 import java.util.Collections;
25 import java.util.List;
26 import org.junit.Rule;
27 import org.junit.Test;
28 import org.junit.rules.ExpectedException;
29 import org.sonar.api.ce.measure.Component;
30 import org.sonar.api.ce.measure.MeasureComputer;
31 import org.sonar.api.config.MapSettings;
32 import org.sonar.api.measures.CoreMetrics;
33 import org.sonar.api.rule.RuleKey;
34 import org.sonar.api.utils.Duration;
35 import org.sonar.core.issue.DefaultIssue;
36 import org.sonar.server.computation.task.projectanalysis.component.SettingsRepository;
37 import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
38 import org.sonar.server.computation.task.projectanalysis.issue.ComponentIssuesRepositoryRule;
39 import org.sonar.server.computation.task.projectanalysis.measure.Measure;
40 import org.sonar.server.computation.task.projectanalysis.measure.MeasureRepositoryRule;
41 import org.sonar.server.computation.task.projectanalysis.metric.Metric;
42 import org.sonar.server.computation.task.projectanalysis.metric.MetricImpl;
43 import org.sonar.server.computation.task.projectanalysis.metric.MetricRepositoryRule;
44
45 import static org.assertj.core.api.Assertions.assertThat;
46 import static org.assertj.guava.api.Assertions.assertThat;
47 import static org.mockito.Mockito.mock;
48 import static org.mockito.Mockito.when;
49 import static org.sonar.api.measures.CoreMetrics.COMMENT_LINES_KEY;
50 import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY;
51 import static org.sonar.server.computation.task.projectanalysis.component.ReportComponent.builder;
52 import static org.sonar.server.computation.task.projectanalysis.measure.Measure.newMeasureBuilder;
53
54 public class MeasureComputerContextImplTest {
55
56   @Rule
57   public ExpectedException thrown = ExpectedException.none();
58
59   private static final String INT_METRIC_KEY = "int_metric_key";
60   private static final String DOUBLE_METRIC_KEY = "double_metric_key";
61   private static final String LONG_METRIC_KEY = "long_metric_key";
62   private static final String STRING_METRIC_KEY = "string_metric_key";
63   private static final String BOOLEAN_METRIC_KEY = "boolean_metric_key";
64
65   private static final int PROJECT_REF = 1;
66   private static final int FILE_1_REF = 12341;
67   private static final String FILE_1_KEY = "fileKey";
68   private static final int FILE_2_REF = 12342;
69
70   private static final org.sonar.server.computation.task.projectanalysis.component.Component FILE_1 = builder(
71     org.sonar.server.computation.task.projectanalysis.component.Component.Type.FILE, FILE_1_REF)
72       .setKey(FILE_1_KEY)
73       .build();
74
75   @Rule
76   public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule()
77     .setRoot(builder(org.sonar.server.computation.task.projectanalysis.component.Component.Type.PROJECT, PROJECT_REF).setKey("project")
78       .addChildren(
79         FILE_1,
80         builder(org.sonar.server.computation.task.projectanalysis.component.Component.Type.FILE, FILE_2_REF).setKey("fileKey2").build())
81       .build());
82
83   @Rule
84   public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
85     .add(1, CoreMetrics.NCLOC)
86     .add(new MetricImpl(2, INT_METRIC_KEY, "int metric", Metric.MetricType.INT))
87     .add(new MetricImpl(3, DOUBLE_METRIC_KEY, "double metric", Metric.MetricType.FLOAT))
88     .add(new MetricImpl(4, LONG_METRIC_KEY, "long metric", Metric.MetricType.MILLISEC))
89     .add(new MetricImpl(5, STRING_METRIC_KEY, "string metric", Metric.MetricType.STRING))
90     .add(new MetricImpl(6, BOOLEAN_METRIC_KEY, "boolean metric", Metric.MetricType.BOOL));
91
92   @Rule
93   public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
94
95   @Rule
96   public ComponentIssuesRepositoryRule componentIssuesRepository = new ComponentIssuesRepositoryRule(treeRootHolder);
97
98   SettingsRepository settingsRepository = mock(SettingsRepository.class);
99
100   @Test
101   public void get_component() throws Exception {
102     MeasureComputerContextImpl underTest = newContext(FILE_1_REF);
103     assertThat(underTest.getComponent().getType()).isEqualTo(Component.Type.FILE);
104   }
105
106   @Test
107   public void get_string_settings() throws Exception {
108     org.sonar.api.config.Settings serverSettings = new MapSettings();
109     serverSettings.setProperty("prop", "value");
110     when(settingsRepository.getSettings(FILE_1)).thenReturn(serverSettings);
111
112     MeasureComputerContextImpl underTest = newContext(FILE_1_REF);
113     assertThat(underTest.getSettings().getString("prop")).isEqualTo("value");
114     assertThat(underTest.getSettings().getString("unknown")).isNull();
115   }
116
117   @Test
118   public void get_string_array_settings() throws Exception {
119     org.sonar.api.config.Settings serverSettings = new MapSettings();
120     serverSettings.setProperty("prop", "1,3.4,8,50");
121     when(settingsRepository.getSettings(FILE_1)).thenReturn(serverSettings);
122
123     MeasureComputerContextImpl underTest = newContext(FILE_1_REF);
124     assertThat(underTest.getSettings().getStringArray("prop")).containsExactly("1", "3.4", "8", "50");
125     assertThat(underTest.getSettings().getStringArray("unknown")).isEmpty();
126   }
127
128   @Test
129   public void get_measure() throws Exception {
130     measureRepository.addRawMeasure(FILE_1_REF, NCLOC_KEY, newMeasureBuilder().create(10));
131
132     MeasureComputerContextImpl underTest = newContext(FILE_1_REF, NCLOC_KEY, COMMENT_LINES_KEY);
133     assertThat(underTest.getMeasure(NCLOC_KEY).getIntValue()).isEqualTo(10);
134   }
135
136   @Test
137   public void fail_with_IAE_when_get_measure_is_called_on_metric_not_in_input_list() throws Exception {
138     thrown.expect(IllegalArgumentException.class);
139     thrown.expectMessage("Only metrics in [another metric] can be used to load measures");
140
141     MeasureComputerContextImpl underTest = newContext(PROJECT_REF, "another metric", "debt");
142     underTest.getMeasure(NCLOC_KEY);
143   }
144
145   @Test
146   public void get_children_measures() throws Exception {
147     measureRepository.addRawMeasure(FILE_1_REF, NCLOC_KEY, newMeasureBuilder().create(10));
148     measureRepository.addRawMeasure(FILE_2_REF, NCLOC_KEY, newMeasureBuilder().create(12));
149
150     MeasureComputerContextImpl underTest = newContext(PROJECT_REF, NCLOC_KEY, COMMENT_LINES_KEY);
151     assertThat(underTest.getChildrenMeasures(NCLOC_KEY)).hasSize(2);
152     assertThat(underTest.getChildrenMeasures(NCLOC_KEY)).extracting("intValue").containsOnly(10, 12);
153   }
154
155   @Test
156   public void get_children_measures_when_one_child_has_no_value() throws Exception {
157     measureRepository.addRawMeasure(FILE_1_REF, NCLOC_KEY, newMeasureBuilder().create(10));
158     // No data on file 2
159
160     MeasureComputerContextImpl underTest = newContext(PROJECT_REF, NCLOC_KEY, COMMENT_LINES_KEY);
161     assertThat(underTest.getChildrenMeasures(NCLOC_KEY)).extracting("intValue").containsOnly(10);
162   }
163
164   @Test
165   public void not_fail_to_get_children_measures_on_output_metric() throws Exception {
166     measureRepository.addRawMeasure(FILE_1_REF, INT_METRIC_KEY, newMeasureBuilder().create(10));
167
168     MeasureComputerContextImpl underTest = newContext(PROJECT_REF, NCLOC_KEY, INT_METRIC_KEY);
169     assertThat(underTest.getChildrenMeasures(INT_METRIC_KEY)).hasSize(1);
170     assertThat(underTest.getChildrenMeasures(INT_METRIC_KEY)).extracting("intValue").containsOnly(10);
171   }
172
173   @Test
174   public void fail_with_IAE_when_get_children_measures_is_called_on_metric_not_in_input_list() throws Exception {
175     thrown.expect(IllegalArgumentException.class);
176     thrown.expectMessage("Only metrics in [another metric] can be used to load measures");
177
178     MeasureComputerContextImpl underTest = newContext(PROJECT_REF, "another metric", "debt");
179     underTest.getChildrenMeasures(NCLOC_KEY);
180   }
181
182   @Test
183   public void add_int_measure_create_measure_of_type_int_with_right_value() throws Exception {
184     MeasureComputerContextImpl underTest = newContext(PROJECT_REF, NCLOC_KEY, INT_METRIC_KEY);
185     underTest.addMeasure(INT_METRIC_KEY, 10);
186
187     Optional<Measure> measure = measureRepository.getAddedRawMeasure(PROJECT_REF, INT_METRIC_KEY);
188     assertThat(measure).isPresent();
189     assertThat(measure.get().getIntValue()).isEqualTo(10);
190   }
191
192   @Test
193   public void add_double_measure_create_measure_of_type_double_with_right_value() throws Exception {
194     MeasureComputerContextImpl underTest = newContext(PROJECT_REF, NCLOC_KEY, DOUBLE_METRIC_KEY);
195     underTest.addMeasure(DOUBLE_METRIC_KEY, 10d);
196
197     Optional<Measure> measure = measureRepository.getAddedRawMeasure(PROJECT_REF, DOUBLE_METRIC_KEY);
198     assertThat(measure).isPresent();
199     assertThat(measure.get().getDoubleValue()).isEqualTo(10d);
200   }
201
202   @Test
203   public void add_long_measure_create_measure_of_type_long_with_right_value() throws Exception {
204     MeasureComputerContextImpl underTest = newContext(PROJECT_REF, NCLOC_KEY, LONG_METRIC_KEY);
205     underTest.addMeasure(LONG_METRIC_KEY, 10L);
206
207     Optional<Measure> measure = measureRepository.getAddedRawMeasure(PROJECT_REF, LONG_METRIC_KEY);
208     assertThat(measure).isPresent();
209     assertThat(measure.get().getLongValue()).isEqualTo(10L);
210   }
211
212   @Test
213   public void add_string_measure_create_measure_of_type_string_with_right_value() throws Exception {
214     MeasureComputerContextImpl underTest = newContext(PROJECT_REF, NCLOC_KEY, STRING_METRIC_KEY);
215     underTest.addMeasure(STRING_METRIC_KEY, "data");
216
217     Optional<Measure> measure = measureRepository.getAddedRawMeasure(PROJECT_REF, STRING_METRIC_KEY);
218     assertThat(measure).isPresent();
219     assertThat(measure.get().getStringValue()).isEqualTo("data");
220   }
221
222   @Test
223   public void add_boolean_measure_create_measure_of_type_boolean_with_right_value() throws Exception {
224     MeasureComputerContextImpl underTest = newContext(PROJECT_REF, NCLOC_KEY, BOOLEAN_METRIC_KEY);
225     underTest.addMeasure(BOOLEAN_METRIC_KEY, true);
226
227     Optional<Measure> measure = measureRepository.getAddedRawMeasure(PROJECT_REF, BOOLEAN_METRIC_KEY);
228     assertThat(measure).isPresent();
229     assertThat(measure.get().getBooleanValue()).isTrue();
230   }
231
232   @Test
233   public void fail_with_IAE_when_add_measure_is_called_on_metric_not_in_output_list() throws Exception {
234     thrown.expect(IllegalArgumentException.class);
235     thrown.expectMessage("Only metrics in [int_metric_key] can be used to add measures. Metric 'double_metric_key' is not allowed.");
236
237     MeasureComputerContextImpl underTest = newContext(PROJECT_REF, NCLOC_KEY, INT_METRIC_KEY);
238     underTest.addMeasure(DOUBLE_METRIC_KEY, 10);
239   }
240
241   @Test
242   public void fail_with_unsupported_operation_when_adding_measure_that_already_exists() throws Exception {
243     thrown.expect(UnsupportedOperationException.class);
244     thrown.expectMessage("A measure on metric 'int_metric_key' already exists on component 'fileKey'");
245
246     measureRepository.addRawMeasure(FILE_1_REF, INT_METRIC_KEY, newMeasureBuilder().create(20));
247
248     MeasureComputerContextImpl underTest = newContext(FILE_1_REF, NCLOC_KEY, INT_METRIC_KEY);
249     underTest.addMeasure(INT_METRIC_KEY, 10);
250   }
251
252   @Test
253   public void get_issues() throws Exception {
254     DefaultIssue issue = new DefaultIssue()
255       .setKey("KEY")
256       .setRuleKey(RuleKey.of("xoo", "S01"))
257       .setSeverity("MAJOR")
258       .setStatus("CLOSED")
259       .setResolution("FIXED")
260       .setEffort(Duration.create(10l));
261
262     MeasureComputerContextImpl underTest = newContext(PROJECT_REF, Arrays.asList(issue));
263
264     assertThat(underTest.getIssues()).hasSize(1);
265     org.sonar.api.ce.measure.Issue result = underTest.getIssues().get(0);
266     assertThat(result.key()).isEqualTo("KEY");
267     assertThat(result.ruleKey()).isEqualTo(RuleKey.of("xoo", "S01"));
268     assertThat(result.severity()).isEqualTo("MAJOR");
269     assertThat(result.status()).isEqualTo("CLOSED");
270     assertThat(result.resolution()).isEqualTo("FIXED");
271     assertThat(result.debt()).isEqualTo(Duration.create(10l));
272   }
273
274   private MeasureComputerContextImpl newContext(int componentRef) {
275     return newContext(componentRef, NCLOC_KEY, COMMENT_LINES_KEY, Collections.<DefaultIssue>emptyList());
276   }
277
278   private MeasureComputerContextImpl newContext(int componentRef, List<DefaultIssue> issues) {
279     return newContext(componentRef, NCLOC_KEY, COMMENT_LINES_KEY, issues);
280   }
281
282   private MeasureComputerContextImpl newContext(int componentRef, String inputMetric, String outputMetric) {
283     return newContext(componentRef, inputMetric, outputMetric, Collections.<DefaultIssue>emptyList());
284   }
285
286   private MeasureComputerContextImpl newContext(int componentRef, String inputMetric, String outputMetric, List<DefaultIssue> issues) {
287     componentIssuesRepository.setIssues(componentRef, issues);
288
289     MeasureComputer.MeasureComputerDefinition definition = new MeasureComputerDefinitionImpl.BuilderImpl()
290       .setInputMetrics(new String[] {inputMetric})
291       .setOutputMetrics(new String[] {outputMetric})
292       .build();
293
294     MeasureComputerContextImpl context = new MeasureComputerContextImpl(treeRootHolder.getComponentByRef(componentRef),
295       settingsRepository, measureRepository, metricRepository, componentIssuesRepository);
296     context.setDefinition(definition);
297     return context;
298   }
299 }