您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

ProjectDaoTest.java 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  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.project;
  21. import java.util.ArrayList;
  22. import java.util.Arrays;
  23. import java.util.Collection;
  24. import java.util.Collections;
  25. import java.util.HashSet;
  26. import java.util.List;
  27. import java.util.Optional;
  28. import java.util.Set;
  29. import java.util.function.Consumer;
  30. import java.util.stream.Collectors;
  31. import java.util.stream.IntStream;
  32. import javax.annotation.Nullable;
  33. import org.assertj.core.api.Assertions;
  34. import org.assertj.core.groups.Tuple;
  35. import org.junit.Rule;
  36. import org.junit.Test;
  37. import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
  38. import org.sonar.api.resources.Qualifiers;
  39. import org.sonar.api.utils.System2;
  40. import org.sonar.db.DbTester;
  41. import org.sonar.db.audit.AuditPersister;
  42. import org.sonar.db.audit.NoOpAuditPersister;
  43. import org.sonar.db.component.ComponentDto;
  44. import org.sonar.db.measure.LiveMeasureDto;
  45. import org.sonar.db.metric.MetricDto;
  46. import org.sonar.db.qualityprofile.QProfileDto;
  47. import static org.apache.commons.lang.math.RandomUtils.nextInt;
  48. import static org.assertj.core.api.Assertions.assertThat;
  49. import static org.assertj.core.api.Assertions.tuple;
  50. import static org.mockito.ArgumentMatchers.any;
  51. import static org.mockito.Mockito.mock;
  52. import static org.mockito.Mockito.times;
  53. import static org.mockito.Mockito.verify;
  54. import static org.mockito.Mockito.verifyNoInteractions;
  55. import static org.sonar.api.measures.CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION_KEY;
  56. import static org.sonar.api.measures.Metric.ValueType.STRING;
  57. public class ProjectDaoTest {
  58. private final System2 system2 = new AlwaysIncreasingSystem2(1000L);
  59. @Rule
  60. public DbTester db = DbTester.create(system2);
  61. private final AuditPersister auditPersister = mock(AuditPersister.class);
  62. private final ProjectDao projectDao = new ProjectDao(system2, new NoOpAuditPersister());
  63. private final ProjectDao projectDaoWithAuditPersister = new ProjectDao(system2, auditPersister);
  64. @Test
  65. public void should_insert_and_select_by_uuid() {
  66. ProjectDto dto = createProject("o1", "p1");
  67. projectDao.insert(db.getSession(), dto);
  68. Optional<ProjectDto> projectByUuid = projectDao.selectByUuid(db.getSession(), "uuid_o1_p1");
  69. assertThat(projectByUuid).isPresent();
  70. assertProject(projectByUuid.get(), "projectName_p1", "projectKee_o1_p1", "uuid_o1_p1", "desc_p1", "tag1,tag2", false);
  71. assertThat(projectByUuid.get().isPrivate()).isFalse();
  72. }
  73. @Test
  74. public void select_project_by_key() {
  75. ProjectDto dto = createProject("o1", "p1");
  76. projectDao.insert(db.getSession(), dto);
  77. Optional<ProjectDto> projectByKee = projectDao.selectProjectByKey(db.getSession(), "projectKee_o1_p1");
  78. assertThat(projectByKee).isPresent();
  79. assertProject(projectByKee.get(), "projectName_p1", "projectKee_o1_p1", "uuid_o1_p1", "desc_p1", "tag1,tag2", false);
  80. }
  81. @Test
  82. public void select_projects() {
  83. ProjectDto dto1 = createProject("o1", "p1");
  84. ProjectDto dto2 = createProject("o1", "p2");
  85. projectDao.insert(db.getSession(), dto1);
  86. projectDao.insert(db.getSession(), dto2);
  87. List<ProjectDto> projects = projectDao.selectProjects(db.getSession());
  88. assertThat(projects).extracting(ProjectDto::getKey).containsExactlyInAnyOrder("projectKee_o1_p1", "projectKee_o1_p2");
  89. }
  90. @Test
  91. public void select_all() {
  92. ProjectDto dto1 = createProject("o1", "p1");
  93. ProjectDto dto2 = createProject("o1", "p2");
  94. ProjectDto dto3 = createProject("o2", "p1");
  95. projectDao.insert(db.getSession(), dto1);
  96. projectDao.insert(db.getSession(), dto2);
  97. projectDao.insert(db.getSession(), dto3);
  98. List<ProjectDto> projectsByOrg = projectDao.selectAll(db.getSession());
  99. assertThat(projectsByOrg)
  100. .extracting(ProjectDto::getName, ProjectDto::getKey, ProjectDto::getUuid, ProjectDto::getDescription,
  101. ProjectDto::getTagsString, ProjectDto::isPrivate)
  102. .containsExactlyInAnyOrder(
  103. tuple("projectName_p1", "projectKee_o1_p1", "uuid_o1_p1", "desc_p1", "tag1,tag2", false),
  104. tuple("projectName_p2", "projectKee_o1_p2", "uuid_o1_p2", "desc_p2", "tag1,tag2", false),
  105. tuple("projectName_p1", "projectKee_o2_p1", "uuid_o2_p1", "desc_p1", "tag1,tag2", false));
  106. }
  107. @Test
  108. public void select_applications_by_keys() {
  109. var applications = new ArrayList<ProjectDto>();
  110. for (int i = 0; i < 1500; i++) {
  111. ProjectDto project = db.components().insertPrivateProjectDto();
  112. ProjectDto app = db.components().insertPrivateApplicationDto();
  113. db.components().addApplicationProject(app, project);
  114. applications.add(i, app);
  115. }
  116. Set<String> applicationsId = new HashSet<>();
  117. List<Tuple> applicationsData = applications
  118. .stream()
  119. .map(x -> {
  120. applicationsId.add(x.getKey());
  121. return tuple(x.getKey(), x.getName(), x.getUuid(), x.getDescription(), x.isPrivate());
  122. })
  123. .collect(Collectors.toList());
  124. List<ProjectDto> selectedApplications = projectDao.selectApplicationsByKeys(db.getSession(), applicationsId);
  125. assertThat(selectedApplications)
  126. .extracting(ProjectDto::getKey, ProjectDto::getName, ProjectDto::getUuid, ProjectDto::getDescription, ProjectDto::isPrivate)
  127. .containsExactlyInAnyOrderElementsOf(applicationsData);
  128. }
  129. @Test
  130. public void update_tags() {
  131. ProjectDto dto1 = createProject("o1", "p1").setTagsString("");
  132. ProjectDto dto2 = createProject("o1", "p2").setTagsString("tag1,tag2");
  133. projectDao.insert(db.getSession(), dto1);
  134. projectDao.insert(db.getSession(), dto2);
  135. List<ProjectDto> projectsByUuids = projectDao.selectByUuids(db.getSession(), new HashSet<>(Arrays.asList("uuid_o1_p1", "uuid_o1_p2")));
  136. assertThat(projectsByUuids).hasSize(2);
  137. assertProject(projectsByUuids.get(0), "projectName_p1", "projectKee_o1_p1", "uuid_o1_p1", "desc_p1", null, false);
  138. assertProject(projectsByUuids.get(1), "projectName_p2", "projectKee_o1_p2", "uuid_o1_p2", "desc_p2", "tag1,tag2", false);
  139. dto1.setTags(Collections.singletonList("tag3"));
  140. dto2.setTagsString("");
  141. projectDao.updateTags(db.getSession(), dto1);
  142. projectDao.updateTags(db.getSession(), dto2);
  143. projectsByUuids = projectDao.selectByUuids(db.getSession(), new HashSet<>(Arrays.asList("uuid_o1_p1", "uuid_o1_p2")));
  144. assertThat(projectsByUuids).hasSize(2);
  145. assertProject(projectsByUuids.get(0), "projectName_p1", "projectKee_o1_p1", "uuid_o1_p1", "desc_p1", "tag3", false);
  146. assertProject(projectsByUuids.get(1), "projectName_p2", "projectKee_o1_p2", "uuid_o1_p2", "desc_p2", null, false);
  147. assertThat(projectsByUuids.get(0).getTags()).containsOnly("tag3");
  148. }
  149. @Test
  150. public void update_visibility() {
  151. ProjectDto dto1 = createProject("o1", "p1").setPrivate(true);
  152. ProjectDto dto2 = createProject("o1", "p2");
  153. projectDao.insert(db.getSession(), dto1);
  154. projectDao.insert(db.getSession(), dto2);
  155. List<ProjectDto> projectsByUuids = projectDao.selectByUuids(db.getSession(), new HashSet<>(Arrays.asList("uuid_o1_p1", "uuid_o1_p2")));
  156. assertThat(projectsByUuids).hasSize(2);
  157. assertProject(projectsByUuids.get(0), "projectName_p1", "projectKee_o1_p1", "uuid_o1_p1", "desc_p1", "tag1,tag2", true);
  158. assertProject(projectsByUuids.get(1), "projectName_p2", "projectKee_o1_p2", "uuid_o1_p2", "desc_p2", "tag1,tag2", false);
  159. projectDao.updateVisibility(db.getSession(), dto1.getUuid(), false);
  160. projectDao.updateVisibility(db.getSession(), dto2.getUuid(), true);
  161. projectsByUuids = projectDao.selectByUuids(db.getSession(), new HashSet<>(Arrays.asList("uuid_o1_p1", "uuid_o1_p2")));
  162. assertThat(projectsByUuids).hasSize(2);
  163. assertProject(projectsByUuids.get(0), "projectName_p1", "projectKee_o1_p1", "uuid_o1_p1", "desc_p1", "tag1,tag2", false);
  164. assertProject(projectsByUuids.get(1), "projectName_p2", "projectKee_o1_p2", "uuid_o1_p2", "desc_p2", "tag1,tag2", true);
  165. }
  166. @Test
  167. public void select_by_uuids() {
  168. ProjectDto dto1 = createProject("o1", "p1");
  169. ProjectDto dto2 = createProject("o1", "p2");
  170. ProjectDto dto3 = createProject("o1", "p3");
  171. projectDao.insert(db.getSession(), dto1);
  172. projectDao.insert(db.getSession(), dto2);
  173. projectDao.insert(db.getSession(), dto3);
  174. List<ProjectDto> projectsByUuids = projectDao.selectByUuids(db.getSession(), new HashSet<>(Arrays.asList("uuid_o1_p1", "uuid_o1_p2")));
  175. assertThat(projectsByUuids).hasSize(2);
  176. assertProject(projectsByUuids.get(0), "projectName_p1", "projectKee_o1_p1", "uuid_o1_p1", "desc_p1", "tag1,tag2", false);
  177. assertProject(projectsByUuids.get(1), "projectName_p2", "projectKee_o1_p2", "uuid_o1_p2", "desc_p2", "tag1,tag2", false);
  178. }
  179. @Test
  180. public void select_by_uuids_over_1000() {
  181. IntStream.range(0, 1005).mapToObj(value -> createProject("o1", "p" + value))
  182. .forEach(projectDto -> projectDao.insert(db.getSession(), projectDto));
  183. var projectUuids = projectDao.selectAll(db.getSession()).stream().map(ProjectDto::getUuid).collect(Collectors.toSet());
  184. List<ProjectDto> projectsByUuids = projectDao.selectByUuids(db.getSession(), projectUuids);
  185. assertThat(projectsByUuids).hasSize(1005);
  186. }
  187. @Test
  188. public void select_empty_by_uuids() {
  189. ProjectDto dto1 = createProject("o1", "p1");
  190. ProjectDto dto2 = createProject("o1", "p2");
  191. ProjectDto dto3 = createProject("o1", "p3");
  192. projectDao.insert(db.getSession(), dto1);
  193. projectDao.insert(db.getSession(), dto2);
  194. projectDao.insert(db.getSession(), dto3);
  195. List<ProjectDto> projectsByUuids = projectDao.selectByUuids(db.getSession(), Collections.emptySet());
  196. assertThat(projectsByUuids).isEmpty();
  197. }
  198. @Test
  199. public void insert_withoutTrack_shouldNotCallAuditPersister() {
  200. ProjectDto dto1 = createProject("o1", "p1");
  201. projectDaoWithAuditPersister.insert(db.getSession(), dto1, false);
  202. verifyNoInteractions(auditPersister);
  203. }
  204. @Test
  205. public void insert_withTrack_shouldCallAuditPersister() {
  206. ProjectDto dto1 = createProject("o1", "p1");
  207. projectDaoWithAuditPersister.insert(db.getSession(), dto1, true);
  208. verify(auditPersister, times(1)).addComponent(any(), any());
  209. }
  210. @Test
  211. public void update_shouldCallAuditPersister() {
  212. ProjectDto dto1 = createProject("o1", "p1");
  213. projectDaoWithAuditPersister.update(db.getSession(), dto1);
  214. verify(auditPersister, times(1)).updateComponent(any(), any());
  215. }
  216. @Test
  217. public void select_project_uuids_associated_to_default_quality_profile_for_specific_language() {
  218. String language = "xoo";
  219. Set<ComponentDto> projects = insertProjects(nextInt(10));
  220. insertDefaultQualityProfile(language);
  221. insertProjectsLiveMeasures(language, projects);
  222. Set<String> projectUuids = projectDao.selectProjectUuidsAssociatedToDefaultQualityProfileByLanguage(db.getSession(), language);
  223. assertThat(projectUuids)
  224. .containsExactlyInAnyOrderElementsOf(extractComponentUuids(projects));
  225. }
  226. @Test
  227. public void update_ncloc_should_update_project() {
  228. ComponentDto project = db.components().insertPublicProject();
  229. projectDao.updateNcloc(db.getSession(), project.uuid(), 10L);
  230. Assertions.assertThat(projectDao.getNclocSum(db.getSession())).isEqualTo(10L);
  231. }
  232. @Test
  233. public void getNcloc_sum_compute_correctly_sum_of_projects() {
  234. projectDao.updateNcloc(db.getSession(), db.components().insertPublicProject().uuid(), 1L);
  235. projectDao.updateNcloc(db.getSession(), db.components().insertPublicProject().uuid(), 20L);
  236. projectDao.updateNcloc(db.getSession(), db.components().insertPublicProject().uuid(), 100L);
  237. Assertions.assertThat(projectDao.getNclocSum(db.getSession())).isEqualTo(121L);
  238. }
  239. @Test
  240. public void getNcloc_sum_compute_correctly_sum_of_projects_while_excluding_project() {
  241. projectDao.updateNcloc(db.getSession(), db.components().insertPublicProject().uuid(), 1L);
  242. projectDao.updateNcloc(db.getSession(), db.components().insertPublicProject().uuid(), 20L);
  243. ComponentDto project3 = db.components().insertPublicProject();
  244. projectDao.updateNcloc(db.getSession(), project3.uuid(), 100L);
  245. Assertions.assertThat(projectDao.getNclocSum(db.getSession(), project3.uuid())).isEqualTo(21L);
  246. }
  247. @Test
  248. public void selectAllProjectUuids_shouldOnlyReturnProjectWithTRKQualifier() {
  249. ComponentDto application = db.components().insertPrivateApplication();
  250. ComponentDto project = db.components().insertPrivateProject();
  251. ComponentDto project2 = db.components().insertPrivateProject();
  252. db.components().addApplicationProject(application, project, project2);
  253. List<String> projectUuids = projectDao.selectAllProjectUuids(db.getSession());
  254. assertThat(projectUuids).containsExactlyInAnyOrder(project.uuid(), project2.uuid());
  255. }
  256. private void insertDefaultQualityProfile(String language) {
  257. QProfileDto profile = db.qualityProfiles().insert(qp -> qp.setIsBuiltIn(true).setLanguage(language));
  258. db.qualityProfiles().setAsDefault(profile);
  259. }
  260. private static Set<String> extractComponentUuids(Collection<ComponentDto> components) {
  261. return components
  262. .stream()
  263. .map(ComponentDto::uuid)
  264. .collect(Collectors.toSet());
  265. }
  266. private Set<ComponentDto> insertProjects(int number) {
  267. return IntStream
  268. .rangeClosed(0, number)
  269. .mapToObj(x -> db.components().insertPrivateProject())
  270. .collect(Collectors.toSet());
  271. }
  272. private Consumer<LiveMeasureDto> configureLiveMeasure(String language, MetricDto metric, ComponentDto project) {
  273. return liveMeasure -> liveMeasure
  274. .setMetricUuid(metric.getUuid())
  275. .setComponentUuid(project.uuid())
  276. .setProjectUuid(project.uuid())
  277. .setData(language + "=" + nextInt(10));
  278. }
  279. private Consumer<ComponentDto> insertLiveMeasure(String language, MetricDto metric) {
  280. return project -> db.measures().insertLiveMeasure(project, metric, configureLiveMeasure(language, metric, project));
  281. }
  282. private void insertProjectsLiveMeasures(String language, Set<ComponentDto> projects) {
  283. Consumer<MetricDto> configureMetric = metric -> metric
  284. .setValueType(STRING.name())
  285. .setKey(NCLOC_LANGUAGE_DISTRIBUTION_KEY);
  286. MetricDto metric = db.measures().insertMetric(configureMetric);
  287. projects
  288. .forEach(insertLiveMeasure(language, metric));
  289. }
  290. private void assertProject(ProjectDto dto, String name, String kee, String uuid, String desc, @Nullable String tags, boolean isPrivate) {
  291. assertThat(dto).extracting("name", "kee", "key", "uuid", "description", "tagsString", "private")
  292. .containsExactly(name, kee, kee, uuid, desc, tags, isPrivate);
  293. }
  294. private ProjectDto createProject(String org, String name) {
  295. return new ProjectDto()
  296. .setName("projectName_" + name)
  297. .setKey("projectKee_" + org + "_" + name)
  298. .setQualifier(Qualifiers.PROJECT)
  299. .setUuid("uuid_" + org + "_" + name)
  300. .setTags(Arrays.asList("tag1", "tag2"))
  301. .setDescription("desc_" + name)
  302. .setPrivate(false);
  303. }
  304. }