Browse Source

SONAR-6260 Replace PeriodsRepository by a PeriodsHolder

tags/5.2-RC1
Julien Lancelot 9 years ago
parent
commit
85cdf23ec2

+ 2
- 2
server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java View File

@@ -51,7 +51,7 @@ import org.sonar.server.computation.language.PlatformLanguageRepository;
import org.sonar.server.computation.measure.MeasureRepositoryImpl;
import org.sonar.server.computation.measure.MetricCache;
import org.sonar.server.computation.period.PeriodFinder;
import org.sonar.server.computation.period.PeriodsRepository;
import org.sonar.server.computation.period.PeriodsHolderImpl;
import org.sonar.server.computation.step.ComputationStep;
import org.sonar.server.computation.step.ComputationSteps;
import org.sonar.server.view.index.ViewIndex;
@@ -128,7 +128,7 @@ public class ComputeEngineContainerImpl extends ComponentContainer implements Co
MeasureRepositoryImpl.class,
EventRepositoryImpl.class,
ProjectSettingsRepository.class,
PeriodsRepository.class,
PeriodsHolderImpl.class,
DbIdsRepository.class,

// issues

+ 1
- 3
server/sonar-server/src/main/java/org/sonar/server/computation/period/Period.java View File

@@ -20,7 +20,6 @@

package org.sonar.server.computation.period;

import com.google.common.annotations.VisibleForTesting;
import java.util.Calendar;
import java.util.Date;
import javax.annotation.Nullable;
@@ -86,8 +85,7 @@ public class Period {
return this;
}

