From 85cdf23ec2bc1f4e596e6c4a200fa19ac344cc66 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Mon, 8 Jun 2015 11:31:32 +0200 Subject: [PATCH] SONAR-6260 Replace PeriodsRepository by a PeriodsHolder --- .../container/ComputeEngineContainerImpl.java | 4 +- .../server/computation/period/Period.java | 4 +- .../computation/period/PeriodFinder.java | 10 ++-- .../computation/period/PeriodsHolder.java | 37 +++++++++++++ .../computation/period/PeriodsHolderImpl.java | 43 +++++++++++++++ .../computation/step/ComputationSteps.java | 1 + .../FeedPeriodsStep.java} | 42 ++++++++------ .../period/PeriodsHolderImplTest.java | 55 +++++++++++++++++++ .../FeedPeriodsStepTest.java} | 51 +++++++++-------- .../FeedPeriodsStepTest}/shared.xml | 0 10 files changed, 196 insertions(+), 51 deletions(-) create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/period/PeriodsHolder.java create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/period/PeriodsHolderImpl.java rename server/sonar-server/src/main/java/org/sonar/server/computation/{period/PeriodsRepository.java => step/FeedPeriodsStep.java} (85%) create mode 100644 server/sonar-server/src/test/java/org/sonar/server/computation/period/PeriodsHolderImplTest.java rename server/sonar-server/src/test/java/org/sonar/server/computation/{period/PeriodsRepositoryTest.java => step/FeedPeriodsStepTest.java} (86%) rename server/sonar-server/src/test/resources/org/sonar/server/computation/{period/PeriodsRepositoryTest => step/FeedPeriodsStepTest}/shared.xml (100%) diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java index 103dc9ce2e9..b92b939d01d 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java @@ -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 diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/period/Period.java b/server/sonar-server/src/main/java/org/sonar/server/computation/period/Period.java index 0ad15f72db8..6b7af6e0391 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/period/Period.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/period/Period.java @@ -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; } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/period/PeriodFinder.java b/server/sonar-server/src/main/java/org/sonar/server/computation/period/PeriodFinder.java index a451fd68d70..8b7efa5e5ed 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/period/PeriodFinder.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/period/PeriodFinder.java @@ -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 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 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; diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/period/PeriodsHolder.java b/server/sonar-server/src/main/java/org/sonar/server/computation/period/PeriodsHolder.java new file mode 100644 index 00000000000..622922f23ce --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/period/PeriodsHolder.java @@ -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 getPeriods(); + +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/period/PeriodsHolderImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/period/PeriodsHolderImpl.java new file mode 100644 index 00000000000..f11422f33ce --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/period/PeriodsHolderImpl.java @@ -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 periods = new ArrayList<>(); + + public void setPeriods(List periods) { + this.periods = periods; + isPeriodsInitialized = true; + } + + @Override + public List getPeriods() { + Preconditions.checkArgument(isPeriodsInitialized, "Periods have not been initialized yet"); + return periods; + } + +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java index 36492c13f77..57396619bdb 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java @@ -52,6 +52,7 @@ public class ComputationSteps { QualityGateEventsStep.class, // Persist data + FeedPeriodsStep.class, PersistComponentsStep.class, PersistSnapshotsStep.class, PersistNumberOfDaysSinceLastCommitStep.class, diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/period/PeriodsRepository.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/FeedPeriodsStep.java similarity index 85% rename from server/sonar-server/src/main/java/org/sonar/server/computation/period/PeriodsRepository.java rename to server/sonar-server/src/main/java/org/sonar/server/computation/step/FeedPeriodsStep.java index cf2181f8cf8..7612c910331 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/period/PeriodsRepository.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/FeedPeriodsStep.java @@ -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 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 getPeriods(){ - if (periods.isEmpty()) { - initPeriods(); - } - return periods; + @Override + public void execute() { + periodsHolder.setPeriods(createPeriods()); } - private void initPeriods() { + private List createPeriods() { + List 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"; + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/period/PeriodsHolderImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/period/PeriodsHolderImplTest.java new file mode 100644 index 00000000000..6f7f6d863ba --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/period/PeriodsHolderImplTest.java @@ -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 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(); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/period/PeriodsRepositoryTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/FeedPeriodsStepTest.java similarity index 86% rename from server/sonar-server/src/test/java/org/sonar/server/computation/period/PeriodsRepositoryTest.java rename to server/sonar-server/src/test/java/org/sonar/server/computation/step/FeedPeriodsStepTest.java index 9a61d70a266..699d5bdf79d 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/period/PeriodsRepositoryTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/FeedPeriodsStepTest.java @@ -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 periods = periodsRepository.getPeriods(); + sut.execute(); + List 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 periods = periodsRepository.getPeriods(); + sut.execute(); + List periods = periodsHolder.getPeriods(); + List periodModes = newArrayList(Iterables.transform(periods, new Function() { @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); } } diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/period/PeriodsRepositoryTest/shared.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/step/FeedPeriodsStepTest/shared.xml similarity index 100% rename from server/sonar-server/src/test/resources/org/sonar/server/computation/period/PeriodsRepositoryTest/shared.xml rename to server/sonar-server/src/test/resources/org/sonar/server/computation/step/FeedPeriodsStepTest/shared.xml -- 2.39.5