Skip to content

Commit

Permalink
SONAR-6260 Persist snapshots with periods
Browse files Browse the repository at this point in the history
  • Loading branch information
julienlancelot committed Jun 10, 2015
1 parent 64032ec commit 38fed3b
Show file tree
Hide file tree
Showing 3 changed files with 239 additions and 21 deletions.
Expand Up @@ -31,6 +31,8 @@
import org.sonar.server.computation.component.Component;
import org.sonar.server.computation.component.DbIdsRepository;
import org.sonar.server.computation.component.TreeRootHolder;
import org.sonar.server.computation.period.Period;
import org.sonar.server.computation.period.PeriodsHolder;
import org.sonar.server.db.DbClient;

/**
Expand All @@ -43,15 +45,17 @@ public class PersistSnapshotsStep implements ComputationStep {
private final DbClient dbClient;
private final TreeRootHolder treeRootHolder;
private final BatchReportReader reportReader;

private final DbIdsRepository dbIdsRepository;
private final PeriodsHolder periodsHolder;

public PersistSnapshotsStep(System2 system2, DbClient dbClient, TreeRootHolder treeRootHolder, BatchReportReader reportReader, DbIdsRepository dbIdsRepository) {
public PersistSnapshotsStep(System2 system2, DbClient dbClient, TreeRootHolder treeRootHolder, BatchReportReader reportReader, DbIdsRepository dbIdsRepository,
PeriodsHolder periodsHolder) {
this.system2 = system2;
this.dbClient = dbClient;
this.treeRootHolder = treeRootHolder;
this.reportReader = reportReader;
this.dbIdsRepository = dbIdsRepository;
this.periodsHolder = periodsHolder;
}

@Override
Expand Down Expand Up @@ -88,22 +92,22 @@ private void process(Component component, @Nullable SnapshotDto parentSnapshot)
switch (component.getType()) {
case PROJECT:
this.projectId = componentId;
SnapshotDto projectSnapshot = persistSnapshot(componentId, Qualifiers.PROJECT, Scopes.PROJECT, reportComponent.getVersion(), parentSnapshot);
SnapshotDto projectSnapshot = persistSnapshot(componentId, Qualifiers.PROJECT, Scopes.PROJECT, reportComponent.getVersion(), parentSnapshot, true);
addToCache(component, projectSnapshot);
processChildren(component, projectSnapshot);
break;
case MODULE:
SnapshotDto moduleSnapshot = persistSnapshot(componentId, Qualifiers.MODULE, Scopes.PROJECT, reportComponent.getVersion(), parentSnapshot);
SnapshotDto moduleSnapshot = persistSnapshot(componentId, Qualifiers.MODULE, Scopes.PROJECT, reportComponent.getVersion(), parentSnapshot, true);
addToCache(component, moduleSnapshot);
processChildren(component, moduleSnapshot);
break;
case DIRECTORY:
SnapshotDto directorySnapshot = persistSnapshot(componentId, Qualifiers.DIRECTORY, Scopes.DIRECTORY, null, parentSnapshot);
SnapshotDto directorySnapshot = persistSnapshot(componentId, Qualifiers.DIRECTORY, Scopes.DIRECTORY, null, parentSnapshot, false);
addToCache(component, directorySnapshot);
processChildren(component, directorySnapshot);
break;
case FILE:
SnapshotDto fileSnapshot = persistSnapshot(componentId, getFileQualifier(reportComponent), Scopes.FILE, null, parentSnapshot);
SnapshotDto fileSnapshot = persistSnapshot(componentId, getFileQualifier(reportComponent), Scopes.FILE, null, parentSnapshot, false);
addToCache(component, fileSnapshot);
break;
default:
Expand All @@ -117,7 +121,7 @@ private void processChildren(Component component, SnapshotDto parentSnapshot) {
}
}

private SnapshotDto persistSnapshot(long componentId, String qualifier, String scope, @Nullable String version, @Nullable SnapshotDto parentSnapshot) {
private SnapshotDto persistSnapshot(long componentId, String qualifier, String scope, @Nullable String version, @Nullable SnapshotDto parentSnapshot, boolean setPeriods) {
SnapshotDto snapshotDto = new SnapshotDto()
.setRootProjectId(projectId)
.setVersion(version)
Expand All @@ -128,6 +132,9 @@ private SnapshotDto persistSnapshot(long componentId, String qualifier, String s
.setStatus(SnapshotDto.STATUS_UNPROCESSED)
.setCreatedAt(analysisDate)
.setBuildDate(system2.now());
if (setPeriods) {
updateSnapshotPeriods(snapshotDto);
}

if (parentSnapshot != null) {
snapshotDto
Expand All @@ -144,6 +151,15 @@ private SnapshotDto persistSnapshot(long componentId, String qualifier, String s
return snapshotDto;
}

private void updateSnapshotPeriods(SnapshotDto snapshotDto) {
for (Period period : periodsHolder.getPeriods()) {
int index = period.getIndex();
snapshotDto.setPeriodMode(index, period.getMode());
snapshotDto.setPeriodParam(index, period.getModeParameter());
snapshotDto.setPeriodDate(index, period.getSnapshotDate());
}
}

private void addToCache(Component component, SnapshotDto snapshotDto) {
dbIdsRepository.setSnapshotId(component, snapshotDto.getId());
}
Expand Down
@@ -0,0 +1,58 @@
/*
* SonarQube, open source software quality management tool.
* Copyright (C) 2008-2014 SonarSource
* mailto:contact AT sonarsource DOT com
*
* SonarQube is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* SonarQube is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package org.sonar.server.computation.period;

import java.util.ArrayList;
import java.util.List;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;

public class PeriodsHolderRule implements TestRule, PeriodsHolder {
private List<Period> periods = new ArrayList<>();

@Override
public Statement apply(final Statement statement, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
try {
statement.evaluate();
} finally {
clear();
}
}
};
}

private void clear() {
this.periods = new ArrayList<>();
}

@Override
public List<Period> getPeriods() {
return periods;
}

public void addPeriod(Period period) {
this.periods.add(period);
}
}
Expand Up @@ -20,14 +20,16 @@

package org.sonar.server.computation.step;

import java.text.SimpleDateFormat;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.sonar.api.CoreProperties;
import org.sonar.api.config.Settings;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.System2;
import org.sonar.batch.protocol.Constants;
import org.sonar.batch.protocol.output.BatchReport;
Expand All @@ -37,13 +39,16 @@
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.DbTester;
import org.sonar.server.component.ComponentTesting;
import org.sonar.server.component.SnapshotTesting;
import org.sonar.server.component.db.ComponentDao;
import org.sonar.server.component.db.SnapshotDao;
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.DbIdsRepository;
import org.sonar.server.computation.component.DumbComponent;
import org.sonar.server.computation.period.Period;
import org.sonar.server.computation.period.PeriodsHolderRule;
import org.sonar.server.db.DbClient;
import org.sonar.test.DbTests;

Expand All @@ -52,9 +57,7 @@
import static org.mockito.Mockito.when;

@Category(DbTests.class)
public class PersistSnapshotStepTest extends BaseStepTest {

private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
public class PersistSnapshotsStepTest extends BaseStepTest {

private static final String PROJECT_KEY = "PROJECT_KEY";

Expand All @@ -67,10 +70,15 @@ public class PersistSnapshotStepTest extends BaseStepTest {
@Rule
public BatchReportReaderRule reportReader = new BatchReportReaderRule();

@Rule
public PeriodsHolderRule periodsHolderRule = new PeriodsHolderRule();

System2 system2 = mock(System2.class);

DbIdsRepository dbIdsRepository;

Settings settings = new Settings();

DbSession session;

DbClient dbClient;
Expand All @@ -87,17 +95,17 @@ public void setup() throws Exception {
session = dbTester.myBatis().openSession(false);
dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new ComponentDao(), new SnapshotDao());

analysisDate = DATE_FORMAT.parse("2015-06-01").getTime();
analysisDate = DateUtils.parseDateQuietly("2015-06-01").getTime();
reportReader.setMetadata(BatchReport.Metadata.newBuilder()
.setAnalysisDate(analysisDate)
.build());
dbIdsRepository = new DbIdsRepository();

now = DATE_FORMAT.parse("2015-06-02").getTime();
now = DateUtils.parseDateQuietly("2015-06-02").getTime();

when(system2.now()).thenReturn(now);

sut = new PersistSnapshotsStep(system2, dbClient, treeRootHolder, reportReader, dbIdsRepository);
sut = new PersistSnapshotsStep(system2, dbClient, treeRootHolder, reportReader, dbIdsRepository, periodsHolderRule);
}

@Override
Expand Down Expand Up @@ -307,11 +315,6 @@ public void persist_snapshots_on_multi_modules() throws Exception {
Component project = new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY, moduleA, moduleB);
treeRootHolder.setRoot(project);

treeRootHolder.setRoot(new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY,
new DumbComponent(Component.Type.MODULE, 2, "BCDE", "MODULE_A",
new DumbComponent(Component.Type.MODULE, 3, "DEFG", "SUB_MODULE_A")),
new DumbComponent(Component.Type.MODULE, 4, "CDEF", "MODULE_B")));

dbIdsRepository.setComponentId(project, projectDto.getId());
dbIdsRepository.setComponentId(moduleA, moduleADto.getId());
dbIdsRepository.setComponentId(subModuleA, subModuleADto.getId());
Expand Down Expand Up @@ -347,10 +350,151 @@ public void persist_snapshots_on_multi_modules() throws Exception {
assertThat(moduleBSnapshot.getRootId()).isEqualTo(projectSnapshot.getId());
assertThat(moduleBSnapshot.getParentId()).isEqualTo(projectSnapshot.getId());
assertThat(moduleBSnapshot.getDepth()).isEqualTo(1);
assertThat(moduleBSnapshot.getPath()).isEqualTo(projectSnapshot.getId() + "." );
assertThat(moduleBSnapshot.getPath()).isEqualTo(projectSnapshot.getId() + ".");
}

@Test
public void persist_snapshots_with_periods() throws Exception {
ComponentDto projectDto = ComponentTesting.newProjectDto("ABCD").setKey(PROJECT_KEY).setName("Project");
dbClient.componentDao().insert(session, projectDto);
SnapshotDto snapshotDto = SnapshotTesting.createForProject(projectDto).setCreatedAt(DateUtils.parseDateQuietly("2015-01-01").getTime());
dbClient.snapshotDao().insert(session, snapshotDto);
session.commit();
periodsHolderRule.addPeriod(new Period(1, CoreProperties.TIMEMACHINE_MODE_DATE, "2015-01-01", analysisDate));

reportReader.putComponent(BatchReport.Component.newBuilder()
.setRef(1)
.setType(Constants.ComponentType.PROJECT)
.setKey(PROJECT_KEY)
.setName("Project")
.setVersion("1.0")
.addChildRef(2)
.build());

Component project = new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY);
treeRootHolder.setRoot(project);
dbIdsRepository.setComponentId(project, projectDto.getId());

sut.execute();

SnapshotDto projectSnapshot = getUnprocessedSnapshot(projectDto.getId());
assertThat(projectSnapshot.getPeriodMode(1)).isEqualTo(CoreProperties.TIMEMACHINE_MODE_DATE);
assertThat(projectSnapshot.getPeriodDate(1)).isEqualTo(analysisDate);
assertThat(projectSnapshot.getPeriodModeParameter(1)).isNotNull();
}

@Test
public void only_persist_snapshots_with_periods_on_project_and_module() throws Exception {
periodsHolderRule.addPeriod(new Period(1, CoreProperties.TIMEMACHINE_MODE_PREVIOUS_ANALYSIS, null, analysisDate));

ComponentDto projectDto = ComponentTesting.newProjectDto("ABCD").setKey(PROJECT_KEY).setName("Project");
dbClient.componentDao().insert(session, projectDto);
SnapshotDto projectSnapshot = SnapshotTesting.createForProject(projectDto);
dbClient.snapshotDao().insert(session, projectSnapshot);

ComponentDto moduleDto = ComponentTesting.newModuleDto("BCDE", projectDto).setKey("MODULE_KEY").setName("Module");
dbClient.componentDao().insert(session, moduleDto);
SnapshotDto moduleSnapshot = SnapshotTesting.createForComponent(moduleDto, projectSnapshot);
dbClient.snapshotDao().insert(session, moduleSnapshot);

ComponentDto directoryDto = ComponentTesting.newDirectory(moduleDto, "CDEF", "MODULE_KEY:src/main/java/dir").setKey("MODULE_KEY:src/main/java/dir");
dbClient.componentDao().insert(session, directoryDto);
SnapshotDto directorySnapshot = SnapshotTesting.createForComponent(directoryDto, moduleSnapshot);
dbClient.snapshotDao().insert(session, directorySnapshot);

ComponentDto fileDto = ComponentTesting.newFileDto(moduleDto, "DEFG").setKey("MODULE_KEY:src/main/java/dir/Foo.java");
dbClient.componentDao().insert(session, fileDto);
SnapshotDto fileSnapshot = SnapshotTesting.createForComponent(fileDto, directorySnapshot);
dbClient.snapshotDao().insert(session, fileSnapshot);

session.commit();

reportReader.putComponent(BatchReport.Component.newBuilder()
.setRef(1)
.setType(Constants.ComponentType.PROJECT)
.setKey(PROJECT_KEY)
.setName("Project")
.setVersion("1.0")
.addChildRef(2)
.build());
reportReader.putComponent(BatchReport.Component.newBuilder()
.setRef(2)
.setType(Constants.ComponentType.MODULE)
.setKey("MODULE_KEY")
.setPath("module")
.setName("Module")
.setVersion("1.1")
.addChildRef(3)
.build());
reportReader.putComponent(BatchReport.Component.newBuilder()
.setRef(3)
.setType(Constants.ComponentType.DIRECTORY)
.setPath("src/main/java/dir")
.addChildRef(4)
.build());
reportReader.putComponent(BatchReport.Component.newBuilder()
.setRef(4)
.setType(Constants.ComponentType.FILE)
.setPath("src/main/java/dir/Foo.java")
.setLanguage("java")
.build());

Component file = new DumbComponent(Component.Type.FILE, 4, "DEFG", "MODULE_KEY:src/main/java/dir/Foo.java");
Component directory = new DumbComponent(Component.Type.DIRECTORY, 3, "CDEF", "MODULE_KEY:src/main/java/dir", file);
Component module = new DumbComponent(Component.Type.MODULE, 2, "BCDE", "MODULE_KEY", directory);
Component project = new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY, module);
treeRootHolder.setRoot(project);

dbIdsRepository.setComponentId(project, projectDto.getId());
dbIdsRepository.setComponentId(module, moduleDto.getId());
dbIdsRepository.setComponentId(directory, directoryDto.getId());
dbIdsRepository.setComponentId(file, fileDto.getId());

sut.execute();

SnapshotDto newProjectSnapshot = getUnprocessedSnapshot(projectDto.getId());
assertThat(newProjectSnapshot.getPeriodMode(1)).isEqualTo(CoreProperties.TIMEMACHINE_MODE_PREVIOUS_ANALYSIS);

SnapshotDto newModuleSnapshot = getUnprocessedSnapshot(moduleDto.getId());
assertThat(newModuleSnapshot.getPeriodMode(1)).isEqualTo(CoreProperties.TIMEMACHINE_MODE_PREVIOUS_ANALYSIS);

SnapshotDto newDirectorySnapshot = getUnprocessedSnapshot(directoryDto.getId());
assertThat(newDirectorySnapshot.getPeriodMode(1)).isNull();

SnapshotDto newFileSnapshot = getUnprocessedSnapshot(fileDto.getId());
assertThat(newFileSnapshot.getPeriodMode(1)).isNull();
}

@Test
public void set_no_period_on_snapshots_when_no_period() throws Exception {
ComponentDto projectDto = ComponentTesting.newProjectDto("ABCD").setKey(PROJECT_KEY).setName("Project");
dbClient.componentDao().insert(session, projectDto);
SnapshotDto snapshotDto = SnapshotTesting.createForProject(projectDto);
dbClient.snapshotDao().insert(session, snapshotDto);
session.commit();

reportReader.putComponent(BatchReport.Component.newBuilder()
.setRef(1)
.setType(Constants.ComponentType.PROJECT)
.setKey(PROJECT_KEY)
.setName("Project")
.setVersion("1.0")
.addChildRef(2)
.build());

Component project = new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY);
treeRootHolder.setRoot(project);
dbIdsRepository.setComponentId(project, projectDto.getId());

sut.execute();

SnapshotDto projectSnapshot = getUnprocessedSnapshot(projectDto.getId());
assertThat(projectSnapshot.getPeriodMode(1)).isNull();
assertThat(projectSnapshot.getPeriodDate(1)).isNull();
assertThat(projectSnapshot.getPeriodModeParameter(1)).isNull();
}

private SnapshotDto getUnprocessedSnapshot(long componentId){
private SnapshotDto getUnprocessedSnapshot(long componentId) {
List<SnapshotDto> projectSnapshots = dbClient.snapshotDao().selectSnapshotsByQuery(session,
new SnapshotQuery().setComponentId(componentId).setIsLast(false).setStatus(SnapshotDto.STATUS_UNPROCESSED));
assertThat(projectSnapshots).hasSize(1);
Expand Down

0 comments on commit 38fed3b

Please sign in to comment.