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.

LiveMeasureDaoTest.java 35KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2023 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.db.measure;
  21. import java.nio.charset.StandardCharsets;
  22. import java.util.ArrayList;
  23. import java.util.Arrays;
  24. import java.util.Collections;
  25. import java.util.List;
  26. import java.util.Map;
  27. import java.util.Optional;
  28. import java.util.stream.IntStream;
  29. import org.apache.commons.lang.RandomStringUtils;
  30. import org.junit.Before;
  31. import org.junit.Rule;
  32. import org.junit.Test;
  33. import org.mockito.internal.util.collections.Sets;
  34. import org.sonar.api.utils.System2;
  35. import org.sonar.db.DbTester;
  36. import org.sonar.db.component.BranchType;
  37. import org.sonar.db.component.ComponentDto;
  38. import org.sonar.db.metric.MetricDto;
  39. import static java.util.Arrays.asList;
  40. import static java.util.Collections.emptyList;
  41. import static java.util.Collections.singleton;
  42. import static java.util.Collections.singletonList;
  43. import static org.assertj.core.api.Assertions.assertThat;
  44. import static org.assertj.core.groups.Tuple.tuple;
  45. import static org.sonar.api.measures.Metric.ValueType.DATA;
  46. import static org.sonar.api.measures.Metric.ValueType.INT;
  47. import static org.sonar.db.component.BranchDto.DEFAULT_MAIN_BRANCH_NAME;
  48. import static org.sonar.db.component.ComponentTesting.newFileDto;
  49. import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto;
  50. import static org.sonar.db.measure.MeasureTesting.newLiveMeasure;
  51. public class LiveMeasureDaoTest {
  52. @Rule
  53. public DbTester db = DbTester.create(System2.INSTANCE);
  54. private final LiveMeasureDao underTest = db.getDbClient().liveMeasureDao();
  55. private MetricDto metric;
  56. @Before
  57. public void setUp() {
  58. metric = db.measures().insertMetric();
  59. }
  60. @Test
  61. public void selectByComponentUuidsAndMetricUuids() {
  62. LiveMeasureDto measure1 = newLiveMeasure().setMetricUuid(metric.getUuid());
  63. LiveMeasureDto measure2 = newLiveMeasure().setMetricUuid(metric.getUuid());
  64. underTest.insert(db.getSession(), measure1);
  65. underTest.insert(db.getSession(), measure2);
  66. List<LiveMeasureDto> selected = underTest.selectByComponentUuidsAndMetricUuids(db.getSession(),
  67. asList(measure1.getComponentUuid(), measure2.getComponentUuid()), singletonList(metric.getUuid()));
  68. assertThat(selected)
  69. .extracting(LiveMeasureDto::getComponentUuid, LiveMeasureDto::getProjectUuid, LiveMeasureDto::getMetricUuid, LiveMeasureDto::getValue, LiveMeasureDto::getDataAsString)
  70. .containsExactlyInAnyOrder(
  71. tuple(measure1.getComponentUuid(), measure1.getProjectUuid(), measure1.getMetricUuid(), measure1.getValue(), measure1.getDataAsString()),
  72. tuple(measure2.getComponentUuid(), measure2.getProjectUuid(), measure2.getMetricUuid(), measure2.getValue(), measure2.getDataAsString()));
  73. assertThat(underTest.selectByComponentUuidsAndMetricUuids(db.getSession(), emptyList(), singletonList(metric.getUuid()))).isEmpty();
  74. assertThat(underTest.selectByComponentUuidsAndMetricUuids(db.getSession(), singletonList(measure1.getComponentUuid()), emptyList())).isEmpty();
  75. }
  76. @Test
  77. public void selectByComponentUuidsAndMetricUuids_returns_empty_list_if_metric_does_not_match() {
  78. LiveMeasureDto measure = newLiveMeasure().setMetricUuid(metric.getUuid());
  79. underTest.insert(db.getSession(), measure);
  80. String otherMetricUuid = metric.getUuid() + "other";
  81. List<LiveMeasureDto> selected = underTest.selectByComponentUuidsAndMetricUuids(db.getSession(), singletonList(measure.getComponentUuid()), singletonList(otherMetricUuid));
  82. assertThat(selected).isEmpty();
  83. }
  84. @Test
  85. public void selectByComponentUuidsAndMetricUuids_returns_empty_list_if_component_does_not_match() {
  86. LiveMeasureDto measure = newLiveMeasure();
  87. underTest.insert(db.getSession(), measure);
  88. List<LiveMeasureDto> selected = underTest.selectByComponentUuidsAndMetricUuids(db.getSession(), singletonList("_missing_"), singletonList(measure.getMetricUuid()));
  89. assertThat(selected).isEmpty();
  90. }
  91. @Test
  92. public void selectByComponentUuidsAndMetricKeys() {
  93. LiveMeasureDto measure1 = newLiveMeasure().setMetricUuid(metric.getUuid());
  94. LiveMeasureDto measure2 = newLiveMeasure().setMetricUuid(metric.getUuid());
  95. underTest.insert(db.getSession(), measure1);
  96. underTest.insert(db.getSession(), measure2);
  97. List<LiveMeasureDto> selected = underTest.selectByComponentUuidsAndMetricKeys(db.getSession(), asList(measure1.getComponentUuid(), measure2.getComponentUuid()),
  98. singletonList(metric.getKey()));
  99. assertThat(selected)
  100. .extracting(LiveMeasureDto::getComponentUuid, LiveMeasureDto::getProjectUuid, LiveMeasureDto::getMetricUuid, LiveMeasureDto::getValue, LiveMeasureDto::getDataAsString)
  101. .containsExactlyInAnyOrder(
  102. tuple(measure1.getComponentUuid(), measure1.getProjectUuid(), measure1.getMetricUuid(), measure1.getValue(), measure1.getDataAsString()),
  103. tuple(measure2.getComponentUuid(), measure2.getProjectUuid(), measure2.getMetricUuid(), measure2.getValue(), measure2.getDataAsString()));
  104. assertThat(underTest.selectByComponentUuidsAndMetricKeys(db.getSession(), emptyList(), singletonList(metric.getKey()))).isEmpty();
  105. assertThat(underTest.selectByComponentUuidsAndMetricKeys(db.getSession(), singletonList(measure1.getComponentUuid()), emptyList())).isEmpty();
  106. }
  107. @Test
  108. public void selectByComponentUuidsAndMetricKeys_returns_empty_list_if_metric_does_not_match() {
  109. LiveMeasureDto measure = newLiveMeasure().setMetricUuid(metric.getUuid());
  110. underTest.insert(db.getSession(), measure);
  111. List<LiveMeasureDto> selected = underTest.selectByComponentUuidsAndMetricKeys(db.getSession(), singletonList(measure.getComponentUuid()), singletonList("_other_"));
  112. assertThat(selected).isEmpty();
  113. }
  114. @Test
  115. public void selectByComponentUuidsAndMetricKeys_returns_empty_list_if_component_does_not_match() {
  116. LiveMeasureDto measure = newLiveMeasure().setMetricUuid(metric.getUuid());
  117. underTest.insert(db.getSession(), measure);
  118. List<LiveMeasureDto> selected = underTest.selectByComponentUuidsAndMetricKeys(db.getSession(), singletonList("_missing_"), singletonList(metric.getKey()));
  119. assertThat(selected).isEmpty();
  120. }
  121. @Test
  122. public void selectForProjectsByMetricUuids() {
  123. MetricDto metric = db.measures().insertMetric();
  124. MetricDto metric2 = db.measures().insertMetric();
  125. ComponentDto project = db.components().insertPrivateProject();
  126. ComponentDto project2 = db.components().insertPrivateProject();
  127. underTest.insert(db.getSession(), newLiveMeasure(project, metric).setValue(3.14).setData((String) null));
  128. underTest.insert(db.getSession(), newLiveMeasure(project, metric2).setValue(4.54).setData((String) null));
  129. underTest.insert(db.getSession(), newLiveMeasure(project2, metric).setValue(99.99).setData((String) null));
  130. List<LiveMeasureDto> selected = underTest.selectForProjectsByMetricUuids(db.getSession(), List.of(metric.getUuid(), metric2.getUuid()));
  131. assertThat(selected)
  132. .extracting(LiveMeasureDto::getComponentUuid, LiveMeasureDto::getProjectUuid, LiveMeasureDto::getMetricUuid, LiveMeasureDto::getValue, LiveMeasureDto::getDataAsString)
  133. .containsExactlyInAnyOrder(
  134. tuple(project.uuid(), project.uuid(), metric.getUuid(), 3.14, null),
  135. tuple(project.uuid(), project.uuid(), metric2.getUuid(), 4.54, null),
  136. tuple(project2.uuid(), project2.uuid(), metric.getUuid(), 99.99, null));
  137. }
  138. @Test
  139. public void selectForProjectsByMetricUuids_whenMetricDoesNotMatch_shouldReturnEmptyList() {
  140. ComponentDto project = db.components().insertPrivateProject();
  141. underTest.insert(db.getSession(), newLiveMeasure(project, metric).setValue(3.14).setData((String) null));
  142. List<LiveMeasureDto> selected = underTest.selectForProjectsByMetricUuids(db.getSession(), singletonList("_other_"));
  143. assertThat(selected).isEmpty();
  144. }
  145. @Test
  146. public void selectForProjectsByMetricUuids_shouldReturnProjectWithTRKQualifierOnly() {
  147. MetricDto metric = db.measures().insertMetric();
  148. ComponentDto application = db.components().insertPrivateApplication();
  149. ComponentDto project = db.components().insertPrivateProject();
  150. ComponentDto project2 = db.components().insertPrivateProject();
  151. db.components().addApplicationProject(application, project, project2);
  152. underTest.insert(db.getSession(), newLiveMeasure(application, metric).setValue(3.14).setData((String) null));
  153. underTest.insert(db.getSession(), newLiveMeasure(project, metric).setValue(4.54).setData((String) null));
  154. underTest.insert(db.getSession(), newLiveMeasure(project2, metric).setValue(5.56).setData((String) null));
  155. List<LiveMeasureDto> selected = underTest.selectForProjectsByMetricUuids(db.getSession(), List.of(metric.getUuid()));
  156. assertThat(selected)
  157. .extracting(LiveMeasureDto::getProjectUuid)
  158. .containsExactlyInAnyOrder(project.uuid(), project2.uuid());
  159. }
  160. @Test
  161. public void selectByComponentUuidAndMetricKey() {
  162. LiveMeasureDto measure = newLiveMeasure().setMetricUuid(metric.getUuid());
  163. underTest.insert(db.getSession(), measure);
  164. Optional<LiveMeasureDto> selected = underTest.selectMeasure(db.getSession(), measure.getComponentUuid(), metric.getKey());
  165. assertThat(selected).isNotEmpty();
  166. assertThat(selected.get()).isEqualToComparingFieldByField(measure);
  167. }
  168. @Test
  169. public void selectByComponentUuidAndMetricKey_return_empty_if_component_does_not_match() {
  170. LiveMeasureDto measure = newLiveMeasure().setMetricUuid(metric.getUuid());
  171. underTest.insert(db.getSession(), measure);
  172. assertThat(underTest.selectMeasure(db.getSession(), "_missing_", metric.getKey())).isEmpty();
  173. }
  174. @Test
  175. public void selectByComponentUuidAndMetricKey_return_empty_if_metric_does_not_match() {
  176. LiveMeasureDto measure = newLiveMeasure().setMetricUuid(metric.getUuid());
  177. underTest.insert(db.getSession(), measure);
  178. assertThat(underTest.selectMeasure(db.getSession(), measure.getComponentUuid(), "_missing_")).isEmpty();
  179. }
  180. @Test
  181. public void selectByComponentUuidAndMetricKeys() {
  182. MetricDto metric2 = db.measures().insertMetric();
  183. LiveMeasureDto measure1 = newLiveMeasure().setMetricUuid(metric.getUuid()).setValue(1.0).setComponentUuid("uuid");
  184. LiveMeasureDto measure2 = newLiveMeasure().setMetricUuid(metric2.getUuid()).setValue(2.0).setComponentUuid("uuid");
  185. underTest.insert(db.getSession(), measure1);
  186. underTest.insert(db.getSession(), measure2);
  187. List<LiveMeasureDto> selected = underTest.selectByComponentUuidAndMetricKeys(db.getSession(), "uuid", asList(metric.getKey(), metric2.getKey()));
  188. assertThat(selected).hasSize(2);
  189. assertThat(selected).extracting(LiveMeasureDto::getMetricUuid, LiveMeasureDto::getValue)
  190. .containsExactlyInAnyOrder(tuple(metric.getUuid(), measure1.getValue()), tuple(metric2.getUuid(), measure2.getValue()));
  191. }
  192. @Test
  193. public void selectByComponentUuidAndMetricKeys_return_empty_if_component_does_not_match() {
  194. LiveMeasureDto measure = newLiveMeasure().setMetricUuid(metric.getUuid());
  195. underTest.insert(db.getSession(), measure);
  196. assertThat(underTest.selectByComponentUuidAndMetricKeys(db.getSession(), "_missing_", singletonList(metric.getKey()))).isEmpty();
  197. }
  198. @Test
  199. public void selectByComponentUuidAndMetricKeys_return_empty_if_no_metric_matches() {
  200. LiveMeasureDto measure = newLiveMeasure().setMetricUuid(metric.getUuid());
  201. underTest.insert(db.getSession(), measure);
  202. assertThat(underTest.selectByComponentUuidAndMetricKeys(db.getSession(), measure.getComponentUuid(), singletonList("_missing_"))).isEmpty();
  203. }
  204. @Test
  205. public void selectMeasure() {
  206. MetricDto metric = db.measures().insertMetric();
  207. LiveMeasureDto stored = newLiveMeasure().setMetricUuid(metric.getUuid());
  208. underTest.insert(db.getSession(), stored);
  209. // metric exists but not component
  210. assertThat(underTest.selectMeasure(db.getSession(), "_missing_", metric.getKey())).isEmpty();
  211. // component exists but not metric
  212. assertThat(underTest.selectMeasure(db.getSession(), stored.getComponentUuid(), "_missing_")).isEmpty();
  213. // component and metric don't match
  214. assertThat(underTest.selectMeasure(db.getSession(), "_missing_", "_missing_")).isEmpty();
  215. // matches
  216. assertThat(underTest.selectMeasure(db.getSession(), stored.getComponentUuid(), metric.getKey()).get())
  217. .isEqualToComparingFieldByField(stored);
  218. }
  219. @Test
  220. public void selectTreeByQuery() {
  221. List<LiveMeasureDto> results = new ArrayList<>();
  222. MetricDto metric = db.measures().insertMetric();
  223. ComponentDto project = db.components().insertPrivateProject();
  224. ComponentDto file = db.components().insertComponent(newFileDto(project));
  225. underTest.insert(db.getSession(), newLiveMeasure(file, metric).setValue(3.14));
  226. underTest.selectTreeByQuery(db.getSession(), project,
  227. MeasureTreeQuery.builder()
  228. .setMetricUuids(singleton(metric.getUuid()))
  229. .setStrategy(MeasureTreeQuery.Strategy.LEAVES).build(),
  230. context -> results.add(context.getResultObject()));
  231. assertThat(results).hasSize(1);
  232. LiveMeasureDto result = results.get(0);
  233. assertThat(result.getComponentUuid()).isEqualTo(file.uuid());
  234. assertThat(result.getMetricUuid()).isEqualTo(metric.getUuid());
  235. assertThat(result.getValue()).isEqualTo(3.14);
  236. }
  237. @Test
  238. public void scrollSelectByComponentUuidAndMetricKeys_for_non_empty_metric_set() {
  239. List<LiveMeasureDto> results = new ArrayList<>();
  240. MetricDto metric = db.measures().insertMetric();
  241. MetricDto metric2 = db.measures().insertMetric();
  242. ComponentDto project = db.components().insertPrivateProject();
  243. ComponentDto project2 = db.components().insertPrivateProject();
  244. underTest.insert(db.getSession(), newLiveMeasure(project, metric).setValue(3.14));
  245. underTest.insert(db.getSession(), newLiveMeasure(project, metric2).setValue(4.54));
  246. underTest.insert(db.getSession(), newLiveMeasure(project2, metric).setValue(99.99));
  247. underTest.scrollSelectByComponentUuidAndMetricKeys(db.getSession(), project.uuid(), Sets.newSet(metric.getKey(), metric2.getKey()),
  248. context -> results.add(context.getResultObject()));
  249. assertThat(results).hasSize(2);
  250. LiveMeasureDto result = results.stream().filter(lm -> lm.getMetricUuid().equals(metric.getUuid())).findFirst().get();
  251. assertThat(result.getComponentUuid()).isEqualTo(project.uuid());
  252. assertThat(result.getMetricUuid()).isEqualTo(metric.getUuid());
  253. assertThat(result.getValue()).isEqualTo(3.14);
  254. LiveMeasureDto result2 = results.stream().filter(lm -> lm.getMetricUuid().equals(metric2.getUuid())).findFirst().get();
  255. assertThat(result2.getComponentUuid()).isEqualTo(project.uuid());
  256. assertThat(result2.getMetricUuid()).isEqualTo(metric2.getUuid());
  257. assertThat(result2.getValue()).isEqualTo(4.54);
  258. }
  259. @Test
  260. public void scrollSelectByComponentUuidAndMetricKeys_for_empty_metric_set() {
  261. List<LiveMeasureDto> results = new ArrayList<>();
  262. ComponentDto project = db.components().insertPrivateProject();
  263. underTest.scrollSelectByComponentUuidAndMetricKeys(db.getSession(), project.uuid(), Sets.newSet(),
  264. context -> results.add(context.getResultObject()));
  265. assertThat(results).isEmpty();
  266. }
  267. @Test
  268. public void selectTreeByQuery_with_empty_results() {
  269. List<LiveMeasureDto> results = new ArrayList<>();
  270. underTest.selectTreeByQuery(db.getSession(), newPrivateProjectDto(),
  271. MeasureTreeQuery.builder().setStrategy(MeasureTreeQuery.Strategy.LEAVES).build(),
  272. context -> results.add(context.getResultObject()));
  273. assertThat(results).isEmpty();
  274. }
  275. @Test
  276. public void selectMeasure_map_fields() {
  277. MetricDto metric = db.measures().insertMetric();
  278. ComponentDto project = db.components().insertPrivateProject();
  279. ComponentDto file = db.components().insertComponent(newFileDto(project));
  280. underTest.insert(db.getSession(), newLiveMeasure(file, metric).setValue(3.14).setData("text_value"));
  281. LiveMeasureDto result = underTest.selectMeasure(db.getSession(), file.uuid(), metric.getKey()).orElseThrow(() -> new IllegalArgumentException("Measure not found"));
  282. assertThat(result).as("Fail to map fields of %s", result.toString()).extracting(
  283. LiveMeasureDto::getProjectUuid, LiveMeasureDto::getComponentUuid, LiveMeasureDto::getMetricUuid, LiveMeasureDto::getValue,
  284. LiveMeasureDto::getDataAsString, LiveMeasureDto::getTextValue)
  285. .contains(project.uuid(), file.uuid(), metric.getUuid(), 3.14, "text_value", "text_value");
  286. }
  287. @Test
  288. public void countNcloc() {
  289. MetricDto ncloc = db.measures().insertMetric(m -> m.setKey("ncloc").setValueType(INT.toString()));
  290. MetricDto lines = db.measures().insertMetric(m -> m.setKey("lines").setValueType(INT.toString()));
  291. ComponentDto simpleProject = db.components().insertPublicProject();
  292. db.measures().insertLiveMeasure(simpleProject, ncloc, m -> m.setValue(10d));
  293. ComponentDto projectWithBiggerBranch = db.components().insertPublicProject();
  294. ComponentDto bigBranch = db.components().insertProjectBranch(projectWithBiggerBranch, b -> b.setBranchType(BranchType.BRANCH));
  295. db.measures().insertLiveMeasure(projectWithBiggerBranch, ncloc, m -> m.setValue(100d));
  296. db.measures().insertLiveMeasure(bigBranch, ncloc, m -> m.setValue(200d));
  297. ComponentDto projectWithLinesButNoLoc = db.components().insertPublicProject();
  298. db.measures().insertLiveMeasure(projectWithLinesButNoLoc, lines, m -> m.setValue(365d));
  299. db.measures().insertLiveMeasure(projectWithLinesButNoLoc, ncloc, m -> m.setValue(0d));
  300. assertThat(underTest.sumNclocOfBiggestBranchForProject(db.getSession(), simpleProject.uuid())).isEqualTo(10L);
  301. assertThat(underTest.sumNclocOfBiggestBranchForProject(db.getSession(), projectWithBiggerBranch.uuid())).isEqualTo(200L);
  302. assertThat(underTest.sumNclocOfBiggestBranchForProject(db.getSession(), projectWithLinesButNoLoc.uuid())).isZero();
  303. }
  304. @Test
  305. public void get_branch_with_max_ncloc_per_project() {
  306. Map<String, MetricDto> metrics = setupMetrics();
  307. setupProjectsWithLoc(metrics.get("ncloc"), metrics.get("ncloc_language_distribution"), metrics.get("lines"));
  308. List<LargestBranchNclocDto> results = underTest.getLargestBranchNclocPerProject(db.getSession());
  309. assertThat(results).hasSize(5);
  310. assertLocForProject(results.get(0), "projectWithTieOnBranchSize", DEFAULT_MAIN_BRANCH_NAME, 250);
  311. assertLocForProject(results.get(1), "projectWithTieOnOtherBranches", "tieBranch1", 230);
  312. assertLocForProject(results.get(2), "projectWithBranchBiggerThanMaster", "notMasterBranch", 200);
  313. assertLocForProject(results.get(3), "simpleProject", DEFAULT_MAIN_BRANCH_NAME, 10);
  314. assertLocForProject(results.get(4), "projectWithLinesButNoLoc", DEFAULT_MAIN_BRANCH_NAME, 0);
  315. }
  316. @Test
  317. public void get_loc_language_distribution() {
  318. Map<String, MetricDto> metrics = setupMetrics();
  319. MetricDto ncloc = metrics.get("ncloc");
  320. MetricDto nclocLanguageDistribution = metrics.get("ncloc_language_distribution");
  321. Map<String, ComponentDto> components = setupProjectsWithLoc(ncloc, nclocLanguageDistribution, metrics.get("lines"));
  322. List<ProjectLocDistributionDto> results = underTest.selectLargestBranchesLocDistribution(db.getSession(), ncloc.getUuid(), nclocLanguageDistribution.getUuid());
  323. assertThat(results)
  324. .containsExactlyInAnyOrder(
  325. new ProjectLocDistributionDto(components.get("projectWithTieOnBranchSize").uuid(), components.get("projectWithTieOnBranchSize").uuid(), "java=250;js=0"),
  326. new ProjectLocDistributionDto(components.get("projectWithTieOnOtherBranches").uuid(), components.get("tieBranch1").uuid(), "java=230;js=0"),
  327. new ProjectLocDistributionDto(components.get("projectWithBranchBiggerThanMaster").uuid(), components.get("notMasterBranch").uuid(), "java=100;js=100"),
  328. new ProjectLocDistributionDto(components.get("simpleProject").uuid(), components.get("simpleProject").uuid(), "java=10;js=0"),
  329. new ProjectLocDistributionDto(components.get("projectWithLinesButNoLoc").uuid(), components.get("projectWithLinesButNoLoc").uuid(), "java=0;js=0"));
  330. }
  331. @Test
  332. public void countNcloc_empty() {
  333. db.measures().insertMetric(m -> m.setKey("ncloc").setValueType(INT.toString()));
  334. db.measures().insertMetric(m -> m.setKey("lines").setValueType(INT.toString()));
  335. long result = underTest.sumNclocOfBiggestBranchForProject(db.getSession(), "non-existing-project-uuid");
  336. assertThat(result).isZero();
  337. }
  338. @Test
  339. public void insert_data() {
  340. byte[] data = "text_value".getBytes(StandardCharsets.UTF_8);
  341. MetricDto metric = db.measures().insertMetric();
  342. ComponentDto project = db.components().insertPrivateProject();
  343. ComponentDto file = db.components().insertComponent(newFileDto(project));
  344. LiveMeasureDto measure = newLiveMeasure(file, metric).setData(data);
  345. underTest.insert(db.getSession(), measure);
  346. LiveMeasureDto result = underTest.selectMeasure(db.getSession(), file.uuid(), metric.getKey()).orElseThrow(() -> new IllegalArgumentException("Measure not found"));
  347. assertThat(new String(result.getData(), StandardCharsets.UTF_8)).isEqualTo("text_value");
  348. assertThat(result.getDataAsString()).isEqualTo("text_value");
  349. }
  350. @Test
  351. public void insertOrUpdate() {
  352. // insert
  353. LiveMeasureDto dto = newLiveMeasure();
  354. underTest.insertOrUpdate(db.getSession(), dto);
  355. verifyPersisted(dto);
  356. verifyTableSize(1);
  357. // update
  358. dto.setValue(dto.getValue() + 1);
  359. dto.setData(dto.getDataAsString() + "_new");
  360. underTest.insertOrUpdate(db.getSession(), dto);
  361. verifyPersisted(dto);
  362. verifyTableSize(1);
  363. }
  364. @Test
  365. public void deleteByComponentUuidExcludingMetricUuids() {
  366. LiveMeasureDto measure1 = newLiveMeasure().setComponentUuid("C1").setMetricUuid("1");
  367. LiveMeasureDto measure2 = newLiveMeasure().setComponentUuid("C1").setMetricUuid("2");
  368. LiveMeasureDto measure3 = newLiveMeasure().setComponentUuid("C1").setMetricUuid("3");
  369. LiveMeasureDto measureOtherComponent = newLiveMeasure().setComponentUuid("C2").setMetricUuid("3");
  370. underTest.insertOrUpdate(db.getSession(), measure1);
  371. underTest.insertOrUpdate(db.getSession(), measure2);
  372. underTest.insertOrUpdate(db.getSession(), measure3);
  373. underTest.insertOrUpdate(db.getSession(), measureOtherComponent);
  374. underTest.deleteByComponentUuidExcludingMetricUuids(db.getSession(), "C1", Arrays.asList("1", "2"));
  375. verifyTableSize(3);
  376. verifyPersisted(measure1);
  377. verifyPersisted(measure2);
  378. verifyPersisted(measureOtherComponent);
  379. }
  380. @Test
  381. public void deleteByComponentUuid() {
  382. LiveMeasureDto measure1 = newLiveMeasure().setComponentUuid("C1").setMetricUuid("1");
  383. LiveMeasureDto measure2 = newLiveMeasure().setComponentUuid("C1").setMetricUuid("2");
  384. LiveMeasureDto measure3 = newLiveMeasure().setComponentUuid("C1").setMetricUuid("3");
  385. LiveMeasureDto measureOtherComponent = newLiveMeasure().setComponentUuid("C2").setMetricUuid("3");
  386. underTest.insertOrUpdate(db.getSession(), measure1);
  387. underTest.insertOrUpdate(db.getSession(), measure2);
  388. underTest.insertOrUpdate(db.getSession(), measure3);
  389. underTest.insertOrUpdate(db.getSession(), measureOtherComponent);
  390. underTest.deleteByComponent(db.getSession(), "C1");
  391. verifyTableSize(1);
  392. verifyPersisted(measureOtherComponent);
  393. }
  394. @Test
  395. public void deleteByComponentUuidExcludingMetricUuids_with_empty_metrics() {
  396. LiveMeasureDto measure1 = newLiveMeasure().setComponentUuid("C1").setMetricUuid("1");
  397. LiveMeasureDto measure2 = newLiveMeasure().setComponentUuid("C1").setMetricUuid("2");
  398. LiveMeasureDto measureOnOtherComponent = newLiveMeasure().setComponentUuid("C2").setMetricUuid("2");
  399. underTest.insertOrUpdate(db.getSession(), measure1);
  400. underTest.insertOrUpdate(db.getSession(), measure2);
  401. underTest.insertOrUpdate(db.getSession(), measureOnOtherComponent);
  402. underTest.deleteByComponentUuidExcludingMetricUuids(db.getSession(), "C1", Collections.emptyList());
  403. verifyTableSize(1);
  404. verifyPersisted(measureOnOtherComponent);
  405. }
  406. @Test
  407. public void countProjectsHavingMeasure() {
  408. MetricDto metric1 = db.measures().insertMetric();
  409. MetricDto metric2 = db.measures().insertMetric();
  410. ComponentDto project1 = db.components().insertPrivateProject();
  411. ComponentDto project2 = db.components().insertPrivateProject();
  412. db.measures().insertLiveMeasure(project1, metric1);
  413. db.measures().insertLiveMeasure(project2, metric1);
  414. db.measures().insertLiveMeasure(project1, metric2);
  415. assertThat(underTest.countProjectsHavingMeasure(db.getSession(), metric1.getKey())).isEqualTo(2);
  416. assertThat(underTest.countProjectsHavingMeasure(db.getSession(), metric2.getKey())).isOne();
  417. assertThat(underTest.countProjectsHavingMeasure(db.getSession(), "unknown")).isZero();
  418. }
  419. @Test
  420. public void upsert_inserts_or_updates_row() {
  421. if (!db.getDbClient().getDatabase().getDialect().supportsUpsert()) {
  422. return;
  423. }
  424. // insert
  425. LiveMeasureDto dto = newLiveMeasure();
  426. int count = underTest.upsert(db.getSession(), dto);
  427. verifyPersisted(dto);
  428. verifyTableSize(1);
  429. assertThat(count).isOne();
  430. // update
  431. dto.setValue(dto.getValue() + 1);
  432. dto.setData(dto.getDataAsString() + "_new");
  433. count = underTest.upsert(db.getSession(), dto);
  434. assertThat(count).isOne();
  435. verifyPersisted(dto);
  436. verifyTableSize(1);
  437. }
  438. @Test
  439. public void upsert_does_not_update_row_if_values_are_not_changed() {
  440. if (!db.getDbClient().getDatabase().getDialect().supportsUpsert()) {
  441. return;
  442. }
  443. LiveMeasureDto dto = newLiveMeasure();
  444. underTest.upsert(db.getSession(), dto);
  445. // update
  446. int count = underTest.upsert(db.getSession(), dto);
  447. assertThat(count).isZero();
  448. verifyPersisted(dto);
  449. verifyTableSize(1);
  450. }
  451. @Test
  452. public void upsert_updates_row_if_lob_data_is_changed() {
  453. if (!db.getDbClient().getDatabase().getDialect().supportsUpsert()) {
  454. return;
  455. }
  456. LiveMeasureDto dto = newLiveMeasure().setData(RandomStringUtils.random(10_000));
  457. underTest.upsert(db.getSession(), dto);
  458. // update
  459. dto.setData(RandomStringUtils.random(dto.getDataAsString().length() + 10));
  460. int count = underTest.upsert(db.getSession(), dto);
  461. assertThat(count).isOne();
  462. verifyPersisted(dto);
  463. verifyTableSize(1);
  464. }
  465. @Test
  466. public void upsert_does_not_update_row_if_lob_data_is_not_changed() {
  467. if (!db.getDbClient().getDatabase().getDialect().supportsUpsert()) {
  468. return;
  469. }
  470. LiveMeasureDto dto = newLiveMeasure().setData(RandomStringUtils.random(10_000));
  471. underTest.upsert(db.getSession(), dto);
  472. // update
  473. int count = underTest.upsert(db.getSession(), dto);
  474. assertThat(count).isZero();
  475. verifyPersisted(dto);
  476. verifyTableSize(1);
  477. }
  478. @Test
  479. public void upsert_updates_row_if_lob_data_is_removed() {
  480. if (!db.getDbClient().getDatabase().getDialect().supportsUpsert()) {
  481. return;
  482. }
  483. LiveMeasureDto dto = newLiveMeasure().setData(RandomStringUtils.random(10_000));
  484. underTest.upsert(db.getSession(), dto);
  485. // update
  486. dto.setData((String) null);
  487. int count = underTest.upsert(db.getSession(), dto);
  488. assertThat(count).isOne();
  489. verifyPersisted(dto);
  490. verifyTableSize(1);
  491. }
  492. @Test
  493. public void upsert_updates_row_if_value_is_changed() {
  494. if (!db.getDbClient().getDatabase().getDialect().supportsUpsert()) {
  495. return;
  496. }
  497. LiveMeasureDto dto = newLiveMeasure().setValue(40.0);
  498. underTest.upsert(db.getSession(), dto);
  499. // update
  500. dto.setValue(50.0);
  501. int count = underTest.upsert(db.getSession(), dto);
  502. assertThat(count).isOne();
  503. verifyPersisted(dto);
  504. verifyTableSize(1);
  505. }
  506. @Test
  507. public void upsert_updates_row_if_value_is_removed() {
  508. if (!db.getDbClient().getDatabase().getDialect().supportsUpsert()) {
  509. return;
  510. }
  511. LiveMeasureDto dto = newLiveMeasure().setValue(40.0);
  512. underTest.upsert(db.getSession(), dto);
  513. // update
  514. dto.setValue(null);
  515. int count = underTest.upsert(db.getSession(), dto);
  516. assertThat(count).isOne();
  517. verifyPersisted(dto);
  518. verifyTableSize(1);
  519. }
  520. @Test
  521. public void upsert_updates_row_if_value_is_added() {
  522. if (!db.getDbClient().getDatabase().getDialect().supportsUpsert()) {
  523. return;
  524. }
  525. LiveMeasureDto dto = newLiveMeasure().setValue(null);
  526. underTest.upsert(db.getSession(), dto);
  527. // update
  528. dto.setValue(40.0);
  529. int count = underTest.upsert(db.getSession(), dto);
  530. assertThat(count).isOne();
  531. verifyPersisted(dto);
  532. verifyTableSize(1);
  533. }
  534. @Test
  535. public void upsert_multiple_rows() {
  536. if (!db.getDbClient().getDatabase().getDialect().supportsUpsert()) {
  537. return;
  538. }
  539. // insert 30
  540. List<LiveMeasureDto> inserted = new ArrayList<>();
  541. IntStream.range(0, 30).forEach(i -> inserted.add(newLiveMeasure()));
  542. for (LiveMeasureDto dto : inserted) {
  543. underTest.upsert(db.getSession(), dto);
  544. }
  545. verifyTableSize(30);
  546. // update 10 with new values, update 5 without any change and insert new 50
  547. List<LiveMeasureDto> upserted = new ArrayList<>();
  548. IntStream.range(0, 10).forEach(i -> {
  549. LiveMeasureDto d = inserted.get(i);
  550. upserted.add(d.setValue(d.getValue() + 123));
  551. });
  552. upserted.addAll(inserted.subList(10, 15));
  553. IntStream.range(0, 50).forEach(i -> upserted.add(newLiveMeasure()));
  554. for (LiveMeasureDto dto : upserted) {
  555. underTest.upsert(db.getSession(), dto);
  556. }
  557. db.getSession().commit();
  558. verifyTableSize(80);
  559. }
  560. private void verifyTableSize(int expectedSize) {
  561. assertThat(db.countRowsOfTable(db.getSession(), "live_measures")).isEqualTo(expectedSize);
  562. }
  563. private void verifyPersisted(LiveMeasureDto dto) {
  564. List<LiveMeasureDto> selected = underTest.selectByComponentUuidsAndMetricUuids(db.getSession(), singletonList(dto.getComponentUuid()), singletonList(dto.getMetricUuid()));
  565. assertThat(selected).hasSize(1);
  566. assertThat(selected.get(0)).isEqualToComparingOnlyGivenFields(dto,
  567. // do not compare the field "uuid", which is used only for insert, not select
  568. "componentUuid", "projectUuid", "metricUuid", "value", "textValue", "data");
  569. }
  570. private Map<String, MetricDto> setupMetrics() {
  571. MetricDto ncloc = db.measures().insertMetric(m -> m.setKey("ncloc").setValueType(INT.toString()));
  572. MetricDto nclocDistribution = db.measures().insertMetric(m -> m.setKey("ncloc_language_distribution").setValueType(DATA.toString()));
  573. MetricDto lines = db.measures().insertMetric(m -> m.setKey("lines").setValueType(INT.toString()));
  574. return Map.of("ncloc", ncloc,
  575. "ncloc_language_distribution", nclocDistribution,
  576. "lines", lines);
  577. }
  578. private Map<String, ComponentDto> setupProjectsWithLoc(MetricDto ncloc, MetricDto nclocDistribution, MetricDto lines) {
  579. ComponentDto simpleProject = addProjectWithMeasure("simpleProject", ncloc, 10d);
  580. addMeasureToComponent(simpleProject, nclocDistribution, "java=10;js=0");
  581. ComponentDto projectWithBranchBiggerThanMaster = addProjectWithMeasure("projectWithBranchBiggerThanMaster", ncloc, 100d);
  582. addMeasureToComponent(projectWithBranchBiggerThanMaster, nclocDistribution, "java=100;js=0");
  583. ComponentDto notMasterBranch = addBranchToProjectWithMeasure(projectWithBranchBiggerThanMaster, "notMasterBranch", ncloc, 200d);
  584. addMeasureToComponent(notMasterBranch, nclocDistribution, "java=100;js=100");
  585. ComponentDto projectWithLinesButNoLoc = addProjectWithMeasure("projectWithLinesButNoLoc", lines, 365d);
  586. addMeasureToComponent(projectWithLinesButNoLoc, nclocDistribution, "java=0;js=0");
  587. addMeasureToComponent(projectWithLinesButNoLoc, ncloc, 0d, false);
  588. ComponentDto projectWithTieOnBranchSize = addProjectWithMeasure("projectWithTieOnBranchSize", ncloc, 250d);
  589. addMeasureToComponent(projectWithTieOnBranchSize, nclocDistribution, "java=250;js=0");
  590. ComponentDto tieBranch = addBranchToProjectWithMeasure(projectWithTieOnBranchSize, "tieBranch", ncloc, 250d);
  591. addMeasureToComponent(tieBranch, nclocDistribution, "java=250;js=0");
  592. ComponentDto projectWithTieOnOtherBranches = addProjectWithMeasure("projectWithTieOnOtherBranches", ncloc, 220d);
  593. addMeasureToComponent(projectWithTieOnOtherBranches, nclocDistribution, "java=220;js=0");
  594. ComponentDto tieBranch1 = addBranchToProjectWithMeasure(projectWithTieOnOtherBranches, "tieBranch1", ncloc, 230d);
  595. addMeasureToComponent(tieBranch1, nclocDistribution, "java=230;js=0");
  596. ComponentDto tieBranch2 = addBranchToProjectWithMeasure(projectWithTieOnOtherBranches, "tieBranch2", ncloc, 230d);
  597. addMeasureToComponent(tieBranch2, nclocDistribution, "java=230;js=0");
  598. return Map.of("simpleProject", simpleProject,
  599. "projectWithBranchBiggerThanMaster", projectWithBranchBiggerThanMaster,
  600. "notMasterBranch", notMasterBranch,
  601. "projectWithLinesButNoLoc", projectWithLinesButNoLoc,
  602. "projectWithTieOnBranchSize", projectWithTieOnBranchSize,
  603. "tieBranch", tieBranch,
  604. "projectWithTieOnOtherBranches", projectWithTieOnOtherBranches,
  605. "tieBranch1", tieBranch1,
  606. "tieBranch2", tieBranch2);
  607. }
  608. private ComponentDto addProjectWithMeasure(String projectKey, MetricDto metric, double metricValue) {
  609. ComponentDto project = db.components().insertPublicProject(p -> p.setKey(projectKey));
  610. addMeasureToComponent(project, metric, metricValue, true);
  611. return project;
  612. }
  613. private void addMeasureToComponent(ComponentDto component, MetricDto metric, double metricValue, boolean addSnapshot) {
  614. db.measures().insertLiveMeasure(component, metric, m -> m.setValue(metricValue));
  615. if (addSnapshot) {
  616. db.components().insertSnapshot(component, t -> t.setLast(true));
  617. }
  618. }
  619. private void addMeasureToComponent(ComponentDto component, MetricDto metric, String metricValue) {
  620. db.measures().insertLiveMeasure(component, metric, m -> m.setData(metricValue));
  621. }
  622. private ComponentDto addBranchToProjectWithMeasure(ComponentDto project, String branchKey, MetricDto metric, double metricValue) {
  623. ComponentDto branch = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.BRANCH).setKey(branchKey));
  624. addMeasureToComponent(branch, metric, metricValue, true);
  625. return branch;
  626. }
  627. private void assertLocForProject(LargestBranchNclocDto result, String projectKey, String branchKey, long linesOfCode) {
  628. assertThat(result.getProjectKey()).isEqualTo(projectKey);
  629. assertThat(result.getBranchName()).isEqualTo(branchKey);
  630. assertThat(result.getLoc()).isEqualTo(linesOfCode);
  631. }
  632. }