You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MeasureComputerContextImplTest.java 13KB

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