summaryrefslogtreecommitdiffstats
path: root/plugins/sonar-core-plugin
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@gmail.com>2014-04-17 23:33:27 +0200
committerSimon Brandhof <simon.brandhof@gmail.com>2014-04-17 23:33:49 +0200
commitf2dd46cf5745f7c14f2bce20f5131e4e242f8c7c (patch)
tree11ea192820faf6916a522d59886f923ac5bd6c1f /plugins/sonar-core-plugin
parentfa306cf2509a427937642db79e391e48ce85221e (diff)
downloadsonarqube-f2dd46cf5745f7c14f2bce20f5131e4e242f8c7c.tar.gz
sonarqube-f2dd46cf5745f7c14f2bce20f5131e4e242f8c7c.zip
SONAR-4969 Do not mix batch and server classpaths
Diffstat (limited to 'plugins/sonar-core-plugin')
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java142
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/ExclusionProperties.java102
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/CoverageMeasurementFilter.java30
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/DebtDecorator.java223
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/NewDebtDecorator.java109
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/package-info.java23
-rw-r--r--plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/ExclusionPropertiesTest.java36
-rw-r--r--plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/CoverageMeasurementFilterTest.java7
-rw-r--r--plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/DebtDecoratorTest.java351
-rw-r--r--plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/NewDebtDecoratorTest.java374
10 files changed, 73 insertions, 1324 deletions
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java
index a87d01690a6..b8770197f47 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java
@@ -20,36 +20,84 @@
package org.sonar.plugins.core;
import com.google.common.collect.ImmutableList;
-import org.sonar.api.*;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.Properties;
+import org.sonar.api.Property;
+import org.sonar.api.PropertyType;
+import org.sonar.api.SonarPlugin;
import org.sonar.api.checks.NoSonarFilter;
-import org.sonar.api.config.PropertyDefinition;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.batch.components.PastSnapshotFinder;
-import org.sonar.batch.debt.IssueChangelogDebtCalculator;
-import org.sonar.batch.issue.ignore.IssueExclusionsConfiguration;
import org.sonar.core.timemachine.Periods;
import org.sonar.plugins.core.batch.IndexProjectPostJob;
import org.sonar.plugins.core.charts.DistributionAreaChart;
import org.sonar.plugins.core.charts.DistributionBarChart;
import org.sonar.plugins.core.charts.XradarChart;
import org.sonar.plugins.core.colorizers.JavaColorizerFormat;
-import org.sonar.plugins.core.dashboards.*;
-import org.sonar.plugins.core.issue.*;
-import org.sonar.plugins.core.issue.notification.*;
+import org.sonar.plugins.core.dashboards.GlobalDefaultDashboard;
+import org.sonar.plugins.core.dashboards.ProjectDefaultDashboard;
+import org.sonar.plugins.core.dashboards.ProjectHotspotDashboard;
+import org.sonar.plugins.core.dashboards.ProjectIssuesDashboard;
+import org.sonar.plugins.core.dashboards.ProjectTimeMachineDashboard;
+import org.sonar.plugins.core.issue.CountFalsePositivesDecorator;
+import org.sonar.plugins.core.issue.CountUnresolvedIssuesDecorator;
+import org.sonar.plugins.core.issue.InitialOpenIssuesSensor;
+import org.sonar.plugins.core.issue.InitialOpenIssuesStack;
+import org.sonar.plugins.core.issue.IssueHandlers;
+import org.sonar.plugins.core.issue.IssueTracking;
+import org.sonar.plugins.core.issue.IssueTrackingDecorator;
+import org.sonar.plugins.core.issue.IssuesDensityDecorator;
+import org.sonar.plugins.core.issue.WeightedIssuesDecorator;
+import org.sonar.plugins.core.issue.notification.ChangesOnMyIssueNotificationDispatcher;
+import org.sonar.plugins.core.issue.notification.IssueChangesEmailTemplate;
+import org.sonar.plugins.core.issue.notification.NewFalsePositiveNotificationDispatcher;
+import org.sonar.plugins.core.issue.notification.NewIssuesEmailTemplate;
+import org.sonar.plugins.core.issue.notification.NewIssuesNotificationDispatcher;
+import org.sonar.plugins.core.issue.notification.SendIssueNotificationsPostJob;
import org.sonar.plugins.core.measurefilters.MyFavouritesFilter;
import org.sonar.plugins.core.measurefilters.ProjectFilter;
import org.sonar.plugins.core.notifications.alerts.NewAlerts;
import org.sonar.plugins.core.security.ApplyProjectRolesDecorator;
-import org.sonar.plugins.core.sensors.*;
-import org.sonar.plugins.core.technicaldebt.DebtDecorator;
-import org.sonar.plugins.core.technicaldebt.NewDebtDecorator;
-import org.sonar.plugins.core.timemachine.*;
+import org.sonar.plugins.core.sensors.BranchCoverageDecorator;
+import org.sonar.plugins.core.sensors.CommentDensityDecorator;
+import org.sonar.plugins.core.sensors.CoverageDecorator;
+import org.sonar.plugins.core.sensors.CoverageMeasurementFilter;
+import org.sonar.plugins.core.sensors.DirectoriesDecorator;
+import org.sonar.plugins.core.sensors.FileHashSensor;
+import org.sonar.plugins.core.sensors.FilesDecorator;
+import org.sonar.plugins.core.sensors.ItBranchCoverageDecorator;
+import org.sonar.plugins.core.sensors.ItCoverageDecorator;
+import org.sonar.plugins.core.sensors.ItLineCoverageDecorator;
+import org.sonar.plugins.core.sensors.LineCoverageDecorator;
+import org.sonar.plugins.core.sensors.ManualMeasureDecorator;
+import org.sonar.plugins.core.sensors.OverallBranchCoverageDecorator;
+import org.sonar.plugins.core.sensors.OverallCoverageDecorator;
+import org.sonar.plugins.core.sensors.OverallLineCoverageDecorator;
+import org.sonar.plugins.core.sensors.ProfileEventsSensor;
+import org.sonar.plugins.core.sensors.ProjectLinksSensor;
+import org.sonar.plugins.core.sensors.UnitTestDecorator;
+import org.sonar.plugins.core.sensors.VersionEventsSensor;
+import org.sonar.plugins.core.timemachine.NewCoverageAggregator;
+import org.sonar.plugins.core.timemachine.NewCoverageFileAnalyzer;
+import org.sonar.plugins.core.timemachine.NewItCoverageFileAnalyzer;
+import org.sonar.plugins.core.timemachine.NewOverallCoverageFileAnalyzer;
+import org.sonar.plugins.core.timemachine.TendencyDecorator;
+import org.sonar.plugins.core.timemachine.TimeMachineConfigurationPersister;
+import org.sonar.plugins.core.timemachine.VariationDecorator;
import org.sonar.plugins.core.web.TestsViewer;
import org.sonar.plugins.core.widgets.*;
-import org.sonar.plugins.core.widgets.issues.*;
-import org.sonar.plugins.core.widgets.measures.*;
+import org.sonar.plugins.core.widgets.issues.ActionPlansWidget;
+import org.sonar.plugins.core.widgets.issues.FalsePositiveIssuesWidget;
+import org.sonar.plugins.core.widgets.issues.IssueFilterWidget;
+import org.sonar.plugins.core.widgets.issues.IssuesWidget;
+import org.sonar.plugins.core.widgets.issues.MyUnresolvedIssuesWidget;
+import org.sonar.plugins.core.widgets.issues.UnresolvedIssuesPerAssigneeWidget;
+import org.sonar.plugins.core.widgets.issues.UnresolvedIssuesStatusesWidget;
+import org.sonar.plugins.core.widgets.measures.MeasureFilterAsBubbleChartWidget;
+import org.sonar.plugins.core.widgets.measures.MeasureFilterAsCloudWidget;
+import org.sonar.plugins.core.widgets.measures.MeasureFilterAsHistogramWidget;
+import org.sonar.plugins.core.widgets.measures.MeasureFilterAsPieChartWidget;
+import org.sonar.plugins.core.widgets.measures.MeasureFilterListWidget;
+import org.sonar.plugins.core.widgets.measures.MeasureFilterTreemapWidget;
-import java.util.Arrays;
import java.util.List;
@Properties({
@@ -292,11 +340,6 @@ public final class CorePlugin extends SonarPlugin {
NewFalsePositiveNotificationDispatcher.class,
NewFalsePositiveNotificationDispatcher.newMetadata(),
- // technical debt
- DebtDecorator.class,
- NewDebtDecorator.class,
- IssueChangelogDebtCalculator.class,
-
// batch
ProfileEventsSensor.class,
ProjectLinksSensor.class,
@@ -334,64 +377,7 @@ public final class CorePlugin extends SonarPlugin {
NewAlerts.class,
NewAlerts.newMetadata());
- extensions.addAll(ExclusionProperties.definitions());
- extensions.addAll(IssueExclusionsConfiguration.getPropertyDefinitions());
- extensions.addAll(CoverageMeasurementFilter.getPropertyDefinitions());
- extensions.addAll(PastSnapshotFinder.getPropertyDefinitions());
- extensions.addAll(DebtDecorator.definitions());
- extensions.addAll(propertyDefinitions());
-
return extensions.build();
}
- static List<PropertyDefinition> propertyDefinitions() {
- return Arrays.asList(
- PropertyDefinition.builder(CoreProperties.CORE_VIOLATION_LOCALE_PROPERTY)
- .defaultValue("en")
- .name("Locale used for issue messages")
- .description("Deprecated property. Keep default value for backward compatibility.")
- .hidden()
- .build(),
- PropertyDefinition.builder(CoreProperties.CORE_ALLOW_USERS_TO_SIGNUP_PROPERTY)
- .defaultValue("" + CoreProperties.CORE_ALLOW_USERS_TO_SIGNUP_DEAULT_VALUE)
- .name("Allow users to sign up online")
- .description("Users can sign up online.")
- .type(PropertyType.BOOLEAN)
- .category(CoreProperties.CATEGORY_SECURITY)
- .build(),
-
- PropertyDefinition.builder(CoreProperties.CORE_DEFAULT_GROUP)
- .defaultValue(CoreProperties.CORE_DEFAULT_GROUP_DEFAULT_VALUE)
- .name("Default user group")
- .description("Any new users will automatically join this group.")
- .category(CoreProperties.CATEGORY_SECURITY)
- .build(),
-
- PropertyDefinition.builder(CoreProperties.CORE_IMPORT_SOURCES_PROPERTY)
- .defaultValue("" + CoreProperties.CORE_IMPORT_SOURCES_DEFAULT_VALUE)
- .name("Import sources")
- .description("Set to false if sources should not be imported and therefore not available in the Web UI (e.g. for security reasons).")
- .type(PropertyType.BOOLEAN)
- .onQualifiers(Qualifiers.PROJECT, Qualifiers.MODULE)
- .category(CoreProperties.CATEGORY_SECURITY)
- .build(),
-
- PropertyDefinition.builder(CoreProperties.CORE_FORCE_AUTHENTICATION_PROPERTY)
- .defaultValue("" + CoreProperties.CORE_FORCE_AUTHENTICATION_DEFAULT_VALUE)
- .name("Force user authentication")
- .description("Forcing user authentication stops un-logged users to access SonarQube.")
- .type(PropertyType.BOOLEAN)
- .category(CoreProperties.CATEGORY_SECURITY)
- .build(),
-
- PropertyDefinition.builder(CoreProperties.CORE_PREVENT_AUTOMATIC_PROJECT_CREATION)
- .defaultValue(Boolean.toString(false))
- .name("Prevent automatic project creation")
- .description("Set to true to prevent automatic project creation at first analysis and force project provisioning.")
- .type(PropertyType.BOOLEAN)
- .category(CoreProperties.CATEGORY_SECURITY)
- .build()
- );
- }
-
}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/ExclusionProperties.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/ExclusionProperties.java
deleted file mode 100644
index b169a572965..00000000000
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/ExclusionProperties.java
+++ /dev/null
@@ -1,102 +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.plugins.core;
-
-import com.google.common.collect.ImmutableList;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.config.PropertyDefinition;
-import org.sonar.api.resources.Qualifiers;
-
-import java.util.List;
-
-class ExclusionProperties {
-
- private ExclusionProperties() {
- // only static stuff
- }
-
- static List<PropertyDefinition> definitions() {
- return ImmutableList.of(
- PropertyDefinition.builder(CoreProperties.PROJECT_INCLUSIONS_PROPERTY)
- .name("Source File Inclusions")
- .multiValues(true)
- .category(CoreProperties.CATEGORY_EXCLUSIONS)
- .subCategory(CoreProperties.SUBCATEGORY_FILES_EXCLUSIONS)
- .onQualifiers(Qualifiers.PROJECT)
- .index(3)
- .build(),
- PropertyDefinition.builder(CoreProperties.PROJECT_TEST_INCLUSIONS_PROPERTY)
- .name("Test File Inclusions")
- .multiValues(true)
- .category(CoreProperties.CATEGORY_EXCLUSIONS)
- .subCategory(CoreProperties.SUBCATEGORY_FILES_EXCLUSIONS)
- .onQualifiers(Qualifiers.PROJECT)
- .index(5)
- .build(),
- PropertyDefinition.builder(CoreProperties.GLOBAL_EXCLUSIONS_PROPERTY)
- .name("Global Source File Exclusions")
- .multiValues(true)
- .category(CoreProperties.CATEGORY_EXCLUSIONS)
- .subCategory(CoreProperties.SUBCATEGORY_FILES_EXCLUSIONS)
- .index(0)
- .build(),
- PropertyDefinition.builder(CoreProperties.GLOBAL_TEST_EXCLUSIONS_PROPERTY)
- .name("Global Test File Exclusions")
- .multiValues(true)
- .category(CoreProperties.CATEGORY_EXCLUSIONS)
- .subCategory(CoreProperties.SUBCATEGORY_FILES_EXCLUSIONS)
- .index(1)
- .build(),
- PropertyDefinition.builder(CoreProperties.PROJECT_EXCLUSIONS_PROPERTY)
- .name("Source File Exclusions")
- .multiValues(true)
- .category(CoreProperties.CATEGORY_EXCLUSIONS)
- .subCategory(CoreProperties.SUBCATEGORY_FILES_EXCLUSIONS)
- .onQualifiers(Qualifiers.PROJECT)
- .index(2)
- .build(),
- PropertyDefinition.builder(CoreProperties.PROJECT_TEST_EXCLUSIONS_PROPERTY)
- .name("Test File Exclusions")
- .multiValues(true)
- .category(CoreProperties.CATEGORY_EXCLUSIONS)
- .subCategory(CoreProperties.SUBCATEGORY_FILES_EXCLUSIONS)
- .onQualifiers(Qualifiers.PROJECT)
- .index(4)
- .build(),
- PropertyDefinition.builder(CoreProperties.CORE_SKIPPED_MODULES_PROPERTY)
- .name("Exclude Modules")
- .description("Maven artifact ids of modules to exclude.")
- .multiValues(true)
- .category(CoreProperties.CATEGORY_EXCLUSIONS)
- .subCategory(CoreProperties.SUBCATEGORY_FILES_EXCLUSIONS)
- .onlyOnQualifiers(Qualifiers.PROJECT)
- .index(0)
- .build(),
- PropertyDefinition.builder(CoreProperties.CORE_INCLUDED_MODULES_PROPERTY)
- .name("Include Modules")
- .description("Maven artifact ids of modules to include.")
- .multiValues(true)
- .category(CoreProperties.CATEGORY_EXCLUSIONS)
- .subCategory(CoreProperties.SUBCATEGORY_FILES_EXCLUSIONS)
- .onlyOnQualifiers(Qualifiers.PROJECT)
- .index(1)
- .build());
- }
-}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/CoverageMeasurementFilter.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/CoverageMeasurementFilter.java
index e2bcea80dce..eeda60396a9 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/CoverageMeasurementFilter.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/CoverageMeasurementFilter.java
@@ -23,34 +23,26 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import com.google.common.collect.ImmutableSet;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.PropertyType;
-import org.sonar.api.config.PropertyDefinition;
import org.sonar.api.config.Settings;
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.Metric;
-import org.sonar.api.resources.Qualifiers;
import org.sonar.api.resources.Resource;
import org.sonar.api.utils.WildcardPattern;
import org.sonar.core.measure.MeasurementFilter;
import java.util.Collection;
import java.util.Iterator;
-import java.util.List;
public class CoverageMeasurementFilter implements MeasurementFilter {
- public static final String PROPERTY_COVERAGE_EXCLUSIONS = "sonar.coverage.exclusions";
- public static final String PROPERTY_COVERAGE_INCLUSIONS = "sonar.coverage.inclusions";
-
private final Settings settings;
private final ImmutableSet<Metric> coverageMetrics;
private Collection<WildcardPattern> resourcePatterns;
public CoverageMeasurementFilter(Settings settings,
- CoverageDecorator coverageDecorator,
- LineCoverageDecorator lineCoverageDecorator,
- BranchCoverageDecorator branchCoverageDecorator) {
+ CoverageDecorator coverageDecorator,
+ LineCoverageDecorator lineCoverageDecorator,
+ BranchCoverageDecorator branchCoverageDecorator) {
this.settings = settings;
this.coverageMetrics = ImmutableSet.<Metric>builder()
.addAll(coverageDecorator.generatedMetrics())
@@ -88,22 +80,10 @@ public class CoverageMeasurementFilter implements MeasurementFilter {
@VisibleForTesting
final void initPatterns() {
- Builder<WildcardPattern> builder = ImmutableList.<WildcardPattern>builder();
- for (String pattern : settings.getStringArray(PROPERTY_COVERAGE_EXCLUSIONS)) {
+ Builder<WildcardPattern> builder = ImmutableList.builder();
+ for (String pattern : settings.getStringArray("sonar.coverage.exclusions")) {
builder.add(WildcardPattern.create(pattern));
}
resourcePatterns = builder.build();
}
-
- public static List<PropertyDefinition> getPropertyDefinitions() {
- return ImmutableList.of(
- PropertyDefinition.builder(PROPERTY_COVERAGE_EXCLUSIONS)
- .category(CoreProperties.CATEGORY_EXCLUSIONS)
- .subCategory(CoreProperties.SUBCATEGORY_COVERAGE_EXCLUSIONS)
- .type(PropertyType.STRING)
- .multiValues(true)
- .onQualifiers(Qualifiers.PROJECT, Qualifiers.MODULE)
- .build()
- );
- }
}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/DebtDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/DebtDecorator.java
deleted file mode 100644
index 2caf164d9c2..00000000000
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/DebtDecorator.java
+++ /dev/null
@@ -1,223 +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.plugins.core.technicaldebt;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.ImmutableList;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.PropertyType;
-import org.sonar.api.batch.*;
-import org.sonar.api.batch.rule.Rule;
-import org.sonar.api.batch.rule.Rules;
-import org.sonar.api.component.ResourcePerspectives;
-import org.sonar.api.config.PropertyDefinition;
-import org.sonar.api.issue.Issuable;
-import org.sonar.api.issue.Issue;
-import org.sonar.api.issue.internal.DefaultIssue;
-import org.sonar.api.measures.*;
-import org.sonar.api.resources.Project;
-import org.sonar.api.resources.Resource;
-import org.sonar.api.resources.ResourceUtils;
-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 javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static com.google.common.collect.Lists.newArrayList;
-import static com.google.common.collect.Maps.newHashMap;
-
-/**
- * Decorator that computes the technical debt metric
- */
-@DependsUpon(DecoratorBarriers.ISSUES_TRACKED)
-public final class DebtDecorator implements Decorator {
-
- private final ResourcePerspectives perspectives;
- private final TechnicalDebtModel model;
- private final Rules rules;
-
- /**
- * ruleFinder is needed to load "old" rule in order to persist rule measure
- */
- private final RuleFinder ruleFinder;
-
- public DebtDecorator(ResourcePerspectives perspectives, TechnicalDebtModel model, Rules rules, RuleFinder ruleFinder) {
- this.perspectives = perspectives;
- this.model = model;
- this.rules = rules;
- this.ruleFinder = ruleFinder;
- }
-
- public boolean shouldExecuteOnProject(Project project) {
- return true;
- }
-
- @DependedUpon
- public List<Metric> generatesMetrics() {
- return Arrays.asList(CoreMetrics.TECHNICAL_DEBT);
- }
-
- public void decorate(Resource resource, DecoratorContext context) {
- Issuable issuable = perspectives.as(Issuable.class, resource);
- if (issuable != null && shouldSaveMeasure(context)) {
- List<Issue> issues = newArrayList(issuable.issues());
- saveMeasures(context, issues);
- }
- }
-
- private void saveMeasures(DecoratorContext context, List<Issue> issues) {
- Long total = 0L;
- SumMap<RuleKey> ruleDebts = new SumMap<RuleKey>();
- SumMap<Characteristic> characteristicDebts = new SumMap<Characteristic>();
-
- // Aggregate rules debt from current issues (and populate current characteristic debt)
- for (Issue issue : issues) {
- Long debt = ((DefaultIssue) issue).debtInMinutes();
- total += computeDebt(debt, issue.ruleKey(), ruleDebts, characteristicDebts);
- }
-
- // Aggregate rules debt from children (and populate children characteristics debt)
- for (Measure measure : context.getChildrenMeasures(MeasuresFilters.rules(CoreMetrics.TECHNICAL_DEBT))) {
- Long debt = measure.getValue().longValue();
- RuleMeasure ruleMeasure = (RuleMeasure) measure;
- total += computeDebt(debt, ruleMeasure.getRule().ruleKey(), ruleDebts, characteristicDebts);
- }
-
- context.saveMeasure(CoreMetrics.TECHNICAL_DEBT, total.doubleValue());
- saveOnRule(context, ruleDebts);
- for (Characteristic characteristic : model.characteristics()) {
- Long debt = characteristicDebts.get(characteristic);
- saveCharacteristicMeasure(context, characteristic, debt != null ? debt.doubleValue() : 0d, false);
- }
- }
-
- private Long computeDebt(@Nullable Long debt, RuleKey ruleKey, SumMap<RuleKey> ruleDebts, SumMap<Characteristic> characteristicDebts) {
- if (debt != null) {
- Rule rule = rules.find(ruleKey);
- if (rule != null) {
- String characteristicKey = rule.debtSubCharacteristic();
- if (characteristicKey != null) {
- Characteristic characteristic = model.characteristicByKey(characteristicKey);
- if (characteristic != null) {
- ruleDebts.add(ruleKey, debt);
- characteristicDebts.add(characteristic, debt);
- propagateTechnicalDebtInParents(characteristic.parent(), debt, characteristicDebts);
- return debt;
- }
- }
- }
- }
- return 0L;
- }
-
- private void propagateTechnicalDebtInParents(@Nullable Characteristic characteristic, long value, SumMap<Characteristic> characteristicDebts) {
- if (characteristic != null) {
- characteristicDebts.add(characteristic, value);
- propagateTechnicalDebtInParents(characteristic.parent(), value, characteristicDebts);
- }
- }
-
- private void saveOnRule(DecoratorContext context, SumMap<RuleKey> ruleDebts) {
- for (Map.Entry<RuleKey, Long> entry : ruleDebts.entrySet()) {
- org.sonar.api.rules.Rule oldRule = ruleFinder.findByKey(entry.getKey());
- if (oldRule != null) {
- saveRuleMeasure(context, oldRule, entry.getValue().doubleValue(), ResourceUtils.isEntity(context.getResource()));
- }
- }
- }
-
- @VisibleForTesting
- void saveCharacteristicMeasure(DecoratorContext context, Characteristic characteristic, Double value, boolean inMemory) {
- // we need the value on projects (root or module) even if value==0 in order to display correctly the SQALE history chart (see SQALE-122)
- // BUT we don't want to save zero-values for non top-characteristics (see SQALE-147)
- if (value > 0.0 || (ResourceUtils.isProject(context.getResource()) && characteristic.isRoot())) {
- Measure measure = new Measure(CoreMetrics.TECHNICAL_DEBT);
- measure.setCharacteristic(characteristic);
- saveMeasure(context, measure, value, inMemory);
- }
- }
-
- @VisibleForTesting
- void saveRuleMeasure(DecoratorContext context, org.sonar.api.rules.Rule rule, Double value, boolean inMemory) {
- // we need the value on projects (root or module) even if value==0 in order to display correctly the SQALE history chart (see SQALE-122)
- // BUT we don't want to save zero-values for non top-characteristics (see SQALE-147)
- if (value > 0.0) {
- RuleMeasure measure = new RuleMeasure(CoreMetrics.TECHNICAL_DEBT, rule, null, null);
- saveMeasure(context, measure, value, inMemory);
- }
- }
-
- private void saveMeasure(DecoratorContext context, Measure measure, Double value, boolean inMemory) {
- measure.setValue(value);
- if (inMemory) {
- measure.setPersistenceMode(PersistenceMode.MEMORY);
- }
- context.saveMeasure(measure);
- }
-
- private boolean shouldSaveMeasure(DecoratorContext context) {
- return context.getMeasure(CoreMetrics.TECHNICAL_DEBT) == null;
- }
-
- public static List<PropertyDefinition> definitions() {
- return ImmutableList.of(
- PropertyDefinition.builder(CoreProperties.HOURS_IN_DAY)
- .name("Number of working hours in a day")
- .type(PropertyType.INTEGER)
- .defaultValue("8")
- .category(CoreProperties.CATEGORY_TECHNICAL_DEBT)
- .deprecatedKey("sqale.hoursInDay")
- .build()
- );
- }
-
- private static class SumMap<E> {
- private Map<E, Long> sumByKeys;
-
- public SumMap() {
- sumByKeys = newHashMap();
- }
-
- public void add(@Nullable E key, Long value) {
- if (key != null) {
- Long currentValue = sumByKeys.get(key);
- sumByKeys.put(key, currentValue != null ? currentValue + value : value);
- }
- }
-
- @CheckForNull
- public Long get(E key) {
- return sumByKeys.get(key);
- }
-
- public Set<Map.Entry<E, Long>> entrySet() {
- return sumByKeys.entrySet();
- }
- }
-}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/NewDebtDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/NewDebtDecorator.java
deleted file mode 100644
index f5f7062a584..00000000000
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/NewDebtDecorator.java
+++ /dev/null
@@ -1,109 +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.plugins.core.technicaldebt;
-
-import com.google.common.collect.ImmutableList;
-import org.sonar.api.batch.*;
-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 org.sonar.batch.debt.IssueChangelogDebtCalculator;
-
-import javax.annotation.Nullable;
-
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
-
-import static com.google.common.collect.Lists.newArrayList;
-
-/**
- * Decorator that computes the technical debt metric
- */
-@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;
- }
-
- public boolean shouldExecuteOnProject(Project project) {
- return true;
- }
-
- @DependedUpon
- public List<Metric> generatesMetrics() {
- return ImmutableList.of(
- CoreMetrics.NEW_TECHNICAL_DEBT
- );
- }
-
- public void decorate(Resource resource, DecoratorContext context) {
- Issuable issuable = perspectives.as(Issuable.class, resource);
- if (issuable != null && shouldSaveNewMetrics(context)) {
- List<Issue> issues = newArrayList(issuable.issues());
- saveMeasures(context, issues);
- }
- }
-
- private void saveMeasures(DecoratorContext context, Collection<Issue> issues) {
- Measure measure = new Measure(CoreMetrics.NEW_TECHNICAL_DEBT);
- for (Period period : timeMachineConfiguration.periods()) {
- Date periodDate = period.getDate();
- double value = calculateNewTechnicalDebtValue(issues, periodDate);
- Collection<Measure> 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<Issue> 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 boolean shouldSaveNewMetrics(DecoratorContext context) {
- return context.getMeasure(CoreMetrics.NEW_TECHNICAL_DEBT) == null;
- }
-
-}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/package-info.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/package-info.java
deleted file mode 100644
index defa4e01d36..00000000000
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/technicaldebt/package-info.java
+++ /dev/null
@@ -1,23 +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.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.plugins.core.technicaldebt;
-
-import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/ExclusionPropertiesTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/ExclusionPropertiesTest.java
deleted file mode 100644
index 42aed67cb00..00000000000
--- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/ExclusionPropertiesTest.java
+++ /dev/null
@@ -1,36 +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.plugins.core;
-
-import org.junit.Test;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.config.PropertyDefinition;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-public class ExclusionPropertiesTest {
- @Test
- public void definitions() throws Exception {
- assertThat(ExclusionProperties.definitions().size()).isGreaterThan(0);
- for (PropertyDefinition definition : ExclusionProperties.definitions()) {
- assertThat(definition.category()).isEqualTo(CoreProperties.CATEGORY_EXCLUSIONS);
- }
- }
-}
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/CoverageMeasurementFilterTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/CoverageMeasurementFilterTest.java
index 8254fb28094..072dea5844e 100644
--- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/CoverageMeasurementFilterTest.java
+++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/CoverageMeasurementFilterTest.java
@@ -27,6 +27,7 @@ import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Measure;
import org.sonar.api.resources.File;
import org.sonar.api.resources.Resource;
+import org.sonar.core.config.ExclusionProperties;
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Mockito.mock;
@@ -40,7 +41,7 @@ public class CoverageMeasurementFilterTest {
@Before
public void createFilter() {
- settings = new Settings(new PropertyDefinitions(CoverageMeasurementFilter.getPropertyDefinitions()));
+ settings = new Settings(new PropertyDefinitions(ExclusionProperties.all()));
filter = new CoverageMeasurementFilter(settings, new CoverageDecorator(), new LineCoverageDecorator(), new BranchCoverageDecorator());
}
@@ -57,7 +58,7 @@ public class CoverageMeasurementFilterTest {
Measure coverageMeasure = mock(Measure.class);
when(coverageMeasure.getMetric()).thenReturn(CoreMetrics.LINES_TO_COVER);
- settings.setProperty(CoverageMeasurementFilter.PROPERTY_COVERAGE_EXCLUSIONS, "src/org/polop/*");
+ settings.setProperty("sonar.coverage.exclusions", "src/org/polop/*");
filter.initPatterns();
assertThat(filter.accept(resource, coverageMeasure)).isFalse();
}
@@ -68,7 +69,7 @@ public class CoverageMeasurementFilterTest {
Measure coverageMeasure = mock(Measure.class);
when(coverageMeasure.getMetric()).thenReturn(CoreMetrics.COVERAGE);
- settings.setProperty(CoverageMeasurementFilter.PROPERTY_COVERAGE_EXCLUSIONS, "src/org/other/*");
+ settings.setProperty("sonar.coverage.exclusions", "src/org/other/*");
filter.initPatterns();
assertThat(filter.accept(resource, coverageMeasure)).isTrue();
}
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/DebtDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/DebtDecoratorTest.java
deleted file mode 100644
index 2aac5804446..00000000000
--- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/DebtDecoratorTest.java
+++ /dev/null
@@ -1,351 +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.plugins.core.technicaldebt;
-
-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.api.issue.internal.DefaultIssue;
-import org.sonar.api.measures.*;
-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.fest.assertions.Assertions.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.*;
-
-@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() throws Exception {
- 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() throws Exception {
- assertThat(decorator.generatesMetrics()).hasSize(1);
- }
-
- @Test
- public void execute_on_project() throws Exception {
- 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() throws Exception {
- 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() throws Exception {
- 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() throws Exception {
- 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() throws Exception {
- 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() throws Exception {
- 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.<Measure>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() throws Exception {
- when(issuable.issues()).thenReturn(Collections.<Issue>emptyList());
-
- when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Lists.<Measure>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() throws Exception {
- // 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(new File("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() throws Exception {
- 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() throws Exception {
- 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() throws Exception {
- DecoratorContext context = mock(DecoratorContext.class);
- when(context.getResource()).thenReturn(new File("foo"));
-
- decorator.saveCharacteristicMeasure(context, (Characteristic) null, 0.0, true);
- verify(context, never()).saveMeasure(new Measure(CoreMetrics.TECHNICAL_DEBT));
- }
-
- @Test
- public void check_definitions() {
- assertThat(DebtDecorator.definitions()).hasSize(1);
- }
-
- private DefaultIssue createIssue(String ruleKey, String repositoryKey) {
- return new DefaultIssue().setRuleKey(RuleKey.of(repositoryKey, ruleKey));
- }
-
- class IsCharacteristicMeasure extends ArgumentMatcher<Measure> {
- 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<RuleMeasure> {
- 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.repository(), m.getRule().getRepositoryKey()) &&
- ObjectUtils.equals(ruleKey.rule(), m.getRule().getKey()) &&
- ObjectUtils.equals(value, m.getValue());
- }
-
- @Override
- public void describeTo(Description description) {
- description.appendText(ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE));
- }
- }
-}
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/NewDebtDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/NewDebtDecoratorTest.java
deleted file mode 100644
index a9391f96da2..00000000000
--- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/technicaldebt/NewDebtDecoratorTest.java
+++ /dev/null
@@ -1,374 +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.plugins.core.technicaldebt;
-
-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.api.issue.internal.DefaultIssue;
-import org.sonar.api.issue.internal.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 org.sonar.batch.debt.IssueChangelogDebtCalculator;
-
-import java.util.Date;
-
-import static com.google.common.collect.Lists.newArrayList;
-import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Mockito.*;
-
-@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() throws Exception {
- assertThat(decorator.generatesMetrics()).hasSize(1);
- }
-
- @Test
- public void execute_on_project() throws Exception {
- 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<Measure> {
- 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());
- }
- }
-
-}