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 34KB

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