diff options
author | Duarte Meneses <duarte.meneses@sonarsource.com> | 2019-08-08 13:43:01 -0500 |
---|---|---|
committer | SonarTech <sonartech@sonarsource.com> | 2019-09-24 20:21:13 +0200 |
commit | 7eaf366fa7f51a69032d840b466f5068ce88239b (patch) | |
tree | 35f366da92ef96544bdcf3b99af55b9258812c41 /server/sonar-ce-task-projectanalysis | |
parent | 14bd90f47ee950d4ee780cbd2a030cac5cb034c0 (diff) | |
download | sonarqube-7eaf366fa7f51a69032d840b466f5068ce88239b.tar.gz sonarqube-7eaf366fa7f51a69032d840b466f5068ce88239b.zip |
SONAR-12394 Load analysis new code period based on hierarchy of New Code Period settings
Diffstat (limited to 'server/sonar-ce-task-projectanalysis')
11 files changed, 321 insertions, 769 deletions
diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/period/Period.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/period/Period.java index 36bdb76fbdc..66dce6fbb94 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/period/Period.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/period/Period.java @@ -34,13 +34,11 @@ public class Period { @CheckForNull private final String modeParameter; private final long snapshotDate; - private final String analysisUuid; - public Period(String mode, @Nullable String modeParameter, long snapshotDate, String analysisUuid) { + public Period(String mode, @Nullable String modeParameter, long snapshotDate) { this.mode = requireNonNull(mode); this.modeParameter = modeParameter; this.snapshotDate = snapshotDate; - this.analysisUuid = analysisUuid; } public String getMode() { @@ -56,10 +54,6 @@ public class Period { return snapshotDate; } - public String getAnalysisUuid() { - return analysisUuid; - } - @Override public boolean equals(@Nullable Object o) { if (this == o) { @@ -70,14 +64,13 @@ public class Period { } Period period = (Period) o; return snapshotDate == period.snapshotDate - && Objects.equals(analysisUuid, period.analysisUuid) && mode.equals(period.mode) && Objects.equals(modeParameter, period.modeParameter); } @Override public int hashCode() { - return hash(mode, modeParameter, snapshotDate, analysisUuid); + return hash(mode, modeParameter, snapshotDate); } @Override @@ -86,7 +79,6 @@ public class Period { .add("mode", mode) .add("modeParameter", modeParameter) .add("snapshotDate", snapshotDate) - .add("analysisUuid", analysisUuid) .toString(); } } diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/LoadPeriodsStep.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/LoadPeriodsStep.java index c153c31afe9..d646d03a213 100644 --- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/LoadPeriodsStep.java +++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/LoadPeriodsStep.java @@ -21,25 +21,16 @@ package org.sonar.ce.task.projectanalysis.step; import java.time.Duration; import java.time.Instant; -import java.time.LocalDate; -import java.time.ZoneId; -import java.time.format.DateTimeParseException; import java.time.temporal.ChronoUnit; -import java.util.Arrays; import java.util.List; import java.util.Optional; import java.util.function.Supplier; -import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.sonar.api.utils.DateUtils; import org.sonar.api.utils.MessageException; -import org.sonar.api.utils.System2; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder; -import org.sonar.ce.task.projectanalysis.analysis.Branch; -import org.sonar.ce.task.projectanalysis.component.Component; -import org.sonar.ce.task.projectanalysis.component.ConfigurationRepository; import org.sonar.ce.task.projectanalysis.component.TreeRootHolder; import org.sonar.ce.task.projectanalysis.period.Period; import org.sonar.ce.task.projectanalysis.period.PeriodHolder; @@ -47,21 +38,17 @@ import org.sonar.ce.task.projectanalysis.period.PeriodHolderImpl; import org.sonar.ce.task.step.ComputationStep; import org.sonar.db.DbClient; import org.sonar.db.DbSession; -import org.sonar.db.component.BranchDto; -import org.sonar.db.component.BranchType; import org.sonar.db.component.SnapshotDto; import org.sonar.db.component.SnapshotQuery; import org.sonar.db.event.EventDto; +import org.sonar.db.newcodeperiod.NewCodePeriodDao; import org.sonar.db.newcodeperiod.NewCodePeriodDto; +import org.sonar.db.newcodeperiod.NewCodePeriodParser; +import org.sonar.db.newcodeperiod.NewCodePeriodType; +import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import static java.lang.String.format; -import static org.sonar.core.config.CorePropertyDefinitions.LEAK_PERIOD; -import static org.sonar.core.config.CorePropertyDefinitions.LEAK_PERIOD_MODE_DATE; -import static org.sonar.core.config.CorePropertyDefinitions.LEAK_PERIOD_MODE_DAYS; -import static org.sonar.core.config.CorePropertyDefinitions.LEAK_PERIOD_MODE_MANUAL_BASELINE; -import static org.sonar.core.config.CorePropertyDefinitions.LEAK_PERIOD_MODE_PREVIOUS_VERSION; -import static org.sonar.core.config.CorePropertyDefinitions.LEAK_PERIOD_MODE_VERSION; import static org.sonar.db.component.SnapshotDto.STATUS_PROCESSED; import static org.sonar.db.component.SnapshotQuery.SORT_FIELD.BY_DATE; import static org.sonar.db.component.SnapshotQuery.SORT_ORDER.ASC; @@ -78,20 +65,18 @@ public class LoadPeriodsStep implements ComputationStep { private static final Logger LOG = Loggers.get(LoadPeriodsStep.class); private final AnalysisMetadataHolder analysisMetadataHolder; + private final NewCodePeriodDao newCodePeriodDao; private final TreeRootHolder treeRootHolder; private final PeriodHolderImpl periodsHolder; - private final System2 system2; private final DbClient dbClient; - private final ConfigurationRepository configRepository; - public LoadPeriodsStep(AnalysisMetadataHolder analysisMetadataHolder, TreeRootHolder treeRootHolder, PeriodHolderImpl periodsHolder, - System2 system2, DbClient dbClient, ConfigurationRepository configRepository) { + public LoadPeriodsStep(AnalysisMetadataHolder analysisMetadataHolder, NewCodePeriodDao newCodePeriodDao, TreeRootHolder treeRootHolder, + PeriodHolderImpl periodsHolder, DbClient dbClient) { this.analysisMetadataHolder = analysisMetadataHolder; + this.newCodePeriodDao = newCodePeriodDao; this.treeRootHolder = treeRootHolder; this.periodsHolder = periodsHolder; - this.system2 = system2; this.dbClient = dbClient; - this.configRepository = configRepository; } @Override @@ -106,169 +91,127 @@ public class LoadPeriodsStep implements ComputationStep { return; } - periodsHolder.setPeriod(resolvePeriod(treeRootHolder.getRoot()).orElse(null)); - } - - private Optional<Period> resolvePeriod(Component projectOrView) { - String currentVersion = projectOrView.getProjectAttributes().getProjectVersion(); - Optional<String> propertyValue = configRepository.getConfiguration().get(LEAK_PERIOD) - .filter(t -> !t.isEmpty()); - checkPeriodProperty(propertyValue.isPresent(), "", "property is undefined or value is empty"); + String projectUuid = getProjectBranchUuid(); + String branchUuid = treeRootHolder.getRoot().getUuid(); + String projectVersion = treeRootHolder.getRoot().getProjectAttributes().getProjectVersion(); try (DbSession dbSession = dbClient.openSession(false)) { - Optional<Period> manualBaselineOpt = resolveByManualBaseline(dbSession, projectOrView.getUuid()); - if (manualBaselineOpt.isPresent()) { - return manualBaselineOpt; - } - return resolve(dbSession, projectOrView.getUuid(), currentVersion, propertyValue.get()); + Optional<NewCodePeriodDto> dto = firstPresent( + () -> getBranchSetting(dbSession, projectUuid, branchUuid), + () -> getProjectSetting(dbSession, projectUuid), + () -> getGlobalSetting(dbSession)); + + Period period = dto.map(d -> toPeriod(d.getType(), d.getValue(), dbSession, projectVersion, branchUuid)) + .orElseGet(() -> toPeriod(NewCodePeriodType.PREVIOUS_VERSION, null, dbSession, projectVersion, branchUuid)); + periodsHolder.setPeriod(period); } } - private Optional<Period> resolveByManualBaseline(DbSession dbSession, String projectUuid) { - Branch branch = analysisMetadataHolder.getBranch(); - if (branch.getType() != BranchType.LONG) { - return Optional.empty(); + private <T> Optional<T> firstPresent(Supplier<Optional<T>>... suppliers) { + for (Supplier<Optional<T>> supplier : suppliers) { + Optional<T> result = supplier.get(); + if (result.isPresent()) { + return result; + } } + return Optional.empty(); + } - return dbClient.branchDao().selectByUuid(dbSession, projectUuid) - .map(branchDto -> resolveByManualBaseline(dbSession, projectUuid, branchDto)); + private Optional<NewCodePeriodDto> getBranchSetting(DbSession dbSession, String projectUuid, String branchUuid) { + return newCodePeriodDao.selectByBranch(dbSession, projectUuid, branchUuid); } - private Period resolveByManualBaseline(DbSession dbSession, String projectUuid, BranchDto branchDto) { - String baselineAnalysisUuid = dbClient.newCodePeriodDao().selectByBranch(dbSession, projectUuid, branchDto.getUuid()) - .map(NewCodePeriodDto::getValue) - .orElse(null); - if (baselineAnalysisUuid == null) { - return null; - } + private Optional<NewCodePeriodDto> getProjectSetting(DbSession dbSession, String projectUuid) { + return newCodePeriodDao.selectByProject(dbSession, projectUuid); + } - LOG.debug("Resolving new code period by manual baseline"); - SnapshotDto baseline = dbClient.snapshotDao().selectByUuid(dbSession, baselineAnalysisUuid) - .filter(t -> t.getComponentUuid().equals(projectUuid)) - .orElseThrow(() -> new IllegalStateException("Analysis '" + baselineAnalysisUuid + "' of project '" + projectUuid - + "' defined as manual baseline does not exist")); - return newPeriod(LEAK_PERIOD_MODE_MANUAL_BASELINE, null, baseline); + private Optional<NewCodePeriodDto> getGlobalSetting(DbSession dbSession) { + return newCodePeriodDao.selectGlobal(dbSession); } - private Optional<Period> resolve(DbSession dbSession, String projectUuid, String analysisProjectVersion, String propertyValue) { - Integer days = parseDaysQuietly(propertyValue); - if (days != null) { - return resolveByDays(dbSession, projectUuid, days, propertyValue); - } - Instant date = parseDate(propertyValue); - if (date != null) { - return resolveByDate(dbSession, projectUuid, date, propertyValue); + private Period toPeriod(NewCodePeriodType type, @Nullable String value, DbSession dbSession, String analysisProjectVersion, String rootUuid) { + switch (type) { + case NUMBER_OF_DAYS: + Integer days = NewCodePeriodParser.parseDays(value); + checkNotNullValue(value, type); + return resolveByDays(dbSession, rootUuid, days, value); + case PREVIOUS_VERSION: + return resolveByPreviousVersion(dbSession, rootUuid, analysisProjectVersion); + case SPECIFIC_ANALYSIS: + checkNotNullValue(value, type); + return resolveBySpecificAnalysis(dbSession, rootUuid, value); + default: + throw new IllegalStateException("Unexpected type: " + type); } + } + private String getProjectBranchUuid() { + return analysisMetadataHolder.getProject().getUuid(); + } + + private Period resolveBySpecificAnalysis(DbSession dbSession, String rootUuid, String value) { + SnapshotDto baseline = dbClient.snapshotDao().selectByUuid(dbSession, value) + .filter(t -> t.getComponentUuid().equals(rootUuid)) + .orElseThrow(() -> new IllegalStateException("Analysis '" + value + "' of project '" + rootUuid + + "' defined as the baseline does not exist")); + LOG.debug("Resolving new code period with a specific analysis"); + return newPeriod(NewCodePeriodType.SPECIFIC_ANALYSIS, value, Instant.ofEpochMilli(baseline.getCreatedAt())); + } + + private Period resolveByPreviousVersion(DbSession dbSession, String projectUuid, String analysisProjectVersion) { List<EventDto> versions = dbClient.eventDao().selectVersionsByMostRecentFirst(dbSession, projectUuid); if (versions.isEmpty()) { - return resolveWhenNoExistingVersion(dbSession, projectUuid, analysisProjectVersion, propertyValue); + return findOldestAnalysis(dbSession, projectUuid); } String mostRecentVersion = Optional.ofNullable(versions.iterator().next().getName()) .orElseThrow(() -> new IllegalStateException("selectVersionsByMostRecentFirst returned a DTO which didn't have a name")); - boolean previousVersionPeriod = LEAK_PERIOD_MODE_PREVIOUS_VERSION.equals(propertyValue); - if (previousVersionPeriod) { - if (versions.size() == 1) { - return resolvePreviousVersionWithOnlyOneExistingVersion(dbSession, projectUuid); - } - return resolvePreviousVersion(dbSession, analysisProjectVersion, versions, mostRecentVersion); + if (versions.size() == 1) { + return findOldestAnalysis(dbSession, projectUuid); } - - return resolveVersion(dbSession, versions, propertyValue); + return resolvePreviousVersion(dbSession, analysisProjectVersion, versions, mostRecentVersion); } - @CheckForNull - private static Instant parseDate(String propertyValue) { - try { - LocalDate localDate = LocalDate.parse(propertyValue); - return localDate.atStartOfDay(ZoneId.systemDefault()).toInstant(); - } catch (DateTimeParseException e) { - boolean invalidDate = e.getCause() == null || e.getCause() == e || !e.getCause().getMessage().contains("Invalid date"); - checkPeriodProperty(invalidDate, propertyValue, "Invalid date"); - return null; - } - } - - private Optional<Period> resolveByDays(DbSession dbSession, String projectUuid, Integer days, String propertyValue) { + private Period resolveByDays(DbSession dbSession, String rootUuid, Integer days, String propertyValue) { checkPeriodProperty(days > 0, propertyValue, "number of days is <= 0"); long analysisDate = analysisMetadataHolder.getAnalysisDate(); - List<SnapshotDto> snapshots = dbClient.snapshotDao().selectAnalysesByQuery(dbSession, createCommonQuery(projectUuid).setCreatedBefore(analysisDate).setSort(BY_DATE, ASC)); - ensureNotOnFirstAnalysis(!snapshots.isEmpty()); + List<SnapshotDto> snapshots = dbClient.snapshotDao().selectAnalysesByQuery(dbSession, createCommonQuery(rootUuid) + .setCreatedBefore(analysisDate).setSort(BY_DATE, ASC)); + ensureNotOnFirstAnalysis(!snapshots.isEmpty()); Instant targetDate = DateUtils.addDays(Instant.ofEpochMilli(analysisDate), -days); LOG.debug("Resolving new code period by {} days: {}", days, supplierToString(() -> logDate(targetDate))); SnapshotDto snapshot = findNearestSnapshotToTargetDate(snapshots, targetDate); - - return Optional.of(newPeriod(LEAK_PERIOD_MODE_DAYS, String.valueOf((int) days), snapshot)); + return newPeriod(NewCodePeriodType.NUMBER_OF_DAYS, String.valueOf((int) days), Instant.ofEpochMilli(snapshot.getCreatedAt())); } - private Optional<Period> resolveByDate(DbSession dbSession, String projectUuid, Instant date, String propertyValue) { - Instant now = Instant.ofEpochMilli(system2.now()); - checkPeriodProperty(date.compareTo(now) <= 0, propertyValue, - "date is in the future (now: '%s')", supplierToString(() -> logDate(now))); - - LOG.debug("Resolving new code period by date: {}", supplierToString(() -> logDate(date))); - Optional<Period> period = findFirstSnapshot(dbSession, createCommonQuery(projectUuid).setCreatedAfter(date.toEpochMilli()).setSort(BY_DATE, ASC)) - .map(dto -> newPeriod(LEAK_PERIOD_MODE_DATE, DateUtils.formatDate(date), dto)); - - checkPeriodProperty(period.isPresent(), propertyValue, "No analysis found created after date '%s'", supplierToString(() -> logDate(date))); - return period; - } - - private Optional<Period> resolveWhenNoExistingVersion(DbSession dbSession, String projectUuid, String currentVersion, String propertyValue) { - LOG.debug("Resolving first analysis as new code period as there is no existing version"); - - boolean previousVersionPeriod = LEAK_PERIOD_MODE_PREVIOUS_VERSION.equals(propertyValue); - boolean currentVersionPeriod = currentVersion.equals(propertyValue); - checkPeriodProperty(previousVersionPeriod || currentVersionPeriod, propertyValue, - "No existing version. Property should be either '%s' or the current version '%s' (actual: '%s')", - LEAK_PERIOD_MODE_PREVIOUS_VERSION, currentVersion, propertyValue); - - String periodMode = previousVersionPeriod ? LEAK_PERIOD_MODE_PREVIOUS_VERSION : LEAK_PERIOD_MODE_VERSION; - return findOldestAnalysis(dbSession, periodMode, projectUuid); + private Period resolvePreviousVersion(DbSession dbSession, String currentVersion, List<EventDto> versions, String mostRecentVersion) { + EventDto previousVersion = versions.get(currentVersion.equals(mostRecentVersion) ? 1 : 0); + LOG.debug("Resolving new code period by previous version: {}", previousVersion.getName()); + return newPeriod(dbSession, previousVersion); } - private Optional<Period> resolvePreviousVersionWithOnlyOneExistingVersion(DbSession dbSession, String projectUuid) { + private Period findOldestAnalysis(DbSession dbSession, String projectUuid) { LOG.debug("Resolving first analysis as new code period as there is only one existing version"); - return findOldestAnalysis(dbSession, LEAK_PERIOD_MODE_PREVIOUS_VERSION, projectUuid); - } - - private Optional<Period> findOldestAnalysis(DbSession dbSession, String periodMode, String projectUuid) { Optional<Period> period = dbClient.snapshotDao().selectOldestSnapshot(dbSession, projectUuid) - .map(dto -> newPeriod(periodMode, null, dto)); + .map(dto -> newPeriod(NewCodePeriodType.PREVIOUS_VERSION, null, Instant.ofEpochMilli(dto.getCreatedAt()))); ensureNotOnFirstAnalysis(period.isPresent()); - return period; + return period.get(); } - private Optional<Period> resolvePreviousVersion(DbSession dbSession, String currentVersion, List<EventDto> versions, String mostRecentVersion) { - EventDto previousVersion = versions.get(currentVersion.equals(mostRecentVersion) ? 1 : 0); - LOG.debug("Resolving new code period by previous version: {}", previousVersion.getName()); - return newPeriod(dbSession, LEAK_PERIOD_MODE_PREVIOUS_VERSION, previousVersion); - } - - private Optional<Period> resolveVersion(DbSession dbSession, List<EventDto> versions, String propertyValue) { - LOG.debug("Resolving new code period by version: {}", propertyValue); - Optional<EventDto> version = versions.stream().filter(t -> propertyValue.equals(t.getName())).findFirst(); - checkPeriodProperty(version.isPresent(), propertyValue, - "version is none of the existing ones: %s", supplierToString(() -> toVersions(versions))); - - return newPeriod(dbSession, LEAK_PERIOD_MODE_VERSION, version.get()); - } - - private Optional<Period> newPeriod(DbSession dbSession, String periodMode, EventDto previousVersion) { + private Period newPeriod(DbSession dbSession, EventDto previousVersion) { Optional<Period> period = dbClient.snapshotDao().selectByUuid(dbSession, previousVersion.getAnalysisUuid()) - .map(dto -> newPeriod(periodMode, previousVersion.getName(), dto)); + .map(dto -> newPeriod(NewCodePeriodType.PREVIOUS_VERSION, dto.getProjectVersion(), Instant.ofEpochMilli(dto.getCreatedAt()))); if (!period.isPresent()) { throw new IllegalStateException(format("Analysis '%s' for version event '%s' has been deleted", previousVersion.getAnalysisUuid(), previousVersion.getName())); } - return period; + return period.get(); } - private static String toVersions(List<EventDto> versions) { - return Arrays.toString(versions.stream().map(EventDto::getName).toArray(String[]::new)); + private static Period newPeriod(NewCodePeriodType type, @Nullable String value, Instant instant) { + return new Period(type.name(), value, instant.toEpochMilli()); } private static Object supplierToString(Supplier<String> s) { @@ -280,37 +223,8 @@ public class LoadPeriodsStep implements ComputationStep { }; } - private static Period newPeriod(String mode, @Nullable String modeParameter, SnapshotDto dto) { - return new Period(mode, modeParameter, dto.getCreatedAt(), dto.getUuid()); - } - - private static void checkPeriodProperty(boolean test, String propertyValue, String testDescription, Object... args) { - if (!test) { - LOG.debug("Invalid code period '{}': {}", propertyValue, supplierToString(() -> format(testDescription, args))); - throw MessageException.of(format("Invalid new code period. '%s' is not one of: " + - "integer > 0, date before current analysis j, \"previous_version\", or version string that exists in the project' \n" + - "Please contact a project administrator to correct this setting", propertyValue)); - } - } - - private Optional<SnapshotDto> findFirstSnapshot(DbSession session, SnapshotQuery query) { - return dbClient.snapshotDao().selectAnalysesByQuery(session, query) - .stream() - .findFirst(); - } - - private static void ensureNotOnFirstAnalysis(boolean expression) { - checkState(expression, "Attempting to resolve period while no analysis exist for project"); - } - - @CheckForNull - private static Integer parseDaysQuietly(String property) { - try { - return Integer.parseInt(property); - } catch (NumberFormatException e) { - // Nothing to, it means that the property is not a number of days - return null; - } + private static SnapshotQuery createCommonQuery(String projectUuid) { + return new SnapshotQuery().setComponentUuid(projectUuid).setStatus(STATUS_PROCESSED); } private static SnapshotDto findNearestSnapshotToTargetDate(List<SnapshotDto> snapshots, Instant targetDate) { @@ -328,8 +242,21 @@ public class LoadPeriodsStep implements ComputationStep { return nearest; } - private static SnapshotQuery createCommonQuery(String projectUuid) { - return new SnapshotQuery().setComponentUuid(projectUuid).setStatus(STATUS_PROCESSED); + private static void checkPeriodProperty(boolean test, String propertyValue, String testDescription, Object... args) { + if (!test) { + LOG.debug("Invalid code period '{}': {}", propertyValue, supplierToString(() -> format(testDescription, args))); + throw MessageException.of(format("Invalid new code period. '%s' is not one of: " + + "integer > 0, date before current analysis j, \"previous_version\", or version string that exists in the project' \n" + + "Please contact a project administrator to correct this setting", propertyValue)); + } + } + + private static void ensureNotOnFirstAnalysis(boolean expression) { + checkState(expression, "Attempting to resolve period while no analysis exist for project"); + } + + private static void checkNotNullValue(@Nullable String value, NewCodePeriodType type) { + checkNotNull(value, "Value can't be null with type %s", type); } private static String logDate(Instant instant) { diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/IssueCounterTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/IssueCounterTest.java index 7a5477afc2d..97b130159a5 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/IssueCounterTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/IssueCounterTest.java @@ -440,7 +440,7 @@ public class IssueCounterTest { } private static Period newPeriod(long date) { - return new Period("mode", null, date, "U1"); + return new Period("mode", null, date); } } diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/NewEffortAggregatorTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/NewEffortAggregatorTest.java index 2431763a984..9f58ea05d49 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/NewEffortAggregatorTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/NewEffortAggregatorTest.java @@ -36,6 +36,7 @@ import org.sonar.ce.task.projectanalysis.period.Period; import org.sonar.ce.task.projectanalysis.period.PeriodHolderRule; import org.sonar.core.issue.DefaultIssue; import org.sonar.db.component.BranchType; +import org.sonar.db.newcodeperiod.NewCodePeriodType; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.guava.api.Assertions.assertThat; @@ -55,7 +56,7 @@ import static org.sonar.core.config.CorePropertyDefinitions.LEAK_PERIOD_MODE_PRE public class NewEffortAggregatorTest { - private static final Period PERIOD = new Period(LEAK_PERIOD_MODE_PREVIOUS_VERSION, null, 1_500_000_000L, "U1"); + private static final Period PERIOD = new Period(NewCodePeriodType.PREVIOUS_VERSION.name(), null, 1_500_000_000L); private static final long[] OLD_ISSUES_DATES = new long[] { PERIOD.getSnapshotDate(), PERIOD.getSnapshotDate() - 1, diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/period/PeriodHolderImplTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/period/PeriodHolderImplTest.java index d19c5666a22..006d66b6b9c 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/period/PeriodHolderImplTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/period/PeriodHolderImplTest.java @@ -78,6 +78,6 @@ public class PeriodHolderImplTest { } private static Period createPeriod() { - return new Period(1 + "mode", null, 1000L, "U1"); + return new Period(1 + "mode", null, 1000L); } } diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/period/PeriodTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/period/PeriodTest.java index 0ab60a7ee42..3822926dea9 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/period/PeriodTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/period/PeriodTest.java @@ -22,48 +22,45 @@ package org.sonar.ce.task.projectanalysis.period; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.sonar.db.newcodeperiod.NewCodePeriodType; import static org.assertj.core.api.Assertions.assertThat; -import static org.sonar.core.config.CorePropertyDefinitions.LEAK_PERIOD_MODE_DAYS; import static org.sonar.core.config.CorePropertyDefinitions.LEAK_PERIOD_MODE_VERSION; public class PeriodTest { private static final String SOME_MODE_PARAM = "mode_para"; - private static final long SOME_SNAPSHOT_DATE = 1000l; - private static final String SOME_ANALYSIS_UUID = "U1"; + private static final long SOME_SNAPSHOT_DATE = 1000L; @Rule public ExpectedException expectedException = ExpectedException.none(); @Test public void test_some_setters_and_getters() { - Period period = new Period(LEAK_PERIOD_MODE_VERSION, SOME_MODE_PARAM, SOME_SNAPSHOT_DATE, SOME_ANALYSIS_UUID); + Period period = new Period(NewCodePeriodType.PREVIOUS_VERSION.name(), SOME_MODE_PARAM, SOME_SNAPSHOT_DATE); - assertThat(period.getMode()).isEqualTo(LEAK_PERIOD_MODE_VERSION); + assertThat(period.getMode()).isEqualTo(NewCodePeriodType.PREVIOUS_VERSION.name()); assertThat(period.getModeParameter()).isEqualTo(SOME_MODE_PARAM); assertThat(period.getSnapshotDate()).isEqualTo(SOME_SNAPSHOT_DATE); - assertThat(period.getAnalysisUuid()).isEqualTo(SOME_ANALYSIS_UUID); } @Test public void verify_to_string() { - assertThat(new Period(LEAK_PERIOD_MODE_VERSION, "2.3", 1420034400000L, "U10").toString()) - .isEqualTo("Period{mode=version, modeParameter=2.3, snapshotDate=1420034400000, analysisUuid=U10}"); + assertThat(new Period(NewCodePeriodType.PREVIOUS_VERSION.name(), "2.3", 1420034400000L).toString()) + .isEqualTo("Period{mode=PREVIOUS_VERSION, modeParameter=2.3, snapshotDate=1420034400000}"); } @Test public void equals_is_done_on_all_fields() { - Period period = new Period(LEAK_PERIOD_MODE_VERSION, "2.3", 1420034400000L, "U10"); + Period period = new Period(NewCodePeriodType.NUMBER_OF_DAYS.name(), "2.3", 1420034400000L); - assertThat(period).isEqualTo(new Period(LEAK_PERIOD_MODE_VERSION, "2.3", 1420034400000L, "U10")); + assertThat(period).isEqualTo(new Period(NewCodePeriodType.NUMBER_OF_DAYS.name(), "2.3", 1420034400000L)); assertThat(period).isNotEqualTo(null); assertThat(period).isNotEqualTo("sdsd"); - assertThat(period).isNotEqualTo(new Period(LEAK_PERIOD_MODE_DAYS, "2.3", 1420034400000L, "U10")); - assertThat(period).isNotEqualTo(new Period(LEAK_PERIOD_MODE_VERSION, "2.4", 1420034400000L, "U10")); - assertThat(period).isNotEqualTo(new Period(LEAK_PERIOD_MODE_VERSION, "2.3", 555L, "U10")); - assertThat(period).isNotEqualTo(new Period(LEAK_PERIOD_MODE_VERSION, "2.3", 1420034400000L, "9632554")); + assertThat(period).isNotEqualTo(new Period(NewCodePeriodType.PREVIOUS_VERSION.name(), "2.3", 1420034400000L)); + assertThat(period).isNotEqualTo(new Period(NewCodePeriodType.NUMBER_OF_DAYS.name(), "2.4", 1420034400000L)); + assertThat(period).isNotEqualTo(new Period(NewCodePeriodType.NUMBER_OF_DAYS.name(), "2.3", 1420034410000L)); } } diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewReliabilityAndSecurityRatingMeasuresVisitorTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewReliabilityAndSecurityRatingMeasuresVisitorTest.java index aa29d30d742..213f3c86e6f 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewReliabilityAndSecurityRatingMeasuresVisitorTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewReliabilityAndSecurityRatingMeasuresVisitorTest.java @@ -109,7 +109,7 @@ public class NewReliabilityAndSecurityRatingMeasuresVisitorTest { public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository); @Rule - public PeriodHolderRule periodsHolder = new PeriodHolderRule().setPeriod(new Period("mode", null, LEAK_PERIOD_SNAPSHOT_IN_MILLISEC, "UUID")); + public PeriodHolderRule periodsHolder = new PeriodHolderRule().setPeriod(new Period("mode", null, LEAK_PERIOD_SNAPSHOT_IN_MILLISEC)); @Rule public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule(); diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/source/NewLinesRepositoryTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/source/NewLinesRepositoryTest.java index 8ca4af7f7da..69cfee6ae8a 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/source/NewLinesRepositoryTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/source/NewLinesRepositoryTest.java @@ -68,7 +68,7 @@ public class NewLinesRepositoryTest { @Test public void compute_new_lines_using_scm_info_for_period() { - periodHolder.setPeriod(new Period("", null, 1000L, "")); + periodHolder.setPeriod(new Period("", null, 1000L)); scmInfoRepository.setScmInfo(FILE.getReportAttributes().getRef(), createChangesets(1100L, 900L, 1000L, 800L)); Optional<Set<Integer>> newLines = repository.getNewLines(FILE); @@ -108,7 +108,7 @@ public class NewLinesRepositoryTest { @Test public void return_empty_if_no_report_and_no_scm_info() { - periodHolder.setPeriod(new Period("", null, 1000L, "")); + periodHolder.setPeriod(new Period("", null, 1000L)); Optional<Set<Integer>> newLines = repository.getNewLines(FILE); diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/LoadPeriodsStepTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/LoadPeriodsStepTest.java index 3e6d831ee22..1d253b9e06a 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/LoadPeriodsStepTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/LoadPeriodsStepTest.java @@ -22,9 +22,11 @@ package org.sonar.ce.task.projectanalysis.step; import com.tngtech.java.junit.dataprovider.DataProvider; import com.tngtech.java.junit.dataprovider.DataProviderRunner; import com.tngtech.java.junit.dataprovider.UseDataProvider; -import java.text.SimpleDateFormat; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.ArrayList; import java.util.Arrays; -import java.util.Date; +import java.util.List; import java.util.Random; import java.util.stream.Stream; import javax.annotation.Nullable; @@ -33,49 +35,37 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; -import org.sonar.api.config.internal.MapSettings; import org.sonar.api.utils.MessageException; import org.sonar.api.utils.System2; import org.sonar.api.utils.log.LogAndArguments; import org.sonar.api.utils.log.LogTester; import org.sonar.api.utils.log.LoggerLevel; import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder; -import org.sonar.ce.task.projectanalysis.analysis.Branch; import org.sonar.ce.task.projectanalysis.component.Component; -import org.sonar.ce.task.projectanalysis.component.ConfigurationRepository; import org.sonar.ce.task.projectanalysis.component.ReportComponent; -import org.sonar.ce.task.projectanalysis.component.TreeRootHolder; import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule; import org.sonar.ce.task.projectanalysis.period.Period; import org.sonar.ce.task.projectanalysis.period.PeriodHolderImpl; import org.sonar.ce.task.step.ComputationStep; import org.sonar.ce.task.step.TestComputationStepContext; -import org.sonar.db.DbClient; +import org.sonar.core.util.SequenceUuidFactory; import org.sonar.db.DbTester; -import org.sonar.db.component.BranchDto; -import org.sonar.db.component.BranchType; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.SnapshotDto; import org.sonar.db.event.EventTesting; -import org.sonar.db.newcodeperiod.NewCodePeriodDto; +import org.sonar.db.newcodeperiod.NewCodePeriodDao; import org.sonar.db.newcodeperiod.NewCodePeriodType; import org.sonar.db.organization.OrganizationDto; +import org.sonar.server.project.Project; import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; -import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; -import static org.sonar.core.config.CorePropertyDefinitions.LEAK_PERIOD_MODE_DATE; -import static org.sonar.core.config.CorePropertyDefinitions.LEAK_PERIOD_MODE_DAYS; -import static org.sonar.core.config.CorePropertyDefinitions.LEAK_PERIOD_MODE_MANUAL_BASELINE; -import static org.sonar.core.config.CorePropertyDefinitions.LEAK_PERIOD_MODE_PREVIOUS_VERSION; -import static org.sonar.core.config.CorePropertyDefinitions.LEAK_PERIOD_MODE_VERSION; import static org.sonar.db.component.SnapshotDto.STATUS_PROCESSED; import static org.sonar.db.component.SnapshotDto.STATUS_UNPROCESSED; import static org.sonar.db.event.EventDto.CATEGORY_VERSION; @@ -83,9 +73,6 @@ import static org.sonar.db.event.EventTesting.newEvent; @RunWith(DataProviderRunner.class) public class LoadPeriodsStepTest extends BaseStepTest { - - private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); - @Rule public DbTester dbTester = DbTester.create(System2.INSTANCE); @Rule @@ -97,14 +84,14 @@ public class LoadPeriodsStepTest extends BaseStepTest { private AnalysisMetadataHolder analysisMetadataHolder = mock(AnalysisMetadataHolder.class); private PeriodHolderImpl periodsHolder = new PeriodHolderImpl(); - private MapSettings settings = new MapSettings(); - private ConfigurationRepository configurationRepository = mock(ConfigurationRepository.class); private System2 system2Mock = mock(System2.class); + private NewCodePeriodDao dao = new NewCodePeriodDao(system2Mock, new SequenceUuidFactory()); + private ZonedDateTime analysisDate = ZonedDateTime.of(2019, 3, 20, 5, 30, 40, 0, ZoneId.systemDefault()); - private LoadPeriodsStep underTest = new LoadPeriodsStep(analysisMetadataHolder, treeRootHolder, periodsHolder, system2Mock, - dbTester.getDbClient(), configurationRepository); + private LoadPeriodsStep underTest = new LoadPeriodsStep(analysisMetadataHolder, dao, treeRootHolder, periodsHolder, dbTester.getDbClient()); - private Date november30th2008; + private OrganizationDto organization; + private ComponentDto project; @Override protected ComputationStep step() { @@ -113,453 +100,185 @@ public class LoadPeriodsStepTest extends BaseStepTest { @Before public void setUp() throws Exception { - november30th2008 = DATE_FORMAT.parse("2008-11-30"); + organization = dbTester.organizations().insert(); + project = dbTester.components().insertMainBranch(organization); + when(analysisMetadataHolder.isLongLivingBranch()).thenReturn(true); + when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(false); + when(analysisMetadataHolder.getAnalysisDate()).thenReturn(analysisDate.toInstant().toEpochMilli()); } @Test - public void no_period_on_first_analysis_and_execute_has_no_effect() { - TreeRootHolder treeRootHolderMock = mock(TreeRootHolder.class); - PeriodHolderImpl periodHolderMock = mock(PeriodHolderImpl.class); - DbClient dbClientMock = mock(DbClient.class); + public void no_period_on_first_analysis() { when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(true); - - LoadPeriodsStep underTest = new LoadPeriodsStep(analysisMetadataHolder, treeRootHolderMock, periodHolderMock, system2Mock, dbClientMock, configurationRepository); - underTest.execute(new TestComputationStepContext()); verify(analysisMetadataHolder).isFirstAnalysis(); - verify(periodHolderMock).setPeriod(null); - verifyNoMoreInteractions(analysisMetadataHolder, periodHolderMock); - verifyZeroInteractions(treeRootHolderMock, system2Mock, dbClientMock, configurationRepository); + assertThat(periodsHolder.hasPeriod()).isFalse(); + verifyNoMoreInteractions(analysisMetadataHolder); } @Test - public void feed_one_period() { - OrganizationDto organization = dbTester.organizations().insert(); - ComponentDto project = dbTester.components().insertMainBranch(organization); - SnapshotDto analysis = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227934800000L)); // 2008-11-29 - when(system2Mock.now()).thenReturn(november30th2008.getTime()); - when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(false); - setupRoot(project); - setupBranchWithNoManualBaseline(project); - String textDate = "2008-11-22"; - - settings.setProperty("sonar.leak.period", textDate); + public void no_period_if_not_LLB() { + when(analysisMetadataHolder.isLongLivingBranch()).thenReturn(false); underTest.execute(new TestComputationStepContext()); - assertPeriod(LEAK_PERIOD_MODE_DATE, textDate, analysis.getCreatedAt(), analysis.getUuid()); + verify(analysisMetadataHolder).isFirstAnalysis(); + verify(analysisMetadataHolder).isLongLivingBranch(); + assertThat(periodsHolder.hasPeriod()).isFalse(); + verifyNoMoreInteractions(analysisMetadataHolder); } @Test - public void ignore_unprocessed_snapshots() { - OrganizationDto organization = dbTester.organizations().insert(); - ComponentDto project = dbTester.components().insertMainBranch(organization); - SnapshotDto analysis1 = dbTester.components() - .insertSnapshot(project, snapshot -> snapshot.setStatus(STATUS_UNPROCESSED).setCreatedAt(1226379600000L).setLast(false));// 2008-11-11 - SnapshotDto analysis2 = dbTester.components().insertSnapshot(project, - snapshot -> snapshot.setStatus(STATUS_PROCESSED).setProjectVersion("not provided").setCreatedAt(1226379600000L).setLast(false));// 2008-11-29 - dbTester.events().insertEvent(newEvent(analysis1).setName("not provided").setCategory(CATEGORY_VERSION).setDate(analysis1.getCreatedAt())); - dbTester.events().insertEvent(newEvent(analysis2).setName("not provided").setCategory(CATEGORY_VERSION).setDate(analysis2.getCreatedAt())); - when(analysisMetadataHolder.getAnalysisDate()).thenReturn(november30th2008.getTime()); - when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(false); + public void load_default_if_nothing_defined() { setupRoot(project); - setupBranchWithNoManualBaseline(project); - - settings.setProperty("sonar.leak.period", "100"); - underTest.execute(new TestComputationStepContext()); - assertPeriod(LEAK_PERIOD_MODE_DAYS, "100", analysis2.getCreatedAt(), analysis2.getUuid()); - verifyDebugLogs("Resolving new code period by 100 days: 2008-08-22"); - } + SnapshotDto analysis = dbTester.components().insertSnapshot(project, + snapshot -> snapshot.setCreatedAt(milisSinceEpoch(2019, 3, 15, 0))); - @Test - public void feed_period_by_date() { - OrganizationDto organization = dbTester.organizations().insert(); - ComponentDto project = dbTester.components().insertMainBranch(organization); - SnapshotDto analysis1 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226379600000L).setLast(false)); // 2008-11-11 - SnapshotDto analysis2 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226494680000L).setLast(false)); // 2008-11-12 - SnapshotDto analysis3 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227157200000L).setLast(false)); // 2008-11-20 - SnapshotDto analysis4 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227358680000L).setLast(false)); // 2008-11-22 - SnapshotDto analysis5 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227934800000L).setLast(true)); // 2008-11-29 - when(system2Mock.now()).thenReturn(november30th2008.getTime()); - when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(false); - setupRoot(project); - setupBranchWithNoManualBaseline(project); - - String textDate = "2008-11-22"; - settings.setProperty("sonar.leak.period", textDate); underTest.execute(new TestComputationStepContext()); - // Return analysis from given date 2008-11-22 - assertPeriod(LEAK_PERIOD_MODE_DATE, textDate, analysis4.getCreatedAt(), analysis4.getUuid()); - - verifyDebugLogs("Resolving new code period by date: 2008-11-22"); + assertPeriod(NewCodePeriodType.PREVIOUS_VERSION, null, analysis.getCreatedAt()); + verifyDebugLogs("Resolving first analysis as new code period as there is only one existing version"); } @Test - @UseDataProvider("branchTypesNotAllowedToHaveManualBaseline") - public void feed_period_by_date_and_ignore_baseline_when_not_eligible_for_manual(BranchType branchType) { - OrganizationDto organization = dbTester.organizations().insert(); - ComponentDto project = dbTester.components().insertMainBranch(organization); - ComponentDto branch = dbTester.components().insertProjectBranch(project, t -> t.setBranchType(branchType)); - SnapshotDto analysis1 = dbTester.components().insertSnapshot(branch, snapshot -> snapshot.setCreatedAt(1226379600000L).setLast(false)); // 2008-11-11 - SnapshotDto analysis2 = dbTester.components().insertSnapshot(branch, snapshot -> snapshot.setCreatedAt(1226494680000L).setLast(false)); // 2008-11-12 - SnapshotDto analysis3 = dbTester.components().insertSnapshot(branch, snapshot -> snapshot.setCreatedAt(1227157200000L).setLast(false)); // 2008-11-20 - SnapshotDto analysis4 = dbTester.components().insertSnapshot(branch, snapshot -> snapshot.setCreatedAt(1227358680000L).setLast(false)); // 2008-11-22 - SnapshotDto analysis5 = dbTester.components().insertSnapshot(branch, snapshot -> snapshot.setCreatedAt(1227934800000L).setLast(true)); // 2008-11-29 - dbTester.newCodePeriods().insert(new NewCodePeriodDto() - .setProjectUuid(project.uuid()) - .setBranchUuid(branch.uuid()) - .setType(NewCodePeriodType.SPECIFIC_ANALYSIS) - .setValue(analysis1.getUuid())); - - dbTester.commit(); - when(system2Mock.now()).thenReturn(november30th2008.getTime()); - when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(false); - setBranchOf(branch); - setupRoot(branch); + public void load_number_of_days_global() { + setGlobalPeriod(NewCodePeriodType.NUMBER_OF_DAYS, "10"); - String textDate = "2008-11-22"; - settings.setProperty("sonar.leak.period", textDate); - underTest.execute(new TestComputationStepContext()); - - // Return analysis from given date 2008-11-22 - assertPeriod(LEAK_PERIOD_MODE_DATE, textDate, analysis4.getCreatedAt(), analysis4.getUuid()); - - verifyDebugLogs("Resolving new code period by date: 2008-11-22"); - } - - @DataProvider - public static Object[][] branchTypesNotAllowedToHaveManualBaseline() { - return new Object[][]{ - {BranchType.SHORT}, - {BranchType.PULL_REQUEST} - }; + testNumberOfDays(project); } @Test - @UseDataProvider("anyValidLeakPeriodSettingValue") - public void do_not_fail_when_project_has_no_BranchDto(String leakPeriodSettingValue) { - OrganizationDto organization = dbTester.organizations().insert(); - // creates row in projects but not in project_branches - ComponentDto project = dbTester.components().insertPrivateProject(organization); - dbTester.components().insertSnapshot(project); - SnapshotDto aVersionAnalysis = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227358680000L).setLast(false));// 2008-11-22 - dbTester.events().insertEvent(EventTesting.newEvent(aVersionAnalysis).setName("a_version").setCategory(CATEGORY_VERSION)); - dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227934800000L).setLast(true)); // 2008-11-29 - when(system2Mock.now()).thenReturn(november30th2008.getTime()); - when(analysisMetadataHolder.getAnalysisDate()).thenReturn(november30th2008.getTime()); - when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(false); - setMetadataBranch(BranchType.LONG); - setupRoot(project); + public void load_number_of_days_on_project() { + setGlobalPeriod(NewCodePeriodType.PREVIOUS_VERSION, null); + setProjectPeriod(project.uuid(), NewCodePeriodType.NUMBER_OF_DAYS, "10"); - settings.setProperty("sonar.leak.period", leakPeriodSettingValue); - underTest.execute(new TestComputationStepContext()); + testNumberOfDays(project); } @Test - @UseDataProvider("anyValidLeakPeriodSettingValue") - public void fail_with_ISE_when_manual_baseline_is_set_but_does_not_exist_in_DB(String leakPeriodSettingValue) { - OrganizationDto organization = dbTester.organizations().insert(); - ComponentDto project = dbTester.components().insertMainBranch(organization); - dbTester.components().setSpecificAnalysisNewCodePeriod(project, new SnapshotDto().setUuid("nonexistent")); - setBranchOf(project); - setupRoot(project); + public void load_number_of_days_on_branch() { + ComponentDto branch = dbTester.components().insertProjectBranch(project); - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage("Analysis 'nonexistent' of project '" + project.uuid() + "' defined as manual baseline does not exist"); + setGlobalPeriod(NewCodePeriodType.PREVIOUS_VERSION, null); + setProjectPeriod(project.uuid(), NewCodePeriodType.PREVIOUS_VERSION, null); + setBranchPeriod(project.uuid(), branch.uuid(), NewCodePeriodType.NUMBER_OF_DAYS, "10"); - settings.setProperty("sonar.leak.period", leakPeriodSettingValue); - underTest.execute(new TestComputationStepContext()); + testNumberOfDays(branch); } - @Test - @UseDataProvider("anyValidLeakPeriodSettingValue") - public void fail_with_ISE_when_manual_baseline_is_set_but_does_not_belong_to_current_project(String leakPeriodSettingValue) { - OrganizationDto organization = dbTester.organizations().insert(); - ComponentDto project = dbTester.components().insertMainBranch(organization); - ComponentDto otherProject = dbTester.components().insertMainBranch(organization); - SnapshotDto otherProjectAnalysis = dbTester.components().insertSnapshot(otherProject); - dbTester.components().setSpecificAnalysisNewCodePeriod(project, otherProjectAnalysis); - setBranchOf(project); - setupRoot(project); - - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage("Analysis '" + otherProjectAnalysis.getUuid() + "' of project '" + project.uuid() - + "' defined as manual baseline does not exist"); + private void testNumberOfDays(ComponentDto projectOrBranch) { + setupRoot(projectOrBranch); - settings.setProperty("sonar.leak.period", leakPeriodSettingValue); - underTest.execute(new TestComputationStepContext()); - } + SnapshotDto analysis = dbTester.components().insertSnapshot(projectOrBranch, + snapshot -> snapshot.setCreatedAt(milisSinceEpoch(2019, 3, 15, 0))); - @Test - @UseDataProvider("anyValidLeakPeriodSettingValue") - public void feed_period_by_manual_baseline_ignores_leak_period_setting(String leakPeriodSettingValue) { - OrganizationDto organization = dbTester.organizations().insert(); - ComponentDto project = dbTester.components().insertMainBranch(organization); - SnapshotDto manualBaselineAnalysis = dbTester.components().insertSnapshot(project); - SnapshotDto aVersionAnalysis = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227358680000L).setLast(false));// 2008-11-22 - dbTester.events().insertEvent(EventTesting.newEvent(aVersionAnalysis).setName("a_version").setCategory(CATEGORY_VERSION)); - dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227934800000L).setLast(true)); // 2008-11-29 - when(system2Mock.now()).thenReturn(november30th2008.getTime()); - when(analysisMetadataHolder.getAnalysisDate()).thenReturn(november30th2008.getTime()); - when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(false); - dbTester.components().setSpecificAnalysisNewCodePeriod(project, manualBaselineAnalysis); - setBranchOf(project); - setupRoot(project); - - settings.setProperty("sonar.leak.period", leakPeriodSettingValue); underTest.execute(new TestComputationStepContext()); - assertPeriod(LEAK_PERIOD_MODE_MANUAL_BASELINE, null, manualBaselineAnalysis.getCreatedAt(), manualBaselineAnalysis.getUuid()); - - verifyDebugLogs("Resolving new code period by manual baseline"); + assertPeriod(NewCodePeriodType.NUMBER_OF_DAYS, "10", analysis.getCreatedAt()); + verifyDebugLogs("Resolving new code period by 10 days: 2019-03-10"); } @Test - @UseDataProvider("anyValidLeakPeriodSettingValue") - public void feed_period_by_manual_baseline_on_long_living_branch(String leakPeriodSettingValue) { - OrganizationDto organization = dbTester.organizations().insert(); - ComponentDto project = dbTester.components().insertMainBranch(organization); + public void load_specific_analysis() { ComponentDto branch = dbTester.components().insertProjectBranch(project); - SnapshotDto manualBaselineAnalysis = dbTester.components().insertSnapshot(branch); - SnapshotDto aVersionAnalysis = dbTester.components().insertSnapshot(branch, snapshot -> snapshot.setCreatedAt(1227358680000L).setLast(false));// 2008-11-22 + SnapshotDto selectedAnalysis = dbTester.components().insertSnapshot(branch); + SnapshotDto aVersionAnalysis = dbTester.components().insertSnapshot(branch, snapshot -> snapshot.setCreatedAt(milisSinceEpoch(2019, 3, 12, 0)).setLast(false)); dbTester.events().insertEvent(EventTesting.newEvent(aVersionAnalysis).setName("a_version").setCategory(CATEGORY_VERSION)); - dbTester.components().insertSnapshot(branch, snapshot -> snapshot.setCreatedAt(1227934800000L).setLast(true)); // 2008-11-29 - when(system2Mock.now()).thenReturn(november30th2008.getTime()); - when(analysisMetadataHolder.getAnalysisDate()).thenReturn(november30th2008.getTime()); - when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(false); - dbTester.components().setSpecificAnalysisNewCodePeriod(branch, manualBaselineAnalysis); - setBranchOf(branch); + dbTester.components().insertSnapshot(branch, snapshot -> snapshot.setCreatedAt(milisSinceEpoch(2019, 3, 15, 0)).setLast(true)); + + setBranchPeriod(project.uuid(), branch.uuid(), NewCodePeriodType.SPECIFIC_ANALYSIS, selectedAnalysis.getUuid()); setupRoot(branch); - settings.setProperty("sonar.leak.period", leakPeriodSettingValue); underTest.execute(new TestComputationStepContext()); - assertPeriod(LEAK_PERIOD_MODE_MANUAL_BASELINE, null, manualBaselineAnalysis.getCreatedAt(), manualBaselineAnalysis.getUuid()); - - verifyDebugLogs("Resolving new code period by manual baseline"); - } - - @DataProvider - public static Object[][] anyValidLeakPeriodSettingValue() { - return new Object[][]{ - // days - {"100"}, - // date - {"2008-11-22"}, - // previous_version keyword - {"previous_version"}, - // an existing version event value - {"a_version"}, - }; + assertPeriod(NewCodePeriodType.SPECIFIC_ANALYSIS, selectedAnalysis.getUuid(), selectedAnalysis.getCreatedAt()); + verifyDebugLogs("Resolving new code period with a specific analysis"); } @Test - public void feed_period_parameter_as_null_when_manual_baseline_has_no_version() { - OrganizationDto organization = dbTester.organizations().insert(); - ComponentDto project = dbTester.components().insertMainBranch(organization); - SnapshotDto manualBaselineAnalysis = dbTester.components().insertSnapshot(project); - dbTester.components().setSpecificAnalysisNewCodePeriod(project, manualBaselineAnalysis); - setBranchOf(project); - setupRoot(project); + public void throw_ISE_if_no_analysis_found_for_number_of_days() { + setProjectPeriod(project.uuid(), NewCodePeriodType.NUMBER_OF_DAYS, "10"); - settings.setProperty("sonar.leak.period", "ignored"); - underTest.execute(new TestComputationStepContext()); - - assertPeriod(LEAK_PERIOD_MODE_MANUAL_BASELINE, null, manualBaselineAnalysis.getCreatedAt(), manualBaselineAnalysis.getUuid()); - } - - @Test - public void feed_period_parameter_as_null_when_manual_baseline_has_same_project_version() { - String version = randomAlphabetic(12); - OrganizationDto organization = dbTester.organizations().insert(); - ComponentDto project = dbTester.components().insertMainBranch(organization); - SnapshotDto manualBaselineAnalysis = dbTester.components().insertSnapshot(project, t -> t.setProjectVersion(version).setProjectVersion(version)); - dbTester.components().setSpecificAnalysisNewCodePeriod(project, manualBaselineAnalysis); - setBranchOf(project); setupRoot(project); - settings.setProperty("sonar.leak.period", "ignored"); - underTest.execute(new TestComputationStepContext()); - - assertPeriod(LEAK_PERIOD_MODE_MANUAL_BASELINE, null, manualBaselineAnalysis.getCreatedAt(), manualBaselineAnalysis.getUuid()); - } - - @Test - public void feed_no_period_parameter_as_projectVersion_when_manual_baseline_has_project_version() { - String projectVersion = randomAlphabetic(15); - OrganizationDto organization = dbTester.organizations().insert(); - ComponentDto project = dbTester.components().insertMainBranch(organization); - SnapshotDto manualBaselineAnalysis = dbTester.components().insertSnapshot(project, t -> t.setProjectVersion(projectVersion)); - dbTester.components().setSpecificAnalysisNewCodePeriod(project, manualBaselineAnalysis); - setBranchOf(project); - setupRoot(project); + expectedException.expect(IllegalStateException.class); + expectedException.expectMessage("Attempting to resolve period while no analysis exist"); - settings.setProperty("sonar.leak.period", "ignored"); underTest.execute(new TestComputationStepContext()); - - assertPeriod(LEAK_PERIOD_MODE_MANUAL_BASELINE, null, manualBaselineAnalysis.getCreatedAt(), manualBaselineAnalysis.getUuid()); } @Test - @UseDataProvider("projectVersionNullOrNot") - public void feed_no_period_parameter_as_version_event_version_when_manual_baseline_has_one(@Nullable String projectVersion) { - String eventVersion = randomAlphabetic(15); - OrganizationDto organization = dbTester.organizations().insert(); - ComponentDto project = dbTester.components().insertMainBranch(organization); - SnapshotDto manualBaselineAnalysis = dbTester.components().insertSnapshot(project, t -> t.setProjectVersion(projectVersion)); - dbTester.events().insertEvent(EventTesting.newEvent(manualBaselineAnalysis).setCategory(CATEGORY_VERSION).setName(eventVersion)); - dbTester.components().setSpecificAnalysisNewCodePeriod(project, manualBaselineAnalysis); - setBranchOf(project); + public void throw_ISE_if_no_analysis_found_with_default() { setupRoot(project); - settings.setProperty("sonar.leak.period", "ignored"); - underTest.execute(new TestComputationStepContext()); - - assertPeriod(LEAK_PERIOD_MODE_MANUAL_BASELINE, null, manualBaselineAnalysis.getCreatedAt(), manualBaselineAnalysis.getUuid()); - } - - @DataProvider - public static Object[][] projectVersionNullOrNot() { - return new Object[][]{ - {null}, - {randomAlphabetic(15)}, - }; - } - - private Branch setBranchOf(ComponentDto project) { - BranchDto branchDto = dbTester.getDbClient().branchDao().selectByUuid(dbTester.getSession(), project.uuid()).get(); - return setMetadataBranch(branchDto.getBranchType()); - } + expectedException.expect(IllegalStateException.class); + expectedException.expectMessage("Attempting to resolve period while no analysis exist"); - private Branch setMetadataBranch(BranchType branchType) { - Branch branch = mock(Branch.class, invoc -> { - throw new UnsupportedOperationException(); - }); - doReturn(branchType).when(branch).getType(); - when(analysisMetadataHolder.getBranch()).thenReturn(branch); - return branch; + underTest.execute(new TestComputationStepContext()); } @Test - public void search_by_date_return_nearest_later_analysis() { - OrganizationDto organization = dbTester.organizations().insert(); - ComponentDto project = dbTester.components().insertMainBranch(organization); - SnapshotDto analysis1 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226379600000L).setLast(false)); // 2008-11-11 - SnapshotDto analysis2 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226494680000L).setLast(false)); // 2008-11-12 - SnapshotDto analysis3 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227157200000L).setLast(false)); // 2008-11-20 - SnapshotDto analysis4 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227358680000L).setLast(false)); // 2008-11-22 - SnapshotDto analysis5 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227934800000L).setLast(true)); // 2008-11-29 - when(system2Mock.now()).thenReturn(november30th2008.getTime()); - when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(false); + public void ignore_unprocessed_snapshots() { + SnapshotDto analysis1 = dbTester.components() + .insertSnapshot(project, snapshot -> snapshot.setStatus(STATUS_UNPROCESSED).setCreatedAt(milisSinceEpoch(2019, 3, 12, 0)).setLast(false)); + SnapshotDto analysis2 = dbTester.components().insertSnapshot(project, + snapshot -> snapshot.setStatus(STATUS_PROCESSED).setProjectVersion("not provided").setCreatedAt(milisSinceEpoch(2019, 3, 15, 0)).setLast(false)); + dbTester.events().insertEvent(newEvent(analysis1).setName("not provided").setCategory(CATEGORY_VERSION).setDate(analysis1.getCreatedAt())); + dbTester.events().insertEvent(newEvent(analysis2).setName("not provided").setCategory(CATEGORY_VERSION).setDate(analysis2.getCreatedAt())); setupRoot(project); - setupBranchWithNoManualBaseline(project); + setProjectPeriod(project.uuid(), NewCodePeriodType.NUMBER_OF_DAYS, "10"); - String date = "2008-11-13"; - settings.setProperty("sonar.leak.period", date); underTest.execute(new TestComputationStepContext()); - // Analysis form 2008-11-20 - assertPeriod(LEAK_PERIOD_MODE_DATE, date, analysis3.getCreatedAt(), analysis3.getUuid()); - verifyDebugLogs("Resolving new code period by date: 2008-11-13"); + assertPeriod(NewCodePeriodType.NUMBER_OF_DAYS, "10", analysis2.getCreatedAt()); + verifyDebugLogs("Resolving new code period by 10 days: 2019-03-10"); } @Test - public void fail_with_MessageException_if_period_is_date_after_today() { + public void throw_ISE_when_specific_analysis_is_set_but_does_not_exist_in_DB() { OrganizationDto organization = dbTester.organizations().insert(); ComponentDto project = dbTester.components().insertMainBranch(organization); - dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227934800000L)); // 2008-11-29 - when(system2Mock.now()).thenReturn(november30th2008.getTime()); - when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(false); - setupRoot(project); - setupBranchWithNoManualBaseline(project); - String propertyValue = "2008-12-01"; - settings.setProperty("sonar.leak.period", propertyValue); - - verifyFailWithInvalidValueMessageException(propertyValue, - "Invalid code period '2008-12-01': date is in the future (now: '2008-11-30')"); - } - - @Test - public void fail_with_MessageException_if_date_does_not_exist() { - OrganizationDto organization = dbTester.organizations().insert(); - ComponentDto project = dbTester.components().insertMainBranch(organization); - dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227934800000L)); // 2008-11-29 - when(system2Mock.now()).thenReturn(november30th2008.getTime()); - when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(false); + setProjectPeriod(project.uuid(), NewCodePeriodType.SPECIFIC_ANALYSIS, "nonexistent"); setupRoot(project); - setupBranchWithNoManualBaseline(project); - String propertyValue = "2008-11-31"; - settings.setProperty("sonar.leak.period", propertyValue); - - verifyFailWithInvalidValueMessageException(propertyValue, - "Invalid code period '2008-11-31': Invalid date"); - } - @Test - public void fail_with_MessageException_if_period_is_today_but_no_analysis_today() { - OrganizationDto organization = dbTester.organizations().insert(); - ComponentDto project = dbTester.components().insertMainBranch(organization); - dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227934800000L)); // 2008-11-29 - when(system2Mock.now()).thenReturn(november30th2008.getTime()); - when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(false); - setupRoot(project); - setupBranchWithNoManualBaseline(project); - String propertyValue = "2008-11-30"; - settings.setProperty("sonar.leak.period", propertyValue); + expectedException.expect(IllegalStateException.class); + expectedException.expectMessage("Analysis 'nonexistent' of project '" + project.uuid() + "' defined as the baseline does not exist"); - verifyFailWithInvalidValueMessageException(propertyValue, - "Resolving new code period by date: 2008-11-30", - "Invalid code period '2008-11-30': No analysis found created after date '2008-11-30'"); + underTest.execute(new TestComputationStepContext()); } @Test - @UseDataProvider("zeroOrLess") - public void fail_with_MessageException_if_period_is_0_or_less(int zeroOrLess) { - OrganizationDto organization = dbTester.organizations().insert(); - ComponentDto project = dbTester.components().insertMainBranch(organization); - when(system2Mock.now()).thenReturn(november30th2008.getTime()); - when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(false); + public void throw_ISE_when_specific_analysis_is_set_but_does_not_belong_to_current_project() { + ComponentDto otherProject = dbTester.components().insertMainBranch(organization); + SnapshotDto otherProjectAnalysis = dbTester.components().insertSnapshot(otherProject); + setBranchPeriod(project.uuid(), project.uuid(), NewCodePeriodType.SPECIFIC_ANALYSIS, otherProjectAnalysis.getUuid()); setupRoot(project); - setupBranchWithNoManualBaseline(project); - String propertyValue = String.valueOf(zeroOrLess); - settings.setProperty("sonar.leak.period", propertyValue); - verifyFailWithInvalidValueMessageException(propertyValue, - "Invalid code period '" + zeroOrLess + "': number of days is <= 0"); - } + expectedException.expect(IllegalStateException.class); + expectedException.expectMessage("Analysis '" + otherProjectAnalysis.getUuid() + "' of project '" + project.uuid() + + "' defined as the baseline does not exist"); - @DataProvider - public static Object[][] zeroOrLess() { - return new Object[][]{ - {0}, - {-1 - new Random().nextInt(30)} - }; + underTest.execute(new TestComputationStepContext()); } @Test - public void fail_with_ISE_if_not_firstAnalysis_but_no_snapshot_in_DB() { - OrganizationDto organization = dbTester.organizations().insert(); - ComponentDto project = dbTester.components().insertMainBranch(organization); - when(system2Mock.now()).thenReturn(november30th2008.getTime()); - when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(false); + public void throw_ISE_when_specific_analysis_is_set_but_does_not_belong_to_current_branch() { + ComponentDto otherBranch = dbTester.components().insertProjectBranch(project); + SnapshotDto otherBranchAnalysis = dbTester.components().insertSnapshot(otherBranch); + setBranchPeriod(project.uuid(), project.uuid(), NewCodePeriodType.SPECIFIC_ANALYSIS, otherBranchAnalysis.getUuid()); setupRoot(project); - setupBranchWithNoManualBaseline(project); - settings.setProperty("sonar.leak.period", "previous_version"); expectedException.expect(IllegalStateException.class); - expectedException.expectMessage("Attempting to resolve period while no analysis exist"); + expectedException.expectMessage("Analysis '" + otherBranchAnalysis.getUuid() + "' of project '" + project.uuid() + + "' defined as the baseline does not exist"); underTest.execute(new TestComputationStepContext()); } @Test - @UseDataProvider("stringConsideredAsVersions") - public void fail_with_MessageException_if_string_is_not_an_existing_version_event(String propertyValue) { - OrganizationDto organization = dbTester.organizations().insert(); - ComponentDto project = dbTester.components().insertMainBranch(organization); + public void load_previous_version() { SnapshotDto analysis1 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226379600000L).setProjectVersion("0.9").setLast(false)); // 2008-11-11 SnapshotDto analysis2 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226494680000L).setProjectVersion("1.0").setLast(false)); // 2008-11-12 SnapshotDto analysis3 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227157200000L).setProjectVersion("1.1").setLast(false)); // 2008-11-20 @@ -568,248 +287,161 @@ public class LoadPeriodsStepTest extends BaseStepTest { dbTester.events().insertEvent(newEvent(analysis1).setName("0.9").setCategory(CATEGORY_VERSION).setDate(analysis1.getCreatedAt())); dbTester.events().insertEvent(newEvent(analysis2).setName("1.0").setCategory(CATEGORY_VERSION).setDate(analysis2.getCreatedAt())); dbTester.events().insertEvent(newEvent(analysis5).setName("1.1").setCategory(CATEGORY_VERSION).setDate(analysis4.getCreatedAt())); - when(system2Mock.now()).thenReturn(november30th2008.getTime()); - when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(false); - setupRoot(project); - setupBranchWithNoManualBaseline(project); - settings.setProperty("sonar.leak.period", propertyValue); - - try { - underTest.execute(new TestComputationStepContext()); - fail("a Message Exception should have been thrown"); - } catch (MessageException e) { - verifyInvalidValueMessage(e, propertyValue); - assertThat(logTester.getLogs()).hasSize(2); - assertThat(logTester.getLogs(LoggerLevel.DEBUG)) - .hasSize(2) - .extracting(LogAndArguments::getFormattedMsg) - .contains("Invalid code period '" + propertyValue + "': version is none of the existing ones: [1.1, 1.0, 0.9]"); - } - } - - @DataProvider - public static Object[][] stringConsideredAsVersions() { - return new Object[][]{ - {randomAlphabetic(5)}, - {"1,3"}, - {"1.3"}, - {"0 1"}, - {"1-SNAPSHOT"}, - {"01-12-2018"}, // unsupported date format - }; - } - - @Test - public void fail_with_MessageException_if_property_does_not_exist() { - OrganizationDto organization = dbTester.organizations().insert(); - ComponentDto project = dbTester.components().insertMainBranch(organization); - when(system2Mock.now()).thenReturn(november30th2008.getTime()); - when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(false); - setupRoot(project); - - verifyFailWithInvalidValueMessageException("", "Invalid code period '': property is undefined or value is empty"); - } - - @Test - public void fail_with_MessageException_if_property_is_empty() { - OrganizationDto organization = dbTester.organizations().insert(); - ComponentDto project = dbTester.components().insertMainBranch(organization); - when(system2Mock.now()).thenReturn(november30th2008.getTime()); - when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(false); - setupRoot(project); - String propertyValue = ""; - settings.setProperty("sonar.leak.period", propertyValue); - - verifyFailWithInvalidValueMessageException(propertyValue, "Invalid code period '': property is undefined or value is empty"); - } - - private void verifyFailWithInvalidValueMessageException(String propertyValue, String debugLog, String... otherDebugLogs) { - try { - underTest.execute(new TestComputationStepContext()); - fail("a Message Exception should have been thrown"); - } catch (MessageException e) { - verifyInvalidValueMessage(e, propertyValue); - verifyDebugLogs(debugLog, otherDebugLogs); - } - } - - @Test - public void feed_period_by_days() { - OrganizationDto organization = dbTester.organizations().insert(); - ComponentDto project = dbTester.components().insertMainBranch(organization); - SnapshotDto analysis1 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226379600000L).setLast(false)); // 2008-11-11 - SnapshotDto analysis2 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226494680000L).setLast(false)); // 2008-11-12 - SnapshotDto analysis3 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227157200000L).setLast(false)); // 2008-11-20 - SnapshotDto analysis4 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227358680000L).setLast(false)); // 2008-11-22 - SnapshotDto analysis5 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227934800000L).setLast(true)); // 2008-11-29 - when(analysisMetadataHolder.getAnalysisDate()).thenReturn(november30th2008.getTime()); - when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(false); - setupRoot(project); - setupBranchWithNoManualBaseline(project); + setupRoot(project, "1.1"); + setProjectPeriod(project.uuid(), NewCodePeriodType.PREVIOUS_VERSION, null); - settings.setProperty("sonar.leak.period", "10"); underTest.execute(new TestComputationStepContext()); - // return analysis from 2008-11-20 - assertPeriod(LEAK_PERIOD_MODE_DAYS, "10", analysis3.getCreatedAt(), analysis3.getUuid()); + assertPeriod(NewCodePeriodType.PREVIOUS_VERSION, "1.0", analysis2.getCreatedAt()); - assertThat(logTester.getLogs()).hasSize(1); - assertThat(logTester.getLogs(LoggerLevel.DEBUG)) - .extracting(LogAndArguments::getFormattedMsg) - .containsOnly("Resolving new code period by 10 days: 2008-11-20"); + verifyDebugLogs("Resolving new code period by previous version: 1.0"); } @Test - public void feed_period_by_previous_version() { - OrganizationDto organization = dbTester.organizations().insert(); - ComponentDto project = dbTester.components().insertMainBranch(organization); - SnapshotDto analysis1 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226379600000L).setProjectVersion("0.9").setLast(false)); // 2008-11-11 - SnapshotDto analysis2 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226494680000L).setProjectVersion("1.0").setLast(false)); // 2008-11-12 - SnapshotDto analysis3 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227157200000L).setProjectVersion("1.1").setLast(false)); // 2008-11-20 - SnapshotDto analysis4 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227358680000L).setProjectVersion("1.1").setLast(false)); // 2008-11-22 - SnapshotDto analysis5 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227934800000L).setProjectVersion("1.1").setLast(true)); // 2008-11-29 - dbTester.events().insertEvent(newEvent(analysis1).setName("0.9").setCategory(CATEGORY_VERSION).setDate(analysis1.getCreatedAt())); - dbTester.events().insertEvent(newEvent(analysis2).setName("1.0").setCategory(CATEGORY_VERSION).setDate(analysis2.getCreatedAt())); - dbTester.events().insertEvent(newEvent(analysis5).setName("1.1").setCategory(CATEGORY_VERSION).setDate(analysis4.getCreatedAt())); - when(system2Mock.now()).thenReturn(november30th2008.getTime()); - when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(false); - setupRoot(project, "1.1"); - setupBranchWithNoManualBaseline(project); - - settings.setProperty("sonar.leak.period", "previous_version"); - underTest.execute(new TestComputationStepContext()); - - // Analysis form 2008-11-12 - assertPeriod(LEAK_PERIOD_MODE_PREVIOUS_VERSION, "1.0", analysis2.getCreatedAt(), analysis2.getUuid()); + @UseDataProvider("zeroOrLess") + public void fail_with_MessageException_if_period_is_0_or_less(int zeroOrLess) { + setupRoot(project); + setProjectPeriod(project.uuid(), NewCodePeriodType.NUMBER_OF_DAYS, String.valueOf(zeroOrLess)); - verifyDebugLogs("Resolving new code period by previous version: 1.0"); + verifyFailWithInvalidValueMessageException(String.valueOf(zeroOrLess), + "Invalid code period '" + zeroOrLess + "': number of days is <= 0"); } @Test - public void feed_period_by_previous_version_with_previous_version_deleted() { - OrganizationDto organization = dbTester.organizations().insert(); - ComponentDto project = dbTester.components().insertMainBranch(organization); + public void load_previous_version_with_previous_version_deleted() { SnapshotDto analysis1 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226379600000L).setProjectVersion("0.9").setLast(false)); // 2008-11-11 SnapshotDto analysis2 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226494680000L).setProjectVersion("1.0").setLast(false)); // 2008-11-12 SnapshotDto analysis3 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227157200000L).setProjectVersion("1.1").setLast(false)); // 2008-11-20 dbTester.events().insertEvent(newEvent(analysis1).setName("0.9").setCategory(CATEGORY_VERSION)); // The "1.0" version was deleted from the history dbTester.events().insertEvent(newEvent(analysis3).setName("1.1").setCategory(CATEGORY_VERSION)); - when(system2Mock.now()).thenReturn(november30th2008.getTime()); - when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(false); setupRoot(project, "1.1"); - setupBranchWithNoManualBaseline(project); - settings.setProperty("sonar.leak.period", "previous_version"); underTest.execute(new TestComputationStepContext()); // Analysis form 2008-11-11 - assertPeriod(LEAK_PERIOD_MODE_PREVIOUS_VERSION, "0.9", analysis1.getCreatedAt(), analysis1.getUuid()); + assertPeriod(NewCodePeriodType.PREVIOUS_VERSION, "0.9", analysis1.getCreatedAt()); } @Test - public void feed_period_by_previous_version_with_first_analysis_when_no_previous_version_found() { - OrganizationDto organization = dbTester.organizations().insert(); - ComponentDto project = dbTester.components().insertMainBranch(organization); + public void load_previous_version_with_first_analysis_when_no_previous_version_found() { SnapshotDto analysis1 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226379600000L).setProjectVersion("1.1").setLast(false)); // 2008-11-11 SnapshotDto analysis2 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227934800000L).setProjectVersion("1.1").setLast(true)); // 2008-11-29 dbTester.events().insertEvent(newEvent(analysis2).setName("1.1").setCategory(CATEGORY_VERSION)); - when(system2Mock.now()).thenReturn(november30th2008.getTime()); - when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(false); setupRoot(project, "1.1"); - setupBranchWithNoManualBaseline(project); - settings.setProperty("sonar.leak.period", "previous_version"); underTest.execute(new TestComputationStepContext()); - assertPeriod(LEAK_PERIOD_MODE_PREVIOUS_VERSION, null, analysis1.getCreatedAt(), analysis1.getUuid()); + assertPeriod(NewCodePeriodType.PREVIOUS_VERSION, null, analysis1.getCreatedAt()); verifyDebugLogs("Resolving first analysis as new code period as there is only one existing version"); } @Test - public void feed_period_by_previous_version_with_first_analysis_when_previous_snapshot_is_the_last_one() { - OrganizationDto organization = dbTester.organizations().insert(); - ComponentDto project = dbTester.components().insertMainBranch(organization); + public void load_previous_version_with_first_analysis_when_previous_snapshot_is_the_last_one() { SnapshotDto analysis = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226379600000L).setProjectVersion("0.9").setLast(true)); // 2008-11-11 dbTester.events().insertEvent(newEvent(analysis).setName("0.9").setCategory(CATEGORY_VERSION)); - when(system2Mock.now()).thenReturn(november30th2008.getTime()); - when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(false); setupRoot(project, "1.1"); - setupBranchWithNoManualBaseline(project); - settings.setProperty("sonar.leak.period", "previous_version"); + //settings.setProperty("sonar.leak.period", "previous_version"); underTest.execute(new TestComputationStepContext()); - assertPeriod(LEAK_PERIOD_MODE_PREVIOUS_VERSION, null, analysis.getCreatedAt(), analysis.getUuid()); + assertPeriod(NewCodePeriodType.PREVIOUS_VERSION, null, analysis.getCreatedAt()); verifyDebugLogs("Resolving first analysis as new code period as there is only one existing version"); } @Test - public void feed_period_by_version() { - OrganizationDto organization = dbTester.organizations().insert(); - ComponentDto project = dbTester.components().insertMainBranch(organization); - SnapshotDto analysis1 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226379600000L).setProjectVersion("0.9").setLast(false)); // 2008-11-11 - SnapshotDto analysis2 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226494680000L).setProjectVersion("1.0").setLast(false)); // 2008-11-12 - SnapshotDto analysis3 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227157200000L).setProjectVersion("1.1").setLast(false)); // 2008-11-20 - SnapshotDto analysis4 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227358680000L).setProjectVersion("1.1").setLast(false)); // 2008-11-22 - SnapshotDto analysis5 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227934800000L).setProjectVersion("1.1").setLast(true)); // 2008-11-29 - dbTester.events().insertEvent(newEvent(analysis1).setName("0.9").setCategory(CATEGORY_VERSION)); - dbTester.events().insertEvent(newEvent(analysis2).setName("1.0").setCategory(CATEGORY_VERSION)); - dbTester.events().insertEvent(newEvent(analysis5).setName("1.1").setCategory(CATEGORY_VERSION)); - when(system2Mock.now()).thenReturn(november30th2008.getTime()); - when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(false); - setupRoot(project, "1.1"); - setupBranchWithNoManualBaseline(project); + @UseDataProvider("anyValidLeakPeriodSettingValue") + public void leak_period_setting_is_ignored_for_SLB_or_PR(String leakPeriodSettingValue) { + when(analysisMetadataHolder.isLongLivingBranch()).thenReturn(false); - settings.setProperty("sonar.leak.period", "1.0"); + //settings.setProperty("sonar.leak.period", leakPeriodSettingValue); underTest.execute(new TestComputationStepContext()); - // Analysis form 2008-11-11 - assertPeriod(LEAK_PERIOD_MODE_VERSION, "1.0", analysis2.getCreatedAt(), analysis2.getUuid()); - verifyDebugLogs("Resolving new code period by version: 1.0"); + assertThat(periodsHolder.hasPeriod()).isFalse(); } - /** - * SONAR-11492 - */ - @Test - public void feed_period_by_version_with_only_one_existing_version() { - OrganizationDto organization = dbTester.organizations().insert(); - ComponentDto project = dbTester.components().insertMainBranch(organization); - SnapshotDto analysis1 = dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226379600000L).setProjectVersion("0.9").setLast(true)); // 2008-11-11 - dbTester.events().insertEvent(newEvent(analysis1).setName("0.9").setCategory(CATEGORY_VERSION)); - when(system2Mock.now()).thenReturn(november30th2008.getTime()); - when(analysisMetadataHolder.isFirstAnalysis()).thenReturn(false); - setupRoot(project, "0.9"); - setupBranchWithNoManualBaseline(project); + private void verifyFailWithInvalidValueMessageException(String propertyValue, String debugLog, String... otherDebugLogs) { + try { + underTest.execute(new TestComputationStepContext()); + fail("a Message Exception should have been thrown"); + } catch (MessageException e) { + verifyInvalidValueMessage(e, propertyValue); + verifyDebugLogs(debugLog, otherDebugLogs); + } + } - settings.setProperty("sonar.leak.period", "0.9"); - underTest.execute(new TestComputationStepContext()); + @DataProvider + public static Object[][] zeroOrLess() { + return new Object[][] { + {0}, + {-1 - new Random().nextInt(30)} + }; + } - // Analysis form 2008-11-11 - assertPeriod(LEAK_PERIOD_MODE_VERSION, "0.9", analysis1.getCreatedAt(), analysis1.getUuid()); - verifyDebugLogs("Resolving new code period by version: 0.9"); + @DataProvider + public static Object[][] stringConsideredAsVersions() { + return new Object[][] { + {randomAlphabetic(5)}, + {"1,3"}, + {"1.3"}, + {"0 1"}, + {"1-SNAPSHOT"}, + {"01-12-2018"}, // unsupported date format + }; } - @Test - @UseDataProvider("anyValidLeakPeriodSettingValue") - public void leak_period_setting_is_ignored_for_SLB_or_PR(String leakPeriodSettingValue) { - when(analysisMetadataHolder.isLongLivingBranch()).thenReturn(false); + @DataProvider + public static Object[][] projectVersionNullOrNot() { + return new Object[][] { + {null}, + {randomAlphabetic(15)}, + }; + } - settings.setProperty("sonar.leak.period", leakPeriodSettingValue); - underTest.execute(new TestComputationStepContext()); + @DataProvider + public static Object[][] anyValidLeakPeriodSettingValue() { + return new Object[][] { + // days + {"100"}, + // previous_version keyword + {"previous_version"} + }; + } - assertThat(periodsHolder.hasPeriod()).isFalse(); + private List<SnapshotDto> createSnapshots(ComponentDto project) { + ArrayList<SnapshotDto> list = new ArrayList<>(); + list.add(dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226379600000L).setLast(false))); // 2008-11-11 + list.add(dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1226494680000L).setLast(false))); // 2008-11-12 + list.add(dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227157200000L).setLast(false))); // 2008-11-20 + list.add(dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227358680000L).setLast(false))); // 2008-11-22 + list.add(dbTester.components().insertSnapshot(project, snapshot -> snapshot.setCreatedAt(1227934800000L).setLast(true))); // 2008-11-29 + return list; + } + + private long milisSinceEpoch(int year, int month, int day, int hour) { + return ZonedDateTime.of(year, month, day, hour, 0, 0, 0, ZoneId.systemDefault()) + .toInstant().toEpochMilli(); + } + + private void setProjectPeriod(String projectUuid, NewCodePeriodType type, @Nullable String value) { + dbTester.newCodePeriods().insert(projectUuid, type, value); } - private void assertPeriod(String mode, @Nullable String modeParameter, long snapshotDate, String analysisUuid) { + private void setBranchPeriod(String projectUuid, String branchUuid, NewCodePeriodType type, @Nullable String value) { + dbTester.newCodePeriods().insert(projectUuid, branchUuid, type, value); + } + + private void setGlobalPeriod(NewCodePeriodType type, @Nullable String value) { + dbTester.newCodePeriods().insert(type, value); + } + + private void assertPeriod(NewCodePeriodType type, @Nullable String value, long snapshotDate) { Period period = periodsHolder.getPeriod(); assertThat(period).isNotNull(); - assertThat(period.getMode()).isEqualTo(mode); - assertThat(period.getModeParameter()).isEqualTo(modeParameter); + assertThat(period.getMode()).isEqualTo(type.name()); + assertThat(period.getModeParameter()).isEqualTo(value); assertThat(period.getSnapshotDate()).isEqualTo(snapshotDate); - assertThat(period.getAnalysisUuid()).isEqualTo(analysisUuid); } private void verifyDebugLogs(String log, String... otherLogs) { @@ -823,14 +455,17 @@ public class LoadPeriodsStepTest extends BaseStepTest { setupRoot(project, randomAlphanumeric(3)); } - private void setupRoot(ComponentDto project, String version) { - treeRootHolder.setRoot(ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(project.uuid()).setKey(project.getKey()).setProjectVersion(version).build()); - when(configurationRepository.getConfiguration()).thenReturn(settings.asConfig()); - } + private void setupRoot(ComponentDto projectDto, String version) { + treeRootHolder.setRoot(ReportComponent + .builder(Component.Type.PROJECT, 1) + .setUuid(projectDto.uuid()) + .setKey(projectDto.getKey()) + .setProjectVersion(version) + .build()); - private void setupBranchWithNoManualBaseline(ComponentDto projectOrLongBranch) { - dbTester.components().unsetBranchNewCodePeriod(projectOrLongBranch); - setBranchOf(projectOrLongBranch); + Project project = mock(Project.class); + when(project.getUuid()).thenReturn(projectDto.getMainBranchProjectUuid() != null ? projectDto.getMainBranchProjectUuid() : projectDto.uuid()); + when(analysisMetadataHolder.getProject()).thenReturn(project); } private static void verifyInvalidValueMessage(MessageException e, String propertyValue) { diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ReportPersistAnalysisStepTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ReportPersistAnalysisStepTest.java index 4354cb751e9..f2b04000ecf 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ReportPersistAnalysisStepTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ReportPersistAnalysisStepTest.java @@ -154,7 +154,7 @@ public class ReportPersistAnalysisStepTest extends BaseStepTest { SnapshotDto snapshotDto = SnapshotTesting.newAnalysis(projectDto).setCreatedAt(DateUtils.parseDateQuietly("2015-01-01").getTime()); dbClient.snapshotDao().insert(dbTester.getSession(), snapshotDto); dbTester.getSession().commit(); - periodsHolder.setPeriod(new Period(LEAK_PERIOD_MODE_DATE, "2015-01-01", analysisDate, "u1")); + periodsHolder.setPeriod(new Period(LEAK_PERIOD_MODE_DATE, "2015-01-01", analysisDate)); Component project = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("ABCD").setKey(PROJECT_KEY).build(); treeRootHolder.setRoot(project); @@ -170,7 +170,7 @@ public class ReportPersistAnalysisStepTest extends BaseStepTest { @Test public void only_persist_snapshots_with_leak_period_on_project_and_module() { - periodsHolder.setPeriod(new Period(LEAK_PERIOD_MODE_PREVIOUS_VERSION, null, analysisDate, "u1")); + periodsHolder.setPeriod(new Period(LEAK_PERIOD_MODE_PREVIOUS_VERSION, null, analysisDate)); OrganizationDto organizationDto = dbTester.organizations().insert(); ComponentDto projectDto = ComponentTesting.newPrivateProjectDto(organizationDto, "ABCD").setDbKey(PROJECT_KEY).setName("Project"); diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ViewsPersistAnalysisStepTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ViewsPersistAnalysisStepTest.java index 9f7937dd0cf..6aba59eb3e8 100644 --- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ViewsPersistAnalysisStepTest.java +++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/ViewsPersistAnalysisStepTest.java @@ -129,7 +129,7 @@ public class ViewsPersistAnalysisStepTest extends BaseStepTest { Component view = ViewsComponent.builder(VIEW, "KEY_VIEW").setUuid("UUID_VIEW").addChildren(subView).build(); treeRootHolder.setRoot(view); - periodsHolder.setPeriod(new Period(LEAK_PERIOD_MODE_DATE, "2015-01-01", analysisDate, "u1")); + periodsHolder.setPeriod(new Period(LEAK_PERIOD_MODE_DATE, "2015-01-01", analysisDate)); underTest.execute(new TestComputationStepContext()); |