From 44a34aca80bb01c3a7689fe02d34f17718bf9293 Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Wed, 24 Jun 2015 16:41:13 +0200 Subject: [PATCH] SONAR-6588 integrate issues to Compute Engine --- .../computation/batch/BatchReportReader.java | 3 +- .../container/ComputeEngineContainerImpl.java | 23 +- .../computation/issue/BaseIssuesLoader.java | 42 +- ...ebtCalculator.java => DebtAggregator.java} | 25 +- .../computation/issue/IssueAssigner.java | 2 +- ...tIssuesListener.java => IssueCounter.java} | 6 +- .../computation/issue/IssueLifecycle.java | 1 + .../{IssueListener.java => IssueVisitor.java} | 14 +- ...IssueListeners.java => IssueVisitors.java} | 26 +- .../computation/issue/NewDebtAggregator.java | 120 ++ .../computation/issue/NewDebtCalculator.java | 106 +- .../computation/issue/RuleTagsCopier.java | 2 +- .../issue/TrackerBaseInputFactory.java | 6 +- .../issue/TrackerRawInputFactory.java | 21 +- .../measure/BatchMeasureToMeasure.java | 54 +- .../measure/MeasureRepositoryImpl.java | 5 +- .../computation/step/ComputationSteps.java | 1 + .../computation/step/FeedDebtModelStep.java | 2 - .../computation/step/IntegrateIssuesStep.java | 36 +- .../computation/step/PersistIssuesStep.java | 26 +- .../sonar/server/source/db/FileSourceDao.java | 5 +- .../computation/debt/CharacteristicTest.java | 2 +- .../debt/DebtModelHolderImplTest.java | 19 + .../issue/CountIssuesListenerTest.java | 7 +- .../issue/NewDebtAggregatorTest.java | 367 ++++++ .../issue/NewDebtCalculatorTest.java | 146 +++ .../measure/BatchMeasureToMeasureTest.java | 57 +- .../measure/MeasureRepositoryImplTest.java | 12 +- .../step/FeedDebtModelStepTest.java | 19 + .../FillMeasuresWithVariationsStepTest.java | 68 +- .../step/PersistIssuesStepTest.java | 5 +- .../step/PersistMeasuresStepTest.java | 12 +- .../close_issue-result.xml | 2 +- .../step/PersistIssuesStepTest/shared.xml | 4 +- .../batch/protocol/output/BatchReport.java | 1074 +++++++---------- .../src/main/protobuf/batch_report.proto | 11 +- .../batch/bootstrap/BatchComponents.java | 6 - .../sonar/batch/debt/DebtModelProvider.java | 83 -- .../debt/IssueChangelogDebtCalculator.java | 142 --- .../sonar/batch/debt/NewDebtDecorator.java | 114 -- .../org/sonar/batch/issue/ModuleIssues.java | 4 +- .../issue/tracking/LocalIssueTracking.java | 2 +- .../sonar/batch/report/IssuesPublisher.java | 26 +- .../sonar/batch/report/MeasuresPublisher.java | 16 - .../sonar/batch/report/MetadataPublisher.java | 74 ++ .../org/sonar/batch/rule/RulesProvider.java | 129 -- .../batch/scan/ProjectScanContainer.java | 37 +- .../batch/scan/measure/MeasureCache.java | 19 +- .../batch/scan/measure/MeasureValueCoder.java | 15 +- .../sonar/batch/debt/DebtDecoratorTest.java | 353 ------ .../batch/debt/DebtModelProviderTest.java | 81 -- .../IssueChangelogDebtCalculatorTest.java | 149 --- .../batch/debt/NewDebtDecoratorTest.java | 376 ------ .../sonar/batch/issue/ModuleIssuesTest.java | 4 - .../batch/report/IssuesPublisherTest.java | 50 +- .../batch/report/MeasuresPublisherTest.java | 13 +- .../batch/report/MetadataPublisherTest.java | 99 ++ .../sonar/batch/rule/RulesProviderTest.java | 215 ---- .../batch/scan/measure/MeasureCacheTest.java | 22 +- .../core/dashboard/ActiveDashboardDao.java | 8 +- .../sonar/core/issue/db/ActionPlanDao.java | 12 +- .../sonar/core/issue/db/IssueChangeDao.java | 22 +- .../core/issue/db/IssueChangeMapper.java | 17 +- .../org/sonar/core/issue/db/IssueDto.java | 1 + .../org/sonar/core/issue/db/IssueMapper.java | 2 +- .../sonar/core/issue/tracking/LazyInput.java | 4 +- .../sonar/core/issue/tracking/Tracker.java | 10 +- .../sonar/core/issue/tracking/Tracking.java | 35 +- .../sonar/core/issue/workflow/SetClosed.java | 2 +- .../sonar/core/persistence/DaoComponent.java | 3 - .../DefaultTechnicalDebtModel.java | 128 -- .../sonar/core/issue/db/IssueChangeMapper.xml | 26 +- .../org/sonar/core/issue/db/IssueMapper.xml | 31 +- .../core/issue/db/IssueChangeDaoTest.java | 52 +- .../core/issue/tracking/TrackerTest.java | 16 +- .../core/issue/workflow/SetClosedTest.java | 2 +- .../DefaultTechnicalDebtModelTest.java | 100 -- ...ChangelogOfUnresolvedIssuesByComponent.xml | 144 +++ .../select_issue_changelog_by_module.xml | 222 ---- ..._by_module_are_sorted_by_creation_date.xml | 67 - .../java/org/sonar/api/batch/rule/Rule.java | 13 +- .../api/batch/rule/internal/DefaultRule.java | 7 - .../api/batch/rule/internal/NewRule.java | 6 - .../java/org/sonar/api/measures/Measure.java | 26 +- .../batch/TechnicalDebtModel.java | 70 -- .../batch/rule/internal/RulesBuilderTest.java | 4 - 86 files changed, 1820 insertions(+), 3570 deletions(-) rename server/sonar-server/src/main/java/org/sonar/server/computation/issue/{DebtCalculator.java => DebtAggregator.java} (86%) rename server/sonar-server/src/main/java/org/sonar/server/computation/issue/{CountIssuesListener.java => IssueCounter.java} (98%) rename server/sonar-server/src/main/java/org/sonar/server/computation/issue/{IssueListener.java => IssueVisitor.java} (78%) rename server/sonar-server/src/main/java/org/sonar/server/computation/issue/{IssueListeners.java => IssueVisitors.java} (67%) create mode 100644 server/sonar-server/src/main/java/org/sonar/server/computation/issue/NewDebtAggregator.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/computation/issue/NewDebtAggregatorTest.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/computation/issue/NewDebtCalculatorTest.java 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 delete mode 100644 sonar-core/src/main/java/org/sonar/core/technicaldebt/DefaultTechnicalDebtModel.java delete mode 100644 sonar-core/src/test/java/org/sonar/core/technicaldebt/DefaultTechnicalDebtModelTest.java create mode 100644 sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/selectChangelogOfUnresolvedIssuesByComponent.xml delete mode 100644 sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/select_issue_changelog_by_module.xml delete mode 100644 sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/select_issue_changelog_by_module_are_sorted_by_creation_date.xml delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/batch/TechnicalDebtModel.java diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/batch/BatchReportReader.java b/server/sonar-server/src/main/java/org/sonar/server/computation/batch/BatchReportReader.java index fbed4ffb945..2568cb4ed9a 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/batch/BatchReportReader.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/batch/BatchReportReader.java @@ -45,7 +45,8 @@ public interface BatchReportReader { CloseableIterator readComponentCoverage(int fileRef); /** - * Reads file source line by line. + * Reads file source line by line. Throws an exception if the ref does not relate + * to a file */ CloseableIterator readFileSource(int fileRef); diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java index 4bd929e44e1..7bbd85c8748 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java @@ -45,13 +45,15 @@ import org.sonar.server.computation.debt.DebtModelHolderImpl; import org.sonar.server.computation.event.EventRepositoryImpl; import org.sonar.server.computation.formula.CoreFormulaRepositoryImpl; import org.sonar.server.computation.issue.BaseIssuesLoader; -import org.sonar.server.computation.issue.CountIssuesListener; -import org.sonar.server.computation.issue.DebtCalculator; +import org.sonar.server.computation.issue.IssueCounter; +import org.sonar.server.computation.issue.DebtAggregator; import org.sonar.server.computation.issue.DefaultAssignee; import org.sonar.server.computation.issue.IssueAssigner; import org.sonar.server.computation.issue.IssueCache; import org.sonar.server.computation.issue.IssueLifecycle; -import org.sonar.server.computation.issue.IssueListeners; +import org.sonar.server.computation.issue.IssueVisitors; +import org.sonar.server.computation.issue.NewDebtAggregator; +import org.sonar.server.computation.issue.NewDebtCalculator; import org.sonar.server.computation.issue.RuleCache; import org.sonar.server.computation.issue.RuleCacheLoader; import org.sonar.server.computation.issue.RuleTagsCopier; @@ -168,16 +170,21 @@ public class ComputeEngineContainerImpl extends ComponentContainer implements Co // issues ScmAccountToUserLoader.class, ScmAccountToUser.class, - IssueAssigner.class, - RuleTagsCopier.class, RuleCache.class, RuleCacheLoader.class, IssueCache.class, DefaultAssignee.class, - DebtCalculator.class, - IssueListeners.class, + IssueVisitors.class, IssueLifecycle.class, - CountIssuesListener.class, + + // order is important, NewDebtAggregator is based on DebtAggregator (new debt requires debt) + DebtAggregator.class, + NewDebtCalculator.class, + NewDebtAggregator.class, + IssueAssigner.class, + RuleTagsCopier.class, + IssueCounter.class, + UpdateConflictResolver.class, TrackerBaseInputFactory.class, TrackerRawInputFactory.class, diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/BaseIssuesLoader.java b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/BaseIssuesLoader.java index 904ac1f1242..216fe6db9b9 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/BaseIssuesLoader.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/BaseIssuesLoader.java @@ -19,31 +19,44 @@ */ package org.sonar.server.computation.issue; +import com.google.common.base.Function; import com.google.common.collect.ImmutableMap; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; +import javax.annotation.Nonnull; import org.apache.ibatis.session.ResultContext; import org.apache.ibatis.session.ResultHandler; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.rule.RuleStatus; +import org.sonar.api.utils.log.Loggers; import org.sonar.core.issue.DefaultIssue; import org.sonar.core.issue.db.IssueDto; import org.sonar.core.issue.db.IssueMapper; import org.sonar.core.persistence.DbSession; import org.sonar.core.persistence.MyBatis; +import org.sonar.core.rule.RuleDto; +import org.sonar.server.computation.batch.BatchReportReader; import org.sonar.server.computation.component.TreeRootHolder; import org.sonar.server.db.DbClient; +import static com.google.common.collect.FluentIterable.from; + /** * Loads all the project open issues from database, including manual issues. + * */ public class BaseIssuesLoader { + private final Set activeRuleKeys; private final TreeRootHolder treeRootHolder; private final DbClient dbClient; private final RuleCache ruleCache; - public BaseIssuesLoader(TreeRootHolder treeRootHolder, DbClient dbClient, RuleCache ruleCache) { + public BaseIssuesLoader(BatchReportReader reportReader, TreeRootHolder treeRootHolder, + DbClient dbClient, RuleCache ruleCache) { + this.activeRuleKeys = from(reportReader.readMetadata().getActiveRuleKeyList()).transform(ToRuleKey.INSTANCE).toSet(); this.treeRootHolder = treeRootHolder; this.dbClient = dbClient; this.ruleCache = ruleCache; @@ -54,11 +67,21 @@ public class BaseIssuesLoader { final List result = new ArrayList<>(); try { Map params = ImmutableMap.of("componentUuid", componentUuid); - session.select(IssueMapper.class.getName() + ".selectOpenByComponentUuid", params, new ResultHandler() { + session.select(IssueMapper.class.getName() + ".selectNonClosedByComponentUuid", params, new ResultHandler() { @Override public void handleResult(ResultContext resultContext) { DefaultIssue issue = ((IssueDto) resultContext.getResultObject()).toDefaultIssue(); - issue.setOnDisabledRule(ruleCache.getNullable(issue.ruleKey()) == null); + + // TODO this field should be set outside this class + RuleDto rule = ruleCache.getNullable(issue.ruleKey()); + if (rule == null || rule.getStatus() == RuleStatus.REMOVED || !isActive(issue.ruleKey())) { + issue.setOnDisabledRule(true); + // TODO to be improved, why setOnDisabledRule(true) is not enough ? + issue.setBeingClosed(true); + } + // FIXME + issue.setSelectedAt(System.currentTimeMillis()); + Loggers.get(getClass()).info("Loaded from db: " + issue); result.add(issue); } }); @@ -68,6 +91,10 @@ public class BaseIssuesLoader { } } + private boolean isActive(RuleKey ruleKey) { + return ruleKey.isManual() || activeRuleKeys.contains(ruleKey); + } + /** * Uuids of all the components that have open issues on this project. */ @@ -79,4 +106,13 @@ public class BaseIssuesLoader { MyBatis.closeQuietly(session); } } + + private enum ToRuleKey implements Function { + INSTANCE; + @Nonnull + @Override + public RuleKey apply(@Nonnull String input) { + return RuleKey.parse(input); + } + } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/DebtCalculator.java b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/DebtAggregator.java similarity index 86% rename from server/sonar-server/src/main/java/org/sonar/server/computation/issue/DebtCalculator.java rename to server/sonar-server/src/main/java/org/sonar/server/computation/issue/DebtAggregator.java index b5ee6bb13ef..8bce13283e3 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/DebtCalculator.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/DebtAggregator.java @@ -26,7 +26,6 @@ import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.sonar.api.measures.CoreMetrics; import org.sonar.core.issue.DefaultIssue; -import org.sonar.core.issue.IssueUpdater; import org.sonar.core.issue.tracking.Tracking; import org.sonar.core.rule.RuleDto; import org.sonar.server.computation.component.Component; @@ -39,9 +38,8 @@ import org.sonar.server.computation.metric.MetricRepository; import static com.google.common.collect.Maps.newHashMap; -public class DebtCalculator extends IssueListener { +public class DebtAggregator extends IssueVisitor { - private final IssueUpdater updater; private final RuleCache ruleCache; private final DebtModelHolder debtModelHolder; private final MetricRepository metricRepository; @@ -50,9 +48,8 @@ public class DebtCalculator extends IssueListener { private final Map debtsByComponentRef = new HashMap<>(); private Debt currentDebt; - public DebtCalculator(IssueUpdater updater, RuleCache ruleCache, DebtModelHolder debtModelHolder, + public DebtAggregator(RuleCache ruleCache, DebtModelHolder debtModelHolder, MetricRepository metricRepository, MeasureRepository measureRepository) { - this.updater = updater; this.ruleCache = ruleCache; this.debtModelHolder = debtModelHolder; this.metricRepository = metricRepository; @@ -67,14 +64,15 @@ public class DebtCalculator extends IssueListener { for (Component child : component.getChildren()) { // no need to keep the children in memory. They can be garbage-collected. Debt childDebt = debtsByComponentRef.remove(child.getRef()); - currentDebt.add(childDebt); + if (childDebt != null) { + currentDebt.add(childDebt); + } } } @Override public void onIssue(Component component, DefaultIssue issue) { if (issue.resolution() == null) { - // TODO calculate debt according to rule remediation function. Currently done by batch. currentDebt.add(issue); } } @@ -117,11 +115,14 @@ public class DebtCalculator extends IssueListener { RuleDto rule = ruleCache.get(issue.ruleKey()); this.minutesByRuleId.add(rule.getId(), issueMinutes); - Characteristic characteristic = debtModelHolder.getCharacteristicById(rule.getSubCharacteristicId()); - this.minutesByCharacteristicId.add(characteristic.getId(), issueMinutes); - Integer characteristicParentId = characteristic.getParentId(); - if (characteristicParentId != null) { - this.minutesByCharacteristicId.add(characteristicParentId, issueMinutes); + Integer subCharacteristicId = rule.getSubCharacteristicId(); + if (subCharacteristicId != null) { + Characteristic characteristic = debtModelHolder.getCharacteristicById(subCharacteristicId); + this.minutesByCharacteristicId.add(characteristic.getId(), issueMinutes); + Integer characteristicParentId = characteristic.getParentId(); + if (characteristicParentId != null) { + this.minutesByCharacteristicId.add(characteristicParentId, issueMinutes); + } } } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueAssigner.java b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueAssigner.java index 7d3087f0a07..7f49d983154 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueAssigner.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueAssigner.java @@ -43,7 +43,7 @@ import org.sonar.server.source.index.SourceLineIndex; *
  • the Elasticsearch index of source lines for non-modified files
  • * */ -public class IssueAssigner extends IssueListener { +public class IssueAssigner extends IssueVisitor { private final SourceLineIndex sourceLineIndex; private final BatchReportReader reportReader; diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/CountIssuesListener.java b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueCounter.java similarity index 98% rename from server/sonar-server/src/main/java/org/sonar/server/computation/issue/CountIssuesListener.java rename to server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueCounter.java index 1b49303f7a1..2e49500d8d2 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/CountIssuesListener.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueCounter.java @@ -73,7 +73,7 @@ import static org.sonar.api.rule.Severity.MINOR; * * For each value, the variation on configured periods is also computed. */ -public class CountIssuesListener extends IssueListener { +public class IssueCounter extends IssueVisitor { private final static Map SEVERITY_TO_METRIC_KEY = ImmutableMap.of( BLOCKER, BLOCKER_VIOLATIONS_KEY, @@ -98,8 +98,8 @@ public class CountIssuesListener extends IssueListener { private final Map countersByComponentRef = new HashMap<>(); private Counters currentCounters; - public CountIssuesListener(PeriodsHolder periodsHolder, - MetricRepository metricRepository, MeasureRepository measureRepository) { + public IssueCounter(PeriodsHolder periodsHolder, + MetricRepository metricRepository, MeasureRepository measureRepository) { this.periodsHolder = periodsHolder; this.metricRepository = metricRepository; this.measureRepository = measureRepository; diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueLifecycle.java b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueLifecycle.java index 713e65306ff..10bd8af2edf 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueLifecycle.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueLifecycle.java @@ -73,6 +73,7 @@ public class IssueLifecycle { updater.setPastMessage(raw, base.getMessage(), changeContext); updater.setPastEffortToFix(raw, base.effortToFix(), changeContext); updater.setPastTechnicalDebt(raw, base.debt(), changeContext); + raw.setSelectedAt(base.selectedAt()); } public void doAutomaticTransition(DefaultIssue issue) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueListener.java b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueVisitor.java similarity index 78% rename from server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueListener.java rename to server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueVisitor.java index ebd3d4eb098..7385ff05326 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueListener.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueVisitor.java @@ -23,7 +23,7 @@ import org.sonar.core.issue.DefaultIssue; import org.sonar.core.issue.tracking.Tracking; import org.sonar.server.computation.component.Component; -public abstract class IssueListener { +public abstract class IssueVisitor { /** * This method is called for each component before processing its issues. @@ -33,18 +33,6 @@ public abstract class IssueListener { } - /** - * This method is called when initializing an open issue. At that time - * any information related to tracking step are not available (line, assignee, - * resolution, status, creation date, uuid, ...). - *

    - * The need for this method is for example to calculate the issue debt - * before merging with base issue - */ - public void onOpenIssueInitialization(Component component, DefaultIssue issue) { - - } - /** * This method is called when tracking is done and issue is initialized. That means that the following fields * are set: resolution, status, line, creation date, uuid and all the fields merged from base issues. diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueListeners.java b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueVisitors.java similarity index 67% rename from server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueListeners.java rename to server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueVisitors.java index 7c92c0e4ad3..51ddee18a05 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueListeners.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/IssueVisitors.java @@ -23,35 +23,29 @@ import org.sonar.core.issue.DefaultIssue; import org.sonar.core.issue.tracking.Tracking; import org.sonar.server.computation.component.Component; -public class IssueListeners { +public class IssueVisitors { - private final IssueListener[] listeners; + private final IssueVisitor[] visitors; - public IssueListeners(IssueListener[] listeners) { - this.listeners = listeners; + public IssueVisitors(IssueVisitor[] visitors) { + this.visitors = visitors; } public void beforeComponent(Component component, Tracking tracking) { - for (IssueListener listener : listeners) { - listener.beforeComponent(component, tracking); - } - } - - public void onOpenIssueInitialization(Component component, DefaultIssue issue) { - for (IssueListener listener : listeners) { - listener.onOpenIssueInitialization(component, issue); + for (IssueVisitor visitor : visitors) { + visitor.beforeComponent(component, tracking); } } public void onIssue(Component component, DefaultIssue issue) { - for (IssueListener listener : listeners) { - listener.onIssue(component, issue); + for (IssueVisitor visitor : visitors) { + visitor.onIssue(component, issue); } } public void afterComponent(Component component) { - for (IssueListener listener : listeners) { - listener.afterComponent(component); + for (IssueVisitor visitor : visitors) { + visitor.afterComponent(component); } } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/NewDebtAggregator.java b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/NewDebtAggregator.java new file mode 100644 index 00000000000..dd212257ab9 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/NewDebtAggregator.java @@ -0,0 +1,120 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.computation.issue; + +import com.google.common.base.Objects; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.ListMultimap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.core.issue.DefaultIssue; +import org.sonar.core.issue.db.IssueChangeDto; +import org.sonar.core.issue.tracking.Tracking; +import org.sonar.server.computation.component.Component; +import org.sonar.server.computation.measure.Measure; +import org.sonar.server.computation.measure.MeasureRepository; +import org.sonar.server.computation.measure.MeasureVariations; +import org.sonar.server.computation.metric.Metric; +import org.sonar.server.computation.metric.MetricRepository; +import org.sonar.server.computation.period.Period; +import org.sonar.server.computation.period.PeriodsHolder; +import org.sonar.server.db.DbClient; + +public class NewDebtAggregator extends IssueVisitor { + + private final NewDebtCalculator calculator; + private final PeriodsHolder periodsHolder; + private final DbClient dbClient; + private final MetricRepository metricRepository; + private final MeasureRepository measureRepository; + + private ListMultimap changesByIssueUuid = ArrayListMultimap.create(); + private Map sumsByComponentRef = new HashMap<>(); + private DebtSum currentSum = null; + + public NewDebtAggregator(NewDebtCalculator calculator, PeriodsHolder periodsHolder, DbClient dbClient, + MetricRepository metricRepository, MeasureRepository measureRepository) { + this.calculator = calculator; + this.periodsHolder = periodsHolder; + this.dbClient = dbClient; + this.metricRepository = metricRepository; + this.measureRepository = measureRepository; + } + + @Override + public void beforeComponent(Component component, Tracking tracking) { + currentSum = new DebtSum(); + sumsByComponentRef.put(component.getRef(), currentSum); + List changes = dbClient.issueChangeDao().selectChangelogOfUnresolvedIssuesByComponent(component.getUuid()); + for (IssueChangeDto change : changes) { + changesByIssueUuid.put(change.getIssueKey(), change); + } + } + + @Override + public void onIssue(Component component, DefaultIssue issue) { + if (issue.debtInMinutes() != null && !periodsHolder.getPeriods().isEmpty()) { + List changelog = changesByIssueUuid.get(issue.key()); + for (Period period : periodsHolder.getPeriods()) { + long newDebt = calculator.calculate(issue, changelog, period); + currentSum.add(period.getIndex(), newDebt); + } + } + for (Component child : component.getChildren()) { + DebtSum childSum = sumsByComponentRef.remove(child.getRef()); + if (childSum != null) { + currentSum.add(childSum); + } + } + } + + @Override + public void afterComponent(Component component) { + if (!currentSum.isEmpty) { + MeasureVariations variations = new MeasureVariations(currentSum.sums); + Metric metric = metricRepository.getByKey(CoreMetrics.NEW_TECHNICAL_DEBT_KEY); + measureRepository.add(component, metric, Measure.newMeasureBuilder().setVariations(variations).createNoValue()); + } + changesByIssueUuid.clear(); + currentSum = null; + } + + private static class DebtSum { + private Double[] sums = new Double[PeriodsHolder.MAX_NUMBER_OF_PERIODS]; + private boolean isEmpty = true; + + void add(int periodIndex, long newDebt) { + double previous = Objects.firstNonNull(sums[periodIndex - 1], 0d); + sums[periodIndex - 1] = previous + newDebt; + isEmpty = false; + } + + void add(DebtSum other) { + for (int i = 0; i < sums.length; i++) { + Double otherValue = other.sums[i]; + if (otherValue != null) { + add(i + 1, otherValue.longValue()); + } + } + } + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/NewDebtCalculator.java b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/NewDebtCalculator.java index b21ffd09de3..6d7c85941c3 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/NewDebtCalculator.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/NewDebtCalculator.java @@ -19,14 +19,110 @@ */ package org.sonar.server.computation.issue; +import com.google.common.base.Function; +import com.google.common.base.Objects; +import com.google.common.base.Predicate; +import com.google.common.collect.Ordering; +import java.util.Calendar; +import java.util.Comparator; +import java.util.Date; +import java.util.Iterator; +import java.util.List; +import javax.annotation.CheckForNull; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.apache.commons.lang.time.DateUtils; import org.sonar.core.issue.DefaultIssue; -import org.sonar.server.computation.component.Component; +import org.sonar.core.issue.FieldDiffs; +import org.sonar.core.issue.IssueUpdater; +import org.sonar.core.issue.db.IssueChangeDto; +import org.sonar.server.computation.period.Period; -public class NewDebtCalculator extends IssueListener { +import static com.google.common.collect.FluentIterable.from; - @Override - public void onIssue(Component component, DefaultIssue issue) { - // TODO +/** + * Gets the issue debt that was introduced on a period. The algorithm + * is based on the issue changelog. + */ +public class NewDebtCalculator { + + public long calculate(DefaultIssue issue, List debtChangelog, Period period) { + if (issue.creationDate().getTime() > period.getSnapshotDate() + 1000L) { + return Objects.firstNonNull(issue.debtInMinutes(), 0L); + } + return calculateFromChangelog(issue, debtChangelog, period.getSnapshotDate()); + } + + private long calculateFromChangelog(DefaultIssue issue, List debtChangelog, long periodDate) { + List debtDiffs = from(debtChangelog).transform(ToFieldDiffs.INSTANCE).filter(HasDebtChange.INSTANCE).toSortedList(CHANGE_ORDERING); + long newDebt = issue.debtInMinutes().longValue(); + + for (Iterator it = debtDiffs.iterator(); it.hasNext();) { + FieldDiffs diffs = it.next(); + Date date = diffs.creationDate(); + // TODO use longs + if (isBeforeOrEqual(date, new Date(periodDate))) { + // return new value from the change that is just before the period date + return subtract(newDebt, debtDiff(diffs).newValueLong()); + } + if (!it.hasNext()) { + // return old value from the change that is just after the period date when there's no more element in changelog + return subtract(newDebt, debtDiff(diffs).oldValueLong()); + } + } + // no changelog + return 0L; + } + + /** + * SONAR-5059 + */ + @CheckForNull + private static long subtract(long newDebt, @Nullable Long with) { + if (with != null) { + return Math.min(0L, newDebt - with); + } + return newDebt; } + private static boolean isBeforeOrEqual(@Nullable Date changeDate, Date periodDate) { + return (changeDate != null) && (DateUtils.truncatedCompareTo(changeDate, periodDate, Calendar.SECOND) <= 0); + } + + private static FieldDiffs.Diff debtDiff(FieldDiffs diffs) { + return diffs.diffs().get(IssueUpdater.TECHNICAL_DEBT); + } + + /** + * 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. + */ + private static final Comparator CHANGE_ORDERING = Ordering.natural().reverse().nullsFirst().onResultOf(new Function() { + @Override + public Date apply(@Nonnull FieldDiffs dto) { + return dto.creationDate(); + } + }); + + private enum ToFieldDiffs implements Function { + INSTANCE; + @Override + public FieldDiffs apply(@Nonnull IssueChangeDto dto) { + FieldDiffs diffs = FieldDiffs.parse(dto.getChangeData()); + diffs.setIssueKey(dto.getIssueKey()); + Long date = dto.getIssueChangeCreationDate(); + if (date != null) { + diffs.setCreationDate(new Date(date)); + } + return diffs; + } + } + + private enum HasDebtChange implements Predicate { + INSTANCE; + @Override + public boolean apply(@Nonnull FieldDiffs diffs) { + return diffs.diffs().containsKey(IssueUpdater.TECHNICAL_DEBT); + } + } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/RuleTagsCopier.java b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/RuleTagsCopier.java index 2d33d7898bf..75530ff601d 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/RuleTagsCopier.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/RuleTagsCopier.java @@ -26,7 +26,7 @@ import org.sonar.server.computation.component.Component; import static com.google.common.collect.Sets.union; -public class RuleTagsCopier extends IssueListener { +public class RuleTagsCopier extends IssueVisitor { private final RuleCache ruleCache; diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/TrackerBaseInputFactory.java b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/TrackerBaseInputFactory.java index e5117d3fe23..8f5feb2573c 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/TrackerBaseInputFactory.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/TrackerBaseInputFactory.java @@ -23,6 +23,7 @@ import java.util.List; import org.sonar.core.issue.DefaultIssue; import org.sonar.core.issue.tracking.Input; import org.sonar.core.issue.tracking.LazyInput; +import org.sonar.core.issue.tracking.LineHashSequence; import org.sonar.core.persistence.DbSession; import org.sonar.core.persistence.MyBatis; import org.sonar.server.computation.component.Component; @@ -53,10 +54,11 @@ public class TrackerBaseInputFactory { } @Override - protected Iterable loadSourceLines() { + protected LineHashSequence loadLineHashSequence() { DbSession session = dbClient.openSession(false); try { - return dbClient.fileSourceDao().selectLineHashes(session, component.getUuid()); + List hashes = dbClient.fileSourceDao().selectLineHashes(session, component.getUuid()); + return new LineHashSequence(hashes); } finally { MyBatis.closeQuietly(session); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/TrackerRawInputFactory.java b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/TrackerRawInputFactory.java index 036a0e5d74d..e61e9a578ba 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/TrackerRawInputFactory.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/TrackerRawInputFactory.java @@ -22,10 +22,12 @@ package org.sonar.server.computation.issue; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import org.sonar.api.issue.Issue; import org.sonar.api.rule.RuleKey; import org.sonar.api.utils.Duration; +import org.sonar.api.utils.log.Loggers; import org.sonar.batch.protocol.output.BatchReport; import org.sonar.core.issue.DefaultIssue; import org.sonar.core.issue.tracking.Input; @@ -59,8 +61,14 @@ public class TrackerRawInputFactory { } @Override - protected Iterable loadSourceLines() { - return Lists.newArrayList(reportReader.readFileSource(component.getRef())); + protected LineHashSequence loadLineHashSequence() { + Iterable lines; + if (component.getType() == Component.Type.FILE) { + lines = Lists.newArrayList(reportReader.readFileSource(component.getRef())); + } else { + lines = Collections.emptyList(); + } + return LineHashSequence.createForLines(lines); } @Override @@ -73,6 +81,7 @@ public class TrackerRawInputFactory { for (BatchReport.Issue reportIssue : reportIssues) { DefaultIssue issue = toIssue(lineHashSeq, reportIssue); if (isValid(issue, lineHashSeq)) { + Loggers.get(getClass()).info("Loaded from report: " + issue); issues.add(issue); } } @@ -83,10 +92,12 @@ public class TrackerRawInputFactory { private DefaultIssue toIssue(LineHashSequence lineHashSeq, BatchReport.Issue reportIssue) { DefaultIssue issue = new DefaultIssue(); issue.setRuleKey(RuleKey.of(reportIssue.getRuleRepository(), reportIssue.getRuleKey())); + issue.setResolution(null); issue.setStatus(Issue.STATUS_OPEN); issue.setComponentUuid(component.getUuid()); issue.setComponentKey(component.getKey()); issue.setProjectUuid(treeRootHolder.getRoot().getUuid()); + issue.setProjectKey(treeRootHolder.getRoot().getKey()); if (reportIssue.hasLine()) { issue.setLine(reportIssue.getLine()); @@ -113,12 +124,14 @@ public class TrackerRawInputFactory { } private boolean isValid(DefaultIssue issue, LineHashSequence lineHashSeq) { - // TODO log debug when invalid ? + // TODO log debug when invalid ? Or throw exception ? + if (ruleCache.getNullable(issue.ruleKey()) == null) { return false; } if (issue.getLine() != null && !lineHashSeq.hasLine(issue.getLine())) { - return false; + // FIXME + //return false; } return true; } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/measure/BatchMeasureToMeasure.java b/server/sonar-server/src/main/java/org/sonar/server/computation/measure/BatchMeasureToMeasure.java index bdaeae33186..41a4e49cb77 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/measure/BatchMeasureToMeasure.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/measure/BatchMeasureToMeasure.java @@ -22,20 +22,12 @@ package org.sonar.server.computation.measure; import com.google.common.base.Optional; import java.util.Objects; import javax.annotation.Nullable; -import org.sonar.api.rule.RuleKey; import org.sonar.batch.protocol.output.BatchReport; -import org.sonar.core.rule.RuleDto; -import org.sonar.server.computation.issue.RuleCache; import org.sonar.server.computation.metric.Metric; import static com.google.common.base.Optional.of; public class BatchMeasureToMeasure { - private final RuleCache ruleCache; - - public BatchMeasureToMeasure(RuleCache ruleCache) { - this.ruleCache = ruleCache; - } public Optional toMeasure(@Nullable BatchReport.Measure batchMeasure, Metric metric) { Objects.requireNonNull(metric); @@ -43,7 +35,7 @@ public class BatchMeasureToMeasure { return Optional.absent(); } - Measure.NewMeasureBuilder builder = createBuilder(batchMeasure); + Measure.NewMeasureBuilder builder = Measure.newMeasureBuilder(); String data = batchMeasure.hasStringValue() ? batchMeasure.getStringValue() : null; switch (metric.getType().getValueType()) { case INT: @@ -65,20 +57,6 @@ public class BatchMeasureToMeasure { } } - private Measure.NewMeasureBuilder createBuilder(BatchReport.Measure batchMeasure) { - if (batchMeasure.hasCharactericId() && batchMeasure.hasRuleKey()) { - throw new IllegalArgumentException("Measure with both characteristicId and ruleKey are not supported"); - } - if (batchMeasure.hasCharactericId()) { - return Measure.newMeasureBuilder().forCharacteristic(batchMeasure.getCharactericId()); - } - if (batchMeasure.hasRuleKey()) { - RuleDto ruleDto = ruleCache.get(RuleKey.parse(batchMeasure.getRuleKey())); - return Measure.newMeasureBuilder().forRule(ruleDto.getId()); - } - return Measure.newMeasureBuilder(); - } - private static Optional toIntegerMeasure(Measure.NewMeasureBuilder builder, BatchReport.Measure batchMeasure, @Nullable String data) { if (!batchMeasure.hasIntValue()) { return toNoValueMeasure(builder, batchMeasure); @@ -113,7 +91,7 @@ public class BatchMeasureToMeasure { } return of(setCommonProperties(builder, batchMeasure).create(batchMeasure.getStringValue())); } - + private static Optional toLevelMeasure(Measure.NewMeasureBuilder builder, BatchReport.Measure batchMeasure) { if (!batchMeasure.hasStringValue()) { return toNoValueMeasure(builder, batchMeasure); @@ -130,14 +108,7 @@ public class BatchMeasureToMeasure { } private static Measure.NewMeasureBuilder setCommonProperties(Measure.NewMeasureBuilder builder, BatchReport.Measure batchMeasure) { - if (batchMeasure.hasAlertStatus()) { - Optional qualityGateStatus = Measure.Level.toLevel(batchMeasure.getAlertStatus()); - if (qualityGateStatus.isPresent()) { - String text = batchMeasure.hasAlertText() ? batchMeasure.getAlertText() : null; - builder.setQualityGateStatus(new QualityGateStatus(qualityGateStatus.get(), text)); - } - } - if (hasAnyVariation(batchMeasure)) { + if (hasAnyVariation(batchMeasure)) { builder.setVariations(createVariations(batchMeasure)); } return builder; @@ -145,20 +116,19 @@ public class BatchMeasureToMeasure { private static boolean hasAnyVariation(BatchReport.Measure batchMeasure) { return batchMeasure.hasVariationValue1() - || batchMeasure.hasVariationValue2() - || batchMeasure.hasVariationValue3() - || batchMeasure.hasVariationValue4() - || batchMeasure.hasVariationValue5(); + || batchMeasure.hasVariationValue2() + || batchMeasure.hasVariationValue3() + || batchMeasure.hasVariationValue4() + || batchMeasure.hasVariationValue5(); } private static MeasureVariations createVariations(BatchReport.Measure batchMeasure) { return new MeasureVariations( - batchMeasure.hasVariationValue1() ? batchMeasure.getVariationValue1() : null, - batchMeasure.hasVariationValue2() ? batchMeasure.getVariationValue2() : null, - batchMeasure.hasVariationValue3() ? batchMeasure.getVariationValue3() : null, - batchMeasure.hasVariationValue4() ? batchMeasure.getVariationValue4() : null, - batchMeasure.hasVariationValue5() ? batchMeasure.getVariationValue5() : null - ); + batchMeasure.hasVariationValue1() ? batchMeasure.getVariationValue1() : null, + batchMeasure.hasVariationValue2() ? batchMeasure.getVariationValue2() : null, + batchMeasure.hasVariationValue3() ? batchMeasure.getVariationValue3() : null, + batchMeasure.hasVariationValue4() ? batchMeasure.getVariationValue4() : null, + batchMeasure.hasVariationValue5() ? batchMeasure.getVariationValue5() : null); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureRepositoryImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureRepositoryImpl.java index 26a486c58bd..8cdb33bcfb5 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureRepositoryImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureRepositoryImpl.java @@ -36,7 +36,6 @@ import org.sonar.core.rule.RuleDto; import org.sonar.server.computation.batch.BatchReportReader; import org.sonar.server.computation.component.Component; import org.sonar.server.computation.debt.Characteristic; -import org.sonar.server.computation.issue.RuleCache; import org.sonar.server.computation.metric.Metric; import org.sonar.server.computation.metric.MetricRepository; import org.sonar.server.db.DbClient; @@ -55,10 +54,10 @@ public class MeasureRepositoryImpl implements MeasureRepository { private final Map> measures = new HashMap<>(); public MeasureRepositoryImpl(DbClient dbClient, BatchReportReader reportReader, - final MetricRepository metricRepository, final RuleCache ruleCache) { + MetricRepository metricRepository) { this.dbClient = dbClient; this.reportReader = reportReader; - this.batchMeasureToMeasure = new BatchMeasureToMeasure(ruleCache); + this.batchMeasureToMeasure = new BatchMeasureToMeasure(); this.metricRepository = metricRepository; } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java index 49643fa299a..bc5d9633880 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ComputationSteps.java @@ -55,6 +55,7 @@ public class ComputationSteps { ComputeIssueMeasuresStep.class, CustomMeasuresCopyStep.class, ComputeFormulaMeasuresStep.class, + CustomMeasuresCopyStep.class, SqaleMeasuresStep.class, NewCoverageMeasuresStep.class, NewCoverageAggregationStep.class, diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/FeedDebtModelStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/FeedDebtModelStep.java index b03a1f9559e..80e7899eb5e 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/FeedDebtModelStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/FeedDebtModelStep.java @@ -22,8 +22,6 @@ package org.sonar.server.computation.step; import com.google.common.base.Function; import com.google.common.base.Predicate; -import com.google.common.base.Predicates; -import com.google.common.collect.FluentIterable; import java.util.Collection; import java.util.List; import java.util.Map; diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/IntegrateIssuesStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/IntegrateIssuesStep.java index fed2f288295..f9c08506ed5 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/IntegrateIssuesStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/IntegrateIssuesStep.java @@ -23,6 +23,7 @@ import com.google.common.collect.Sets; import java.util.List; import java.util.Map; import java.util.Set; +import org.sonar.api.utils.log.Loggers; import org.sonar.core.issue.DefaultIssue; import org.sonar.core.issue.tracking.Tracking; import org.sonar.server.computation.component.Component; @@ -31,11 +32,11 @@ import org.sonar.server.computation.component.TreeRootHolder; import org.sonar.server.computation.issue.BaseIssuesLoader; import org.sonar.server.computation.issue.IssueCache; import org.sonar.server.computation.issue.IssueLifecycle; -import org.sonar.server.computation.issue.IssueListeners; +import org.sonar.server.computation.issue.IssueVisitors; import org.sonar.server.computation.issue.TrackerExecution; import org.sonar.server.util.cache.DiskCache; -import static org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor.Order.POST_ORDER; +import static org.sonar.server.computation.component.ComponentVisitor.Order.POST_ORDER; public class IntegrateIssuesStep implements ComputationStep { @@ -44,17 +45,17 @@ public class IntegrateIssuesStep implements ComputationStep { private final IssueCache issueCache; private final BaseIssuesLoader baseIssuesLoader; private final IssueLifecycle issueLifecycle; - private final IssueListeners issueListeners; + private final IssueVisitors issueVisitors; public IntegrateIssuesStep(TreeRootHolder treeRootHolder, TrackerExecution tracker, IssueCache issueCache, BaseIssuesLoader baseIssuesLoader, IssueLifecycle issueLifecycle, - IssueListeners issueListeners) { + IssueVisitors issueVisitors) { this.treeRootHolder = treeRootHolder; this.tracker = tracker; this.issueCache = issueCache; this.baseIssuesLoader = baseIssuesLoader; this.issueLifecycle = issueLifecycle; - this.issueListeners = issueListeners; + this.issueVisitors = issueVisitors; } @Override @@ -75,13 +76,15 @@ public class IntegrateIssuesStep implements ComputationStep { private void processIssues(Component component) { Tracking tracking = tracker.track(component); + Loggers.get(getClass()).info("----- tracking ------"); + Loggers.get(getClass()).info("" + tracking); DiskCache.DiskAppender cacheAppender = issueCache.newAppender(); try { - issueListeners.beforeComponent(component, tracking); + issueVisitors.beforeComponent(component, tracking); fillNewOpenIssues(component, tracking, cacheAppender); fillExistingOpenIssues(component, tracking, cacheAppender); closeUnmatchedBaseIssues(component, tracking, cacheAppender); - issueListeners.afterComponent(component); + issueVisitors.afterComponent(component); } finally { cacheAppender.close(); } @@ -89,42 +92,49 @@ public class IntegrateIssuesStep implements ComputationStep { private void fillNewOpenIssues(Component component, Tracking tracking, DiskCache.DiskAppender cacheAppender) { Set issues = tracking.getUnmatchedRaws(); + Loggers.get(getClass()).info("----- fillNewOpenIssues on " + component.getKey()); for (DefaultIssue issue : issues) { issueLifecycle.initNewOpenIssue(issue); - issueListeners.onOpenIssueInitialization(component, issue); + Loggers.get(getClass()).info("new " + issue); process(component, issue, cacheAppender); } + Loggers.get(getClass()).info("----- /fillNewOpenIssues on " + component.getKey()); } private void fillExistingOpenIssues(Component component, Tracking tracking, DiskCache.DiskAppender cacheAppender) { + Loggers.get(getClass()).info("----- fillExistingOpenIssues on " + component.getKey()); for (Map.Entry entry : tracking.getMatchedRaws().entrySet()) { DefaultIssue raw = entry.getKey(); DefaultIssue base = entry.getValue(); - issueListeners.onOpenIssueInitialization(component, raw); issueLifecycle.mergeExistingOpenIssue(raw, base); + Loggers.get(getClass()).info("merged " + raw); process(component, raw, cacheAppender); } for (Map.Entry entry : tracking.getOpenManualIssuesByLine().entries()) { int line = entry.getKey(); DefaultIssue manualIssue = entry.getValue(); manualIssue.setLine(line == 0 ? null : line); - issueListeners.onOpenIssueInitialization(component, manualIssue); + Loggers.get(getClass()).info("kept manual " + manualIssue); process(component, manualIssue, cacheAppender); } + Loggers.get(getClass()).info("----- /fillExistingOpenIssues on " + component.getKey()); } private void closeUnmatchedBaseIssues(Component component, Tracking tracking, DiskCache.DiskAppender cacheAppender) { + Loggers.get(getClass()).info("----- closeUnmatchedBaseIssues on " + component.getKey()); for (DefaultIssue issue : tracking.getUnmatchedBases()) { // TODO should replace flag "beingClosed" by express call to transition "automaticClose" issue.setBeingClosed(true); + Loggers.get(getClass()).info("closing " + issue); // TODO manual issues -> was updater.setResolution(newIssue, Issue.RESOLUTION_REMOVED, changeContext);. Is it a problem ? process(component, issue, cacheAppender); } + Loggers.get(getClass()).info("----- /closeUnmatchedBaseIssues on " + component.getKey()); } private void process(Component component, DefaultIssue issue, DiskCache.DiskAppender cacheAppender) { issueLifecycle.doAutomaticTransition(issue); - issueListeners.onIssue(component, issue); + issueVisitors.onIssue(component, issue); cacheAppender.append(issue); } @@ -135,8 +145,10 @@ public class IntegrateIssuesStep implements ComputationStep { List issues = baseIssuesLoader.loadForComponentUuid(deletedComponentUuid); for (DefaultIssue issue : issues) { issue.setBeingClosed(true); + // FIXME should be renamed "setToRemovedStatus" + issue.setOnDisabledRule(true); issueLifecycle.doAutomaticTransition(issue); - // TODO execute listeners ? Component is currently missing. + // TODO execute visitors ? Component is currently missing. cacheAppender.append(issue); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistIssuesStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistIssuesStep.java index 539d5b6cbc7..a5ac16a7477 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistIssuesStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistIssuesStep.java @@ -19,9 +19,9 @@ */ package org.sonar.server.computation.step; -import org.sonar.api.issue.Issue; import org.sonar.api.issue.IssueComment; import org.sonar.api.utils.System2; +import org.sonar.api.utils.log.Loggers; import org.sonar.core.issue.DefaultIssue; import org.sonar.core.issue.DefaultIssueComment; import org.sonar.core.issue.FieldDiffs; @@ -67,22 +67,24 @@ public class PersistIssuesStep implements ComputationStep { boolean saved = false; if (issue.isNew()) { Integer ruleId = ruleCache.get(issue.ruleKey()).getId(); - mapper.insert(IssueDto.toDtoForComputationInsert(issue, ruleId, system2.now())); + IssueDto dto = IssueDto.toDtoForComputationInsert(issue, ruleId, system2.now()); + Loggers.get(getClass()).info("---- INSERT " + dto); + mapper.insert(dto); saved = true; } else if (issue.isChanged()) { IssueDto dto = IssueDto.toDtoForUpdate(issue, system2.now()); - if (Issue.STATUS_CLOSED.equals(issue.status()) || issue.selectedAt() == null) { - // Issue is closed by scan or changed by end-user - mapper.update(dto); - } else { - int updateCount = mapper.updateIfBeforeSelectedDate(dto); - if (updateCount == 0) { - // End-user and scan changed the issue at the same time. - // See https://jira.sonarsource.com/browse/SONAR-4309 - conflictResolver.resolve(issue, mapper); - } + Loggers.get(getClass()).info("---- UPDATE " + dto); + int updateCount = mapper.updateIfBeforeSelectedDate(dto); + if (updateCount == 0) { + Loggers.get(getClass()).info("---- CONFLICT: " + updateCount); + // End-user and scan changed the issue at the same time. + // See https://jira.sonarsource.com/browse/SONAR-4309 + conflictResolver.resolve(issue, mapper); } + saved = true; + } else { + Loggers.get(getClass()).info("---- UNCHANGED " + issue); } if (saved) { insertChanges(changeMapper, issue); diff --git a/server/sonar-server/src/main/java/org/sonar/server/source/db/FileSourceDao.java b/server/sonar-server/src/main/java/org/sonar/server/source/db/FileSourceDao.java index 4e78181f4c5..c1d8f0e6002 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/source/db/FileSourceDao.java +++ b/server/sonar-server/src/main/java/org/sonar/server/source/db/FileSourceDao.java @@ -27,6 +27,7 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.List; import javax.annotation.CheckForNull; import org.apache.commons.dbutils.DbUtils; import org.apache.commons.io.IOUtils; @@ -69,7 +70,7 @@ public class FileSourceDao implements DaoComponent { } @CheckForNull - public Iterable selectLineHashes(DbSession dbSession, String fileUuid) { + public List selectLineHashes(DbSession dbSession, String fileUuid) { Connection connection = dbSession.getConnection(); PreparedStatement pstmt = null; ResultSet rs = null; @@ -79,7 +80,7 @@ public class FileSourceDao implements DaoComponent { pstmt.setString(2, Type.SOURCE); rs = pstmt.executeQuery(); if (rs.next()) { - return END_OF_LINE_SPLITTER.split(rs.getString(1)); + return END_OF_LINE_SPLITTER.splitToList(rs.getString(1)); } return null; } catch (SQLException e) { diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/debt/CharacteristicTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/debt/CharacteristicTest.java index 55a984af894..c1deba15921 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/debt/CharacteristicTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/debt/CharacteristicTest.java @@ -41,7 +41,7 @@ public class CharacteristicTest { @Test public void test_to_string() throws Exception { - assertThat(new Characteristic(1, "PORTABILITY", null).toString()).isEqualTo("Characteristic{id=1, key='PORTABILITY'}"); + assertThat(new Characteristic(1, "PORTABILITY", null).toString()).isEqualTo("Characteristic{id=1, key='PORTABILITY', parentId=null}"); } @Test diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/debt/DebtModelHolderImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/debt/DebtModelHolderImplTest.java index df3a0e6be99..a9172d9842e 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/debt/DebtModelHolderImplTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/debt/DebtModelHolderImplTest.java @@ -1,3 +1,22 @@ +/* + * 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. + */ ///* // * SonarQube, open source software quality management tool. // * Copyright (C) 2008-2014 SonarSource diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/issue/CountIssuesListenerTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/issue/CountIssuesListenerTest.java index 56b65390a89..5a7fa451ba4 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/issue/CountIssuesListenerTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/issue/CountIssuesListenerTest.java @@ -107,15 +107,14 @@ public class CountIssuesListenerTest { Tracking tracking = mock(Tracking.class); MetricRepository metricRepository = mock(MetricRepository.class); MeasureRepository measureRepository; - RuleCache ruleCache = mock(RuleCache.class); - CountIssuesListener sut; + IssueCounter sut; @Before public void setUp() throws Exception { initMetrics(); - measureRepository = new MeasureRepositoryImpl(null, reportReader, metricRepository, ruleCache); + measureRepository = new MeasureRepositoryImpl(null, reportReader, metricRepository); - sut = new CountIssuesListener(periodsHolder, metricRepository, measureRepository); + sut = new IssueCounter(periodsHolder, metricRepository, measureRepository); } @Test diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/issue/NewDebtAggregatorTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/issue/NewDebtAggregatorTest.java new file mode 100644 index 00000000000..17c4dc053d3 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/issue/NewDebtAggregatorTest.java @@ -0,0 +1,367 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +//package org.sonar.server.computation.issue; +// +//import java.util.Date; +//import org.apache.commons.lang.ObjectUtils; +//import org.apache.commons.lang.time.DateUtils; +//import org.junit.Before; +//import org.junit.Test; +//import org.mockito.ArgumentMatcher; +//import org.mockito.Mock; +//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.measures.CoreMetrics; +//import org.sonar.api.measures.Measure; +//import org.sonar.api.measures.Metric; +//import org.sonar.api.resources.Resource; +//import org.sonar.api.utils.Duration; +//import org.sonar.core.issue.DefaultIssue; +//import org.sonar.core.issue.FieldDiffs; +// +//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; +// +//public class NewDebtAggregatorTest { +// 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/server/sonar-server/src/test/java/org/sonar/server/computation/issue/NewDebtCalculatorTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/issue/NewDebtCalculatorTest.java new file mode 100644 index 00000000000..bfbcb7a87ce --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/issue/NewDebtCalculatorTest.java @@ -0,0 +1,146 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +//package org.sonar.server.computation.issue; +// +//import java.util.Date; +//import org.apache.commons.lang.time.DateUtils; +//import org.junit.Before; +//import org.junit.Test; +//import org.sonar.api.issue.Issue; +//import org.sonar.api.utils.Duration; +//import org.sonar.core.issue.DefaultIssue; +//import org.sonar.core.issue.FieldDiffs; +// +//import static com.google.common.collect.Lists.newArrayList; +//import static org.assertj.core.api.Assertions.assertThat; +// +//public class NewDebtCalculatorTest { +// 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/server/sonar-server/src/test/java/org/sonar/server/computation/measure/BatchMeasureToMeasureTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/measure/BatchMeasureToMeasureTest.java index fbf88dbdf0d..c00155eb02f 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/measure/BatchMeasureToMeasureTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/measure/BatchMeasureToMeasureTest.java @@ -23,20 +23,14 @@ import com.google.common.base.Optional; import com.tngtech.java.junit.dataprovider.DataProvider; import com.tngtech.java.junit.dataprovider.DataProviderRunner; import com.tngtech.java.junit.dataprovider.UseDataProvider; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.sonar.api.rule.RuleKey; import org.sonar.batch.protocol.output.BatchReport; -import org.sonar.core.rule.RuleDto; -import org.sonar.server.computation.issue.RuleCache; import org.sonar.server.computation.metric.Metric; import org.sonar.server.computation.metric.MetricImpl; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.guava.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; @RunWith(DataProviderRunner.class) public class BatchMeasureToMeasureTest { @@ -48,19 +42,9 @@ public class BatchMeasureToMeasureTest { private static final Metric SOME_LEVEL_METRIC = new MetricImpl(42, "level", "name", Metric.MetricType.LEVEL); private static final String SOME_DATA = "some_data man!"; - private static final String SOME_ALERT_TEXT = "some alert text_be_careFul!"; private static final BatchReport.Measure EMPTY_BATCH_MEASURE = BatchReport.Measure.newBuilder().build(); - private static final RuleKey SOME_RULE_KEY = RuleKey.of("A", "B"); - private static final int SOME_RULE_ID = 9513; - private static final RuleDto SOME_RULE = new RuleDto().setRuleKey(SOME_RULE_KEY.toString()).setId(SOME_RULE_ID); - private RuleCache ruleCache = mock(RuleCache.class); - private BatchMeasureToMeasure underTest = new BatchMeasureToMeasure(ruleCache); - - @Before - public void setUp() throws Exception { - when(ruleCache.get(SOME_RULE_KEY)).thenReturn(SOME_RULE); - } + private BatchMeasureToMeasure underTest = new BatchMeasureToMeasure(); @Test public void toMeasure_returns_absent_for_null_argument() { @@ -77,25 +61,6 @@ public class BatchMeasureToMeasureTest { underTest.toMeasure(null, null); } - @Test(expected = IllegalArgumentException.class) - public void toMeasure_throws_IAE_if_batch_Measure_has_both_ruleKey_and_characteristicId() { - underTest.toMeasure(BatchReport.Measure.newBuilder().setRuleKey(SOME_RULE_KEY.toString()).setCharactericId(42).build(), SOME_STRING_METRIC); - } - - @Test - public void toMeasure_maps_characteristicId_if_present() { - BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder().setCharactericId(42).build(); - - assertThat(underTest.toMeasure(batchMeasure, SOME_STRING_METRIC).get().getCharacteristicId()).isEqualTo(42); - } - - @Test - public void toMeasure_maps_ruleKey_if_present() { - BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder().setRuleKey(SOME_RULE_KEY.toString()).build(); - - assertThat(underTest.toMeasure(batchMeasure, SOME_STRING_METRIC).get().getRuleId()).isEqualTo(SOME_RULE_ID); - } - @Test public void toMeasure_returns_no_value_if_dto_has_no_string_value_for_LEVEL_Metric() { Optional measure = underTest.toMeasure(EMPTY_BATCH_MEASURE, SOME_LEVEL_METRIC); @@ -138,8 +103,6 @@ public class BatchMeasureToMeasureTest { public void toMeasure_for_LEVEL_Metric_maps_QualityGateStatus() { BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder() .setStringValue(Measure.Level.OK.name()) - .setAlertStatus(Measure.Level.ERROR.name()) - .setAlertText(SOME_ALERT_TEXT) .build(); Optional measure = underTest.toMeasure(batchMeasure, SOME_LEVEL_METRIC); @@ -147,8 +110,6 @@ public class BatchMeasureToMeasureTest { assertThat(measure).isPresent(); assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.LEVEL); assertThat(measure.get().getLevelValue()).isEqualTo(Measure.Level.OK); - assertThat(measure.get().getQualityGateStatus().getStatus()).isEqualTo(Measure.Level.ERROR); - assertThat(measure.get().getQualityGateStatus().getText()).isEqualTo(SOME_ALERT_TEXT); } @Test @@ -182,7 +143,6 @@ public class BatchMeasureToMeasureTest { BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder() .setIntValue(10) .setStringValue(SOME_DATA) - .setAlertStatus(Measure.Level.OK.name()).setAlertText(SOME_ALERT_TEXT) .build(); Optional measure = underTest.toMeasure(batchMeasure, SOME_INT_METRIC); @@ -191,8 +151,6 @@ public class BatchMeasureToMeasureTest { assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.INT); assertThat(measure.get().getIntValue()).isEqualTo(10); assertThat(measure.get().getData()).isEqualTo(SOME_DATA); - assertThat(measure.get().getQualityGateStatus().getStatus()).isEqualTo(Measure.Level.OK); - assertThat(measure.get().getQualityGateStatus().getText()).isEqualTo(SOME_ALERT_TEXT); } @Test @@ -217,7 +175,6 @@ public class BatchMeasureToMeasureTest { BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder() .setLongValue(10l) .setStringValue(SOME_DATA) - .setAlertStatus(Measure.Level.OK.name()).setAlertText(SOME_ALERT_TEXT) .build(); Optional measure = underTest.toMeasure(batchMeasure, SOME_LONG_METRIC); @@ -226,8 +183,6 @@ public class BatchMeasureToMeasureTest { assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.LONG); assertThat(measure.get().getLongValue()).isEqualTo(10); assertThat(measure.get().getData()).isEqualTo(SOME_DATA); - assertThat(measure.get().getQualityGateStatus().getStatus()).isEqualTo(Measure.Level.OK); - assertThat(measure.get().getQualityGateStatus().getText()).isEqualTo(SOME_ALERT_TEXT); } @Test @@ -243,7 +198,6 @@ public class BatchMeasureToMeasureTest { BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder() .setDoubleValue(10.6395d) .setStringValue(SOME_DATA) - .setAlertStatus(Measure.Level.OK.name()).setAlertText(SOME_ALERT_TEXT) .build(); Optional measure = underTest.toMeasure(batchMeasure, SOME_DOUBLE_METRIC); @@ -252,8 +206,6 @@ public class BatchMeasureToMeasureTest { assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.DOUBLE); assertThat(measure.get().getDoubleValue()).isEqualTo(10.6d); assertThat(measure.get().getData()).isEqualTo(SOME_DATA); - assertThat(measure.get().getQualityGateStatus().getStatus()).isEqualTo(Measure.Level.OK); - assertThat(measure.get().getQualityGateStatus().getText()).isEqualTo(SOME_ALERT_TEXT); } @Test @@ -281,7 +233,7 @@ public class BatchMeasureToMeasureTest { @Test public void toMeasure_maps_data_and_alert_properties_in_dto_for_Boolean_metric() { BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder() - .setBooleanValue(true).setStringValue(SOME_DATA).setAlertStatus(Measure.Level.OK.name()).setAlertText(SOME_ALERT_TEXT).build(); + .setBooleanValue(true).setStringValue(SOME_DATA).build(); Optional measure = underTest.toMeasure(batchMeasure, SOME_BOOLEAN_METRIC); @@ -289,8 +241,6 @@ public class BatchMeasureToMeasureTest { assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.BOOLEAN); assertThat(measure.get().getBooleanValue()).isTrue(); assertThat(measure.get().getData()).isEqualTo(SOME_DATA); - assertThat(measure.get().getQualityGateStatus().getStatus()).isEqualTo(Measure.Level.OK); - assertThat(measure.get().getQualityGateStatus().getText()).isEqualTo(SOME_ALERT_TEXT); } @Test @@ -305,7 +255,6 @@ public class BatchMeasureToMeasureTest { public void toMeasure_maps_alert_properties_in_dto_for_String_Metric() { BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder() .setStringValue(SOME_DATA) - .setAlertStatus(Measure.Level.OK.name()).setAlertText(SOME_ALERT_TEXT) .build(); Optional measure = underTest.toMeasure(batchMeasure, SOME_STRING_METRIC); @@ -314,8 +263,6 @@ public class BatchMeasureToMeasureTest { assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.STRING); assertThat(measure.get().getStringValue()).isEqualTo(SOME_DATA); assertThat(measure.get().getData()).isEqualTo(SOME_DATA); - assertThat(measure.get().getQualityGateStatus().getStatus()).isEqualTo(Measure.Level.OK); - assertThat(measure.get().getQualityGateStatus().getText()).isEqualTo(SOME_ALERT_TEXT); } @DataProvider diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/measure/MeasureRepositoryImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/measure/MeasureRepositoryImplTest.java index 22f1a271827..67d0a10e685 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/measure/MeasureRepositoryImplTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/measure/MeasureRepositoryImplTest.java @@ -49,7 +49,6 @@ import org.sonar.server.computation.batch.BatchReportReaderRule; import org.sonar.server.computation.component.Component; import org.sonar.server.computation.component.DumbComponent; import org.sonar.server.computation.debt.Characteristic; -import org.sonar.server.computation.issue.RuleCache; import org.sonar.server.computation.metric.Metric; import org.sonar.server.computation.metric.MetricImpl; import org.sonar.server.computation.metric.MetricRepository; @@ -93,12 +92,11 @@ public class MeasureRepositoryImplTest { private DbClient dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new MeasureDao(), new SnapshotDao(), new MetricDao(), new ComponentDao()); private MetricRepository metricRepository = mock(MetricRepository.class); - private RuleCache ruleCache = mock(RuleCache.class); - private MeasureRepositoryImpl underTest = new MeasureRepositoryImpl(dbClient, reportReader, metricRepository, ruleCache); + private MeasureRepositoryImpl underTest = new MeasureRepositoryImpl(dbClient, reportReader, metricRepository); private DbClient mockedDbClient = mock(DbClient.class); private BatchReportReader mockBatchReportReader = mock(BatchReportReader.class); - private MeasureRepositoryImpl underTestWithMock = new MeasureRepositoryImpl(mockedDbClient, mockBatchReportReader, metricRepository, ruleCache); + private MeasureRepositoryImpl underTestWithMock = new MeasureRepositoryImpl(mockedDbClient, mockBatchReportReader, metricRepository); @CheckForNull private DbSession dbSession; @@ -227,7 +225,7 @@ public class MeasureRepositoryImplTest { @Nullable @Override public Object[] apply(Measure input) { - return new Measure[] { input }; + return new Measure[] {input}; } }).toArray(Object[].class); } @@ -254,8 +252,8 @@ public class MeasureRepositoryImplTest { fail("An IllegalArgumentException should have been raised"); } catch (IllegalArgumentException e) { assertThat(e).hasMessage(format( - "Measure's ValueType (%s) is not consistent with the Measure's ValueType (%s)", - measure.getValueType(), metricType.getValueType())); + "Measure's ValueType (%s) is not consistent with the Measure's ValueType (%s)", + measure.getValueType(), metricType.getValueType())); } } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/FeedDebtModelStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/FeedDebtModelStepTest.java index 97ae6bf520e..edf10791eb2 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/FeedDebtModelStepTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/FeedDebtModelStepTest.java @@ -1,3 +1,22 @@ +/* + * 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. + */ ///* // * SonarQube, open source software quality management tool. // * Copyright (C) 2008-2014 SonarSource diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/FillMeasuresWithVariationsStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/FillMeasuresWithVariationsStepTest.java index 573b543f541..786fdcce131 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/FillMeasuresWithVariationsStepTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/FillMeasuresWithVariationsStepTest.java @@ -35,9 +35,7 @@ import org.sonar.core.measure.db.MeasureDto; import org.sonar.core.metric.db.MetricDto; import org.sonar.core.persistence.DbSession; import org.sonar.core.persistence.DbTester; -import org.sonar.core.rule.RuleDto; import org.sonar.core.technicaldebt.db.CharacteristicDao; -import org.sonar.core.technicaldebt.db.CharacteristicDto; import org.sonar.server.component.ComponentTesting; import org.sonar.server.component.db.ComponentDao; import org.sonar.server.component.db.SnapshotDao; @@ -45,9 +43,6 @@ import org.sonar.server.computation.batch.BatchReportReaderRule; import org.sonar.server.computation.batch.TreeRootHolderRule; import org.sonar.server.computation.component.Component; import org.sonar.server.computation.component.DumbComponent; -import org.sonar.server.computation.debt.Characteristic; -import org.sonar.server.computation.issue.RuleCache; -import org.sonar.server.computation.issue.RuleCacheLoader; import org.sonar.server.computation.measure.Measure; import org.sonar.server.computation.measure.MeasureRepository; import org.sonar.server.computation.measure.MeasureRepositoryImpl; @@ -60,7 +55,6 @@ import org.sonar.server.computation.period.PeriodsHolderRule; import org.sonar.server.db.DbClient; import org.sonar.server.measure.persistence.MeasureDao; import org.sonar.server.metric.persistence.MetricDao; -import org.sonar.server.rule.RuleTesting; import org.sonar.server.rule.db.RuleDao; import org.sonar.test.DbTests; @@ -119,7 +113,7 @@ public class FillMeasuresWithVariationsStepTest { metricRepository = new MetricRepositoryImpl(dbClient); metricRepository.start(); - measureRepository = new MeasureRepositoryImpl(dbClient, reportReader, metricRepository, new RuleCache(new RuleCacheLoader(dbClient))); + measureRepository = new MeasureRepositoryImpl(dbClient, reportReader, metricRepository); sut = new FillMeasuresWithVariationsStep(dbClient, treeRootHolder, periodsHolder, metricRepository, measureRepository); } @@ -257,66 +251,6 @@ public class FillMeasuresWithVariationsStepTest { assertThat(measureRepository.getRawMeasure(PROJECT, toMetric(BUILD_BREAKER_METRIC)).get().getVariations().getVariation1()).isEqualTo(-1d); } - @Test - public void set_variation_on_rule_measure() throws Exception { - SnapshotDto period1ProjectSnapshot = createForProject(PROJECT_DTO); - dbClient.snapshotDao().insert(session, period1ProjectSnapshot); - - RuleDto rule1 = RuleTesting.newXooX1(); - RuleDto rule2 = RuleTesting.newXooX2(); - dbClient.ruleDao().insert(session, rule1, rule2); - - dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 60d)); - dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 40d).setRuleId(rule1.getId())); - dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 20d).setRuleId(rule2.getId())); - session.commit(); - - periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot)); - - treeRootHolder.setRoot(PROJECT); - - measureRepository.add(PROJECT, toMetric(ISSUES_METRIC), Measure.newMeasureBuilder().create(80, null)); - measureRepository.add(PROJECT, toMetric(ISSUES_METRIC), Measure.newMeasureBuilder().forRule(rule1.getId()).create(45, null)); - measureRepository.add(PROJECT, toMetric(ISSUES_METRIC), Measure.newMeasureBuilder().forRule(rule2.getId()).create(35, null)); - - sut.execute(); - - assertThat(measureRepository.getRawMeasure(PROJECT, toMetric(ISSUES_METRIC)).get().getVariations().getVariation1()).isEqualTo(20d); - assertThat(measureRepository.getRawMeasure(PROJECT, toMetric(ISSUES_METRIC), rule1).get().getVariations().getVariation1()).isEqualTo(5d); - assertThat(measureRepository.getRawMeasure(PROJECT, toMetric(ISSUES_METRIC), rule2).get().getVariations().getVariation1()).isEqualTo(15d); - } - - @Test - public void set_variation_on_characteristic_measure() throws Exception { - SnapshotDto period1ProjectSnapshot = createForProject(PROJECT_DTO); - dbClient.snapshotDao().insert(session, period1ProjectSnapshot); - - CharacteristicDto char1 = new CharacteristicDto().setKey("PORTABILITY"); - CharacteristicDto char2 = new CharacteristicDto().setKey("MAINTAINABILITY"); - dbClient.debtCharacteristicDao().insert(session, char1, char2); - - dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 60d)); - dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 40d).setCharacteristicId(char1.getId())); - dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 20d).setCharacteristicId(char2.getId())); - session.commit(); - - periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot)); - - treeRootHolder.setRoot(PROJECT); - - measureRepository.add(PROJECT, toMetric(ISSUES_METRIC), Measure.newMeasureBuilder().create(80, null)); - measureRepository.add(PROJECT, toMetric(ISSUES_METRIC), Measure.newMeasureBuilder().forCharacteristic(char1.getId()).create(45, null)); - measureRepository.add(PROJECT, toMetric(ISSUES_METRIC), Measure.newMeasureBuilder().forCharacteristic(char2.getId()).create(35, null)); - - sut.execute(); - - assertThat(measureRepository.getRawMeasure(PROJECT, toMetric(ISSUES_METRIC)).get().getVariations().getVariation1()).isEqualTo(20d); - assertThat(measureRepository.getRawMeasure(PROJECT, toMetric(ISSUES_METRIC), new Characteristic(char1.getId(), char1.getKey(), null)).get().getVariations().getVariation1()) - .isEqualTo(5d); - assertThat(measureRepository.getRawMeasure(PROJECT, toMetric(ISSUES_METRIC), new Characteristic(char2.getId(), char2.getKey(), null)).get().getVariations().getVariation1()) - .isEqualTo(15d); - } - @Test public void read_measure_from_batch() throws Exception { // Project diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistIssuesStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistIssuesStepTest.java index e5592554a47..ff4b22ba991 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistIssuesStepTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistIssuesStepTest.java @@ -48,6 +48,8 @@ import static org.mockito.Mockito.when; public class PersistIssuesStepTest extends BaseStepTest { + public static final long NOW = 1400000000000L; + @Rule public TemporaryFolder temp = new TemporaryFolder(); @@ -77,7 +79,7 @@ public class PersistIssuesStepTest extends BaseStepTest { issueCache = new IssueCache(temp.newFile(), System2.INSTANCE); system2 = mock(System2.class); - when(system2.now()).thenReturn(1400000000000L); + when(system2.now()).thenReturn(NOW); step = new PersistIssuesStep(dbClient, system2, new UpdateConflictResolver(), new RuleCache(new RuleCacheLoader(dbClient)), issueCache); } @@ -117,6 +119,7 @@ public class PersistIssuesStepTest extends BaseStepTest { .setSeverity(Severity.BLOCKER) .setStatus(Issue.STATUS_CLOSED) .setResolution(Issue.RESOLUTION_FIXED) + .setSelectedAt(NOW) .setNew(false) .setChanged(true) ).close(); diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistMeasuresStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistMeasuresStepTest.java index 296dda1d018..b99f981492a 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistMeasuresStepTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistMeasuresStepTest.java @@ -57,6 +57,7 @@ import org.sonar.server.rule.RuleTesting; import org.sonar.server.rule.db.RuleDao; import org.sonar.test.DbTests; +import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; import static org.sonar.api.measures.CoreMetrics.DUPLICATIONS_DATA; import static org.sonar.api.measures.CoreMetrics.DUPLICATIONS_DATA_KEY; @@ -151,11 +152,8 @@ public class PersistMeasuresStepTest extends BaseStepTest { .setVariationValue3(3.3d) .setVariationValue4(4.4d) .setVariationValue5(5.5d) - .setAlertStatus("WARN") - .setAlertText("Open issues > 0") .setDescription("measure-description") .setMetricKey(STRING_METRIC_KEY) - .setCharactericId(123456) .build())); reportReader.putMeasures(FILE_REF, Arrays.asList( @@ -167,11 +165,8 @@ public class PersistMeasuresStepTest extends BaseStepTest { .setVariationValue3(3.3d) .setVariationValue4(4.4d) .setVariationValue5(5.5d) - .setAlertStatus("ERROR") - .setAlertText("Blocker issues variation > 0") .setDescription("measure-description") .setMetricKey(DOUBLE_METRIC_KEY) - .setRuleKey(RULE_KEY.toString()) .build())); sut.execute(); @@ -192,10 +187,15 @@ public class PersistMeasuresStepTest extends BaseStepTest { dto = dtos.get(PROJECT_REF); assertThat(dto.get("snapshotId")).isEqualTo(4L); assertThat(dto.get("componentId")).isEqualTo(fileDto.getId()); +<<<<<<< HEAD assertThat(dto.get("metricId")).isEqualTo(2L); assertThat(dto.get("ruleId")).isEqualTo(rule.getId().longValue()); assertThat(dto.get("characteristicId")).isNull(); assertThat(dto.get("value")).isEqualTo(123.1d); +======= + assertThat(dto.get("metricId")).isEqualTo(doubleMetric.getId().longValue()); + assertThat(dto.get("value")).isEqualTo(123.123d); +>>>>>>> SONAR-6588 integrate issues to Compute Engine assertThat(dto.get("severity")).isNull(); } diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/step/PersistIssuesStepTest/close_issue-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/step/PersistIssuesStepTest/close_issue-result.xml index e15b08c3e25..a4c029b4606 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/computation/step/PersistIssuesStepTest/close_issue-result.xml +++ b/server/sonar-server/src/test/resources/org/sonar/server/computation/step/PersistIssuesStepTest/close_issue-result.xml @@ -24,7 +24,7 @@ issue_creation_date="[null]" issue_update_date="[null]" issue_close_date="[null]" - created_at="1100000000000" + created_at="1300000000000" updated_at="1400000000000" /> diff --git a/server/sonar-server/src/test/resources/org/sonar/server/computation/step/PersistIssuesStepTest/shared.xml b/server/sonar-server/src/test/resources/org/sonar/server/computation/step/PersistIssuesStepTest/shared.xml index 23f7ab20677..3cee2f8e087 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/computation/step/PersistIssuesStepTest/shared.xml +++ b/server/sonar-server/src/test/resources/org/sonar/server/computation/step/PersistIssuesStepTest/shared.xml @@ -36,8 +36,8 @@ issue_creation_date="[null]" issue_update_date="[null]" issue_close_date="[null]" - created_at="1100000000000" - updated_at="1100000000000" + created_at="1300000000000" + updated_at="1300000000000" /> diff --git a/sonar-batch-protocol/src/main/gen-java/org/sonar/batch/protocol/output/BatchReport.java b/sonar-batch-protocol/src/main/gen-java/org/sonar/batch/protocol/output/BatchReport.java index 5f02ff8f82e..21d7b857ca9 100644 --- a/sonar-batch-protocol/src/main/gen-java/org/sonar/batch/protocol/output/BatchReport.java +++ b/sonar-batch-protocol/src/main/gen-java/org/sonar/batch/protocol/output/BatchReport.java @@ -69,6 +69,49 @@ public final class BatchReport { * optional int32 root_component_ref = 4; */ int getRootComponentRef(); + + /** + * repeated string active_rule_key = 5; + * + *

    +     *Keys of the rules that were enabled in Quality profiles.
    +     *A key is a string composed of the repository and the subKey, specific to the repository. Format is
    +     *"{repository}:{subKey}", for instance "java:NullDereference".
    +     * 
    + */ + com.google.protobuf.ProtocolStringList + getActiveRuleKeyList(); + /** + * repeated string active_rule_key = 5; + * + *
    +     *Keys of the rules that were enabled in Quality profiles.
    +     *A key is a string composed of the repository and the subKey, specific to the repository. Format is
    +     *"{repository}:{subKey}", for instance "java:NullDereference".
    +     * 
    + */ + int getActiveRuleKeyCount(); + /** + * repeated string active_rule_key = 5; + * + *
    +     *Keys of the rules that were enabled in Quality profiles.
    +     *A key is a string composed of the repository and the subKey, specific to the repository. Format is
    +     *"{repository}:{subKey}", for instance "java:NullDereference".
    +     * 
    + */ + java.lang.String getActiveRuleKey(int index); + /** + * repeated string active_rule_key = 5; + * + *
    +     *Keys of the rules that were enabled in Quality profiles.
    +     *A key is a string composed of the repository and the subKey, specific to the repository. Format is
    +     *"{repository}:{subKey}", for instance "java:NullDereference".
    +     * 
    + */ + com.google.protobuf.ByteString + getActiveRuleKeyBytes(int index); } /** * Protobuf type {@code Metadata} @@ -144,6 +187,15 @@ public final class BatchReport { rootComponentRef_ = input.readInt32(); break; } + case 42: { + com.google.protobuf.ByteString bs = input.readBytes(); + if (!((mutable_bitField0_ & 0x00000010) == 0x00000010)) { + activeRuleKey_ = new com.google.protobuf.LazyStringArrayList(); + mutable_bitField0_ |= 0x00000010; + } + activeRuleKey_.add(bs); + break; + } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { @@ -152,6 +204,9 @@ public final class BatchReport { throw new com.google.protobuf.InvalidProtocolBufferException( e.getMessage()).setUnfinishedMessage(this); } finally { + if (((mutable_bitField0_ & 0x00000010) == 0x00000010)) { + activeRuleKey_ = activeRuleKey_.getUnmodifiableView(); + } this.unknownFields = unknownFields.build(); makeExtensionsImmutable(); } @@ -310,11 +365,65 @@ public final class BatchReport { return rootComponentRef_; } + public static final int ACTIVE_RULE_KEY_FIELD_NUMBER = 5; + private com.google.protobuf.LazyStringList activeRuleKey_; + /** + * repeated string active_rule_key = 5; + * + *
    +     *Keys of the rules that were enabled in Quality profiles.
    +     *A key is a string composed of the repository and the subKey, specific to the repository. Format is
    +     *"{repository}:{subKey}", for instance "java:NullDereference".
    +     * 
    + */ + public com.google.protobuf.ProtocolStringList + getActiveRuleKeyList() { + return activeRuleKey_; + } + /** + * repeated string active_rule_key = 5; + * + *
    +     *Keys of the rules that were enabled in Quality profiles.
    +     *A key is a string composed of the repository and the subKey, specific to the repository. Format is
    +     *"{repository}:{subKey}", for instance "java:NullDereference".
    +     * 
    + */ + public int getActiveRuleKeyCount() { + return activeRuleKey_.size(); + } + /** + * repeated string active_rule_key = 5; + * + *
    +     *Keys of the rules that were enabled in Quality profiles.
    +     *A key is a string composed of the repository and the subKey, specific to the repository. Format is
    +     *"{repository}:{subKey}", for instance "java:NullDereference".
    +     * 
    + */ + public java.lang.String getActiveRuleKey(int index) { + return activeRuleKey_.get(index); + } + /** + * repeated string active_rule_key = 5; + * + *
    +     *Keys of the rules that were enabled in Quality profiles.
    +     *A key is a string composed of the repository and the subKey, specific to the repository. Format is
    +     *"{repository}:{subKey}", for instance "java:NullDereference".
    +     * 
    + */ + public com.google.protobuf.ByteString + getActiveRuleKeyBytes(int index) { + return activeRuleKey_.getByteString(index); + } + private void initFields() { analysisDate_ = 0L; projectKey_ = ""; branch_ = ""; rootComponentRef_ = 0; + activeRuleKey_ = com.google.protobuf.LazyStringArrayList.EMPTY; } private byte memoizedIsInitialized = -1; public final boolean isInitialized() { @@ -341,6 +450,9 @@ public final class BatchReport { if (((bitField0_ & 0x00000008) == 0x00000008)) { output.writeInt32(4, rootComponentRef_); } + for (int i = 0; i < activeRuleKey_.size(); i++) { + output.writeBytes(5, activeRuleKey_.getByteString(i)); + } getUnknownFields().writeTo(output); } @@ -366,6 +478,15 @@ public final class BatchReport { size += com.google.protobuf.CodedOutputStream .computeInt32Size(4, rootComponentRef_); } + { + int dataSize = 0; + for (int i = 0; i < activeRuleKey_.size(); i++) { + dataSize += com.google.protobuf.CodedOutputStream + .computeBytesSizeNoTag(activeRuleKey_.getByteString(i)); + } + size += dataSize; + size += 1 * getActiveRuleKeyList().size(); + } size += getUnknownFields().getSerializedSize(); memoizedSerializedSize = size; return size; @@ -491,6 +612,8 @@ public final class BatchReport { bitField0_ = (bitField0_ & ~0x00000004); rootComponentRef_ = 0; bitField0_ = (bitField0_ & ~0x00000008); + activeRuleKey_ = com.google.protobuf.LazyStringArrayList.EMPTY; + bitField0_ = (bitField0_ & ~0x00000010); return this; } @@ -535,6 +658,11 @@ public final class BatchReport { to_bitField0_ |= 0x00000008; } result.rootComponentRef_ = rootComponentRef_; + if (((bitField0_ & 0x00000010) == 0x00000010)) { + activeRuleKey_ = activeRuleKey_.getUnmodifiableView(); + bitField0_ = (bitField0_ & ~0x00000010); + } + result.activeRuleKey_ = activeRuleKey_; result.bitField0_ = to_bitField0_; onBuilt(); return result; @@ -567,6 +695,16 @@ public final class BatchReport { if (other.hasRootComponentRef()) { setRootComponentRef(other.getRootComponentRef()); } + if (!other.activeRuleKey_.isEmpty()) { + if (activeRuleKey_.isEmpty()) { + activeRuleKey_ = other.activeRuleKey_; + bitField0_ = (bitField0_ & ~0x00000010); + } else { + ensureActiveRuleKeyIsMutable(); + activeRuleKey_.addAll(other.activeRuleKey_); + } + onChanged(); + } this.mergeUnknownFields(other.getUnknownFields()); return this; } @@ -834,6 +972,153 @@ public final class BatchReport { return this; } + private com.google.protobuf.LazyStringList activeRuleKey_ = com.google.protobuf.LazyStringArrayList.EMPTY; + private void ensureActiveRuleKeyIsMutable() { + if (!((bitField0_ & 0x00000010) == 0x00000010)) { + activeRuleKey_ = new com.google.protobuf.LazyStringArrayList(activeRuleKey_); + bitField0_ |= 0x00000010; + } + } + /** + * repeated string active_rule_key = 5; + * + *
    +       *Keys of the rules that were enabled in Quality profiles.
    +       *A key is a string composed of the repository and the subKey, specific to the repository. Format is
    +       *"{repository}:{subKey}", for instance "java:NullDereference".
    +       * 
    + */ + public com.google.protobuf.ProtocolStringList + getActiveRuleKeyList() { + return activeRuleKey_.getUnmodifiableView(); + } + /** + * repeated string active_rule_key = 5; + * + *
    +       *Keys of the rules that were enabled in Quality profiles.
    +       *A key is a string composed of the repository and the subKey, specific to the repository. Format is
    +       *"{repository}:{subKey}", for instance "java:NullDereference".
    +       * 
    + */ + public int getActiveRuleKeyCount() { + return activeRuleKey_.size(); + } + /** + * repeated string active_rule_key = 5; + * + *
    +       *Keys of the rules that were enabled in Quality profiles.
    +       *A key is a string composed of the repository and the subKey, specific to the repository. Format is
    +       *"{repository}:{subKey}", for instance "java:NullDereference".
    +       * 
    + */ + public java.lang.String getActiveRuleKey(int index) { + return activeRuleKey_.get(index); + } + /** + * repeated string active_rule_key = 5; + * + *
    +       *Keys of the rules that were enabled in Quality profiles.
    +       *A key is a string composed of the repository and the subKey, specific to the repository. Format is
    +       *"{repository}:{subKey}", for instance "java:NullDereference".
    +       * 
    + */ + public com.google.protobuf.ByteString + getActiveRuleKeyBytes(int index) { + return activeRuleKey_.getByteString(index); + } + /** + * repeated string active_rule_key = 5; + * + *
    +       *Keys of the rules that were enabled in Quality profiles.
    +       *A key is a string composed of the repository and the subKey, specific to the repository. Format is
    +       *"{repository}:{subKey}", for instance "java:NullDereference".
    +       * 
    + */ + public Builder setActiveRuleKey( + int index, java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + ensureActiveRuleKeyIsMutable(); + activeRuleKey_.set(index, value); + onChanged(); + return this; + } + /** + * repeated string active_rule_key = 5; + * + *
    +       *Keys of the rules that were enabled in Quality profiles.
    +       *A key is a string composed of the repository and the subKey, specific to the repository. Format is
    +       *"{repository}:{subKey}", for instance "java:NullDereference".
    +       * 
    + */ + public Builder addActiveRuleKey( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + ensureActiveRuleKeyIsMutable(); + activeRuleKey_.add(value); + onChanged(); + return this; + } + /** + * repeated string active_rule_key = 5; + * + *
    +       *Keys of the rules that were enabled in Quality profiles.
    +       *A key is a string composed of the repository and the subKey, specific to the repository. Format is
    +       *"{repository}:{subKey}", for instance "java:NullDereference".
    +       * 
    + */ + public Builder addAllActiveRuleKey( + java.lang.Iterable values) { + ensureActiveRuleKeyIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, activeRuleKey_); + onChanged(); + return this; + } + /** + * repeated string active_rule_key = 5; + * + *
    +       *Keys of the rules that were enabled in Quality profiles.
    +       *A key is a string composed of the repository and the subKey, specific to the repository. Format is
    +       *"{repository}:{subKey}", for instance "java:NullDereference".
    +       * 
    + */ + public Builder clearActiveRuleKey() { + activeRuleKey_ = com.google.protobuf.LazyStringArrayList.EMPTY; + bitField0_ = (bitField0_ & ~0x00000010); + onChanged(); + return this; + } + /** + * repeated string active_rule_key = 5; + * + *
    +       *Keys of the rules that were enabled in Quality profiles.
    +       *A key is a string composed of the repository and the subKey, specific to the repository. Format is
    +       *"{repository}:{subKey}", for instance "java:NullDereference".
    +       * 
    + */ + public Builder addActiveRuleKeyBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + ensureActiveRuleKeyIsMutable(); + activeRuleKey_.add(value); + onChanged(); + return this; + } + // @@protoc_insertion_point(builder_scope:Metadata) } @@ -3814,48 +4099,6 @@ public final class BatchReport { com.google.protobuf.ByteString getDescriptionBytes(); - /** - * optional string rule_key = 10; - */ - boolean hasRuleKey(); - /** - * optional string rule_key = 10; - */ - java.lang.String getRuleKey(); - /** - * optional string rule_key = 10; - */ - com.google.protobuf.ByteString - getRuleKeyBytes(); - - /** - * optional string alert_status = 12; - */ - boolean hasAlertStatus(); - /** - * optional string alert_status = 12; - */ - java.lang.String getAlertStatus(); - /** - * optional string alert_status = 12; - */ - com.google.protobuf.ByteString - getAlertStatusBytes(); - - /** - * optional string alert_text = 13; - */ - boolean hasAlertText(); - /** - * optional string alert_text = 13; - */ - java.lang.String getAlertText(); - /** - * optional string alert_text = 13; - */ - com.google.protobuf.ByteString - getAlertTextBytes(); - /** * optional double variation_value_1 = 14; */ @@ -3901,15 +4144,6 @@ public final class BatchReport { */ double getVariationValue5(); - /** - * optional int32 characteric_id = 19; - */ - boolean hasCharactericId(); - /** - * optional int32 characteric_id = 19; - */ - int getCharactericId(); - /** * optional int32 person_id = 20; */ @@ -4020,56 +4254,33 @@ public final class BatchReport { description_ = bs; break; } - case 82: { - com.google.protobuf.ByteString bs = input.readBytes(); - bitField0_ |= 0x00000100; - ruleKey_ = bs; - break; - } - case 98: { - com.google.protobuf.ByteString bs = input.readBytes(); - bitField0_ |= 0x00000200; - alertStatus_ = bs; - break; - } - case 106: { - com.google.protobuf.ByteString bs = input.readBytes(); - bitField0_ |= 0x00000400; - alertText_ = bs; - break; - } case 113: { - bitField0_ |= 0x00000800; + bitField0_ |= 0x00000100; variationValue1_ = input.readDouble(); break; } case 121: { - bitField0_ |= 0x00001000; + bitField0_ |= 0x00000200; variationValue2_ = input.readDouble(); break; } case 129: { - bitField0_ |= 0x00002000; + bitField0_ |= 0x00000400; variationValue3_ = input.readDouble(); break; } case 137: { - bitField0_ |= 0x00004000; + bitField0_ |= 0x00000800; variationValue4_ = input.readDouble(); break; } case 145: { - bitField0_ |= 0x00008000; + bitField0_ |= 0x00001000; variationValue5_ = input.readDouble(); break; } - case 152: { - bitField0_ |= 0x00010000; - charactericId_ = input.readInt32(); - break; - } case 160: { - bitField0_ |= 0x00020000; + bitField0_ |= 0x00002000; personId_ = input.readInt32(); break; } @@ -4334,157 +4545,31 @@ public final class BatchReport { } } - public static final int RULE_KEY_FIELD_NUMBER = 10; - private java.lang.Object ruleKey_; + public static final int VARIATION_VALUE_1_FIELD_NUMBER = 14; + private double variationValue1_; /** - * optional string rule_key = 10; + * optional double variation_value_1 = 14; */ - public boolean hasRuleKey() { + public boolean hasVariationValue1() { return ((bitField0_ & 0x00000100) == 0x00000100); } /** - * optional string rule_key = 10; - */ - public java.lang.String getRuleKey() { - java.lang.Object ref = ruleKey_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - if (bs.isValidUtf8()) { - ruleKey_ = s; - } - return s; - } - } - /** - * optional string rule_key = 10; + * optional double variation_value_1 = 14; */ - public com.google.protobuf.ByteString - getRuleKeyBytes() { - java.lang.Object ref = ruleKey_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - ruleKey_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } + public double getVariationValue1() { + return variationValue1_; } - public static final int ALERT_STATUS_FIELD_NUMBER = 12; - private java.lang.Object alertStatus_; + public static final int VARIATION_VALUE_2_FIELD_NUMBER = 15; + private double variationValue2_; /** - * optional string alert_status = 12; + * optional double variation_value_2 = 15; */ - public boolean hasAlertStatus() { + public boolean hasVariationValue2() { return ((bitField0_ & 0x00000200) == 0x00000200); } /** - * optional string alert_status = 12; - */ - public java.lang.String getAlertStatus() { - java.lang.Object ref = alertStatus_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - if (bs.isValidUtf8()) { - alertStatus_ = s; - } - return s; - } - } - /** - * optional string alert_status = 12; - */ - public com.google.protobuf.ByteString - getAlertStatusBytes() { - java.lang.Object ref = alertStatus_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - alertStatus_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int ALERT_TEXT_FIELD_NUMBER = 13; - private java.lang.Object alertText_; - /** - * optional string alert_text = 13; - */ - public boolean hasAlertText() { - return ((bitField0_ & 0x00000400) == 0x00000400); - } - /** - * optional string alert_text = 13; - */ - public java.lang.String getAlertText() { - java.lang.Object ref = alertText_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - if (bs.isValidUtf8()) { - alertText_ = s; - } - return s; - } - } - /** - * optional string alert_text = 13; - */ - public com.google.protobuf.ByteString - getAlertTextBytes() { - java.lang.Object ref = alertText_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - alertText_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int VARIATION_VALUE_1_FIELD_NUMBER = 14; - private double variationValue1_; - /** - * optional double variation_value_1 = 14; - */ - public boolean hasVariationValue1() { - return ((bitField0_ & 0x00000800) == 0x00000800); - } - /** - * optional double variation_value_1 = 14; - */ - public double getVariationValue1() { - return variationValue1_; - } - - public static final int VARIATION_VALUE_2_FIELD_NUMBER = 15; - private double variationValue2_; - /** - * optional double variation_value_2 = 15; - */ - public boolean hasVariationValue2() { - return ((bitField0_ & 0x00001000) == 0x00001000); - } - /** - * optional double variation_value_2 = 15; + * optional double variation_value_2 = 15; */ public double getVariationValue2() { return variationValue2_; @@ -4496,7 +4581,7 @@ public final class BatchReport { * optional double variation_value_3 = 16; */ public boolean hasVariationValue3() { - return ((bitField0_ & 0x00002000) == 0x00002000); + return ((bitField0_ & 0x00000400) == 0x00000400); } /** * optional double variation_value_3 = 16; @@ -4511,7 +4596,7 @@ public final class BatchReport { * optional double variation_value_4 = 17; */ public boolean hasVariationValue4() { - return ((bitField0_ & 0x00004000) == 0x00004000); + return ((bitField0_ & 0x00000800) == 0x00000800); } /** * optional double variation_value_4 = 17; @@ -4526,7 +4611,7 @@ public final class BatchReport { * optional double variation_value_5 = 18; */ public boolean hasVariationValue5() { - return ((bitField0_ & 0x00008000) == 0x00008000); + return ((bitField0_ & 0x00001000) == 0x00001000); } /** * optional double variation_value_5 = 18; @@ -4535,28 +4620,13 @@ public final class BatchReport { return variationValue5_; } - public static final int CHARACTERIC_ID_FIELD_NUMBER = 19; - private int charactericId_; - /** - * optional int32 characteric_id = 19; - */ - public boolean hasCharactericId() { - return ((bitField0_ & 0x00010000) == 0x00010000); - } - /** - * optional int32 characteric_id = 19; - */ - public int getCharactericId() { - return charactericId_; - } - public static final int PERSON_ID_FIELD_NUMBER = 20; private int personId_; /** * optional int32 person_id = 20; */ public boolean hasPersonId() { - return ((bitField0_ & 0x00020000) == 0x00020000); + return ((bitField0_ & 0x00002000) == 0x00002000); } /** * optional int32 person_id = 20; @@ -4574,15 +4644,11 @@ public final class BatchReport { stringValue_ = ""; metricKey_ = ""; description_ = ""; - ruleKey_ = ""; - alertStatus_ = ""; - alertText_ = ""; variationValue1_ = 0D; variationValue2_ = 0D; variationValue3_ = 0D; variationValue4_ = 0D; variationValue5_ = 0D; - charactericId_ = 0; personId_ = 0; } private byte memoizedIsInitialized = -1; @@ -4623,33 +4689,21 @@ public final class BatchReport { output.writeBytes(9, getDescriptionBytes()); } if (((bitField0_ & 0x00000100) == 0x00000100)) { - output.writeBytes(10, getRuleKeyBytes()); - } - if (((bitField0_ & 0x00000200) == 0x00000200)) { - output.writeBytes(12, getAlertStatusBytes()); - } - if (((bitField0_ & 0x00000400) == 0x00000400)) { - output.writeBytes(13, getAlertTextBytes()); - } - if (((bitField0_ & 0x00000800) == 0x00000800)) { output.writeDouble(14, variationValue1_); } - if (((bitField0_ & 0x00001000) == 0x00001000)) { + if (((bitField0_ & 0x00000200) == 0x00000200)) { output.writeDouble(15, variationValue2_); } - if (((bitField0_ & 0x00002000) == 0x00002000)) { + if (((bitField0_ & 0x00000400) == 0x00000400)) { output.writeDouble(16, variationValue3_); } - if (((bitField0_ & 0x00004000) == 0x00004000)) { + if (((bitField0_ & 0x00000800) == 0x00000800)) { output.writeDouble(17, variationValue4_); } - if (((bitField0_ & 0x00008000) == 0x00008000)) { + if (((bitField0_ & 0x00001000) == 0x00001000)) { output.writeDouble(18, variationValue5_); } - if (((bitField0_ & 0x00010000) == 0x00010000)) { - output.writeInt32(19, charactericId_); - } - if (((bitField0_ & 0x00020000) == 0x00020000)) { + if (((bitField0_ & 0x00002000) == 0x00002000)) { output.writeInt32(20, personId_); } getUnknownFields().writeTo(output); @@ -4694,42 +4748,26 @@ public final class BatchReport { .computeBytesSize(9, getDescriptionBytes()); } if (((bitField0_ & 0x00000100) == 0x00000100)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(10, getRuleKeyBytes()); - } - if (((bitField0_ & 0x00000200) == 0x00000200)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(12, getAlertStatusBytes()); - } - if (((bitField0_ & 0x00000400) == 0x00000400)) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(13, getAlertTextBytes()); - } - if (((bitField0_ & 0x00000800) == 0x00000800)) { size += com.google.protobuf.CodedOutputStream .computeDoubleSize(14, variationValue1_); } - if (((bitField0_ & 0x00001000) == 0x00001000)) { + if (((bitField0_ & 0x00000200) == 0x00000200)) { size += com.google.protobuf.CodedOutputStream .computeDoubleSize(15, variationValue2_); } - if (((bitField0_ & 0x00002000) == 0x00002000)) { + if (((bitField0_ & 0x00000400) == 0x00000400)) { size += com.google.protobuf.CodedOutputStream .computeDoubleSize(16, variationValue3_); } - if (((bitField0_ & 0x00004000) == 0x00004000)) { + if (((bitField0_ & 0x00000800) == 0x00000800)) { size += com.google.protobuf.CodedOutputStream .computeDoubleSize(17, variationValue4_); } - if (((bitField0_ & 0x00008000) == 0x00008000)) { + if (((bitField0_ & 0x00001000) == 0x00001000)) { size += com.google.protobuf.CodedOutputStream .computeDoubleSize(18, variationValue5_); } - if (((bitField0_ & 0x00010000) == 0x00010000)) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(19, charactericId_); - } - if (((bitField0_ & 0x00020000) == 0x00020000)) { + if (((bitField0_ & 0x00002000) == 0x00002000)) { size += com.google.protobuf.CodedOutputStream .computeInt32Size(20, personId_); } @@ -4866,26 +4904,18 @@ public final class BatchReport { bitField0_ = (bitField0_ & ~0x00000040); description_ = ""; bitField0_ = (bitField0_ & ~0x00000080); - ruleKey_ = ""; - bitField0_ = (bitField0_ & ~0x00000100); - alertStatus_ = ""; - bitField0_ = (bitField0_ & ~0x00000200); - alertText_ = ""; - bitField0_ = (bitField0_ & ~0x00000400); variationValue1_ = 0D; - bitField0_ = (bitField0_ & ~0x00000800); + bitField0_ = (bitField0_ & ~0x00000100); variationValue2_ = 0D; - bitField0_ = (bitField0_ & ~0x00001000); + bitField0_ = (bitField0_ & ~0x00000200); variationValue3_ = 0D; - bitField0_ = (bitField0_ & ~0x00002000); + bitField0_ = (bitField0_ & ~0x00000400); variationValue4_ = 0D; - bitField0_ = (bitField0_ & ~0x00004000); + bitField0_ = (bitField0_ & ~0x00000800); variationValue5_ = 0D; - bitField0_ = (bitField0_ & ~0x00008000); - charactericId_ = 0; - bitField0_ = (bitField0_ & ~0x00010000); + bitField0_ = (bitField0_ & ~0x00001000); personId_ = 0; - bitField0_ = (bitField0_ & ~0x00020000); + bitField0_ = (bitField0_ & ~0x00002000); return this; } @@ -4949,42 +4979,26 @@ public final class BatchReport { if (((from_bitField0_ & 0x00000100) == 0x00000100)) { to_bitField0_ |= 0x00000100; } - result.ruleKey_ = ruleKey_; + result.variationValue1_ = variationValue1_; if (((from_bitField0_ & 0x00000200) == 0x00000200)) { to_bitField0_ |= 0x00000200; } - result.alertStatus_ = alertStatus_; + result.variationValue2_ = variationValue2_; if (((from_bitField0_ & 0x00000400) == 0x00000400)) { to_bitField0_ |= 0x00000400; } - result.alertText_ = alertText_; + result.variationValue3_ = variationValue3_; if (((from_bitField0_ & 0x00000800) == 0x00000800)) { to_bitField0_ |= 0x00000800; } - result.variationValue1_ = variationValue1_; + result.variationValue4_ = variationValue4_; if (((from_bitField0_ & 0x00001000) == 0x00001000)) { to_bitField0_ |= 0x00001000; } - result.variationValue2_ = variationValue2_; + result.variationValue5_ = variationValue5_; if (((from_bitField0_ & 0x00002000) == 0x00002000)) { to_bitField0_ |= 0x00002000; } - result.variationValue3_ = variationValue3_; - if (((from_bitField0_ & 0x00004000) == 0x00004000)) { - to_bitField0_ |= 0x00004000; - } - result.variationValue4_ = variationValue4_; - if (((from_bitField0_ & 0x00008000) == 0x00008000)) { - to_bitField0_ |= 0x00008000; - } - result.variationValue5_ = variationValue5_; - if (((from_bitField0_ & 0x00010000) == 0x00010000)) { - to_bitField0_ |= 0x00010000; - } - result.charactericId_ = charactericId_; - if (((from_bitField0_ & 0x00020000) == 0x00020000)) { - to_bitField0_ |= 0x00020000; - } result.personId_ = personId_; result.bitField0_ = to_bitField0_; onBuilt(); @@ -5032,21 +5046,6 @@ public final class BatchReport { description_ = other.description_; onChanged(); } - if (other.hasRuleKey()) { - bitField0_ |= 0x00000100; - ruleKey_ = other.ruleKey_; - onChanged(); - } - if (other.hasAlertStatus()) { - bitField0_ |= 0x00000200; - alertStatus_ = other.alertStatus_; - onChanged(); - } - if (other.hasAlertText()) { - bitField0_ |= 0x00000400; - alertText_ = other.alertText_; - onChanged(); - } if (other.hasVariationValue1()) { setVariationValue1(other.getVariationValue1()); } @@ -5062,9 +5061,6 @@ public final class BatchReport { if (other.hasVariationValue5()) { setVariationValue5(other.getVariationValue5()); } - if (other.hasCharactericId()) { - setCharactericId(other.getCharactericId()); - } if (other.hasPersonId()) { setPersonId(other.getPersonId()); } @@ -5526,240 +5522,12 @@ public final class BatchReport { return this; } - private java.lang.Object ruleKey_ = ""; - /** - * optional string rule_key = 10; - */ - public boolean hasRuleKey() { - return ((bitField0_ & 0x00000100) == 0x00000100); - } - /** - * optional string rule_key = 10; - */ - public java.lang.String getRuleKey() { - java.lang.Object ref = ruleKey_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - if (bs.isValidUtf8()) { - ruleKey_ = s; - } - return s; - } else { - return (java.lang.String) ref; - } - } - /** - * optional string rule_key = 10; - */ - public com.google.protobuf.ByteString - getRuleKeyBytes() { - java.lang.Object ref = ruleKey_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - ruleKey_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - * optional string rule_key = 10; - */ - public Builder setRuleKey( - java.lang.String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000100; - ruleKey_ = value; - onChanged(); - return this; - } - /** - * optional string rule_key = 10; - */ - public Builder clearRuleKey() { - bitField0_ = (bitField0_ & ~0x00000100); - ruleKey_ = getDefaultInstance().getRuleKey(); - onChanged(); - return this; - } - /** - * optional string rule_key = 10; - */ - public Builder setRuleKeyBytes( - com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000100; - ruleKey_ = value; - onChanged(); - return this; - } - - private java.lang.Object alertStatus_ = ""; - /** - * optional string alert_status = 12; - */ - public boolean hasAlertStatus() { - return ((bitField0_ & 0x00000200) == 0x00000200); - } - /** - * optional string alert_status = 12; - */ - public java.lang.String getAlertStatus() { - java.lang.Object ref = alertStatus_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - if (bs.isValidUtf8()) { - alertStatus_ = s; - } - return s; - } else { - return (java.lang.String) ref; - } - } - /** - * optional string alert_status = 12; - */ - public com.google.protobuf.ByteString - getAlertStatusBytes() { - java.lang.Object ref = alertStatus_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - alertStatus_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - * optional string alert_status = 12; - */ - public Builder setAlertStatus( - java.lang.String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000200; - alertStatus_ = value; - onChanged(); - return this; - } - /** - * optional string alert_status = 12; - */ - public Builder clearAlertStatus() { - bitField0_ = (bitField0_ & ~0x00000200); - alertStatus_ = getDefaultInstance().getAlertStatus(); - onChanged(); - return this; - } - /** - * optional string alert_status = 12; - */ - public Builder setAlertStatusBytes( - com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000200; - alertStatus_ = value; - onChanged(); - return this; - } - - private java.lang.Object alertText_ = ""; - /** - * optional string alert_text = 13; - */ - public boolean hasAlertText() { - return ((bitField0_ & 0x00000400) == 0x00000400); - } - /** - * optional string alert_text = 13; - */ - public java.lang.String getAlertText() { - java.lang.Object ref = alertText_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - if (bs.isValidUtf8()) { - alertText_ = s; - } - return s; - } else { - return (java.lang.String) ref; - } - } - /** - * optional string alert_text = 13; - */ - public com.google.protobuf.ByteString - getAlertTextBytes() { - java.lang.Object ref = alertText_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - alertText_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - * optional string alert_text = 13; - */ - public Builder setAlertText( - java.lang.String value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000400; - alertText_ = value; - onChanged(); - return this; - } - /** - * optional string alert_text = 13; - */ - public Builder clearAlertText() { - bitField0_ = (bitField0_ & ~0x00000400); - alertText_ = getDefaultInstance().getAlertText(); - onChanged(); - return this; - } - /** - * optional string alert_text = 13; - */ - public Builder setAlertTextBytes( - com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - bitField0_ |= 0x00000400; - alertText_ = value; - onChanged(); - return this; - } - private double variationValue1_ ; /** * optional double variation_value_1 = 14; */ public boolean hasVariationValue1() { - return ((bitField0_ & 0x00000800) == 0x00000800); + return ((bitField0_ & 0x00000100) == 0x00000100); } /** * optional double variation_value_1 = 14; @@ -5771,7 +5539,7 @@ public final class BatchReport { * optional double variation_value_1 = 14; */ public Builder setVariationValue1(double value) { - bitField0_ |= 0x00000800; + bitField0_ |= 0x00000100; variationValue1_ = value; onChanged(); return this; @@ -5780,7 +5548,7 @@ public final class BatchReport { * optional double variation_value_1 = 14; */ public Builder clearVariationValue1() { - bitField0_ = (bitField0_ & ~0x00000800); + bitField0_ = (bitField0_ & ~0x00000100); variationValue1_ = 0D; onChanged(); return this; @@ -5791,7 +5559,7 @@ public final class BatchReport { * optional double variation_value_2 = 15; */ public boolean hasVariationValue2() { - return ((bitField0_ & 0x00001000) == 0x00001000); + return ((bitField0_ & 0x00000200) == 0x00000200); } /** * optional double variation_value_2 = 15; @@ -5803,7 +5571,7 @@ public final class BatchReport { * optional double variation_value_2 = 15; */ public Builder setVariationValue2(double value) { - bitField0_ |= 0x00001000; + bitField0_ |= 0x00000200; variationValue2_ = value; onChanged(); return this; @@ -5812,7 +5580,7 @@ public final class BatchReport { * optional double variation_value_2 = 15; */ public Builder clearVariationValue2() { - bitField0_ = (bitField0_ & ~0x00001000); + bitField0_ = (bitField0_ & ~0x00000200); variationValue2_ = 0D; onChanged(); return this; @@ -5823,7 +5591,7 @@ public final class BatchReport { * optional double variation_value_3 = 16; */ public boolean hasVariationValue3() { - return ((bitField0_ & 0x00002000) == 0x00002000); + return ((bitField0_ & 0x00000400) == 0x00000400); } /** * optional double variation_value_3 = 16; @@ -5835,7 +5603,7 @@ public final class BatchReport { * optional double variation_value_3 = 16; */ public Builder setVariationValue3(double value) { - bitField0_ |= 0x00002000; + bitField0_ |= 0x00000400; variationValue3_ = value; onChanged(); return this; @@ -5844,7 +5612,7 @@ public final class BatchReport { * optional double variation_value_3 = 16; */ public Builder clearVariationValue3() { - bitField0_ = (bitField0_ & ~0x00002000); + bitField0_ = (bitField0_ & ~0x00000400); variationValue3_ = 0D; onChanged(); return this; @@ -5855,7 +5623,7 @@ public final class BatchReport { * optional double variation_value_4 = 17; */ public boolean hasVariationValue4() { - return ((bitField0_ & 0x00004000) == 0x00004000); + return ((bitField0_ & 0x00000800) == 0x00000800); } /** * optional double variation_value_4 = 17; @@ -5867,7 +5635,7 @@ public final class BatchReport { * optional double variation_value_4 = 17; */ public Builder setVariationValue4(double value) { - bitField0_ |= 0x00004000; + bitField0_ |= 0x00000800; variationValue4_ = value; onChanged(); return this; @@ -5876,7 +5644,7 @@ public final class BatchReport { * optional double variation_value_4 = 17; */ public Builder clearVariationValue4() { - bitField0_ = (bitField0_ & ~0x00004000); + bitField0_ = (bitField0_ & ~0x00000800); variationValue4_ = 0D; onChanged(); return this; @@ -5887,7 +5655,7 @@ public final class BatchReport { * optional double variation_value_5 = 18; */ public boolean hasVariationValue5() { - return ((bitField0_ & 0x00008000) == 0x00008000); + return ((bitField0_ & 0x00001000) == 0x00001000); } /** * optional double variation_value_5 = 18; @@ -5899,7 +5667,7 @@ public final class BatchReport { * optional double variation_value_5 = 18; */ public Builder setVariationValue5(double value) { - bitField0_ |= 0x00008000; + bitField0_ |= 0x00001000; variationValue5_ = value; onChanged(); return this; @@ -5908,50 +5676,18 @@ public final class BatchReport { * optional double variation_value_5 = 18; */ public Builder clearVariationValue5() { - bitField0_ = (bitField0_ & ~0x00008000); + bitField0_ = (bitField0_ & ~0x00001000); variationValue5_ = 0D; onChanged(); return this; } - private int charactericId_ ; - /** - * optional int32 characteric_id = 19; - */ - public boolean hasCharactericId() { - return ((bitField0_ & 0x00010000) == 0x00010000); - } - /** - * optional int32 characteric_id = 19; - */ - public int getCharactericId() { - return charactericId_; - } - /** - * optional int32 characteric_id = 19; - */ - public Builder setCharactericId(int value) { - bitField0_ |= 0x00010000; - charactericId_ = value; - onChanged(); - return this; - } - /** - * optional int32 characteric_id = 19; - */ - public Builder clearCharactericId() { - bitField0_ = (bitField0_ & ~0x00010000); - charactericId_ = 0; - onChanged(); - return this; - } - private int personId_ ; /** * optional int32 person_id = 20; */ public boolean hasPersonId() { - return ((bitField0_ & 0x00020000) == 0x00020000); + return ((bitField0_ & 0x00002000) == 0x00002000); } /** * optional int32 person_id = 20; @@ -5963,7 +5699,7 @@ public final class BatchReport { * optional int32 person_id = 20; */ public Builder setPersonId(int value) { - bitField0_ |= 0x00020000; + bitField0_ |= 0x00002000; personId_ = value; onChanged(); return this; @@ -5972,7 +5708,7 @@ public final class BatchReport { * optional int32 person_id = 20; */ public Builder clearPersonId() { - bitField0_ = (bitField0_ & ~0x00020000); + bitField0_ = (bitField0_ & ~0x00002000); personId_ = 0; onChanged(); return this; @@ -19705,66 +19441,64 @@ public final class BatchReport { descriptor; static { java.lang.String[] descriptorData = { - "\n\022batch_report.proto\032\017constants.proto\"b\n" + + "\n\022batch_report.proto\032\017constants.proto\"{\n" + "\010Metadata\022\025\n\ranalysis_date\030\001 \001(\003\022\023\n\013proj" + "ect_key\030\002 \001(\t\022\016\n\006branch\030\003 \001(\t\022\032\n\022root_co" + - "mponent_ref\030\004 \001(\005\"?\n\rComponentLink\022 \n\004ty" + - "pe\030\001 \001(\0162\022.ComponentLinkType\022\014\n\004href\030\002 \001" + - "(\t\"\354\001\n\tComponent\022\013\n\003ref\030\001 \001(\005\022\014\n\004path\030\002 " + - "\001(\t\022\014\n\004name\030\003 \001(\t\022\034\n\004type\030\004 \001(\0162\016.Compon" + - "entType\022\017\n\007is_test\030\005 \001(\010\022\020\n\010language\030\006 \001" + - "(\t\022\025\n\tchild_ref\030\007 \003(\005B\002\020\001\022\034\n\004link\030\010 \003(\0132" + - "\016.ComponentLink\022\017\n\007version\030\t \001(\t\022\013\n\003key\030", - "\n \001(\t\022\r\n\005lines\030\013 \001(\005\022\023\n\013description\030\014 \001(" + - "\t\"\261\003\n\007Measure\022%\n\nvalue_type\030\001 \001(\0162\021.Meas" + - "ureValueType\022\025\n\rboolean_value\030\002 \001(\010\022\021\n\ti" + - "nt_value\030\003 \001(\005\022\022\n\nlong_value\030\004 \001(\003\022\024\n\014do" + - "uble_value\030\005 \001(\001\022\024\n\014string_value\030\006 \001(\t\022\022" + - "\n\nmetric_key\030\007 \001(\t\022\023\n\013description\030\t \001(\t\022" + - "\020\n\010rule_key\030\n \001(\t\022\024\n\014alert_status\030\014 \001(\t\022" + - "\022\n\nalert_text\030\r \001(\t\022\031\n\021variation_value_1" + - "\030\016 \001(\001\022\031\n\021variation_value_2\030\017 \001(\001\022\031\n\021var" + - "iation_value_3\030\020 \001(\001\022\031\n\021variation_value_", - "4\030\021 \001(\001\022\031\n\021variation_value_5\030\022 \001(\001\022\026\n\016ch" + - "aracteric_id\030\023 \001(\005\022\021\n\tperson_id\030\024 \001(\005\"<\n" + - "\010Measures\022\025\n\rcomponent_ref\030\001 \001(\005\022\031\n\007meas" + - "ure\030\002 \003(\0132\010.Measure\"\273\001\n\005Issue\022\027\n\017rule_re" + - "pository\030\001 \001(\t\022\020\n\010rule_key\030\002 \001(\t\022\014\n\004line" + - "\030\003 \001(\005\022\013\n\003msg\030\004 \001(\t\022\033\n\010severity\030\005 \001(\0162\t." + - "Severity\022\013\n\003tag\030\006 \003(\t\022\025\n\reffort_to_fix\030\007" + - " \001(\001\022\022\n\nattributes\030\010 \001(\t\022\027\n\017debt_in_minu" + - "tes\030\t \001(\003\"6\n\006Issues\022\025\n\rcomponent_ref\030\001 \001" + - "(\005\022\025\n\005issue\030\002 \003(\0132\006.Issue\"\254\001\n\nChangesets", - "\022\025\n\rcomponent_ref\030\001 \001(\005\022(\n\tchangeset\030\002 \003" + - "(\0132\025.Changesets.Changeset\022 \n\024changesetIn" + - "dexByLine\030\003 \003(\005B\002\020\001\032;\n\tChangeset\022\020\n\010revi" + - "sion\030\001 \001(\t\022\016\n\006author\030\002 \001(\t\022\014\n\004date\030\003 \001(\003" + - "\"R\n\tDuplicate\022\026\n\016other_file_ref\030\001 \001(\005\022\025\n" + - "\005range\030\002 \001(\0132\006.Range\022\026\n\016other_file_key\030\003" + - " \001(\t\"M\n\013Duplication\022\037\n\017origin_position\030\001" + - " \001(\0132\006.Range\022\035\n\tduplicate\030\002 \003(\0132\n.Duplic" + - "ate\"H\n\014Duplications\022\025\n\rcomponent_ref\030\001 \001" + - "(\005\022!\n\013duplication\030\002 \003(\0132\014.Duplication\"W\n", - "\005Range\022\022\n\nstart_line\030\001 \001(\005\022\020\n\010end_line\030\002" + - " \001(\005\022\024\n\014start_offset\030\003 \001(\005\022\022\n\nend_offset" + - "\030\004 \001(\005\"~\n\007Symbols\022\020\n\010file_ref\030\001 \001(\005\022\037\n\006s" + - "ymbol\030\002 \003(\0132\017.Symbols.Symbol\032@\n\006Symbol\022\033" + - "\n\013declaration\030\001 \001(\0132\006.Range\022\031\n\treference" + - "\030\002 \003(\0132\006.Range\"\260\001\n\010Coverage\022\014\n\004line\030\001 \001(" + - "\005\022\022\n\nconditions\030\002 \001(\005\022\017\n\007ut_hits\030\003 \001(\010\022\017" + - "\n\007it_hits\030\004 \001(\010\022\035\n\025ut_covered_conditions" + - "\030\005 \001(\005\022\035\n\025it_covered_conditions\030\006 \001(\005\022\"\n" + - "\032overall_covered_conditions\030\007 \001(\005\"L\n\022Syn", - "taxHighlighting\022\025\n\005range\030\001 \001(\0132\006.Range\022\037" + - "\n\004type\030\002 \001(\0162\021.HighlightingType\"j\n\004Test\022" + - "\014\n\004name\030\001 \001(\t\022\033\n\006status\030\002 \001(\0162\013.TestStat" + - "us\022\026\n\016duration_in_ms\030\003 \001(\003\022\022\n\nstacktrace" + - "\030\004 \001(\t\022\013\n\003msg\030\005 \001(\t\"\221\001\n\016CoverageDetail\022\021" + - "\n\ttest_name\030\001 \001(\t\0221\n\014covered_file\030\002 \003(\0132" + - "\033.CoverageDetail.CoveredFile\0329\n\013CoveredF" + - "ile\022\020\n\010file_ref\030\001 \001(\005\022\030\n\014covered_line\030\002 " + - "\003(\005B\002\020\001B#\n\037org.sonar.batch.protocol.outp" + - "utH\001" + "mponent_ref\030\004 \001(\005\022\027\n\017active_rule_key\030\005 \003" + + "(\t\"?\n\rComponentLink\022 \n\004type\030\001 \001(\0162\022.Comp" + + "onentLinkType\022\014\n\004href\030\002 \001(\t\"\354\001\n\tComponen" + + "t\022\013\n\003ref\030\001 \001(\005\022\014\n\004path\030\002 \001(\t\022\014\n\004name\030\003 \001" + + "(\t\022\034\n\004type\030\004 \001(\0162\016.ComponentType\022\017\n\007is_t" + + "est\030\005 \001(\010\022\020\n\010language\030\006 \001(\t\022\025\n\tchild_ref" + + "\030\007 \003(\005B\002\020\001\022\034\n\004link\030\010 \003(\0132\016.ComponentLink", + "\022\017\n\007version\030\t \001(\t\022\013\n\003key\030\n \001(\t\022\r\n\005lines\030" + + "\013 \001(\005\022\023\n\013description\030\014 \001(\t\"\335\002\n\007Measure\022%" + + "\n\nvalue_type\030\001 \001(\0162\021.MeasureValueType\022\025\n" + + "\rboolean_value\030\002 \001(\010\022\021\n\tint_value\030\003 \001(\005\022" + + "\022\n\nlong_value\030\004 \001(\003\022\024\n\014double_value\030\005 \001(" + + "\001\022\024\n\014string_value\030\006 \001(\t\022\022\n\nmetric_key\030\007 " + + "\001(\t\022\023\n\013description\030\t \001(\t\022\031\n\021variation_va" + + "lue_1\030\016 \001(\001\022\031\n\021variation_value_2\030\017 \001(\001\022\031" + + "\n\021variation_value_3\030\020 \001(\001\022\031\n\021variation_v" + + "alue_4\030\021 \001(\001\022\031\n\021variation_value_5\030\022 \001(\001\022", + "\021\n\tperson_id\030\024 \001(\005\"<\n\010Measures\022\025\n\rcompon" + + "ent_ref\030\001 \001(\005\022\031\n\007measure\030\002 \003(\0132\010.Measure" + + "\"\273\001\n\005Issue\022\027\n\017rule_repository\030\001 \001(\t\022\020\n\010r" + + "ule_key\030\002 \001(\t\022\014\n\004line\030\003 \001(\005\022\013\n\003msg\030\004 \001(\t" + + "\022\033\n\010severity\030\005 \001(\0162\t.Severity\022\013\n\003tag\030\006 \003" + + "(\t\022\025\n\reffort_to_fix\030\007 \001(\001\022\022\n\nattributes\030" + + "\010 \001(\t\022\027\n\017debt_in_minutes\030\t \001(\003\"6\n\006Issues" + + "\022\025\n\rcomponent_ref\030\001 \001(\005\022\025\n\005issue\030\002 \003(\0132\006" + + ".Issue\"\254\001\n\nChangesets\022\025\n\rcomponent_ref\030\001" + + " \001(\005\022(\n\tchangeset\030\002 \003(\0132\025.Changesets.Cha", + "ngeset\022 \n\024changesetIndexByLine\030\003 \003(\005B\002\020\001" + + "\032;\n\tChangeset\022\020\n\010revision\030\001 \001(\t\022\016\n\006autho" + + "r\030\002 \001(\t\022\014\n\004date\030\003 \001(\003\"R\n\tDuplicate\022\026\n\016ot" + + "her_file_ref\030\001 \001(\005\022\025\n\005range\030\002 \001(\0132\006.Rang" + + "e\022\026\n\016other_file_key\030\003 \001(\t\"M\n\013Duplication" + + "\022\037\n\017origin_position\030\001 \001(\0132\006.Range\022\035\n\tdup" + + "licate\030\002 \003(\0132\n.Duplicate\"H\n\014Duplications" + + "\022\025\n\rcomponent_ref\030\001 \001(\005\022!\n\013duplication\030\002" + + " \003(\0132\014.Duplication\"W\n\005Range\022\022\n\nstart_lin" + + "e\030\001 \001(\005\022\020\n\010end_line\030\002 \001(\005\022\024\n\014start_offse", + "t\030\003 \001(\005\022\022\n\nend_offset\030\004 \001(\005\"~\n\007Symbols\022\020" + + "\n\010file_ref\030\001 \001(\005\022\037\n\006symbol\030\002 \003(\0132\017.Symbo" + + "ls.Symbol\032@\n\006Symbol\022\033\n\013declaration\030\001 \001(\013" + + "2\006.Range\022\031\n\treference\030\002 \003(\0132\006.Range\"\260\001\n\010" + + "Coverage\022\014\n\004line\030\001 \001(\005\022\022\n\nconditions\030\002 \001" + + "(\005\022\017\n\007ut_hits\030\003 \001(\010\022\017\n\007it_hits\030\004 \001(\010\022\035\n\025" + + "ut_covered_conditions\030\005 \001(\005\022\035\n\025it_covere" + + "d_conditions\030\006 \001(\005\022\"\n\032overall_covered_co" + + "nditions\030\007 \001(\005\"L\n\022SyntaxHighlighting\022\025\n\005" + + "range\030\001 \001(\0132\006.Range\022\037\n\004type\030\002 \001(\0162\021.High", + "lightingType\"j\n\004Test\022\014\n\004name\030\001 \001(\t\022\033\n\006st" + + "atus\030\002 \001(\0162\013.TestStatus\022\026\n\016duration_in_m" + + "s\030\003 \001(\003\022\022\n\nstacktrace\030\004 \001(\t\022\013\n\003msg\030\005 \001(\t" + + "\"\221\001\n\016CoverageDetail\022\021\n\ttest_name\030\001 \001(\t\0221" + + "\n\014covered_file\030\002 \003(\0132\033.CoverageDetail.Co" + + "veredFile\0329\n\013CoveredFile\022\020\n\010file_ref\030\001 \001" + + "(\005\022\030\n\014covered_line\030\002 \003(\005B\002\020\001B#\n\037org.sona" + + "r.batch.protocol.outputH\001" }; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() { @@ -19784,7 +19518,7 @@ public final class BatchReport { internal_static_Metadata_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_Metadata_descriptor, - new java.lang.String[] { "AnalysisDate", "ProjectKey", "Branch", "RootComponentRef", }); + new java.lang.String[] { "AnalysisDate", "ProjectKey", "Branch", "RootComponentRef", "ActiveRuleKey", }); internal_static_ComponentLink_descriptor = getDescriptor().getMessageTypes().get(1); internal_static_ComponentLink_fieldAccessorTable = new @@ -19802,7 +19536,7 @@ public final class BatchReport { internal_static_Measure_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_Measure_descriptor, - new java.lang.String[] { "ValueType", "BooleanValue", "IntValue", "LongValue", "DoubleValue", "StringValue", "MetricKey", "Description", "RuleKey", "AlertStatus", "AlertText", "VariationValue1", "VariationValue2", "VariationValue3", "VariationValue4", "VariationValue5", "CharactericId", "PersonId", }); + new java.lang.String[] { "ValueType", "BooleanValue", "IntValue", "LongValue", "DoubleValue", "StringValue", "MetricKey", "Description", "VariationValue1", "VariationValue2", "VariationValue3", "VariationValue4", "VariationValue5", "PersonId", }); internal_static_Measures_descriptor = getDescriptor().getMessageTypes().get(4); internal_static_Measures_fieldAccessorTable = new diff --git a/sonar-batch-protocol/src/main/protobuf/batch_report.proto b/sonar-batch-protocol/src/main/protobuf/batch_report.proto index 0ecee214e93..361c0419fff 100644 --- a/sonar-batch-protocol/src/main/protobuf/batch_report.proto +++ b/sonar-batch-protocol/src/main/protobuf/batch_report.proto @@ -45,6 +45,13 @@ message Metadata { optional string project_key = 2; optional string branch = 3; optional int32 root_component_ref = 4; + + /* + Keys of the rules that were enabled in Quality profiles. + A key is a string composed of the repository and the subKey, specific to the repository. Format is + "{repository}:{subKey}", for instance "java:NullDereference". + */ + repeated string active_rule_key = 5; } message ComponentLink { @@ -84,15 +91,11 @@ message Measure { // temporary fields during development of computation stack optional string description = 9; - optional string rule_key = 10; - optional string alert_status = 12; - optional string alert_text = 13; optional double variation_value_1 = 14; optional double variation_value_2 = 15; optional double variation_value_3 = 16; optional double variation_value_4 = 17; optional double variation_value_5 = 18; - optional int32 characteric_id = 19; optional int32 person_id = 20; } 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(); } diff --git a/sonar-core/src/main/java/org/sonar/core/dashboard/ActiveDashboardDao.java b/sonar-core/src/main/java/org/sonar/core/dashboard/ActiveDashboardDao.java index 7ac05f224f6..cfacc608706 100644 --- a/sonar-core/src/main/java/org/sonar/core/dashboard/ActiveDashboardDao.java +++ b/sonar-core/src/main/java/org/sonar/core/dashboard/ActiveDashboardDao.java @@ -19,17 +19,13 @@ */ package org.sonar.core.dashboard; +import java.util.List; +import javax.annotation.Nullable; import org.apache.ibatis.session.SqlSession; -import org.sonar.api.batch.BatchSide; import org.sonar.api.server.ServerSide; import org.sonar.core.persistence.DaoComponent; import org.sonar.core.persistence.MyBatis; -import javax.annotation.Nullable; - -import java.util.List; - -@BatchSide @ServerSide public class ActiveDashboardDao implements DaoComponent { diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/ActionPlanDao.java b/sonar-core/src/main/java/org/sonar/core/issue/db/ActionPlanDao.java index 774956178fe..cc75c1e1a93 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/db/ActionPlanDao.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/db/ActionPlanDao.java @@ -21,22 +21,16 @@ package org.sonar.core.issue.db; import com.google.common.collect.Lists; +import java.util.Collection; +import java.util.Collections; +import java.util.List; import org.apache.ibatis.session.SqlSession; -import org.sonar.api.batch.BatchSide; import org.sonar.api.server.ServerSide; import org.sonar.core.persistence.DaoComponent; import org.sonar.core.persistence.MyBatis; -import java.util.Collection; -import java.util.Collections; -import java.util.List; - import static com.google.common.collect.Lists.newArrayList; -/** - * @since 3.6 - */ -@BatchSide @ServerSide public class ActionPlanDao implements DaoComponent { diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueChangeDao.java b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueChangeDao.java index a400a04c9cd..3e7c21e8d23 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueChangeDao.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueChangeDao.java @@ -21,28 +21,20 @@ package org.sonar.core.issue.db; import com.google.common.collect.Lists; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.Map; import javax.annotation.CheckForNull; -import org.apache.ibatis.session.ResultHandler; -import org.sonar.api.batch.BatchSide; +import org.sonar.api.server.ServerSide; import org.sonar.core.issue.DefaultIssueComment; import org.sonar.core.issue.FieldDiffs; -import org.sonar.api.server.ServerSide; import org.sonar.core.persistence.DaoComponent; import org.sonar.core.persistence.DbSession; import org.sonar.core.persistence.MyBatis; import static com.google.common.collect.Lists.newArrayList; -import static com.google.common.collect.Maps.newHashMap; +import static java.util.Arrays.asList; -/** - * @since 3.6 - */ -@BatchSide @ServerSide public class IssueChangeDao implements DaoComponent { @@ -64,7 +56,7 @@ public class IssueChangeDao implements DaoComponent { DbSession session = mybatis.openSession(false); try { List result = Lists.newArrayList(); - for (IssueChangeDto dto : selectByIssuesAndType(session, Arrays.asList(issueKey), IssueChangeDto.TYPE_FIELD_CHANGE)) { + for (IssueChangeDto dto : selectByIssuesAndType(session, asList(issueKey), IssueChangeDto.TYPE_FIELD_CHANGE)) { result.add(dto.toFieldDiffs()); } return result; @@ -73,13 +65,11 @@ public class IssueChangeDao implements DaoComponent { } } - public void selectChangelogOnNonClosedIssuesByModuleAndType(long componentId, ResultHandler handler) { + public List selectChangelogOfUnresolvedIssuesByComponent(String componentUuid) { DbSession session = mybatis.openSession(false); try { - Map params = newHashMap(); - params.put("componentId", componentId); - params.put("changeType", IssueChangeDto.TYPE_FIELD_CHANGE); - session.select("org.sonar.core.issue.db.IssueChangeMapper.selectChangelogOnNonClosedIssuesByModuleAndType", params, handler); + IssueChangeMapper mapper = session.getMapper(IssueChangeMapper.class); + return mapper.selectChangelogOfUnresolvedIssuesByComponent(componentUuid, IssueChangeDto.TYPE_FIELD_CHANGE); } finally { MyBatis.closeQuietly(session); diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueChangeMapper.java b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueChangeMapper.java index cadf024cda4..732ddc5c75b 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueChangeMapper.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueChangeMapper.java @@ -20,15 +20,10 @@ package org.sonar.core.issue.db; -import org.apache.ibatis.annotations.Param; - -import javax.annotation.CheckForNull; - import java.util.List; +import javax.annotation.CheckForNull; +import org.apache.ibatis.annotations.Param; -/** - * @since 3.6 - */ public interface IssueChangeMapper { void insert(IssueChangeDto dto); @@ -38,13 +33,13 @@ public interface IssueChangeMapper { int update(IssueChangeDto change); @CheckForNull - IssueChangeDto selectByKeyAndType(@Param("key") String key, - @Param("changeType") String type); + IssueChangeDto selectByKeyAndType(@Param("key") String key, @Param("changeType") String type); + /** * Issue changes by chronological date of creation */ List selectByIssuesAndType(@Param("issueKeys") List issueKeys, - @Param("changeType") String changeType); + @Param("changeType") String changeType); - List selectByIssue(String issueKey); + List selectChangelogOfUnresolvedIssuesByComponent(@Param("componentUuid") String componentUuid, @Param("changeType") String changeType); } diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java index 44baff06b8c..ec3b3b60cea 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java @@ -661,6 +661,7 @@ public final class IssueDto implements Serializable { issue.setEffortToFix(effortToFix); issue.setDebt(debt != null ? Duration.create(debt) : null); issue.setLine(line); + issue.setChecksum(checksum); issue.setSeverity(severity); issue.setReporter(reporter); issue.setAssignee(assignee); diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueMapper.java b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueMapper.java index aba2531071e..a3a8f61c490 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueMapper.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueMapper.java @@ -26,7 +26,7 @@ public interface IssueMapper { IssueDto selectByKey(String key); - List selectOpenByComponentUuid(String componentUuid); + List selectNonClosedByComponentUuid(String componentUuid); Set selectComponentUuidsOfOpenIssuesForProjectUuid(String projectUuid); diff --git a/sonar-core/src/main/java/org/sonar/core/issue/tracking/LazyInput.java b/sonar-core/src/main/java/org/sonar/core/issue/tracking/LazyInput.java index 0406c631f09..2a5dc580a81 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/tracking/LazyInput.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/tracking/LazyInput.java @@ -31,7 +31,7 @@ public abstract class LazyInput implements Input @Override public LineHashSequence getLineHashSequence() { if (lineHashSeq == null) { - lineHashSeq = LineHashSequence.createForLines(loadSourceLines()); + lineHashSeq = loadLineHashSequence(); } return lineHashSeq; } @@ -52,7 +52,7 @@ public abstract class LazyInput implements Input return issues; } - protected abstract Iterable loadSourceLines(); + protected abstract LineHashSequence loadLineHashSequence(); protected abstract List loadIssues(); } diff --git a/sonar-core/src/main/java/org/sonar/core/issue/tracking/Tracker.java b/sonar-core/src/main/java/org/sonar/core/issue/tracking/Tracker.java index 8691757440c..5da2ca5da04 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/tracking/Tracker.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/tracking/Tracker.java @@ -27,7 +27,9 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Objects; import javax.annotation.Nonnull; +import org.apache.commons.lang.StringUtils; import org.sonar.api.rule.RuleKey; +import org.sonar.api.utils.log.Loggers; import static com.google.common.collect.FluentIterable.from; @@ -43,7 +45,7 @@ public class Tracker { detectCodeMoves(rawInput, baseInput, tracking); // 3. match issues with same rule, same message and same line hash - match(tracking, LineHashAndMessagekeyFactory.INSTANCE); + match(tracking, LineHashAndMessageKeyFactory.INSTANCE); // 4. match issues with same rule, same line and same message match(tracking, LineAndMessageKeyFactory.INSTANCE); @@ -135,7 +137,7 @@ public class Tracker { LineAndLineHashKey(Trackable trackable) { this.ruleKey = trackable.getRuleKey(); this.line = trackable.getLine(); - this.lineHash = trackable.getLineHash(); + this.lineHash = StringUtils.defaultString(trackable.getLineHash(), ""); } @Override @@ -178,7 +180,7 @@ public class Tracker { LineHashAndMessageKey(Trackable trackable) { this.ruleKey = trackable.getRuleKey(); this.message = trackable.getMessage(); - this.lineHash = trackable.getLineHash(); + this.lineHash = StringUtils.defaultString(trackable.getLineHash(), ""); } @Override @@ -206,7 +208,7 @@ public class Tracker { } } - private enum LineHashAndMessagekeyFactory implements SearchKeyFactory { + private enum LineHashAndMessageKeyFactory implements SearchKeyFactory { INSTANCE; @Override public SearchKey create(Trackable t) { diff --git a/sonar-core/src/main/java/org/sonar/core/issue/tracking/Tracking.java b/sonar-core/src/main/java/org/sonar/core/issue/tracking/Tracking.java index 27f34ac3887..f2a5306e500 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/tracking/Tracking.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/tracking/Tracking.java @@ -19,6 +19,7 @@ */ package org.sonar.core.issue.tracking; +import com.google.common.base.Objects; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import java.util.Collection; @@ -53,14 +54,7 @@ public class Tracking { private final Multimap openManualIssues = ArrayListMultimap.create(); public Tracking(Input rawInput, Input baseInput) { - for (RAW raw : rawInput.getIssues()) { - // Extra verification if some plugins create issues on wrong lines - Integer rawLine = raw.getLine(); - if (rawLine != null && !rawInput.getLineHashSequence().hasLine(rawLine)) { - throw new IllegalArgumentException("Issue line is not valid: " + raw); - } - this.unmatchedRaws.add(raw); - } + this.unmatchedRaws.addAll(rawInput.getIssues()); this.unmatchedBases.addAll(baseInput.getIssues()); } @@ -90,15 +84,24 @@ public class Tracking { void associateRawToBase(RAW raw, BASE base) { rawToBase.put(raw, base); - unmatchedBases.remove(base); + if (!unmatchedBases.remove(base)) { + throw new IllegalStateException(String.format("Fail to associate base issue %s to %s among %s", base, raw, this)); + } } void markRawAsAssociated(RAW raw) { - unmatchedRaws.remove(raw); + if (!unmatchedRaws.remove(raw)) { + throw new IllegalStateException(String.format("Fail to mark issue as associated: %s among %s", raw, this)); + } } void markRawsAsAssociated(Collection c) { - unmatchedRaws.removeAll(c); + // important : do not use unmatchedRaws.removeAll(Collection) as it's buggy. See: + // http://stackoverflow.com/questions/19682542/why-identityhashmap-keyset-removeallkeys-does-not-use-identity-is-it-a-bug/19682543#19682543 + // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6588783 + for (RAW raw : c) { + markRawAsAssociated(raw); + } } boolean isComplete() { @@ -113,4 +116,14 @@ public class Tracking { openManualIssues.put(line, manualIssue); unmatchedBases.remove(manualIssue); } + + @Override + public String toString() { + return Objects.toStringHelper(this) + .add("rawToBase", rawToBase) + .add("unmatchedRaws", unmatchedRaws) + .add("unmatchedBases", unmatchedBases) + .add("openManualIssues", openManualIssues) + .toString(); + } } diff --git a/sonar-core/src/main/java/org/sonar/core/issue/workflow/SetClosed.java b/sonar-core/src/main/java/org/sonar/core/issue/workflow/SetClosed.java index cee06ac4181..49b874220e7 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/workflow/SetClosed.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/workflow/SetClosed.java @@ -29,7 +29,7 @@ public enum SetClosed implements Function { public void execute(Context context) { DefaultIssue issue = (DefaultIssue) context.issue(); if (!issue.isBeingClosed()) { - throw new IllegalStateException("Issue is still alive: " + issue); + throw new IllegalStateException("Issue is still open: " + issue); } if (issue.isOnDisabledRule()) { context.setResolution(Issue.RESOLUTION_REMOVED); diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/DaoComponent.java b/sonar-core/src/main/java/org/sonar/core/persistence/DaoComponent.java index da0a5f12224..09849be20fb 100644 --- a/sonar-core/src/main/java/org/sonar/core/persistence/DaoComponent.java +++ b/sonar-core/src/main/java/org/sonar/core/persistence/DaoComponent.java @@ -19,8 +19,5 @@ */ package org.sonar.core.persistence; -/** - * @since 4.4 - */ public interface DaoComponent { } diff --git a/sonar-core/src/main/java/org/sonar/core/technicaldebt/DefaultTechnicalDebtModel.java b/sonar-core/src/main/java/org/sonar/core/technicaldebt/DefaultTechnicalDebtModel.java deleted file mode 100644 index a7016a55947..00000000000 --- a/sonar-core/src/main/java/org/sonar/core/technicaldebt/DefaultTechnicalDebtModel.java +++ /dev/null @@ -1,128 +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.core.technicaldebt; - -import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; -import org.sonar.api.batch.RequiresDB; -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.rule.RuleKey; -import org.sonar.api.technicaldebt.batch.TechnicalDebtModel; -import org.sonar.api.technicaldebt.batch.internal.DefaultCharacteristic; -import org.sonar.api.technicaldebt.batch.internal.DefaultRequirement; - -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; - -import java.util.Collections; -import java.util.List; - -import static com.google.common.collect.Lists.newArrayList; - -@RequiresDB -public class DefaultTechnicalDebtModel implements TechnicalDebtModel { - - private final DebtModel model; - - public DefaultTechnicalDebtModel(DebtModel model) { - this.model = model; - } - - public List rootCharacteristics() { - return newArrayList(Iterables.filter(characteristics(), new Predicate() { - @Override - public boolean apply(DefaultCharacteristic input) { - return input.isRoot(); - } - })); - } - - @Override - @CheckForNull - public DefaultCharacteristic characteristicByKey(final String key) { - return Iterables.find(characteristics(), new Predicate() { - @Override - public boolean apply(DefaultCharacteristic input) { - return input.key().equals(key); - } - }, null); - } - - @Override - @CheckForNull - public DefaultCharacteristic characteristicById(final Integer id) { - return Iterables.find(characteristics(), new Predicate() { - @Override - public boolean apply(DefaultCharacteristic input) { - return input.id().equals(id); - } - }, null); - } - - @Override - @CheckForNull - public DefaultRequirement requirementsByRule(final RuleKey ruleKey) { - return null; - } - - @Override - @CheckForNull - public DefaultRequirement requirementsById(final Integer id) { - return null; - } - - @Override - public List characteristics() { - List flatCharacteristics = newArrayList(); - for (DebtCharacteristic characteristic : model.characteristics()) { - DefaultCharacteristic root = toDefaultCharacteristic((DefaultDebtCharacteristic) characteristic, null); - flatCharacteristics.add(root); - for (DebtCharacteristic subCharacteristic : model.subCharacteristics(characteristic.key())) { - flatCharacteristics.add(toDefaultCharacteristic((DefaultDebtCharacteristic) subCharacteristic, root)); - } - } - return flatCharacteristics; - } - - @Override - public List requirements() { - return Collections.emptyList(); - } - - public boolean isEmpty() { - return model.allCharacteristics().isEmpty(); - } - - private static DefaultCharacteristic toDefaultCharacteristic(DefaultDebtCharacteristic debtCharacteristic, @Nullable DefaultCharacteristic parentCharacteristic) { - return new DefaultCharacteristic() - .setId(debtCharacteristic.id()) - .setKey(debtCharacteristic.key()) - .setName(debtCharacteristic.name()) - .setOrder(debtCharacteristic.order()) - .setParent(parentCharacteristic) - .setRoot(parentCharacteristic) - .setCreatedAt(debtCharacteristic.createdAt()) - .setUpdatedAt(debtCharacteristic.updatedAt()); - } - -} diff --git a/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueChangeMapper.xml b/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueChangeMapper.xml index 47d0bc96d71..e810f1dc33c 100644 --- a/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueChangeMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueChangeMapper.xml @@ -1,6 +1,6 @@ - + @@ -43,20 +43,6 @@ order by c.created_at - - + + diff --git a/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml b/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml index 50eb94db4d3..a6511b06329 100644 --- a/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml @@ -148,36 +148,13 @@ where i.kee=#{kee} - select - i.id, - i.kee as kee, - i.rule_id as ruleId, - i.action_plan_key as actionPlanKey, - i.severity as severity, - i.manual_severity as manualSeverity, - i.message as message, - i.line as line, - i.effort_to_fix as effortToFix, - i.technical_debt as debt, - i.status as status, - i.resolution as resolution, - i.checksum as checksum, - i.reporter as reporter, - i.assignee as assignee, - i.author_login as authorLogin, - i.tags as tagsString, - i.issue_attributes as issueAttributes, - i.issue_creation_date as issueCreationTime, - i.issue_update_date as issueUpdateTime, - i.issue_close_date as issueCloseTime, - i.created_at as createdAt, - i.updated_at as updatedAt, - r.plugin_rule_key as ruleKey, - i.component_uuid as componentUuid, - i.project_uuid as projectUuid + from issues i inner join rules r on r.id=i.rule_id + inner join projects p on p.uuid=i.component_uuid + inner join projects root on root.uuid=i.project_uuid where i.component_uuid=#{componentUuid} and i.status <> 'CLOSED' diff --git a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueChangeDaoTest.java b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueChangeDaoTest.java index 411048b421e..2d379cfee6c 100644 --- a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueChangeDaoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueChangeDaoTest.java @@ -19,21 +19,19 @@ */ package org.sonar.core.issue.db; -import org.apache.ibatis.executor.result.DefaultResultHandler; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.sonar.api.utils.DateUtils; import org.sonar.core.issue.DefaultIssueComment; import org.sonar.core.issue.FieldDiffs; -import org.sonar.api.utils.DateUtils; import org.sonar.core.persistence.AbstractDaoTestCase; import org.sonar.core.persistence.DbSession; import org.sonar.core.persistence.MyBatis; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - import static com.google.common.collect.Lists.newArrayList; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -115,45 +113,11 @@ public class IssueChangeDaoTest extends AbstractDaoTestCase { } @Test - public void select_issue_changelog_by_module() { - setupData("select_issue_changelog_by_module"); - - // 400 is a non-root module, we should find 2 + 1 changelog from classes and one on itself - DefaultResultHandler handler = new DefaultResultHandler(); - dao.selectChangelogOnNonClosedIssuesByModuleAndType(400, handler); - assertThat(handler.getResultList()).hasSize(4); - - IssueChangeDto issueChangeDto = (IssueChangeDto) handler.getResultList().get(0); - assertThat(issueChangeDto.getId()).isNotNull(); - assertThat(issueChangeDto.getKey()).isNotNull(); - assertThat(issueChangeDto.getIssueKey()).isNotNull(); - assertThat(issueChangeDto.getUserLogin()).isNotNull(); - assertThat(issueChangeDto.getChangeType()).isNotNull(); - assertThat(issueChangeDto.getChangeData()).isNotNull(); - assertThat(issueChangeDto.getCreatedAt()).isNotNull(); - assertThat(issueChangeDto.getUpdatedAt()).isNotNull(); - - for (Object changeDtoObject : handler.getResultList()) { - IssueChangeDto changeDto = (IssueChangeDto) changeDtoObject; - assertThat(changeDto.getChangeType()).isEqualTo(IssueChangeDto.TYPE_FIELD_CHANGE); - } + public void selectChangelogOfUnresolvedIssuesByComponent() { + setupData("selectChangelogOfUnresolvedIssuesByComponent"); - // 399 is the root module, we should only find 1 changelog on itself - handler = new DefaultResultHandler(); - dao.selectChangelogOnNonClosedIssuesByModuleAndType(399, handler); - assertThat(handler.getResultList()).hasSize(1); - } - - @Test - public void select_issue_changelog_by_module_should_be_sorted_by_creation_date() { - setupData("select_issue_changelog_by_module_are_sorted_by_creation_date"); - - DefaultResultHandler handler = new DefaultResultHandler(); - dao.selectChangelogOnNonClosedIssuesByModuleAndType(399, handler); - assertThat(handler.getResultList()).hasSize(3); - assertThat(((IssueChangeDto) handler.getResultList().get(0)).getId()).isEqualTo(1001); - assertThat(((IssueChangeDto) handler.getResultList().get(1)).getId()).isEqualTo(1002); - assertThat(((IssueChangeDto) handler.getResultList().get(2)).getId()).isEqualTo(1000); + List dtos = dao.selectChangelogOfUnresolvedIssuesByComponent("FILE_1"); + assertThat(dtos).extracting("id").containsExactly(100L); } @Test diff --git a/sonar-core/src/test/java/org/sonar/core/issue/tracking/TrackerTest.java b/sonar-core/src/test/java/org/sonar/core/issue/tracking/TrackerTest.java index 37391225a84..a9fe647095e 100644 --- a/sonar-core/src/test/java/org/sonar/core/issue/tracking/TrackerTest.java +++ b/sonar-core/src/test/java/org/sonar/core/issue/tracking/TrackerTest.java @@ -196,13 +196,13 @@ public class TrackerTest { } @Test - public void fail_if_raw_line_does_not_exist() throws Exception { + public void do_not_fail_if_raw_line_does_not_exist() throws Exception { FakeInput baseInput = new FakeInput(); FakeInput rawInput = new FakeInput("H1").addIssue(new Issue(200, "H200", RULE_SYSTEM_PRINT, "msg")); - thrown.expect(IllegalArgumentException.class); - thrown.expectMessage("Issue line is not valid"); - tracker.track(rawInput, baseInput); + Tracking tracking = tracker.track(rawInput, baseInput); + + assertThat(tracking.getUnmatchedRaws()).hasSize(1); } /** @@ -406,7 +406,7 @@ public class TrackerTest { private final List issues = new ArrayList<>(); private final List lineHashes; - public FakeInput(String... lineHashes) { + FakeInput(String... lineHashes) { this.lineHashes = asList(lineHashes); } @@ -418,7 +418,7 @@ public class TrackerTest { return new FakeInput(hashes); } - public Issue createIssueOnLine(int line, RuleKey ruleKey, String message) { + Issue createIssueOnLine(int line, RuleKey ruleKey, String message) { Issue issue = new Issue(line, lineHashes.get(line - 1), ruleKey, message); issues.add(issue); return issue; @@ -427,13 +427,13 @@ public class TrackerTest { /** * No line (line 0) */ - public Issue createIssue(RuleKey ruleKey, String message) { + Issue createIssue(RuleKey ruleKey, String message) { Issue issue = new Issue(null, "", ruleKey, message); issues.add(issue); return issue; } - public FakeInput addIssue(Issue issue) { + FakeInput addIssue(Issue issue) { this.issues.add(issue); return this; } diff --git a/sonar-core/src/test/java/org/sonar/core/issue/workflow/SetClosedTest.java b/sonar-core/src/test/java/org/sonar/core/issue/workflow/SetClosedTest.java index 84e46786292..3418cd9d1d3 100644 --- a/sonar-core/src/test/java/org/sonar/core/issue/workflow/SetClosedTest.java +++ b/sonar-core/src/test/java/org/sonar/core/issue/workflow/SetClosedTest.java @@ -56,7 +56,7 @@ public class SetClosedTest { INSTANCE.execute(context); fail(); } catch (IllegalStateException e) { - assertThat(e.getMessage()).contains("Issue is still alive"); + assertThat(e.getMessage()).contains("Issue is still open"); verify(context, never()).setResolution(anyString()); } } diff --git a/sonar-core/src/test/java/org/sonar/core/technicaldebt/DefaultTechnicalDebtModelTest.java b/sonar-core/src/test/java/org/sonar/core/technicaldebt/DefaultTechnicalDebtModelTest.java deleted file mode 100644 index 3ea3a311fda..00000000000 --- a/sonar-core/src/test/java/org/sonar/core/technicaldebt/DefaultTechnicalDebtModelTest.java +++ /dev/null @@ -1,100 +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.core.technicaldebt; - -import org.junit.Before; -import org.junit.Test; -import org.sonar.api.batch.debt.internal.DefaultDebtCharacteristic; -import org.sonar.api.batch.debt.internal.DefaultDebtModel; -import org.sonar.api.rule.RuleKey; -import org.sonar.api.technicaldebt.batch.internal.DefaultCharacteristic; - -import static org.assertj.core.api.Assertions.assertThat; - -public class DefaultTechnicalDebtModelTest { - - private DefaultTechnicalDebtModel sqaleModel; - - @Before - public void setUp() { - DefaultDebtModel debtModel = new DefaultDebtModel(); - debtModel.addCharacteristic( - new DefaultDebtCharacteristic().setId(1) - .setKey("MEMORY_EFFICIENCY") - .setName("Memory use") - .setOrder(1) - ); - debtModel.addSubCharacteristic( - new DefaultDebtCharacteristic().setId(2) - .setKey("EFFICIENCY") - .setName("Efficiency") - .setParentId(1), - "MEMORY_EFFICIENCY" - ); - sqaleModel = new DefaultTechnicalDebtModel(debtModel); - } - - @Test - public void get_characteristics() { - assertThat(sqaleModel.rootCharacteristics()).hasSize(1); - - DefaultCharacteristic resultRootCharacteristic = sqaleModel.rootCharacteristics().get(0); - assertThat(resultRootCharacteristic.id()).isEqualTo(1); - assertThat(resultRootCharacteristic.key()).isEqualTo("MEMORY_EFFICIENCY"); - assertThat(resultRootCharacteristic.name()).isEqualTo("Memory use"); - assertThat(resultRootCharacteristic.order()).isEqualTo(1); - assertThat(resultRootCharacteristic.children()).hasSize(1); - assertThat(resultRootCharacteristic.parent()).isNull(); - assertThat(resultRootCharacteristic.root()).isNull(); - } - - @Test - public void get_characteristic_by_key() { - assertThat(sqaleModel.characteristicByKey("MEMORY_EFFICIENCY")).isNotNull(); - assertThat(sqaleModel.characteristicByKey("EFFICIENCY")).isNotNull(); - assertThat(sqaleModel.characteristicByKey("EFFICIENCY").parent()).isNotNull(); - - assertThat(sqaleModel.characteristicByKey("UNKNOWN")).isNull(); - } - - @Test - public void characteristic_by_id() { - assertThat(sqaleModel.characteristicById(1)).isNotNull(); - assertThat(sqaleModel.characteristicById(2)).isNotNull(); - assertThat(sqaleModel.characteristicById(123)).isNull(); - } - - @Test - public void get_requirement_by_rule_key_always_return_null() { - assertThat(sqaleModel.requirementsByRule(RuleKey.of("checkstyle", "Regexp"))).isNull(); - } - - @Test - public void get_requirement_by_id_always_return_null() { - assertThat(sqaleModel.requirementsById(1)).isNull(); - } - - @Test - public void get_requirements_always_return_empty_list() { - assertThat(sqaleModel.requirements()).isEmpty(); - } - -} diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/selectChangelogOfUnresolvedIssuesByComponent.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/selectChangelogOfUnresolvedIssuesByComponent.xml new file mode 100644 index 00000000000..966f7c31cac --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/selectChangelogOfUnresolvedIssuesByComponent.xml @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/select_issue_changelog_by_module.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/select_issue_changelog_by_module.xml deleted file mode 100644 index fd4ee9c31d0..00000000000 --- a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/select_issue_changelog_by_module.xml +++ /dev/null @@ -1,222 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/select_issue_changelog_by_module_are_sorted_by_creation_date.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/select_issue_changelog_by_module_are_sorted_by_creation_date.xml deleted file mode 100644 index b019869a390..00000000000 --- a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueChangeDaoTest/select_issue_changelog_by_module_are_sorted_by_creation_date.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/Rule.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/Rule.java index d0a6cec8a44..0866cb8b203 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/Rule.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/Rule.java @@ -19,13 +19,12 @@ */ package org.sonar.api.batch.rule; +import java.util.Collection; +import javax.annotation.CheckForNull; import org.sonar.api.batch.debt.DebtRemediationFunction; import org.sonar.api.rule.RuleKey; import org.sonar.api.rule.RuleStatus; -import javax.annotation.CheckForNull; -import java.util.Collection; - /** * @since 4.2 */ @@ -50,14 +49,6 @@ public interface Rule { RuleStatus status(); - /** - * Sub characteristic key. - * - * @since 4.3 - */ - @CheckForNull - String debtSubCharacteristic(); - /** * Remediation function : can by Linear (with a coefficient), Linear with offset (with a coefficient and an offset) or Constant per issue (with an offset) * diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/internal/DefaultRule.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/internal/DefaultRule.java index 4493449e62f..097694e146c 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/internal/DefaultRule.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/internal/DefaultRule.java @@ -41,7 +41,6 @@ public class DefaultRule implements Rule { private final String severity; private final String description; private final String internalKey; - private final String debtSubCharacteristic; private final RuleStatus status; private final DebtRemediationFunction debtRemediationFunction; private final Map params; @@ -54,7 +53,6 @@ public class DefaultRule implements Rule { this.description = newRule.description; this.internalKey = newRule.internalKey; this.status = newRule.status; - this.debtSubCharacteristic = newRule.debtSubCharacteristic; this.debtRemediationFunction = newRule.debtRemediationFunction; ImmutableMap.Builder builder = ImmutableMap.builder(); @@ -99,11 +97,6 @@ public class DefaultRule implements Rule { return status; } - @Override - public String debtSubCharacteristic() { - return debtSubCharacteristic; - } - @Override public DebtRemediationFunction debtRemediationFunction() { return debtRemediationFunction; diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/internal/NewRule.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/internal/NewRule.java index 3572315f472..2e174b2b2ae 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/internal/NewRule.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/internal/NewRule.java @@ -41,7 +41,6 @@ public class NewRule { String description; String severity = DEFAULT_SEVERITY; String internalKey; - String debtSubCharacteristic; DebtRemediationFunction debtRemediationFunction; RuleStatus status = RuleStatus.defaultStatus(); Map params = new HashMap<>(); @@ -80,11 +79,6 @@ public class NewRule { return this; } - public NewRule setDebtSubCharacteristic(@Nullable String c) { - this.debtSubCharacteristic = c; - return this; - } - public NewRule setDebtRemediationFunction(@Nullable DebtRemediationFunction f) { this.debtRemediationFunction = f; return this; diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java index b5f423c257e..391cc49eb99 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java @@ -20,18 +20,16 @@ package org.sonar.api.measures; import com.google.common.annotations.Beta; -import org.apache.commons.lang.builder.ReflectionToStringBuilder; -import org.apache.commons.lang.math.NumberUtils; -import org.sonar.api.technicaldebt.batch.Characteristic; -import org.sonar.api.technicaldebt.batch.Requirement; - -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; - import java.io.Serializable; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.Date; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.apache.commons.lang.builder.ReflectionToStringBuilder; +import org.apache.commons.lang.math.NumberUtils; +import org.sonar.api.technicaldebt.batch.Characteristic; +import org.sonar.api.technicaldebt.batch.Requirement; /** * A class to handle measures. @@ -62,8 +60,6 @@ public class Measure implements Serializable { protected Double variation4; protected Double variation5; protected String url; - protected Characteristic characteristic; - protected Requirement requirement; protected Integer personId; protected PersistenceMode persistenceMode = PersistenceMode.FULL; private boolean fromCore; @@ -631,14 +627,13 @@ public class Measure implements Serializable { */ @CheckForNull public final Characteristic getCharacteristic() { - return characteristic; + return null; } /** * @since 4.1 */ public final Measure setCharacteristic(@Nullable Characteristic characteristic) { - this.characteristic = characteristic; return this; } @@ -649,7 +644,7 @@ public class Measure implements Serializable { @Deprecated @CheckForNull public final Requirement getRequirement() { - return requirement; + return null; } /** @@ -658,7 +653,6 @@ public class Measure implements Serializable { */ @Deprecated public final Measure setRequirement(@Nullable Requirement requirement) { - this.requirement = requirement; return this; } @@ -737,16 +731,12 @@ public class Measure implements Serializable { if (metricKey != null ? !metricKey.equals(measure.metricKey) : (measure.metricKey != null)) { return false; } - if (characteristic != null ? !characteristic.equals(measure.characteristic) : (measure.characteristic != null)) { - return false; - } return !(personId != null ? !personId.equals(measure.personId) : (measure.personId != null)); } @Override public int hashCode() { int result = metricKey != null ? metricKey.hashCode() : 0; - result = 31 * result + (characteristic != null ? characteristic.hashCode() : 0); result = 31 * result + (personId != null ? personId.hashCode() : 0); return result; } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/batch/TechnicalDebtModel.java b/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/batch/TechnicalDebtModel.java deleted file mode 100644 index 39f551dbbd2..00000000000 --- a/sonar-plugin-api/src/main/java/org/sonar/api/technicaldebt/batch/TechnicalDebtModel.java +++ /dev/null @@ -1,70 +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.api.technicaldebt.batch; - -import org.sonar.api.batch.BatchSide; -import org.sonar.api.rule.RuleKey; -import org.sonar.api.technicaldebt.batch.internal.DefaultCharacteristic; - -import javax.annotation.CheckForNull; - -import java.util.List; - -/** - * @since 4.1 - * @deprecated since 4.3 - */ -@Deprecated -@BatchSide -public interface TechnicalDebtModel { - - @CheckForNull - Characteristic characteristicById(Integer id); - - @CheckForNull - Characteristic characteristicByKey(String key); - - /** - * @deprecated since 4.3. Always return null - */ - @CheckForNull - @Deprecated - Requirement requirementsByRule(RuleKey ruleKey); - - /** - * @deprecated since 4.3. Always return null - */ - @CheckForNull - @Deprecated - Requirement requirementsById(Integer id); - - /** - * @deprecated since 4.3. Always return empty list - */ - @Deprecated - List requirements(); - - /** - * @since 4.3 - */ - List characteristics(); - -} diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/rule/internal/RulesBuilderTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/rule/internal/RulesBuilderTest.java index a64550d7b09..3c5270f6996 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/rule/internal/RulesBuilderTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/rule/internal/RulesBuilderTest.java @@ -51,7 +51,6 @@ public class RulesBuilderTest { newSquid1.setInternalKey("foo=bar"); newSquid1.setSeverity(Severity.CRITICAL); newSquid1.setStatus(RuleStatus.BETA); - newSquid1.setDebtSubCharacteristic("COMPILER"); newSquid1.setDebtRemediationFunction(DebtRemediationFunction.create(DebtRemediationFunction.Type.LINEAR_OFFSET, Duration.create(10), Duration.create(60))); newSquid1.addParam("min"); newSquid1.addParam("max").setDescription("Maximum"); @@ -74,11 +73,9 @@ public class RulesBuilderTest { assertThat(squid1.internalKey()).isEqualTo("foo=bar"); assertThat(squid1.status()).isEqualTo(RuleStatus.BETA); assertThat(squid1.severity()).isEqualTo(Severity.CRITICAL); - assertThat(squid1.debtSubCharacteristic()).isEqualTo("COMPILER"); assertThat(squid1.debtRemediationFunction().type()).isEqualTo(DebtRemediationFunction.Type.LINEAR_OFFSET); assertThat(squid1.debtRemediationFunction().coefficient()).isEqualTo(Duration.create(10)); assertThat(squid1.debtRemediationFunction().offset()).isEqualTo(Duration.create(60)); - assertThat(squid1.debtSubCharacteristic()).isEqualTo("COMPILER"); assertThat(squid1.params()).hasSize(2); assertThat(squid1.param("min").key()).isEqualTo("min"); assertThat(squid1.param("min").description()).isNull(); @@ -92,7 +89,6 @@ public class RulesBuilderTest { assertThat(squid2.internalKey()).isNull(); assertThat(squid2.status()).isEqualTo(RuleStatus.defaultStatus()); assertThat(squid2.severity()).isEqualTo(Severity.defaultSeverity()); - assertThat(squid2.debtSubCharacteristic()).isNull(); assertThat(squid2.debtRemediationFunction()).isNull(); assertThat(squid2.params()).isEmpty(); } -- 2.39.5