@VisibleForTesting
Long getTargetDate() {
public Long getTargetDate() {
return targetDate;
}


+ 5
- 5
server/sonar-server/src/main/java/org/sonar/server/computation/period/PeriodFinder.java View File

@@ -47,7 +47,7 @@ public class PeriodFinder {
}

@CheckForNull
Period findByDate(DbSession session, Long projectId, Date date) {
public Period findByDate(DbSession session, Long projectId, Date date) {
SnapshotDto snapshot = findFirstSnapshot(session, createCommonQuery(projectId).setCreatedAfter(date.getTime()).setSort(BY_DATE, ASC));
if (snapshot == null) {
return null;
@@ -56,7 +56,7 @@ public class PeriodFinder {
}

@CheckForNull
Period findByDays(DbSession session, Long projectId, long analysisDate, int days) {
public Period findByDays(DbSession session, Long projectId, long analysisDate, int days) {
List<SnapshotDto> snapshots = dbClient.snapshotDao().selectSnapshotsByQuery(session, createCommonQuery(projectId).setCreatedBefore(analysisDate).setSort(BY_DATE, ASC));
long targetDate = DateUtils.addDays(new Date(analysisDate), -days).getTime();
SnapshotDto snapshot = findNearestSnapshotToTargetDate(snapshots, targetDate);
@@ -67,7 +67,7 @@ public class PeriodFinder {
}

@CheckForNull
Period findByPreviousAnalysis(DbSession session, Long projectId, long analysisDate) {
public Period findByPreviousAnalysis(DbSession session, Long projectId, long analysisDate) {
SnapshotDto snapshot = findFirstSnapshot(session, createCommonQuery(projectId).setCreatedBefore(analysisDate).setIsLast(true).setSort(BY_DATE, DESC));
if (snapshot == null) {
return null;
@@ -76,7 +76,7 @@ public class PeriodFinder {
}

@CheckForNull
Period findByPreviousVersion(DbSession session, Long projectId, String version) {
public Period findByPreviousVersion(DbSession session, Long projectId, String version) {
List<SnapshotDto> snapshotDtos = dbClient.snapshotDao().selectPreviousVersionSnapshots(session, projectId, version);
if (snapshotDtos.isEmpty()) {
return null;
@@ -86,7 +86,7 @@ public class PeriodFinder {
}

@CheckForNull
Period findByVersion(DbSession session, Long projectId, String version) {
public Period findByVersion(DbSession session, Long projectId, String version) {
SnapshotDto snapshot = findFirstSnapshot(session, createCommonQuery(projectId).setVersion(version).setSort(BY_DATE, DESC));
if (snapshot == null) {
return null;

+ 37
- 0
server/sonar-server/src/main/java/org/sonar/server/computation/period/PeriodsHolder.java View File

@@ -0,0 +1,37 @@
/*
* 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.List;
import org.sonar.api.CoreProperties;

/**
* Repository of periods used to compute differential measures.
* Here are the steps to retrieve these periods :
* - Read the 5 period properties ${@link CoreProperties#TIMEMACHINE_PERIOD_PREFIX}
* - Try to find the matching snapshots from the properties
* - If a snapshot is found, a new period is added to the repository
*/
public interface PeriodsHolder {

List<Period> getPeriods();

}

+ 43
- 0
server/sonar-server/src/main/java/org/sonar/server/computation/period/PeriodsHolderImpl.java View File

@@ -0,0 +1,43 @@
/*
* 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 com.google.common.base.Preconditions;
import java.util.ArrayList;
import java.util.List;

public class PeriodsHolderImpl implements PeriodsHolder {

private boolean isPeriodsInitialized = false;
private List<Period> periods = new ArrayList<>();

public void setPeriods(List<Period> periods) {
this.periods = periods;
isPeriodsInitialized = true;
}

@Override
public List<Period> getPeriods() {
Preconditions.checkArgument(isPeriodsInitialized, "Periods have not been initialized yet");
return periods;
}

}

+ 1
- 0
server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java View File

@@ -52,6 +52,7 @@ public class ComputationSteps {
QualityGateEventsStep.class,

// Persist data
FeedPeriodsStep.class,
PersistComponentsStep.class,
PersistSnapshotsStep.class,
PersistNumberOfDaysSinceLastCommitStep.class,

server/sonar-server/src/main/java/org/sonar/server/computation/period/PeriodsRepository.java → server/sonar-server/src/main/java/org/sonar/server/computation/step/FeedPeriodsStep.java View File

@@ -18,7 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package org.sonar.server.computation.period;
package org.sonar.server.computation.step;

import com.google.common.base.Strings;
import java.text.ParseException;
@@ -41,18 +41,21 @@ import org.sonar.core.persistence.DbSession;
import org.sonar.server.computation.batch.BatchReportReader;
import org.sonar.server.computation.component.Component;
import org.sonar.server.computation.component.TreeRootHolder;
import org.sonar.server.computation.period.Period;
import org.sonar.server.computation.period.PeriodFinder;
import org.sonar.server.computation.period.PeriodsHolderImpl;
import org.sonar.server.db.DbClient;

/**
* Repository of periods used to compute differential measures.
* Here are the steps to retrieve these periods :
* Populates the {@link org.sonar.server.computation.period.PeriodsHolder}
*
* Here is how these periods are computed :
* - Read the 5 period properties ${@link CoreProperties#TIMEMACHINE_PERIOD_PREFIX}
* - Try to find the matching snapshots from the properties
* - If a snapshot is found, a new period is added to the repository
*/
public class PeriodsRepository {

private static final Logger LOG = LoggerFactory.getLogger(PeriodsRepository.class);
public class FeedPeriodsStep implements ComputationStep {
private static final Logger LOG = LoggerFactory.getLogger(PeriodsHolderImpl.class);

private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat(DateUtils.DATE_FORMAT);

@@ -63,25 +66,25 @@ public class PeriodsRepository {
private final TreeRootHolder treeRootHolder;
private final PeriodFinder periodFinder;
private final BatchReportReader batchReportReader;
private final PeriodsHolderImpl periodsHolder;

private List<Period> periods = new ArrayList<>();

public PeriodsRepository(DbClient dbClient, Settings settings, TreeRootHolder treeRootHolder, PeriodFinder periodFinder, BatchReportReader batchReportReader) {
public FeedPeriodsStep(DbClient dbClient, Settings settings, TreeRootHolder treeRootHolder, PeriodFinder periodFinder, BatchReportReader batchReportReader,
PeriodsHolderImpl periodsHolder) {
this.dbClient = dbClient;
this.settings = settings;
this.treeRootHolder = treeRootHolder;
this.periodFinder = periodFinder;
this.batchReportReader = batchReportReader;
this.periodsHolder = periodsHolder;
}

public List<Period> getPeriods(){
if (periods.isEmpty()) {
initPeriods();
}
return periods;
@Override
public void execute() {
periodsHolder.setPeriods(createPeriods());
}

private void initPeriods() {
private List<Period> createPeriods() {
List<Period> periods = new ArrayList<>();
DbSession session = dbClient.openSession(false);
try {
Component project = treeRootHolder.getRoot();
@@ -105,6 +108,7 @@ public class PeriodsRepository {
} finally {
session.close();
}
return periods;
}

private class PeriodResolver {
@@ -157,7 +161,7 @@ public class PeriodsRepository {
}

@CheckForNull
private Integer tryToResolveByDays(String property){
private Integer tryToResolveByDays(String property) {
try {
return Integer.parseInt(property);
} catch (NumberFormatException e) {
@@ -166,7 +170,7 @@ public class PeriodsRepository {
}

@CheckForNull
private Date tryToResolveByDate(String property){
private Date tryToResolveByDate(String property) {
try {
return DATE_FORMAT.parse(property);
} catch (ParseException e) {
@@ -184,4 +188,8 @@ public class PeriodsRepository {
return value;
}

@Override
public String getDescription() {
return "Feed differential periods";
}
}

+ 55
- 0
server/sonar-server/src/test/java/org/sonar/server/computation/period/PeriodsHolderImplTest.java View File

@@ -0,0 +1,55 @@
/*
* 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.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.core.component.SnapshotDto;

import static org.assertj.core.api.Assertions.assertThat;

public class PeriodsHolderImplTest {

@Rule
public ExpectedException thrown = ExpectedException.none();

@Test
public void get_periods() throws Exception {
List<Period> periods = new ArrayList<>();
periods.add(new Period("mode", null, new SnapshotDto()));

PeriodsHolderImpl periodsHolder = new PeriodsHolderImpl();
periodsHolder.setPeriods(periods);

assertThat(periodsHolder.getPeriods()).hasSize(1);
}

@Test
public void fail_to_get_periods_if_not_initialized() throws Exception {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Periods have not been initialized yet");

new PeriodsHolderImpl().getPeriods();
}
}

server/sonar-server/src/test/java/org/sonar/server/computation/period/PeriodsRepositoryTest.java → server/sonar-server/src/test/java/org/sonar/server/computation/step/FeedPeriodsStepTest.java View File

@@ -18,7 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package org.sonar.server.computation.period;
package org.sonar.server.computation.step;

import com.google.common.base.Function;
import com.google.common.collect.Iterables;
@@ -43,6 +43,9 @@ 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.DumbComponent;
import org.sonar.server.computation.period.Period;
import org.sonar.server.computation.period.PeriodFinder;
import org.sonar.server.computation.period.PeriodsHolderImpl;
import org.sonar.server.db.DbClient;
import org.sonar.test.DbTests;

@@ -50,7 +53,7 @@ import static com.google.common.collect.Lists.newArrayList;
import static org.assertj.core.api.Assertions.assertThat;

@Category(DbTests.class)
public class PeriodsRepositoryTest {
public class FeedPeriodsStepTest extends BaseStepTest {

private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
private static final String PROJECT_KEY = "PROJECT_KEY";
@@ -64,13 +67,20 @@ public class PeriodsRepositoryTest {
@Rule
public BatchReportReaderRule reportReader = new BatchReportReaderRule();

PeriodsHolderImpl periodsHolder = new PeriodsHolderImpl();

DbClient dbClient;

DbSession dbSession;

Settings settings = new Settings();

PeriodsRepository periodsRepository;
FeedPeriodsStep sut;

@Override
protected ComputationStep step() {
return sut;
}

@Before
public void setUp() throws Exception {
@@ -91,7 +101,7 @@ public class PeriodsRepositoryTest {
Component project = new DumbComponent(Component.Type.PROJECT, 1, "ABCD", PROJECT_KEY);
treeRootHolder.setRoot(project);

periodsRepository = new PeriodsRepository(dbClient, settings, treeRootHolder, new PeriodFinder(dbClient), reportReader);
sut = new FeedPeriodsStep(dbClient, settings, treeRootHolder, new PeriodFinder(dbClient), reportReader, periodsHolder);
}

@After
@@ -103,7 +113,8 @@ public class PeriodsRepositoryTest {
public void no_period_on_first_analysis() throws Exception {
// No project, no snapshot

assertThat(periodsRepository.getPeriods()).isEmpty();
sut.execute();
assertThat(periodsHolder.getPeriods()).isEmpty();
}

@Test
@@ -114,7 +125,8 @@ public class PeriodsRepositoryTest {
Date date = DATE_FORMAT.parse(textDate);
settings.setProperty("sonar.timemachine.period1", textDate);

List<Period> periods = periodsRepository.getPeriods();
sut.execute();
List<Period> periods = periodsHolder.getPeriods();
assertThat(periods).hasSize(1);

Period period = periods.get(0);
@@ -131,7 +143,8 @@ public class PeriodsRepositoryTest {

settings.setProperty("sonar.timemachine.period1", "UNKNWOWN VERSION");

assertThat(periodsRepository.getPeriods()).isEmpty();
sut.execute();
assertThat(periodsHolder.getPeriods()).isEmpty();
}

@Test
@@ -140,7 +153,8 @@ public class PeriodsRepositoryTest {

settings.setProperty("sonar.timemachine.period1", "");

assertThat(periodsRepository.getPeriods()).isEmpty();
sut.execute();
assertThat(periodsHolder.getPeriods()).isEmpty();
}

@Test
@@ -153,7 +167,9 @@ public class PeriodsRepositoryTest {
settings.setProperty("sonar.timemachine.period4", "previous_version"); // Analysis from 2008-11-12 should be returned
settings.setProperty("sonar.timemachine.period5", "0.9"); // Anaylsis from 2008-11-11

List<Period> periods = periodsRepository.getPeriods();
sut.execute();
List<Period> periods = periodsHolder.getPeriods();

List<String> periodModes = newArrayList(Iterables.transform(periods, new Function<Period, String>() {
@Override
public String apply(Period input) {
@@ -191,21 +207,8 @@ public class PeriodsRepositoryTest {
settings.setProperty("sonar.timemachine.period4.TRK", "2008-11-22");
settings.setProperty("sonar.timemachine.period5.TRK", "previous_analysis");

assertThat(periodsRepository.getPeriods()).hasSize(2);
}

@Test
public void only_load_periods_on_first_call_of_get_periods() throws Exception {
dbTester.prepareDbUnit(getClass(), "shared.xml");

settings.setProperty("sonar.timemachine.period1", "2008-11-22");

// First call, periods are loaded
assertThat(periodsRepository.getPeriods()).hasSize(1);

// Second call, set project without key to check that it won't fail with a NPE
treeRootHolder.setRoot(new DumbComponent(Component.Type.PROJECT, 1, null, null));
assertThat(periodsRepository.getPeriods()).hasSize(1);
sut.execute();
assertThat(periodsHolder.getPeriods()).hasSize(2);
}

}

server/sonar-server/src/test/resources/org/sonar/server/computation/period/PeriodsRepositoryTest/shared.xml → server/sonar-server/src/test/resources/org/sonar/server/computation/step/FeedPeriodsStepTest/shared.xml View File


Loading…
Cancel
Save