From afb07c2d2acbf713ad1e3dec6f82edaf55aa0835 Mon Sep 17 00:00:00 2001 From: Teryk Bellahsene Date: Wed, 3 Dec 2014 15:44:17 +0100 Subject: [PATCH] SONAR-5804 delete source lines from index while purging and deleting a project --- .../component/ComponentCleanerService.java | 6 +- .../server/computation/DataCleanerStep.java | 9 +- .../source/index/SourceLineIndexer.java | 22 ++++- .../DataCleanerStepMediumTest.java | 5 +- .../computation/DataCleanerStepTest.java | 5 +- .../source/index/SourceLineIndexerTest.java | 97 ++++++++++++++----- .../index/SourceLineIndexerTest/line3.json | 19 ++++ .../line3_other_project.json | 19 ++++ .../dbcleaner/ProjectPurgeTask.java | 6 ++ .../java/org/sonar/core/purge/PurgeDao.java | 6 +- .../org/sonar/core/purge/PurgeMapper.java | 2 + .../org/sonar/core/purge/PurgeMapper.xml | 6 ++ .../org/sonar/core/purge/PurgeDaoTest.java | 48 ++++++--- .../select_purgeable_file_uuids.xml | 86 ++++++++++++++++ 14 files changed, 292 insertions(+), 44 deletions(-) create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/source/index/SourceLineIndexerTest/line3.json create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/source/index/SourceLineIndexerTest/line3_other_project.json create mode 100644 sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/select_purgeable_file_uuids.xml diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ComponentCleanerService.java b/server/sonar-server/src/main/java/org/sonar/server/component/ComponentCleanerService.java index b7c65566034..b14b61793d6 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/ComponentCleanerService.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/ComponentCleanerService.java @@ -30,6 +30,7 @@ import org.sonar.core.purge.PurgeDao; import org.sonar.server.db.DbClient; import org.sonar.server.issue.index.IssueAuthorizationIndexer; import org.sonar.server.issue.index.IssueIndexer; +import org.sonar.server.source.index.SourceLineIndexer; public class ComponentCleanerService implements ServerComponent { @@ -37,12 +38,14 @@ public class ComponentCleanerService implements ServerComponent { private final PurgeDao purgeDao; private final IssueAuthorizationIndexer issueAuthorizationIndexer; private final IssueIndexer issueIndexer; + private final SourceLineIndexer sourceLineIndexer; - public ComponentCleanerService(DbClient dbClient, PurgeDao purgeDao, IssueAuthorizationIndexer issueAuthorizationIndexer, IssueIndexer issueIndexer) { + public ComponentCleanerService(DbClient dbClient, PurgeDao purgeDao, IssueAuthorizationIndexer issueAuthorizationIndexer, IssueIndexer issueIndexer, SourceLineIndexer sourceLineIndexer) { this.dbClient = dbClient; this.purgeDao = purgeDao; this.issueAuthorizationIndexer = issueAuthorizationIndexer; this.issueIndexer = issueIndexer; + this.sourceLineIndexer = sourceLineIndexer; } public void delete(String projectKey) { @@ -65,6 +68,7 @@ public class ComponentCleanerService implements ServerComponent { // optimization : index issues is refreshed once at the end issueAuthorizationIndexer.deleteProject(projectUuid, false); issueIndexer.deleteProject(projectUuid, true); + sourceLineIndexer.deleteByProject(projectUuid); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/DataCleanerStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/DataCleanerStep.java index 86e953a638c..8636b0ae74c 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/DataCleanerStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/DataCleanerStep.java @@ -28,18 +28,23 @@ import org.sonar.core.persistence.DbSession; import org.sonar.core.purge.PurgeConfiguration; import org.sonar.server.issue.index.IssueIndex; import org.sonar.server.properties.ProjectSettingsFactory; +import org.sonar.server.source.index.SourceLineIndexer; + +import java.util.List; import static org.sonar.core.purge.PurgeConfiguration.newDefaultPurgeConfiguration; public class DataCleanerStep implements ComputationStep { private final ProjectPurgeTask purgeTask; private final IssueIndex issueIndex; + private final SourceLineIndexer sourceLineIndexer; private final ProjectSettingsFactory projectSettingsFactory; - public DataCleanerStep(ProjectSettingsFactory projectSettingsFactory, ProjectPurgeTask purgeTask, IssueIndex issueIndex) { + public DataCleanerStep(ProjectSettingsFactory projectSettingsFactory, ProjectPurgeTask purgeTask, IssueIndex issueIndex, SourceLineIndexer sourceLineIndexer) { this.projectSettingsFactory = projectSettingsFactory; this.purgeTask = purgeTask; this.issueIndex = issueIndex; + this.sourceLineIndexer = sourceLineIndexer; } @Override @@ -49,10 +54,12 @@ public class DataCleanerStep implements ComputationStep { Settings settings = projectSettingsFactory.newProjectSettings(session, projectId); PurgeConfiguration purgeConfiguration = newDefaultPurgeConfiguration(settings, projectId); + List fileUuidsToDisable = purgeTask.findUuidsToDisable(session, projectId); purgeTask.purge(session, purgeConfiguration, settings); if (purgeConfiguration.maxLiveDateOfClosedIssues() != null) { issueIndex.deleteClosedIssuesOfProjectBefore(project.uuid(), purgeConfiguration.maxLiveDateOfClosedIssues()); + sourceLineIndexer.deleteByFiles(fileUuidsToDisable); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/source/index/SourceLineIndexer.java b/server/sonar-server/src/main/java/org/sonar/server/source/index/SourceLineIndexer.java index 12213981ee6..6809c2fd263 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/source/index/SourceLineIndexer.java +++ b/server/sonar-server/src/main/java/org/sonar/server/source/index/SourceLineIndexer.java @@ -19,8 +19,8 @@ */ package org.sonar.server.source.index; -import com.google.common.annotations.VisibleForTesting; import org.elasticsearch.action.update.UpdateRequest; +import org.elasticsearch.index.query.FilterBuilders; import org.elasticsearch.index.query.QueryBuilders; import org.sonar.core.persistence.DbSession; import org.sonar.server.db.DbClient; @@ -30,6 +30,10 @@ import org.sonar.server.es.EsClient; import java.sql.Connection; import java.util.Iterator; +import java.util.List; + +import static org.sonar.server.source.index.SourceLineIndexDefinition.FIELD_FILE_UUID; +import static org.sonar.server.source.index.SourceLineIndexDefinition.FIELD_PROJECT_UUID; public class SourceLineIndexer extends BaseIndexer { @@ -93,8 +97,22 @@ public class SourceLineIndexer extends BaseIndexer { esClient.prepareDeleteByQuery(SourceLineIndexDefinition.INDEX) .setTypes(SourceLineIndexDefinition.TYPE) .setQuery(QueryBuilders.boolQuery() - .must(QueryBuilders.termQuery(SourceLineIndexDefinition.FIELD_FILE_UUID, fileUuid)) + .must(QueryBuilders.termQuery(FIELD_FILE_UUID, fileUuid)) .must(QueryBuilders.rangeQuery(SourceLineIndexDefinition.FIELD_LINE).gt(lastLine)) ).get(); } + + public void deleteByFiles(List uuids) { + esClient.prepareDeleteByQuery(SourceLineIndexDefinition.INDEX) + .setTypes(SourceLineIndexDefinition.TYPE) + .setQuery(QueryBuilders.filteredQuery(QueryBuilders.matchAllQuery(), FilterBuilders.termsFilter(FIELD_FILE_UUID, uuids).cache(false))) + .get(); + } + + public void deleteByProject(String projectUuid) { + esClient.prepareDeleteByQuery(SourceLineIndexDefinition.INDEX) + .setTypes(SourceLineIndexDefinition.TYPE) + .setQuery(QueryBuilders.filteredQuery(QueryBuilders.matchAllQuery(), FilterBuilders.termFilter(FIELD_PROJECT_UUID, projectUuid).cache(false))) + .get(); + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/DataCleanerStepMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/DataCleanerStepMediumTest.java index 23e886589b0..7e6cfbefa71 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/DataCleanerStepMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/DataCleanerStepMediumTest.java @@ -40,6 +40,7 @@ import org.sonar.server.db.DbClient; import org.sonar.server.issue.index.IssueIndex; import org.sonar.server.properties.ProjectSettingsFactory; import org.sonar.server.search.IndexClient; +import org.sonar.server.source.index.SourceLineIndexer; import org.sonar.server.tester.ServerTester; import java.util.Date; @@ -55,6 +56,7 @@ public class DataCleanerStepMediumTest { private DbClient dbClient; private DbSession dbSession; private IndexClient indexClient; + private SourceLineIndexer sourceLineIndexer; private ProjectSettingsFactory projectSettingsFactory; private ProjectPurgeTask purgeTask; @@ -66,8 +68,9 @@ public class DataCleanerStepMediumTest { this.indexClient = tester.get(IndexClient.class); this.projectSettingsFactory = tester.get(ProjectSettingsFactory.class); this.purgeTask = tester.get(ProjectPurgeTask.class); + this.sourceLineIndexer = tester.get(SourceLineIndexer.class); - this.sut = new DataCleanerStep(projectSettingsFactory, purgeTask, indexClient.get(IssueIndex.class)); + this.sut = new DataCleanerStep(projectSettingsFactory, purgeTask, indexClient.get(IssueIndex.class), sourceLineIndexer); } @After diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/DataCleanerStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/DataCleanerStepTest.java index ad016a66ec1..3c6523d6d95 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/DataCleanerStepTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/DataCleanerStepTest.java @@ -31,6 +31,7 @@ import org.sonar.core.purge.PurgeConfiguration; import org.sonar.server.issue.index.IssueIndex; import org.sonar.server.properties.ProjectSettings; import org.sonar.server.properties.ProjectSettingsFactory; +import org.sonar.server.source.index.SourceLineIndexer; import java.util.Date; @@ -44,6 +45,7 @@ public class DataCleanerStepTest { private DataCleanerStep sut; private ProjectPurgeTask purgeTask; private IssueIndex issueIndex; + private SourceLineIndexer sourceLineIndexer; private Settings settings; private ProjectSettingsFactory projectSettingsFactory; @@ -51,12 +53,13 @@ public class DataCleanerStepTest { public void before() { this.purgeTask = mock(ProjectPurgeTask.class); this.issueIndex = mock(IssueIndex.class); + this.sourceLineIndexer = mock(SourceLineIndexer.class); this.settings = mock(ProjectSettings.class); this.projectSettingsFactory = mock(ProjectSettingsFactory.class); when(projectSettingsFactory.newProjectSettings(any(DbSession.class), anyLong())).thenReturn(settings); when(settings.getInt(any(String.class))).thenReturn(123); - this.sut = new DataCleanerStep(projectSettingsFactory, purgeTask, issueIndex); + this.sut = new DataCleanerStep(projectSettingsFactory, purgeTask, issueIndex, sourceLineIndexer); } @Test diff --git a/server/sonar-server/src/test/java/org/sonar/server/source/index/SourceLineIndexerTest.java b/server/sonar-server/src/test/java/org/sonar/server/source/index/SourceLineIndexerTest.java index db7f9b53701..d0731a06734 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/source/index/SourceLineIndexerTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/source/index/SourceLineIndexerTest.java @@ -22,9 +22,13 @@ package org.sonar.server.source.index; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterators; +import com.google.common.collect.Lists; import org.apache.commons.io.IOUtils; +import org.elasticsearch.action.index.IndexRequestBuilder; +import org.elasticsearch.action.search.SearchRequestBuilder; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.search.SearchHit; import org.fest.assertions.MapAssert; import org.junit.Before; import org.junit.Rule; @@ -43,6 +47,7 @@ import java.util.List; import java.util.Map; import static org.fest.assertions.Assertions.assertThat; +import static org.sonar.server.source.index.SourceLineIndexDefinition.*; public class SourceLineIndexerTest { @@ -68,24 +73,24 @@ public class SourceLineIndexerTest { @Test public void update_already_indexed_lines() throws Exception { - es.client().prepareIndex(SourceLineIndexDefinition.INDEX, SourceLineIndexDefinition.TYPE) + prepareIndex() .setSource(IOUtils.toString(new FileInputStream(TestUtils.getResource(this.getClass(), "line2.json")))) .get(); - es.client().prepareIndex(SourceLineIndexDefinition.INDEX, SourceLineIndexDefinition.TYPE) + prepareIndex() .setSource(IOUtils.toString(new FileInputStream(TestUtils.getResource(this.getClass(), "line2_other_file.json")))) .setRefresh(true) .get(); List duplications = ImmutableList.of(1, 2, 3); SourceLineDoc line1 = new SourceLineDoc(ImmutableMap.builder() - .put(SourceLineIndexDefinition.FIELD_PROJECT_UUID, "abcd") - .put(SourceLineIndexDefinition.FIELD_FILE_UUID, "efgh") - .put(SourceLineIndexDefinition.FIELD_LINE, 1) - .put(SourceLineIndexDefinition.FIELD_SCM_REVISION, "cafebabe") - .put(SourceLineIndexDefinition.FIELD_SCM_DATE, DateUtils.parseDateTime("2014-01-01T12:34:56+0100")) - .put(SourceLineIndexDefinition.FIELD_SCM_AUTHOR, "polop") - .put(SourceLineIndexDefinition.FIELD_SOURCE, "package org.sonar.server.source;") - .put(SourceLineIndexDefinition.FIELD_DUPLICATIONS, duplications) + .put(FIELD_PROJECT_UUID, "abcd") + .put(FIELD_FILE_UUID, "efgh") + .put(FIELD_LINE, 1) + .put(FIELD_SCM_REVISION, "cafebabe") + .put(FIELD_SCM_DATE, DateUtils.parseDateTime("2014-01-01T12:34:56+0100")) + .put(FIELD_SCM_AUTHOR, "polop") + .put(FIELD_SOURCE, "package org.sonar.server.source;") + .put(FIELD_DUPLICATIONS, duplications) .put(BaseNormalizer.UPDATED_AT_FIELD, new Date()) .build()); SourceLineResultSetIterator.SourceFile file = new SourceLineResultSetIterator.SourceFile("efgh", System.currentTimeMillis()); @@ -94,26 +99,74 @@ public class SourceLineIndexerTest { assertThat(countDocuments()).isEqualTo(2L); - SearchResponse fileSearch = es.client().prepareSearch(SourceLineIndexDefinition.INDEX) - .setTypes(SourceLineIndexDefinition.TYPE) - .setQuery(QueryBuilders.termQuery(SourceLineIndexDefinition.FIELD_FILE_UUID, "efgh")) + SearchResponse fileSearch = prepareSearch() + .setQuery(QueryBuilders.termQuery(FIELD_FILE_UUID, "efgh")) .get(); assertThat(fileSearch.getHits().getTotalHits()).isEqualTo(1L); Map fields = fileSearch.getHits().getHits()[0].sourceAsMap(); assertThat(fields).hasSize(9); assertThat(fields).includes( - MapAssert.entry(SourceLineIndexDefinition.FIELD_PROJECT_UUID, "abcd"), - MapAssert.entry(SourceLineIndexDefinition.FIELD_FILE_UUID, "efgh"), - MapAssert.entry(SourceLineIndexDefinition.FIELD_LINE, 1), - MapAssert.entry(SourceLineIndexDefinition.FIELD_SCM_REVISION, "cafebabe"), - MapAssert.entry(SourceLineIndexDefinition.FIELD_SCM_DATE, "2014-01-01T11:34:56.000Z"), - MapAssert.entry(SourceLineIndexDefinition.FIELD_SCM_AUTHOR, "polop"), - MapAssert.entry(SourceLineIndexDefinition.FIELD_SOURCE, "package org.sonar.server.source;"), - MapAssert.entry(SourceLineIndexDefinition.FIELD_DUPLICATIONS, duplications) + MapAssert.entry(FIELD_PROJECT_UUID, "abcd"), + MapAssert.entry(FIELD_FILE_UUID, "efgh"), + MapAssert.entry(FIELD_LINE, 1), + MapAssert.entry(FIELD_SCM_REVISION, "cafebabe"), + MapAssert.entry(FIELD_SCM_DATE, "2014-01-01T11:34:56.000Z"), + MapAssert.entry(FIELD_SCM_AUTHOR, "polop"), + MapAssert.entry(FIELD_SOURCE, "package org.sonar.server.source;"), + MapAssert.entry(FIELD_DUPLICATIONS, duplications) ); } + @Test + public void delete_file_uuids() throws Exception { + addSource("line2.json"); + addSource("line3.json"); + addSource("line2_other_file.json"); + + indexer.deleteByFiles(Lists.newArrayList("efgh")); + + List hits = getDocuments(); + Map document = hits.get(0).getSource(); + assertThat(hits).hasSize(1); + assertThat(document.get(FIELD_LINE)).isEqualTo(2); + assertThat(document.get(FIELD_FILE_UUID)).isEqualTo("fdsq"); + } + + @Test + public void delete_by_project_uuid() throws Exception { + addSource("line2.json"); + addSource("line3.json"); + addSource("line2_other_file.json"); + addSource("line3_other_project.json"); + + indexer.deleteByProject("abcd"); + + List hits = getDocuments(); + Map document = hits.get(0).getSource(); + assertThat(hits).hasSize(1); + assertThat(document.get(FIELD_PROJECT_UUID)).isEqualTo("plmn"); + } + + private void addSource(String fileName) throws Exception { + prepareIndex() + .setSource(IOUtils.toString(new FileInputStream(TestUtils.getResource(this.getClass(), fileName)))) + .get(); + } + + private SearchRequestBuilder prepareSearch() { + return es.client().prepareSearch(INDEX) + .setTypes(TYPE); + } + + private IndexRequestBuilder prepareIndex() { + return es.client().prepareIndex(INDEX, TYPE); + } + + private List getDocuments() { + return es.getDocuments(INDEX, TYPE); + } + private long countDocuments() { - return es.countDocuments(SourceLineIndexDefinition.INDEX, SourceLineIndexDefinition.TYPE); + return es.countDocuments(INDEX, TYPE); } } diff --git a/server/sonar-server/src/test/resources/org/sonar/server/source/index/SourceLineIndexerTest/line3.json b/server/sonar-server/src/test/resources/org/sonar/server/source/index/SourceLineIndexerTest/line3.json new file mode 100644 index 00000000000..a6899aea73e --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/source/index/SourceLineIndexerTest/line3.json @@ -0,0 +1,19 @@ +{ + "projectUuid": "abcd", + "fileUuid": "efgh", + "line": 3, + "scmAuthor": "polop", + "scmDate": "2014-01-01T12:34:56.7+01:00", + "scmRevision": "cafebabe", + "source": "// Empty", + "updatedAt": "2014-01-01T23:45:01.8+01:00", + "utLineHits": 0, + "utConditions": 0, + "utCoveredConditions": 0, + "itLineHits": 0, + "itConditions": 0, + "itCoveredConditions": 0, + "overallLineHits": 0, + "overallConditions": 0, + "overallCoveredConditions": 0 +} \ No newline at end of file diff --git a/server/sonar-server/src/test/resources/org/sonar/server/source/index/SourceLineIndexerTest/line3_other_project.json b/server/sonar-server/src/test/resources/org/sonar/server/source/index/SourceLineIndexerTest/line3_other_project.json new file mode 100644 index 00000000000..107ccb1331f --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/source/index/SourceLineIndexerTest/line3_other_project.json @@ -0,0 +1,19 @@ +{ + "projectUuid": "plmn", + "fileUuid": "efgh", + "line": 3, + "scmAuthor": "polop", + "scmDate": "2014-01-01T12:34:56.7+01:00", + "scmRevision": "cafebabe", + "source": "// Empty", + "updatedAt": "2014-01-01T23:45:01.8+01:00", + "utLineHits": 0, + "utConditions": 0, + "utCoveredConditions": 0, + "itLineHits": 0, + "itConditions": 0, + "itCoveredConditions": 0, + "overallLineHits": 0, + "overallConditions": 0, + "overallCoveredConditions": 0 +} \ No newline at end of file diff --git a/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/ProjectPurgeTask.java b/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/ProjectPurgeTask.java index 96b391a06ea..931a746b620 100644 --- a/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/ProjectPurgeTask.java +++ b/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/ProjectPurgeTask.java @@ -32,6 +32,8 @@ import org.sonar.core.purge.PurgeConfiguration; import org.sonar.core.purge.PurgeDao; import org.sonar.core.purge.PurgeProfiler; +import java.util.List; + public class ProjectPurgeTask implements ServerComponent { private static final Logger LOG = LoggerFactory.getLogger(ProjectPurgeTask.class); private final PurgeProfiler profiler; @@ -75,4 +77,8 @@ public class ProjectPurgeTask implements ServerComponent { LOG.error("Fail to purge data [id=" + configuration.rootProjectId() + "]", e); } } + + public List findUuidsToDisable(DbSession session, Long projectId) { + return purgeDao.selectPurgeableFiles(session, projectId); + } } diff --git a/sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java b/sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java index c43f3df6d93..9eb298082ab 100644 --- a/sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java +++ b/sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java @@ -45,7 +45,7 @@ public class PurgeDao { private final MyBatis mybatis; private final ResourceDao resourceDao; private final System2 system2; - private PurgeProfiler profiler; + private final PurgeProfiler profiler; public PurgeDao(MyBatis mybatis, ResourceDao resourceDao, PurgeProfiler profiler, System2 system2) { this.mybatis = mybatis; @@ -222,4 +222,8 @@ public class PurgeDao { return projects; } + public List selectPurgeableFiles(DbSession dbSession, Long projectId) { + PurgeMapper mapper = dbSession.getMapper(PurgeMapper.class); + return mapper.selectPurgeableFileUuids(projectId); + } } diff --git a/sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java b/sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java index f498b122496..a31a2abd2b9 100644 --- a/sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java +++ b/sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java @@ -107,4 +107,6 @@ public interface PurgeMapper { void deleteFileSourcesByProjectUuid(String rootProjectUuid); void deleteFileSourcesByUuid(String fileUuid); + + List selectPurgeableFileUuids(Long projectId); } diff --git a/sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml b/sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml index c0173090485..6134cde6f24 100644 --- a/sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml @@ -78,6 +78,12 @@ and not exists(select s.project_id from snapshots s where s.islast=${_true} and s.project_id=p.id) + + diff --git a/sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java b/sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java index e0bc253992d..8487e4076aa 100644 --- a/sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java @@ -19,12 +19,15 @@ */ package org.sonar.core.purge; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.sonar.api.resources.Scopes; import org.sonar.api.utils.DateUtils; import org.sonar.api.utils.System2; import org.sonar.core.persistence.AbstractDaoTestCase; +import org.sonar.core.persistence.DbSession; +import org.sonar.core.persistence.MyBatis; import org.sonar.core.resource.ResourceDao; import java.util.List; @@ -35,9 +38,9 @@ import static org.mockito.Mockito.when; public class PurgeDaoTest extends AbstractDaoTestCase { - System2 system2; - - PurgeDao dao; + private PurgeDao sut; + private System2 system2; + private DbSession dbSession; private static PurgeableSnapshotDto getById(List snapshots, long id) { for (PurgeableSnapshotDto snapshot : snapshots) { @@ -49,59 +52,65 @@ public class PurgeDaoTest extends AbstractDaoTestCase { } @Before - public void createDao() { + public void before() { system2 = mock(System2.class); when(system2.now()).thenReturn(DateUtils.parseDate("2014-04-09").getTime()); + dbSession = getMyBatis().openSession(false); + + sut = new PurgeDao(getMyBatis(), new ResourceDao(getMyBatis(), system2), new PurgeProfiler(), system2); + } - dao = new PurgeDao(getMyBatis(), new ResourceDao(getMyBatis(), system2), new PurgeProfiler(), system2); + @After + public void after() { + MyBatis.closeQuietly(dbSession); } @Test public void shouldDeleteAbortedBuilds() { setupData("shouldDeleteAbortedBuilds"); - dao.purge(new PurgeConfiguration(1L, new String[0], 30)); + sut.purge(new PurgeConfiguration(1L, new String[0], 30)); checkTables("shouldDeleteAbortedBuilds", "snapshots"); } @Test public void should_purge_project() { setupData("shouldPurgeProject"); - dao.purge(new PurgeConfiguration(1L, new String[0], 30)); + sut.purge(new PurgeConfiguration(1L, new String[0], 30)); checkTables("shouldPurgeProject", "projects", "snapshots"); } @Test public void delete_file_sources_of_disabled_resources() { setupData("delete_file_sources_of_disabled_resources"); - dao.purge(new PurgeConfiguration(1L, new String[0], 30, system2)); + sut.purge(new PurgeConfiguration(1L, new String[0], 30, system2)); checkTables("delete_file_sources_of_disabled_resources", "file_sources"); } @Test public void shouldDeleteHistoricalDataOfDirectoriesAndFiles() { setupData("shouldDeleteHistoricalDataOfDirectoriesAndFiles"); - dao.purge(new PurgeConfiguration(1L, new String[] {Scopes.DIRECTORY, Scopes.FILE}, 30)); + sut.purge(new PurgeConfiguration(1L, new String[] {Scopes.DIRECTORY, Scopes.FILE}, 30)); checkTables("shouldDeleteHistoricalDataOfDirectoriesAndFiles", "projects", "snapshots"); } @Test public void disable_resources_without_last_snapshot() { setupData("disable_resources_without_last_snapshot"); - dao.purge(new PurgeConfiguration(1L, new String[0], 30, system2)); + sut.purge(new PurgeConfiguration(1L, new String[0], 30, system2)); checkTables("disable_resources_without_last_snapshot", "projects", "snapshots", "issues"); } @Test public void shouldDeleteSnapshots() { setupData("shouldDeleteSnapshots"); - dao.deleteSnapshots(PurgeSnapshotQuery.create().setIslast(false).setResourceId(1L)); + sut.deleteSnapshots(PurgeSnapshotQuery.create().setIslast(false).setResourceId(1L)); checkTables("shouldDeleteSnapshots", "snapshots"); } @Test public void shouldSelectPurgeableSnapshots() { setupData("shouldSelectPurgeableSnapshots"); - List snapshots = dao.selectPurgeableSnapshots(1L); + List snapshots = sut.selectPurgeableSnapshots(1L); assertThat(snapshots).hasSize(3); assertThat(getById(snapshots, 1L).isLast()).isTrue(); @@ -115,21 +124,30 @@ public class PurgeDaoTest extends AbstractDaoTestCase { @Test public void should_delete_project_and_associated_data() { setupData("shouldDeleteProject"); - dao.deleteResourceTree(new IdUuidPair(1L, "A")); + sut.deleteResourceTree(new IdUuidPair(1L, "A")); assertEmptyTables("projects", "snapshots", "action_plans", "issues", "issue_changes", "file_sources"); } @Test public void should_delete_old_closed_issues() { setupData("should_delete_old_closed_issues"); - dao.purge(new PurgeConfiguration(1L, new String[0], 30)); + sut.purge(new PurgeConfiguration(1L, new String[0], 30)); checkTables("should_delete_old_closed_issues", "issues", "issue_changes"); } @Test public void should_delete_all_closed_issues() { setupData("should_delete_all_closed_issues"); - dao.purge(new PurgeConfiguration(1L, new String[0], 0)); + sut.purge(new PurgeConfiguration(1L, new String[0], 0)); checkTables("should_delete_all_closed_issues", "issues", "issue_changes"); } + + @Test + public void select_purgeable_file_uuids_and_only_them() { + setupData("select_purgeable_file_uuids"); + + List uuids = sut.selectPurgeableFiles(dbSession, 1L); + + assertThat(uuids).containsOnly("GHIJ"); + } } diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/select_purgeable_file_uuids.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/select_purgeable_file_uuids.xml new file mode 100644 index 00000000000..2925fef21a4 --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/select_purgeable_file_uuids.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + -- 2.39.5