From 44a34aca80bb01c3a7689fe02d34f17718bf9293 Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Wed, 24 Jun 2015 16:41:13 +0200 Subject: SONAR-6588 integrate issues to Compute Engine --- .../org/sonar/batch/bootstrap/BatchComponents.java | 6 - .../org/sonar/batch/debt/DebtModelProvider.java | 83 ----- .../batch/debt/IssueChangelogDebtCalculator.java | 142 -------- .../org/sonar/batch/debt/NewDebtDecorator.java | 114 ------- .../java/org/sonar/batch/issue/ModuleIssues.java | 4 +- .../batch/issue/tracking/LocalIssueTracking.java | 2 +- .../org/sonar/batch/report/IssuesPublisher.java | 26 +- .../org/sonar/batch/report/MeasuresPublisher.java | 16 - .../org/sonar/batch/report/MetadataPublisher.java | 74 ++++ .../java/org/sonar/batch/rule/RulesProvider.java | 129 ------- .../org/sonar/batch/scan/ProjectScanContainer.java | 37 +- .../org/sonar/batch/scan/measure/MeasureCache.java | 19 +- .../batch/scan/measure/MeasureValueCoder.java | 15 +- .../org/sonar/batch/debt/DebtDecoratorTest.java | 353 ------------------- .../sonar/batch/debt/DebtModelProviderTest.java | 81 ----- .../debt/IssueChangelogDebtCalculatorTest.java | 149 -------- .../org/sonar/batch/debt/NewDebtDecoratorTest.java | 376 --------------------- .../org/sonar/batch/issue/ModuleIssuesTest.java | 4 - .../sonar/batch/report/IssuesPublisherTest.java | 50 +-- .../sonar/batch/report/MeasuresPublisherTest.java | 13 +- .../sonar/batch/report/MetadataPublisherTest.java | 99 ++++++ .../org/sonar/batch/rule/RulesProviderTest.java | 215 ------------ .../sonar/batch/scan/measure/MeasureCacheTest.java | 22 +- 23 files changed, 211 insertions(+), 1818 deletions(-) delete mode 100644 sonar-batch/src/main/java/org/sonar/batch/debt/DebtModelProvider.java delete mode 100644 sonar-batch/src/main/java/org/sonar/batch/debt/IssueChangelogDebtCalculator.java delete mode 100644 sonar-batch/src/main/java/org/sonar/batch/debt/NewDebtDecorator.java create mode 100644 sonar-batch/src/main/java/org/sonar/batch/report/MetadataPublisher.java delete mode 100644 sonar-batch/src/main/java/org/sonar/batch/rule/RulesProvider.java delete mode 100644 sonar-batch/src/test/java/org/sonar/batch/debt/DebtDecoratorTest.java delete mode 100644 sonar-batch/src/test/java/org/sonar/batch/debt/DebtModelProviderTest.java delete mode 100644 sonar-batch/src/test/java/org/sonar/batch/debt/IssueChangelogDebtCalculatorTest.java delete mode 100644 sonar-batch/src/test/java/org/sonar/batch/debt/NewDebtDecoratorTest.java create mode 100644 sonar-batch/src/test/java/org/sonar/batch/report/MetadataPublisherTest.java delete mode 100644 sonar-batch/src/test/java/org/sonar/batch/rule/RulesProviderTest.java (limited to 'sonar-batch') diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java index 58a2e630d3c..53b2f2c1bb1 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java @@ -37,8 +37,6 @@ import org.sonar.batch.compute.OverallCoverageDecorator; import org.sonar.batch.compute.OverallLineCoverageDecorator; import org.sonar.batch.compute.UnitTestDecorator; import org.sonar.batch.cpd.CpdComponents; -import org.sonar.batch.debt.IssueChangelogDebtCalculator; -import org.sonar.batch.debt.NewDebtDecorator; import org.sonar.batch.issue.tracking.IssueTracking; import org.sonar.batch.language.LanguageDistributionDecorator; import org.sonar.batch.scan.report.ConsoleReport; @@ -83,10 +81,6 @@ public class BatchComponents { // language LanguageDistributionDecorator.class, - // Debt - IssueChangelogDebtCalculator.class, - NewDebtDecorator.class, - // to be moved to compute engine UnitTestDecorator.class, LineCoverageDecorator.class, diff --git a/sonar-batch/src/main/java/org/sonar/batch/debt/DebtModelProvider.java b/sonar-batch/src/main/java/org/sonar/batch/debt/DebtModelProvider.java deleted file mode 100644 index dc95f8e8679..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/debt/DebtModelProvider.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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.batch.debt; - -import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; -import java.util.List; -import javax.annotation.Nullable; -import org.picocontainer.injectors.ProviderAdapter; -import org.sonar.api.batch.debt.DebtCharacteristic; -import org.sonar.api.batch.debt.DebtModel; -import org.sonar.api.batch.debt.internal.DefaultDebtCharacteristic; -import org.sonar.api.batch.debt.internal.DefaultDebtModel; -import org.sonar.api.utils.log.Loggers; -import org.sonar.api.utils.log.Profiler; -import org.sonar.core.technicaldebt.db.CharacteristicDao; -import org.sonar.core.technicaldebt.db.CharacteristicDto; - -public class DebtModelProvider extends ProviderAdapter { - - private DebtModel model; - - public DebtModel provide(CharacteristicDao dao) { - if (model == null) { - Profiler profiler = Profiler.create(Loggers.get(getClass())).startInfo("Load technical debt model"); - model = load(dao); - profiler.stopDebug(); - } - return model; - } - - private static DebtModel load(CharacteristicDao dao) { - DefaultDebtModel debtModel = new DefaultDebtModel(); - - List allCharacteristics = dao.selectEnabledCharacteristics(); - for (CharacteristicDto dto : allCharacteristics) { - Integer parentId = dto.getParentId(); - if (parentId == null) { - debtModel.addCharacteristic(toDebtCharacteristic(dto)); - } else { - debtModel.addSubCharacteristic(toDebtCharacteristic(dto), characteristicById(parentId, allCharacteristics).getKey()); - } - } - return debtModel; - } - - private static CharacteristicDto characteristicById(final int id, List allCharacteristics) { - return Iterables.find(allCharacteristics, new Predicate() { - @Override - public boolean apply(@Nullable CharacteristicDto input) { - return input != null && id == input.getId(); - } - }); - } - - private static DebtCharacteristic toDebtCharacteristic(CharacteristicDto characteristic) { - return new DefaultDebtCharacteristic() - .setId(characteristic.getId()) - .setKey(characteristic.getKey()) - .setName(characteristic.getName()) - .setOrder(characteristic.getOrder()) - .setParentId(characteristic.getParentId()); - } - -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/debt/IssueChangelogDebtCalculator.java b/sonar-batch/src/main/java/org/sonar/batch/debt/IssueChangelogDebtCalculator.java deleted file mode 100644 index 5d34e8f89de..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/debt/IssueChangelogDebtCalculator.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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.batch.debt; - -import com.google.common.base.Function; -import com.google.common.collect.Ordering; -import java.util.Calendar; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; -import org.apache.commons.lang.time.DateUtils; -import org.sonar.api.batch.BatchSide; -import org.sonar.api.issue.Issue; -import org.sonar.core.issue.DefaultIssue; -import org.sonar.core.issue.FieldDiffs; -import org.sonar.core.issue.IssueUpdater; - -import static com.google.common.collect.Lists.newArrayList; - -/** - * Warning, before modifying this class, please do not forget that it's used by the Dev Cockpit plugin - */ -@BatchSide -public class IssueChangelogDebtCalculator { - - @CheckForNull - public Long calculateNewTechnicalDebt(Issue issue, @Nullable Date periodDate) { - Long debt = ((DefaultIssue) issue).debtInMinutes(); - Date periodDatePlusOneSecond = periodDate != null ? DateUtils.addSeconds(periodDate, 1) : null; - if (isAfter(issue.creationDate(), periodDatePlusOneSecond)) { - return debt; - } else { - return calculateNewTechnicalDebtValueFromChangelog(debt, issue, periodDate); - } - } - - @CheckForNull - private Long calculateNewTechnicalDebtValueFromChangelog(@Nullable Long currentTechnicalDebtValue, Issue issue, Date periodDate) { - List changelog = technicalDebtHistory(issue); - for (Iterator iterator = changelog.iterator(); iterator.hasNext();) { - FieldDiffs diff = iterator.next(); - Date date = diff.creationDate(); - if (isLesserOrEqual(date, periodDate)) { - // return new value from the change that is just before the period date - return subtractNeverNegative(currentTechnicalDebtValue, newValue(diff)); - } - if (!iterator.hasNext()) { - // return old value from the change that is just after the period date when there's no more element in changelog - return subtractNeverNegative(currentTechnicalDebtValue, oldValue(diff)); - } - } - // Return null when no changelog - return null; - } - - /** - * SONAR-5059 - */ - @CheckForNull - private static Long subtractNeverNegative(@Nullable Long value, @Nullable Long with) { - Long result = (value != null ? value : 0) - (with != null ? with : 0); - return result > 0 ? result : null; - } - - private List technicalDebtHistory(Issue issue) { - List technicalDebtChangelog = changesOnField(((DefaultIssue) issue).changes()); - if (!technicalDebtChangelog.isEmpty()) { - // Changelog have to be sorted from newest to oldest. - // Null date should be the first as this happen when technical debt has changed since previous analysis. - Ordering ordering = Ordering.natural().reverse().nullsFirst().onResultOf(new Function() { - @Override - public Date apply(FieldDiffs diff) { - return diff.creationDate(); - } - }); - return ordering.immutableSortedCopy(technicalDebtChangelog); - } - return Collections.emptyList(); - } - - private static List changesOnField(Collection fieldDiffs) { - List diffs = newArrayList(); - for (FieldDiffs fieldDiff : fieldDiffs) { - if (fieldDiff.diffs().containsKey(IssueUpdater.TECHNICAL_DEBT)) { - diffs.add(fieldDiff); - } - } - return diffs; - } - - @CheckForNull - private static Long newValue(FieldDiffs fieldDiffs) { - for (Map.Entry entry : fieldDiffs.diffs().entrySet()) { - if (entry.getKey().equals(IssueUpdater.TECHNICAL_DEBT)) { - return entry.getValue().newValueLong(); - } - } - return null; - } - - @CheckForNull - private static Long oldValue(FieldDiffs fieldDiffs) { - for (Map.Entry entry : fieldDiffs.diffs().entrySet()) { - if (entry.getKey().equals(IssueUpdater.TECHNICAL_DEBT)) { - return entry.getValue().oldValueLong(); - } - } - return null; - } - - private static boolean isAfter(@Nullable Date currentDate, @Nullable Date pastDate) { - return pastDate == null || (currentDate != null && DateUtils.truncatedCompareTo(currentDate, pastDate, Calendar.SECOND) > 0); - } - - private static boolean isLesserOrEqual(@Nullable Date currentDate, @Nullable Date pastDate) { - return (currentDate != null) && (pastDate == null || (DateUtils.truncatedCompareTo(currentDate, pastDate, Calendar.SECOND) <= 0)); - } - -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/debt/NewDebtDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/debt/NewDebtDecorator.java deleted file mode 100644 index c334520aa79..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/debt/NewDebtDecorator.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * 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.batch.debt; - -import com.google.common.collect.ImmutableList; -import java.util.Collection; -import java.util.Date; -import java.util.List; -import javax.annotation.Nullable; -import org.sonar.api.batch.Decorator; -import org.sonar.api.batch.DecoratorBarriers; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.batch.DependedUpon; -import org.sonar.api.batch.DependsUpon; -import org.sonar.api.batch.RequiresDB; -import org.sonar.api.component.ResourcePerspectives; -import org.sonar.api.issue.Issuable; -import org.sonar.api.issue.Issue; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Measure; -import org.sonar.api.measures.MeasureUtils; -import org.sonar.api.measures.Metric; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Resource; -import org.sonar.batch.components.Period; -import org.sonar.batch.components.TimeMachineConfiguration; - -import static com.google.common.collect.Lists.newArrayList; - -/** - * Decorator that computes the technical debt metric - */ -@RequiresDB -@DependsUpon(DecoratorBarriers.ISSUES_TRACKED) -public final class NewDebtDecorator implements Decorator { - - private final ResourcePerspectives perspectives; - private final TimeMachineConfiguration timeMachineConfiguration; - private final IssueChangelogDebtCalculator issueChangelogDebtCalculator; - - public NewDebtDecorator(ResourcePerspectives perspectives, TimeMachineConfiguration timeMachineConfiguration, - IssueChangelogDebtCalculator issueChangelogDebtCalculator) { - this.perspectives = perspectives; - this.timeMachineConfiguration = timeMachineConfiguration; - this.issueChangelogDebtCalculator = issueChangelogDebtCalculator; - } - - @Override - public boolean shouldExecuteOnProject(Project project) { - return true; - } - - @DependedUpon - public List generatesMetrics() { - return ImmutableList.of( - CoreMetrics.NEW_TECHNICAL_DEBT - ); - } - - @Override - public void decorate(Resource resource, DecoratorContext context) { - Issuable issuable = perspectives.as(Issuable.class, resource); - if (issuable != null && shouldSaveNewMetrics(context)) { - List issues = newArrayList(issuable.issues()); - saveMeasures(context, issues); - } - } - - private void saveMeasures(DecoratorContext context, Collection issues) { - Measure measure = new Measure(CoreMetrics.NEW_TECHNICAL_DEBT); - for (Period period : timeMachineConfiguration.periods()) { - Date periodDate = period.getDate(); - double value = calculateNewTechnicalDebtValue(issues, periodDate); - Collection children = context.getChildrenMeasures(measure.getMetric()); - double sum = MeasureUtils.sumOnVariation(true, period.getIndex(), children) + value; - measure.setVariation(period.getIndex(), sum); - } - context.saveMeasure(measure); - } - - private long calculateNewTechnicalDebtValue(Collection issues, @Nullable Date periodDate) { - long result = 0; - for (Issue issue : issues) { - Long debt = issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, periodDate); - if (debt != null) { - result += debt; - } - } - return result; - } - - private static boolean shouldSaveNewMetrics(DecoratorContext context) { - return context.getMeasure(CoreMetrics.NEW_TECHNICAL_DEBT) == null; - } - -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/ModuleIssues.java b/sonar-batch/src/main/java/org/sonar/batch/issue/ModuleIssues.java index 23fa523df44..2ff7190907b 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/issue/ModuleIssues.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/ModuleIssues.java @@ -28,12 +28,12 @@ import org.sonar.api.batch.rule.ActiveRules; import org.sonar.api.batch.rule.Rule; import org.sonar.api.batch.rule.Rules; import org.sonar.api.batch.rule.internal.DefaultActiveRule; -import org.sonar.core.issue.DefaultIssue; import org.sonar.api.resources.Project; import org.sonar.api.rule.RuleKey; import org.sonar.api.rules.Violation; import org.sonar.api.utils.Duration; import org.sonar.api.utils.MessageException; +import org.sonar.core.issue.DefaultIssue; import org.sonar.core.issue.DefaultIssueBuilder; /** @@ -120,7 +120,7 @@ public class ModuleIssues { } if (rule != null) { DebtRemediationFunction function = rule.debtRemediationFunction(); - if (rule.debtSubCharacteristic() != null && function != null) { + if (function != null) { issue.setDebt(calculateDebt(function, issue.effortToFix(), rule.key())); } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/LocalIssueTracking.java b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/LocalIssueTracking.java index 733e41d26a1..729e4d7cff1 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/LocalIssueTracking.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/LocalIssueTracking.java @@ -143,7 +143,7 @@ public class LocalIssueTracking { if (file == null) { throw new IllegalStateException("Resource " + component.resource() + " was not found in InputPath cache"); } - sourceHashHolder = new SourceHashHolder((DefaultInputFile) file, lastLineHashes); + sourceHashHolder = new SourceHashHolder(file, lastLineHashes); } return sourceHashHolder; } diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/IssuesPublisher.java b/sonar-batch/src/main/java/org/sonar/batch/report/IssuesPublisher.java index 0377b3e0889..9c56d2404af 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/report/IssuesPublisher.java +++ b/sonar-batch/src/main/java/org/sonar/batch/report/IssuesPublisher.java @@ -21,9 +21,6 @@ package org.sonar.batch.report; import com.google.common.base.Function; import com.google.common.collect.Iterables; -import org.sonar.api.CoreProperties; -import org.sonar.api.batch.bootstrap.ProjectDefinition; -import org.sonar.api.resources.Project; import org.sonar.api.utils.KeyValueFormat; import org.sonar.batch.index.BatchComponent; import org.sonar.batch.index.BatchComponentCache; @@ -31,19 +28,17 @@ import org.sonar.batch.issue.IssueCache; import org.sonar.batch.protocol.Constants; import org.sonar.batch.protocol.output.BatchReport; import org.sonar.batch.protocol.output.BatchReportWriter; -import org.sonar.batch.scan.ImmutableProjectReactor; import org.sonar.core.issue.DefaultIssue; public class IssuesPublisher implements ReportPublisherStep { private final BatchComponentCache componentCache; private final IssueCache issueCache; - private final ImmutableProjectReactor reactor; - public IssuesPublisher(ImmutableProjectReactor reactor, BatchComponentCache componentCache, IssueCache issueCache) { - this.reactor = reactor; + public IssuesPublisher(BatchComponentCache componentCache, IssueCache issueCache) { this.componentCache = componentCache; this.issueCache = issueCache; + } @Override @@ -60,23 +55,6 @@ public class IssuesPublisher implements ReportPublisherStep { } })); } - - exportMetadata(writer); - } - - private void exportMetadata(BatchReportWriter writer) { - ProjectDefinition root = reactor.getRoot(); - BatchComponent rootProject = componentCache.getRoot(); - BatchReport.Metadata.Builder builder = BatchReport.Metadata.newBuilder() - .setAnalysisDate(((Project) rootProject.resource()).getAnalysisDate().getTime()) - // Here we want key without branch - .setProjectKey(root.getKey()) - .setRootComponentRef(rootProject.batchId()); - String branch = root.properties().get(CoreProperties.PROJECT_BRANCH_PROPERTY); - if (branch != null) { - builder.setBranch(branch); - } - writer.writeMetadata(builder.build()); } private BatchReport.Issue toReportIssue(BatchReport.Issue.Builder builder, DefaultIssue issue) { diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/MeasuresPublisher.java b/sonar-batch/src/main/java/org/sonar/batch/report/MeasuresPublisher.java index 9aad7276659..8a8ae99436a 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/report/MeasuresPublisher.java +++ b/sonar-batch/src/main/java/org/sonar/batch/report/MeasuresPublisher.java @@ -26,14 +26,10 @@ import com.google.common.collect.Iterables; import java.io.Serializable; import javax.annotation.Nullable; import org.sonar.api.measures.Measure; -import org.sonar.api.measures.Metric.Level; import org.sonar.api.measures.Metric.ValueType; import org.sonar.api.measures.MetricFinder; -import org.sonar.api.measures.RuleMeasure; import org.sonar.api.resources.Resource; import org.sonar.api.resources.ResourceUtils; -import org.sonar.api.rule.RuleKey; -import org.sonar.api.technicaldebt.batch.Characteristic; import org.sonar.batch.index.BatchComponent; import org.sonar.batch.index.BatchComponentCache; import org.sonar.batch.protocol.Constants.MeasureValueType; @@ -111,14 +107,6 @@ public class MeasuresPublisher implements ReportPublisherStep { if (description != null) { builder.setDescription(description); } - Level alertStatus = measure.getAlertStatus(); - if (alertStatus != null) { - builder.setAlertStatus(alertStatus.toString()); - } - String alertText = measure.getAlertText(); - if (alertText != null) { - builder.setAlertText(alertText); - } Double variation1 = measure.getVariation1(); if (variation1 != null) { builder.setVariationValue1(variation1); @@ -139,10 +127,6 @@ public class MeasuresPublisher implements ReportPublisherStep { if (variation5 != null) { builder.setVariationValue5(variation5); } - Characteristic charac = measure.getCharacteristic(); - if (charac != null) { - builder.setCharactericId(charac.id()); - } Integer personId = measure.getPersonId(); if (personId != null) { builder.setPersonId(personId); diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/MetadataPublisher.java b/sonar-batch/src/main/java/org/sonar/batch/report/MetadataPublisher.java new file mode 100644 index 00000000000..d5c4152d541 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/report/MetadataPublisher.java @@ -0,0 +1,74 @@ +/* + * 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.batch.report; + +import com.google.common.base.Function; +import javax.annotation.Nonnull; +import org.sonar.api.CoreProperties; +import org.sonar.api.batch.bootstrap.ProjectDefinition; +import org.sonar.api.batch.rule.ActiveRule; +import org.sonar.api.batch.rule.ActiveRules; +import org.sonar.api.resources.Project; +import org.sonar.batch.index.BatchComponent; +import org.sonar.batch.index.BatchComponentCache; +import org.sonar.batch.protocol.output.BatchReport; +import org.sonar.batch.protocol.output.BatchReportWriter; +import org.sonar.batch.scan.ImmutableProjectReactor; + +import static com.google.common.collect.FluentIterable.from; + +public class MetadataPublisher implements ReportPublisherStep { + + private final BatchComponentCache componentCache; + private final ImmutableProjectReactor reactor; + private final ActiveRules activeRules; + + public MetadataPublisher(BatchComponentCache componentCache, ImmutableProjectReactor reactor, ActiveRules activeRules) { + this.componentCache = componentCache; + this.reactor = reactor; + this.activeRules = activeRules; + } + + @Override + public void publish(BatchReportWriter writer) { + ProjectDefinition root = reactor.getRoot(); + BatchComponent rootProject = componentCache.getRoot(); + BatchReport.Metadata.Builder builder = BatchReport.Metadata.newBuilder() + .setAnalysisDate(((Project) rootProject.resource()).getAnalysisDate().getTime()) + // Here we want key without branch + .setProjectKey(root.getKey()) + .setRootComponentRef(rootProject.batchId()); + String branch = root.properties().get(CoreProperties.PROJECT_BRANCH_PROPERTY); + if (branch != null) { + builder.setBranch(branch); + } + builder.addAllActiveRuleKey(from(activeRules.findAll()).transform(ToRuleKey.INSTANCE)); + writer.writeMetadata(builder.build()); + } + + private enum ToRuleKey implements Function { + INSTANCE; + @Nonnull + @Override + public String apply(@Nonnull ActiveRule input) { + return input.ruleKey().toString(); + } + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/rule/RulesProvider.java b/sonar-batch/src/main/java/org/sonar/batch/rule/RulesProvider.java deleted file mode 100644 index 9a8af6d87ef..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/rule/RulesProvider.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * 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.batch.rule; - -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.ListMultimap; -import java.util.List; -import javax.annotation.Nullable; -import org.picocontainer.injectors.ProviderAdapter; -import org.sonar.api.batch.debt.DebtCharacteristic; -import org.sonar.api.batch.debt.DebtModel; -import org.sonar.api.batch.debt.DebtRemediationFunction; -import org.sonar.api.batch.debt.internal.DefaultDebtModel; -import org.sonar.api.batch.rule.Rules; -import org.sonar.api.batch.rule.internal.NewRule; -import org.sonar.api.batch.rule.internal.RulesBuilder; -import org.sonar.api.rule.RuleKey; -import org.sonar.api.utils.Durations; -import org.sonar.api.utils.log.Loggers; -import org.sonar.api.utils.log.Profiler; -import org.sonar.core.rule.RuleDao; -import org.sonar.core.rule.RuleDto; -import org.sonar.core.rule.RuleParamDto; - -/** - * Loads all enabled and non manual rules - */ -public class RulesProvider extends ProviderAdapter { - - private Rules singleton = null; - - public Rules provide(RuleDao ruleDao, DebtModel debtModel, Durations durations) { - if (singleton == null) { - Profiler profiler = Profiler.create(Loggers.get(getClass())).startInfo("Load rules"); - singleton = load(ruleDao, (DefaultDebtModel) debtModel, durations); - profiler.stopDebug(); - } - return singleton; - } - - private Rules load(RuleDao ruleDao, DefaultDebtModel debtModel, Durations durations) { - RulesBuilder rulesBuilder = new RulesBuilder(); - - List ruleParamDtos = ruleDao.selectParameters(); - ListMultimap paramDtosByRuleId = ArrayListMultimap.create(); - for (RuleParamDto dto : ruleParamDtos) { - paramDtosByRuleId.put(dto.getRuleId(), dto); - } - for (RuleDto ruleDto : ruleDao.selectEnablesAndNonManual()) { - RuleKey ruleKey = RuleKey.of(ruleDto.getRepositoryKey(), ruleDto.getRuleKey()); - NewRule newRule = rulesBuilder.add(ruleKey) - .setId(ruleDto.getId()) - .setName(ruleDto.getName()) - .setSeverity(ruleDto.getSeverityString()) - .setDescription(ruleDto.getDescription()) - .setStatus(ruleDto.getStatus()) - .setInternalKey(ruleDto.getConfigKey()); - - if (hasCharacteristic(ruleDto)) { - newRule.setDebtSubCharacteristic(effectiveCharacteristic(ruleDto, ruleKey, debtModel).key()); - newRule.setDebtRemediationFunction(effectiveFunction(ruleDto, ruleKey, durations)); - } - - for (RuleParamDto ruleParamDto : paramDtosByRuleId.get(ruleDto.getId())) { - newRule.addParam(ruleParamDto.getName()) - .setDescription(ruleParamDto.getDescription()); - } - } - return rulesBuilder.build(); - } - - private static DebtCharacteristic effectiveCharacteristic(RuleDto ruleDto, RuleKey ruleKey, DefaultDebtModel debtModel) { - Integer subCharacteristicId = ruleDto.getSubCharacteristicId(); - Integer defaultSubCharacteristicId = ruleDto.getDefaultSubCharacteristicId(); - Integer effectiveSubCharacteristicId = subCharacteristicId != null ? subCharacteristicId : defaultSubCharacteristicId; - DebtCharacteristic subCharacteristic = debtModel.characteristicById(effectiveSubCharacteristicId); - if (subCharacteristic == null) { - throw new IllegalStateException(String.format("Sub characteristic id '%s' on rule '%s' has not been found", effectiveSubCharacteristicId, ruleKey)); - } - return subCharacteristic; - } - - private DebtRemediationFunction effectiveFunction(RuleDto ruleDto, RuleKey ruleKey, Durations durations) { - String function = ruleDto.getRemediationFunction(); - String defaultFunction = ruleDto.getDefaultRemediationFunction(); - if (function != null) { - return createDebtRemediationFunction(function, ruleDto.getRemediationCoefficient(), ruleDto.getRemediationOffset(), durations); - } else if (defaultFunction != null) { - return createDebtRemediationFunction(defaultFunction, ruleDto.getDefaultRemediationCoefficient(), ruleDto.getDefaultRemediationOffset(), durations); - } else { - throw new IllegalStateException(String.format("Remediation function should not be null on rule '%s'", ruleKey)); - } - } - - private DebtRemediationFunction createDebtRemediationFunction(String function, @Nullable String factor, @Nullable String offset, Durations durations) { - return DebtRemediationFunction.create(DebtRemediationFunction.Type.valueOf(function), - factor != null ? durations.decode(factor) : null, - offset != null ? durations.decode(offset) : null); - } - - /** - * Return true is the characteristic has not been overridden and a default characteristic is existing or - * if the characteristic has been overridden but is not disabled - */ - private static boolean hasCharacteristic(RuleDto ruleDto) { - Integer subCharacteristicId = ruleDto.getSubCharacteristicId(); - return (subCharacteristicId == null && ruleDto.getDefaultSubCharacteristicId() != null) || - (subCharacteristicId != null && !RuleDto.DISABLED_CHARACTERISTIC_ID.equals(subCharacteristicId)); - } - -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java index 83f24753ef4..53aa790b4a4 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java @@ -43,7 +43,6 @@ import org.sonar.batch.bootstrap.ExtensionUtils; import org.sonar.batch.bootstrap.MetricProvider; import org.sonar.batch.bootstrapper.EnvironmentInformation; import org.sonar.batch.components.PastMeasuresLoader; -import org.sonar.batch.debt.DebtModelProvider; import org.sonar.batch.deprecated.components.DefaultResourceCreationLock; import org.sonar.batch.deprecated.components.PeriodsDefinition; import org.sonar.batch.duplication.DuplicationCache; @@ -63,13 +62,13 @@ import org.sonar.batch.report.CoveragePublisher; import org.sonar.batch.report.DuplicationsPublisher; import org.sonar.batch.report.IssuesPublisher; import org.sonar.batch.report.MeasuresPublisher; +import org.sonar.batch.report.MetadataPublisher; import org.sonar.batch.report.ReportPublisher; import org.sonar.batch.report.SourcePublisher; import org.sonar.batch.report.TestExecutionAndCoveragePublisher; import org.sonar.batch.repository.ProjectRepositoriesProvider; import org.sonar.batch.repository.language.DefaultLanguagesRepository; import org.sonar.batch.rule.ActiveRulesProvider; -import org.sonar.batch.rule.RulesProvider; import org.sonar.batch.scan.filesystem.InputPathCache; import org.sonar.batch.scan.measure.DefaultMetricFinder; import org.sonar.batch.scan.measure.DeprecatedMetricFinder; @@ -82,7 +81,6 @@ import org.sonar.core.issue.workflow.FunctionExecutor; import org.sonar.core.issue.workflow.IssueWorkflow; import org.sonar.core.permission.PermissionFacade; import org.sonar.core.platform.ComponentContainer; -import org.sonar.core.technicaldebt.DefaultTechnicalDebtModel; public class ProjectScanContainer extends ComponentContainer { @@ -159,10 +157,10 @@ public class ProjectScanContainer extends ComponentContainer { InputPathCache.class, PathResolver.class, - // rules + // rules new ActiveRulesProvider(), - // issues + // issues IssueUpdater.class, FunctionExecutor.class, IssueWorkflow.class, @@ -171,31 +169,32 @@ public class ProjectScanContainer extends ComponentContainer { LocalIssueTracking.class, ServerIssueRepository.class, - // metrics + // metrics DefaultMetricFinder.class, DeprecatedMetricFinder.class, - // tests + // tests TestPlanBuilder.class, TestableBuilder.class, - // lang + // lang Languages.class, DefaultLanguagesRepository.class, - // Differential periods + // Differential periods PeriodsDefinition.class, - // Measures + // Measures MeasureCache.class, - // Duplications + // Duplications DuplicationCache.class, - ProjectSettings.class, + ProjectSettings.class, - // Report + // Report ReportPublisher.class, + MetadataPublisher.class, ComponentsPublisher.class, IssuesPublisher.class, MeasuresPublisher.class, @@ -204,19 +203,11 @@ public class ProjectScanContainer extends ComponentContainer { SourcePublisher.class, TestExecutionAndCoveragePublisher.class, - ScanTaskObservers.class); + ScanTaskObservers.class); } private void addDataBaseComponents() { - add( - PastMeasuresLoader.class, - - // Rules - new RulesProvider(), - new DebtModelProvider(), - - // technical debt - DefaultTechnicalDebtModel.class); + add(PastMeasuresLoader.class); } private void addBatchExtensions() { diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureCache.java b/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureCache.java index 92ab2292956..2fd211534ab 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureCache.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureCache.java @@ -23,10 +23,7 @@ import com.google.common.base.Preconditions; import org.sonar.api.batch.BatchSide; import org.sonar.api.batch.measure.MetricFinder; import org.sonar.api.measures.Measure; -import org.sonar.api.measures.RuleMeasure; import org.sonar.api.resources.Resource; -import org.sonar.api.technicaldebt.batch.Characteristic; -import org.sonar.api.technicaldebt.batch.TechnicalDebtModel; import org.sonar.batch.index.Cache; import org.sonar.batch.index.Cache.Entry; import org.sonar.batch.index.Caches; @@ -39,13 +36,8 @@ public class MeasureCache { private final Cache cache; - public MeasureCache(Caches caches, MetricFinder metricFinder, TechnicalDebtModel techDebtModel) { - caches.registerValueCoder(Measure.class, new MeasureValueCoder(metricFinder, techDebtModel)); - cache = caches.createCache("measures"); - } - public MeasureCache(Caches caches, MetricFinder metricFinder) { - caches.registerValueCoder(Measure.class, new MeasureValueCoder(metricFinder, null)); + caches.registerValueCoder(Measure.class, new MeasureValueCoder(metricFinder)); cache = caches.createCache("measures"); } @@ -88,19 +80,10 @@ public class MeasureCache { sb.append(m.getMetricKey()); } sb.append("|"); - Characteristic characteristic = m.getCharacteristic(); - if (characteristic != null) { - sb.append(characteristic.key()); - } - sb.append("|"); Integer personId = m.getPersonId(); if (personId != null) { sb.append(personId); } - if (m instanceof RuleMeasure) { - sb.append("|"); - sb.append(((RuleMeasure) m).ruleKey()); - } return sb.toString(); } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureValueCoder.java b/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureValueCoder.java index e7dae02780d..e0fb8bb54a9 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureValueCoder.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/measure/MeasureValueCoder.java @@ -22,24 +22,19 @@ package org.sonar.batch.scan.measure; import com.persistit.Value; import com.persistit.encoding.CoderContext; import com.persistit.encoding.ValueCoder; +import javax.annotation.Nullable; import org.sonar.api.batch.measure.MetricFinder; import org.sonar.api.measures.Measure; import org.sonar.api.measures.Metric; import org.sonar.api.measures.PersistenceMode; -import org.sonar.api.technicaldebt.batch.Characteristic; import org.sonar.api.technicaldebt.batch.Requirement; -import org.sonar.api.technicaldebt.batch.TechnicalDebtModel; - -import javax.annotation.Nullable; class MeasureValueCoder implements ValueCoder { private final MetricFinder metricFinder; - private final TechnicalDebtModel techDebtModel; - public MeasureValueCoder(MetricFinder metricFinder, @Nullable TechnicalDebtModel techDebtModel) { + public MeasureValueCoder(MetricFinder metricFinder) { this.metricFinder = metricFinder; - this.techDebtModel = techDebtModel; } @Override @@ -58,10 +53,6 @@ class MeasureValueCoder implements ValueCoder { value.put(m.getVariation4()); value.put(m.getVariation5()); putUTFOrNull(value, m.getUrl()); - Characteristic characteristic = m.getCharacteristic(); - value.put(characteristic != null ? characteristic.id() : null); - Requirement requirement = m.getRequirement(); - value.put(requirement != null ? requirement.id() : null); Integer personId = m.getPersonId(); value.put(personId != null ? personId.intValue() : null); PersistenceMode persistenceMode = m.getPersistenceMode(); @@ -97,8 +88,6 @@ class MeasureValueCoder implements ValueCoder { m.setVariation4(value.isNull(true) ? null : value.getDouble()); m.setVariation5(value.isNull(true) ? null : value.getDouble()); m.setUrl(value.getString()); - m.setCharacteristic(value.isNull(true) ? null : techDebtModel.characteristicById(value.getInt())); - m.setRequirement(value.isNull(true) ? null : techDebtModel.requirementsById(value.getInt())); m.setPersonId(value.isNull(true) ? null : value.getInt()); m.setPersistenceMode(value.isNull(true) ? null : PersistenceMode.valueOf(value.getString())); return m; diff --git a/sonar-batch/src/test/java/org/sonar/batch/debt/DebtDecoratorTest.java b/sonar-batch/src/test/java/org/sonar/batch/debt/DebtDecoratorTest.java deleted file mode 100644 index 4b96aba9ac0..00000000000 --- a/sonar-batch/src/test/java/org/sonar/batch/debt/DebtDecoratorTest.java +++ /dev/null @@ -1,353 +0,0 @@ -///* -// * 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.batch.debt; -// -//import com.google.common.collect.Lists; -//import org.apache.commons.lang.ObjectUtils; -//import org.apache.commons.lang.builder.ToStringBuilder; -//import org.apache.commons.lang.builder.ToStringStyle; -//import org.hamcrest.Description; -//import org.junit.Before; -//import org.junit.Test; -//import org.junit.runner.RunWith; -//import org.mockito.ArgumentMatcher; -//import org.mockito.Mock; -//import org.mockito.runners.MockitoJUnitRunner; -//import org.sonar.api.batch.DecoratorContext; -//import org.sonar.api.batch.rule.Rules; -//import org.sonar.api.batch.rule.internal.RulesBuilder; -//import org.sonar.api.component.ResourcePerspectives; -//import org.sonar.api.issue.Issuable; -//import org.sonar.api.issue.Issue; -//import org.sonar.core.issue.DefaultIssue; -//import org.sonar.api.measures.CoreMetrics; -//import org.sonar.api.measures.Measure; -//import org.sonar.api.measures.MeasuresFilter; -//import org.sonar.api.measures.Metric; -//import org.sonar.api.measures.RuleMeasure; -//import org.sonar.api.resources.File; -//import org.sonar.api.resources.Project; -//import org.sonar.api.resources.Resource; -//import org.sonar.api.rule.RuleKey; -//import org.sonar.api.rules.RuleFinder; -//import org.sonar.api.technicaldebt.batch.Characteristic; -//import org.sonar.api.technicaldebt.batch.TechnicalDebtModel; -//import org.sonar.api.technicaldebt.batch.internal.DefaultCharacteristic; -//import org.sonar.api.test.IsMeasure; -//import org.sonar.api.utils.Duration; -// -//import java.util.Collections; -// -//import static com.google.common.collect.Lists.newArrayList; -//import static org.assertj.core.api.Assertions.assertThat; -//import static org.mockito.Matchers.any; -//import static org.mockito.Matchers.argThat; -//import static org.mockito.Mockito.mock; -//import static org.mockito.Mockito.never; -//import static org.mockito.Mockito.times; -//import static org.mockito.Mockito.verify; -//import static org.mockito.Mockito.when; -// -//@RunWith(MockitoJUnitRunner.class) -//public class DebtDecoratorTest { -// -// static final int HOURS_IN_DAY = 8; -// -// static final Long ONE_DAY_IN_MINUTES = 1L * HOURS_IN_DAY * 60; -// -// @Mock -// DecoratorContext context; -// -// @Mock -// Resource resource; -// -// @Mock -// TechnicalDebtModel debtModel; -// -// @Mock -// Issuable issuable; -// -// @Mock -// ResourcePerspectives perspectives; -// -// @Mock -// RuleFinder ruleFinder; -// -// RuleKey ruleKey1 = RuleKey.of("repo1", "rule1"); -// RuleKey ruleKey2 = RuleKey.of("repo2", "rule2"); -// Rules rules; -// -// DefaultCharacteristic efficiency = new DefaultCharacteristic().setKey("EFFICIENCY"); -// DefaultCharacteristic memoryEfficiency = new DefaultCharacteristic().setKey("MEMORY_EFFICIENCY").setParent(efficiency); -// -// DefaultCharacteristic reusability = new DefaultCharacteristic().setKey("REUSABILITY"); -// DefaultCharacteristic modularity = new DefaultCharacteristic().setKey("MODULARITY").setParent(reusability); -// -// DebtDecorator decorator; -// -// @Before -// public void before() { -// when(perspectives.as(Issuable.class, resource)).thenReturn(issuable); -// RulesBuilder rulesBuilder = new RulesBuilder(); -// rulesBuilder.add(ruleKey1).setName("rule1").setDebtSubCharacteristic("MEMORY_EFFICIENCY"); -// rulesBuilder.add(ruleKey2).setName("rule2").setDebtSubCharacteristic("MODULARITY"); -// rules = rulesBuilder.build(); -// -// when(ruleFinder.findByKey(ruleKey1)).thenReturn(org.sonar.api.rules.Rule.create(ruleKey1.repository(), ruleKey1.rule())); -// when(ruleFinder.findByKey(ruleKey2)).thenReturn(org.sonar.api.rules.Rule.create(ruleKey2.repository(), ruleKey2.rule())); -// -// when(debtModel.characteristics()).thenReturn(newArrayList(efficiency, memoryEfficiency, reusability, modularity)); -// when(debtModel.characteristicByKey("EFFICIENCY")).thenReturn(efficiency); -// when(debtModel.characteristicByKey("MEMORY_EFFICIENCY")).thenReturn(memoryEfficiency); -// when(debtModel.characteristicByKey("REUSABILITY")).thenReturn(reusability); -// when(debtModel.characteristicByKey("MODULARITY")).thenReturn(modularity); -// -// decorator = new DebtDecorator(perspectives, debtModel, rules, ruleFinder); -// } -// -// @Test -// public void generates_metrics() { -// assertThat(decorator.generatesMetrics()).hasSize(1); -// } -// -// @Test -// public void execute_on_project() { -// assertThat(decorator.shouldExecuteOnProject(null)).isTrue(); -// } -// -// @Test -// public void not_save_if_measure_already_computed() { -// when(context.getMeasure(CoreMetrics.TECHNICAL_DEBT)).thenReturn(new Measure()); -// -// decorator.decorate(resource, context); -// -// verify(context, never()).saveMeasure(argThat(new IsMeasure(CoreMetrics.TECHNICAL_DEBT))); -// } -// -// @Test -// public void add_technical_debt_from_one_issue_and_no_parent() { -// Issue issue = createIssue("rule1", "repo1").setDebt(Duration.create(ONE_DAY_IN_MINUTES)); -// when(issuable.issues()).thenReturn(newArrayList(issue)); -// -// decorator.decorate(resource, context); -// -// verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, ONE_DAY_IN_MINUTES.doubleValue()); -// verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, ONE_DAY_IN_MINUTES.doubleValue()))); -// } -// -// @Test -// public void add_technical_debt_from_one_issue_without_debt() { -// Issue issue = createIssue("rule1", "repo1").setDebt(null); -// when(issuable.issues()).thenReturn(newArrayList(issue)); -// -// decorator.decorate(resource, context); -// -// verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, 0.0); -// } -// -// @Test -// public void add_technical_debt_from_one_issue_and_propagate_to_parents() { -// Issue issue = createIssue("rule1", "repo1").setDebt(Duration.create(ONE_DAY_IN_MINUTES)); -// when(issuable.issues()).thenReturn(newArrayList(issue)); -// -// decorator.decorate(resource, context); -// -// verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, ONE_DAY_IN_MINUTES.doubleValue()); -// verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, ONE_DAY_IN_MINUTES.doubleValue()))); -// verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, efficiency, ONE_DAY_IN_MINUTES.doubleValue()))); -// verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, memoryEfficiency, ONE_DAY_IN_MINUTES.doubleValue()))); -// } -// -// @Test -// public void add_technical_debt_from_issues() { -// Long technicalDebt1 = ONE_DAY_IN_MINUTES; -// Long technicalDebt2 = 2 * ONE_DAY_IN_MINUTES; -// -// Issue issue1 = createIssue("rule1", "repo1").setDebt(Duration.create(technicalDebt1)); -// Issue issue2 = createIssue("rule1", "repo1").setDebt(Duration.create(technicalDebt1)); -// Issue issue3 = createIssue("rule2", "repo2").setDebt(Duration.create(technicalDebt2)); -// Issue issue4 = createIssue("rule2", "repo2").setDebt(Duration.create(technicalDebt2)); -// when(issuable.issues()).thenReturn(newArrayList(issue1, issue2, issue3, issue4)); -// -// decorator.decorate(resource, context); -// -// verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, 6d * ONE_DAY_IN_MINUTES); -// verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, 2d * ONE_DAY_IN_MINUTES))); -// verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey2, 4d * ONE_DAY_IN_MINUTES))); -// } -// -// @Test -// public void add_technical_debt_from_current_and_children_measures() { -// Issue issue1 = createIssue("rule1", "repo1").setDebt(Duration.create(ONE_DAY_IN_MINUTES)); -// Issue issue2 = createIssue("rule1", "repo1").setDebt(Duration.create(ONE_DAY_IN_MINUTES)); -// when(issuable.issues()).thenReturn(newArrayList(issue1, issue2)); -// -// when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Lists.newArrayList( -// new RuleMeasure(CoreMetrics.TECHNICAL_DEBT, -// org.sonar.api.rules.Rule.create(ruleKey1.repository(), ruleKey1.rule()), null, null) -// .setValue(5d * ONE_DAY_IN_MINUTES) -// )); -// decorator.decorate(resource, context); -// -// verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, 7d * ONE_DAY_IN_MINUTES); -// verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, 7d * ONE_DAY_IN_MINUTES))); -// verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, memoryEfficiency, 7d * ONE_DAY_IN_MINUTES))); -// verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, efficiency, 7d * ONE_DAY_IN_MINUTES))); -// } -// -// @Test -// public void add_technical_debt_only_from_children_measures() { -// when(issuable.issues()).thenReturn(Collections.emptyList()); -// -// when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Lists.newArrayList( -// new RuleMeasure(CoreMetrics.TECHNICAL_DEBT, -// org.sonar.api.rules.Rule.create(ruleKey1.repository(), ruleKey1.rule()) -// , null, null).setValue(5d * ONE_DAY_IN_MINUTES), -// -// new RuleMeasure(CoreMetrics.TECHNICAL_DEBT, -// org.sonar.api.rules.Rule.create(ruleKey2.repository(), ruleKey2.rule()) -// , null, null).setValue(10d * ONE_DAY_IN_MINUTES) -// )); -// decorator.decorate(resource, context); -// -// verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, 15d * ONE_DAY_IN_MINUTES); -// verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, 5d * ONE_DAY_IN_MINUTES))); -// verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey2, 10d * ONE_DAY_IN_MINUTES))); -// verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, memoryEfficiency, 5d * ONE_DAY_IN_MINUTES))); -// verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, efficiency, 5d * ONE_DAY_IN_MINUTES))); -// verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, reusability, 10d * ONE_DAY_IN_MINUTES))); -// verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, modularity, 10d * ONE_DAY_IN_MINUTES))); -// } -// -// @Test -// public void always_save_technical_debt_for_positive_values() { -// // for a project -// DecoratorContext context = mock(DecoratorContext.class); -// when(context.getResource()).thenReturn(new Project("foo")); -// decorator.saveCharacteristicMeasure(context, (Characteristic) null, 12.0, false); -// verify(context, times(1)).saveMeasure(new Measure(CoreMetrics.TECHNICAL_DEBT)); -// -// // or for a file -// context = mock(DecoratorContext.class); -// when(context.getResource()).thenReturn(File.create("foo")); -// decorator.saveCharacteristicMeasure(context, (Characteristic) null, 12.0, false); -// verify(context, times(1)).saveMeasure(new Measure(CoreMetrics.TECHNICAL_DEBT)); -// } -// -// @Test -// public void always_save_technical_debt_for_project_if_top_characteristic() { -// DecoratorContext context = mock(DecoratorContext.class); -// when(context.getResource()).thenReturn(new Project("foo")); -// -// // this is a top characteristic -// DefaultCharacteristic rootCharacteristic = new DefaultCharacteristic().setKey("root"); -// -// decorator.saveCharacteristicMeasure(context, rootCharacteristic, 0.0, true); -// verify(context, times(1)).saveMeasure(new Measure(CoreMetrics.TECHNICAL_DEBT).setCharacteristic(rootCharacteristic)); -// } -// -// /** -// * SQALE-147 -// */ -// @Test -// public void never_save_technical_debt_for_project_if_not_top_characteristic() { -// DecoratorContext context = mock(DecoratorContext.class); -// when(context.getResource()).thenReturn(new Project("foo")); -// -// DefaultCharacteristic rootCharacteristic = new DefaultCharacteristic().setKey("EFFICIENCY"); -// DefaultCharacteristic characteristic = new DefaultCharacteristic().setKey("MEMORY_EFFICIENCY").setParent(rootCharacteristic); -// -// decorator.saveCharacteristicMeasure(context, characteristic, 0.0, true); -// verify(context, never()).saveMeasure(any(Measure.class)); -// } -// -// @Test -// public void not_save_technical_debt_for_file_if_zero() { -// DecoratorContext context = mock(DecoratorContext.class); -// when(context.getResource()).thenReturn(File.create("foo")); -// -// decorator.saveCharacteristicMeasure(context, null, 0.0, true); -// verify(context, never()).saveMeasure(new Measure(CoreMetrics.TECHNICAL_DEBT)); -// } -// -// private DefaultIssue createIssue(String ruleKey, String repositoryKey) { -// return new DefaultIssue().setRuleKey(RuleKey.of(repositoryKey, ruleKey)); -// } -// -// class IsCharacteristicMeasure extends ArgumentMatcher { -// Metric metric = null; -// Characteristic characteristic = null; -// Double value = null; -// -// public IsCharacteristicMeasure(Metric metric, Characteristic characteristic, Double value) { -// this.metric = metric; -// this.characteristic = characteristic; -// this.value = value; -// } -// -// @Override -// public boolean matches(Object o) { -// if (!(o instanceof Measure)) { -// return false; -// } -// Measure m = (Measure) o; -// return ObjectUtils.equals(metric, m.getMetric()) && -// ObjectUtils.equals(characteristic, m.getCharacteristic()) && -// ObjectUtils.equals(value, m.getValue()); -// } -// -// @Override -// public void describeTo(Description description) { -// description.appendText(new StringBuilder() -// .append("value=").append(value).append(",") -// .append("characteristic=").append(characteristic.key()).append(",") -// .append("metric=").append(metric.getKey()).toString()); -// } -// } -// -// class IsRuleMeasure extends ArgumentMatcher { -// Metric metric = null; -// RuleKey ruleKey = null; -// Double value = null; -// -// public IsRuleMeasure(Metric metric, RuleKey ruleKey, Double value) { -// this.metric = metric; -// this.ruleKey = ruleKey; -// this.value = value; -// } -// -// @Override -// public boolean matches(Object o) { -// if (!(o instanceof RuleMeasure)) { -// return false; -// } -// RuleMeasure m = (RuleMeasure) o; -// return ObjectUtils.equals(metric, m.getMetric()) && -// ObjectUtils.equals(ruleKey, m.ruleKey()) && -// ObjectUtils.equals(value, m.getValue()); -// } -// -// @Override -// public void describeTo(Description description) { -// description.appendText(ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE)); -// } -// } -//} diff --git a/sonar-batch/src/test/java/org/sonar/batch/debt/DebtModelProviderTest.java b/sonar-batch/src/test/java/org/sonar/batch/debt/DebtModelProviderTest.java deleted file mode 100644 index 1d434d5d2e5..00000000000 --- a/sonar-batch/src/test/java/org/sonar/batch/debt/DebtModelProviderTest.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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.batch.debt; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; -import org.sonar.api.batch.debt.DebtCharacteristic; -import org.sonar.api.batch.debt.DebtModel; -import org.sonar.core.technicaldebt.db.CharacteristicDao; -import org.sonar.core.technicaldebt.db.CharacteristicDto; - -import static com.google.common.collect.Lists.newArrayList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.when; - -@RunWith(MockitoJUnitRunner.class) -public class DebtModelProviderTest { - - @Mock - CharacteristicDao dao; - - DebtModelProvider provider; - - @Before - public void before() { - provider = new DebtModelProvider(); - } - - @Test - public void provide_model() { - CharacteristicDto rootCharacteristicDto = new CharacteristicDto() - .setId(1) - .setKey("MEMORY_EFFICIENCY") - .setName("Memory use") - .setOrder(1); - - CharacteristicDto characteristicDto = new CharacteristicDto() - .setId(2) - .setKey("EFFICIENCY") - .setName("Efficiency") - .setParentId(1); - - when(dao.selectEnabledCharacteristics()).thenReturn(newArrayList(rootCharacteristicDto, characteristicDto)); - - DebtModel result = provider.provide(dao); - assertThat(result.characteristics()).hasSize(1); - - DebtCharacteristic characteristic = result.characteristicByKey("MEMORY_EFFICIENCY"); - assertThat(characteristic.key()).isEqualTo("MEMORY_EFFICIENCY"); - assertThat(characteristic.name()).isEqualTo("Memory use"); - assertThat(characteristic.isSub()).isFalse(); - assertThat(characteristic.order()).isEqualTo(1); - - DebtCharacteristic subCharacteristic = result.characteristicByKey("EFFICIENCY"); - assertThat(subCharacteristic.key()).isEqualTo("EFFICIENCY"); - assertThat(subCharacteristic.name()).isEqualTo("Efficiency"); - assertThat(subCharacteristic.isSub()).isTrue(); - assertThat(subCharacteristic.order()).isNull(); - } -} diff --git a/sonar-batch/src/test/java/org/sonar/batch/debt/IssueChangelogDebtCalculatorTest.java b/sonar-batch/src/test/java/org/sonar/batch/debt/IssueChangelogDebtCalculatorTest.java deleted file mode 100644 index fb2bf2e90f5..00000000000 --- a/sonar-batch/src/test/java/org/sonar/batch/debt/IssueChangelogDebtCalculatorTest.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * 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.batch.debt; - -import org.apache.commons.lang.time.DateUtils; -import org.junit.Before; -import org.junit.Test; -import org.sonar.api.issue.Issue; -import org.sonar.core.issue.DefaultIssue; -import org.sonar.core.issue.FieldDiffs; -import org.sonar.api.utils.Duration; - -import java.util.Date; - -import static com.google.common.collect.Lists.newArrayList; -import static org.assertj.core.api.Assertions.assertThat; - -public class IssueChangelogDebtCalculatorTest { - - private static final int HOURS_IN_DAY = 8; - - IssueChangelogDebtCalculator issueChangelogDebtCalculator; - - Date rightNow = new Date(); - Date elevenDaysAgo = DateUtils.addDays(rightNow, -11); - Date tenDaysAgo = DateUtils.addDays(rightNow, -10); - Date nineDaysAgo = DateUtils.addDays(rightNow, -9); - Date fiveDaysAgo = DateUtils.addDays(rightNow, -5); - Date fourDaysAgo = DateUtils.addDays(rightNow, -4); - - long oneDay = 1 * HOURS_IN_DAY * 60 * 60L; - long twoDays = 2 * HOURS_IN_DAY * 60 * 60L; - long fiveDays = 5 * HOURS_IN_DAY * 60 * 60L; - - Duration oneDayDebt = Duration.create(oneDay); - Duration twoDaysDebt = Duration.create(twoDays); - Duration fiveDaysDebt = Duration.create(fiveDays); - - @Before - public void setUp() { - issueChangelogDebtCalculator = new IssueChangelogDebtCalculator(); - } - - @Test - public void calculate_new_technical_debt_with_one_diff_in_changelog() { - Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(twoDaysDebt).setChanges( - newArrayList( - // changelog created at is null because it has just been created on the current analysis - new FieldDiffs().setDiff("technicalDebt", oneDay, twoDays).setCreationDate(null) - ) - ); - - assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, rightNow)).isEqualTo(oneDay); - assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, fiveDaysAgo)).isEqualTo(oneDay); - - assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, elevenDaysAgo)).isEqualTo(twoDays); - } - - @Test - public void calculate_new_technical_debt_with_many_diffs_in_changelog() { - Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(fiveDaysDebt).setChanges( - newArrayList( - new FieldDiffs().setDiff("technicalDebt", twoDays, fiveDays).setCreationDate(null), - new FieldDiffs().setDiff("technicalDebt", oneDay, twoDays).setCreationDate(fourDaysAgo) - ) - ); - - assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, rightNow)).isEqualTo(3 * oneDay); - assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, fiveDaysAgo)).isEqualTo(4 * oneDay); - assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, elevenDaysAgo)).isEqualTo(5 * oneDay); - } - - @Test - public void changelog_can_be_in_wrong_order() { - Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(fiveDaysDebt).setChanges( - newArrayList( - // 3rd - new FieldDiffs().setDiff("technicalDebt", null, oneDay).setCreationDate(nineDaysAgo), - // 1st - new FieldDiffs().setDiff("technicalDebt", twoDays, fiveDays).setCreationDate(rightNow), - // 2nd - new FieldDiffs().setDiff("technicalDebt", oneDay, twoDays).setCreationDate(fourDaysAgo) - ) - ); - - assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, fiveDaysAgo)).isEqualTo(4 * oneDay); - assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, elevenDaysAgo)).isEqualTo(5 * oneDay); - } - - @Test - public void calculate_new_technical_debt_with_null_date() { - Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(twoDaysDebt).setChanges( - newArrayList( - new FieldDiffs().setDiff("technicalDebt", oneDay, twoDays).setCreationDate(null) - ) - ); - - assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, null)).isEqualTo(2 * oneDay); - } - - @Test - public void calculate_new_technical_debt_when_new_debt_is_null() { - Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(null).setChanges( - newArrayList( - new FieldDiffs().setDiff("technicalDebt", oneDay, null).setCreationDate(null), - new FieldDiffs().setDiff("technicalDebt", null, oneDay).setCreationDate(nineDaysAgo) - ) - ); - - assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, rightNow)).isNull(); - } - - @Test - public void calculate_new_technical_debt_on_issue_without_technical_debt_and_without_changelog() { - Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo); - - assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, rightNow)).isNull(); - } - - @Test - public void not_return_negative_debt() { - Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(oneDayDebt).setChanges( - newArrayList( - new FieldDiffs().setDiff("technicalDebt", twoDays, oneDay).setCreationDate(null) - ) - ); - - assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, rightNow)).isNull(); - } - -} diff --git a/sonar-batch/src/test/java/org/sonar/batch/debt/NewDebtDecoratorTest.java b/sonar-batch/src/test/java/org/sonar/batch/debt/NewDebtDecoratorTest.java deleted file mode 100644 index 8b00495711b..00000000000 --- a/sonar-batch/src/test/java/org/sonar/batch/debt/NewDebtDecoratorTest.java +++ /dev/null @@ -1,376 +0,0 @@ -/* - * 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.batch.debt; - -import org.apache.commons.lang.ObjectUtils; -import org.apache.commons.lang.time.DateUtils; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentMatcher; -import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; -import org.sonar.api.CoreProperties; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.component.ResourcePerspectives; -import org.sonar.api.config.Settings; -import org.sonar.api.issue.Issuable; -import org.sonar.api.issue.Issue; -import org.sonar.core.issue.DefaultIssue; -import org.sonar.core.issue.FieldDiffs; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Measure; -import org.sonar.api.measures.Metric; -import org.sonar.api.resources.Resource; -import org.sonar.api.test.IsMeasure; -import org.sonar.api.utils.Duration; -import org.sonar.batch.components.Period; -import org.sonar.batch.components.TimeMachineConfiguration; - -import java.util.Date; - -import static com.google.common.collect.Lists.newArrayList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.argThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -@RunWith(MockitoJUnitRunner.class) -public class NewDebtDecoratorTest { - - NewDebtDecorator decorator; - - @Mock - TimeMachineConfiguration timeMachineConfiguration; - - @Mock - Resource resource; - - @Mock - Issuable issuable; - - @Mock - DecoratorContext context; - - Date rightNow; - Date elevenDaysAgo; - Date tenDaysAgo; - Date nineDaysAgo; - Date fiveDaysAgo; - Date fourDaysAgo; - - static final int HOURS_IN_DAY = 8; - - static final Long ONE_DAY_IN_MINUTES = 1L * HOURS_IN_DAY * 60; - static final Long TWO_DAYS_IN_MINUTES = 2L * HOURS_IN_DAY * 60; - static final Long FIVE_DAYS_IN_MINUTES = 5L * HOURS_IN_DAY * 60; - - @Before - public void setup() { - Settings settings = new Settings(); - settings.setProperty(CoreProperties.HOURS_IN_DAY, HOURS_IN_DAY); - - ResourcePerspectives perspectives = mock(ResourcePerspectives.class); - when(perspectives.as(Issuable.class, resource)).thenReturn(issuable); - - rightNow = new Date(); - elevenDaysAgo = DateUtils.addDays(rightNow, -11); - tenDaysAgo = DateUtils.addDays(rightNow, -10); - nineDaysAgo = DateUtils.addDays(rightNow, -9); - fiveDaysAgo = DateUtils.addDays(rightNow, -5); - fourDaysAgo = DateUtils.addDays(rightNow, -4); - - when(timeMachineConfiguration.periods()).thenReturn(newArrayList(new Period(1, fiveDaysAgo), new Period(2, tenDaysAgo))); - - decorator = new NewDebtDecorator(perspectives, timeMachineConfiguration, new IssueChangelogDebtCalculator()); - } - - @Test - public void generates_metrics() { - assertThat(decorator.generatesMetrics()).hasSize(1); - } - - @Test - public void execute_on_project() { - assertThat(decorator.shouldExecuteOnProject(null)).isTrue(); - } - - @Test - public void save_on_one_issue_with_one_new_changelog() { - Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(Duration.create(TWO_DAYS_IN_MINUTES)).setChanges( - newArrayList( - // changelog created at is null because it has just been created on the current analysis - new FieldDiffs().setDiff("technicalDebt", ONE_DAY_IN_MINUTES, TWO_DAYS_IN_MINUTES).setCreationDate(null) - ) - ); - when(issuable.issues()).thenReturn(newArrayList(issue)); - - decorator.decorate(resource, context); - - // remember : period1 is 5daysAgo, period2 is 10daysAgo - verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 1.0 * ONE_DAY_IN_MINUTES, 1.0 * ONE_DAY_IN_MINUTES))); - } - - @Test - public void save_on_one_issue_with_changelog() { - Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES)).setChanges( - newArrayList( - new FieldDiffs().setDiff("technicalDebt", TWO_DAYS_IN_MINUTES, FIVE_DAYS_IN_MINUTES).setCreationDate(null), - new FieldDiffs().setDiff("technicalDebt", ONE_DAY_IN_MINUTES, TWO_DAYS_IN_MINUTES).setCreationDate(fourDaysAgo) - ) - ); - when(issuable.issues()).thenReturn(newArrayList(issue)); - - decorator.decorate(resource, context); - - // remember : period1 is 5daysAgo, period2 is 10daysAgo - verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 4.0 * ONE_DAY_IN_MINUTES, 4.0 * ONE_DAY_IN_MINUTES))); - } - - @Test - public void save_on_one_issue_with_changelog_only_in_the_past() { - Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(Duration.create(ONE_DAY_IN_MINUTES)).setChanges( - newArrayList( - // Change before all periods - new FieldDiffs().setDiff("technicalDebt", null, ONE_DAY_IN_MINUTES).setCreationDate(elevenDaysAgo) - ) - ); - when(issuable.issues()).thenReturn(newArrayList(issue)); - - decorator.decorate(resource, context); - - // remember : period1 is 5daysAgo, period2 is 10daysAgo - verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0, 0.0))); - } - - @Test - public void save_on_one_issue_with_changelog_having_null_value() { - Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES)).setChanges( - newArrayList( - new FieldDiffs().setDiff("technicalDebt", null, FIVE_DAYS_IN_MINUTES).setCreationDate(null), - new FieldDiffs().setDiff("technicalDebt", ONE_DAY_IN_MINUTES, null).setCreationDate(fourDaysAgo), - new FieldDiffs().setDiff("technicalDebt", null, ONE_DAY_IN_MINUTES).setCreationDate(nineDaysAgo) - ) - ); - when(issuable.issues()).thenReturn(newArrayList(issue)); - - decorator.decorate(resource, context); - - // remember : period1 is 5daysAgo, period2 is 10daysAgo - verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 4.0 * ONE_DAY_IN_MINUTES, 5.0 * ONE_DAY_IN_MINUTES))); - } - - @Test - public void save_on_one_issue_with_changelog_and_periods_have_no_dates() { - when(timeMachineConfiguration.periods()).thenReturn(newArrayList(new Period(1, null), new Period(2, null))); - - Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES)).setChanges( - newArrayList( - new FieldDiffs().setDiff("technicalDebt", null, FIVE_DAYS_IN_MINUTES).setCreationDate(null), - new FieldDiffs().setDiff("technicalDebt", ONE_DAY_IN_MINUTES, null).setCreationDate(fourDaysAgo), - new FieldDiffs().setDiff("technicalDebt", null, ONE_DAY_IN_MINUTES).setCreationDate(nineDaysAgo) - ) - ); - when(issuable.issues()).thenReturn(newArrayList(issue)); - - decorator.decorate(resource, context); - - // remember : period1 is 5daysAgo, period2 is 10daysAgo - verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 5.0 * ONE_DAY_IN_MINUTES, 5.0 * ONE_DAY_IN_MINUTES))); - } - - @Test - public void save_on_one_issue_with_changelog_having_not_only_technical_debt_changes() { - Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES)).setChanges( - newArrayList( - new FieldDiffs() - .setDiff("actionPlan", "1.0", "1.1").setCreationDate(fourDaysAgo) - .setDiff("technicalDebt", ONE_DAY_IN_MINUTES, TWO_DAYS_IN_MINUTES).setCreationDate(fourDaysAgo) - ) - ); - when(issuable.issues()).thenReturn(newArrayList(issue)); - - decorator.decorate(resource, context); - - // remember : period1 is 5daysAgo, period2 is 10daysAgo - verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 4.0 * ONE_DAY_IN_MINUTES, 4.0 * ONE_DAY_IN_MINUTES))); - } - - @Test - public void save_on_issues_with_changelog() { - Issue issue1 = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES)).setChanges( - newArrayList( - new FieldDiffs().setDiff("technicalDebt", TWO_DAYS_IN_MINUTES, FIVE_DAYS_IN_MINUTES).setCreationDate(rightNow), - new FieldDiffs().setDiff("technicalDebt", ONE_DAY_IN_MINUTES, TWO_DAYS_IN_MINUTES).setCreationDate(fourDaysAgo), - new FieldDiffs().setDiff("technicalDebt", null, ONE_DAY_IN_MINUTES).setCreationDate(nineDaysAgo) - ) - ); - Issue issue2 = new DefaultIssue().setKey("B").setCreationDate(tenDaysAgo).setDebt(Duration.create(TWO_DAYS_IN_MINUTES)).setChanges( - newArrayList( - new FieldDiffs().setDiff("technicalDebt", ONE_DAY_IN_MINUTES, TWO_DAYS_IN_MINUTES).setCreationDate(rightNow), - new FieldDiffs().setDiff("technicalDebt", null, ONE_DAY_IN_MINUTES).setCreationDate(nineDaysAgo) - ) - ); - when(issuable.issues()).thenReturn(newArrayList(issue1, issue2)); - - decorator.decorate(resource, context); - - // remember : period1 is 5daysAgo, period2 is 10daysAgo - verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 5.0 * ONE_DAY_IN_MINUTES, 7.0 * ONE_DAY_IN_MINUTES))); - } - - @Test - public void save_on_one_issue_without_changelog() { - when(issuable.issues()).thenReturn(newArrayList( - (Issue) new DefaultIssue().setKey("A").setCreationDate(nineDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES))) - ); - - decorator.decorate(resource, context); - - // remember : period1 is 5daysAgo, period2 is 10daysAgo - verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0, 5.0 * ONE_DAY_IN_MINUTES))); - } - - @Test - public void save_on_one_issue_without_technical_debt_and_without_changelog() { - when(issuable.issues()).thenReturn(newArrayList( - (Issue) new DefaultIssue().setKey("A").setCreationDate(nineDaysAgo).setDebt(null)) - ); - - decorator.decorate(resource, context); - - // remember : period1 is 5daysAgo, period2 is 10daysAgo - verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0, 0.0))); - } - - @Test - public void save_on_one_issue_without_changelog_and_periods_have_no_dates() { - when(timeMachineConfiguration.periods()).thenReturn(newArrayList(new Period(1, null), new Period(2, null))); - - when(issuable.issues()).thenReturn(newArrayList( - (Issue) new DefaultIssue().setKey("A").setCreationDate(nineDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES))) - ); - - decorator.decorate(resource, context); - - // remember : period1 is null, period2 is null - verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 5.0 * ONE_DAY_IN_MINUTES, 5.0 * ONE_DAY_IN_MINUTES))); - } - - @Test - public void save_on_issues_without_changelog() { - when(issuable.issues()).thenReturn(newArrayList( - (Issue) new DefaultIssue().setKey("A").setCreationDate(nineDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES)), - new DefaultIssue().setKey("B").setCreationDate(fiveDaysAgo).setDebt(Duration.create(TWO_DAYS_IN_MINUTES)) - )); - - decorator.decorate(resource, context); - - // remember : period1 is 5daysAgo, period2 is 10daysAgo - verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0, 7.0 * ONE_DAY_IN_MINUTES))); - } - - @Test - public void save_on_issues_with_changelog_and_issues_without_changelog() { - // issue1 and issue2 have changelog - Issue issue1 = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES)).setChanges( - newArrayList( - new FieldDiffs().setDiff("technicalDebt", TWO_DAYS_IN_MINUTES, FIVE_DAYS_IN_MINUTES).setCreationDate(rightNow), - new FieldDiffs().setDiff("technicalDebt", ONE_DAY_IN_MINUTES, TWO_DAYS_IN_MINUTES).setCreationDate(fourDaysAgo), - new FieldDiffs().setDiff("technicalDebt", null, ONE_DAY_IN_MINUTES).setCreationDate(nineDaysAgo) - ) - ); - Issue issue2 = new DefaultIssue().setKey("B").setCreationDate(tenDaysAgo).setDebt(Duration.create(TWO_DAYS_IN_MINUTES)).setChanges( - newArrayList( - new FieldDiffs().setDiff("technicalDebt", ONE_DAY_IN_MINUTES, TWO_DAYS_IN_MINUTES).setCreationDate(rightNow), - new FieldDiffs().setDiff("technicalDebt", null, ONE_DAY_IN_MINUTES).setCreationDate(nineDaysAgo) - ) - ); - - // issue3 and issue4 have no changelog - Issue issue3 = new DefaultIssue().setKey("C").setCreationDate(nineDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES)); - Issue issue4 = new DefaultIssue().setKey("D").setCreationDate(fiveDaysAgo).setDebt(Duration.create(TWO_DAYS_IN_MINUTES)); - when(issuable.issues()).thenReturn(newArrayList(issue1, issue2, issue3, issue4)); - - decorator.decorate(resource, context); - - // remember : period1 is 5daysAgo, period2 is 10daysAgo - verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 5.0 * ONE_DAY_IN_MINUTES, 14.0 * ONE_DAY_IN_MINUTES))); - } - - @Test - public void not_save_if_measure_already_computed() { - when(context.getMeasure(CoreMetrics.NEW_TECHNICAL_DEBT)).thenReturn(new Measure()); - when(issuable.issues()).thenReturn(newArrayList( - (Issue) new DefaultIssue().setKey("A").setCreationDate(nineDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES)), - new DefaultIssue().setKey("B").setCreationDate(fiveDaysAgo).setDebt(Duration.create(TWO_DAYS_IN_MINUTES)) - )); - - decorator.decorate(resource, context); - - verify(context, never()).saveMeasure(argThat(new IsMeasure(CoreMetrics.NEW_TECHNICAL_DEBT))); - } - - /** - * SONAR-5059 - */ - @Test - public void not_return_negative_debt() { - Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(Duration.create(ONE_DAY_IN_MINUTES)).setChanges( - newArrayList( - // changelog created at is null because it has just been created on the current analysis - new FieldDiffs().setDiff("technicalDebt", TWO_DAYS_IN_MINUTES, ONE_DAY_IN_MINUTES).setCreationDate(null) - ) - ); - when(issuable.issues()).thenReturn(newArrayList(issue)); - - decorator.decorate(resource, context); - - // remember : period1 is 5daysAgo, period2 is 10daysAgo - verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0, 0.0))); - } - - - class IsVariationMeasure extends ArgumentMatcher { - Metric metric = null; - Double var1 = null; - Double var2 = null; - - public IsVariationMeasure(Metric metric, Double var1, Double var2) { - this.metric = metric; - this.var1 = var1; - this.var2 = var2; - } - - public boolean matches(Object o) { - if (!(o instanceof Measure)) { - return false; - } - Measure m = (Measure) o; - return ObjectUtils.equals(metric, m.getMetric()) && - ObjectUtils.equals(var1, m.getVariation1()) && - ObjectUtils.equals(var2, m.getVariation2()); - } - } - -} diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/ModuleIssuesTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/ModuleIssuesTest.java index f1157f16572..6f9961c681a 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/issue/ModuleIssuesTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ModuleIssuesTest.java @@ -253,7 +253,6 @@ public class ModuleIssuesTest { public void set_debt_with_linear_function() { ruleBuilder.add(SQUID_RULE_KEY) .setName(SQUID_RULE_NAME) - .setDebtSubCharacteristic("COMPILER_RELATED_PORTABILITY") .setDebtRemediationFunction(DebtRemediationFunction.createLinear(Duration.create(10L))); activeRulesBuilder.create(SQUID_RULE_KEY).setSeverity(Severity.INFO).activate(); initModuleIssues(); @@ -279,7 +278,6 @@ public class ModuleIssuesTest { public void set_debt_with_linear_with_offset_function() { ruleBuilder.add(SQUID_RULE_KEY) .setName(SQUID_RULE_NAME) - .setDebtSubCharacteristic("COMPILER_RELATED_PORTABILITY") .setDebtRemediationFunction(DebtRemediationFunction.createLinearWithOffset(Duration.create(10L), Duration.create(25L))); activeRulesBuilder.create(SQUID_RULE_KEY).setSeverity(Severity.INFO).activate(); initModuleIssues(); @@ -305,7 +303,6 @@ public class ModuleIssuesTest { public void set_debt_with_constant_issue_function() { ruleBuilder.add(SQUID_RULE_KEY) .setName(SQUID_RULE_NAME) - .setDebtSubCharacteristic("COMPILER_RELATED_PORTABILITY") .setDebtRemediationFunction(DebtRemediationFunction.createConstantPerIssue(Duration.create(10L))); activeRulesBuilder.create(SQUID_RULE_KEY).setSeverity(Severity.INFO).activate(); initModuleIssues(); @@ -331,7 +328,6 @@ public class ModuleIssuesTest { public void fail_to_set_debt_with_constant_issue_function_when_effort_to_fix_is_set() { ruleBuilder.add(SQUID_RULE_KEY) .setName(SQUID_RULE_NAME) - .setDebtSubCharacteristic("COMPILER_RELATED_PORTABILITY") .setDebtRemediationFunction(DebtRemediationFunction.createConstantPerIssue(Duration.create(25L))); activeRulesBuilder.create(SQUID_RULE_KEY).setSeverity(Severity.INFO).activate(); initModuleIssues(); diff --git a/sonar-batch/src/test/java/org/sonar/batch/report/IssuesPublisherTest.java b/sonar-batch/src/test/java/org/sonar/batch/report/IssuesPublisherTest.java index fbe835369f3..bdcce1bd74f 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/report/IssuesPublisherTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/report/IssuesPublisherTest.java @@ -27,7 +27,6 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; -import org.sonar.api.CoreProperties; import org.sonar.api.batch.bootstrap.ProjectDefinition; import org.sonar.api.database.model.Snapshot; import org.sonar.api.resources.Project; @@ -35,10 +34,8 @@ import org.sonar.api.rule.RuleKey; import org.sonar.api.utils.Duration; import org.sonar.batch.index.BatchComponentCache; import org.sonar.batch.issue.IssueCache; -import org.sonar.batch.protocol.output.BatchReport.Metadata; import org.sonar.batch.protocol.output.BatchReportReader; import org.sonar.batch.protocol.output.BatchReportWriter; -import org.sonar.batch.scan.ImmutableProjectReactor; import org.sonar.core.issue.DefaultIssue; import org.sonar.core.issue.FieldDiffs; @@ -52,29 +49,27 @@ public class IssuesPublisherTest { @Rule public TemporaryFolder temp = new TemporaryFolder(); - private IssueCache issueCache; - private IssuesPublisher publisher; + IssueCache issueCache; + ProjectDefinition projectDef; + Project project; - private ProjectDefinition root; - - private Project p; + IssuesPublisher underTest; @Before public void prepare() { - root = ProjectDefinition.create().setKey("foo"); - p = new Project("foo").setAnalysisDate(new Date(1234567L)); + projectDef = ProjectDefinition.create().setKey("foo"); + project = new Project("foo").setAnalysisDate(new Date(1234567L)); BatchComponentCache componentCache = new BatchComponentCache(); org.sonar.api.resources.Resource sampleFile = org.sonar.api.resources.File.create("src/Foo.php").setEffectiveKey("foo:src/Foo.php"); - componentCache.add(p, null).setSnapshot(new Snapshot().setId(2)); - componentCache.add(sampleFile, p); + componentCache.add(project, null).setSnapshot(new Snapshot().setId(2)); + componentCache.add(sampleFile, project); issueCache = mock(IssueCache.class); when(issueCache.byComponent(anyString())).thenReturn(Collections.emptyList()); - publisher = new IssuesPublisher(new ImmutableProjectReactor(root), componentCache, issueCache); + underTest = new IssuesPublisher(componentCache, issueCache); } @Test - public void publishIssuesAndMetadata() throws Exception { - + public void write_issues() throws Exception { DefaultIssue issue1 = new DefaultIssue(); issue1.setKey("uuid"); issue1.setSeverity("MAJOR"); @@ -104,34 +99,11 @@ public class IssuesPublisherTest { File outputDir = temp.newFolder(); BatchReportWriter writer = new BatchReportWriter(outputDir); - publisher.publish(writer); + underTest.publish(writer); BatchReportReader reader = new BatchReportReader(outputDir); - Metadata metadata = reader.readMetadata(); - assertThat(metadata.getAnalysisDate()).isEqualTo(1234567L); - assertThat(metadata.getProjectKey()).isEqualTo("foo"); - assertThat(reader.readComponentIssues(1)).hasSize(0); assertThat(reader.readComponentIssues(2)).hasSize(2); - - } - - @Test - public void publishMetadataWithBranch() throws Exception { - root.properties().put(CoreProperties.PROJECT_BRANCH_PROPERTY, "myBranch"); - p.setKey("foo:myBranch"); - p.setEffectiveKey("foo:myBranch"); - - File outputDir = temp.newFolder(); - BatchReportWriter writer = new BatchReportWriter(outputDir); - - publisher.publish(writer); - - BatchReportReader reader = new BatchReportReader(outputDir); - Metadata metadata = reader.readMetadata(); - assertThat(metadata.getAnalysisDate()).isEqualTo(1234567L); - assertThat(metadata.getProjectKey()).isEqualTo("foo"); - assertThat(metadata.getBranch()).isEqualTo("myBranch"); } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/report/MeasuresPublisherTest.java b/sonar-batch/src/test/java/org/sonar/batch/report/MeasuresPublisherTest.java index 94204a3afbc..c4faec31bce 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/report/MeasuresPublisherTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/report/MeasuresPublisherTest.java @@ -37,12 +37,12 @@ import org.sonar.api.measures.Metric.ValueType; import org.sonar.api.measures.MetricFinder; import org.sonar.api.resources.Project; import org.sonar.api.resources.Resource; -import org.sonar.api.technicaldebt.batch.Characteristic; import org.sonar.batch.index.BatchComponentCache; import org.sonar.batch.protocol.output.BatchReportReader; import org.sonar.batch.protocol.output.BatchReportWriter; import org.sonar.batch.scan.measure.MeasureCache; +import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; @@ -81,12 +81,8 @@ public class MeasuresPublisherTest { @Test public void publishMeasures() throws Exception { - Measure measure1 = new Measure<>(CoreMetrics.COVERAGE) .setValue(2.0) - .setAlertStatus(Level.ERROR) - .setAlertText("Foo") - .setCharacteristic(mock(Characteristic.class)) .setPersonId(2); // No value on new_xxx Measure measure2 = new Measure<>(CoreMetrics.NEW_BLOCKER_VIOLATIONS) @@ -109,8 +105,7 @@ public class MeasuresPublisherTest { // String value Measure stringMeasure = new Measure<>(CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION) .setData("foo bar"); - - when(measureCache.byResource(sampleFile)).thenReturn(Arrays.asList(measure1, measure2, manual, rating, longMeasure, stringMeasure)); + when(measureCache.byResource(sampleFile)).thenReturn(asList(measure1, measure2, manual, rating, longMeasure, stringMeasure)); File outputDir = temp.newFolder(); BatchReportWriter writer = new BatchReportWriter(outputDir); @@ -121,10 +116,8 @@ public class MeasuresPublisherTest { assertThat(reader.readComponentMeasures(1)).hasSize(0); List componentMeasures = reader.readComponentMeasures(2); - assertThat(componentMeasures).hasSize(8); + assertThat(componentMeasures).hasSize(6); assertThat(componentMeasures.get(0).getDoubleValue()).isEqualTo(2.0); - assertThat(componentMeasures.get(0).getAlertStatus()).isEqualTo("ERROR"); - assertThat(componentMeasures.get(0).getAlertText()).isEqualTo("Foo"); assertThat(componentMeasures.get(0).getPersonId()).isEqualTo(2); } diff --git a/sonar-batch/src/test/java/org/sonar/batch/report/MetadataPublisherTest.java b/sonar-batch/src/test/java/org/sonar/batch/report/MetadataPublisherTest.java new file mode 100644 index 00000000000..23f9860660a --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/report/MetadataPublisherTest.java @@ -0,0 +1,99 @@ +/* + * 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.batch.report; + +import java.io.File; +import java.util.Collections; +import java.util.Date; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.sonar.api.CoreProperties; +import org.sonar.api.batch.bootstrap.ProjectDefinition; +import org.sonar.api.batch.rule.ActiveRules; +import org.sonar.api.batch.rule.internal.DefaultActiveRules; +import org.sonar.api.batch.rule.internal.NewActiveRule; +import org.sonar.api.database.model.Snapshot; +import org.sonar.api.resources.Project; +import org.sonar.batch.index.BatchComponentCache; +import org.sonar.batch.protocol.output.BatchReport; +import org.sonar.batch.protocol.output.BatchReportReader; +import org.sonar.batch.protocol.output.BatchReportWriter; +import org.sonar.batch.scan.ImmutableProjectReactor; + +import static org.assertj.core.api.Assertions.assertThat; + +public class MetadataPublisherTest { + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + ActiveRules activeRules = new DefaultActiveRules(Collections.emptyList()); + ProjectDefinition projectDef; + Project project; + + MetadataPublisher underTest; + + @Before + public void prepare() { + projectDef = ProjectDefinition.create().setKey("foo"); + project = new Project("foo").setAnalysisDate(new Date(1234567L)); + BatchComponentCache componentCache = new BatchComponentCache(); + org.sonar.api.resources.Resource sampleFile = org.sonar.api.resources.File.create("src/Foo.php").setEffectiveKey("foo:src/Foo.php"); + componentCache.add(project, null).setSnapshot(new Snapshot().setId(2)); + componentCache.add(sampleFile, project); + underTest = new MetadataPublisher(componentCache, new ImmutableProjectReactor(projectDef), activeRules); + } + + @Test + public void write_metadata() throws Exception { + + File outputDir = temp.newFolder(); + BatchReportWriter writer = new BatchReportWriter(outputDir); + + underTest.publish(writer); + + BatchReportReader reader = new BatchReportReader(outputDir); + BatchReport.Metadata metadata = reader.readMetadata(); + assertThat(metadata.getAnalysisDate()).isEqualTo(1234567L); + assertThat(metadata.getProjectKey()).isEqualTo("foo"); + + } + + @Test + public void write_project_branch() throws Exception { + projectDef.properties().put(CoreProperties.PROJECT_BRANCH_PROPERTY, "myBranch"); + project.setKey("foo:myBranch"); + project.setEffectiveKey("foo:myBranch"); + + File outputDir = temp.newFolder(); + BatchReportWriter writer = new BatchReportWriter(outputDir); + + underTest.publish(writer); + + BatchReportReader reader = new BatchReportReader(outputDir); + BatchReport.Metadata metadata = reader.readMetadata(); + assertThat(metadata.getAnalysisDate()).isEqualTo(1234567L); + assertThat(metadata.getProjectKey()).isEqualTo("foo"); + assertThat(metadata.getBranch()).isEqualTo("myBranch"); + } + +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/rule/RulesProviderTest.java b/sonar-batch/src/test/java/org/sonar/batch/rule/RulesProviderTest.java deleted file mode 100644 index 79ba7df94bc..00000000000 --- a/sonar-batch/src/test/java/org/sonar/batch/rule/RulesProviderTest.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * 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.batch.rule; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; -import org.sonar.api.batch.debt.DebtRemediationFunction; -import org.sonar.api.batch.debt.internal.DefaultDebtCharacteristic; -import org.sonar.api.batch.debt.internal.DefaultDebtModel; -import org.sonar.api.batch.rule.Rule; -import org.sonar.api.batch.rule.RuleParam; -import org.sonar.api.batch.rule.Rules; -import org.sonar.api.config.Settings; -import org.sonar.api.rule.RuleKey; -import org.sonar.api.rule.Severity; -import org.sonar.api.utils.Duration; -import org.sonar.api.utils.Durations; -import org.sonar.core.persistence.AbstractDaoTestCase; -import org.sonar.core.rule.RuleDao; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.fail; - -@RunWith(MockitoJUnitRunner.class) -public class RulesProviderTest extends AbstractDaoTestCase { - - @Mock - Durations durations; - - RuleDao ruleDao; - - DefaultDebtModel debtModel; - - RulesProvider provider; - - @Before - public void setUp() { - debtModel = new DefaultDebtModel() - .addCharacteristic(new DefaultDebtCharacteristic() - .setId(100) - .setKey("MEMORY_EFFICIENCY") - .setName("Memory use") - .setOrder(1)) - .addCharacteristic(new DefaultDebtCharacteristic() - .setId(101) - .setKey("EFFICIENCY") - .setName("Efficiency") - .setParentId(100)); - debtModel - .addCharacteristic(new DefaultDebtCharacteristic() - .setId(102) - .setKey("COMPILER_RELATED_PORTABILITY") - .setName("Compiler") - .setOrder(1)) - .addCharacteristic(new DefaultDebtCharacteristic() - .setId(103) - .setKey("PORTABILITY") - .setName("Portability") - .setParentId(102)); - - durations = new Durations(new Settings().setProperty("sonar.technicalDebt.hoursInDay", 8), null); - ruleDao = new RuleDao(getMyBatis()); - - provider = new RulesProvider(); - } - - @Test - public void build_rules() { - setupData("shared"); - - Rules rules = provider.provide(ruleDao, debtModel, durations); - - assertThat(rules.findAll()).hasSize(1); - assertThat(rules.findByRepository("checkstyle")).hasSize(1); - assertThat(rules.findByRepository("unknown")).isEmpty(); - - Rule rule = rules.find(RuleKey.of("checkstyle", "AvoidNull")); - assertThat(rule).isNotNull(); - assertThat(rule.key()).isEqualTo(RuleKey.of("checkstyle", "AvoidNull")); - assertThat(rule.name()).isEqualTo("Avoid Null"); - assertThat(rule.description()).isEqualTo("Should avoid NULL"); - assertThat(rule.severity()).isEqualTo(Severity.MINOR); - assertThat(rule.internalKey()).isNull(); - assertThat(rule.params()).hasSize(1); - - RuleParam param = rule.param("myParameter"); - assertThat(param).isNotNull(); - assertThat(param.description()).isEqualTo("My Parameter"); - } - - @Test - public void build_rules_with_default_debt_definitions() { - setupData("build_rules_with_default_debt_definitions"); - - Rules rules = provider.provide(ruleDao, debtModel, durations); - - Rule rule = rules.find(RuleKey.of("checkstyle", "AvoidNull")); - assertThat(rule.debtSubCharacteristic()).isEqualTo("EFFICIENCY"); - assertThat(rule.debtRemediationFunction()).isEqualTo(DebtRemediationFunction.createLinearWithOffset(Duration.decode("5d", 8), Duration.decode("10h", 8))); - } - - @Test - public void build_rules_with_overridden_debt_definitions() { - setupData("build_rules_with_overridden_debt_definitions"); - - Rules rules = provider.provide(ruleDao, debtModel, durations); - - Rule rule = rules.find(RuleKey.of("checkstyle", "AvoidNull")); - assertThat(rule.debtSubCharacteristic()).isEqualTo("PORTABILITY"); - assertThat(rule.debtRemediationFunction()).isEqualTo(DebtRemediationFunction.createLinear(Duration.decode("2h", 8))); - } - - @Test - public void build_rules_with_default_and_overridden_debt_definitions() { - setupData("build_rules_with_default_and_overridden_debt_definitions"); - - Rules rules = provider.provide(ruleDao, debtModel, durations); - - // As both default columns and user columns on debt are set, user debt columns should be used - Rule rule = rules.find(RuleKey.of("checkstyle", "AvoidNull")); - assertThat(rule.debtSubCharacteristic()).isEqualTo("PORTABILITY"); - assertThat(rule.debtRemediationFunction()).isEqualTo(DebtRemediationFunction.createLinear(Duration.decode("2h", 8))); - } - - @Test - public void build_rules_with_default_characteristic_and_overridden_function() { - setupData("build_rules_with_default_characteristic_and_overridden_function"); - - Rules rules = provider.provide(ruleDao, debtModel, durations); - - // As both default columns and user columns on debt are set, user debt columns should be used - Rule rule = rules.find(RuleKey.of("checkstyle", "AvoidNull")); - assertThat(rule.debtSubCharacteristic()).isEqualTo("PORTABILITY"); - assertThat(rule.debtRemediationFunction()).isEqualTo(DebtRemediationFunction.createLinear(Duration.decode("2h", 8))); - } - - @Test - public void build_rules_with_overridden_characteristic_and_default_function() { - setupData("build_rules_with_overridden_characteristic_and_default_function"); - - Rules rules = provider.provide(ruleDao, debtModel, durations); - - // As both default columns and user columns on debt are set, user debt columns should be used - Rule rule = rules.find(RuleKey.of("checkstyle", "AvoidNull")); - assertThat(rule.debtSubCharacteristic()).isEqualTo("PORTABILITY"); - assertThat(rule.debtRemediationFunction()).isEqualTo(DebtRemediationFunction.createLinear(Duration.decode("2h", 8))); - } - - @Test - public void build_rules_with_disable_characteristic() { - setupData("build_rules_with_disable_characteristic"); - - Rules rules = provider.provide(ruleDao, debtModel, durations); - - Rule rule = rules.find(RuleKey.of("checkstyle", "AvoidNull")); - assertThat(rule.debtSubCharacteristic()).isNull(); - assertThat(rule.debtRemediationFunction()).isNull(); - } - - @Test - public void build_rules_with_default_characteristic_and_disable_characteristic() { - setupData("build_rules_with_default_characteristic_and_disable_characteristic"); - - Rules rules = provider.provide(ruleDao, debtModel, durations); - - Rule rule = rules.find(RuleKey.of("checkstyle", "AvoidNull")); - assertThat(rule.debtSubCharacteristic()).isNull(); - assertThat(rule.debtRemediationFunction()).isNull(); - } - - @Test - public void fail_if_characteristic_not_found() { - setupData("fail_if_characteristic_not_found"); - - try { - provider.provide(ruleDao, debtModel, durations); - fail(); - } catch (Exception e) { - assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Sub characteristic id '999' on rule 'checkstyle:AvoidNull' has not been found"); - } - } - - @Test - public void fail_if_no_function() { - setupData("fail_if_no_function"); - - try { - provider.provide(ruleDao, debtModel, durations); - fail(); - } catch (Exception e) { - assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("Remediation function should not be null on rule 'checkstyle:AvoidNull'"); - } - } -} diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/measure/MeasureCacheTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/measure/MeasureCacheTest.java index 58dcf64ffdf..505ee23191e 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/measure/MeasureCacheTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/measure/MeasureCacheTest.java @@ -34,8 +34,6 @@ import org.sonar.api.resources.Directory; import org.sonar.api.resources.File; import org.sonar.api.resources.Project; import org.sonar.api.resources.Resource; -import org.sonar.api.technicaldebt.batch.Characteristic; -import org.sonar.api.technicaldebt.batch.Requirement; import org.sonar.batch.index.AbstractCachesTest; import org.sonar.batch.index.Cache.Entry; @@ -64,7 +62,6 @@ public class MeasureCacheTest extends AbstractCachesTest { Project p = new Project("struts"); assertThat(measureCache.entries()).hasSize(0); - assertThat(measureCache.byResource(p)).hasSize(0); Measure m = new Measure(CoreMetrics.NCLOC, 1.0); @@ -227,29 +224,14 @@ public class MeasureCacheTest extends AbstractCachesTest { public void test_measure_coder() throws Exception { Resource file1 = File.create("foo/bar/File1.txt").setEffectiveKey("struts:foo/bar/File1.txt"); - Measure measure = new Measure(CoreMetrics.NCLOC, 1.786, 5); - measureCache.put(file1, measure); - - Measure savedMeasure = measureCache.byResource(file1).iterator().next(); - - assertThat(EqualsBuilder.reflectionEquals(measure, savedMeasure)).isTrue(); - - measure = new Measure(CoreMetrics.NCLOC); + Measure measure = new Measure(CoreMetrics.NCLOC, 3.14); measure.setData("data"); measure.setAlertStatus(Level.ERROR); measure.setAlertText("alert"); - Characteristic c = mock(Characteristic.class); - when(c.id()).thenReturn(1); - when(techDebtModel.characteristicById(1)).thenReturn(c); - measure.setCharacteristic(c); measure.setDate(new Date()); measure.setDescription("description"); measure.setPersistenceMode(null); measure.setPersonId(3); - Requirement r = mock(Requirement.class); - when(r.id()).thenReturn(7); - when(techDebtModel.requirementsById(7)).thenReturn(r); - measure.setRequirement(r); measure.setUrl("http://foo"); measure.setVariation1(11.0); measure.setVariation2(12.0); @@ -258,7 +240,7 @@ public class MeasureCacheTest extends AbstractCachesTest { measure.setVariation5(15.0); measureCache.put(file1, measure); - savedMeasure = measureCache.byResource(file1).iterator().next(); + Measure savedMeasure = measureCache.byResource(file1).iterator().next(); assertThat(EqualsBuilder.reflectionEquals(measure, savedMeasure)).isTrue(); } -- cgit v1.2.3