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.

PurgeDaoTest.java 91KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2019 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.google.common.collect.ImmutableList;
  22. import com.google.common.collect.ImmutableSet;
  23. import java.io.ByteArrayInputStream;
  24. import java.time.LocalDateTime;
  25. import java.time.ZoneOffset;
  26. import java.util.Arrays;
  27. import java.util.Collections;
  28. import java.util.Date;
  29. import java.util.List;
  30. import java.util.Optional;
  31. import java.util.Random;
  32. import java.util.Set;
  33. import java.util.function.Consumer;
  34. import java.util.stream.Collectors;
  35. import java.util.stream.IntStream;
  36. import java.util.stream.Stream;
  37. import org.apache.commons.lang.math.RandomUtils;
  38. import org.apache.commons.lang.time.DateUtils;
  39. import org.junit.Rule;
  40. import org.junit.Test;
  41. import org.junit.rules.ExpectedException;
  42. import org.sonar.api.issue.Issue;
  43. import org.sonar.api.resources.Scopes;
  44. import org.sonar.api.utils.System2;
  45. import org.sonar.core.util.CloseableIterator;
  46. import org.sonar.core.util.UuidFactoryFast;
  47. import org.sonar.core.util.Uuids;
  48. import org.sonar.db.DbClient;
  49. import org.sonar.db.DbSession;
  50. import org.sonar.db.DbTester;
  51. import org.sonar.db.alm.ALM;
  52. import org.sonar.db.ce.CeActivityDto;
  53. import org.sonar.db.ce.CeQueueDto;
  54. import org.sonar.db.ce.CeQueueDto.Status;
  55. import org.sonar.db.ce.CeTaskCharacteristicDto;
  56. import org.sonar.db.ce.CeTaskInputDao;
  57. import org.sonar.db.ce.CeTaskMessageDto;
  58. import org.sonar.db.ce.CeTaskTypes;
  59. import org.sonar.db.component.BranchDto;
  60. import org.sonar.db.component.BranchType;
  61. import org.sonar.db.component.ComponentDbTester;
  62. import org.sonar.db.component.ComponentDto;
  63. import org.sonar.db.component.ComponentTesting;
  64. import org.sonar.db.component.SnapshotDto;
  65. import org.sonar.db.event.EventComponentChangeDto;
  66. import org.sonar.db.event.EventDto;
  67. import org.sonar.db.event.EventTesting;
  68. import org.sonar.db.issue.IssueChangeDto;
  69. import org.sonar.db.issue.IssueDto;
  70. import org.sonar.db.measure.LiveMeasureDto;
  71. import org.sonar.db.measure.MeasureDto;
  72. import org.sonar.db.measure.custom.CustomMeasureDto;
  73. import org.sonar.db.metric.MetricDto;
  74. import org.sonar.db.newcodeperiod.NewCodePeriodDto;
  75. import org.sonar.db.newcodeperiod.NewCodePeriodType;
  76. import org.sonar.db.organization.OrganizationDto;
  77. import org.sonar.db.property.PropertyDto;
  78. import org.sonar.db.rule.RuleDefinitionDto;
  79. import org.sonar.db.source.FileSourceDto;
  80. import org.sonar.db.webhook.WebhookDeliveryLiteDto;
  81. import org.sonar.db.webhook.WebhookDto;
  82. import static com.google.common.base.MoreObjects.firstNonNull;
  83. import static java.time.ZoneOffset.UTC;
  84. import static java.util.Arrays.asList;
  85. import static java.util.Collections.emptyList;
  86. import static java.util.Collections.emptySet;
  87. import static java.util.Collections.singletonList;
  88. import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic;
  89. import static org.assertj.core.api.Assertions.assertThat;
  90. import static org.assertj.core.api.Assertions.tuple;
  91. import static org.mockito.Mockito.mock;
  92. import static org.mockito.Mockito.verify;
  93. import static org.mockito.Mockito.verifyZeroInteractions;
  94. import static org.mockito.Mockito.when;
  95. import static org.sonar.db.ce.CeTaskTypes.REPORT;
  96. import static org.sonar.db.component.ComponentTesting.newBranchDto;
  97. import static org.sonar.db.component.ComponentTesting.newDirectory;
  98. import static org.sonar.db.component.ComponentTesting.newFileDto;
  99. import static org.sonar.db.component.ComponentTesting.newModuleDto;
  100. import static org.sonar.db.component.ComponentTesting.newProjectCopy;
  101. import static org.sonar.db.component.ComponentTesting.newSubView;
  102. import static org.sonar.db.component.SnapshotDto.STATUS_PROCESSED;
  103. import static org.sonar.db.component.SnapshotDto.STATUS_UNPROCESSED;
  104. import static org.sonar.db.component.SnapshotTesting.newSnapshot;
  105. import static org.sonar.db.event.EventDto.CATEGORY_VERSION;
  106. import static org.sonar.db.webhook.WebhookDeliveryTesting.newDto;
  107. import static org.sonar.db.webhook.WebhookDeliveryTesting.selectAllDeliveryUuids;
  108. public class PurgeDaoTest {
  109. private static final String PROJECT_UUID = "P1";
  110. private System2 system2 = mock(System2.class);
  111. @Rule
  112. public DbTester db = DbTester.create(system2);
  113. @Rule
  114. public ExpectedException expectedException = ExpectedException.none();
  115. private DbClient dbClient = db.getDbClient();
  116. private DbSession dbSession = db.getSession();
  117. private PurgeDao underTest = db.getDbClient().purgeDao();
  118. @Test
  119. public void purge_failed_ce_tasks() {
  120. ComponentDto project = db.components().insertPrivateProject();
  121. SnapshotDto pastAnalysis = db.components().insertSnapshot(project, t -> t.setStatus(STATUS_PROCESSED).setLast(false));
  122. db.components().insertSnapshot(project, t -> t.setStatus(STATUS_UNPROCESSED).setLast(false));
  123. SnapshotDto lastAnalysis = db.components().insertSnapshot(project, t -> t.setStatus(STATUS_PROCESSED).setLast(true));
  124. underTest.purge(dbSession, newConfigurationWith30Days(project.uuid()), PurgeListener.EMPTY, new PurgeProfiler());
  125. dbSession.commit();
  126. assertThat(uuidsOfAnalysesOfRoot(project)).containsOnly(pastAnalysis.getUuid(), lastAnalysis.getUuid());
  127. }
  128. @Test
  129. public void purge_inactive_branches() {
  130. when(system2.now()).thenReturn(new Date().getTime());
  131. RuleDefinitionDto rule = db.rules().insert();
  132. ComponentDto project = db.components().insertMainBranch();
  133. ComponentDto branch1 = db.components().insertProjectBranch(project);
  134. ComponentDto branch2 = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.BRANCH));
  135. // branch with other components and issues, updated 31 days ago
  136. when(system2.now()).thenReturn(DateUtils.addDays(new Date(), -31).getTime());
  137. ComponentDto branch3 = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.BRANCH));
  138. ComponentDto module = db.components().insertComponent(newModuleDto(branch3));
  139. ComponentDto subModule = db.components().insertComponent(newModuleDto(module));
  140. ComponentDto file = db.components().insertComponent(newFileDto(subModule));
  141. db.issues().insert(rule, branch3, file);
  142. db.issues().insert(rule, branch3, subModule);
  143. db.issues().insert(rule, branch3, module);
  144. underTest.purge(dbSession, newConfigurationWith30Days(System2.INSTANCE, project.uuid(), project.uuid()), PurgeListener.EMPTY, new PurgeProfiler());
  145. dbSession.commit();
  146. assertThat(uuidsIn("projects")).containsOnly(project.uuid(), branch1.uuid(), branch2.uuid());
  147. }
  148. @Test
  149. public void purge_inactive_pull_request() {
  150. when(system2.now()).thenReturn(new Date().getTime());
  151. RuleDefinitionDto rule = db.rules().insert();
  152. ComponentDto project = db.components().insertMainBranch();
  153. ComponentDto nonMainBranch = db.components().insertProjectBranch(project);
  154. ComponentDto recentPullRequest = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.PULL_REQUEST));
  155. // pull request with other components and issues, updated 31 days ago
  156. when(system2.now()).thenReturn(DateUtils.addDays(new Date(), -31).getTime());
  157. ComponentDto pullRequest = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.PULL_REQUEST));
  158. ComponentDto module = db.components().insertComponent(newModuleDto(pullRequest));
  159. ComponentDto subModule = db.components().insertComponent(newModuleDto(module));
  160. ComponentDto file = db.components().insertComponent(newFileDto(subModule));
  161. db.issues().insert(rule, pullRequest, file);
  162. db.issues().insert(rule, pullRequest, subModule);
  163. db.issues().insert(rule, pullRequest, module);
  164. underTest.purge(dbSession, newConfigurationWith30Days(System2.INSTANCE, project.uuid(), project.uuid()), PurgeListener.EMPTY, new PurgeProfiler());
  165. dbSession.commit();
  166. assertThat(uuidsIn("projects")).containsOnly(project.uuid(), nonMainBranch.uuid(), recentPullRequest.uuid());
  167. }
  168. @Test
  169. public void purge_inactive_branches_when_analyzing_non_main_branch() {
  170. when(system2.now()).thenReturn(new Date().getTime());
  171. RuleDefinitionDto rule = db.rules().insert();
  172. ComponentDto project = db.components().insertMainBranch();
  173. ComponentDto nonMainBranch = db.components().insertProjectBranch(project);
  174. when(system2.now()).thenReturn(DateUtils.addDays(new Date(), -31).getTime());
  175. // branch updated 31 days ago
  176. ComponentDto branch1 = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.BRANCH));
  177. // branch with other components and issues, updated 31 days ago
  178. ComponentDto branch2 = db.components().insertProjectBranch(project, b -> b.setBranchType(BranchType.PULL_REQUEST));
  179. ComponentDto file = db.components().insertComponent(newFileDto(branch2));
  180. db.issues().insert(rule, branch2, file);
  181. // back to present
  182. when(system2.now()).thenReturn(new Date().getTime());
  183. // analysing branch1
  184. underTest.purge(dbSession, newConfigurationWith30Days(system2, branch1.uuid(), branch1.getMainBranchProjectUuid()), PurgeListener.EMPTY, new PurgeProfiler());
  185. dbSession.commit();
  186. // branch1 wasn't deleted since it was being analyzed!
  187. assertThat(uuidsIn("projects")).containsOnly(project.uuid(), nonMainBranch.uuid(), branch1.uuid());
  188. }
  189. @Test
  190. public void shouldDeleteHistoricalDataOfDirectoriesAndFiles() {
  191. MetricDto metricWithHistory = db.measures().insertMetric(t -> t.setDeleteHistoricalData(false));
  192. MetricDto metricWithoutHistory = db.measures().insertMetric(t -> t.setDeleteHistoricalData(true));
  193. ComponentDto project = db.components().insertPrivateProject();
  194. SnapshotDto lastAnalysis = db.components().insertSnapshot(project, t -> t.setLast(true));
  195. SnapshotDto oldAnalysis = db.components().insertSnapshot(project, t -> t.setLast(false));
  196. db.measures().insertMeasure(project, lastAnalysis, metricWithHistory);
  197. db.measures().insertMeasure(project, lastAnalysis, metricWithoutHistory);
  198. db.measures().insertMeasure(project, oldAnalysis, metricWithHistory);
  199. db.measures().insertMeasure(project, oldAnalysis, metricWithoutHistory);
  200. ComponentDto otherProject = db.components().insertPrivateProject();
  201. SnapshotDto otherLastAnalysis = db.components().insertSnapshot(otherProject, t -> t.setLast(true));
  202. SnapshotDto otherOldAnalysis = db.components().insertSnapshot(otherProject, t -> t.setLast(false));
  203. db.measures().insertMeasure(otherProject, otherLastAnalysis, metricWithHistory);
  204. db.measures().insertMeasure(otherProject, otherLastAnalysis, metricWithoutHistory);
  205. db.measures().insertMeasure(otherProject, otherOldAnalysis, metricWithHistory);
  206. db.measures().insertMeasure(otherProject, otherOldAnalysis, metricWithoutHistory);
  207. PurgeConfiguration conf = new PurgeConfiguration(project.uuid(), project.uuid(), asList(Scopes.DIRECTORY, Scopes.FILE),
  208. 30, Optional.of(30), System2.INSTANCE, emptySet());
  209. underTest.purge(dbSession, conf, PurgeListener.EMPTY, new PurgeProfiler());
  210. dbSession.commit();
  211. assertThat(db.select("select metric_id as \"METRIC\",analysis_uuid as \"ANALYSIS\" from project_measures"))
  212. .extracting(t -> ((Long) t.get("METRIC")).intValue(), t -> t.get("ANALYSIS"))
  213. .containsOnly(
  214. tuple(metricWithHistory.getId(), lastAnalysis.getUuid()),
  215. tuple(metricWithoutHistory.getId(), lastAnalysis.getUuid()),
  216. tuple(metricWithHistory.getId(), oldAnalysis.getUuid()),
  217. tuple(metricWithHistory.getId(), otherLastAnalysis.getUuid()),
  218. tuple(metricWithoutHistory.getId(), otherLastAnalysis.getUuid()),
  219. tuple(metricWithHistory.getId(), otherOldAnalysis.getUuid()),
  220. tuple(metricWithoutHistory.getId(), otherOldAnalysis.getUuid()));
  221. }
  222. private Stream<Long> idsOf(String tableName) {
  223. return db.select("select id as \"ID\" from " + tableName)
  224. .stream()
  225. .map(t -> (Long) t.get("ID"));
  226. }
  227. @Test
  228. public void close_issues_clean_index_and_file_sources_of_disabled_components_specified_by_uuid_in_configuration() {
  229. RuleDefinitionDto rule = db.rules().insert();
  230. ComponentDto project = db.components().insertMainBranch();
  231. db.components().insertSnapshot(project);
  232. db.components().insertSnapshot(project);
  233. db.components().insertSnapshot(project, s -> s.setLast(false));
  234. ComponentDto module = db.components().insertComponent(newModuleDto(project).setEnabled(false));
  235. ComponentDto dir = db.components().insertComponent(newDirectory(module, "sub").setEnabled(false));
  236. ComponentDto srcFile = db.components().insertComponent(newFileDto(module, dir).setEnabled(false));
  237. ComponentDto testFile = db.components().insertComponent(newFileDto(module, dir).setEnabled(false));
  238. ComponentDto enabledFile = db.components().insertComponent(newFileDto(module, dir).setEnabled(true));
  239. IssueDto openOnFile = db.issues().insert(rule, project, srcFile, issue -> issue.setStatus("OPEN"));
  240. IssueDto confirmOnFile = db.issues().insert(rule, project, srcFile, issue -> issue.setStatus("CONFIRM"));
  241. IssueDto openOnDir = db.issues().insert(rule, project, dir, issue -> issue.setStatus("OPEN"));
  242. IssueDto confirmOnDir = db.issues().insert(rule, project, dir, issue -> issue.setStatus("CONFIRM"));
  243. IssueDto openOnEnabledComponent = db.issues().insert(rule, project, enabledFile, issue -> issue.setStatus("OPEN"));
  244. IssueDto confirmOnEnabledComponent = db.issues().insert(rule, project, enabledFile, issue -> issue.setStatus("CONFIRM"));
  245. assertThat(db.countSql("select count(*) from snapshots where purge_status = 1")).isEqualTo(0);
  246. assertThat(db.countSql("select count(*) from issues where status = 'CLOSED'")).isEqualTo(0);
  247. assertThat(db.countSql("select count(*) from issues where resolution = 'REMOVED'")).isEqualTo(0);
  248. db.fileSources().insertFileSource(srcFile);
  249. FileSourceDto nonSelectedFileSource = db.fileSources().insertFileSource(enabledFile);
  250. assertThat(db.countRowsOfTable("file_sources")).isEqualTo(2);
  251. MetricDto metric1 = db.measures().insertMetric();
  252. MetricDto metric2 = db.measures().insertMetric();
  253. LiveMeasureDto liveMeasureMetric1OnFile = db.measures().insertLiveMeasure(srcFile, metric1);
  254. LiveMeasureDto liveMeasureMetric2OnFile = db.measures().insertLiveMeasure(srcFile, metric2);
  255. LiveMeasureDto liveMeasureMetric1OnDir = db.measures().insertLiveMeasure(dir, metric1);
  256. LiveMeasureDto liveMeasureMetric2OnDir = db.measures().insertLiveMeasure(dir, metric2);
  257. LiveMeasureDto liveMeasureMetric1OnProject = db.measures().insertLiveMeasure(project, metric1);
  258. LiveMeasureDto liveMeasureMetric2OnProject = db.measures().insertLiveMeasure(project, metric2);
  259. LiveMeasureDto liveMeasureMetric1OnNonSelected = db.measures().insertLiveMeasure(enabledFile, metric1);
  260. LiveMeasureDto liveMeasureMetric2OnNonSelected = db.measures().insertLiveMeasure(enabledFile, metric2);
  261. assertThat(db.countRowsOfTable("live_measures")).isEqualTo(8);
  262. PurgeListener purgeListener = mock(PurgeListener.class);
  263. // back to present
  264. Set<String> selectedComponentUuids = ImmutableSet.of(module.uuid(), srcFile.uuid(), testFile.uuid());
  265. underTest.purge(dbSession, newConfigurationWith30Days(system2, project.uuid(), project.uuid(), selectedComponentUuids),
  266. purgeListener, new PurgeProfiler());
  267. dbSession.commit();
  268. verify(purgeListener).onComponentsDisabling(project.uuid(), selectedComponentUuids);
  269. verify(purgeListener).onComponentsDisabling(project.uuid(), ImmutableSet.of(dir.uuid()));
  270. // set purge_status=1 for non-last snapshot
  271. assertThat(db.countSql("select count(*) from snapshots where purge_status = 1")).isEqualTo(1);
  272. // close open issues of selected
  273. assertThat(db.countSql("select count(*) from issues where status = 'CLOSED'")).isEqualTo(4);
  274. for (IssueDto issue : Arrays.asList(openOnFile, confirmOnFile, openOnDir, confirmOnDir)) {
  275. assertThat(db.getDbClient().issueDao().selectOrFailByKey(dbSession, issue.getKey()))
  276. .extracting(IssueDto::getStatus, IssueDto::getResolution)
  277. .containsExactlyInAnyOrder("CLOSED", "REMOVED");
  278. }
  279. for (IssueDto issue : Arrays.asList(openOnEnabledComponent, confirmOnEnabledComponent)) {
  280. assertThat(db.getDbClient().issueDao().selectByKey(dbSession, issue.getKey()).get())
  281. .extracting("status", "resolution")
  282. .containsExactlyInAnyOrder(issue.getStatus(), null);
  283. }
  284. // delete file sources of selected
  285. assertThat(db.countRowsOfTable("file_sources")).isEqualTo(1);
  286. assertThat(db.getDbClient().fileSourceDao().selectByFileUuid(dbSession, nonSelectedFileSource.getFileUuid())).isNotNull();
  287. // deletes live measure of selected
  288. assertThat(db.countRowsOfTable("live_measures")).isEqualTo(4);
  289. List<LiveMeasureDto> liveMeasureDtos = db.getDbClient().liveMeasureDao()
  290. .selectByComponentUuidsAndMetricIds(dbSession, ImmutableSet.of(srcFile.uuid(), dir.uuid(), project.uuid(), enabledFile.uuid()),
  291. ImmutableSet.of(metric1.getId(), metric2.getId()));
  292. assertThat(liveMeasureDtos)
  293. .extracting(LiveMeasureDto::getComponentUuid)
  294. .containsOnly(enabledFile.uuid(), project.uuid());
  295. assertThat(liveMeasureDtos)
  296. .extracting(LiveMeasureDto::getMetricId)
  297. .containsOnly(metric1.getId(), metric2.getId());
  298. }
  299. @Test
  300. public void shouldDeleteAnalyses() {
  301. ComponentDto project = db.components().insertPrivateProject();
  302. SnapshotDto analysis1 = db.components().insertSnapshot(project);
  303. SnapshotDto analysis2 = db.components().insertSnapshot(project);
  304. SnapshotDto analysis3 = db.components().insertSnapshot(project);
  305. ComponentDto otherProject = db.components().insertPrivateProject();
  306. SnapshotDto otherAnalysis1 = db.components().insertSnapshot(otherProject);
  307. underTest.deleteAnalyses(dbSession, new PurgeProfiler(), ImmutableList.of(idUuidPairOf(analysis1)));
  308. assertThat(uuidsIn("snapshots")).containsOnly(analysis2.getUuid(), analysis3.getUuid(), otherAnalysis1.getUuid());
  309. underTest.deleteAnalyses(dbSession, new PurgeProfiler(), ImmutableList.of(idUuidPairOf(analysis1), idUuidPairOf(analysis3), idUuidPairOf(otherAnalysis1)));
  310. assertThat(uuidsIn("snapshots")).containsOnly(analysis2.getUuid());
  311. }
  312. @Test
  313. public void deleteAnalyses_deletes_rows_in_events_and_event_component_changes() {
  314. ComponentDto project = ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization());
  315. dbClient.componentDao().insert(dbSession, project);
  316. SnapshotDto projectAnalysis1 = db.components().insertSnapshot(project);
  317. SnapshotDto projectAnalysis2 = db.components().insertSnapshot(project);
  318. SnapshotDto projectAnalysis3 = db.components().insertSnapshot(project);
  319. SnapshotDto projectAnalysis4 = db.components().insertSnapshot(project);
  320. EventDto projectEvent1 = db.events().insertEvent(projectAnalysis1);
  321. EventDto projectEvent2 = db.events().insertEvent(projectAnalysis2);
  322. EventDto projectEvent3 = db.events().insertEvent(projectAnalysis3);
  323. // note: projectAnalysis4 has no event
  324. ComponentDto referencedProjectA = db.components().insertPublicProject();
  325. ComponentDto referencedProjectB = db.components().insertPublicProject();
  326. db.events().insertEventComponentChanges(projectEvent1, projectAnalysis1, randomChangeCategory(), referencedProjectA, null);
  327. db.events().insertEventComponentChanges(projectEvent1, projectAnalysis1, randomChangeCategory(), referencedProjectB, null);
  328. BranchDto branchProjectA = newBranchDto(referencedProjectA);
  329. ComponentDto cptBranchProjectA = ComponentTesting.newProjectBranch(referencedProjectA, branchProjectA);
  330. db.events().insertEventComponentChanges(projectEvent2, projectAnalysis2, randomChangeCategory(), cptBranchProjectA, branchProjectA);
  331. // note: projectEvent3 has no component change
  332. // delete non existing analysis has no effect
  333. underTest.deleteAnalyses(dbSession, new PurgeProfiler(), ImmutableList.of(new IdUuidPair(3, "foo")));
  334. assertThat(uuidsIn("event_component_changes", "event_analysis_uuid"))
  335. .containsOnly(projectAnalysis1.getUuid(), projectAnalysis2.getUuid());
  336. assertThat(db.countRowsOfTable("event_component_changes"))
  337. .isEqualTo(3);
  338. assertThat(uuidsIn("events"))
  339. .containsOnly(projectEvent1.getUuid(), projectEvent2.getUuid(), projectEvent3.getUuid());
  340. underTest.deleteAnalyses(dbSession, new PurgeProfiler(), ImmutableList.of(idUuidPairOf(projectAnalysis1)));
  341. assertThat(uuidsIn("event_component_changes", "event_analysis_uuid"))
  342. .containsOnly(projectAnalysis2.getUuid());
  343. assertThat(db.countRowsOfTable("event_component_changes"))
  344. .isEqualTo(1);
  345. assertThat(uuidsIn("events"))
  346. .containsOnly(projectEvent2.getUuid(), projectEvent3.getUuid());
  347. underTest.deleteAnalyses(dbSession, new PurgeProfiler(), ImmutableList.of(idUuidPairOf(projectAnalysis4)));
  348. assertThat(uuidsIn("event_component_changes", "event_analysis_uuid"))
  349. .containsOnly(projectAnalysis2.getUuid());
  350. assertThat(db.countRowsOfTable("event_component_changes"))
  351. .isEqualTo(1);
  352. assertThat(uuidsIn("events"))
  353. .containsOnly(projectEvent2.getUuid(), projectEvent3.getUuid());
  354. underTest.deleteAnalyses(dbSession, new PurgeProfiler(), ImmutableList.of(idUuidPairOf(projectAnalysis3)));
  355. assertThat(uuidsIn("event_component_changes", "event_analysis_uuid"))
  356. .containsOnly(projectAnalysis2.getUuid());
  357. assertThat(db.countRowsOfTable("event_component_changes"))
  358. .isEqualTo(1);
  359. assertThat(uuidsIn("events"))
  360. .containsOnly(projectEvent2.getUuid());
  361. underTest.deleteAnalyses(dbSession, new PurgeProfiler(), ImmutableList.of(idUuidPairOf(projectAnalysis2)));
  362. assertThat(db.countRowsOfTable("event_component_changes"))
  363. .isZero();
  364. assertThat(db.countRowsOfTable("events"))
  365. .isZero();
  366. }
  367. @Test
  368. public void selectPurgeableAnalyses() {
  369. SnapshotDto[] analyses = new SnapshotDto[] {
  370. newSnapshot()
  371. .setUuid("u1")
  372. .setComponentUuid(PROJECT_UUID)
  373. .setStatus(STATUS_PROCESSED)
  374. .setLast(true),
  375. // not processed -> exclude
  376. newSnapshot()
  377. .setUuid("u2")
  378. .setComponentUuid(PROJECT_UUID)
  379. .setStatus(STATUS_UNPROCESSED)
  380. .setLast(false),
  381. // on other resource -> exclude
  382. newSnapshot()
  383. .setUuid("u3")
  384. .setComponentUuid("uuid_222")
  385. .setStatus(STATUS_PROCESSED)
  386. .setLast(true),
  387. // without event -> select
  388. newSnapshot()
  389. .setUuid("u4")
  390. .setComponentUuid(PROJECT_UUID)
  391. .setStatus(STATUS_PROCESSED)
  392. .setLast(false),
  393. // with event -> select
  394. newSnapshot()
  395. .setUuid("u5")
  396. .setComponentUuid(PROJECT_UUID)
  397. .setStatus(STATUS_PROCESSED)
  398. .setLast(false)
  399. .setProjectVersion("V5")
  400. };
  401. db.components().insertSnapshots(analyses);
  402. db.events().insertEvent(EventTesting.newEvent(analyses[4])
  403. .setName("V5")
  404. .setCategory(CATEGORY_VERSION));
  405. List<PurgeableAnalysisDto> purgeableAnalyses = underTest.selectPurgeableAnalyses(PROJECT_UUID, dbSession);
  406. assertThat(purgeableAnalyses).hasSize(3);
  407. assertThat(getById(purgeableAnalyses, "u1").isLast()).isTrue();
  408. assertThat(getById(purgeableAnalyses, "u1").hasEvents()).isFalse();
  409. assertThat(getById(purgeableAnalyses, "u1").getVersion()).isNull();
  410. assertThat(getById(purgeableAnalyses, "u4").isLast()).isFalse();
  411. assertThat(getById(purgeableAnalyses, "u4").hasEvents()).isFalse();
  412. assertThat(getById(purgeableAnalyses, "u4").getVersion()).isNull();
  413. assertThat(getById(purgeableAnalyses, "u5").isLast()).isFalse();
  414. assertThat(getById(purgeableAnalyses, "u5").hasEvents()).isTrue();
  415. assertThat(getById(purgeableAnalyses, "u5").getVersion()).isEqualTo("V5");
  416. }
  417. @Test
  418. public void selectPurgeableAnalyses_does_not_return_the_baseline() {
  419. ComponentDto project1 = db.components().insertMainBranch(db.getDefaultOrganization(), "master");
  420. SnapshotDto analysis1 = db.components().insertSnapshot(newSnapshot()
  421. .setComponentUuid(project1.uuid())
  422. .setStatus(STATUS_PROCESSED)
  423. .setLast(false));
  424. dbClient.newCodePeriodDao().insert(dbSession,
  425. new NewCodePeriodDto()
  426. .setProjectUuid(project1.uuid())
  427. .setBranchUuid(project1.uuid())
  428. .setType(NewCodePeriodType.SPECIFIC_ANALYSIS)
  429. .setValue(analysis1.getUuid()));
  430. ComponentDto project2 = db.components().insertPrivateProject();
  431. SnapshotDto analysis2 = db.components().insertSnapshot(newSnapshot()
  432. .setComponentUuid(project2.uuid())
  433. .setStatus(STATUS_PROCESSED)
  434. .setLast(false));
  435. db.components().insertProjectBranch(project2);
  436. assertThat(underTest.selectPurgeableAnalyses(project1.uuid(), dbSession)).isEmpty();
  437. assertThat(underTest.selectPurgeableAnalyses(project2.uuid(), dbSession))
  438. .extracting(PurgeableAnalysisDto::getAnalysisUuid)
  439. .containsOnly(analysis2.getUuid());
  440. }
  441. @Test
  442. public void selectPurgeableAnalyses_does_not_return_the_baseline_of_specific_branch() {
  443. ComponentDto project = db.components().insertMainBranch(db.getDefaultOrganization(), "master");
  444. SnapshotDto analysisProject = db.components().insertSnapshot(newSnapshot()
  445. .setComponentUuid(project.uuid())
  446. .setStatus(STATUS_PROCESSED)
  447. .setLast(false));
  448. dbClient.newCodePeriodDao().insert(dbSession,
  449. new NewCodePeriodDto()
  450. .setProjectUuid(project.uuid())
  451. .setBranchUuid(project.uuid())
  452. .setType(NewCodePeriodType.SPECIFIC_ANALYSIS)
  453. .setValue(analysisProject.getUuid()));
  454. ComponentDto branch1 = db.components().insertProjectBranch(project);
  455. SnapshotDto analysisBranch1 = db.components().insertSnapshot(newSnapshot()
  456. .setComponentUuid(branch1.uuid())
  457. .setStatus(STATUS_PROCESSED)
  458. .setLast(false));
  459. ComponentDto branch2 = db.components().insertProjectBranch(project);
  460. SnapshotDto analysisBranch2 = db.components().insertSnapshot(newSnapshot()
  461. .setComponentUuid(branch2.uuid())
  462. .setStatus(STATUS_PROCESSED)
  463. .setLast(false));
  464. dbClient.newCodePeriodDao().insert(dbSession,
  465. new NewCodePeriodDto()
  466. .setProjectUuid(project.uuid())
  467. .setBranchUuid(branch2.uuid())
  468. .setType(NewCodePeriodType.SPECIFIC_ANALYSIS)
  469. .setValue(analysisBranch2.getUuid()));
  470. dbSession.commit();
  471. assertThat(underTest.selectPurgeableAnalyses(project.uuid(), dbSession))
  472. .isEmpty();
  473. assertThat(underTest.selectPurgeableAnalyses(branch1.uuid(), dbSession))
  474. .extracting(PurgeableAnalysisDto::getAnalysisUuid)
  475. .containsOnly(analysisBranch1.getUuid());
  476. assertThat(underTest.selectPurgeableAnalyses(branch2.uuid(), dbSession))
  477. .isEmpty();
  478. }
  479. @Test
  480. public void delete_project_and_associated_data() {
  481. RuleDefinitionDto rule = db.rules().insert();
  482. ComponentDto project = db.components().insertPrivateProject();
  483. ComponentDto module = db.components().insertComponent(newModuleDto(project));
  484. ComponentDto directory = db.components().insertComponent(newDirectory(module, "a/b"));
  485. ComponentDto file = db.components().insertComponent(newFileDto(directory));
  486. SnapshotDto analysis = db.components().insertSnapshot(project);
  487. IssueDto issue1 = db.issues().insert(rule, project, file);
  488. IssueChangeDto issueChange1 = db.issues().insertChange(issue1);
  489. IssueDto issue2 = db.issues().insert(rule, project, file);
  490. FileSourceDto fileSource = db.fileSources().insertFileSource(file);
  491. ComponentDto otherProject = db.components().insertPrivateProject();
  492. ComponentDto otherModule = db.components().insertComponent(newModuleDto(otherProject));
  493. ComponentDto otherDirectory = db.components().insertComponent(newDirectory(otherModule, "a/b"));
  494. ComponentDto otherFile = db.components().insertComponent(newFileDto(otherDirectory));
  495. SnapshotDto otherAnalysis = db.components().insertSnapshot(otherProject);
  496. IssueDto otherIssue1 = db.issues().insert(rule, otherProject, otherFile);
  497. IssueChangeDto otherIssueChange1 = db.issues().insertChange(otherIssue1);
  498. IssueDto otherIssue2 = db.issues().insert(rule, otherProject, otherFile);
  499. FileSourceDto otherFileSource = db.fileSources().insertFileSource(otherFile);
  500. underTest.deleteProject(dbSession, project.uuid());
  501. dbSession.commit();
  502. assertThat(uuidsIn("projects")).containsOnly(otherProject.uuid(), otherModule.uuid(), otherDirectory.uuid(), otherFile.uuid());
  503. assertThat(uuidsIn("snapshots")).containsOnly(otherAnalysis.getUuid());
  504. assertThat(uuidsIn("issues", "kee")).containsOnly(otherIssue1.getKey(), otherIssue2.getKey());
  505. assertThat(uuidsIn("issue_changes", "kee")).containsOnly(otherIssueChange1.getKey());
  506. assertThat(uuidsIn("file_sources", "file_uuid")).containsOnly(otherFileSource.getFileUuid());
  507. }
  508. @Test
  509. public void delete_webhooks_from_project() {
  510. OrganizationDto organization = db.organizations().insert();
  511. ComponentDto project1 = db.components().insertPrivateProject(organization);
  512. WebhookDto webhook = db.webhooks().insertWebhook(project1);
  513. db.webhookDelivery().insert(webhook);
  514. ComponentDto projectNotToBeDeleted = db.components().insertPrivateProject(organization);
  515. WebhookDto webhookNotDeleted = db.webhooks().insertWebhook(projectNotToBeDeleted);
  516. WebhookDeliveryLiteDto webhookDeliveryNotDeleted = db.webhookDelivery().insert(webhookNotDeleted);
  517. underTest.deleteProject(dbSession, project1.uuid());
  518. assertThat(db.select(db.getSession(), "select uuid as \"uuid\" from webhooks"))
  519. .extracting(m -> m.get("uuid"))
  520. .containsExactlyInAnyOrder(webhookNotDeleted.getUuid());
  521. assertThat(db.select(db.getSession(), "select uuid as \"uuid\" from webhook_deliveries"))
  522. .extracting(m -> m.get("uuid"))
  523. .containsExactlyInAnyOrder(webhookDeliveryNotDeleted.getUuid());
  524. }
  525. private Stream<String> uuidsOfTable(String tableName) {
  526. return db.select("select uuid as \"UUID\" from " + tableName)
  527. .stream()
  528. .map(s -> (String) s.get("UUID"));
  529. }
  530. @Test
  531. public void delete_row_in_ce_activity_when_deleting_project() {
  532. ComponentDto projectToBeDeleted = ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization());
  533. ComponentDto anotherLivingProject = ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization());
  534. dbClient.componentDao().insert(dbSession, projectToBeDeleted, anotherLivingProject);
  535. // Insert 2 rows in CE_ACTIVITY : one for the project that will be deleted, and one on another project
  536. CeActivityDto toBeDeletedActivity = insertCeActivity(projectToBeDeleted);
  537. CeActivityDto notDeletedActivity = insertCeActivity(anotherLivingProject);
  538. dbSession.commit();
  539. underTest.deleteProject(dbSession, projectToBeDeleted.uuid());
  540. dbSession.commit();
  541. assertThat(uuidsOfTable("ce_activity"))
  542. .containsOnly(notDeletedActivity.getUuid())
  543. .hasSize(1);
  544. }
  545. @Test
  546. public void delete_row_in_ce_task_input_referring_to_a_row_in_ce_activity_when_deleting_project() {
  547. ComponentDto project = ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization());
  548. ComponentDto branch = ComponentTesting.newProjectBranch(project, newBranchDto(project));
  549. ComponentDto anotherBranch = ComponentTesting.newProjectBranch(project, newBranchDto(project));
  550. ComponentDto anotherProject = ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization());
  551. dbClient.componentDao().insert(dbSession, project, branch, anotherBranch, anotherProject);
  552. CeActivityDto projectTask = insertCeActivity(project);
  553. insertCeTaskInput(projectTask.getUuid());
  554. CeActivityDto branchTask = insertCeActivity(branch);
  555. insertCeTaskInput(branchTask.getUuid());
  556. CeActivityDto anotherBranchTask = insertCeActivity(anotherBranch);
  557. insertCeTaskInput(anotherBranchTask.getUuid());
  558. CeActivityDto anotherProjectTask = insertCeActivity(anotherProject);
  559. insertCeTaskInput(anotherProjectTask.getUuid());
  560. insertCeTaskInput("non existing task");
  561. dbSession.commit();
  562. underTest.deleteProject(dbSession, branch.uuid());
  563. dbSession.commit();
  564. assertThat(uuidsIn("ce_activity")).containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid());
  565. assertThat(taskUuidsIn("ce_task_input")).containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid(), "non existing task");
  566. underTest.deleteProject(dbSession, project.uuid());
  567. dbSession.commit();
  568. assertThat(uuidsIn("ce_activity")).containsOnly(anotherProjectTask.getUuid());
  569. assertThat(taskUuidsIn("ce_task_input")).containsOnly(anotherProjectTask.getUuid(), "non existing task");
  570. }
  571. @Test
  572. public void delete_row_in_ce_scanner_context_referring_to_a_row_in_ce_activity_when_deleting_project() {
  573. ComponentDto project = ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization());
  574. ComponentDto branch = ComponentTesting.newProjectBranch(project, newBranchDto(project));
  575. ComponentDto anotherBranch = ComponentTesting.newProjectBranch(project, newBranchDto(project));
  576. ComponentDto anotherProject = ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization());
  577. dbClient.componentDao().insert(dbSession, project, branch, anotherBranch, anotherProject);
  578. CeActivityDto projectTask = insertCeActivity(project);
  579. insertCeScannerContext(projectTask.getUuid());
  580. CeActivityDto branchTask = insertCeActivity(branch);
  581. insertCeScannerContext(branchTask.getUuid());
  582. CeActivityDto anotherBranchTask = insertCeActivity(anotherBranch);
  583. insertCeScannerContext(anotherBranchTask.getUuid());
  584. CeActivityDto anotherProjectTask = insertCeActivity(anotherProject);
  585. insertCeScannerContext(anotherProjectTask.getUuid());
  586. insertCeScannerContext("non existing task");
  587. dbSession.commit();
  588. underTest.deleteProject(dbSession, branch.uuid());
  589. dbSession.commit();
  590. assertThat(uuidsIn("ce_activity")).containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid());
  591. assertThat(taskUuidsIn("ce_scanner_context")).containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid(), "non existing task");
  592. underTest.deleteProject(dbSession, project.uuid());
  593. dbSession.commit();
  594. assertThat(uuidsIn("ce_activity")).containsOnly(anotherProjectTask.getUuid());
  595. assertThat(taskUuidsIn("ce_scanner_context")).containsOnly(anotherProjectTask.getUuid(), "non existing task");
  596. }
  597. @Test
  598. public void delete_row_in_ce_task_characteristics_referring_to_a_row_in_ce_activity_when_deleting_project() {
  599. ComponentDto project = ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization());
  600. ComponentDto branch = ComponentTesting.newProjectBranch(project, newBranchDto(project));
  601. ComponentDto anotherBranch = ComponentTesting.newProjectBranch(project, newBranchDto(project));
  602. ComponentDto anotherProject = ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization());
  603. dbClient.componentDao().insert(dbSession, project, branch, anotherBranch, anotherProject);
  604. CeActivityDto projectTask = insertCeActivity(project);
  605. insertCeTaskCharacteristics(projectTask.getUuid(), 3);
  606. CeActivityDto branchTask = insertCeActivity(branch);
  607. insertCeTaskCharacteristics(branchTask.getUuid(), 2);
  608. CeActivityDto anotherBranchTask = insertCeActivity(anotherBranch);
  609. insertCeTaskCharacteristics(anotherBranchTask.getUuid(), 6);
  610. CeActivityDto anotherProjectTask = insertCeActivity(anotherProject);
  611. insertCeTaskCharacteristics(anotherProjectTask.getUuid(), 2);
  612. insertCeTaskCharacteristics("non existing task", 5);
  613. dbSession.commit();
  614. underTest.deleteProject(dbSession, branch.uuid());
  615. dbSession.commit();
  616. assertThat(uuidsIn("ce_activity")).containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid());
  617. assertThat(taskUuidsIn("ce_task_characteristics")).containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid(), "non existing task");
  618. underTest.deleteProject(dbSession, project.uuid());
  619. dbSession.commit();
  620. assertThat(uuidsIn("ce_activity")).containsOnly(anotherProjectTask.getUuid());
  621. assertThat(taskUuidsIn("ce_task_characteristics")).containsOnly(anotherProjectTask.getUuid(), "non existing task");
  622. }
  623. @Test
  624. public void delete_row_in_ce_task_message_referring_to_a_row_in_ce_activity_when_deleting_project() {
  625. ComponentDto project = ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization());
  626. ComponentDto branch = ComponentTesting.newProjectBranch(project, newBranchDto(project));
  627. ComponentDto anotherBranch = ComponentTesting.newProjectBranch(project, newBranchDto(project));
  628. ComponentDto anotherProject = ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization());
  629. dbClient.componentDao().insert(dbSession, project, branch, anotherBranch, anotherProject);
  630. CeActivityDto projectTask = insertCeActivity(project);
  631. insertCeTaskMessages(projectTask.getUuid(), 3);
  632. CeActivityDto branchTask = insertCeActivity(branch);
  633. insertCeTaskMessages(branchTask.getUuid(), 2);
  634. CeActivityDto anotherBranchTask = insertCeActivity(anotherBranch);
  635. insertCeTaskMessages(anotherBranchTask.getUuid(), 6);
  636. CeActivityDto anotherProjectTask = insertCeActivity(anotherProject);
  637. insertCeTaskMessages(anotherProjectTask.getUuid(), 2);
  638. insertCeTaskMessages("non existing task", 5);
  639. dbSession.commit();
  640. underTest.deleteProject(dbSession, branch.uuid());
  641. dbSession.commit();
  642. assertThat(uuidsIn("ce_activity")).containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid());
  643. assertThat(taskUuidsIn("ce_task_message")).containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid(), "non existing task");
  644. underTest.deleteProject(dbSession, project.uuid());
  645. dbSession.commit();
  646. assertThat(uuidsIn("ce_activity")).containsOnly(anotherProjectTask.getUuid());
  647. assertThat(taskUuidsIn("ce_task_message")).containsOnly(anotherProjectTask.getUuid(), "non existing task");
  648. }
  649. @Test
  650. public void delete_tasks_in_ce_queue_when_deleting_project() {
  651. ComponentDto projectToBeDeleted = db.components().insertPrivateProject();
  652. ComponentDto anotherLivingProject = db.components().insertPrivateProject();
  653. // Insert 3 rows in CE_QUEUE: two for the project that will be deleted (in order to check that status
  654. // is not involved in deletion), and one on another project
  655. dbClient.ceQueueDao().insert(dbSession, createCeQueue(projectToBeDeleted, Status.PENDING));
  656. dbClient.ceQueueDao().insert(dbSession, createCeQueue(projectToBeDeleted, Status.IN_PROGRESS));
  657. dbClient.ceQueueDao().insert(dbSession, createCeQueue(anotherLivingProject, Status.PENDING));
  658. dbSession.commit();
  659. underTest.deleteProject(dbSession, projectToBeDeleted.uuid());
  660. dbSession.commit();
  661. assertThat(db.countRowsOfTable("ce_queue")).isEqualTo(1);
  662. assertThat(db.countSql("select count(*) from ce_queue where main_component_uuid='" + projectToBeDeleted.uuid() + "'")).isEqualTo(0);
  663. }
  664. @Test
  665. public void delete_row_in_ce_task_input_referring_to_a_row_in_ce_queue_when_deleting_project() {
  666. ComponentDto project = ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization());
  667. ComponentDto branch = ComponentTesting.newProjectBranch(project, newBranchDto(project));
  668. ComponentDto anotherBranch = ComponentTesting.newProjectBranch(project, newBranchDto(project));
  669. ComponentDto anotherProject = ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization());
  670. dbClient.componentDao().insert(dbSession, project, branch, anotherBranch, anotherProject);
  671. CeQueueDto projectTask = insertCeQueue(project);
  672. insertCeTaskInput(projectTask.getUuid());
  673. CeQueueDto branchTask = insertCeQueue(branch);
  674. insertCeTaskInput(branchTask.getUuid());
  675. CeQueueDto anotherBranchTask = insertCeQueue(anotherBranch);
  676. insertCeTaskInput(anotherBranchTask.getUuid());
  677. CeQueueDto anotherProjectTask = insertCeQueue(anotherProject);
  678. insertCeTaskInput(anotherProjectTask.getUuid());
  679. insertCeTaskInput("non existing task");
  680. dbSession.commit();
  681. underTest.deleteProject(dbSession, branch.uuid());
  682. dbSession.commit();
  683. assertThat(uuidsIn("ce_queue")).containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid());
  684. assertThat(taskUuidsIn("ce_task_input")).containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid(), "non existing task");
  685. underTest.deleteProject(dbSession, project.uuid());
  686. dbSession.commit();
  687. assertThat(uuidsIn("ce_queue")).containsOnly(anotherProjectTask.getUuid());
  688. assertThat(taskUuidsIn("ce_task_input")).containsOnly(anotherProjectTask.getUuid(), "non existing task");
  689. }
  690. @Test
  691. public void delete_row_in_ce_scanner_context_referring_to_a_row_in_ce_queue_when_deleting_project() {
  692. ComponentDto project = ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization());
  693. ComponentDto branch = ComponentTesting.newProjectBranch(project, newBranchDto(project));
  694. ComponentDto anotherBranch = ComponentTesting.newProjectBranch(project, newBranchDto(project));
  695. ComponentDto anotherProject = ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization());
  696. dbClient.componentDao().insert(dbSession, project, branch, anotherBranch, anotherProject);
  697. CeQueueDto projectTask = insertCeQueue(project);
  698. insertCeScannerContext(projectTask.getUuid());
  699. CeQueueDto branchTask = insertCeQueue(branch);
  700. insertCeScannerContext(branchTask.getUuid());
  701. CeQueueDto anotherBranchTask = insertCeQueue(anotherBranch);
  702. insertCeScannerContext(anotherBranchTask.getUuid());
  703. CeQueueDto anotherProjectTask = insertCeQueue(anotherProject);
  704. insertCeScannerContext(anotherProjectTask.getUuid());
  705. insertCeScannerContext("non existing task");
  706. dbSession.commit();
  707. underTest.deleteProject(dbSession, branch.uuid());
  708. dbSession.commit();
  709. assertThat(uuidsIn("ce_queue")).containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid());
  710. assertThat(taskUuidsIn("ce_scanner_context"))
  711. .containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid(), "non existing task");
  712. underTest.deleteProject(dbSession, project.uuid());
  713. dbSession.commit();
  714. assertThat(uuidsIn("ce_queue")).containsOnly(anotherProjectTask.getUuid());
  715. assertThat(taskUuidsIn("ce_scanner_context")).containsOnly(anotherProjectTask.getUuid(), "non existing task");
  716. }
  717. @Test
  718. public void delete_row_in_ce_task_characteristics_referring_to_a_row_in_ce_queue_when_deleting_project() {
  719. ComponentDto project = ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization());
  720. ComponentDto branch = ComponentTesting.newProjectBranch(project, newBranchDto(project));
  721. ComponentDto anotherBranch = ComponentTesting.newProjectBranch(project, newBranchDto(project));
  722. ComponentDto anotherProject = ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization());
  723. dbClient.componentDao().insert(dbSession, project, branch, anotherBranch, anotherProject);
  724. CeQueueDto projectTask = insertCeQueue(project);
  725. insertCeTaskCharacteristics(projectTask.getUuid(), 3);
  726. CeQueueDto branchTask = insertCeQueue(branch);
  727. insertCeTaskCharacteristics(branchTask.getUuid(), 1);
  728. CeQueueDto anotherBranchTask = insertCeQueue(anotherBranch);
  729. insertCeTaskCharacteristics(anotherBranchTask.getUuid(), 5);
  730. CeQueueDto anotherProjectTask = insertCeQueue(anotherProject);
  731. insertCeTaskCharacteristics(anotherProjectTask.getUuid(), 2);
  732. insertCeTaskCharacteristics("non existing task", 5);
  733. dbSession.commit();
  734. underTest.deleteProject(dbSession, branch.uuid());
  735. dbSession.commit();
  736. assertThat(uuidsIn("ce_queue")).containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid());
  737. assertThat(taskUuidsIn("ce_task_characteristics"))
  738. .containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid(), "non existing task");
  739. underTest.deleteProject(dbSession, project.uuid());
  740. dbSession.commit();
  741. assertThat(uuidsIn("ce_queue")).containsOnly(anotherProjectTask.getUuid());
  742. assertThat(taskUuidsIn("ce_task_characteristics")).containsOnly(anotherProjectTask.getUuid(), "non existing task");
  743. }
  744. @Test
  745. public void delete_row_in_ce_task_message_referring_to_a_row_in_ce_queue_when_deleting_project() {
  746. ComponentDto project = ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization());
  747. ComponentDto branch = ComponentTesting.newProjectBranch(project, newBranchDto(project));
  748. ComponentDto anotherBranch = ComponentTesting.newProjectBranch(project, newBranchDto(project));
  749. ComponentDto anotherProject = ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization());
  750. dbClient.componentDao().insert(dbSession, project, branch, anotherBranch, anotherProject);
  751. CeQueueDto projectTask = insertCeQueue(project);
  752. insertCeTaskMessages(projectTask.getUuid(), 3);
  753. CeQueueDto branchTask = insertCeQueue(branch);
  754. insertCeTaskMessages(branchTask.getUuid(), 1);
  755. CeQueueDto anotherBranchTask = insertCeQueue(anotherBranch);
  756. insertCeTaskMessages(anotherBranchTask.getUuid(), 5);
  757. CeQueueDto anotherProjectTask = insertCeQueue(anotherProject);
  758. insertCeTaskMessages(anotherProjectTask.getUuid(), 2);
  759. insertCeTaskMessages("non existing task", 5);
  760. dbSession.commit();
  761. underTest.deleteProject(dbSession, branch.uuid());
  762. dbSession.commit();
  763. assertThat(uuidsIn("ce_queue")).containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid());
  764. assertThat(taskUuidsIn("ce_task_message"))
  765. .containsOnly(projectTask.getUuid(), anotherBranchTask.getUuid(), anotherProjectTask.getUuid(), "non existing task");
  766. underTest.deleteProject(dbSession, project.uuid());
  767. dbSession.commit();
  768. assertThat(uuidsIn("ce_queue")).containsOnly(anotherProjectTask.getUuid());
  769. assertThat(taskUuidsIn("ce_task_message")).containsOnly(anotherProjectTask.getUuid(), "non existing task");
  770. }
  771. @Test
  772. public void delete_row_in_events_and_event_component_changes_when_deleting_project() {
  773. ComponentDto project = ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization());
  774. ComponentDto branch = ComponentTesting.newProjectBranch(project, newBranchDto(project));
  775. ComponentDto anotherBranch = ComponentTesting.newProjectBranch(project, newBranchDto(project));
  776. ComponentDto anotherProject = ComponentTesting.newPrivateProjectDto(db.getDefaultOrganization());
  777. dbClient.componentDao().insert(dbSession, project, branch, anotherBranch, anotherProject);
  778. SnapshotDto projectAnalysis1 = db.components().insertSnapshot(project);
  779. SnapshotDto projectAnalysis2 = db.components().insertSnapshot(project);
  780. EventDto projectEvent1 = db.events().insertEvent(projectAnalysis1);
  781. EventDto projectEvent2 = db.events().insertEvent(projectAnalysis2);
  782. EventDto projectEvent3 = db.events().insertEvent(db.components().insertSnapshot(project));
  783. SnapshotDto branchAnalysis1 = db.components().insertSnapshot(branch);
  784. SnapshotDto branchAnalysis2 = db.components().insertSnapshot(branch);
  785. EventDto branchEvent1 = db.events().insertEvent(branchAnalysis1);
  786. EventDto branchEvent2 = db.events().insertEvent(branchAnalysis2);
  787. SnapshotDto anotherBranchAnalysis = db.components().insertSnapshot(anotherBranch);
  788. EventDto anotherBranchEvent = db.events().insertEvent(anotherBranchAnalysis);
  789. SnapshotDto anotherProjectAnalysis = db.components().insertSnapshot(anotherProject);
  790. EventDto anotherProjectEvent = db.events().insertEvent(anotherProjectAnalysis);
  791. ComponentDto referencedProjectA = db.components().insertPublicProject();
  792. ComponentDto referencedProjectB = db.components().insertPublicProject();
  793. db.events().insertEventComponentChanges(projectEvent1, projectAnalysis1, randomChangeCategory(), referencedProjectA, null);
  794. db.events().insertEventComponentChanges(projectEvent1, projectAnalysis1, randomChangeCategory(), referencedProjectB, null);
  795. BranchDto branchProjectA = newBranchDto(referencedProjectA);
  796. ComponentDto cptBranchProjectA = ComponentTesting.newProjectBranch(referencedProjectA, branchProjectA);
  797. db.events().insertEventComponentChanges(projectEvent2, projectAnalysis2, randomChangeCategory(), cptBranchProjectA, branchProjectA);
  798. // note: projectEvent3 has no component change
  799. db.events().insertEventComponentChanges(branchEvent1, branchAnalysis1, randomChangeCategory(), referencedProjectB, null);
  800. db.events().insertEventComponentChanges(branchEvent2, branchAnalysis2, randomChangeCategory(), cptBranchProjectA, branchProjectA);
  801. db.events().insertEventComponentChanges(anotherBranchEvent, anotherBranchAnalysis, randomChangeCategory(), referencedProjectB, null);
  802. db.events().insertEventComponentChanges(anotherProjectEvent, anotherProjectAnalysis, randomChangeCategory(), referencedProjectB, null);
  803. // deleting referenced project does not delete any data
  804. underTest.deleteProject(dbSession, referencedProjectA.uuid());
  805. assertThat(db.countRowsOfTable("event_component_changes"))
  806. .isEqualTo(7);
  807. assertThat(db.countRowsOfTable("events"))
  808. .isEqualTo(7);
  809. underTest.deleteProject(dbSession, branch.uuid());
  810. assertThat(uuidsIn("event_component_changes", "event_component_uuid"))
  811. .containsOnly(project.uuid(), anotherBranch.uuid(), anotherProject.uuid());
  812. assertThat(db.countRowsOfTable("event_component_changes"))
  813. .isEqualTo(5);
  814. assertThat(uuidsIn("events"))
  815. .containsOnly(projectEvent1.getUuid(), projectEvent2.getUuid(), projectEvent3.getUuid(), anotherBranchEvent.getUuid(), anotherProjectEvent.getUuid());
  816. underTest.deleteProject(dbSession, project.uuid());
  817. assertThat(uuidsIn("event_component_changes", "event_component_uuid"))
  818. .containsOnly(anotherBranch.uuid(), anotherProject.uuid());
  819. assertThat(db.countRowsOfTable("event_component_changes"))
  820. .isEqualTo(2);
  821. assertThat(uuidsIn("events"))
  822. .containsOnly(anotherBranchEvent.getUuid(), anotherProjectEvent.getUuid());
  823. }
  824. private static EventComponentChangeDto.ChangeCategory randomChangeCategory() {
  825. return EventComponentChangeDto.ChangeCategory.values()[new Random().nextInt(EventComponentChangeDto.ChangeCategory.values().length)];
  826. }
  827. private ComponentDto insertProjectWithBranchAndRelatedData() {
  828. RuleDefinitionDto rule = db.rules().insert();
  829. ComponentDto project = db.components().insertMainBranch();
  830. ComponentDto branch = db.components().insertProjectBranch(project);
  831. ComponentDto module = db.components().insertComponent(newModuleDto(branch));
  832. ComponentDto subModule = db.components().insertComponent(newModuleDto(module));
  833. ComponentDto file = db.components().insertComponent(newFileDto(subModule));
  834. db.issues().insert(rule, branch, file);
  835. db.issues().insert(rule, branch, subModule);
  836. db.issues().insert(rule, branch, module);
  837. return project;
  838. }
  839. @Test
  840. public void delete_branch_content_when_deleting_project() {
  841. ComponentDto anotherLivingProject = insertProjectWithBranchAndRelatedData();
  842. int projectEntryCount = db.countRowsOfTable("projects");
  843. int issueCount = db.countRowsOfTable("issues");
  844. int branchCount = db.countRowsOfTable("project_branches");
  845. ComponentDto projectToDelete = insertProjectWithBranchAndRelatedData();
  846. assertThat(db.countRowsOfTable("projects")).isGreaterThan(projectEntryCount);
  847. assertThat(db.countRowsOfTable("issues")).isGreaterThan(issueCount);
  848. assertThat(db.countRowsOfTable("project_branches")).isGreaterThan(branchCount);
  849. underTest.deleteProject(dbSession, projectToDelete.uuid());
  850. dbSession.commit();
  851. assertThat(db.countRowsOfTable("projects")).isEqualTo(projectEntryCount);
  852. assertThat(db.countRowsOfTable("issues")).isEqualTo(issueCount);
  853. assertThat(db.countRowsOfTable("project_branches")).isEqualTo(branchCount);
  854. }
  855. @Test
  856. public void delete_view_and_child() {
  857. ComponentDto project = db.components().insertPrivateProject();
  858. ComponentDto view = db.components().insertView();
  859. ComponentDto subView = db.components().insertComponent(newSubView(view));
  860. ComponentDto projectCopy = db.components().insertComponent(newProjectCopy(project, subView));
  861. ComponentDto otherView = db.components().insertView();
  862. ComponentDto otherSubView = db.components().insertComponent(newSubView(otherView));
  863. ComponentDto otherProjectCopy = db.components().insertComponent(newProjectCopy(project, otherSubView));
  864. underTest.deleteProject(dbSession, view.uuid());
  865. dbSession.commit();
  866. assertThat(uuidsIn("projects"))
  867. .containsOnly(project.uuid(), otherView.uuid(), otherSubView.uuid(), otherProjectCopy.uuid());
  868. }
  869. @Test
  870. public void deleteProject_fails_with_IAE_if_specified_component_is_module() {
  871. ComponentDto privateProject = db.components().insertPrivateProject();
  872. ComponentDto module = db.components().insertComponent(ComponentTesting.newModuleDto(privateProject));
  873. expectedException.expect(IllegalArgumentException.class);
  874. expectedException.expectMessage("Couldn't find root component with uuid " + module.uuid());
  875. underTest.deleteProject(dbSession, module.uuid());
  876. }
  877. @Test
  878. public void deleteProject_fails_with_IAE_if_specified_component_is_directory() {
  879. ComponentDto privateProject = db.components().insertPrivateProject();
  880. ComponentDto directory = db.components().insertComponent(newDirectory(privateProject, "A/B"));
  881. expectedException.expect(IllegalArgumentException.class);
  882. expectedException.expectMessage("Couldn't find root component with uuid " + directory.uuid());
  883. underTest.deleteProject(dbSession, directory.uuid());
  884. }
  885. @Test
  886. public void deleteProject_fails_with_IAE_if_specified_component_is_file() {
  887. ComponentDto privateProject = db.components().insertPrivateProject();
  888. ComponentDto file = db.components().insertComponent(newFileDto(privateProject));
  889. expectedException.expect(IllegalArgumentException.class);
  890. expectedException.expectMessage("Couldn't find root component with uuid " + file.uuid());
  891. underTest.deleteProject(dbSession, file.uuid());
  892. }
  893. @Test
  894. public void deleteProject_fails_with_IAE_if_specified_component_is_subview() {
  895. ComponentDto view = db.components().insertView();
  896. ComponentDto subview = db.components().insertComponent(newSubView(view));
  897. expectedException.expect(IllegalArgumentException.class);
  898. expectedException.expectMessage("Couldn't find root component with uuid " + subview.uuid());
  899. underTest.deleteProject(dbSession, subview.uuid());
  900. }
  901. @Test
  902. public void should_delete_old_closed_issues() {
  903. RuleDefinitionDto rule = db.rules().insert();
  904. ComponentDto project = db.components().insertMainBranch();
  905. ComponentDto module = db.components().insertComponent(newModuleDto(project));
  906. ComponentDto file = db.components().insertComponent(newFileDto(module));
  907. IssueDto oldClosed = db.issues().insert(rule, project, file, issue -> {
  908. issue.setStatus("CLOSED");
  909. issue.setIssueCloseDate(DateUtils.addDays(new Date(), -31));
  910. });
  911. IssueDto notOldEnoughClosed = db.issues().insert(rule, project, file, issue -> {
  912. issue.setStatus("CLOSED");
  913. issue.setIssueCloseDate(new Date());
  914. });
  915. IssueDto notClosed = db.issues().insert(rule, project, file);
  916. when(system2.now()).thenReturn(new Date().getTime());
  917. underTest.purge(dbSession, newConfigurationWith30Days(system2, project.uuid(), project.uuid()), PurgeListener.EMPTY, new PurgeProfiler());
  918. dbSession.commit();
  919. // old closed got deleted
  920. assertThat(db.getDbClient().issueDao().selectByKey(dbSession, oldClosed.getKey())).isEmpty();
  921. // others remain
  922. assertThat(db.countRowsOfTable("issues")).isEqualTo(2);
  923. assertThat(db.getDbClient().issueDao().selectByKey(dbSession, notOldEnoughClosed.getKey())).isNotEmpty();
  924. assertThat(db.getDbClient().issueDao().selectByKey(dbSession, notClosed.getKey())).isNotEmpty();
  925. }
  926. @Test
  927. public void delete_disabled_components_without_issues() {
  928. ComponentDto project = db.components().insertMainBranch(p -> p.setEnabled(true));
  929. ComponentDto enabledFileWithIssues = db.components().insertComponent(newFileDto(project).setEnabled(true));
  930. ComponentDto disabledFileWithIssues = db.components().insertComponent(newFileDto(project).setEnabled(false));
  931. ComponentDto enabledFileWithoutIssues = db.components().insertComponent(newFileDto(project).setEnabled(true));
  932. ComponentDto disabledFileWithoutIssues = db.components().insertComponent(newFileDto(project).setEnabled(false));
  933. RuleDefinitionDto rule = db.rules().insert();
  934. IssueDto closed1 = db.issues().insert(rule, project, enabledFileWithIssues, issue -> {
  935. issue.setStatus("CLOSED");
  936. issue.setResolution(Issue.RESOLUTION_FIXED);
  937. issue.setIssueCloseDate(new Date());
  938. });
  939. IssueDto closed2 = db.issues().insert(rule, project, disabledFileWithIssues, issue -> {
  940. issue.setStatus("CLOSED");
  941. issue.setResolution(Issue.RESOLUTION_FIXED);
  942. issue.setIssueCloseDate(new Date());
  943. });
  944. PurgeListener purgeListener = mock(PurgeListener.class);
  945. Set<String> disabledComponentUuids = ImmutableSet.of(disabledFileWithIssues.uuid(), disabledFileWithoutIssues.uuid());
  946. underTest.purge(dbSession,
  947. newConfigurationWith30Days(System2.INSTANCE, project.uuid(), project.uuid(), disabledComponentUuids),
  948. purgeListener, new PurgeProfiler());
  949. assertThat(db.getDbClient().componentDao().selectByProjectUuid(project.uuid(), dbSession))
  950. .extracting("uuid")
  951. .containsOnly(project.uuid(), enabledFileWithIssues.uuid(), disabledFileWithIssues.uuid(),
  952. enabledFileWithoutIssues.uuid());
  953. verify(purgeListener).onComponentsDisabling(project.uuid(), disabledComponentUuids);
  954. }
  955. @Test
  956. public void delete_ce_analysis_older_than_180_and_scanner_context_older_than_40_days_of_specified_project_when_purging_project() {
  957. LocalDateTime now = LocalDateTime.now();
  958. ComponentDto project1 = db.components().insertPublicProject();
  959. Consumer<CeQueueDto> belongsToProject1 = t -> t.setMainComponentUuid(project1.uuid()).setComponentUuid(project1.uuid());
  960. ComponentDto project2 = db.components().insertPublicProject();
  961. Consumer<CeQueueDto> belongsToProject2 = t -> t.setMainComponentUuid(project2.uuid()).setComponentUuid(project2.uuid());
  962. insertCeActivityAndChildDataWithDate("VERY_OLD_1", now.minusDays(180).minusMonths(10), belongsToProject1);
  963. insertCeActivityAndChildDataWithDate("JUST_OLD_ENOUGH_1", now.minusDays(180).minusDays(1), belongsToProject1);
  964. insertCeActivityAndChildDataWithDate("NOT_OLD_ENOUGH_1", now.minusDays(180), belongsToProject1);
  965. insertCeActivityAndChildDataWithDate("RECENT_1", now.minusDays(1), belongsToProject1);
  966. insertCeActivityAndChildDataWithDate("VERY_OLD_2", now.minusDays(180).minusMonths(10), belongsToProject2);
  967. insertCeActivityAndChildDataWithDate("JUST_OLD_ENOUGH_2", now.minusDays(180).minusDays(1), belongsToProject2);
  968. insertCeActivityAndChildDataWithDate("NOT_OLD_ENOUGH_2", now.minusDays(180), belongsToProject2);
  969. insertCeActivityAndChildDataWithDate("RECENT_2", now.minusDays(1), belongsToProject2);
  970. when(system2.now()).thenReturn(now.toInstant(ZoneOffset.UTC).toEpochMilli());
  971. underTest.purge(db.getSession(), newConfigurationWith30Days(System2.INSTANCE, project1.uuid(), project1.uuid()),
  972. PurgeListener.EMPTY, new PurgeProfiler());
  973. assertThat(selectActivity("VERY_OLD_1")).isEmpty();
  974. assertThat(selectTaskInput("VERY_OLD_1")).isEmpty();
  975. assertThat(selectTaskCharacteristic("VERY_OLD_1")).hasSize(0);
  976. assertThat(scannerContextExists("VERY_OLD_1")).isFalse();
  977. assertThat(selectActivity("VERY_OLD_2")).isNotEmpty();
  978. assertThat(selectTaskInput("VERY_OLD_2")).isNotEmpty();
  979. assertThat(selectTaskCharacteristic("VERY_OLD_2")).hasSize(1);
  980. assertThat(scannerContextExists("VERY_OLD_2")).isTrue();
  981. assertThat(selectActivity("JUST_OLD_ENOUGH_1")).isEmpty();
  982. assertThat(selectTaskInput("JUST_OLD_ENOUGH_1")).isEmpty();
  983. assertThat(selectTaskCharacteristic("JUST_OLD_ENOUGH_1")).hasSize(0);
  984. assertThat(scannerContextExists("JUST_OLD_ENOUGH_1")).isFalse();
  985. assertThat(selectActivity("JUST_OLD_ENOUGH_2")).isNotEmpty();
  986. assertThat(selectTaskInput("JUST_OLD_ENOUGH_2")).isNotEmpty();
  987. assertThat(selectTaskCharacteristic("JUST_OLD_ENOUGH_2")).hasSize(1);
  988. assertThat(scannerContextExists("JUST_OLD_ENOUGH_2")).isTrue();
  989. assertThat(selectActivity("NOT_OLD_ENOUGH_1")).isNotEmpty();
  990. assertThat(selectTaskInput("NOT_OLD_ENOUGH_1")).isNotEmpty();
  991. assertThat(selectTaskCharacteristic("NOT_OLD_ENOUGH_1")).hasSize(1);
  992. assertThat(scannerContextExists("NOT_OLD_ENOUGH_1")).isFalse(); // because more than 4 weeks old
  993. assertThat(selectActivity("NOT_OLD_ENOUGH_2")).isNotEmpty();
  994. assertThat(selectTaskInput("NOT_OLD_ENOUGH_2")).isNotEmpty();
  995. assertThat(selectTaskCharacteristic("NOT_OLD_ENOUGH_2")).hasSize(1);
  996. assertThat(scannerContextExists("NOT_OLD_ENOUGH_2")).isTrue();
  997. assertThat(selectActivity("RECENT_1")).isNotEmpty();
  998. assertThat(selectTaskInput("RECENT_1")).isNotEmpty();
  999. assertThat(selectTaskCharacteristic("RECENT_1")).hasSize(1);
  1000. assertThat(scannerContextExists("RECENT_1")).isTrue();
  1001. assertThat(selectActivity("RECENT_2")).isNotEmpty();
  1002. assertThat(selectTaskInput("RECENT_2")).isNotEmpty();
  1003. assertThat(selectTaskCharacteristic("RECENT_2")).hasSize(1);
  1004. assertThat(scannerContextExists("RECENT_2")).isTrue();
  1005. }
  1006. @Test
  1007. public void delete_ce_analysis_older_than_180_and_scanner_context_older_than_40_days_of_project_and_branches_when_purging_project() {
  1008. LocalDateTime now = LocalDateTime.now();
  1009. ComponentDto project1 = db.components().insertMainBranch();
  1010. ComponentDto branch1 = db.components().insertProjectBranch(project1, b -> b.setExcludeFromPurge(true));
  1011. Consumer<CeQueueDto> belongsToProject1 = t -> t.setMainComponentUuid(project1.uuid()).setComponentUuid(project1.uuid());
  1012. Consumer<CeQueueDto> belongsToBranch1 = t -> t.setMainComponentUuid(project1.uuid()).setComponentUuid(branch1.uuid());
  1013. insertCeActivityAndChildDataWithDate("VERY_OLD_1", now.minusDays(180).minusMonths(10), belongsToProject1);
  1014. insertCeActivityAndChildDataWithDate("JUST_OLD_ENOUGH_1", now.minusDays(180).minusDays(1), belongsToProject1);
  1015. insertCeActivityAndChildDataWithDate("NOT_OLD_ENOUGH_1", now.minusDays(180), belongsToProject1);
  1016. insertCeActivityAndChildDataWithDate("RECENT_1", now.minusDays(1), belongsToProject1);
  1017. insertCeActivityAndChildDataWithDate("VERY_OLD_2", now.minusDays(180).minusMonths(10), belongsToBranch1);
  1018. insertCeActivityAndChildDataWithDate("JUST_OLD_ENOUGH_2", now.minusDays(180).minusDays(1), belongsToBranch1);
  1019. insertCeActivityAndChildDataWithDate("NOT_OLD_ENOUGH_2", now.minusDays(180), belongsToBranch1);
  1020. insertCeActivityAndChildDataWithDate("RECENT_2", now.minusDays(1), belongsToBranch1);
  1021. when(system2.now()).thenReturn(now.toInstant(ZoneOffset.UTC).toEpochMilli());
  1022. underTest.purge(db.getSession(), newConfigurationWith30Days(System2.INSTANCE, project1.uuid(), project1.uuid()),
  1023. PurgeListener.EMPTY, new PurgeProfiler());
  1024. assertThat(selectActivity("VERY_OLD_1")).isEmpty();
  1025. assertThat(selectTaskInput("VERY_OLD_1")).isEmpty();
  1026. assertThat(selectTaskCharacteristic("VERY_OLD_1")).hasSize(0);
  1027. assertThat(scannerContextExists("VERY_OLD_1")).isFalse();
  1028. assertThat(selectActivity("VERY_OLD_2")).isEmpty();
  1029. assertThat(selectTaskInput("VERY_OLD_2")).isEmpty();
  1030. assertThat(selectTaskCharacteristic("VERY_OLD_2")).isEmpty();
  1031. assertThat(scannerContextExists("VERY_OLD_2")).isFalse();
  1032. assertThat(selectActivity("JUST_OLD_ENOUGH_1")).isEmpty();
  1033. assertThat(selectTaskInput("JUST_OLD_ENOUGH_1")).isEmpty();
  1034. assertThat(selectTaskCharacteristic("JUST_OLD_ENOUGH_1")).hasSize(0);
  1035. assertThat(scannerContextExists("JUST_OLD_ENOUGH_1")).isFalse();
  1036. assertThat(selectActivity("JUST_OLD_ENOUGH_2")).isEmpty();
  1037. assertThat(selectTaskInput("JUST_OLD_ENOUGH_2")).isEmpty();
  1038. assertThat(selectTaskCharacteristic("JUST_OLD_ENOUGH_2")).isEmpty();
  1039. assertThat(scannerContextExists("JUST_OLD_ENOUGH_2")).isFalse();
  1040. assertThat(selectActivity("NOT_OLD_ENOUGH_1")).isNotEmpty();
  1041. assertThat(selectTaskInput("NOT_OLD_ENOUGH_1")).isNotEmpty();
  1042. assertThat(selectTaskCharacteristic("NOT_OLD_ENOUGH_1")).hasSize(1);
  1043. assertThat(scannerContextExists("NOT_OLD_ENOUGH_1")).isFalse(); // because more than 4 weeks old
  1044. assertThat(selectActivity("NOT_OLD_ENOUGH_2")).isNotEmpty();
  1045. assertThat(selectTaskInput("NOT_OLD_ENOUGH_2")).isNotEmpty();
  1046. assertThat(selectTaskCharacteristic("NOT_OLD_ENOUGH_2")).hasSize(1);
  1047. assertThat(scannerContextExists("NOT_OLD_ENOUGH_2")).isFalse(); // because more than 4 weeks old
  1048. assertThat(selectActivity("RECENT_1")).isNotEmpty();
  1049. assertThat(selectTaskInput("RECENT_1")).isNotEmpty();
  1050. assertThat(selectTaskCharacteristic("RECENT_1")).hasSize(1);
  1051. assertThat(scannerContextExists("RECENT_1")).isTrue();
  1052. assertThat(selectActivity("RECENT_2")).isNotEmpty();
  1053. assertThat(selectTaskInput("RECENT_2")).isNotEmpty();
  1054. assertThat(selectTaskCharacteristic("RECENT_2")).hasSize(1);
  1055. assertThat(scannerContextExists("RECENT_2")).isTrue();
  1056. }
  1057. @Test
  1058. public void delete_ce_analysis_of_branch_older_than_180_and_scanner_context_older_than_40_days_when_purging_branch() {
  1059. LocalDateTime now = LocalDateTime.now();
  1060. ComponentDto project1 = db.components().insertPublicProject();
  1061. ComponentDto branch1 = db.components().insertProjectBranch(project1);
  1062. Consumer<CeQueueDto> belongsToProject1 = t -> t.setMainComponentUuid(project1.uuid()).setComponentUuid(project1.uuid());
  1063. Consumer<CeQueueDto> belongsToBranch1 = t -> t.setMainComponentUuid(project1.uuid()).setComponentUuid(branch1.uuid());
  1064. insertCeActivityAndChildDataWithDate("VERY_OLD_1", now.minusDays(180).minusMonths(10), belongsToProject1);
  1065. insertCeActivityAndChildDataWithDate("JUST_OLD_ENOUGH_1", now.minusDays(180).minusDays(1), belongsToProject1);
  1066. insertCeActivityAndChildDataWithDate("NOT_OLD_ENOUGH_1", now.minusDays(180), belongsToProject1);
  1067. insertCeActivityAndChildDataWithDate("RECENT_1", now.minusDays(1), belongsToProject1);
  1068. insertCeActivityAndChildDataWithDate("VERY_OLD_2", now.minusDays(180).minusMonths(10), belongsToBranch1);
  1069. insertCeActivityAndChildDataWithDate("JUST_OLD_ENOUGH_2", now.minusDays(180).minusDays(1), belongsToBranch1);
  1070. insertCeActivityAndChildDataWithDate("NOT_OLD_ENOUGH_2", now.minusDays(180), belongsToBranch1);
  1071. insertCeActivityAndChildDataWithDate("RECENT_2", now.minusDays(1), belongsToBranch1);
  1072. when(system2.now()).thenReturn(now.toInstant(ZoneOffset.UTC).toEpochMilli());
  1073. underTest.purge(db.getSession(), newConfigurationWith30Days(System2.INSTANCE, branch1.uuid(), branch1.uuid()),
  1074. PurgeListener.EMPTY, new PurgeProfiler());
  1075. assertThat(selectActivity("VERY_OLD_1")).isNotEmpty();
  1076. assertThat(selectTaskInput("VERY_OLD_1")).isNotEmpty();
  1077. assertThat(selectTaskCharacteristic("VERY_OLD_1")).hasSize(1);
  1078. assertThat(scannerContextExists("VERY_OLD_1")).isTrue();
  1079. assertThat(selectActivity("VERY_OLD_2")).isEmpty();
  1080. assertThat(selectTaskInput("VERY_OLD_2")).isEmpty();
  1081. assertThat(selectTaskCharacteristic("VERY_OLD_2")).isEmpty();
  1082. assertThat(scannerContextExists("VERY_OLD_2")).isFalse();
  1083. assertThat(selectActivity("JUST_OLD_ENOUGH_1")).isNotEmpty();
  1084. assertThat(selectTaskInput("JUST_OLD_ENOUGH_1")).isNotEmpty();
  1085. assertThat(selectTaskCharacteristic("JUST_OLD_ENOUGH_1")).hasSize(1);
  1086. assertThat(scannerContextExists("JUST_OLD_ENOUGH_1")).isTrue();
  1087. assertThat(selectActivity("JUST_OLD_ENOUGH_2")).isEmpty();
  1088. assertThat(selectTaskInput("JUST_OLD_ENOUGH_2")).isEmpty();
  1089. assertThat(selectTaskCharacteristic("JUST_OLD_ENOUGH_2")).isEmpty();
  1090. assertThat(scannerContextExists("JUST_OLD_ENOUGH_2")).isFalse();
  1091. assertThat(selectActivity("NOT_OLD_ENOUGH_1")).isNotEmpty();
  1092. assertThat(selectTaskInput("NOT_OLD_ENOUGH_1")).isNotEmpty();
  1093. assertThat(selectTaskCharacteristic("NOT_OLD_ENOUGH_1")).hasSize(1);
  1094. assertThat(scannerContextExists("NOT_OLD_ENOUGH_1")).isTrue();
  1095. assertThat(selectActivity("NOT_OLD_ENOUGH_2")).isNotEmpty();
  1096. assertThat(selectTaskInput("NOT_OLD_ENOUGH_2")).isNotEmpty();
  1097. assertThat(selectTaskCharacteristic("NOT_OLD_ENOUGH_2")).hasSize(1);
  1098. assertThat(scannerContextExists("NOT_OLD_ENOUGH_2")).isFalse(); // because more than 4 weeks old
  1099. assertThat(selectActivity("RECENT_1")).isNotEmpty();
  1100. assertThat(selectTaskInput("RECENT_1")).isNotEmpty();
  1101. assertThat(selectTaskCharacteristic("RECENT_1")).hasSize(1);
  1102. assertThat(scannerContextExists("RECENT_1")).isTrue();
  1103. assertThat(selectActivity("RECENT_2")).isNotEmpty();
  1104. assertThat(selectTaskInput("RECENT_2")).isNotEmpty();
  1105. assertThat(selectTaskCharacteristic("RECENT_2")).hasSize(1);
  1106. assertThat(scannerContextExists("RECENT_2")).isTrue();
  1107. }
  1108. @Test
  1109. public void deleteProject_deletes_webhook_deliveries() {
  1110. ComponentDto project = db.components().insertPublicProject();
  1111. dbClient.webhookDeliveryDao().insert(dbSession, newDto().setComponentUuid(project.uuid()).setUuid("D1").setDurationMs(1000).setWebhookUuid("webhook-uuid"));
  1112. dbClient.webhookDeliveryDao().insert(dbSession, newDto().setComponentUuid("P2").setUuid("D2").setDurationMs(1000).setWebhookUuid("webhook-uuid"));
  1113. underTest.deleteProject(dbSession, project.uuid());
  1114. assertThat(selectAllDeliveryUuids(db, dbSession)).containsOnly("D2");
  1115. }
  1116. @Test
  1117. public void deleteProject_deletes_project_mappings() {
  1118. ComponentDto project = db.components().insertPublicProject();
  1119. dbClient.projectMappingsDao().put(dbSession, "a.key.type", "a.key", project.uuid());
  1120. dbClient.projectMappingsDao().put(dbSession, "a.key.type", "another.key", "D2");
  1121. underTest.deleteProject(dbSession, project.uuid());
  1122. assertThat(dbClient.projectMappingsDao().get(dbSession, "a.key.type", "a.key")).isEmpty();
  1123. assertThat(dbClient.projectMappingsDao().get(dbSession, "a.key.type", "another.key")).isNotEmpty();
  1124. }
  1125. @Test
  1126. public void deleteProject_deletes_project_alm_bindings() {
  1127. ALM alm = ALM.GITHUB;
  1128. String repoId = "123";
  1129. String otherRepoId = repoId + "-foo";
  1130. ComponentDto project = db.components().insertPublicProject();
  1131. ComponentDto otherProject = db.components().insertPublicProject();
  1132. dbClient.projectAlmBindingsDao().insertOrUpdate(dbSession, alm, repoId, project.uuid(), null, "foo");
  1133. dbClient.projectAlmBindingsDao().insertOrUpdate(dbSession, alm, otherRepoId, otherProject.uuid(), null, "bar");
  1134. underTest.deleteProject(dbSession, project.uuid());
  1135. assertThat(dbClient.projectAlmBindingsDao().findProjectKey(dbSession, alm, repoId)).isEmpty();
  1136. assertThat(dbClient.projectAlmBindingsDao().findProjectKey(dbSession, alm, otherRepoId)).isNotEmpty();
  1137. }
  1138. @Test
  1139. public void deleteNonRootComponents_has_no_effect_when_parameter_is_empty() {
  1140. DbSession dbSession = mock(DbSession.class);
  1141. underTest.deleteNonRootComponentsInView(dbSession, Collections.emptyList());
  1142. verifyZeroInteractions(dbSession);
  1143. }
  1144. @Test
  1145. public void deleteNonRootComponents_has_no_effect_when_parameter_contains_only_projects_and_or_views() {
  1146. ComponentDbTester componentDbTester = db.components();
  1147. verifyNoEffect(componentDbTester.insertPrivateProject());
  1148. verifyNoEffect(componentDbTester.insertPublicProject());
  1149. verifyNoEffect(componentDbTester.insertView());
  1150. verifyNoEffect(componentDbTester.insertView(), componentDbTester.insertPrivateProject(), componentDbTester.insertPublicProject());
  1151. }
  1152. @Test
  1153. public void delete_live_measures_when_deleting_project() {
  1154. MetricDto metric = db.measures().insertMetric();
  1155. ComponentDto project1 = db.components().insertPublicProject();
  1156. ComponentDto module1 = db.components().insertComponent(ComponentTesting.newModuleDto(project1));
  1157. db.measures().insertLiveMeasure(project1, metric);
  1158. db.measures().insertLiveMeasure(module1, metric);
  1159. ComponentDto project2 = db.components().insertPublicProject();
  1160. ComponentDto module2 = db.components().insertComponent(ComponentTesting.newModuleDto(project2));
  1161. db.measures().insertLiveMeasure(project2, metric);
  1162. db.measures().insertLiveMeasure(module2, metric);
  1163. underTest.deleteProject(dbSession, project1.uuid());
  1164. assertThat(dbClient.liveMeasureDao().selectByComponentUuidsAndMetricIds(dbSession, asList(project1.uuid(), module1.uuid()), asList(metric.getId()))).isEmpty();
  1165. assertThat(dbClient.liveMeasureDao().selectByComponentUuidsAndMetricIds(dbSession, asList(project2.uuid(), module2.uuid()), asList(metric.getId()))).hasSize(2);
  1166. }
  1167. private void verifyNoEffect(ComponentDto firstRoot, ComponentDto... otherRoots) {
  1168. DbSession dbSession = mock(DbSession.class);
  1169. List<ComponentDto> componentDtos = Stream.concat(Stream.of(firstRoot), Arrays.stream(otherRoots)).collect(Collectors.toList());
  1170. Collections.shuffle(componentDtos); // order of collection must not matter
  1171. underTest.deleteNonRootComponentsInView(dbSession, componentDtos);
  1172. verifyZeroInteractions(dbSession);
  1173. }
  1174. @Test
  1175. public void deleteNonRootComponents_deletes_only_non_root_components_of_a_project_from_table_PROJECTS() {
  1176. ComponentDto project = new Random().nextBoolean() ? db.components().insertPublicProject() : db.components().insertPrivateProject();
  1177. ComponentDto module1 = db.components().insertComponent(ComponentTesting.newModuleDto(project));
  1178. ComponentDto module2 = db.components().insertComponent(ComponentTesting.newModuleDto(module1));
  1179. ComponentDto dir1 = db.components().insertComponent(newDirectory(module1, "A/B"));
  1180. List<ComponentDto> components = asList(
  1181. project,
  1182. module1,
  1183. module2,
  1184. dir1,
  1185. db.components().insertComponent(newDirectory(module2, "A/C")),
  1186. db.components().insertComponent(newFileDto(dir1)),
  1187. db.components().insertComponent(newFileDto(module2)),
  1188. db.components().insertComponent(newFileDto(project)));
  1189. Collections.shuffle(components);
  1190. underTest.deleteNonRootComponentsInView(dbSession, components);
  1191. assertThat(uuidsIn("projects"))
  1192. .containsOnly(project.uuid());
  1193. }
  1194. @Test
  1195. public void deleteNonRootComponents_deletes_only_non_root_components_of_a_view_from_table_PROJECTS() {
  1196. ComponentDto[] projects = {
  1197. db.components().insertPrivateProject(),
  1198. db.components().insertPrivateProject(),
  1199. db.components().insertPrivateProject()
  1200. };
  1201. ComponentDto view = db.components().insertView();
  1202. ComponentDto subview1 = db.components().insertComponent(newSubView(view));
  1203. ComponentDto subview2 = db.components().insertComponent(newSubView(subview1));
  1204. List<ComponentDto> components = asList(
  1205. view,
  1206. subview1,
  1207. subview2,
  1208. db.components().insertComponent(newProjectCopy("a", projects[0], view)),
  1209. db.components().insertComponent(newProjectCopy("b", projects[1], subview1)),
  1210. db.components().insertComponent(newProjectCopy("c", projects[2], subview2)));
  1211. Collections.shuffle(components);
  1212. underTest.deleteNonRootComponentsInView(dbSession, components);
  1213. assertThat(uuidsIn("projects"))
  1214. .containsOnly(view.uuid(), projects[0].uuid(), projects[1].uuid(), projects[2].uuid());
  1215. }
  1216. @Test
  1217. public void deleteNonRootComponents_deletes_only_specified_non_root_components_of_a_project_from_table_PROJECTS() {
  1218. ComponentDto project = new Random().nextBoolean() ? db.components().insertPublicProject() : db.components().insertPrivateProject();
  1219. ComponentDto module1 = db.components().insertComponent(ComponentTesting.newModuleDto(project));
  1220. ComponentDto module2 = db.components().insertComponent(ComponentTesting.newModuleDto(module1));
  1221. ComponentDto dir1 = db.components().insertComponent(newDirectory(module1, "A/B"));
  1222. ComponentDto dir2 = db.components().insertComponent(newDirectory(module2, "A/C"));
  1223. ComponentDto file1 = db.components().insertComponent(newFileDto(dir1));
  1224. ComponentDto file2 = db.components().insertComponent(newFileDto(module2));
  1225. ComponentDto file3 = db.components().insertComponent(newFileDto(project));
  1226. underTest.deleteNonRootComponentsInView(dbSession, singletonList(file3));
  1227. assertThat(uuidsIn("projects"))
  1228. .containsOnly(project.uuid(), module1.uuid(), module2.uuid(), dir1.uuid(), dir2.uuid(), file1.uuid(), file2.uuid());
  1229. underTest.deleteNonRootComponentsInView(dbSession, asList(module1, dir2, file1));
  1230. assertThat(uuidsIn("projects"))
  1231. .containsOnly(project.uuid(), module2.uuid(), dir1.uuid(), file2.uuid());
  1232. }
  1233. @Test
  1234. public void deleteNonRootComponents_deletes_only_specified_non_root_components_of_a_view_from_table_PROJECTS() {
  1235. ComponentDto[] projects = {
  1236. db.components().insertPrivateProject(),
  1237. db.components().insertPrivateProject(),
  1238. db.components().insertPrivateProject()
  1239. };
  1240. ComponentDto view = db.components().insertView();
  1241. ComponentDto subview1 = db.components().insertComponent(newSubView(view));
  1242. ComponentDto subview2 = db.components().insertComponent(newSubView(subview1));
  1243. ComponentDto pc1 = db.components().insertComponent(newProjectCopy("a", projects[0], view));
  1244. ComponentDto pc2 = db.components().insertComponent(newProjectCopy("b", projects[1], subview1));
  1245. ComponentDto pc3 = db.components().insertComponent(newProjectCopy("c", projects[2], subview2));
  1246. underTest.deleteNonRootComponentsInView(dbSession, singletonList(pc3));
  1247. assertThat(uuidsIn("projects"))
  1248. .containsOnly(view.uuid(), projects[0].uuid(), projects[1].uuid(), projects[2].uuid(),
  1249. subview1.uuid(), subview2.uuid(), pc1.uuid(), pc2.uuid());
  1250. underTest.deleteNonRootComponentsInView(dbSession, asList(subview1, pc2));
  1251. assertThat(uuidsIn("projects"))
  1252. .containsOnly(view.uuid(), projects[0].uuid(), projects[1].uuid(), projects[2].uuid(), subview2.uuid(), pc1.uuid());
  1253. }
  1254. @Test
  1255. public void deleteNonRootComponents_deletes_measures_of_any_non_root_component_of_a_view() {
  1256. ComponentDto view = db.components().insertView();
  1257. ComponentDto subview = db.components().insertComponent(newSubView(view));
  1258. ComponentDto pc = db.components().insertComponent(newProjectCopy("a", db.components().insertPrivateProject(), view));
  1259. insertMeasureFor(view, subview, pc);
  1260. assertThat(getComponentUuidsOfMeasures()).containsOnly(view.uuid(), subview.uuid(), pc.uuid());
  1261. underTest.deleteNonRootComponentsInView(dbSession, singletonList(pc));
  1262. assertThat(getComponentUuidsOfMeasures())
  1263. .containsOnly(view.uuid(), subview.uuid());
  1264. underTest.deleteNonRootComponentsInView(dbSession, singletonList(subview));
  1265. assertThat(getComponentUuidsOfMeasures())
  1266. .containsOnly(view.uuid());
  1267. }
  1268. @Test
  1269. public void deleteNonRootComponents_deletes_properties_of_subviews_of_a_view() {
  1270. ComponentDto view = db.components().insertView();
  1271. ComponentDto subview1 = db.components().insertComponent(newSubView(view));
  1272. ComponentDto subview2 = db.components().insertComponent(newSubView(subview1));
  1273. ComponentDto subview3 = db.components().insertComponent(newSubView(view));
  1274. ComponentDto pc = db.components().insertComponent(newProjectCopy("a", db.components().insertPrivateProject(), view));
  1275. insertPropertyFor(view, subview1, subview2, subview3, pc);
  1276. assertThat(getResourceIdOfProperties()).containsOnly(view.getId(), subview1.getId(), subview2.getId(), subview3.getId(), pc.getId());
  1277. underTest.deleteNonRootComponentsInView(dbSession, singletonList(subview1));
  1278. assertThat(getResourceIdOfProperties())
  1279. .containsOnly(view.getId(), subview2.getId(), subview3.getId(), pc.getId());
  1280. underTest.deleteNonRootComponentsInView(dbSession, asList(subview2, subview3, pc));
  1281. assertThat(getResourceIdOfProperties())
  1282. .containsOnly(view.getId(), pc.getId());
  1283. }
  1284. @Test
  1285. public void deleteNonRootComponentsInView_deletes_manual_measures_of_subviews_of_a_view() {
  1286. ComponentDto view = db.components().insertView();
  1287. ComponentDto subview1 = db.components().insertComponent(newSubView(view));
  1288. ComponentDto subview2 = db.components().insertComponent(newSubView(subview1));
  1289. ComponentDto subview3 = db.components().insertComponent(newSubView(view));
  1290. ComponentDto pc = db.components().insertComponent(newProjectCopy("a", db.components().insertPrivateProject(), view));
  1291. insertManualMeasureFor(view, subview1, subview2, subview3, pc);
  1292. assertThat(getComponentUuidsOfManualMeasures()).containsOnly(view.uuid(), subview1.uuid(), subview2.uuid(), subview3.uuid(), pc.uuid());
  1293. underTest.deleteNonRootComponentsInView(dbSession, singletonList(subview1));
  1294. assertThat(getComponentUuidsOfManualMeasures())
  1295. .containsOnly(view.uuid(), subview2.uuid(), subview3.uuid(), pc.uuid());
  1296. underTest.deleteNonRootComponentsInView(dbSession, asList(subview2, subview3, pc));
  1297. assertThat(getComponentUuidsOfManualMeasures())
  1298. .containsOnly(view.uuid(), pc.uuid());
  1299. }
  1300. @Test
  1301. public void purgeCeActivities_deletes_activity_older_than_180_days_and_their_scanner_context() {
  1302. LocalDateTime now = LocalDateTime.now();
  1303. insertCeActivityAndChildDataWithDate("VERY_OLD", now.minusDays(180).minusMonths(10));
  1304. insertCeActivityAndChildDataWithDate("JUST_OLD_ENOUGH", now.minusDays(180).minusDays(1));
  1305. insertCeActivityAndChildDataWithDate("NOT_OLD_ENOUGH", now.minusDays(180));
  1306. insertCeActivityAndChildDataWithDate("RECENT", now.minusDays(1));
  1307. when(system2.now()).thenReturn(now.toInstant(ZoneOffset.UTC).toEpochMilli());
  1308. underTest.purgeCeActivities(db.getSession(), new PurgeProfiler());
  1309. assertThat(selectActivity("VERY_OLD")).isEmpty();
  1310. assertThat(selectTaskInput("VERY_OLD")).isEmpty();
  1311. assertThat(selectTaskCharacteristic("VERY_OLD")).hasSize(0);
  1312. assertThat(scannerContextExists("VERY_OLD")).isFalse();
  1313. assertThat(selectActivity("JUST_OLD_ENOUGH")).isEmpty();
  1314. assertThat(selectTaskInput("JUST_OLD_ENOUGH")).isEmpty();
  1315. assertThat(selectTaskCharacteristic("JUST_OLD_ENOUGH")).hasSize(0);
  1316. assertThat(scannerContextExists("JUST_OLD_ENOUGH")).isFalse();
  1317. assertThat(selectActivity("NOT_OLD_ENOUGH")).isNotEmpty();
  1318. assertThat(selectTaskInput("NOT_OLD_ENOUGH")).isNotEmpty();
  1319. assertThat(selectTaskCharacteristic("NOT_OLD_ENOUGH")).hasSize(1);
  1320. assertThat(scannerContextExists("NOT_OLD_ENOUGH")).isTrue();
  1321. assertThat(selectActivity("RECENT")).isNotEmpty();
  1322. assertThat(selectTaskInput("RECENT")).isNotEmpty();
  1323. assertThat(selectTaskCharacteristic("RECENT")).hasSize(1);
  1324. assertThat(scannerContextExists("RECENT")).isTrue();
  1325. }
  1326. @Test
  1327. public void purgeCeScannerContexts_deletes_ce_scanner_context_older_than_28_days() {
  1328. LocalDateTime now = LocalDateTime.now();
  1329. insertCeActivityAndChildDataWithDate("VERY_OLD", now.minusDays(28).minusMonths(12));
  1330. insertCeActivityAndChildDataWithDate("JUST_OLD_ENOUGH", now.minusDays(28).minusDays(1));
  1331. insertCeActivityAndChildDataWithDate("NOT_OLD_ENOUGH", now.minusDays(28));
  1332. insertCeActivityAndChildDataWithDate("RECENT", now.minusDays(1));
  1333. when(system2.now()).thenReturn(now.toInstant(ZoneOffset.UTC).toEpochMilli());
  1334. underTest.purgeCeScannerContexts(db.getSession(), new PurgeProfiler());
  1335. assertThat(scannerContextExists("VERY_OLD")).isFalse();
  1336. assertThat(scannerContextExists("JUST_OLD_ENOUGH")).isFalse();
  1337. assertThat(scannerContextExists("NOT_OLD_ENOUGH")).isTrue();
  1338. assertThat(scannerContextExists("RECENT")).isTrue();
  1339. }
  1340. private Optional<CeActivityDto> selectActivity(String taskUuid) {
  1341. return db.getDbClient().ceActivityDao().selectByUuid(db.getSession(), taskUuid);
  1342. }
  1343. private List<CeTaskCharacteristicDto> selectTaskCharacteristic(String taskUuid) {
  1344. return db.getDbClient().ceTaskCharacteristicsDao().selectByTaskUuids(db.getSession(), Collections.singletonList(taskUuid));
  1345. }
  1346. private Optional<CeTaskInputDao.DataStream> selectTaskInput(String taskUuid) {
  1347. return db.getDbClient().ceTaskInputDao().selectData(db.getSession(), taskUuid);
  1348. }
  1349. private boolean scannerContextExists(String uuid) {
  1350. return db.countSql("select count(1) from ce_scanner_context where task_uuid = '" + uuid + "'") == 1;
  1351. }
  1352. @SafeVarargs
  1353. private final void insertCeActivityAndChildDataWithDate(String ceActivityUuid, LocalDateTime dateTime,
  1354. Consumer<CeQueueDto>... queueDtoConsumers) {
  1355. long date = dateTime.toInstant(UTC).toEpochMilli();
  1356. CeQueueDto queueDto = new CeQueueDto();
  1357. queueDto.setUuid(ceActivityUuid);
  1358. queueDto.setTaskType(CeTaskTypes.REPORT);
  1359. Arrays.stream(queueDtoConsumers).forEach(t -> t.accept(queueDto));
  1360. CeActivityDto dto = new CeActivityDto(queueDto);
  1361. dto.setStatus(CeActivityDto.Status.SUCCESS);
  1362. when(system2.now()).thenReturn(date);
  1363. insertCeTaskInput(dto.getUuid());
  1364. insertCeTaskCharacteristics(dto.getUuid(), 1);
  1365. insertCeScannerContext(dto.getUuid());
  1366. insertCeTaskMessages(dto.getUuid(), 2);
  1367. db.getDbClient().ceActivityDao().insert(db.getSession(), dto);
  1368. db.getSession().commit();
  1369. }
  1370. private void insertManualMeasureFor(ComponentDto... componentDtos) {
  1371. Arrays.stream(componentDtos).forEach(componentDto -> dbClient.customMeasureDao().insert(dbSession, new CustomMeasureDto()
  1372. .setComponentUuid(componentDto.uuid())
  1373. .setMetricId(new Random().nextInt())));
  1374. dbSession.commit();
  1375. }
  1376. private Stream<String> getComponentUuidsOfManualMeasures() {
  1377. return db.select("select component_uuid as \"COMPONENT_UUID\" from manual_measures").stream()
  1378. .map(row -> (String) row.get("COMPONENT_UUID"));
  1379. }
  1380. private Stream<Long> getResourceIdOfProperties() {
  1381. return db.select("select resource_id as \"ID\" from properties").stream()
  1382. .map(row -> (Long) row.get("ID"));
  1383. }
  1384. private void insertPropertyFor(ComponentDto... components) {
  1385. Stream.of(components).forEach(componentDto -> db.properties().insertProperty(new PropertyDto()
  1386. .setKey(randomAlphabetic(3))
  1387. .setValue(randomAlphabetic(3))
  1388. .setResourceId(componentDto.getId())));
  1389. }
  1390. private Stream<String> getComponentUuidsOfMeasures() {
  1391. return db.select("select component_uuid as \"COMPONENT_UUID\" from project_measures").stream()
  1392. .map(row -> (String) row.get("COMPONENT_UUID"));
  1393. }
  1394. private void insertMeasureFor(ComponentDto... components) {
  1395. Arrays.stream(components).forEach(componentDto -> db.getDbClient().measureDao().insert(dbSession, new MeasureDto()
  1396. .setMetricId(new Random().nextInt())
  1397. .setComponentUuid(componentDto.uuid())
  1398. .setAnalysisUuid(randomAlphabetic(3))));
  1399. dbSession.commit();
  1400. }
  1401. private CeQueueDto createCeQueue(ComponentDto component, Status status) {
  1402. CeQueueDto queueDto = new CeQueueDto();
  1403. queueDto.setUuid(Uuids.create());
  1404. queueDto.setTaskType(REPORT);
  1405. queueDto.setComponentUuid(component.uuid());
  1406. queueDto.setMainComponentUuid(firstNonNull(component.getMainBranchProjectUuid(), component.uuid()));
  1407. queueDto.setSubmitterUuid("submitter uuid");
  1408. queueDto.setCreatedAt(1_300_000_000_000L);
  1409. queueDto.setStatus(status);
  1410. return queueDto;
  1411. }
  1412. private CeActivityDto insertCeActivity(ComponentDto component) {
  1413. Status unusedStatus = Status.values()[RandomUtils.nextInt(Status.values().length)];
  1414. CeQueueDto queueDto = createCeQueue(component, unusedStatus);
  1415. CeActivityDto dto = new CeActivityDto(queueDto);
  1416. dto.setStatus(CeActivityDto.Status.SUCCESS);
  1417. dto.setStartedAt(1_500_000_000_000L);
  1418. dto.setExecutedAt(1_500_000_000_500L);
  1419. dto.setExecutionTimeMs(500L);
  1420. dbClient.ceActivityDao().insert(dbSession, dto);
  1421. return dto;
  1422. }
  1423. private CeQueueDto insertCeQueue(ComponentDto component) {
  1424. CeQueueDto res = new CeQueueDto()
  1425. .setUuid(UuidFactoryFast.getInstance().create())
  1426. .setTaskType("foo")
  1427. .setComponentUuid(component.uuid())
  1428. .setMainComponentUuid(firstNonNull(component.getMainBranchProjectUuid(), component.uuid()))
  1429. .setStatus(Status.PENDING)
  1430. .setCreatedAt(1_2323_222L)
  1431. .setUpdatedAt(1_2323_222L);
  1432. dbClient.ceQueueDao().insert(dbSession, res);
  1433. dbSession.commit();
  1434. return res;
  1435. }
  1436. private void insertCeScannerContext(String uuid) {
  1437. dbClient.ceScannerContextDao().insert(dbSession, uuid, CloseableIterator.from(Arrays.asList("a", "b", "c").iterator()));
  1438. dbSession.commit();
  1439. }
  1440. private void insertCeTaskCharacteristics(String uuid, int count) {
  1441. List<CeTaskCharacteristicDto> dtos = IntStream.range(0, count)
  1442. .mapToObj(i -> new CeTaskCharacteristicDto()
  1443. .setUuid(UuidFactoryFast.getInstance().create())
  1444. .setTaskUuid(uuid)
  1445. .setKey("key_" + uuid.hashCode() + i)
  1446. .setValue("value_" + uuid.hashCode() + i))
  1447. .collect(Collectors.toList());
  1448. dbClient.ceTaskCharacteristicsDao().insert(dbSession, dtos);
  1449. dbSession.commit();
  1450. }
  1451. private void insertCeTaskInput(String uuid) {
  1452. dbClient.ceTaskInputDao().insert(dbSession, uuid, new ByteArrayInputStream("some content man!".getBytes()));
  1453. dbSession.commit();
  1454. }
  1455. private void insertCeTaskMessages(String uuid, int count) {
  1456. IntStream.range(0, count)
  1457. .mapToObj(i -> new CeTaskMessageDto()
  1458. .setUuid(UuidFactoryFast.getInstance().create())
  1459. .setTaskUuid(uuid)
  1460. .setMessage("key_" + uuid.hashCode() + i)
  1461. .setCreatedAt(2_333_444L + i))
  1462. .forEach(dto -> dbClient.ceTaskMessageDao().insert(dbSession, dto));
  1463. dbSession.commit();
  1464. }
  1465. private static PurgeableAnalysisDto getById(List<PurgeableAnalysisDto> snapshots, String uuid) {
  1466. return snapshots.stream()
  1467. .filter(snapshot -> uuid.equals(snapshot.getAnalysisUuid()))
  1468. .findFirst()
  1469. .orElse(null);
  1470. }
  1471. private Stream<String> uuidsIn(String tableName) {
  1472. return uuidsIn(tableName, "uuid");
  1473. }
  1474. private Stream<String> taskUuidsIn(String tableName) {
  1475. return uuidsIn(tableName, "task_uuid");
  1476. }
  1477. private Stream<String> uuidsIn(String tableName, String columnName) {
  1478. return db.select("select " + columnName + " as \"UUID\" from " + tableName)
  1479. .stream()
  1480. .map(row -> (String) row.get("UUID"));
  1481. }
  1482. private static PurgeConfiguration newConfigurationWith30Days(String rootUuid) {
  1483. return new PurgeConfiguration(rootUuid, rootUuid, emptyList(), 30, Optional.of(30), System2.INSTANCE, emptySet());
  1484. }
  1485. private static PurgeConfiguration newConfigurationWith30Days(System2 system2, String rootUuid, String projectUuid) {
  1486. return newConfigurationWith30Days(system2, rootUuid, projectUuid, Collections.emptySet());
  1487. }
  1488. private static PurgeConfiguration newConfigurationWith30Days(System2 system2, String rootUuid, String projectUuid, Set<String> disabledComponentUuids) {
  1489. return new PurgeConfiguration(rootUuid, projectUuid, emptyList(), 30, Optional.of(30), system2, disabledComponentUuids);
  1490. }
  1491. private Stream<String> uuidsOfAnalysesOfRoot(ComponentDto rootComponent) {
  1492. return db.select("select uuid as \"UUID\" from snapshots where component_uuid='" + rootComponent.uuid() + "'")
  1493. .stream()
  1494. .map(t -> (String) t.get("UUID"));
  1495. }
  1496. private static IdUuidPair idUuidPairOf(SnapshotDto analysis3) {
  1497. return new IdUuidPair(analysis3.getId(), analysis3.getUuid());
  1498. }
  1499. }