package org.sonar.server.computation.step;
import org.sonar.core.computation.dbcleaner.ProjectCleaner;
+import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
-import org.sonar.db.MyBatis;
import org.sonar.db.purge.IdUuidPair;
import org.sonar.server.computation.component.Component;
import org.sonar.server.computation.component.DbIdsRepository;
+import org.sonar.server.computation.component.DepthTraversalTypeAwareCrawler;
import org.sonar.server.computation.component.SettingsRepository;
import org.sonar.server.computation.component.TreeRootHolder;
-import org.sonar.db.DbClient;
+import org.sonar.server.computation.component.TypeAwareVisitorAdapter;
+
+import static org.sonar.server.computation.component.Component.Type.PROJECT;
+import static org.sonar.server.computation.component.Component.Type.VIEW;
+import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;
+import static org.sonar.server.computation.component.CrawlerDepthLimit.reportMaxDepth;
public class PurgeDatastoresStep implements ComputationStep {
@Override
public void execute() {
+ new DepthTraversalTypeAwareCrawler(
+ new TypeAwareVisitorAdapter(reportMaxDepth(PROJECT).withViewsMaxDepth(VIEW), PRE_ORDER) {
+ @Override
+ public void visitProject(Component project) {
+ execute(project);
+ }
+
+ @Override
+ public void visitView(Component view) {
+ execute(view);
+ }
+ }).visit(treeRootHolder.getRoot());
+ }
+
+ private void execute(Component root) {
DbSession session = dbClient.openSession(true);
try {
- Component project = treeRootHolder.getRoot();
- projectCleaner.purge(session, new IdUuidPair(dbIdsRepository.getComponentId(project), project.getUuid()), settingsRepository.getSettings(project));
+ projectCleaner.purge(session, new IdUuidPair(dbIdsRepository.getComponentId(root), root.getUuid()), settingsRepository.getSettings(root));
session.commit();
} finally {
- MyBatis.closeQuietly(session);
+ dbClient.closeSession(session);
}
}
package org.sonar.server.computation.step;
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
+import com.tngtech.java.junit.dataprovider.DataProvider;
+import com.tngtech.java.junit.dataprovider.DataProviderRunner;
+import com.tngtech.java.junit.dataprovider.UseDataProvider;
+import javax.annotation.Nullable;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.sonar.api.config.Settings;
-import org.sonar.batch.protocol.output.BatchReport;
import org.sonar.core.computation.dbcleaner.ProjectCleaner;
import org.sonar.db.DbSession;
import org.sonar.db.purge.IdUuidPair;
-import org.sonar.server.computation.batch.BatchReportReaderRule;
import org.sonar.server.computation.batch.TreeRootHolderRule;
import org.sonar.server.computation.component.Component;
-import org.sonar.server.computation.component.DbIdsRepositoryImpl;
+import org.sonar.server.computation.component.MutableDbIdsRepositoryRule;
import org.sonar.server.computation.component.ReportComponent;
import org.sonar.server.computation.component.SettingsRepository;
+import org.sonar.server.computation.component.ViewsComponent;
import org.sonar.server.db.DbClient;
+import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
+@RunWith(DataProviderRunner.class)
public class PurgeDatastoresStepTest extends BaseStepTest {
private static final String PROJECT_KEY = "PROJECT_KEY";
-
- @Rule
- public BatchReportReaderRule reportReader = new BatchReportReaderRule();
+ private static final long PROJECT_ID = 123L;
+ private static final String PROJECT_UUID = "UUID-1234";
@Rule
public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
-
- DbIdsRepositoryImpl dbIdsRepository = new DbIdsRepositoryImpl();
+ @Rule
+ public MutableDbIdsRepositoryRule dbIdsRepository = MutableDbIdsRepositoryRule.standalone();
ProjectCleaner projectCleaner = mock(ProjectCleaner.class);
SettingsRepository settingsRepository = mock(SettingsRepository.class);
PurgeDatastoresStep underTest = new PurgeDatastoresStep(mock(DbClient.class, Mockito.RETURNS_DEEP_STUBS), projectCleaner, dbIdsRepository, treeRootHolder, settingsRepository);
@Test
- public void call_purge_method_of_the_purge_task() {
- Component project = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("UUID-1234").setKey(PROJECT_KEY).build();
+ public void call_purge_method_of_the_purge_task_for_project() {
+ Component project = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(PROJECT_UUID).setKey(PROJECT_KEY).build();
+
+ verify_call_purge_method_of_the_purge_task(project);
+ }
+
+ @Test
+ public void call_purge_method_of_the_purge_task_for_view() {
+ Component project = ViewsComponent.builder(Component.Type.VIEW, PROJECT_KEY).setUuid(PROJECT_UUID).build();
+
+ verify_call_purge_method_of_the_purge_task(project);
+ }
+
+ @DataProvider
+ public static Object[][] nonRootProjectComponentTypes() {
+ return dataproviderFromComponentTypeValues(new Predicate<Component.Type>() {
+ @Override
+ public boolean apply(Component.Type input) {
+ return input.isReportType() && input != Component.Type.PROJECT;
+ }
+ });
+ }
+
+ @Test
+ @UseDataProvider("nonRootProjectComponentTypes")
+ public void do_not_call_purge_method_of_the_purge_task_for_other_report_components(Component.Type type) {
+ Component component = ReportComponent.builder(type, 1).setUuid(PROJECT_UUID).setKey(PROJECT_KEY).build();
+
+ verify_do_not_call_purge_method_of_the_purge_task(component);
+ }
+
+ @DataProvider
+ public static Object[][] nonRootViewsComponentTypes() {
+ return dataproviderFromComponentTypeValues(new Predicate<Component.Type>() {
+ @Override
+ public boolean apply(Component.Type input) {
+ return input.isViewsType() && input != Component.Type.VIEW;
+ }
+ });
+ }
+
+ @Test
+ @UseDataProvider("nonRootViewsComponentTypes")
+ public void do_not_call_purge_method_of_the_purge_task_for_other_views_components(Component.Type type) {
+ Component component = ViewsComponent.builder(type, PROJECT_KEY).setUuid(PROJECT_UUID).build();
+
+ verify_do_not_call_purge_method_of_the_purge_task(component);
+ }
+
+ private void verify_do_not_call_purge_method_of_the_purge_task(Component component) {
+ treeRootHolder.setRoot(component);
+
+ underTest.execute();
+
+ verifyNoMoreInteractions(projectCleaner);
+ }
+
+ private void verify_call_purge_method_of_the_purge_task(Component project) {
treeRootHolder.setRoot(project);
when(settingsRepository.getSettings(project)).thenReturn(new Settings());
- dbIdsRepository.setComponentId(project, 123L);
-
- reportReader.setMetadata(BatchReport.Metadata.newBuilder()
- .setRootComponentRef(1)
- .build());
+ dbIdsRepository.setComponentId(project, PROJECT_ID);
underTest.execute();
ArgumentCaptor<IdUuidPair> argumentCaptor = ArgumentCaptor.forClass(IdUuidPair.class);
verify(projectCleaner).purge(any(DbSession.class), argumentCaptor.capture(), any(Settings.class));
- assertThat(argumentCaptor.getValue().getId()).isEqualTo(123L);
- assertThat(argumentCaptor.getValue().getUuid()).isEqualTo("UUID-1234");
+ assertThat(argumentCaptor.getValue().getId()).isEqualTo(PROJECT_ID);
+ assertThat(argumentCaptor.getValue().getUuid()).isEqualTo(PROJECT_UUID);
+ }
+
+ private static Object[][] dataproviderFromComponentTypeValues(Predicate<Component.Type> predicate) {
+ return FluentIterable.from(asList(Component.Type.values()))
+ .filter(predicate)
+ .transform(new Function<Object, Object[]>() {
+ @Nullable
+ @Override
+ public Object[] apply(Object input) {
+ return new Object[]{input};
+ }
+ }).toArray(Object[].class);
}
@Override