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.

LiveMeasureComputerImplTest.java 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  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.server.measure.live;
  21. import com.tngtech.java.junit.dataprovider.DataProvider;
  22. import com.tngtech.java.junit.dataprovider.DataProviderRunner;
  23. import com.tngtech.java.junit.dataprovider.UseDataProvider;
  24. import java.util.Arrays;
  25. import java.util.Collection;
  26. import java.util.List;
  27. import java.util.Optional;
  28. import java.util.concurrent.atomic.AtomicInteger;
  29. import java.util.function.Supplier;
  30. import javax.annotation.Nullable;
  31. import org.junit.Before;
  32. import org.junit.Rule;
  33. import org.junit.Test;
  34. import org.junit.rules.ExpectedException;
  35. import org.junit.runner.RunWith;
  36. import org.sonar.api.config.Configuration;
  37. import org.sonar.api.config.PropertyDefinitions;
  38. import org.sonar.api.config.internal.MapSettings;
  39. import org.sonar.api.measures.CoreMetrics;
  40. import org.sonar.api.measures.Metric;
  41. import org.sonar.api.resources.Qualifiers;
  42. import org.sonar.api.utils.System2;
  43. import org.sonar.core.config.CorePropertyDefinitions;
  44. import org.sonar.db.DbSession;
  45. import org.sonar.db.DbTester;
  46. import org.sonar.db.component.BranchDto;
  47. import org.sonar.db.component.BranchType;
  48. import org.sonar.db.component.ComponentDto;
  49. import org.sonar.db.component.ComponentTesting;
  50. import org.sonar.db.measure.LiveMeasureDto;
  51. import org.sonar.db.metric.MetricDto;
  52. import org.sonar.db.project.ProjectDto;
  53. import org.sonar.server.es.ProjectIndexer;
  54. import org.sonar.server.es.TestProjectIndexers;
  55. import org.sonar.server.measure.Rating;
  56. import org.sonar.server.qualitygate.EvaluatedQualityGate;
  57. import org.sonar.server.qualitygate.QualityGate;
  58. import org.sonar.server.qualitygate.changeevent.QGChangeEvent;
  59. import org.sonar.server.setting.ProjectConfigurationLoader;
  60. import org.sonar.server.setting.TestProjectConfigurationLoader;
  61. import static java.util.Arrays.asList;
  62. import static java.util.Collections.emptyList;
  63. import static java.util.Collections.singleton;
  64. import static org.assertj.core.api.Assertions.assertThat;
  65. import static org.mockito.ArgumentMatchers.any;
  66. import static org.mockito.ArgumentMatchers.argThat;
  67. import static org.mockito.ArgumentMatchers.eq;
  68. import static org.mockito.ArgumentMatchers.same;
  69. import static org.mockito.Mockito.mock;
  70. import static org.mockito.Mockito.verify;
  71. import static org.mockito.Mockito.when;
  72. import static org.sonar.api.resources.Qualifiers.ORDERED_BOTTOM_UP;
  73. @RunWith(DataProviderRunner.class)
  74. public class LiveMeasureComputerImplTest {
  75. @Rule
  76. public DbTester db = DbTester.create();
  77. @Rule
  78. public ExpectedException expectedException = ExpectedException.none();
  79. private final TestProjectIndexers projectIndexer = new TestProjectIndexers();
  80. private MetricDto intMetric;
  81. private MetricDto ratingMetric;
  82. private MetricDto alertStatusMetric;
  83. private ComponentDto project;
  84. private ProjectDto projectDto;
  85. private ComponentDto dir;
  86. private ComponentDto file1;
  87. private ComponentDto file2;
  88. private ComponentDto branch;
  89. private ComponentDto branchFile;
  90. private final LiveQualityGateComputer qGateComputer = mock(LiveQualityGateComputer.class);
  91. private final QualityGate qualityGate = mock(QualityGate.class);
  92. private final EvaluatedQualityGate newQualityGate = mock(EvaluatedQualityGate.class);
  93. @Before
  94. public void setUp() {
  95. intMetric = db.measures().insertMetric(m -> m.setValueType(Metric.ValueType.INT.name()));
  96. ratingMetric = db.measures().insertMetric(m -> m.setValueType(Metric.ValueType.RATING.name()));
  97. alertStatusMetric = db.measures().insertMetric(m -> m.setKey(CoreMetrics.ALERT_STATUS_KEY));
  98. project = db.components().insertPublicProject();
  99. projectDto = db.components().getProjectDto(project);
  100. dir = db.components().insertComponent(ComponentTesting.newDirectory(project, "src/main/java"));
  101. file1 = db.components().insertComponent(ComponentTesting.newFileDto(project, dir));
  102. file2 = db.components().insertComponent(ComponentTesting.newFileDto(project, dir));
  103. branch = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.PULL_REQUEST));
  104. branchFile = db.components().insertComponent(ComponentTesting.newFileDto(branch));
  105. }
  106. @Test
  107. public void compute_and_insert_measures_if_they_do_not_exist_yet() {
  108. markProjectAsAnalyzed(project);
  109. List<QGChangeEvent> result = run(asList(file1, file2), newQualifierBasedIntFormula(), newRatingConstantFormula(Rating.C));
  110. // 2 measures per component have been created
  111. // Numeric value depends on qualifier (see newQualifierBasedIntFormula())
  112. assertThat(db.countRowsOfTable(db.getSession(), "live_measures")).isEqualTo(8);
  113. assertThatIntMeasureHasValue(file1, ORDERED_BOTTOM_UP.indexOf(Qualifiers.FILE));
  114. assertThatRatingMeasureHasValue(file1, Rating.C);
  115. assertThatIntMeasureHasValue(file2, ORDERED_BOTTOM_UP.indexOf(Qualifiers.FILE));
  116. assertThatRatingMeasureHasValue(file2, Rating.C);
  117. assertThatIntMeasureHasValue(dir, ORDERED_BOTTOM_UP.indexOf(Qualifiers.DIRECTORY));
  118. assertThatRatingMeasureHasValue(dir, Rating.C);
  119. assertThatIntMeasureHasValue(project, ORDERED_BOTTOM_UP.indexOf(Qualifiers.PROJECT));
  120. assertThatRatingMeasureHasValue(project, Rating.C);
  121. assertThatProjectChanged(result, project);
  122. }
  123. @Test
  124. public void compute_and_update_measures_if_they_already_exist() {
  125. markProjectAsAnalyzed(project);
  126. db.measures().insertLiveMeasure(project, intMetric, m -> m.setValue(42.0));
  127. db.measures().insertLiveMeasure(dir, intMetric, m -> m.setValue(42.0));
  128. db.measures().insertLiveMeasure(file1, intMetric, m -> m.setValue(42.0));
  129. db.measures().insertLiveMeasure(file2, intMetric, m -> m.setValue(42.0));
  130. // generates values 1, 2, 3
  131. List<QGChangeEvent> result = run(file1, newQualifierBasedIntFormula());
  132. assertThat(db.countRowsOfTable(db.getSession(), "live_measures")).isEqualTo(4);
  133. assertThatProjectChanged(result, project);
  134. // Numeric value depends on qualifier (see newQualifierBasedIntFormula())
  135. assertThatIntMeasureHasValue(file1, ORDERED_BOTTOM_UP.indexOf(Qualifiers.FILE));
  136. assertThatIntMeasureHasValue(dir, ORDERED_BOTTOM_UP.indexOf(Qualifiers.DIRECTORY));
  137. assertThatIntMeasureHasValue(project, ORDERED_BOTTOM_UP.indexOf(Qualifiers.PROJECT));
  138. // untouched
  139. assertThatIntMeasureHasValue(file2, 42.0);
  140. }
  141. @Test
  142. public void variation_is_refreshed_when_int_value_is_changed() {
  143. markProjectAsAnalyzed(project);
  144. // value is:
  145. // 42 on last analysis
  146. // 42-12=30 on beginning of leak period
  147. db.measures().insertLiveMeasure(project, intMetric, m -> m.setValue(42.0).setVariation(12.0));
  148. // new value is 44, so variation on leak period is 44-30=14
  149. List<QGChangeEvent> result = run(file1, newIntConstantFormula(44.0));
  150. LiveMeasureDto measure = assertThatIntMeasureHasValue(project, 44.0);
  151. assertThat(measure.getVariation()).isEqualTo(14.0);
  152. assertThatProjectChanged(result, project);
  153. }
  154. @Test
  155. public void variation_is_refreshed_when_rating_value_is_changed() {
  156. markProjectAsAnalyzed(project);
  157. // value is:
  158. // B on last analysis
  159. // D on beginning of leak period --> variation is -2
  160. db.measures().insertLiveMeasure(project, ratingMetric, m -> m.setValue((double) Rating.B.getIndex()).setData("B").setVariation(-2.0));
  161. // new value is C, so variation on leak period is D to C = -1
  162. List<QGChangeEvent> result = run(file1, newRatingConstantFormula(Rating.C));
  163. LiveMeasureDto measure = assertThatRatingMeasureHasValue(project, Rating.C);
  164. assertThat(measure.getVariation()).isEqualTo(-1.0);
  165. assertThatProjectChanged(result, project);
  166. }
  167. @Test
  168. public void variation_does_not_change_if_rating_value_does_not_change() {
  169. markProjectAsAnalyzed(project);
  170. // value is:
  171. // B on last analysis
  172. // D on beginning of leak period --> variation is -2
  173. db.measures().insertLiveMeasure(project, ratingMetric, m -> m.setValue((double) Rating.B.getIndex()).setData("B").setVariation(-2.0));
  174. // new value is still B, so variation on leak period is still -2
  175. List<QGChangeEvent> result = run(file1, newRatingConstantFormula(Rating.B));
  176. LiveMeasureDto measure = assertThatRatingMeasureHasValue(project, Rating.B);
  177. assertThat(measure.getVariation()).isEqualTo(-2.0);
  178. assertThatProjectChanged(result, project);
  179. }
  180. @Test
  181. public void refresh_leak_measures() {
  182. markProjectAsAnalyzed(project);
  183. db.measures().insertLiveMeasure(project, intMetric, m -> m.setVariation(42.0).setValue(null));
  184. db.measures().insertLiveMeasure(project, ratingMetric, m -> m.setVariation((double) Rating.E.getIndex()));
  185. db.measures().insertLiveMeasure(dir, intMetric, m -> m.setVariation(42.0).setValue(null));
  186. db.measures().insertLiveMeasure(dir, ratingMetric, m -> m.setVariation((double) Rating.D.getIndex()));
  187. db.measures().insertLiveMeasure(file1, intMetric, m -> m.setVariation(42.0).setValue(null));
  188. db.measures().insertLiveMeasure(file1, ratingMetric, m -> m.setVariation((double) Rating.C.getIndex()));
  189. // generates values 1, 2, 3 on leak measures
  190. List<QGChangeEvent> result = run(file1, newQualifierBasedIntLeakFormula(), newRatingLeakFormula(Rating.B));
  191. assertThat(db.countRowsOfTable(db.getSession(), "live_measures")).isEqualTo(6);
  192. // Numeric value depends on qualifier (see newQualifierBasedIntLeakFormula())
  193. assertThatIntMeasureHasLeakValue(file1, ORDERED_BOTTOM_UP.indexOf(Qualifiers.FILE));
  194. assertThatRatingMeasureHasLeakValue(file1, Rating.B);
  195. assertThatIntMeasureHasLeakValue(dir, ORDERED_BOTTOM_UP.indexOf(Qualifiers.DIRECTORY));
  196. assertThatRatingMeasureHasLeakValue(dir, Rating.B);
  197. assertThatIntMeasureHasLeakValue(project, ORDERED_BOTTOM_UP.indexOf(Qualifiers.PROJECT));
  198. assertThatRatingMeasureHasLeakValue(project, Rating.B);
  199. assertThatProjectChanged(result, project);
  200. }
  201. @Test
  202. public void calculate_new_metrics_if_it_is_pr_or_branch() {
  203. markProjectAsAnalyzed(branch, null);
  204. db.measures().insertLiveMeasure(branch, intMetric, m -> m.setVariation(42.0).setValue(null));
  205. db.measures().insertLiveMeasure(branchFile, intMetric, m -> m.setVariation(42.0).setValue(null));
  206. // generates values 1, 2, 3 on leak measures
  207. List<QGChangeEvent> result = run(branchFile, newQualifierBasedIntLeakFormula(), newRatingLeakFormula(Rating.B));
  208. assertThat(db.countRowsOfTable(db.getSession(), "live_measures")).isEqualTo(4);
  209. // Numeric value depends on qualifier (see newQualifierBasedIntLeakFormula())
  210. assertThatIntMeasureHasLeakValue(branchFile, ORDERED_BOTTOM_UP.indexOf(Qualifiers.FILE));
  211. assertThatRatingMeasureHasLeakValue(branchFile, Rating.B);
  212. assertThatIntMeasureHasLeakValue(branch, ORDERED_BOTTOM_UP.indexOf(Qualifiers.PROJECT));
  213. assertThatRatingMeasureHasLeakValue(branch, Rating.B);
  214. assertThatProjectChanged(result, branch);
  215. }
  216. @Test
  217. public void do_nothing_if_project_has_not_been_analyzed() {
  218. // project has no snapshots
  219. List<QGChangeEvent> result = run(file1, newIncrementalFormula());
  220. assertThat(db.countRowsOfTable(db.getSession(), "live_measures")).isZero();
  221. assertThatProjectNotChanged(result, project);
  222. }
  223. @Test
  224. public void do_nothing_if_input_components_are_empty() {
  225. List<QGChangeEvent> result = run(emptyList(), newIncrementalFormula());
  226. assertThat(db.countRowsOfTable(db.getSession(), "live_measures")).isZero();
  227. assertThatProjectNotChanged(result, project);
  228. }
  229. @Test
  230. public void refresh_multiple_projects_at_the_same_time() {
  231. markProjectAsAnalyzed(project);
  232. ComponentDto project2 = db.components().insertPublicProject();
  233. ComponentDto fileInProject2 = db.components().insertComponent(ComponentTesting.newFileDto(project2));
  234. markProjectAsAnalyzed(project2);
  235. List<QGChangeEvent> result = run(asList(file1, fileInProject2), newQualifierBasedIntFormula());
  236. // generated values depend on position of qualifier in Qualifiers.ORDERED_BOTTOM_UP (see formula)
  237. assertThatIntMeasureHasValue(file1, 0);
  238. assertThatIntMeasureHasValue(dir, 2);
  239. assertThatIntMeasureHasValue(project, 4);
  240. assertThatIntMeasureHasValue(fileInProject2, 0);
  241. assertThatIntMeasureHasValue(project2, 4);
  242. // no other measures generated
  243. assertThat(db.countRowsOfTable(db.getSession(), "live_measures")).isEqualTo(5);
  244. assertThatProjectChanged(result, project, project2);
  245. }
  246. @Test
  247. public void refresh_multiple_branches_at_the_same_time() {
  248. // FIXME
  249. }
  250. @Test
  251. public void event_contains_no_previousStatus_if_measure_does_not_exist() {
  252. markProjectAsAnalyzed(project);
  253. List<QGChangeEvent> result = run(file1);
  254. assertThat(result)
  255. .extracting(QGChangeEvent::getPreviousStatus)
  256. .containsExactly(Optional.empty());
  257. }
  258. @Test
  259. public void event_contains_no_previousStatus_if_measure_exists_and_has_no_value() {
  260. markProjectAsAnalyzed(project);
  261. db.measures().insertLiveMeasure(project, alertStatusMetric, m -> m.setData((String) null));
  262. List<QGChangeEvent> result = run(file1);
  263. assertThat(result)
  264. .extracting(QGChangeEvent::getPreviousStatus)
  265. .containsExactly(Optional.empty());
  266. }
  267. @Test
  268. public void event_contains_no_previousStatus_if_measure_exists_and_is_empty() {
  269. markProjectAsAnalyzed(project);
  270. db.measures().insertLiveMeasure(project, alertStatusMetric, m -> m.setData(""));
  271. List<QGChangeEvent> result = run(file1);
  272. assertThat(result)
  273. .extracting(QGChangeEvent::getPreviousStatus)
  274. .containsExactly(Optional.empty());
  275. }
  276. @Test
  277. public void event_contains_no_previousStatus_if_measure_exists_and_is_not_a_level() {
  278. markProjectAsAnalyzed(project);
  279. db.measures().insertLiveMeasure(project, alertStatusMetric, m -> m.setData("fooBar"));
  280. List<QGChangeEvent> result = run(file1);
  281. assertThat(result)
  282. .extracting(QGChangeEvent::getPreviousStatus)
  283. .containsExactly(Optional.empty());
  284. }
  285. @Test
  286. @UseDataProvider("metricLevels")
  287. public void event_contains_previousStatus_if_measure_exists(Metric.Level level) {
  288. markProjectAsAnalyzed(project);
  289. db.measures().insertLiveMeasure(project, alertStatusMetric, m -> m.setData(level.name()));
  290. db.measures().insertLiveMeasure(project, intMetric, m -> m.setVariation(42.0).setValue(null));
  291. List<QGChangeEvent> result = run(file1, newQualifierBasedIntLeakFormula());
  292. assertThat(result)
  293. .extracting(QGChangeEvent::getPreviousStatus)
  294. .containsExactly(Optional.of(level));
  295. }
  296. @DataProvider
  297. public static Object[][] metricLevels() {
  298. return Arrays.stream(Metric.Level.values())
  299. .map(l -> new Object[] {l})
  300. .toArray(Object[][]::new);
  301. }
  302. @Test
  303. public void event_contains_newQualityGate_computed_by_LiveQualityGateComputer() {
  304. markProjectAsAnalyzed(project);
  305. db.measures().insertLiveMeasure(project, alertStatusMetric, m -> m.setData(Metric.Level.ERROR.name()));
  306. db.measures().insertLiveMeasure(project, intMetric, m -> m.setVariation(42.0).setValue(null));
  307. BranchDto branch = db.getDbClient().branchDao().selectByBranchKey(db.getSession(), project.projectUuid(), "master")
  308. .orElseThrow(() -> new IllegalStateException("Can't find master branch"));
  309. List<QGChangeEvent> result = run(file1, newQualifierBasedIntLeakFormula());
  310. assertThat(result)
  311. .extracting(QGChangeEvent::getQualityGateSupplier)
  312. .extracting(Supplier::get)
  313. .containsExactly(Optional.of(newQualityGate));
  314. verify(qGateComputer).loadQualityGate(any(DbSession.class), argThat(p -> p.getUuid().equals(projectDto.getUuid())), eq(branch));
  315. verify(qGateComputer).getMetricsRelatedTo(qualityGate);
  316. verify(qGateComputer).refreshGateStatus(eq(project), same(qualityGate), any(MeasureMatrix.class), any(Configuration.class));
  317. }
  318. @Test
  319. public void exception_describes_context_when_a_formula_fails() {
  320. markProjectAsAnalyzed(project);
  321. Metric metric = new Metric.Builder(intMetric.getKey(), intMetric.getShortName(), Metric.ValueType.valueOf(intMetric.getValueType())).create();
  322. expectedException.expect(IllegalStateException.class);
  323. expectedException.expectMessage("Fail to compute " + metric.getKey() + " on " + project.getDbKey());
  324. run(project, new IssueMetricFormula(metric, false, (context, issueCounter) -> {
  325. throw new NullPointerException("BOOM");
  326. }));
  327. }
  328. private List<QGChangeEvent> run(ComponentDto component, IssueMetricFormula... formulas) {
  329. return run(singleton(component), formulas);
  330. }
  331. private List<QGChangeEvent> run(Collection<ComponentDto> components, IssueMetricFormula... formulas) {
  332. IssueMetricFormulaFactory formulaFactory = new TestIssueMetricFormulaFactory(asList(formulas));
  333. when(qGateComputer.loadQualityGate(any(DbSession.class), any(ProjectDto.class), any(BranchDto.class)))
  334. .thenReturn(qualityGate);
  335. when(qGateComputer.getMetricsRelatedTo(qualityGate)).thenReturn(singleton(CoreMetrics.ALERT_STATUS_KEY));
  336. when(qGateComputer.refreshGateStatus(eq(project), same(qualityGate), any(MeasureMatrix.class), any(Configuration.class)))
  337. .thenReturn(newQualityGate);
  338. MapSettings settings = new MapSettings(new PropertyDefinitions(System2.INSTANCE, CorePropertyDefinitions.all()));
  339. ProjectConfigurationLoader configurationLoader = new TestProjectConfigurationLoader(settings.asConfig());
  340. LiveMeasureComputerImpl underTest = new LiveMeasureComputerImpl(db.getDbClient(), formulaFactory, qGateComputer, configurationLoader, projectIndexer);
  341. return underTest.refresh(db.getSession(), components);
  342. }
  343. private void markProjectAsAnalyzed(ComponentDto p) {
  344. markProjectAsAnalyzed(p, 1_490_000_000L);
  345. }
  346. private void markProjectAsAnalyzed(ComponentDto p, @Nullable Long periodDate) {
  347. assertThat(p.qualifier()).isEqualTo(Qualifiers.PROJECT);
  348. db.components().insertSnapshot(p, s -> s.setPeriodDate(periodDate));
  349. }
  350. private LiveMeasureDto assertThatIntMeasureHasValue(ComponentDto component, double expectedValue) {
  351. LiveMeasureDto measure = db.getDbClient().liveMeasureDao().selectMeasure(db.getSession(), component.uuid(), intMetric.getKey()).get();
  352. assertThat(measure.getComponentUuid()).isEqualTo(component.uuid());
  353. assertThat(measure.getProjectUuid()).isEqualTo(component.projectUuid());
  354. assertThat(measure.getMetricUuid()).isEqualTo(intMetric.getUuid());
  355. assertThat(measure.getValue()).isEqualTo(expectedValue);
  356. return measure;
  357. }
  358. private LiveMeasureDto assertThatRatingMeasureHasValue(ComponentDto component, Rating expectedRating) {
  359. LiveMeasureDto measure = db.getDbClient().liveMeasureDao().selectMeasure(db.getSession(), component.uuid(), ratingMetric.getKey()).get();
  360. assertThat(measure.getComponentUuid()).isEqualTo(component.uuid());
  361. assertThat(measure.getProjectUuid()).isEqualTo(component.projectUuid());
  362. assertThat(measure.getMetricUuid()).isEqualTo(ratingMetric.getUuid());
  363. assertThat(measure.getValue()).isEqualTo(expectedRating.getIndex());
  364. assertThat(measure.getDataAsString()).isEqualTo(expectedRating.name());
  365. return measure;
  366. }
  367. private void assertThatIntMeasureHasLeakValue(ComponentDto component, double expectedValue) {
  368. LiveMeasureDto measure = db.getDbClient().liveMeasureDao().selectMeasure(db.getSession(), component.uuid(), intMetric.getKey()).get();
  369. assertThat(measure.getComponentUuid()).isEqualTo(component.uuid());
  370. assertThat(measure.getProjectUuid()).isEqualTo(component.projectUuid());
  371. assertThat(measure.getMetricUuid()).isEqualTo(intMetric.getUuid());
  372. assertThat(measure.getValue()).isNull();
  373. assertThat(measure.getVariation()).isEqualTo(expectedValue);
  374. }
  375. private void assertThatRatingMeasureHasLeakValue(ComponentDto component, Rating expectedValue) {
  376. LiveMeasureDto measure = db.getDbClient().liveMeasureDao().selectMeasure(db.getSession(), component.uuid(), ratingMetric.getKey()).get();
  377. assertThat(measure.getComponentUuid()).isEqualTo(component.uuid());
  378. assertThat(measure.getProjectUuid()).isEqualTo(component.projectUuid());
  379. assertThat(measure.getMetricUuid()).isEqualTo(ratingMetric.getUuid());
  380. assertThat(measure.getVariation()).isEqualTo(expectedValue.getIndex());
  381. }
  382. private IssueMetricFormula newIncrementalFormula() {
  383. Metric metric = new Metric.Builder(intMetric.getKey(), intMetric.getShortName(), Metric.ValueType.valueOf(intMetric.getValueType())).create();
  384. AtomicInteger counter = new AtomicInteger();
  385. return new IssueMetricFormula(metric, false, (ctx, issues) -> {
  386. ctx.setValue(counter.incrementAndGet());
  387. });
  388. }
  389. private IssueMetricFormula newIntConstantFormula(double constant) {
  390. Metric metric = new Metric.Builder(intMetric.getKey(), intMetric.getShortName(), Metric.ValueType.valueOf(intMetric.getValueType())).create();
  391. return new IssueMetricFormula(metric, false, (ctx, issues) -> {
  392. ctx.setValue(constant);
  393. });
  394. }
  395. private IssueMetricFormula newRatingConstantFormula(Rating constant) {
  396. Metric metric = new Metric.Builder(ratingMetric.getKey(), ratingMetric.getShortName(), Metric.ValueType.valueOf(ratingMetric.getValueType())).create();
  397. return new IssueMetricFormula(metric, false, (ctx, issues) -> {
  398. ctx.setValue(constant);
  399. });
  400. }
  401. private IssueMetricFormula newRatingLeakFormula(Rating rating) {
  402. Metric metric = new Metric.Builder(ratingMetric.getKey(), ratingMetric.getShortName(), Metric.ValueType.valueOf(ratingMetric.getValueType())).create();
  403. return new IssueMetricFormula(metric, true, (ctx, issues) -> {
  404. ctx.setLeakValue(rating);
  405. });
  406. }
  407. private IssueMetricFormula newQualifierBasedIntFormula() {
  408. Metric metric = new Metric.Builder(intMetric.getKey(), intMetric.getShortName(), Metric.ValueType.valueOf(intMetric.getValueType())).create();
  409. return new IssueMetricFormula(metric, false, (ctx, issues) -> {
  410. ctx.setValue(ORDERED_BOTTOM_UP.indexOf(ctx.getComponent().qualifier()));
  411. });
  412. }
  413. private IssueMetricFormula newQualifierBasedIntLeakFormula() {
  414. Metric metric = new Metric.Builder(intMetric.getKey(), intMetric.getShortName(), Metric.ValueType.valueOf(intMetric.getValueType())).create();
  415. return new IssueMetricFormula(metric, true, (ctx, issues) -> {
  416. ctx.setLeakValue(ORDERED_BOTTOM_UP.indexOf(ctx.getComponent().qualifier()));
  417. });
  418. }
  419. private void assertThatProjectChanged(List<QGChangeEvent> events, ComponentDto... projects) {
  420. for (ComponentDto p : projects) {
  421. assertThat(projectIndexer.hasBeenCalled(p.uuid(), ProjectIndexer.Cause.MEASURE_CHANGE)).isTrue();
  422. }
  423. assertThat(events).extracting(e -> e.getBranch().getUuid())
  424. .containsExactlyInAnyOrder(Arrays.stream(projects).map(ComponentDto::uuid).toArray(String[]::new));
  425. }
  426. private void assertThatProjectNotChanged(List<QGChangeEvent> events, ComponentDto project) {
  427. assertThat(projectIndexer.hasBeenCalled(project.uuid(), ProjectIndexer.Cause.MEASURE_CHANGE)).isFalse();
  428. assertThat(events).isEmpty();
  429. }
  430. }