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.

PurgeCommandsTest.java 36KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2020 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.purge;
  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.List;
  26. import java.util.Random;
  27. import java.util.function.Consumer;
  28. import java.util.stream.IntStream;
  29. import java.util.stream.Stream;
  30. import org.junit.After;
  31. import org.junit.Rule;
  32. import org.junit.Test;
  33. import org.junit.runner.RunWith;
  34. import org.sonar.api.impl.utils.AlwaysIncreasingSystem2;
  35. import org.sonar.api.utils.System2;
  36. import org.sonar.core.util.UuidFactoryFast;
  37. import org.sonar.db.DbTester;
  38. import org.sonar.db.ce.CeTaskMessageType;
  39. import org.sonar.db.component.BranchDto;
  40. import org.sonar.db.component.ComponentDto;
  41. import org.sonar.db.component.ComponentTesting;
  42. import org.sonar.db.component.SnapshotDto;
  43. import org.sonar.db.dialect.Dialect;
  44. import org.sonar.db.duplication.DuplicationUnitDto;
  45. import org.sonar.db.issue.IssueDto;
  46. import org.sonar.db.metric.MetricDto;
  47. import org.sonar.db.newcodeperiod.NewCodePeriodType;
  48. import org.sonar.db.organization.OrganizationDto;
  49. import org.sonar.db.organization.OrganizationTesting;
  50. import org.sonar.db.permission.OrganizationPermission;
  51. import org.sonar.db.project.ProjectDto;
  52. import org.sonar.db.rule.RuleDefinitionDto;
  53. import org.sonar.db.user.GroupDto;
  54. import org.sonar.db.user.UserDto;
  55. import static com.google.common.collect.Lists.newArrayList;
  56. import static java.util.Arrays.asList;
  57. import static java.util.Collections.singletonList;
  58. import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
  59. import static org.assertj.core.api.Assertions.assertThat;
  60. import static org.sonar.db.component.ComponentTesting.newBranchDto;
  61. import static org.sonar.db.component.ComponentTesting.newFileDto;
  62. import static org.sonar.db.component.ComponentTesting.newProjectCopy;
  63. import static org.sonar.db.component.SnapshotDto.STATUS_PROCESSED;
  64. import static org.sonar.db.component.SnapshotDto.STATUS_UNPROCESSED;
  65. @RunWith(DataProviderRunner.class)
  66. public class PurgeCommandsTest {
  67. @Rule
  68. public DbTester dbTester = DbTester.create(System2.INSTANCE);
  69. private AlwaysIncreasingSystem2 system2 = new AlwaysIncreasingSystem2();
  70. private PurgeProfiler profiler = new PurgeProfiler();
  71. private Random random = new Random();
  72. private PurgeCommands underTest = new PurgeCommands(dbTester.getSession(), profiler, system2);
  73. /**
  74. * Required because there is no autogenerated keys for analysis_properties
  75. */
  76. @After
  77. public void resetAnalysisProperties() {
  78. dbTester.executeUpdateSql("DELETE FROM analysis_properties");
  79. }
  80. /**
  81. * Test that SQL queries execution do not fail with a huge number of parameter
  82. */
  83. @Test
  84. public void should_not_fail_when_deleting_huge_number_of_analyses() {
  85. new PurgeCommands(dbTester.getSession(), profiler, system2).deleteAnalyses(getHugeNumberOfUuids());
  86. // The goal of this test is only to check that the query do no fail, not to check result
  87. }
  88. @Test
  89. public void purgeAnalyses_deletes_duplications() {
  90. ComponentDto project = dbTester.components().insertPrivateProject();
  91. SnapshotDto analysis1 = dbTester.components().insertSnapshot(project);
  92. SnapshotDto analysis2 = dbTester.components().insertSnapshot(project);
  93. SnapshotDto analysis3 = dbTester.components().insertSnapshot(project);
  94. SnapshotDto analysis4 = dbTester.components().insertSnapshot(project);
  95. int count = 8;
  96. for (SnapshotDto analysis : asList(analysis1, analysis2, analysis3, analysis4)) {
  97. IntStream.range(0, count).forEach(i -> insertDuplication(project, analysis));
  98. }
  99. underTest.purgeAnalyses(singletonList(analysis1.getUuid()));
  100. assertThat(countDuplications(analysis1)).isZero();
  101. assertThat(countDuplications(analysis2)).isEqualTo(count);
  102. assertThat(countDuplications(analysis3)).isEqualTo(count);
  103. assertThat(countDuplications(analysis4)).isEqualTo(count);
  104. underTest.purgeAnalyses(asList(analysis1.getUuid(), analysis3.getUuid(), analysis4.getUuid()));
  105. assertThat(countDuplications(analysis1)).isZero();
  106. assertThat(countDuplications(analysis2)).isEqualTo(count);
  107. assertThat(countDuplications(analysis3)).isZero();
  108. assertThat(countDuplications(analysis4)).isZero();
  109. }
  110. /**
  111. * Test that SQL queries execution do not fail with a huge number of parameter
  112. */
  113. @Test
  114. public void purgeAnalyses_should_not_fail_when_purging_huge_number_of_analyses() {
  115. new PurgeCommands(dbTester.getSession(), profiler, system2).purgeAnalyses(getHugeNumberOfUuids());
  116. // The goal of this test is only to check that the query do no fail, not to check result
  117. }
  118. @Test
  119. @UseDataProvider("projects")
  120. public void deleteComponents_delete_tree_of_components_of_a_project(OrganizationDto organizationDto, ComponentDto project) {
  121. dbTester.organizations().insert(organizationDto);
  122. dbTester.components().insertComponent(project);
  123. ComponentDto otherProject = dbTester.components().insertPrivateProject(organizationDto);
  124. Stream.of(project, otherProject).forEach(prj -> {
  125. ComponentDto module = dbTester.components().insertComponent(ComponentTesting.newModuleDto(prj));
  126. ComponentDto directory1 = dbTester.components().insertComponent(ComponentTesting.newDirectory(module, "a"));
  127. ComponentDto directory2 = dbTester.components().insertComponent(ComponentTesting.newDirectory(prj, "b"));
  128. dbTester.components().insertComponent(newFileDto(prj));
  129. dbTester.components().insertComponent(newFileDto(module));
  130. dbTester.components().insertComponent(newFileDto(directory1));
  131. dbTester.components().insertComponent(newFileDto(directory2));
  132. });
  133. underTest.deleteComponents(project.uuid());
  134. assertThat(countComponentOfRoot(project)).isZero();
  135. assertThat(countComponentOfRoot(otherProject)).isEqualTo(8);
  136. }
  137. @Test
  138. @UseDataProvider("projects")
  139. public void deleteComponentsByMainBranchProjectUuid_deletes_all_branches_of_a_project(OrganizationDto organizationDto, ComponentDto project) {
  140. dbTester.organizations().insert(organizationDto);
  141. dbTester.components().insertComponent(project);
  142. ComponentDto branch = dbTester.components().insertProjectBranch(project);
  143. Stream.of(project, branch).forEach(prj -> {
  144. ComponentDto module = dbTester.components().insertComponent(ComponentTesting.newModuleDto(prj));
  145. ComponentDto directory1 = dbTester.components().insertComponent(ComponentTesting.newDirectory(module, "a"));
  146. ComponentDto directory2 = dbTester.components().insertComponent(ComponentTesting.newDirectory(prj, "b"));
  147. dbTester.components().insertComponent(newFileDto(prj));
  148. dbTester.components().insertComponent(newFileDto(module));
  149. dbTester.components().insertComponent(newFileDto(directory1));
  150. dbTester.components().insertComponent(newFileDto(directory2));
  151. });
  152. underTest.deleteComponentsByMainBranchProjectUuid(project.uuid());
  153. assertThat(countComponentOfRoot(project)).isEqualTo(8);
  154. assertThat(countComponentOfRoot(branch)).isZero();
  155. }
  156. @Test
  157. @UseDataProvider("views")
  158. public void deleteComponents_delete_tree_of_components_of_a_view(OrganizationDto organizationDto, ComponentDto view) {
  159. dbTester.organizations().insert(organizationDto);
  160. dbTester.components().insertComponent(view);
  161. ComponentDto otherView = dbTester.components().insertPrivatePortfolio(organizationDto);
  162. Stream.of(view, otherView).forEach(vw -> {
  163. dbTester.components().insertSubView(vw);
  164. dbTester.components().insertComponent(newProjectCopy(dbTester.components().insertPrivateProject(), vw));
  165. dbTester.components().insertComponent(newProjectCopy(dbTester.components().insertPrivateProject(), vw));
  166. });
  167. underTest.deleteComponents(view.uuid());
  168. assertThat(countComponentOfRoot(view)).isZero();
  169. assertThat(countComponentOfRoot(otherView)).isEqualTo(4);
  170. }
  171. @Test
  172. public void deleteComponents_does_not_delete_child_tables() {
  173. ComponentDto component = dbTester.components().insertPrivateProject();
  174. ComponentDto file = dbTester.components().insertComponent(newFileDto(component));
  175. SnapshotDto analysis = dbTester.components().insertSnapshot(component);
  176. dbTester.events().insertEvent(analysis);
  177. IssueDto issue = dbTester.issues().insert(dbTester.rules().insert(), component, file);
  178. dbTester.issues().insertChange(issue);
  179. underTest.deleteComponents(component.uuid());
  180. assertThat(dbTester.countRowsOfTable("components")).isZero();
  181. assertThat(dbTester.countRowsOfTable("snapshots")).isEqualTo(1);
  182. assertThat(dbTester.countRowsOfTable("events")).isEqualTo(1);
  183. assertThat(dbTester.countRowsOfTable("issues")).isEqualTo(1);
  184. assertThat(dbTester.countRowsOfTable("issue_changes")).isEqualTo(1);
  185. }
  186. @Test
  187. public void deleteProjects() {
  188. ComponentDto project = dbTester.components().insertPrivateProject();
  189. ProjectDto projectDto = dbTester.getDbClient().projectDao().selectProjectByKey(dbTester.getSession(), project.getDbKey()).get();
  190. ComponentDto file = dbTester.components().insertComponent(newFileDto(project));
  191. SnapshotDto analysis = dbTester.components().insertSnapshot(project);
  192. dbTester.events().insertEvent(analysis);
  193. IssueDto issue = dbTester.issues().insert(dbTester.rules().insert(), project, file);
  194. dbTester.issues().insertChange(issue);
  195. assertThat(dbTester.countRowsOfTable("projects")).isOne();
  196. underTest.deleteComponents(project.uuid());
  197. underTest.deleteProject(project.uuid());
  198. assertThat(dbTester.countRowsOfTable("projects")).isZero();
  199. assertThat(dbTester.countRowsOfTable("components")).isZero();
  200. assertThat(dbTester.countRowsOfTable("snapshots")).isEqualTo(1);
  201. assertThat(dbTester.countRowsOfTable("events")).isEqualTo(1);
  202. assertThat(dbTester.countRowsOfTable("issues")).isEqualTo(1);
  203. assertThat(dbTester.countRowsOfTable("issue_changes")).isEqualTo(1);
  204. }
  205. @Test
  206. @UseDataProvider("projectsAndViews")
  207. public void deleteAnalyses_by_rootUuid_all_analyses_of_specified_root_uuid(ComponentDto projectOrView) {
  208. dbTester.components().insertComponent(projectOrView);
  209. ComponentDto otherProject = dbTester.components().insertPrivateProject();
  210. Stream.of(projectOrView, otherProject).forEach(p -> {
  211. dbTester.components().insertSnapshot(p, t -> t.setLast(false));
  212. dbTester.components().insertSnapshot(p, t -> t.setLast(true));
  213. dbTester.components().insertSnapshot(p, t -> t.setLast(false).setStatus(STATUS_UNPROCESSED));
  214. dbTester.components().insertSnapshot(p, t -> t.setLast(false).setStatus(STATUS_PROCESSED));
  215. });
  216. underTest.deleteAnalyses(projectOrView.uuid());
  217. assertThat(countAnalysesOfRoot(projectOrView)).isZero();
  218. assertThat(countAnalysesOfRoot(otherProject)).isEqualTo(4);
  219. }
  220. @Test
  221. @UseDataProvider("projectsAndViews")
  222. public void deleteAnalyses_by_rootUuid_deletes_event_component_changes(ComponentDto projectOrView) {
  223. dbTester.components().insertComponent(projectOrView);
  224. ComponentDto otherProject = dbTester.components().insertPrivateProject();
  225. int count = 5;
  226. IntStream.range(0, count).forEach(i -> {
  227. insertRandomEventComponentChange(projectOrView);
  228. insertRandomEventComponentChange(otherProject);
  229. });
  230. underTest.deleteAnalyses(projectOrView.uuid());
  231. assertThat(countEventComponentChangesOf(projectOrView)).isZero();
  232. assertThat(countEventComponentChangesOf(otherProject)).isEqualTo(count);
  233. }
  234. @Test
  235. @UseDataProvider("projectsAndViews")
  236. public void deleteAnalyses_by_rootUuid_deletes_events(ComponentDto projectOrView) {
  237. dbTester.components().insertComponent(projectOrView);
  238. SnapshotDto analysis1 = dbTester.components().insertSnapshot(projectOrView);
  239. SnapshotDto analysis2 = dbTester.components().insertSnapshot(projectOrView);
  240. ComponentDto otherProject = dbTester.components().insertPrivateProject();
  241. SnapshotDto otherAnalysis1 = dbTester.components().insertSnapshot(otherProject);
  242. SnapshotDto otherAnalysis2 = dbTester.components().insertSnapshot(otherProject);
  243. int count = 7;
  244. IntStream.range(0, count).forEach(i -> {
  245. dbTester.events().insertEvent(analysis1);
  246. dbTester.events().insertEvent(analysis2);
  247. dbTester.events().insertEvent(otherAnalysis1);
  248. dbTester.events().insertEvent(otherAnalysis2);
  249. });
  250. underTest.deleteAnalyses(projectOrView.uuid());
  251. assertThat(countEventsOf(analysis1)).isZero();
  252. assertThat(countEventsOf(analysis2)).isZero();
  253. assertThat(countEventsOf(otherAnalysis1)).isEqualTo(count);
  254. assertThat(countEventsOf(otherAnalysis2)).isEqualTo(count);
  255. }
  256. @Test
  257. @UseDataProvider("projectsAndViews")
  258. public void deleteAnalyses_by_rootUuid_deletes_measures(ComponentDto projectOrView) {
  259. MetricDto metric1 = dbTester.measures().insertMetric();
  260. MetricDto metric2 = dbTester.measures().insertMetric();
  261. dbTester.components().insertComponent(projectOrView);
  262. SnapshotDto analysis1 = dbTester.components().insertSnapshot(projectOrView);
  263. SnapshotDto analysis2 = dbTester.components().insertSnapshot(projectOrView);
  264. ComponentDto otherProject = dbTester.components().insertPrivateProject();
  265. SnapshotDto otherAnalysis1 = dbTester.components().insertSnapshot(otherProject);
  266. SnapshotDto otherAnalysis2 = dbTester.components().insertSnapshot(otherProject);
  267. int count = 5;
  268. Stream.of(metric1, metric2)
  269. .forEach(metric -> {
  270. IntStream.range(0, count).forEach(i -> {
  271. dbTester.measures().insertMeasure(projectOrView, analysis1, metric);
  272. dbTester.measures().insertMeasure(projectOrView, analysis2, metric);
  273. dbTester.measures().insertMeasure(otherProject, otherAnalysis1, metric);
  274. dbTester.measures().insertMeasure(otherProject, otherAnalysis2, metric);
  275. });
  276. });
  277. underTest.deleteAnalyses(projectOrView.uuid());
  278. assertThat(countMeasuresOf(analysis1)).isZero();
  279. assertThat(countMeasuresOf(analysis2)).isZero();
  280. assertThat(countMeasuresOf(otherAnalysis1)).isEqualTo(count * 2);
  281. assertThat(countMeasuresOf(otherAnalysis2)).isEqualTo(count * 2);
  282. }
  283. @Test
  284. @UseDataProvider("projectsAndViews")
  285. public void deleteAnalyses_by_rootUuid_deletes_analysis_properties(ComponentDto projectOrView) {
  286. dbTester.components().insertComponent(projectOrView);
  287. SnapshotDto analysis1 = dbTester.components().insertSnapshot(projectOrView);
  288. SnapshotDto analysis2 = dbTester.components().insertSnapshot(projectOrView);
  289. ComponentDto otherProject = dbTester.components().insertPrivateProject();
  290. SnapshotDto otherAnalysis1 = dbTester.components().insertSnapshot(otherProject);
  291. SnapshotDto otherAnalysis2 = dbTester.components().insertSnapshot(otherProject);
  292. int count = 5;
  293. IntStream.range(0, count).forEach(i -> {
  294. insertRandomAnalysisProperty(analysis1);
  295. insertRandomAnalysisProperty(analysis2);
  296. insertRandomAnalysisProperty(otherAnalysis1);
  297. insertRandomAnalysisProperty(otherAnalysis2);
  298. });
  299. underTest.deleteAnalyses(projectOrView.uuid());
  300. assertThat(countAnalysisPropertiesOf(analysis1)).isZero();
  301. assertThat(countAnalysisPropertiesOf(analysis2)).isZero();
  302. assertThat(countAnalysisPropertiesOf(otherAnalysis1)).isEqualTo(count);
  303. assertThat(countAnalysisPropertiesOf(otherAnalysis2)).isEqualTo(count);
  304. }
  305. @Test
  306. @UseDataProvider("projectsAndViews")
  307. public void deleteAbortedAnalyses_deletes_only_analyse_with_unprocessed_status(ComponentDto projectOrView) {
  308. dbTester.components().insertComponent(projectOrView);
  309. ComponentDto otherProject = dbTester.components().insertPrivateProject();
  310. Stream.of(projectOrView, otherProject)
  311. .forEach(p -> {
  312. dbTester.components().insertSnapshot(p, t -> t.setStatus(STATUS_PROCESSED).setLast(false));
  313. dbTester.components().insertSnapshot(p, t -> t.setStatus(STATUS_PROCESSED).setLast(true));
  314. dbTester.components().insertSnapshot(p, t -> t.setStatus(STATUS_UNPROCESSED).setLast(false));
  315. // unrealistic case but the last analysis is never deleted even if unprocessed
  316. dbTester.components().insertSnapshot(p, t -> t.setStatus(STATUS_UNPROCESSED).setLast(true));
  317. });
  318. underTest.deleteAbortedAnalyses(projectOrView.uuid());
  319. assertThat(countAnalysesOfRoot(projectOrView, STATUS_UNPROCESSED, true)).isEqualTo(1);
  320. assertThat(countAnalysesOfRoot(projectOrView, STATUS_UNPROCESSED, false)).isZero();
  321. assertThat(countAnalysesOfRoot(projectOrView, STATUS_PROCESSED, true)).isEqualTo(1);
  322. assertThat(countAnalysesOfRoot(projectOrView, STATUS_PROCESSED, false)).isEqualTo(1);
  323. assertThat(countAnalysesOfRoot(otherProject, STATUS_UNPROCESSED, true)).isEqualTo(1);
  324. assertThat(countAnalysesOfRoot(otherProject, STATUS_UNPROCESSED, false)).isEqualTo(1);
  325. assertThat(countAnalysesOfRoot(otherProject, STATUS_PROCESSED, true)).isEqualTo(1);
  326. assertThat(countAnalysesOfRoot(otherProject, STATUS_PROCESSED, false)).isEqualTo(1);
  327. }
  328. @Test
  329. @UseDataProvider("projectsAndViews")
  330. public void deleteAnalyses_by_analyses_deletes_specified_analysis(ComponentDto projectOrView) {
  331. dbTester.components().insertComponent(projectOrView);
  332. SnapshotDto analysis1 = dbTester.components().insertSnapshot(projectOrView, s -> s.setStatus(STATUS_PROCESSED));
  333. SnapshotDto analysis2 = dbTester.components().insertSnapshot(projectOrView, s -> s.setStatus(STATUS_PROCESSED));
  334. SnapshotDto analysis3 = dbTester.components().insertSnapshot(projectOrView, s -> s.setStatus(STATUS_UNPROCESSED));
  335. SnapshotDto analysis4 = dbTester.components().insertSnapshot(projectOrView, s -> s.setStatus(STATUS_UNPROCESSED));
  336. underTest.deleteAnalyses(singletonList(analysis1.getUuid()));
  337. assertThat(uuidsOfAnalysesOfRoot(projectOrView))
  338. .containsOnly(analysis2.getUuid(), analysis3.getUuid(), analysis4.getUuid());
  339. underTest.deleteAnalyses(asList(analysis2.getUuid(), analysis3.getUuid()));
  340. assertThat(uuidsOfAnalysesOfRoot(projectOrView))
  341. .containsOnly(analysis4.getUuid());
  342. underTest.deleteAnalyses(asList(analysis1.getUuid(), analysis2.getUuid(), analysis3.getUuid(), analysis4.getUuid()));
  343. assertThat(uuidsOfAnalysesOfRoot(projectOrView)).isEmpty();
  344. }
  345. private Stream<String> uuidsOfAnalysesOfRoot(ComponentDto rootComponent) {
  346. return dbTester.select("select uuid as \"UUID\" from snapshots where component_uuid='" + rootComponent.uuid() + "'")
  347. .stream()
  348. .map(t -> (String) t.get("UUID"));
  349. }
  350. @Test
  351. @UseDataProvider("projectsAndViews")
  352. public void deleteAnalyses_by_analyses_deletes_event_component_changes(ComponentDto projectOrView) {
  353. dbTester.components().insertComponent(projectOrView);
  354. SnapshotDto analysis = dbTester.components().insertSnapshot(projectOrView, randomLastAndStatus());
  355. SnapshotDto otherAnalysis = dbTester.components().insertSnapshot(projectOrView);
  356. int count = 5;
  357. IntStream.range(0, count).forEach(i -> {
  358. insertRandomEventComponentChange(analysis);
  359. insertRandomEventComponentChange(otherAnalysis);
  360. });
  361. underTest.deleteAnalyses(singletonList(analysis.getUuid()));
  362. assertThat(countEventComponentChangesOf(analysis)).isZero();
  363. assertThat(countEventComponentChangesOf(otherAnalysis)).isEqualTo(count);
  364. }
  365. @Test
  366. @UseDataProvider("projectsAndViews")
  367. public void deleteAnalyses_by_analyses_deletes_events(ComponentDto projectOrView) {
  368. dbTester.components().insertComponent(projectOrView);
  369. SnapshotDto analysis = dbTester.components().insertSnapshot(projectOrView, randomLastAndStatus());
  370. SnapshotDto otherAnalysis = dbTester.components().insertSnapshot(projectOrView);
  371. int count = 5;
  372. IntStream.range(0, count).forEach(i -> {
  373. dbTester.events().insertEvent(analysis);
  374. dbTester.events().insertEvent(otherAnalysis);
  375. });
  376. underTest.deleteAnalyses(singletonList(analysis.getUuid()));
  377. assertThat(countEventsOf(analysis)).isZero();
  378. assertThat(countEventsOf(otherAnalysis)).isEqualTo(count);
  379. }
  380. @Test
  381. @UseDataProvider("projectsAndViews")
  382. public void deleteAnalyses_by_analyses_deletes_measures(ComponentDto projectOrView) {
  383. MetricDto metric1 = dbTester.measures().insertMetric();
  384. MetricDto metric2 = dbTester.measures().insertMetric();
  385. dbTester.components().insertComponent(projectOrView);
  386. SnapshotDto analysis = dbTester.components().insertSnapshot(projectOrView, randomLastAndStatus());
  387. SnapshotDto otherAnalysis = dbTester.components().insertSnapshot(projectOrView);
  388. int count = 5;
  389. Stream.of(metric1, metric2)
  390. .forEach(metric -> {
  391. IntStream.range(0, count).forEach(i -> {
  392. dbTester.measures().insertMeasure(projectOrView, analysis, metric);
  393. dbTester.measures().insertMeasure(projectOrView, otherAnalysis, metric);
  394. });
  395. });
  396. underTest.deleteAnalyses(singletonList(analysis.getUuid()));
  397. assertThat(countMeasuresOf(analysis)).isZero();
  398. assertThat(countMeasuresOf(otherAnalysis)).isEqualTo(count * 2);
  399. }
  400. @Test
  401. @UseDataProvider("projectsAndViews")
  402. public void deleteAnalyses_by_analyses_deletes_analysis_properties(ComponentDto projectOrView) {
  403. dbTester.components().insertComponent(projectOrView);
  404. SnapshotDto analysis = dbTester.components().insertSnapshot(projectOrView, randomLastAndStatus());
  405. SnapshotDto otherAnalysis = dbTester.components().insertSnapshot(projectOrView);
  406. int count = 4;
  407. IntStream.range(0, count).forEach(i -> {
  408. insertRandomAnalysisProperty(analysis);
  409. insertRandomAnalysisProperty(otherAnalysis);
  410. });
  411. underTest.deleteAnalyses(singletonList(analysis.getUuid()));
  412. assertThat(countAnalysisPropertiesOf(analysis)).isZero();
  413. assertThat(countAnalysisPropertiesOf(otherAnalysis)).isEqualTo(count);
  414. }
  415. @Test
  416. @UseDataProvider("projectsAndViews")
  417. public void deleteIssues_deletes_all_issues_of_specified_root_component(ComponentDto projectOrView) {
  418. RuleDefinitionDto rule1 = dbTester.rules().insert();
  419. RuleDefinitionDto rule2 = dbTester.rules().insert();
  420. dbTester.components().insertComponent(projectOrView);
  421. ComponentDto file = dbTester.components().insertComponent(newFileDto(projectOrView));
  422. ComponentDto otherProject = dbTester.components().insertPrivateProject();
  423. ComponentDto otherFile = dbTester.components().insertComponent(newFileDto(otherProject));
  424. int count = 5;
  425. IntStream.range(0, count).forEach(i -> {
  426. Stream.of(rule1, rule2).forEach(rule -> {
  427. dbTester.issues().insertIssue(t -> t.setRule(rule).setProject(projectOrView).setComponent(projectOrView));
  428. dbTester.issues().insertIssue(t -> t.setRule(rule).setProject(projectOrView).setComponent(file));
  429. dbTester.issues().insertIssue(t -> t.setRule(rule).setProject(otherProject).setComponent(otherProject));
  430. dbTester.issues().insertIssue(t -> t.setRule(rule).setProject(otherProject).setComponent(otherFile));
  431. });
  432. });
  433. underTest.deleteIssues(projectOrView.uuid());
  434. assertThat(countIssuesOfRoot(projectOrView)).isZero();
  435. assertThat(countIssuesOfRoot(otherProject)).isEqualTo(count * 4);
  436. }
  437. @Test
  438. @UseDataProvider("projectsAndViews")
  439. public void deleteIssues_deletes_issue_changes(ComponentDto projectOrView) {
  440. RuleDefinitionDto rule = dbTester.rules().insert();
  441. dbTester.components().insertComponent(projectOrView);
  442. ComponentDto file = dbTester.components().insertComponent(newFileDto(projectOrView));
  443. int count = 5;
  444. IntStream.range(0, count).forEach(i -> {
  445. IssueDto issue = dbTester.issues().insertIssue(t -> t.setRule(rule).setProject(projectOrView).setComponent(projectOrView));
  446. dbTester.issues().insertChange(issue);
  447. issue = dbTester.issues().insertIssue(t -> t.setRule(rule).setProject(projectOrView).setComponent(file));
  448. dbTester.issues().insertChange(issue);
  449. });
  450. underTest.deleteIssues(projectOrView.uuid());
  451. assertThat(dbTester.countRowsOfTable("ISSUE_CHANGES")).isZero();
  452. }
  453. @Test
  454. public void deletePermissions_deletes_permissions_of_public_project() {
  455. OrganizationDto organization = dbTester.organizations().insert();
  456. ComponentDto project = dbTester.components().insertPublicProject(organization);
  457. addPermissions(project);
  458. PurgeCommands purgeCommands = new PurgeCommands(dbTester.getSession(), profiler, system2);
  459. purgeCommands.deletePermissions(project.uuid());
  460. assertThat(dbTester.countRowsOfTable("group_roles")).isEqualTo(2);
  461. assertThat(dbTester.countRowsOfTable("user_roles")).isEqualTo(1);
  462. }
  463. @Test
  464. public void deletePermissions_deletes_permissions_of_private_project() {
  465. OrganizationDto organization = dbTester.organizations().insert();
  466. ComponentDto project = dbTester.components().insertPrivateProject(organization);
  467. addPermissions(project);
  468. PurgeCommands purgeCommands = new PurgeCommands(dbTester.getSession(), profiler, system2);
  469. purgeCommands.deletePermissions(project.uuid());
  470. assertThat(dbTester.countRowsOfTable("group_roles")).isEqualTo(1);
  471. assertThat(dbTester.countRowsOfTable("user_roles")).isEqualTo(1);
  472. }
  473. @Test
  474. public void deletePermissions_deletes_permissions_of_view() {
  475. OrganizationDto organization = dbTester.organizations().insert();
  476. ComponentDto project = dbTester.components().insertPublicPortfolio(organization);
  477. addPermissions(project);
  478. PurgeCommands purgeCommands = new PurgeCommands(dbTester.getSession(), profiler, system2);
  479. purgeCommands.deletePermissions(project.uuid());
  480. assertThat(dbTester.countRowsOfTable("group_roles")).isEqualTo(2);
  481. assertThat(dbTester.countRowsOfTable("user_roles")).isEqualTo(1);
  482. }
  483. @Test
  484. public void deleteNewCodePeriodsByRootUuid_deletes_branch_new_code_periods() {
  485. OrganizationDto organization = dbTester.organizations().insert();
  486. ComponentDto project = dbTester.components().insertPrivateProject(organization);
  487. BranchDto branch = newBranchDto(project);
  488. dbTester.components().insertProjectBranch(project, branch);
  489. // global settings
  490. dbTester.newCodePeriods().insert(NewCodePeriodType.PREVIOUS_VERSION, null);
  491. // project settings
  492. dbTester.newCodePeriods().insert(project.uuid(), NewCodePeriodType.NUMBER_OF_DAYS, "20");
  493. // branch settings
  494. dbTester.newCodePeriods().insert(project.uuid(), branch.getUuid(), NewCodePeriodType.NUMBER_OF_DAYS, "1");
  495. PurgeCommands purgeCommands = new PurgeCommands(dbTester.getSession(), profiler, system2);
  496. purgeCommands.deleteNewCodePeriods(branch.getUuid());
  497. // should delete branch settings only
  498. assertThat(dbTester.countRowsOfTable("new_code_periods")).isEqualTo(2);
  499. }
  500. @Test
  501. public void deleteNewCodePeriodsByRootUuid_deletes_project_new_code_periods() {
  502. OrganizationDto organization = dbTester.organizations().insert();
  503. ComponentDto project = dbTester.components().insertPrivateProject(organization);
  504. BranchDto branch = newBranchDto(project);
  505. dbTester.components().insertProjectBranch(project, branch);
  506. // global settings
  507. dbTester.newCodePeriods().insert(NewCodePeriodType.PREVIOUS_VERSION, null);
  508. // project settings
  509. dbTester.newCodePeriods().insert(project.uuid(), NewCodePeriodType.NUMBER_OF_DAYS, "20");
  510. // branch settings
  511. dbTester.newCodePeriods().insert(project.uuid(), branch.getUuid(), NewCodePeriodType.NUMBER_OF_DAYS, "1");
  512. PurgeCommands purgeCommands = new PurgeCommands(dbTester.getSession(), profiler, system2);
  513. purgeCommands.deleteNewCodePeriods(project.uuid());
  514. // should delete branch and project settings only
  515. assertThat(dbTester.countRowsOfTable("new_code_periods")).isEqualTo(1);
  516. }
  517. @Test
  518. public void deleteNewCodePeriodsByRootUuid_should_not_delete_any_if_root_uuid_is_null() {
  519. OrganizationDto organization = dbTester.organizations().insert();
  520. ComponentDto project = dbTester.components().insertPrivateProject(organization);
  521. BranchDto branch = newBranchDto(project);
  522. dbTester.components().insertProjectBranch(project, branch);
  523. // global settings
  524. dbTester.newCodePeriods().insert(NewCodePeriodType.PREVIOUS_VERSION, null);
  525. // project settings
  526. dbTester.newCodePeriods().insert(project.uuid(), NewCodePeriodType.NUMBER_OF_DAYS, "20");
  527. // branch settings
  528. dbTester.newCodePeriods().insert(project.uuid(), branch.getUuid(), NewCodePeriodType.NUMBER_OF_DAYS, "1");
  529. PurgeCommands purgeCommands = new PurgeCommands(dbTester.getSession(), profiler, system2);
  530. purgeCommands.deleteNewCodePeriods(null);
  531. // should delete branch and project settings only
  532. assertThat(dbTester.countRowsOfTable("new_code_periods")).isEqualTo(3);
  533. }
  534. @Test
  535. public void deleteUserDismissedMessages_deletes_dismissed_warnings_on_project_for_all_users() {
  536. UserDto user1 = dbTester.users().insertUser();
  537. UserDto user2 = dbTester.users().insertUser();
  538. ProjectDto project = dbTester.components().insertPrivateProjectDto();
  539. ProjectDto anotherProject = dbTester.components().insertPrivateProjectDto();
  540. dbTester.users().insertUserDismissedMessage(user1, project, CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
  541. dbTester.users().insertUserDismissedMessage(user2, project, CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
  542. dbTester.users().insertUserDismissedMessage(user1, anotherProject, CeTaskMessageType.SUGGEST_DEVELOPER_EDITION_UPGRADE);
  543. PurgeCommands purgeCommands = new PurgeCommands(dbTester.getSession(), profiler, system2);
  544. purgeCommands.deleteUserDismissedMessages(project.getUuid());
  545. assertThat(dbTester.countRowsOfTable("user_dismissed_messages")).isEqualTo(1);
  546. }
  547. private void addPermissions(ComponentDto root) {
  548. if (!root.isPrivate()) {
  549. dbTester.users().insertProjectPermissionOnAnyone("foo1", root);
  550. dbTester.users().insertPermissionOnAnyone("not project level");
  551. }
  552. GroupDto group = dbTester.users().insertGroup();
  553. dbTester.users().insertProjectPermissionOnGroup(group, "bar", root);
  554. dbTester.users().insertPermissionOnGroup(group, "not project level");
  555. UserDto user = dbTester.users().insertUser();
  556. dbTester.users().insertProjectPermissionOnUser(user, "doh", root);
  557. dbTester.users().insertPermissionOnUser(user, OrganizationPermission.SCAN);
  558. assertThat(dbTester.countRowsOfTable("group_roles")).isEqualTo(root.isPrivate() ? 2 : 4);
  559. assertThat(dbTester.countRowsOfTable("user_roles")).isEqualTo(2);
  560. }
  561. private int countMeasures(SnapshotDto analysis, MetricDto metric) {
  562. return dbTester.countSql("select count(*) from project_measures where analysis_uuid='" + analysis.getUuid() + "' and metric_id=" + metric.getUuid());
  563. }
  564. private int countComponentOfRoot(ComponentDto projectOrView) {
  565. return dbTester.countSql("select count(1) from components where project_uuid='" + projectOrView.uuid() + "'");
  566. }
  567. private void insertDuplication(ComponentDto project, SnapshotDto analysis) {
  568. dbTester.getDbClient().duplicationDao().insert(dbTester.getSession(), new DuplicationUnitDto()
  569. .setAnalysisUuid(analysis.getUuid())
  570. .setComponentUuid(project.uuid())
  571. .setHash(randomAlphabetic(12))
  572. .setIndexInFile(random.nextInt(10))
  573. .setStartLine(random.nextInt(10))
  574. .setEndLine(random.nextInt(10)));
  575. dbTester.commit();
  576. }
  577. private int countDuplications(SnapshotDto analysis) {
  578. return dbTester.countSql("select count(1) from duplications_index where analysis_uuid='" + analysis.getUuid() + "'");
  579. }
  580. private int countMeasuresOf(SnapshotDto analysis) {
  581. return dbTester.countSql("select count(1) from project_measures where analysis_uuid='" + analysis.getUuid() + "'");
  582. }
  583. private void insertRandomEventComponentChange(ComponentDto componentDto) {
  584. insertRandomEventComponentChange(newUuid(), componentDto.uuid());
  585. }
  586. private void insertRandomEventComponentChange(SnapshotDto analysis) {
  587. insertRandomEventComponentChange(analysis.getUuid(), newUuid());
  588. }
  589. private void insertRandomEventComponentChange(String analysisUuid, String componentUuid) {
  590. dbTester.executeInsert(
  591. "EVENT_COMPONENT_CHANGES",
  592. "UUID", newUuid(),
  593. "EVENT_UUID", newUuid(),
  594. "EVENT_COMPONENT_UUID", componentUuid,
  595. "EVENT_ANALYSIS_UUID", analysisUuid,
  596. "CHANGE_CATEGORY", randomAlphabetic(12),
  597. "COMPONENT_UUID", newUuid(),
  598. "COMPONENT_KEY", randomAlphabetic(9),
  599. "COMPONENT_NAME", randomAlphabetic(10),
  600. "CREATED_AT", 1L);
  601. }
  602. private static String newUuid() {
  603. return UuidFactoryFast.getInstance().create();
  604. }
  605. private int countAnalysisPropertiesOf(SnapshotDto analysis) {
  606. return dbTester.countSql("select count(1) from analysis_properties where analysis_uuid='" + analysis.getUuid() + "'");
  607. }
  608. private int countEventsOf(SnapshotDto analysis) {
  609. return dbTester.countSql("select count(1) from events where analysis_uuid='" + analysis.getUuid() + "'");
  610. }
  611. private int countEventComponentChangesOf(ComponentDto rootComponent) {
  612. return dbTester.countSql("select count(1) from event_component_changes where event_component_uuid='" + rootComponent.uuid() + "'");
  613. }
  614. private int countEventComponentChangesOf(SnapshotDto analysis) {
  615. return dbTester.countSql("select count(1) from event_component_changes where event_analysis_uuid='" + analysis.getUuid() + "'");
  616. }
  617. private void insertRandomAnalysisProperty(SnapshotDto analysis1) {
  618. boolean isEmpty = new Random().nextBoolean();
  619. dbTester.executeInsert(
  620. "ANALYSIS_PROPERTIES",
  621. "UUID", newUuid(),
  622. "ANALYSIS_UUID", analysis1.getUuid(),
  623. "KEE", randomAlphabetic(10),
  624. "TEXT_VALUE", isEmpty ? null : randomAlphabetic(50),
  625. "IS_EMPTY", isEmpty,
  626. "CREATED_AT", 1L);
  627. }
  628. private int countAnalysesOfRoot(ComponentDto projectOrView) {
  629. return dbTester.countSql("select count(1) from snapshots where component_uuid='" + projectOrView.uuid() + "'");
  630. }
  631. private int countAnalysesOfRoot(ComponentDto projectOrView, String status, boolean isLast) {
  632. Dialect dialect = dbTester.getDbClient().getDatabase().getDialect();
  633. String bool = isLast ? dialect.getTrueSqlValue() : dialect.getFalseSqlValue();
  634. return dbTester.countSql("select count(1) from snapshots where component_uuid='" + projectOrView.uuid() + "' and status='" + status + "' and islast=" + bool);
  635. }
  636. private List<String> getHugeNumberOfUuids() {
  637. List<String> hugeNbOfSnapshotUuids = newArrayList();
  638. for (long i = 0; i < 4500; i++) {
  639. hugeNbOfSnapshotUuids.add("uuid_" + i);
  640. }
  641. return hugeNbOfSnapshotUuids;
  642. }
  643. @DataProvider
  644. public static Object[][] projects() {
  645. OrganizationDto organization = OrganizationTesting.newOrganizationDto();
  646. return new Object[][] {
  647. {organization, ComponentTesting.newPrivateProjectDto(organization)},
  648. {organization, ComponentTesting.newPublicProjectDto(organization)},
  649. };
  650. }
  651. @DataProvider
  652. public static Object[][] views() {
  653. OrganizationDto organization = OrganizationTesting.newOrganizationDto();
  654. return new Object[][] {
  655. {organization, ComponentTesting.newView(organization)},
  656. {organization, ComponentTesting.newApplication(organization)}
  657. };
  658. }
  659. @DataProvider
  660. public static Object[][] projectsAndViews() {
  661. return Stream.concat(Arrays.stream(views()), Arrays.stream(projects()))
  662. .map(t -> new Object[] {t[1]})
  663. .toArray(Object[][]::new);
  664. }
  665. private Consumer<SnapshotDto> randomLastAndStatus() {
  666. return t -> t.setLast(random.nextBoolean()).setStatus(random.nextBoolean() ? STATUS_PROCESSED : STATUS_UNPROCESSED);
  667. }
  668. private int countIssuesOfRoot(ComponentDto root) {
  669. return dbTester.countSql("select count(*) from issues where project_uuid='" + root.uuid() + "'");
  670. }
  671. }