diff options
author | Simon Brandhof <simon.brandhof@sonarsource.com> | 2015-07-02 20:01:59 +0200 |
---|---|---|
committer | Simon Brandhof <simon.brandhof@sonarsource.com> | 2015-07-02 20:01:59 +0200 |
commit | be9b5a2ea93b7959cbaa4a630bff79467b3ba8d0 (patch) | |
tree | 03fad10de15f1cf9d64199e32bfa3b90158035ea /sonar-batch | |
parent | e154f3cf3e73c0ba447fffef1d447dc729f8bf9b (diff) | |
parent | 1c0b9a97e3bc6d58c4697b4350b39adc81a6efc1 (diff) | |
download | sonarqube-be9b5a2ea93b7959cbaa4a630bff79467b3ba8d0.tar.gz sonarqube-be9b5a2ea93b7959cbaa4a630bff79467b3ba8d0.zip |
Merge branch 'feature/ce_issue_tracking'
Diffstat (limited to 'sonar-batch')
65 files changed, 267 insertions, 4355 deletions
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 d40e1c223f7..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,13 +37,7 @@ 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.DebtDecorator; -import org.sonar.batch.debt.IssueChangelogDebtCalculator; -import org.sonar.batch.debt.NewDebtDecorator; -import org.sonar.batch.issue.tracking.InitialOpenIssuesSensor; -import org.sonar.batch.issue.tracking.IssueHandlers; import org.sonar.batch.issue.tracking.IssueTracking; -import org.sonar.batch.issue.tracking.IssueTrackingDecorator; import org.sonar.batch.language.LanguageDistributionDecorator; import org.sonar.batch.scan.report.ConsoleReport; import org.sonar.batch.scan.report.HtmlReport; @@ -87,16 +81,6 @@ public class BatchComponents { // language LanguageDistributionDecorator.class, - // Debt - IssueChangelogDebtCalculator.class, - DebtDecorator.class, - NewDebtDecorator.class, - - // Issue tracking - IssueTrackingDecorator.class, - IssueHandlers.class, - InitialOpenIssuesSensor.class, - // to be moved to compute engine UnitTestDecorator.class, LineCoverageDecorator.class, diff --git a/sonar-batch/src/main/java/org/sonar/batch/compute/SeverityUtils.java b/sonar-batch/src/main/java/org/sonar/batch/compute/SeverityUtils.java deleted file mode 100644 index fd92039ce98..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/compute/SeverityUtils.java +++ /dev/null @@ -1,66 +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.compute; - -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Metric; -import org.sonar.api.rules.RulePriority; - -final class SeverityUtils { - private SeverityUtils() { - // only static methods - } - - static Metric severityToIssueMetric(RulePriority severity) { - Metric metric; - if (severity.equals(RulePriority.BLOCKER)) { - metric = CoreMetrics.BLOCKER_VIOLATIONS; - } else if (severity.equals(RulePriority.CRITICAL)) { - metric = CoreMetrics.CRITICAL_VIOLATIONS; - } else if (severity.equals(RulePriority.MAJOR)) { - metric = CoreMetrics.MAJOR_VIOLATIONS; - } else if (severity.equals(RulePriority.MINOR)) { - metric = CoreMetrics.MINOR_VIOLATIONS; - } else if (severity.equals(RulePriority.INFO)) { - metric = CoreMetrics.INFO_VIOLATIONS; - } else { - throw new IllegalArgumentException("Unsupported severity: " + severity); - } - return metric; - } - - static Metric severityToNewMetricIssue(RulePriority severity) { - Metric metric; - if (severity.equals(RulePriority.BLOCKER)) { - metric = CoreMetrics.NEW_BLOCKER_VIOLATIONS; - } else if (severity.equals(RulePriority.CRITICAL)) { - metric = CoreMetrics.NEW_CRITICAL_VIOLATIONS; - } else if (severity.equals(RulePriority.MAJOR)) { - metric = CoreMetrics.NEW_MAJOR_VIOLATIONS; - } else if (severity.equals(RulePriority.MINOR)) { - metric = CoreMetrics.NEW_MINOR_VIOLATIONS; - } else if (severity.equals(RulePriority.INFO)) { - metric = CoreMetrics.NEW_INFO_VIOLATIONS; - } else { - throw new IllegalArgumentException("Unsupported severity: " + severity); - } - return metric; - } -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/debt/DebtDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/debt/DebtDecorator.java deleted file mode 100644 index 5ddb7e45949..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/debt/DebtDecorator.java +++ /dev/null @@ -1,218 +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.annotations.VisibleForTesting; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Set; -import javax.annotation.CheckForNull; -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.batch.rule.Rule; -import org.sonar.api.batch.rule.Rules; -import org.sonar.api.component.ResourcePerspectives; -import org.sonar.api.issue.Issuable; -import org.sonar.api.issue.Issue; -import org.sonar.api.issue.internal.DefaultIssue; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Measure; -import org.sonar.api.measures.MeasuresFilters; -import org.sonar.api.measures.Metric; -import org.sonar.api.measures.PersistenceMode; -import org.sonar.api.measures.RuleMeasure; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Resource; -import org.sonar.api.resources.ResourceUtils; -import org.sonar.api.rule.RuleKey; -import org.sonar.api.rules.RuleFinder; -import org.sonar.api.technicaldebt.batch.Characteristic; -import org.sonar.api.technicaldebt.batch.TechnicalDebtModel; - -import static com.google.common.collect.Lists.newArrayList; -import static com.google.common.collect.Maps.newHashMap; - -/** - * Decorator that computes the technical debt metric - */ -@DependsUpon(DecoratorBarriers.ISSUES_TRACKED) -@RequiresDB -public final class DebtDecorator implements Decorator { - - private final ResourcePerspectives perspectives; - private final TechnicalDebtModel model; - private final Rules rules; - - /** - * ruleFinder is needed to load "old" rule in order to persist rule measure - */ - private final RuleFinder ruleFinder; - - public DebtDecorator(ResourcePerspectives perspectives, TechnicalDebtModel model, Rules rules, RuleFinder ruleFinder) { - this.perspectives = perspectives; - this.model = model; - this.rules = rules; - this.ruleFinder = ruleFinder; - } - - @Override - public boolean shouldExecuteOnProject(Project project) { - return true; - } - - @DependedUpon - public List<Metric> generatesMetrics() { - return Arrays.<Metric>asList(CoreMetrics.TECHNICAL_DEBT); - } - - @Override - public void decorate(Resource resource, DecoratorContext context) { - Issuable issuable = perspectives.as(Issuable.class, resource); - if (issuable != null && shouldSaveMeasure(context)) { - List<Issue> issues = newArrayList(issuable.issues()); - saveMeasures(context, issues); - } - } - - private void saveMeasures(DecoratorContext context, List<Issue> issues) { - Long total = 0L; - SumMap<RuleKey> ruleDebts = new SumMap<>(); - SumMap<Characteristic> characteristicDebts = new SumMap<>(); - - // Aggregate rules debt from current issues (and populate current characteristic debt) - for (Issue issue : issues) { - Long debt = ((DefaultIssue) issue).debtInMinutes(); - total += computeDebt(debt, issue.ruleKey(), ruleDebts, characteristicDebts); - } - - // Aggregate rules debt from children (and populate children characteristics debt) - for (Measure measure : context.getChildrenMeasures(MeasuresFilters.rules(CoreMetrics.TECHNICAL_DEBT))) { - Long debt = measure.getValue().longValue(); - RuleMeasure ruleMeasure = (RuleMeasure) measure; - total += computeDebt(debt, ruleMeasure.ruleKey(), ruleDebts, characteristicDebts); - } - - context.saveMeasure(CoreMetrics.TECHNICAL_DEBT, total.doubleValue()); - saveOnRule(context, ruleDebts); - for (Characteristic characteristic : model.characteristics()) { - Long debt = characteristicDebts.get(characteristic); - saveCharacteristicMeasure(context, characteristic, debt != null ? debt.doubleValue() : 0d, false); - } - } - - private Long computeDebt(@Nullable Long debt, RuleKey ruleKey, SumMap<RuleKey> ruleDebts, SumMap<Characteristic> characteristicDebts) { - if (debt != null) { - Rule rule = rules.find(ruleKey); - if (rule != null) { - String characteristicKey = rule.debtSubCharacteristic(); - if (characteristicKey != null) { - Characteristic characteristic = model.characteristicByKey(characteristicKey); - if (characteristic != null) { - ruleDebts.add(ruleKey, debt); - characteristicDebts.add(characteristic, debt); - propagateTechnicalDebtInParents(characteristic.parent(), debt, characteristicDebts); - return debt; - } - } - } - } - return 0L; - } - - private void propagateTechnicalDebtInParents(@Nullable Characteristic characteristic, long value, SumMap<Characteristic> characteristicDebts) { - if (characteristic != null) { - characteristicDebts.add(characteristic, value); - propagateTechnicalDebtInParents(characteristic.parent(), value, characteristicDebts); - } - } - - private void saveOnRule(DecoratorContext context, SumMap<RuleKey> ruleDebts) { - for (Map.Entry<RuleKey, Long> entry : ruleDebts.entrySet()) { - org.sonar.api.rules.Rule oldRule = ruleFinder.findByKey(entry.getKey()); - if (oldRule != null) { - saveRuleMeasure(context, oldRule, entry.getValue().doubleValue(), ResourceUtils.isEntity(context.getResource())); - } - } - } - - @VisibleForTesting - void saveCharacteristicMeasure(DecoratorContext context, Characteristic characteristic, Double value, boolean inMemory) { - // we need the value on projects (root or module) even if value==0 in order to display correctly the SQALE history chart (see SQALE-122) - // BUT we don't want to save zero-values for non top-characteristics (see SQALE-147) - if (value > 0.0 || (ResourceUtils.isProject(context.getResource()) && characteristic.isRoot())) { - Measure measure = new Measure(CoreMetrics.TECHNICAL_DEBT); - measure.setCharacteristic(characteristic); - saveMeasure(context, measure, value, inMemory); - } - } - - @VisibleForTesting - void saveRuleMeasure(DecoratorContext context, org.sonar.api.rules.Rule rule, Double value, boolean inMemory) { - // we need the value on projects (root or module) even if value==0 in order to display correctly the SQALE history chart (see SQALE-122) - // BUT we don't want to save zero-values for non top-characteristics (see SQALE-147) - if (value > 0.0) { - RuleMeasure measure = new RuleMeasure(CoreMetrics.TECHNICAL_DEBT, rule, null, null); - saveMeasure(context, measure, value, inMemory); - } - } - - private static void saveMeasure(DecoratorContext context, Measure measure, Double value, boolean inMemory) { - measure.setValue(value); - if (inMemory) { - measure.setPersistenceMode(PersistenceMode.MEMORY); - } - context.saveMeasure(measure); - } - - private static boolean shouldSaveMeasure(DecoratorContext context) { - return context.getMeasure(CoreMetrics.TECHNICAL_DEBT) == null; - } - - private static class SumMap<E> { - private Map<E, Long> sumByKeys; - - public SumMap() { - sumByKeys = newHashMap(); - } - - public void add(@Nullable E key, Long value) { - if (key != null) { - Long currentValue = sumByKeys.get(key); - sumByKeys.put(key, currentValue != null ? (currentValue + value) : value); - } - } - - @CheckForNull - public Long get(E key) { - return sumByKeys.get(key); - } - - public Set<Map.Entry<E, Long>> entrySet() { - return sumByKeys.entrySet(); - } - } -} diff --git a/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<CharacteristicDto> 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<CharacteristicDto> allCharacteristics) { - return Iterables.find(allCharacteristics, new Predicate<CharacteristicDto>() { - @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 fb882a7a0eb..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.api.issue.internal.DefaultIssue; -import org.sonar.api.issue.internal.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<FieldDiffs> changelog = technicalDebtHistory(issue); - for (Iterator<FieldDiffs> 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<FieldDiffs> technicalDebtHistory(Issue issue) { - List<FieldDiffs> 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<FieldDiffs> ordering = Ordering.natural().reverse().nullsFirst().onResultOf(new Function<FieldDiffs, Date>() { - @Override - public Date apply(FieldDiffs diff) { - return diff.creationDate(); - } - }); - return ordering.immutableSortedCopy(technicalDebtChangelog); - } - return Collections.emptyList(); - } - - private static List<FieldDiffs> changesOnField(Collection<FieldDiffs> fieldDiffs) { - List<FieldDiffs> 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<String, FieldDiffs.Diff> 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<String, FieldDiffs.Diff> 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<Metric> generatesMetrics() { - return ImmutableList.<Metric>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<Issue> issues = newArrayList(issuable.issues()); - saveMeasures(context, issues); - } - } - - private void saveMeasures(DecoratorContext context, Collection<Issue> issues) { - Measure measure = new Measure(CoreMetrics.NEW_TECHNICAL_DEBT); - for (Period period : timeMachineConfiguration.periods()) { - Date periodDate = period.getDate(); - double value = calculateNewTechnicalDebtValue(issues, periodDate); - Collection<Measure> children = context.getChildrenMeasures(measure.getMetric()); - double sum = MeasureUtils.sumOnVariation(true, period.getIndex(), children) + value; - measure.setVariation(period.getIndex(), sum); - } - context.saveMeasure(measure); - } - - private long calculateNewTechnicalDebtValue(Collection<Issue> issues, @Nullable Date periodDate) { - long result = 0; - for (Issue issue : issues) { - Long debt = issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, periodDate); - if (debt != null) { - result += debt; - } - } - return result; - } - - private static boolean shouldSaveNewMetrics(DecoratorContext context) { - return context.getMeasure(CoreMetrics.NEW_TECHNICAL_DEBT) == null; - } - -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/ScanPersister.java b/sonar-batch/src/main/java/org/sonar/batch/index/ScanPersister.java deleted file mode 100644 index 88b749ecb18..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/index/ScanPersister.java +++ /dev/null @@ -1,29 +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.index; - -import org.sonar.api.batch.BatchSide; - -@BatchSide -public interface ScanPersister { - - void persist(); - -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/DefaultIssuable.java b/sonar-batch/src/main/java/org/sonar/batch/issue/DefaultIssuable.java index 89561865d63..9dd268a8d22 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/issue/DefaultIssuable.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/DefaultIssuable.java @@ -23,7 +23,7 @@ import com.google.common.collect.Lists; import java.util.List; import org.sonar.api.issue.Issuable; import org.sonar.api.issue.Issue; -import org.sonar.api.issue.internal.DefaultIssue; +import org.sonar.core.issue.DefaultIssue; import org.sonar.api.resources.Project; import org.sonar.batch.index.BatchComponent; import org.sonar.core.issue.DefaultIssueBuilder; diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/DefaultProjectIssues.java b/sonar-batch/src/main/java/org/sonar/batch/issue/DefaultProjectIssues.java index 1cc682c0e34..ed9de9a5def 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/issue/DefaultProjectIssues.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/DefaultProjectIssues.java @@ -23,7 +23,7 @@ import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import org.sonar.api.issue.Issue; import org.sonar.api.issue.ProjectIssues; -import org.sonar.api.issue.internal.DefaultIssue; +import org.sonar.core.issue.DefaultIssue; import javax.annotation.Nullable; diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/IssueCache.java b/sonar-batch/src/main/java/org/sonar/batch/issue/IssueCache.java index dc5daaaafb4..52a29fb7483 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/issue/IssueCache.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/IssueCache.java @@ -20,7 +20,7 @@ package org.sonar.batch.issue; import org.sonar.api.batch.BatchSide; -import org.sonar.api.issue.internal.DefaultIssue; +import org.sonar.core.issue.DefaultIssue; import org.sonar.batch.index.Cache; import org.sonar.batch.index.Caches; diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/IssueFilters.java b/sonar-batch/src/main/java/org/sonar/batch/issue/IssueFilters.java index 0e623246b50..70bd4d54d5b 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/issue/IssueFilters.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/IssueFilters.java @@ -21,7 +21,7 @@ package org.sonar.batch.issue; import org.sonar.api.batch.BatchSide; import org.sonar.api.issue.batch.IssueFilter; -import org.sonar.api.issue.internal.DefaultIssue; +import org.sonar.core.issue.DefaultIssue; @BatchSide public class IssueFilters { 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 2586d4f898a..73c7604860c 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 @@ -19,21 +19,18 @@ */ package org.sonar.batch.issue; -import com.google.common.base.Objects; import com.google.common.base.Strings; import javax.annotation.Nullable; -import org.sonar.api.batch.debt.DebtRemediationFunction; import org.sonar.api.batch.rule.ActiveRule; 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.api.issue.internal.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; /** @@ -118,31 +115,5 @@ public class ModuleIssues { if (issue.severity() == null) { issue.setSeverity(activeRule.severity()); } - if (rule != null) { - DebtRemediationFunction function = rule.debtRemediationFunction(); - if (rule.debtSubCharacteristic() != null && function != null) { - issue.setDebt(calculateDebt(function, issue.effortToFix(), rule.key())); - } - } - } - - private Duration calculateDebt(DebtRemediationFunction function, @Nullable Double effortToFix, RuleKey ruleKey) { - if (DebtRemediationFunction.Type.CONSTANT_ISSUE.equals(function.type()) && effortToFix != null) { - throw new IllegalArgumentException("Rule '" + ruleKey + "' can not use 'Constant/issue' remediation function " + - "because this rule does not have a fixed remediation cost."); - } - Duration result = Duration.create(0); - Duration factor = function.coefficient(); - Duration offset = function.offset(); - - if (factor != null) { - int effortToFixValue = Objects.firstNonNull(effortToFix, 1).intValue(); - result = factor.multiply(effortToFixValue); - } - if (offset != null) { - result = result.add(offset); - } - return result; } - } diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/InitialOpenIssuesSensor.java b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/InitialOpenIssuesSensor.java deleted file mode 100644 index ef39e6b77e9..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/InitialOpenIssuesSensor.java +++ /dev/null @@ -1,93 +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.issue.tracking; - -import java.util.Calendar; -import java.util.Date; -import org.apache.commons.lang.time.DateUtils; -import org.apache.ibatis.session.ResultContext; -import org.apache.ibatis.session.ResultHandler; -import org.sonar.api.batch.RequiresDB; -import org.sonar.api.batch.Sensor; -import org.sonar.api.batch.SensorContext; -import org.sonar.api.resources.Project; -import org.sonar.core.issue.db.IssueChangeDao; -import org.sonar.core.issue.db.IssueChangeDto; -import org.sonar.core.issue.db.IssueDao; -import org.sonar.core.issue.db.IssueDto; -import org.sonar.core.resource.ResourceDao; -import org.sonar.core.resource.ResourceDto; -import org.sonar.core.resource.ResourceQuery; - -/** - * Load all the issues referenced during the previous scan. - */ -@RequiresDB -public class InitialOpenIssuesSensor implements Sensor { - - private final InitialOpenIssuesStack initialOpenIssuesStack; - private final IssueDao issueDao; - private final IssueChangeDao issueChangeDao; - private final ResourceDao resourceDao; - - public InitialOpenIssuesSensor(InitialOpenIssuesStack initialOpenIssuesStack, IssueDao issueDao, IssueChangeDao issueChangeDao, ResourceDao resourceDao) { - this.initialOpenIssuesStack = initialOpenIssuesStack; - this.issueDao = issueDao; - this.issueChangeDao = issueChangeDao; - this.resourceDao = resourceDao; - } - - @Override - public boolean shouldExecuteOnProject(Project project) { - return true; - } - - @Override - public void analyse(Project project, SensorContext context) { - ResourceDto module = resourceDao.getResource(ResourceQuery.create().setKey(project.getEffectiveKey())); - if (module != null) { - long moduleId = module.getId(); - // Adding one second is a hack for resolving conflicts with concurrent user - // changes during issue persistence - final Date now = DateUtils.addSeconds(DateUtils.truncate(new Date(), Calendar.MILLISECOND), 1); - issueDao.selectNonClosedIssuesByModule(moduleId, new ResultHandler() { - @Override - public void handleResult(ResultContext rc) { - IssueDto dto = (IssueDto) rc.getResultObject(); - dto.setSelectedAt(now.getTime()); - initialOpenIssuesStack.addIssue(dto); - } - }); - - issueChangeDao.selectChangelogOnNonClosedIssuesByModuleAndType(moduleId, new ResultHandler() { - @Override - public void handleResult(ResultContext rc) { - IssueChangeDto dto = (IssueChangeDto) rc.getResultObject(); - initialOpenIssuesStack.addChangelog(dto); - } - }); - } - } - - @Override - public String toString() { - return getClass().getSimpleName(); - } -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/InitialOpenIssuesStack.java b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/InitialOpenIssuesStack.java deleted file mode 100644 index ea7b9fb6e95..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/InitialOpenIssuesStack.java +++ /dev/null @@ -1,86 +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.issue.tracking; - -import org.sonar.api.batch.BatchSide; -import org.sonar.api.batch.InstantiationStrategy; -import org.sonar.batch.index.Cache; -import org.sonar.batch.index.Caches; -import org.sonar.core.issue.db.IssueChangeDto; -import org.sonar.core.issue.db.IssueDto; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import static com.google.common.collect.Lists.newArrayList; - -@BatchSide -@InstantiationStrategy(InstantiationStrategy.PER_BATCH) -public class InitialOpenIssuesStack { - - private final Cache<IssueDto> issuesCache; - private final Cache<ArrayList<IssueChangeDto>> issuesChangelogCache; - - public InitialOpenIssuesStack(Caches caches) { - issuesCache = caches.createCache("last-open-issues"); - issuesChangelogCache = caches.createCache("issues-changelog"); - } - - public InitialOpenIssuesStack addIssue(IssueDto issueDto) { - issuesCache.put(issueDto.getComponentKey(), issueDto.getKee(), issueDto); - return this; - } - - public List<ServerIssue> selectAndRemoveIssues(String componentKey) { - Iterable<IssueDto> issues = issuesCache.values(componentKey); - List<ServerIssue> result = newArrayList(); - for (IssueDto issue : issues) { - result.add(new ServerIssueFromDb(issue)); - } - issuesCache.clear(componentKey); - return result; - } - - public Iterable<IssueDto> selectAllIssues() { - return issuesCache.values(); - } - - public InitialOpenIssuesStack addChangelog(IssueChangeDto issueChangeDto) { - List<IssueChangeDto> changeDtos = issuesChangelogCache.get(issueChangeDto.getIssueKey()); - if (changeDtos == null) { - changeDtos = newArrayList(); - } - changeDtos.add(issueChangeDto); - issuesChangelogCache.put(issueChangeDto.getIssueKey(), newArrayList(changeDtos)); - return this; - } - - public List<IssueChangeDto> selectChangelog(String issueKey) { - List<IssueChangeDto> changeDtos = issuesChangelogCache.get(issueKey); - return changeDtos != null ? changeDtos : Collections.<IssueChangeDto>emptyList(); - } - - public void clear() { - issuesCache.clear(); - issuesChangelogCache.clear(); - } -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/IssueHandlers.java b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/IssueHandlers.java deleted file mode 100644 index c7ef0dd53c4..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/IssueHandlers.java +++ /dev/null @@ -1,141 +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.issue.tracking; - -import org.sonar.api.batch.BatchSide; -import org.sonar.api.issue.Issue; -import org.sonar.api.issue.IssueHandler; -import org.sonar.api.issue.internal.DefaultIssue; -import org.sonar.api.issue.internal.IssueChangeContext; -import org.sonar.api.user.User; -import org.sonar.core.issue.IssueUpdater; -import org.sonar.core.user.DefaultUser; - -import javax.annotation.Nullable; - -@BatchSide -public class IssueHandlers { - private final IssueHandler[] handlers; - private final DefaultContext context; - - public IssueHandlers(IssueUpdater updater, IssueHandler[] handlers) { - this.handlers = handlers; - this.context = new DefaultContext(updater); - } - - public IssueHandlers(IssueUpdater updater) { - this(updater, new IssueHandler[0]); - } - - public void execute(DefaultIssue issue, IssueChangeContext changeContext) { - context.reset(issue, changeContext); - for (IssueHandler handler : handlers) { - handler.onIssue(context); - } - } - - static class DefaultContext implements IssueHandler.Context { - private final IssueUpdater updater; - private DefaultIssue issue; - private IssueChangeContext changeContext; - - private DefaultContext(IssueUpdater updater) { - this.updater = updater; - } - - private void reset(DefaultIssue i, IssueChangeContext changeContext) { - this.issue = i; - this.changeContext = changeContext; - } - - @Override - public Issue issue() { - return issue; - } - - @Override - public boolean isNew() { - return issue.isNew(); - } - - @Override - public boolean isEndOfLife() { - return issue.isEndOfLife(); - } - - @Override - public IssueHandler.Context setLine(@Nullable Integer line) { - updater.setLine(issue, line); - return this; - } - - @Override - public IssueHandler.Context setMessage(@Nullable String s) { - updater.setMessage(issue, s, changeContext); - return this; - } - - @Override - public IssueHandler.Context setSeverity(String severity) { - updater.setSeverity(issue, severity, changeContext); - return this; - } - - @Override - public IssueHandler.Context setAuthorLogin(@Nullable String login) { - updater.setAuthorLogin(issue, login, changeContext); - return this; - } - - @Override - public IssueHandler.Context setEffortToFix(@Nullable Double d) { - updater.setEffortToFix(issue, d, changeContext); - return this; - } - - @Override - public IssueHandler.Context setAttribute(String key, @Nullable String value) { - throw new UnsupportedOperationException("TODO"); - } - - @Override - public IssueHandler.Context assign(@Nullable String assignee) { - User user = null; - if (assignee != null) { - user = new DefaultUser().setLogin(assignee).setName(assignee); - } - updater.assign(issue, user, changeContext); - return this; - } - - @Override - public IssueHandler.Context assign(@Nullable User user) { - updater.assign(issue, user, changeContext); - return this; - } - - @Override - public IssueHandler.Context addComment(String text) { - updater.addComment(issue, text, changeContext); - return this; - } - } - -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/IssueTracking.java b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/IssueTracking.java index bd339571e51..ee089357320 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/IssueTracking.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/IssueTracking.java @@ -29,7 +29,7 @@ import com.google.common.collect.Maps; import com.google.common.collect.Multimap; import org.sonar.api.batch.BatchSide; import org.sonar.api.batch.InstantiationStrategy; -import org.sonar.api.issue.internal.DefaultIssue; +import org.sonar.core.issue.DefaultIssue; import javax.annotation.Nullable; diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/IssueTrackingDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/IssueTrackingDecorator.java deleted file mode 100644 index 7c05341ffe1..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/IssueTrackingDecorator.java +++ /dev/null @@ -1,279 +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.issue.tracking; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Strings; -import com.google.common.collect.Lists; -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -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.batch.fs.InputFile; -import org.sonar.api.batch.fs.internal.DefaultInputFile; -import org.sonar.api.component.ResourcePerspectives; -import org.sonar.api.issue.Issuable; -import org.sonar.api.issue.Issue; -import org.sonar.api.issue.internal.DefaultIssue; -import org.sonar.api.issue.internal.IssueChangeContext; -import org.sonar.api.profiles.RulesProfile; -import org.sonar.api.resources.File; -import org.sonar.api.resources.Project; -import org.sonar.api.resources.Resource; -import org.sonar.api.resources.ResourceUtils; -import org.sonar.api.rules.ActiveRule; -import org.sonar.api.rules.Rule; -import org.sonar.api.rules.RuleFinder; -import org.sonar.api.utils.Duration; -import org.sonar.api.utils.KeyValueFormat; -import org.sonar.batch.issue.IssueCache; -import org.sonar.batch.scan.filesystem.InputPathCache; -import org.sonar.core.issue.IssueUpdater; -import org.sonar.core.issue.db.IssueChangeDto; -import org.sonar.core.issue.db.IssueDto; -import org.sonar.core.issue.workflow.IssueWorkflow; - -import java.util.Collection; - -@DependsUpon(DecoratorBarriers.ISSUES_ADDED) -@DependedUpon(DecoratorBarriers.ISSUES_TRACKED) -@RequiresDB -public class IssueTrackingDecorator implements Decorator { - - private static final Logger LOG = LoggerFactory.getLogger(IssueTrackingDecorator.class); - - private final IssueCache issueCache; - private final InitialOpenIssuesStack initialOpenIssues; - private final IssueTracking tracking; - private final ServerLineHashesLoader lastLineHashes; - private final IssueHandlers handlers; - private final IssueWorkflow workflow; - private final IssueUpdater updater; - private final IssueChangeContext changeContext; - private final ResourcePerspectives perspectives; - private final RulesProfile rulesProfile; - private final RuleFinder ruleFinder; - private final InputPathCache inputPathCache; - private final Project project; - - public IssueTrackingDecorator(IssueCache issueCache, InitialOpenIssuesStack initialOpenIssues, IssueTracking tracking, - ServerLineHashesLoader lastLineHashes, - IssueHandlers handlers, IssueWorkflow workflow, - IssueUpdater updater, - Project project, - ResourcePerspectives perspectives, - RulesProfile rulesProfile, - RuleFinder ruleFinder, InputPathCache inputPathCache) { - this.issueCache = issueCache; - this.initialOpenIssues = initialOpenIssues; - this.tracking = tracking; - this.lastLineHashes = lastLineHashes; - this.handlers = handlers; - this.workflow = workflow; - this.updater = updater; - this.project = project; - this.inputPathCache = inputPathCache; - this.changeContext = IssueChangeContext.createScan(project.getAnalysisDate()); - this.perspectives = perspectives; - this.rulesProfile = rulesProfile; - this.ruleFinder = ruleFinder; - } - - @Override - public boolean shouldExecuteOnProject(Project project) { - return true; - } - - @Override - public void decorate(Resource resource, DecoratorContext context) { - Issuable issuable = perspectives.as(Issuable.class, resource); - if (issuable != null) { - doDecorate(resource); - } - } - - @VisibleForTesting - void doDecorate(Resource resource) { - Collection<DefaultIssue> issues = Lists.newArrayList(); - for (Issue issue : issueCache.byComponent(resource.getEffectiveKey())) { - issues.add((DefaultIssue) issue); - } - issueCache.clear(resource.getEffectiveKey()); - // issues = all the issues created by rule engines during this module scan and not excluded by filters - - // all the issues that are not closed in db before starting this module scan, including manual issues - Collection<ServerIssue> dbOpenIssues = initialOpenIssues.selectAndRemoveIssues(resource.getEffectiveKey()); - - SourceHashHolder sourceHashHolder = null; - if (ResourceUtils.isFile(resource)) { - File sonarFile = (File) resource; - InputFile file = inputPathCache.getFile(project.getEffectiveKey(), sonarFile.getPath()); - if (file == null) { - throw new IllegalStateException("File " + resource + " was not found in InputPath cache"); - } - sourceHashHolder = new SourceHashHolder((DefaultInputFile) file, lastLineHashes); - } - - IssueTrackingResult trackingResult = tracking.track(sourceHashHolder, dbOpenIssues, issues); - - // unmatched = issues that have been resolved + issues on disabled/removed rules + manual issues - addUnmatched(trackingResult.unmatched(), sourceHashHolder, issues); - - mergeMatched(trackingResult); - - if (ResourceUtils.isProject(resource)) { - // issues that relate to deleted components - addIssuesOnDeletedComponents(issues); - } - - for (DefaultIssue issue : issues) { - workflow.doAutomaticTransition(issue, changeContext); - handlers.execute(issue, changeContext); - issueCache.put(issue); - } - } - - @VisibleForTesting - protected void mergeMatched(IssueTrackingResult result) { - for (DefaultIssue issue : result.matched()) { - IssueDto ref = ((ServerIssueFromDb) result.matching(issue)).getDto(); - - // invariant fields - issue.setKey(ref.getKee()); - issue.setCreationDate(ref.getIssueCreationDate()); - issue.setUpdateDate(ref.getIssueUpdateDate()); - issue.setCloseDate(ref.getIssueCloseDate()); - - // non-persisted fields - issue.setNew(false); - issue.setEndOfLife(false); - issue.setOnDisabledRule(false); - issue.setSelectedAt(ref.getSelectedAt()); - - // fields to update with old values - issue.setActionPlanKey(ref.getActionPlanKey()); - issue.setResolution(ref.getResolution()); - issue.setStatus(ref.getStatus()); - issue.setAssignee(ref.getAssignee()); - issue.setAuthorLogin(ref.getAuthorLogin()); - issue.setTags(ref.getTags()); - - if (ref.getIssueAttributes() != null) { - issue.setAttributes(KeyValueFormat.parse(ref.getIssueAttributes())); - } - - // populate existing changelog - Collection<IssueChangeDto> issueChangeDtos = initialOpenIssues.selectChangelog(issue.key()); - for (IssueChangeDto issueChangeDto : issueChangeDtos) { - issue.addChange(issueChangeDto.toFieldDiffs()); - } - - // fields to update with current values - if (ref.isManualSeverity()) { - issue.setManualSeverity(true); - issue.setSeverity(ref.getSeverity()); - } else { - updater.setPastSeverity(issue, ref.getSeverity(), changeContext); - } - updater.setPastLine(issue, ref.getLine()); - updater.setPastMessage(issue, ref.getMessage(), changeContext); - updater.setPastEffortToFix(issue, ref.getEffortToFix(), changeContext); - Long debtInMinutes = ref.getDebt(); - Duration previousTechnicalDebt = debtInMinutes != null ? Duration.create(debtInMinutes) : null; - updater.setPastTechnicalDebt(issue, previousTechnicalDebt, changeContext); - updater.setPastProject(issue, ref.getProjectKey(), changeContext); - } - } - - private void addUnmatched(Collection<ServerIssue> unmatchedIssues, SourceHashHolder sourceHashHolder, Collection<DefaultIssue> issues) { - for (ServerIssue unmatchedIssue : unmatchedIssues) { - IssueDto unmatchedDto = ((ServerIssueFromDb) unmatchedIssue).getDto(); - DefaultIssue unmatched = unmatchedDto.toDefaultIssue(); - if (StringUtils.isNotBlank(unmatchedDto.getReporter()) && !Issue.STATUS_CLOSED.equals(unmatchedDto.getStatus())) { - relocateManualIssue(unmatched, unmatchedDto, sourceHashHolder); - } - updateUnmatchedIssue(unmatched, false /* manual issues can be kept open */); - issues.add(unmatched); - } - } - - private void addIssuesOnDeletedComponents(Collection<DefaultIssue> issues) { - for (IssueDto deadDto : initialOpenIssues.selectAllIssues()) { - DefaultIssue dead = deadDto.toDefaultIssue(); - updateUnmatchedIssue(dead, true); - issues.add(dead); - } - initialOpenIssues.clear(); - } - - private void updateUnmatchedIssue(DefaultIssue issue, boolean forceEndOfLife) { - issue.setNew(false); - - boolean manualIssue = !Strings.isNullOrEmpty(issue.reporter()); - Rule rule = ruleFinder.findByKey(issue.ruleKey()); - if (manualIssue) { - // Manual rules are not declared in Quality profiles, so no need to check ActiveRule - boolean isRemovedRule = rule == null || Rule.STATUS_REMOVED.equals(rule.getStatus()); - issue.setEndOfLife(forceEndOfLife || isRemovedRule); - issue.setOnDisabledRule(isRemovedRule); - } else { - ActiveRule activeRule = rulesProfile.getActiveRule(issue.ruleKey().repository(), issue.ruleKey().rule()); - issue.setEndOfLife(true); - issue.setOnDisabledRule(activeRule == null || rule == null || Rule.STATUS_REMOVED.equals(rule.getStatus())); - } - } - - private void relocateManualIssue(DefaultIssue newIssue, IssueDto oldIssue, SourceHashHolder sourceHashHolder) { - LOG.debug("Trying to relocate manual issue {}", oldIssue.getKee()); - - Integer previousLine = oldIssue.getLine(); - if (previousLine == null) { - LOG.debug("Cannot relocate issue at resource level"); - return; - } - - Collection<Integer> newLinesWithSameHash = sourceHashHolder.getNewLinesMatching(previousLine); - LOG.debug("Found the following lines with same hash: {}", newLinesWithSameHash); - if (newLinesWithSameHash.isEmpty()) { - if (previousLine > sourceHashHolder.getHashedSource().length()) { - LOG.debug("Old issue line {} is out of new source, closing and removing line number", previousLine); - newIssue.setLine(null); - updater.setStatus(newIssue, Issue.STATUS_CLOSED, changeContext); - updater.setResolution(newIssue, Issue.RESOLUTION_REMOVED, changeContext); - updater.setPastLine(newIssue, previousLine); - updater.setPastMessage(newIssue, oldIssue.getMessage(), changeContext); - updater.setPastEffortToFix(newIssue, oldIssue.getEffortToFix(), changeContext); - } - } else if (newLinesWithSameHash.size() == 1) { - Integer newLine = newLinesWithSameHash.iterator().next(); - LOG.debug("Relocating issue to line {}", newLine); - - newIssue.setLine(newLine); - updater.setPastLine(newIssue, previousLine); - updater.setPastMessage(newIssue, oldIssue.getMessage(), changeContext); - updater.setPastEffortToFix(newIssue, oldIssue.getEffortToFix(), changeContext); - } - } -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/IssueTrackingResult.java b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/IssueTrackingResult.java index 8fe3549e66b..e04cdc240b4 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/IssueTrackingResult.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/IssueTrackingResult.java @@ -23,7 +23,7 @@ import com.google.common.collect.HashMultimap; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; import org.apache.commons.lang.StringUtils; -import org.sonar.api.issue.internal.DefaultIssue; +import org.sonar.core.issue.DefaultIssue; import org.sonar.api.rule.RuleKey; import javax.annotation.Nullable; 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 a946c9f7dea..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 @@ -29,8 +29,8 @@ import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.batch.rule.ActiveRule; import org.sonar.api.batch.rule.ActiveRules; import org.sonar.api.issue.Issue; -import org.sonar.api.issue.internal.DefaultIssue; -import org.sonar.api.issue.internal.IssueChangeContext; +import org.sonar.core.issue.DefaultIssue; +import org.sonar.core.issue.IssueChangeContext; import org.sonar.api.resources.Project; import org.sonar.api.resources.ResourceUtils; import org.sonar.api.rule.RuleKey; @@ -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; } @@ -166,7 +166,7 @@ public class LocalIssueTracking { // non-persisted fields issue.setNew(false); - issue.setEndOfLife(false); + issue.setBeingClosed(false); issue.setOnDisabledRule(false); // fields to update with old values @@ -226,9 +226,9 @@ public class LocalIssueTracking { boolean manualIssue = issue.ruleKey().isManual(); boolean isRemovedRule = activeRule == null; if (manualIssue) { - issue.setEndOfLife(forceEndOfLife || isRemovedRule); + issue.setBeingClosed(forceEndOfLife || isRemovedRule); } else { - issue.setEndOfLife(true); + issue.setBeingClosed(true); } issue.setOnDisabledRule(isRemovedRule); } diff --git a/sonar-batch/src/main/java/org/sonar/batch/mediumtest/TaskResult.java b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/TaskResult.java index 55502e9ba78..9b6ece676b1 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/mediumtest/TaskResult.java +++ b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/TaskResult.java @@ -37,7 +37,7 @@ import org.sonar.api.batch.sensor.duplication.Duplication; import org.sonar.api.batch.sensor.highlighting.TypeOfText; import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure; import org.sonar.api.issue.Issue; -import org.sonar.api.issue.internal.DefaultIssue; +import org.sonar.core.issue.DefaultIssue; import org.sonar.api.measures.Measure; import org.sonar.batch.duplication.DuplicationCache; import org.sonar.batch.index.Cache.Entry; diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/PersisterExecutionEvent.java b/sonar-batch/src/main/java/org/sonar/batch/phases/PersisterExecutionEvent.java deleted file mode 100644 index cb6574591c7..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/phases/PersisterExecutionEvent.java +++ /dev/null @@ -1,50 +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.phases; - -import org.sonar.batch.index.ScanPersister; -import org.sonar.batch.phases.event.PersisterExecutionHandler; - -class PersisterExecutionEvent extends AbstractPhaseEvent<PersisterExecutionHandler> - implements PersisterExecutionHandler.PersisterExecutionEvent { - - private final ScanPersister persister; - - PersisterExecutionEvent(ScanPersister persister, boolean start) { - super(start); - this.persister = persister; - } - - @Override - public ScanPersister getPersister() { - return persister; - } - - @Override - public void dispatch(PersisterExecutionHandler handler) { - handler.onPersisterExecution(this); - } - - @Override - public Class getType() { - return PersisterExecutionHandler.class; - } - -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/PersistersExecutor.java b/sonar-batch/src/main/java/org/sonar/batch/phases/PersistersExecutor.java deleted file mode 100644 index 8e114b6ec31..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/phases/PersistersExecutor.java +++ /dev/null @@ -1,65 +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.phases; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.sonar.api.batch.BatchSide; -import org.sonar.batch.bootstrap.DefaultAnalysisMode; -import org.sonar.batch.events.EventBus; -import org.sonar.batch.index.ScanPersister; - -import java.util.Arrays; - -@BatchSide -public class PersistersExecutor { - - private static final Logger LOG = LoggerFactory.getLogger(PersistersExecutor.class); - - private final ScanPersister[] persisters; - private final DefaultAnalysisMode analysisMode; - private final EventBus eventBus; - - public PersistersExecutor(DefaultAnalysisMode analysisMode, EventBus eventBus, ScanPersister[] persisters) { - this.analysisMode = analysisMode; - this.eventBus = eventBus; - this.persisters = persisters; - } - - public PersistersExecutor(DefaultAnalysisMode analysisMode, EventBus eventBus) { - this(analysisMode, eventBus, new ScanPersister[0]); - } - - public void execute() { - if (analysisMode.isDb()) { - LOG.info("Store results in database"); - eventBus.fireEvent(new PersistersPhaseEvent(Arrays.asList(persisters), true)); - for (ScanPersister persister : persisters) { - LOG.debug("Execute {}", persister.getClass().getName()); - eventBus.fireEvent(new PersisterExecutionEvent(persister, true)); - persister.persist(); - eventBus.fireEvent(new PersisterExecutionEvent(persister, false)); - } - - eventBus.fireEvent(new PersistersPhaseEvent(Arrays.asList(persisters), false)); - } - } - -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/PersistersPhaseEvent.java b/sonar-batch/src/main/java/org/sonar/batch/phases/PersistersPhaseEvent.java deleted file mode 100644 index ad43c00ab36..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/phases/PersistersPhaseEvent.java +++ /dev/null @@ -1,52 +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.phases; - -import org.sonar.batch.index.ScanPersister; -import org.sonar.batch.phases.event.PersistersPhaseHandler; - -import java.util.List; - -class PersistersPhaseEvent extends AbstractPhaseEvent<PersistersPhaseHandler> - implements PersistersPhaseHandler.PersistersPhaseEvent { - - private final List<ScanPersister> persisters; - - PersistersPhaseEvent(List<ScanPersister> persisters, boolean start) { - super(start); - this.persisters = persisters; - } - - @Override - public List<ScanPersister> getPersisters() { - return persisters; - } - - @Override - protected void dispatch(PersistersPhaseHandler handler) { - handler.onPersistersPhase(this); - } - - @Override - protected Class getType() { - return PersistersPhaseHandler.class; - } - -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java b/sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java index af07cf80cb0..e41acc6760d 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java +++ b/sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java @@ -44,7 +44,6 @@ public final class PhaseExecutor { private final SensorContext sensorContext; private final DefaultIndex index; private final ProjectInitializer pi; - private final PersistersExecutor persistersExecutor; private final FileSystemLogger fsLogger; private final DefaultModuleFileSystem fs; private final QProfileVerifier profileVerifier; @@ -57,7 +56,7 @@ public final class PhaseExecutor { InitializersExecutor initializersExecutor, PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor, SensorContext sensorContext, DefaultIndex index, EventBus eventBus, ReportPublisher reportPublisher, ProjectInitializer pi, - PersistersExecutor persistersExecutor, FileSystemLogger fsLogger, IssuesReports jsonReport, DefaultModuleFileSystem fs, QProfileVerifier profileVerifier, + FileSystemLogger fsLogger, IssuesReports jsonReport, DefaultModuleFileSystem fs, QProfileVerifier profileVerifier, IssueExclusionsLoader issueExclusionsLoader, DefaultAnalysisMode analysisMode, LocalIssueTracking localIssueTracking) { this.decoratorsExecutor = decoratorsExecutor; this.postJobsExecutor = postJobsExecutor; @@ -68,7 +67,6 @@ public final class PhaseExecutor { this.eventBus = eventBus; this.reportPublisher = reportPublisher; this.pi = pi; - this.persistersExecutor = persistersExecutor; this.fsLogger = fsLogger; this.issuesReport = jsonReport; this.fs = fs; @@ -106,11 +104,6 @@ public final class PhaseExecutor { localIssueTracking(); } issuesReport(); - - if (!analysisMode.isPreview()) { - persistersExecutor.execute(); - } - publishReportJob(); postJobsExecutor.execute(sensorContext); } diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/event/PersisterExecutionHandler.java b/sonar-batch/src/main/java/org/sonar/batch/phases/event/PersisterExecutionHandler.java deleted file mode 100644 index 7df8dae4ade..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/phases/event/PersisterExecutionHandler.java +++ /dev/null @@ -1,45 +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.phases.event; - -import org.sonar.api.batch.events.EventHandler; -import org.sonar.batch.index.ScanPersister; - -public interface PersisterExecutionHandler extends EventHandler { - - /** - * This interface is not intended to be implemented by clients. - */ - interface PersisterExecutionEvent { - - ScanPersister getPersister(); - - boolean isStart(); - - boolean isEnd(); - - } - - /** - * Called before and after execution of {@link ScanPersister}. - */ - void onPersisterExecution(PersisterExecutionEvent event); - -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/event/PersistersPhaseHandler.java b/sonar-batch/src/main/java/org/sonar/batch/phases/event/PersistersPhaseHandler.java deleted file mode 100644 index 087755bacab..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/phases/event/PersistersPhaseHandler.java +++ /dev/null @@ -1,50 +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.phases.event; - -import org.sonar.api.batch.events.EventHandler; -import org.sonar.batch.index.ScanPersister; - -import java.util.List; - -public interface PersistersPhaseHandler extends EventHandler { - - /** - * This interface is not intended to be implemented by clients. - */ - interface PersistersPhaseEvent { - - /** - * @return list of Persisters in the order of execution - */ - List<ScanPersister> getPersisters(); - - boolean isStart(); - - boolean isEnd(); - - } - - /** - * Called before and after execution of all {@link ScanPersister}s. - */ - void onPersistersPhase(PersistersPhaseEvent event); - -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/event/package-info.java b/sonar-batch/src/main/java/org/sonar/batch/phases/event/package-info.java deleted file mode 100644 index 6aefbe5b6bb..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/phases/event/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -@ParametersAreNonnullByDefault -package org.sonar.batch.phases.event; - -import javax.annotation.ParametersAreNonnullByDefault; diff --git a/sonar-batch/src/main/java/org/sonar/batch/postjob/DefaultPostJobContext.java b/sonar-batch/src/main/java/org/sonar/batch/postjob/DefaultPostJobContext.java index 6f46c012ce9..7b1edddabec 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/postjob/DefaultPostJobContext.java +++ b/sonar-batch/src/main/java/org/sonar/batch/postjob/DefaultPostJobContext.java @@ -28,7 +28,7 @@ import org.sonar.api.batch.postjob.PostJobContext; import org.sonar.api.batch.postjob.issue.Issue; import org.sonar.api.batch.rule.Severity; import org.sonar.api.config.Settings; -import org.sonar.api.issue.internal.DefaultIssue; +import org.sonar.core.issue.DefaultIssue; import org.sonar.api.rule.RuleKey; import org.sonar.batch.index.BatchComponent; import org.sonar.batch.index.BatchComponentCache; diff --git a/sonar-batch/src/main/java/org/sonar/batch/profiling/PhasesSumUpTimeProfiler.java b/sonar-batch/src/main/java/org/sonar/batch/profiling/PhasesSumUpTimeProfiler.java index 97e5c09dcdb..1da5585e762 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/profiling/PhasesSumUpTimeProfiler.java +++ b/sonar-batch/src/main/java/org/sonar/batch/profiling/PhasesSumUpTimeProfiler.java @@ -48,16 +48,13 @@ import org.sonar.api.utils.System2; import org.sonar.api.utils.TimeUtils; import org.sonar.batch.bootstrap.BootstrapProperties; import org.sonar.batch.events.BatchStepHandler; -import org.sonar.batch.phases.event.PersisterExecutionHandler; -import org.sonar.batch.phases.event.PersistersPhaseHandler; import org.sonar.batch.util.BatchUtils; import static org.sonar.batch.profiling.AbstractTimeProfiling.sortByDescendingTotalTime; import static org.sonar.batch.profiling.AbstractTimeProfiling.truncate; public class PhasesSumUpTimeProfiler implements ProjectAnalysisHandler, SensorExecutionHandler, DecoratorExecutionHandler, PostJobExecutionHandler, DecoratorsPhaseHandler, - SensorsPhaseHandler, PostJobsPhaseHandler, InitializersPhaseHandler, InitializerExecutionHandler, BatchStepHandler, PersistersPhaseHandler, - PersisterExecutionHandler { + SensorsPhaseHandler, PostJobsPhaseHandler, InitializersPhaseHandler, InitializerExecutionHandler, BatchStepHandler { static final Logger LOG = LoggerFactory.getLogger(PhasesSumUpTimeProfiler.class); private static final int TEXT_RIGHT_PAD = 60; @@ -175,25 +172,6 @@ public class PhasesSumUpTimeProfiler implements ProjectAnalysisHandler, SensorEx } @Override - public void onPersistersPhase(PersistersPhaseEvent event) { - if (event.isStart()) { - currentModuleProfiling.addPhaseProfiling(Phase.PERSISTER); - } else { - currentModuleProfiling.getProfilingPerPhase(Phase.PERSISTER).stop(); - } - } - - @Override - public void onPersisterExecution(PersisterExecutionEvent event) { - PhaseProfiling profiling = currentModuleProfiling.getProfilingPerPhase(Phase.PERSISTER); - if (event.isStart()) { - profiling.newItemProfiling(event.getPersister()); - } else { - profiling.getProfilingPerItem(event.getPersister()).stop(); - } - } - - @Override public void onDecoratorExecution(DecoratorExecutionEvent event) { PhaseProfiling profiling = currentModuleProfiling.getProfilingPerPhase(Phase.DECORATOR); if (event.isStart()) { 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 08be39df953..b3e3692d937 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,15 +21,6 @@ package org.sonar.batch.report; import com.google.common.base.Function; import com.google.common.collect.Iterables; -import java.util.Collection; -import java.util.Date; -import java.util.Iterator; -import javax.annotation.Nullable; -import org.sonar.api.CoreProperties; -import org.sonar.api.batch.bootstrap.ProjectDefinition; -import org.sonar.api.issue.internal.DefaultIssue; -import org.sonar.api.issue.internal.FieldDiffs; -import org.sonar.api.resources.Project; import org.sonar.api.utils.KeyValueFormat; import org.sonar.batch.index.BatchComponent; import org.sonar.batch.index.BatchComponentCache; @@ -37,23 +28,21 @@ 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 public void publish(BatchReportWriter writer) { - Collection<Object> deletedComponentKeys = issueCache.componentKeys(); for (BatchComponent resource : componentCache.all()) { String componentKey = resource.resource().getEffectiveKey(); Iterable<DefaultIssue> issues = issueCache.byComponent(componentKey); @@ -65,63 +54,17 @@ public class IssuesPublisher implements ReportPublisherStep { return toReportIssue(builder, input); } })); - deletedComponentKeys.remove(componentKey); } - - int count = exportIssuesOfDeletedComponents(deletedComponentKeys, writer); - - exportMetadata(writer, count); - } - - private void exportMetadata(BatchReportWriter writer, int count) { - 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()) - .setDeletedComponentsCount(count); - String branch = root.properties().get(CoreProperties.PROJECT_BRANCH_PROPERTY); - if (branch != null) { - builder.setBranch(branch); - } - writer.writeMetadata(builder.build()); - } - - private int exportIssuesOfDeletedComponents(Collection<Object> deletedComponentKeys, BatchReportWriter writer) { - int deletedComponentCount = 0; - for (Object componentKey : deletedComponentKeys) { - deletedComponentCount++; - Iterable<DefaultIssue> issues = issueCache.byComponent(componentKey.toString()); - Iterator<DefaultIssue> iterator = issues.iterator(); - if (iterator.hasNext()) { - String componentUuid = iterator.next().componentUuid(); - writer.writeDeletedComponentIssues(deletedComponentCount, componentUuid, Iterables.transform(issues, new Function<DefaultIssue, BatchReport.Issue>() { - private BatchReport.Issue.Builder builder = BatchReport.Issue.newBuilder(); - - @Override - public BatchReport.Issue apply(DefaultIssue input) { - return toReportIssue(builder, input); - } - })); - } - } - return deletedComponentCount; } private BatchReport.Issue toReportIssue(BatchReport.Issue.Builder builder, DefaultIssue issue) { builder.clear(); // non-null fields - builder.setUuid(issue.key()); - builder.setIsNew(issue.isNew()); builder.setSeverity(Constants.Severity.valueOf(issue.severity())); builder.setRuleRepository(issue.ruleKey().repository()); builder.setRuleKey(issue.ruleKey().rule()); builder.setAttributes(KeyValueFormat.format(issue.attributes())); builder.addAllTag(issue.tags()); - builder.setMustSendNotification(issue.mustSendNotifications()); - builder.setIsChanged(issue.isChanged()); // nullable fields Integer line = issue.line(); @@ -136,65 +79,7 @@ public class IssuesPublisher implements ReportPublisherStep { if (effortToFix != null) { builder.setEffortToFix(effortToFix); } - - Long debtInMinutes = issue.debtInMinutes(); - if (debtInMinutes != null) { - builder.setDebtInMinutes(debtInMinutes); - } - String resolution = issue.resolution(); - if (resolution != null) { - builder.setResolution(resolution); - } - String status = issue.status(); - if (status != null) { - builder.setStatus(status); - } - String checksum = issue.checksum(); - if (checksum != null) { - builder.setChecksum(checksum); - } - builder.setManualSeverity(issue.manualSeverity()); - String reporter = issue.reporter(); - if (reporter != null) { - builder.setReporter(reporter); - } - String assignee = issue.assignee(); - if (assignee != null) { - builder.setAssignee(assignee); - } - String actionPlanKey = issue.actionPlanKey(); - if (actionPlanKey != null) { - builder.setActionPlanKey(actionPlanKey); - } - String authorLogin = issue.authorLogin(); - if (authorLogin != null) { - builder.setAuthorLogin(authorLogin); - } - String diff = diffsToString(issue.currentChange()); - if (diff != null) { - builder.setDiffFields(diff); - } - Date creationDate = issue.creationDate(); - if (creationDate != null) { - builder.setCreationDate(creationDate.getTime()); - } - Long selectedAt = issue.selectedAt(); - if (selectedAt != null) { - builder.setSelectedAt(selectedAt); - } - Date closeDate = issue.closeDate(); - if (closeDate != null) { - builder.setCloseDate(closeDate.getTime()); - } - Date updateDate = issue.updateDate(); - if (updateDate != null) { - builder.setUpdateDate(updateDate.getTime()); - } return builder.build(); } - private String diffsToString(@Nullable FieldDiffs diffs) { - return diffs != null ? diffs.toString() : null; - } - } 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 fe57b624502..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,21 +107,6 @@ public class MeasuresPublisher implements ReportPublisherStep { if (description != null) { builder.setDescription(description); } - if (measure instanceof RuleMeasure) { - RuleMeasure ruleMeasure = (RuleMeasure) measure; - RuleKey ruleKey = ruleMeasure.ruleKey(); - if (ruleKey != null) { - builder.setRuleKey(ruleKey.toString()); - } - } - 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); @@ -146,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<ActiveRule, String> { + 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<RuleParamDto> ruleParamDtos = ruleDao.selectParameters(); - ListMultimap<Integer, RuleParamDto> 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/ModuleScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java index 4d4fb03fff9..c4524dca799 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java @@ -50,7 +50,6 @@ import org.sonar.batch.issue.ignore.scanner.IssueExclusionsLoader; import org.sonar.batch.issue.ignore.scanner.IssueExclusionsRegexpScanner; import org.sonar.batch.phases.DecoratorsExecutor; import org.sonar.batch.phases.InitializersExecutor; -import org.sonar.batch.phases.PersistersExecutor; import org.sonar.batch.phases.PhaseExecutor; import org.sonar.batch.phases.PostJobsExecutor; import org.sonar.batch.phases.ProjectInitializer; @@ -120,7 +119,6 @@ public class ModuleScanContainer extends ComponentContainer { PostJobsExecutor.class, DecoratorsExecutor.class, SensorsExecutor.class, - PersistersExecutor.class, InitializersExecutor.class, ProjectInitializer.class, moduleDefinition.getContainerExtensions(), 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 1c3e864170d..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; @@ -53,7 +52,6 @@ import org.sonar.batch.index.Caches; import org.sonar.batch.index.DefaultIndex; import org.sonar.batch.issue.DefaultProjectIssues; import org.sonar.batch.issue.IssueCache; -import org.sonar.batch.issue.tracking.InitialOpenIssuesStack; import org.sonar.batch.issue.tracking.LocalIssueTracking; import org.sonar.batch.issue.tracking.ServerIssueRepository; import org.sonar.batch.mediumtest.ScanTaskObservers; @@ -64,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; @@ -83,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 { @@ -160,10 +157,10 @@ public class ProjectScanContainer extends ComponentContainer { InputPathCache.class, PathResolver.class, - // rules + // rules new ActiveRulesProvider(), - // issues + // issues IssueUpdater.class, FunctionExecutor.class, IssueWorkflow.class, @@ -172,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, @@ -205,22 +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, - - // Issue tracking - InitialOpenIssuesStack.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<Measure> 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..b9c8f06511b 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,18 @@ 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 +52,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 +87,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/main/java/org/sonar/batch/scan/report/ConsoleReport.java b/sonar-batch/src/main/java/org/sonar/batch/scan/report/ConsoleReport.java index e23e8a816e3..2634fdd9af9 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/report/ConsoleReport.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/report/ConsoleReport.java @@ -25,7 +25,7 @@ import org.sonar.api.Properties; import org.sonar.api.Property; import org.sonar.api.PropertyType; import org.sonar.api.config.Settings; -import org.sonar.api.issue.internal.DefaultIssue; +import org.sonar.core.issue.DefaultIssue; import org.sonar.api.rule.Severity; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/report/IssuesReportBuilder.java b/sonar-batch/src/main/java/org/sonar/batch/scan/report/IssuesReportBuilder.java index 72c48f9bb7a..43e423e7fa7 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/report/IssuesReportBuilder.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/report/IssuesReportBuilder.java @@ -23,7 +23,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.batch.BatchSide; import org.sonar.api.issue.Issue; -import org.sonar.api.issue.internal.DefaultIssue; +import org.sonar.core.issue.DefaultIssue; import org.sonar.api.resources.Project; import org.sonar.api.rule.RuleKey; import org.sonar.api.rules.Rule; diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/report/JSONReport.java b/sonar-batch/src/main/java/org/sonar/batch/scan/report/JSONReport.java index e2959d9352d..b13b5468d67 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/report/JSONReport.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/report/JSONReport.java @@ -34,7 +34,7 @@ import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.batch.rule.ActiveRules; import org.sonar.api.batch.rule.internal.DefaultActiveRule; import org.sonar.api.config.Settings; -import org.sonar.api.issue.internal.DefaultIssue; +import org.sonar.core.issue.DefaultIssue; import org.sonar.api.platform.Server; import org.sonar.api.resources.Project; import org.sonar.api.rule.RuleKey; diff --git a/sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorStorage.java b/sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorStorage.java index 0277408cbe4..4ddfe03452e 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorStorage.java +++ b/sonar-batch/src/main/java/org/sonar/batch/sensor/DefaultSensorStorage.java @@ -42,7 +42,7 @@ import org.sonar.api.batch.sensor.issue.Issue; import org.sonar.api.batch.sensor.measure.Measure; import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure; import org.sonar.api.config.Settings; -import org.sonar.api.issue.internal.DefaultIssue; +import org.sonar.core.issue.DefaultIssue; import org.sonar.api.measures.Formula; import org.sonar.api.measures.Metric; import org.sonar.api.measures.PersistenceMode; 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 5ce426696d5..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.api.issue.internal.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.<Measure>newArrayList( - new RuleMeasure(CoreMetrics.TECHNICAL_DEBT, - org.sonar.api.rules.Rule.create(ruleKey1.repository(), ruleKey1.rule()), null, null) - .setValue(5d * ONE_DAY_IN_MINUTES) - )); - decorator.decorate(resource, context); - - verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, 7d * ONE_DAY_IN_MINUTES); - verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, 7d * ONE_DAY_IN_MINUTES))); - verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, memoryEfficiency, 7d * ONE_DAY_IN_MINUTES))); - verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, efficiency, 7d * ONE_DAY_IN_MINUTES))); - } - - @Test - public void add_technical_debt_only_from_children_measures() { - when(issuable.issues()).thenReturn(Collections.<Issue>emptyList()); - - when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Lists.<Measure>newArrayList( - new RuleMeasure(CoreMetrics.TECHNICAL_DEBT, - org.sonar.api.rules.Rule.create(ruleKey1.repository(), ruleKey1.rule()) - , null, null).setValue(5d * ONE_DAY_IN_MINUTES), - - new RuleMeasure(CoreMetrics.TECHNICAL_DEBT, - org.sonar.api.rules.Rule.create(ruleKey2.repository(), ruleKey2.rule()) - , null, null).setValue(10d * ONE_DAY_IN_MINUTES) - )); - decorator.decorate(resource, context); - - verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, 15d * ONE_DAY_IN_MINUTES); - verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, 5d * ONE_DAY_IN_MINUTES))); - verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey2, 10d * ONE_DAY_IN_MINUTES))); - verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, memoryEfficiency, 5d * ONE_DAY_IN_MINUTES))); - verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, efficiency, 5d * ONE_DAY_IN_MINUTES))); - verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, reusability, 10d * ONE_DAY_IN_MINUTES))); - verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, modularity, 10d * ONE_DAY_IN_MINUTES))); - } - - @Test - public void always_save_technical_debt_for_positive_values() { - // 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<Measure> { - Metric metric = null; - Characteristic characteristic = null; - Double value = null; - - public IsCharacteristicMeasure(Metric metric, Characteristic characteristic, Double value) { - this.metric = metric; - this.characteristic = characteristic; - this.value = value; - } - - @Override - public boolean matches(Object o) { - if (!(o instanceof Measure)) { - return false; - } - Measure m = (Measure) o; - return ObjectUtils.equals(metric, m.getMetric()) && - ObjectUtils.equals(characteristic, m.getCharacteristic()) && - ObjectUtils.equals(value, m.getValue()); - } - - @Override - public void describeTo(Description description) { - description.appendText(new StringBuilder() - .append("value=").append(value).append(",") - .append("characteristic=").append(characteristic.key()).append(",") - .append("metric=").append(metric.getKey()).toString()); - } - } - - class IsRuleMeasure extends ArgumentMatcher<RuleMeasure> { - Metric metric = null; - RuleKey ruleKey = null; - Double value = null; - - public IsRuleMeasure(Metric metric, RuleKey ruleKey, Double value) { - this.metric = metric; - this.ruleKey = ruleKey; - this.value = value; - } - - @Override - public boolean matches(Object o) { - if (!(o instanceof RuleMeasure)) { - return false; - } - RuleMeasure m = (RuleMeasure) o; - return ObjectUtils.equals(metric, m.getMetric()) && - ObjectUtils.equals(ruleKey, 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 952075dec78..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.api.issue.internal.DefaultIssue; -import org.sonar.api.issue.internal.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 8de52b074c2..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.api.issue.internal.DefaultIssue; -import org.sonar.api.issue.internal.FieldDiffs; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Measure; -import org.sonar.api.measures.Metric; -import org.sonar.api.resources.Resource; -import org.sonar.api.test.IsMeasure; -import org.sonar.api.utils.Duration; -import org.sonar.batch.components.Period; -import org.sonar.batch.components.TimeMachineConfiguration; - -import 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<Measure> { - Metric metric = null; - Double var1 = null; - Double var2 = null; - - public IsVariationMeasure(Metric metric, Double var1, Double var2) { - this.metric = metric; - this.var1 = var1; - this.var2 = var2; - } - - public boolean matches(Object o) { - if (!(o instanceof Measure)) { - return false; - } - Measure m = (Measure) o; - return ObjectUtils.equals(metric, m.getMetric()) && - ObjectUtils.equals(var1, m.getVariation1()) && - ObjectUtils.equals(var2, m.getVariation2()); - } - } - -} diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/DefaultIssuableTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/DefaultIssuableTest.java index 42843ddd8ec..7f50a767efe 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/issue/DefaultIssuableTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/DefaultIssuableTest.java @@ -23,7 +23,7 @@ import java.util.Arrays; import java.util.List; import org.junit.Test; import org.sonar.api.issue.Issue; -import org.sonar.api.issue.internal.DefaultIssue; +import org.sonar.core.issue.DefaultIssue; import org.sonar.api.resources.Project; import org.sonar.batch.index.BatchComponent; diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/DefaultProjectIssuesTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/DefaultProjectIssuesTest.java index b46e3551a6d..99c6d5f7100 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/issue/DefaultProjectIssuesTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/DefaultProjectIssuesTest.java @@ -22,7 +22,7 @@ package org.sonar.batch.issue; import com.google.common.collect.Lists; import org.junit.Test; import org.sonar.api.issue.Issue; -import org.sonar.api.issue.internal.DefaultIssue; +import org.sonar.core.issue.DefaultIssue; import org.sonar.api.rule.RuleKey; import org.sonar.api.rule.Severity; diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/IssueCacheTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/IssueCacheTest.java index 25fefe6f13d..18e90aff802 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/issue/IssueCacheTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/IssueCacheTest.java @@ -26,7 +26,7 @@ import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; import org.junit.Test; import org.sonar.api.issue.Issue; -import org.sonar.api.issue.internal.DefaultIssue; +import org.sonar.core.issue.DefaultIssue; import org.sonar.api.rule.Severity; import javax.annotation.Nullable; diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/IssueFiltersTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/IssueFiltersTest.java index 46aea62325c..b99aefe9bb8 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/issue/IssueFiltersTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/IssueFiltersTest.java @@ -21,7 +21,7 @@ package org.sonar.batch.issue; import org.junit.Test; import org.sonar.api.issue.Issue; -import org.sonar.api.issue.internal.DefaultIssue; +import org.sonar.core.issue.DefaultIssue; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.any; 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 2577ba98a41..356b9f9e436 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 @@ -19,6 +19,8 @@ */ package org.sonar.batch.issue; +import java.util.Calendar; +import java.util.Date; import org.apache.commons.lang.time.DateUtils; import org.junit.Before; import org.junit.Test; @@ -26,10 +28,8 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; -import org.sonar.api.batch.debt.DebtRemediationFunction; import org.sonar.api.batch.rule.internal.ActiveRulesBuilder; import org.sonar.api.batch.rule.internal.RulesBuilder; -import org.sonar.api.issue.internal.DefaultIssue; import org.sonar.api.resources.File; import org.sonar.api.resources.Project; import org.sonar.api.resources.Resource; @@ -37,11 +37,8 @@ import org.sonar.api.rule.RuleKey; import org.sonar.api.rule.Severity; import org.sonar.api.rules.RulePriority; import org.sonar.api.rules.Violation; -import org.sonar.api.utils.Duration; import org.sonar.api.utils.MessageException; - -import java.util.Calendar; -import java.util.Date; +import org.sonar.core.issue.DefaultIssue; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.fail; @@ -249,110 +246,6 @@ public class ModuleIssuesTest { verifyZeroInteractions(cache); } - @Test - 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(); - - Date analysisDate = new Date(); - when(project.getAnalysisDate()).thenReturn(analysisDate); - - DefaultIssue issue = new DefaultIssue() - .setKey("ABCDE") - .setRuleKey(SQUID_RULE_KEY) - .setSeverity(Severity.CRITICAL) - .setEffortToFix(2d); - - when(filters.accept(issue)).thenReturn(true); - moduleIssues.initAndAddIssue(issue); - - ArgumentCaptor<DefaultIssue> argument = ArgumentCaptor.forClass(DefaultIssue.class); - verify(cache).put(argument.capture()); - assertThat(argument.getValue().debt()).isEqualTo(Duration.create(20L)); - } - - @Test - 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(); - - Date analysisDate = new Date(); - when(project.getAnalysisDate()).thenReturn(analysisDate); - - DefaultIssue issue = new DefaultIssue() - .setKey("ABCDE") - .setRuleKey(SQUID_RULE_KEY) - .setSeverity(Severity.CRITICAL) - .setEffortToFix(2d); - - when(filters.accept(issue)).thenReturn(true); - moduleIssues.initAndAddIssue(issue); - - ArgumentCaptor<DefaultIssue> argument = ArgumentCaptor.forClass(DefaultIssue.class); - verify(cache).put(argument.capture()); - assertThat(argument.getValue().debt()).isEqualTo(Duration.create(45L)); - } - - @Test - 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(); - - Date analysisDate = new Date(); - when(project.getAnalysisDate()).thenReturn(analysisDate); - - DefaultIssue issue = new DefaultIssue() - .setKey("ABCDE") - .setRuleKey(SQUID_RULE_KEY) - .setSeverity(Severity.CRITICAL) - .setEffortToFix(null); - - when(filters.accept(issue)).thenReturn(true); - moduleIssues.initAndAddIssue(issue); - - ArgumentCaptor<DefaultIssue> argument = ArgumentCaptor.forClass(DefaultIssue.class); - verify(cache).put(argument.capture()); - assertThat(argument.getValue().debt()).isEqualTo(Duration.create(10L)); - } - - @Test - 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(); - - DefaultIssue issue = new DefaultIssue() - .setKey("ABCDE") - .setRuleKey(SQUID_RULE_KEY) - .setSeverity(Severity.CRITICAL) - .setEffortToFix(2d); - - when(filters.accept(issue)).thenReturn(true); - - try { - moduleIssues.initAndAddIssue(issue); - fail(); - } catch (Exception e) { - assertThat(e).isInstanceOf(IllegalArgumentException.class) - .hasMessage("Rule 'squid:AvoidCycle' can not use 'Constant/issue' remediation function because this rule does not have a fixed remediation cost."); - } - } - /** * Every rules and active rules has to be added in builders before creating ModuleIssues */ diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/InitialOpenIssuesSensorTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/InitialOpenIssuesSensorTest.java deleted file mode 100644 index 1b4a6adf544..00000000000 --- a/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/InitialOpenIssuesSensorTest.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.issue.tracking; - -import org.apache.ibatis.session.ResultHandler; -import org.junit.Test; -import org.sonar.api.resources.Project; -import org.sonar.core.issue.db.IssueChangeDao; -import org.sonar.core.issue.db.IssueDao; -import org.sonar.core.resource.ResourceDao; -import org.sonar.core.resource.ResourceDto; -import org.sonar.core.resource.ResourceQuery; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; - -public class InitialOpenIssuesSensorTest { - - InitialOpenIssuesStack stack = mock(InitialOpenIssuesStack.class); - IssueDao issueDao = mock(IssueDao.class); - IssueChangeDao issueChangeDao = mock(IssueChangeDao.class); - ResourceDao resourceDao = mock(ResourceDao.class); - - InitialOpenIssuesSensor sensor = new InitialOpenIssuesSensor(stack, issueDao, issueChangeDao, resourceDao); - - @Test - public void should_select_module_open_issues() { - when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(new ResourceDto().setId(1L)); - - sensor.analyse(new Project("key"), null); - - verify(issueDao).selectNonClosedIssuesByModule(eq(1L), any(ResultHandler.class)); - } - - @Test - public void should_select_module_open_issues_changelog() { - when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(new ResourceDto().setId(1L)); - - sensor.analyse(new Project("key"), null); - - verify(issueChangeDao).selectChangelogOnNonClosedIssuesByModuleAndType(eq(1L), any(ResultHandler.class)); - } - - @Test - public void nothing_to_on_new_component() { - when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(null); - - sensor.analyse(new Project("key"), null); - - verifyZeroInteractions(issueDao); - verifyZeroInteractions(issueChangeDao); - } - - @Test - public void test_toString() throws Exception { - assertThat(sensor.toString()).isEqualTo("InitialOpenIssuesSensor"); - - } -} diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/InitialOpenIssuesStackTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/InitialOpenIssuesStackTest.java deleted file mode 100644 index c6f42f12b6a..00000000000 --- a/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/InitialOpenIssuesStackTest.java +++ /dev/null @@ -1,120 +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.issue.tracking; - -import org.sonar.batch.index.AbstractCachesTest; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.sonar.core.issue.db.IssueChangeDto; -import org.sonar.core.issue.db.IssueDto; - -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; - -public class InitialOpenIssuesStackTest extends AbstractCachesTest { - - InitialOpenIssuesStack stack; - - @Before - public void before() { - stack = new InitialOpenIssuesStack(caches); - } - - @After - public void after() { - caches.stop(); - } - - @Test - public void get_and_remove_issues() { - IssueDto issueDto = new IssueDto().setComponentKey("org.struts.Action").setKee("ISSUE-1"); - stack.addIssue(issueDto); - - List<ServerIssue> issueDtos = stack.selectAndRemoveIssues("org.struts.Action"); - assertThat(issueDtos).hasSize(1); - assertThat(issueDtos.get(0).key()).isEqualTo("ISSUE-1"); - - assertThat(stack.selectAllIssues()).isEmpty(); - } - - @Test - public void get_and_remove_with_many_issues_on_same_resource() { - stack.addIssue(new IssueDto().setComponentKey("org.struts.Action").setKee("ISSUE-1")); - stack.addIssue(new IssueDto().setComponentKey("org.struts.Action").setKee("ISSUE-2")); - - List<ServerIssue> issueDtos = stack.selectAndRemoveIssues("org.struts.Action"); - assertThat(issueDtos).hasSize(2); - - assertThat(stack.selectAllIssues()).isEmpty(); - } - - @Test - public void get_and_remove_do_nothing_if_resource_not_found() { - stack.addIssue(new IssueDto().setComponentKey("org.struts.Action").setKee("ISSUE-1")); - - List<ServerIssue> issueDtos = stack.selectAndRemoveIssues("Other"); - assertThat(issueDtos).hasSize(0); - - assertThat(stack.selectAllIssues()).hasSize(1); - } - - @Test - public void select_changelog() { - stack.addChangelog(new IssueChangeDto().setKey("CHANGE-1").setIssueKey("ISSUE-1")); - stack.addChangelog(new IssueChangeDto().setKey("CHANGE-2").setIssueKey("ISSUE-1")); - - List<IssueChangeDto> issueChangeDtos = stack.selectChangelog("ISSUE-1"); - assertThat(issueChangeDtos).hasSize(2); - assertThat(issueChangeDtos.get(0).getKey()).isEqualTo("CHANGE-1"); - assertThat(issueChangeDtos.get(1).getKey()).isEqualTo("CHANGE-2"); - } - - @Test - public void return_empty_changelog() { - assertThat(stack.selectChangelog("ISSUE-1")).isEmpty(); - } - - @Test - public void clear_issues() { - stack.addIssue(new IssueDto().setComponentKey("org.struts.Action").setKee("ISSUE-1")); - - assertThat(stack.selectAllIssues()).hasSize(1); - - // issues are not removed - assertThat(stack.selectAllIssues()).hasSize(1); - - stack.clear(); - assertThat(stack.selectAllIssues()).isEmpty(); - } - - @Test - public void clear_issues_changelog() { - stack.addChangelog(new IssueChangeDto().setKey("CHANGE-1").setIssueKey("ISSUE-1")); - - assertThat(stack.selectChangelog("ISSUE-1")).hasSize(1); - - stack.clear(); - assertThat(stack.selectChangelog("ISSUE-1")).isEmpty(); - } -} diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/IssueHandlersTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/IssueHandlersTest.java deleted file mode 100644 index fe81ee2006b..00000000000 --- a/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/IssueHandlersTest.java +++ /dev/null @@ -1,62 +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.issue.tracking; - -import org.junit.Test; -import org.mockito.ArgumentMatcher; -import org.sonar.api.issue.IssueHandler; -import org.sonar.api.issue.internal.DefaultIssue; -import org.sonar.api.issue.internal.IssueChangeContext; -import org.sonar.core.issue.IssueUpdater; - -import java.util.Date; - -import static org.mockito.Matchers.argThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; - -public class IssueHandlersTest { - @Test - public void should_execute_handlers() { - IssueHandler h1 = mock(IssueHandler.class); - IssueHandler h2 = mock(IssueHandler.class); - IssueUpdater updater = mock(IssueUpdater.class); - - IssueHandlers handlers = new IssueHandlers(updater, new IssueHandler[]{h1, h2}); - final DefaultIssue issue = new DefaultIssue(); - handlers.execute(issue, IssueChangeContext.createScan(new Date())); - - verify(h1).onIssue(argThat(new ArgumentMatcher<IssueHandler.Context>() { - @Override - public boolean matches(Object o) { - return ((IssueHandler.Context) o).issue() == issue; - } - })); - } - - @Test - public void test_no_handlers() { - IssueUpdater updater = mock(IssueUpdater.class); - IssueHandlers handlers = new IssueHandlers(updater); - handlers.execute(new DefaultIssue(), IssueChangeContext.createScan(new Date())); - verifyZeroInteractions(updater); - } -} diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/IssueTrackingDecoratorTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/IssueTrackingDecoratorTest.java deleted file mode 100644 index d09c7908d20..00000000000 --- a/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/IssueTrackingDecoratorTest.java +++ /dev/null @@ -1,584 +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.issue.tracking; - -import org.apache.commons.codec.digest.DigestUtils; -import org.apache.commons.io.FileUtils; -import org.apache.commons.lang.StringUtils; -import org.junit.Before; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.mockito.ArgumentCaptor; -import org.mockito.ArgumentMatcher; -import org.sonar.api.batch.DecoratorContext; -import org.sonar.api.batch.fs.internal.DefaultInputFile; -import org.sonar.api.component.ResourcePerspectives; -import org.sonar.api.issue.Issue; -import org.sonar.api.issue.internal.DefaultIssue; -import org.sonar.api.issue.internal.IssueChangeContext; -import org.sonar.api.profiles.RulesProfile; -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.Rule; -import org.sonar.api.rules.RuleFinder; -import org.sonar.api.utils.Duration; -import org.sonar.api.utils.System2; -import org.sonar.batch.issue.IssueCache; -import org.sonar.batch.scan.filesystem.InputPathCache; -import org.sonar.core.issue.IssueUpdater; -import org.sonar.core.issue.db.IssueChangeDto; -import org.sonar.core.issue.db.IssueDto; -import org.sonar.core.issue.workflow.IssueWorkflow; -import org.sonar.java.api.JavaClass; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.Collection; -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.Matchers.any; -import static org.mockito.Matchers.anyCollection; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.argThat; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.isA; -import static org.mockito.Mockito.RETURNS_MOCKS; -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.verifyZeroInteractions; -import static org.mockito.Mockito.when; - -public class IssueTrackingDecoratorTest { - - @org.junit.Rule - public TemporaryFolder temp = new TemporaryFolder(); - - IssueTrackingDecorator decorator; - IssueCache issueCache = mock(IssueCache.class, RETURNS_MOCKS); - InitialOpenIssuesStack initialOpenIssues = mock(InitialOpenIssuesStack.class); - IssueTracking tracking = mock(IssueTracking.class, RETURNS_MOCKS); - ServerLineHashesLoader lastSnapshots = mock(ServerLineHashesLoader.class); - IssueHandlers handlers = mock(IssueHandlers.class); - IssueWorkflow workflow = mock(IssueWorkflow.class); - IssueUpdater updater = mock(IssueUpdater.class); - ResourcePerspectives perspectives = mock(ResourcePerspectives.class); - RulesProfile profile = mock(RulesProfile.class); - RuleFinder ruleFinder = mock(RuleFinder.class); - InputPathCache inputPathCache = mock(InputPathCache.class); - - @Before - public void init() { - decorator = new IssueTrackingDecorator( - issueCache, - initialOpenIssues, - tracking, - lastSnapshots, - handlers, - workflow, - updater, - new Project("foo"), - perspectives, - profile, - ruleFinder, - inputPathCache); - } - - @Test - public void should_execute_on_project() { - Project project = mock(Project.class); - assertThat(decorator.shouldExecuteOnProject(project)).isTrue(); - } - - @Test - public void should_not_be_executed_on_classes_not_methods() { - DecoratorContext context = mock(DecoratorContext.class); - decorator.decorate(JavaClass.create("org.foo.Bar"), context); - verifyZeroInteractions(context, issueCache, tracking, handlers, workflow); - } - - @Test - public void should_process_open_issues() { - Resource file = File.create("Action.java").setEffectiveKey("struts:Action.java").setId(123); - final DefaultIssue issue = new DefaultIssue(); - - // INPUT : one issue, no open issues during previous scan, no filtering - when(issueCache.byComponent("struts:Action.java")).thenReturn(Arrays.asList(issue)); - List<ServerIssue> dbIssues = Collections.emptyList(); - when(initialOpenIssues.selectAndRemoveIssues("struts:Action.java")).thenReturn(dbIssues); - when(inputPathCache.getFile("foo", "Action.java")).thenReturn(mock(DefaultInputFile.class)); - decorator.doDecorate(file); - - // Apply filters, track, apply transitions, notify extensions then update cache - verify(tracking).track(isA(SourceHashHolder.class), eq(dbIssues), argThat(new ArgumentMatcher<Collection<DefaultIssue>>() { - @Override - public boolean matches(Object o) { - List<DefaultIssue> issues = (List<DefaultIssue>) o; - return issues.size() == 1 && issues.get(0) == issue; - } - })); - verify(workflow).doAutomaticTransition(eq(issue), any(IssueChangeContext.class)); - verify(handlers).execute(eq(issue), any(IssueChangeContext.class)); - verify(issueCache).put(issue); - } - - @Test - public void should_register_unmatched_issues_as_end_of_life() { - // "Unmatched" issues existed in previous scan but not in current one -> they have to be closed - Resource file = File.create("Action.java").setEffectiveKey("struts:Action.java").setId(123); - - // INPUT : one issue existing during previous scan - ServerIssue unmatchedIssue = new ServerIssueFromDb(new IssueDto().setKee("ABCDE").setResolution(null).setStatus("OPEN").setRuleKey("squid", "AvoidCycle")); - - IssueTrackingResult trackingResult = new IssueTrackingResult(); - trackingResult.addUnmatched(unmatchedIssue); - - when(tracking.track(isA(SourceHashHolder.class), anyCollection(), anyCollection())).thenReturn(trackingResult); - when(inputPathCache.getFile("foo", "Action.java")).thenReturn(mock(DefaultInputFile.class)); - - decorator.doDecorate(file); - - verify(workflow, times(1)).doAutomaticTransition(any(DefaultIssue.class), any(IssueChangeContext.class)); - verify(handlers, times(1)).execute(any(DefaultIssue.class), any(IssueChangeContext.class)); - - ArgumentCaptor<DefaultIssue> argument = ArgumentCaptor.forClass(DefaultIssue.class); - verify(issueCache).put(argument.capture()); - - DefaultIssue issue = argument.getValue(); - assertThat(issue.key()).isEqualTo("ABCDE"); - assertThat(issue.isNew()).isFalse(); - assertThat(issue.isEndOfLife()).isTrue(); - } - - @Test - public void manual_issues_should_be_moved_if_matching_line_found() throws Exception { - // INPUT : one issue existing during previous scan - ServerIssue unmatchedIssue = new ServerIssueFromDb(new IssueDto().setKee("ABCDE").setReporter("freddy").setLine(6).setStatus("OPEN").setRuleKey("manual", "Performance")); - when(ruleFinder.findByKey(RuleKey.of("manual", "Performance"))).thenReturn(new Rule("manual", "Performance")); - - IssueTrackingResult trackingResult = new IssueTrackingResult(); - trackingResult.addUnmatched(unmatchedIssue); - - String originalSource = "public interface Action {\n" - + " void method1();\n" - + " void method2();\n" - + " void method3();\n" - + " void method4();\n" - + " void method5();\n" // Original issue here - + "}"; - String newSource = "public interface Action {\n" - + " void method5();\n" // New issue here - + " void method1();\n" - + " void method2();\n" - + " void method3();\n" - + " void method4();\n" - + "}"; - Resource file = mockHashes(originalSource, newSource); - - when(tracking.track(isA(SourceHashHolder.class), anyCollection(), anyCollection())).thenReturn(trackingResult); - - decorator.doDecorate(file); - - verify(workflow, times(1)).doAutomaticTransition(any(DefaultIssue.class), any(IssueChangeContext.class)); - verify(handlers, times(1)).execute(any(DefaultIssue.class), any(IssueChangeContext.class)); - - ArgumentCaptor<DefaultIssue> argument = ArgumentCaptor.forClass(DefaultIssue.class); - verify(issueCache).put(argument.capture()); - - DefaultIssue issue = argument.getValue(); - assertThat(issue.line()).isEqualTo(2); - assertThat(issue.key()).isEqualTo("ABCDE"); - assertThat(issue.isNew()).isFalse(); - assertThat(issue.isEndOfLife()).isFalse(); - assertThat(issue.isOnDisabledRule()).isFalse(); - } - - private Resource mockHashes(String originalSource, String newSource) throws IOException { - DefaultInputFile inputFile = mock(DefaultInputFile.class); - java.io.File f = temp.newFile(); - when(inputFile.path()).thenReturn(f.toPath()); - when(inputFile.file()).thenReturn(f); - when(inputFile.charset()).thenReturn(StandardCharsets.UTF_8); - when(inputFile.lines()).thenReturn(StringUtils.countMatches(newSource, "\n") + 1); - FileUtils.write(f, newSource, StandardCharsets.UTF_8); - when(inputFile.key()).thenReturn("foo:Action.java"); - when(inputPathCache.getFile("foo", "Action.java")).thenReturn(inputFile); - when(lastSnapshots.getLineHashes("foo:Action.java")).thenReturn(computeHexHashes(originalSource)); - Resource file = File.create("Action.java"); - return file; - } - - @Test - public void manual_issues_should_be_untouched_if_already_closed() throws Exception { - - // INPUT : one issue existing during previous scan - ServerIssue unmatchedIssue = new ServerIssueFromDb(new IssueDto().setKee("ABCDE").setReporter("freddy").setLine(1).setStatus("CLOSED").setRuleKey("manual", "Performance")); - when(ruleFinder.findByKey(RuleKey.of("manual", "Performance"))).thenReturn(new Rule("manual", "Performance")); - - IssueTrackingResult trackingResult = new IssueTrackingResult(); - trackingResult.addUnmatched(unmatchedIssue); - - String originalSource = "public interface Action {}"; - Resource file = mockHashes(originalSource, originalSource); - - when(tracking.track(isA(SourceHashHolder.class), anyCollection(), anyCollection())).thenReturn(trackingResult); - - decorator.doDecorate(file); - - verify(workflow, times(1)).doAutomaticTransition(any(DefaultIssue.class), any(IssueChangeContext.class)); - verify(handlers, times(1)).execute(any(DefaultIssue.class), any(IssueChangeContext.class)); - - ArgumentCaptor<DefaultIssue> argument = ArgumentCaptor.forClass(DefaultIssue.class); - verify(issueCache).put(argument.capture()); - - DefaultIssue issue = argument.getValue(); - assertThat(issue.line()).isEqualTo(1); - assertThat(issue.key()).isEqualTo("ABCDE"); - assertThat(issue.isNew()).isFalse(); - assertThat(issue.isEndOfLife()).isFalse(); - assertThat(issue.isOnDisabledRule()).isFalse(); - assertThat(issue.status()).isEqualTo("CLOSED"); - } - - @Test - public void manual_issues_should_be_untouched_if_line_is_null() throws Exception { - - // INPUT : one issue existing during previous scan - ServerIssue unmatchedIssue = new ServerIssueFromDb(new IssueDto().setKee("ABCDE").setReporter("freddy").setLine(null).setStatus("OPEN").setRuleKey("manual", "Performance")); - when(ruleFinder.findByKey(RuleKey.of("manual", "Performance"))).thenReturn(new Rule("manual", "Performance")); - - IssueTrackingResult trackingResult = new IssueTrackingResult(); - trackingResult.addUnmatched(unmatchedIssue); - - String originalSource = "public interface Action {}"; - Resource file = mockHashes(originalSource, originalSource); - - when(tracking.track(isA(SourceHashHolder.class), anyCollection(), anyCollection())).thenReturn(trackingResult); - - decorator.doDecorate(file); - - verify(workflow, times(1)).doAutomaticTransition(any(DefaultIssue.class), any(IssueChangeContext.class)); - verify(handlers, times(1)).execute(any(DefaultIssue.class), any(IssueChangeContext.class)); - - ArgumentCaptor<DefaultIssue> argument = ArgumentCaptor.forClass(DefaultIssue.class); - verify(issueCache).put(argument.capture()); - - DefaultIssue issue = argument.getValue(); - assertThat(issue.line()).isEqualTo(null); - assertThat(issue.key()).isEqualTo("ABCDE"); - assertThat(issue.isNew()).isFalse(); - assertThat(issue.isEndOfLife()).isFalse(); - assertThat(issue.isOnDisabledRule()).isFalse(); - assertThat(issue.status()).isEqualTo("OPEN"); - } - - @Test - public void manual_issues_should_be_kept_if_matching_line_not_found() throws Exception { - // "Unmatched" issues existed in previous scan but not in current one -> they have to be closed - - // INPUT : one issue existing during previous scan - final int issueOnLine = 6; - ServerIssue unmatchedIssue = new ServerIssueFromDb(new IssueDto().setKee("ABCDE").setReporter("freddy").setLine(issueOnLine).setStatus("OPEN") - .setRuleKey("manual", "Performance")); - when(ruleFinder.findByKey(RuleKey.of("manual", "Performance"))).thenReturn(new Rule("manual", "Performance")); - - IssueTrackingResult trackingResult = new IssueTrackingResult(); - trackingResult.addUnmatched(unmatchedIssue); - - String originalSource = "public interface Action {\n" - + " void method1();\n" - + " void method2();\n" - + " void method3();\n" - + " void method4();\n" - + " void method5();\n" // Original issue here - + "}"; - String newSource = "public interface Action {\n" - + " void method1();\n" - + " void method2();\n" - + " void method3();\n" - + " void method4();\n" - + " void method6();\n" // Poof, no method5 anymore - + "}"; - - Resource file = mockHashes(originalSource, newSource); - - when(tracking.track(isA(SourceHashHolder.class), anyCollection(), anyCollection())).thenReturn(trackingResult); - - decorator.doDecorate(file); - - verify(workflow, times(1)).doAutomaticTransition(any(DefaultIssue.class), any(IssueChangeContext.class)); - verify(handlers, times(1)).execute(any(DefaultIssue.class), any(IssueChangeContext.class)); - - ArgumentCaptor<DefaultIssue> argument = ArgumentCaptor.forClass(DefaultIssue.class); - verify(issueCache).put(argument.capture()); - - DefaultIssue issue = argument.getValue(); - assertThat(issue.line()).isEqualTo(issueOnLine); - assertThat(issue.key()).isEqualTo("ABCDE"); - assertThat(issue.isNew()).isFalse(); - assertThat(issue.isEndOfLife()).isFalse(); - assertThat(issue.isOnDisabledRule()).isFalse(); - } - - @Test - public void manual_issues_should_be_kept_if_multiple_matching_lines_found() throws Exception { - // "Unmatched" issues existed in previous scan but not in current one -> they have to be closed - - // INPUT : one issue existing during previous scan - final int issueOnLine = 3; - ServerIssue unmatchedIssue = new ServerIssueFromDb(new IssueDto().setKee("ABCDE").setReporter("freddy").setLine(issueOnLine).setStatus("OPEN") - .setRuleKey("manual", "Performance")); - when(ruleFinder.findByKey(RuleKey.of("manual", "Performance"))).thenReturn(new Rule("manual", "Performance")); - - IssueTrackingResult trackingResult = new IssueTrackingResult(); - trackingResult.addUnmatched(unmatchedIssue); - - String originalSource = "public class Action {\n" - + " void method1() {\n" - + " notify();\n" // initial issue - + " }\n" - + "}"; - String newSource = "public class Action {\n" - + " \n" - + " void method1() {\n" // new issue will appear here - + " notify();\n" - + " }\n" - + " void method2() {\n" - + " notify();\n" - + " }\n" - + "}"; - Resource file = mockHashes(originalSource, newSource); - - when(tracking.track(isA(SourceHashHolder.class), anyCollection(), anyCollection())).thenReturn(trackingResult); - - decorator.doDecorate(file); - - verify(workflow, times(1)).doAutomaticTransition(any(DefaultIssue.class), any(IssueChangeContext.class)); - verify(handlers, times(1)).execute(any(DefaultIssue.class), any(IssueChangeContext.class)); - - ArgumentCaptor<DefaultIssue> argument = ArgumentCaptor.forClass(DefaultIssue.class); - verify(issueCache).put(argument.capture()); - - DefaultIssue issue = argument.getValue(); - assertThat(issue.line()).isEqualTo(issueOnLine); - assertThat(issue.key()).isEqualTo("ABCDE"); - assertThat(issue.isNew()).isFalse(); - assertThat(issue.isEndOfLife()).isFalse(); - assertThat(issue.isOnDisabledRule()).isFalse(); - } - - @Test - public void manual_issues_should_be_closed_if_manual_rule_is_removed() throws Exception { - // "Unmatched" issues existed in previous scan but not in current one -> they have to be closed - - // INPUT : one issue existing during previous scan - ServerIssue unmatchedIssue = new ServerIssueFromDb(new IssueDto().setKee("ABCDE").setReporter("freddy").setLine(1).setStatus("OPEN").setRuleKey("manual", "Performance")); - when(ruleFinder.findByKey(RuleKey.of("manual", "Performance"))).thenReturn(new Rule("manual", "Performance").setStatus(Rule.STATUS_REMOVED)); - - IssueTrackingResult trackingResult = new IssueTrackingResult(); - trackingResult.addUnmatched(unmatchedIssue); - - String source = "public interface Action {}"; - Resource file = mockHashes(source, source); - - when(tracking.track(isA(SourceHashHolder.class), anyCollection(), anyCollection())).thenReturn(trackingResult); - - decorator.doDecorate(file); - - verify(workflow, times(1)).doAutomaticTransition(any(DefaultIssue.class), any(IssueChangeContext.class)); - verify(handlers, times(1)).execute(any(DefaultIssue.class), any(IssueChangeContext.class)); - - ArgumentCaptor<DefaultIssue> argument = ArgumentCaptor.forClass(DefaultIssue.class); - verify(issueCache).put(argument.capture()); - - DefaultIssue issue = argument.getValue(); - assertThat(issue.key()).isEqualTo("ABCDE"); - assertThat(issue.isNew()).isFalse(); - assertThat(issue.isEndOfLife()).isTrue(); - assertThat(issue.isOnDisabledRule()).isTrue(); - } - - @Test - public void manual_issues_should_be_closed_if_manual_rule_is_not_found() throws Exception { - // "Unmatched" issues existed in previous scan but not in current one -> they have to be closed - - // INPUT : one issue existing during previous scan - ServerIssue unmatchedIssue = new ServerIssueFromDb(new IssueDto().setKee("ABCDE").setReporter("freddy").setLine(1).setStatus("OPEN").setRuleKey("manual", "Performance")); - when(ruleFinder.findByKey(RuleKey.of("manual", "Performance"))).thenReturn(null); - - IssueTrackingResult trackingResult = new IssueTrackingResult(); - trackingResult.addUnmatched(unmatchedIssue); - - String source = "public interface Action {}"; - Resource file = mockHashes(source, source); - - when(tracking.track(isA(SourceHashHolder.class), anyCollection(), anyCollection())).thenReturn(trackingResult); - - decorator.doDecorate(file); - - verify(workflow, times(1)).doAutomaticTransition(any(DefaultIssue.class), any(IssueChangeContext.class)); - verify(handlers, times(1)).execute(any(DefaultIssue.class), any(IssueChangeContext.class)); - - ArgumentCaptor<DefaultIssue> argument = ArgumentCaptor.forClass(DefaultIssue.class); - verify(issueCache).put(argument.capture()); - - DefaultIssue issue = argument.getValue(); - assertThat(issue.key()).isEqualTo("ABCDE"); - assertThat(issue.isNew()).isFalse(); - assertThat(issue.isEndOfLife()).isTrue(); - assertThat(issue.isOnDisabledRule()).isTrue(); - } - - @Test - public void manual_issues_should_be_closed_if_new_source_is_shorter() throws Exception { - // "Unmatched" issues existed in previous scan but not in current one -> they have to be closed - - // INPUT : one issue existing during previous scan - ServerIssue unmatchedIssue = new ServerIssueFromDb(new IssueDto().setKee("ABCDE").setReporter("freddy").setLine(6).setStatus("OPEN").setRuleKey("manual", "Performance")); - when(ruleFinder.findByKey(RuleKey.of("manual", "Performance"))).thenReturn(null); - - IssueTrackingResult trackingResult = new IssueTrackingResult(); - trackingResult.addUnmatched(unmatchedIssue); - - String originalSource = "public interface Action {\n" - + " void method1();\n" - + " void method2();\n" - + " void method3();\n" - + " void method4();\n" - + " void method5();\n" - + "}"; - String newSource = "public interface Action {\n" - + " void method1();\n" - + " void method2();\n" - + "}"; - Resource file = mockHashes(originalSource, newSource); - - when(tracking.track(isA(SourceHashHolder.class), anyCollection(), anyCollection())).thenReturn(trackingResult); - - decorator.doDecorate(file); - - verify(workflow, times(1)).doAutomaticTransition(any(DefaultIssue.class), any(IssueChangeContext.class)); - verify(handlers, times(1)).execute(any(DefaultIssue.class), any(IssueChangeContext.class)); - - ArgumentCaptor<DefaultIssue> argument = ArgumentCaptor.forClass(DefaultIssue.class); - verify(issueCache).put(argument.capture()); - - DefaultIssue issue = argument.getValue(); - verify(updater).setResolution(eq(issue), eq(Issue.RESOLUTION_REMOVED), any(IssueChangeContext.class)); - verify(updater).setStatus(eq(issue), eq(Issue.STATUS_CLOSED), any(IssueChangeContext.class)); - - assertThat(issue.key()).isEqualTo("ABCDE"); - assertThat(issue.isNew()).isFalse(); - assertThat(issue.isEndOfLife()).isTrue(); - assertThat(issue.isOnDisabledRule()).isTrue(); - } - - @Test - public void should_register_issues_on_deleted_components() { - Project project = new Project("struts"); - DefaultIssue openIssue = new DefaultIssue(); - when(issueCache.byComponent("struts")).thenReturn(Arrays.asList(openIssue)); - IssueDto deadIssue = new IssueDto().setKee("ABCDE").setResolution(null).setStatus("OPEN").setRuleKey("squid", "AvoidCycle"); - when(initialOpenIssues.selectAllIssues()).thenReturn(Arrays.asList(deadIssue)); - - decorator.doDecorate(project); - - // the dead issue must be closed -> apply automatic transition, notify handlers and add to cache - verify(workflow, times(2)).doAutomaticTransition(any(DefaultIssue.class), any(IssueChangeContext.class)); - verify(handlers, times(2)).execute(any(DefaultIssue.class), any(IssueChangeContext.class)); - verify(issueCache, times(2)).put(any(DefaultIssue.class)); - - verify(issueCache).put(argThat(new ArgumentMatcher<DefaultIssue>() { - @Override - public boolean matches(Object o) { - DefaultIssue dead = (DefaultIssue) o; - return "ABCDE".equals(dead.key()) && !dead.isNew() && dead.isEndOfLife(); - } - })); - } - - @Test - public void merge_matched_issue() { - ServerIssue previousIssue = new ServerIssueFromDb(new IssueDto().setKee("ABCDE").setResolution(null).setStatus("OPEN").setRuleKey("squid", "AvoidCycle") - .setLine(10).setSeverity("MAJOR").setMessage("Message").setEffortToFix(1.5).setDebt(1L).setProjectKey("sample")); - DefaultIssue issue = new DefaultIssue(); - - IssueTrackingResult trackingResult = mock(IssueTrackingResult.class); - when(trackingResult.matched()).thenReturn(newArrayList(issue)); - when(trackingResult.matching(eq(issue))).thenReturn(previousIssue); - decorator.mergeMatched(trackingResult); - - verify(updater).setPastSeverity(eq(issue), eq("MAJOR"), any(IssueChangeContext.class)); - verify(updater).setPastLine(eq(issue), eq(10)); - verify(updater).setPastMessage(eq(issue), eq("Message"), any(IssueChangeContext.class)); - verify(updater).setPastEffortToFix(eq(issue), eq(1.5), any(IssueChangeContext.class)); - verify(updater).setPastTechnicalDebt(eq(issue), eq(Duration.create(1L)), any(IssueChangeContext.class)); - verify(updater).setPastProject(eq(issue), eq("sample"), any(IssueChangeContext.class)); - } - - @Test - public void merge_matched_issue_on_manual_severity() { - ServerIssue previousIssue = new ServerIssueFromDb(new IssueDto().setKee("ABCDE").setResolution(null).setStatus("OPEN").setRuleKey("squid", "AvoidCycle") - .setLine(10).setManualSeverity(true).setSeverity("MAJOR").setMessage("Message").setEffortToFix(1.5).setDebt(1L)); - DefaultIssue issue = new DefaultIssue(); - - IssueTrackingResult trackingResult = mock(IssueTrackingResult.class); - when(trackingResult.matched()).thenReturn(newArrayList(issue)); - when(trackingResult.matching(eq(issue))).thenReturn(previousIssue); - decorator.mergeMatched(trackingResult); - - assertThat(issue.manualSeverity()).isTrue(); - assertThat(issue.severity()).isEqualTo("MAJOR"); - verify(updater, never()).setPastSeverity(eq(issue), anyString(), any(IssueChangeContext.class)); - } - - @Test - public void merge_issue_changelog_with_previous_changelog() { - when(initialOpenIssues.selectChangelog("ABCDE")).thenReturn(newArrayList(new IssueChangeDto().setIssueKey("ABCD").setCreatedAt(System2.INSTANCE.now()))); - - ServerIssue previousIssue = new ServerIssueFromDb(new IssueDto().setKee("ABCDE").setResolution(null).setStatus("OPEN").setRuleKey("squid", "AvoidCycle") - .setLine(10).setMessage("Message").setEffortToFix(1.5).setDebt(1L).setCreatedAt(System2.INSTANCE.now())); - DefaultIssue issue = new DefaultIssue(); - - IssueTrackingResult trackingResult = mock(IssueTrackingResult.class); - when(trackingResult.matched()).thenReturn(newArrayList(issue)); - when(trackingResult.matching(eq(issue))).thenReturn(previousIssue); - decorator.mergeMatched(trackingResult); - - assertThat(issue.changes()).hasSize(1); - } - - private String[] computeHexHashes(String source) { - String[] lines = source.split("\n"); - String[] hashes = new String[lines.length]; - for (int i = 0; i < lines.length; i++) { - hashes[i] = DigestUtils.md5Hex(lines[i].replaceAll("[\t ]", "")); - } - return hashes; - } - -} diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/IssueTrackingTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/IssueTrackingTest.java index 062c539b457..616c7fb6ed4 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/IssueTrackingTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/IssueTrackingTest.java @@ -32,7 +32,7 @@ import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.issue.Issue; -import org.sonar.api.issue.internal.DefaultIssue; +import org.sonar.core.issue.DefaultIssue; import org.sonar.api.resources.Project; import org.sonar.api.resources.Resource; import org.sonar.api.rule.RuleKey; @@ -246,7 +246,7 @@ public class IssueTrackingTest { DefaultIssue newIssue = newDefaultIssue("1 branch need to be covered", 200, RuleKey.of("squid", "AvoidCycle"), null); thrown - .expectMessage("Invalid line number for issue DefaultIssue[key=<null>,componentUuid=<null>,componentKey=<null>,moduleUuid=<null>,moduleUuidPath=<null>,projectUuid=<null>,projectKey=<null>,ruleKey=squid:AvoidCycle,language=<null>,severity=<null>,manualSeverity=false,message=1 branch need to be covered,line=200,effortToFix=<null>,debt=<null>,status=OPEN,resolution=<null>,reporter=<null>,assignee=<null>,checksum=<null>,attributes=<null>,authorLogin=<null>,actionPlanKey=<null>,comments=<null>,tags=<null>,creationDate=<null>,updateDate=<null>,closeDate=<null>,currentChange=<null>,changes=<null>,isNew=true,endOfLife=false,onDisabledRule=false,isChanged=false,sendNotifications=false,selectedAt=<null>]. File has only 17 line(s)"); + .expectMessage("Invalid line number for issue"); tracking.track(sourceHashHolder, Collections.<ServerIssue>emptyList(), newArrayList(newIssue)); } diff --git a/sonar-batch/src/test/java/org/sonar/batch/postjob/DefaultPostJobContextTest.java b/sonar-batch/src/test/java/org/sonar/batch/postjob/DefaultPostJobContextTest.java index 5db240ddeb5..081dcb968b5 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/postjob/DefaultPostJobContextTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/postjob/DefaultPostJobContextTest.java @@ -26,7 +26,7 @@ import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.postjob.issue.Issue; import org.sonar.api.batch.rule.Severity; import org.sonar.api.config.Settings; -import org.sonar.api.issue.internal.DefaultIssue; +import org.sonar.core.issue.DefaultIssue; import org.sonar.api.resources.File; import org.sonar.batch.index.BatchComponentCache; import org.sonar.batch.issue.IssueCache; diff --git a/sonar-batch/src/test/java/org/sonar/batch/profiling/PhasesSumUpTimeProfilerTest.java b/sonar-batch/src/test/java/org/sonar/batch/profiling/PhasesSumUpTimeProfilerTest.java index 0aa11588a8c..1ff8b82c9c4 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/profiling/PhasesSumUpTimeProfilerTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/profiling/PhasesSumUpTimeProfilerTest.java @@ -20,6 +20,10 @@ package org.sonar.batch.profiling; import com.google.common.collect.Maps; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -48,14 +52,6 @@ import org.sonar.api.resources.Resource; import org.sonar.api.utils.System2; import org.sonar.batch.bootstrap.BootstrapProperties; import org.sonar.batch.events.BatchStepEvent; -import org.sonar.batch.index.ScanPersister; -import org.sonar.batch.phases.event.PersisterExecutionHandler; -import org.sonar.batch.phases.event.PersistersPhaseHandler; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.spy; @@ -88,7 +84,6 @@ public class PhasesSumUpTimeProfilerTest { assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.INIT).getProfilingPerItem(new FakeInitializer()).totalTime()).isEqualTo(7L); assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.SENSOR).getProfilingPerItem(new FakeSensor()).totalTime()).isEqualTo(10L); assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.DECORATOR).getProfilingPerItem(new FakeDecorator1()).totalTime()).isEqualTo(20L); - assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.PERSISTER).getProfilingPerItem(new FakeScanPersister()).totalTime()).isEqualTo(40L); assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.POSTJOB).getProfilingPerItem(new FakePostJob()).totalTime()).isEqualTo(30L); assertThat(profiler.currentModuleProfiling.getProfilingPerBatchStep("Free memory").totalTime()).isEqualTo(9L); @@ -109,14 +104,12 @@ public class PhasesSumUpTimeProfilerTest { assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.SENSOR).getProfilingPerItem(new FakeSensor()).totalTime()).isEqualTo(10L); assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.DECORATOR).getProfilingPerItem(new FakeDecorator1()).totalTime()).isEqualTo(20L); assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.DECORATOR).getProfilingPerItem(new FakeDecorator2()).totalTime()).isEqualTo(10L); - assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.PERSISTER).getProfilingPerItem(new FakeScanPersister()).totalTime()).isEqualTo(40L); assertThat(profiler.currentModuleProfiling.getProfilingPerPhase(Phase.POSTJOB).getProfilingPerItem(new FakePostJob()).totalTime()).isEqualTo(30L); assertThat(profiler.totalProfiling.getProfilingPerPhase(Phase.INIT).getProfilingPerItem(new FakeInitializer()).totalTime()).isEqualTo(21L); assertThat(profiler.totalProfiling.getProfilingPerPhase(Phase.SENSOR).getProfilingPerItem(new FakeSensor()).totalTime()).isEqualTo(30L); assertThat(profiler.totalProfiling.getProfilingPerPhase(Phase.DECORATOR).getProfilingPerItem(new FakeDecorator1()).totalTime()).isEqualTo(60L); assertThat(profiler.totalProfiling.getProfilingPerPhase(Phase.DECORATOR).getProfilingPerItem(new FakeDecorator2()).totalTime()).isEqualTo(30L); - assertThat(profiler.totalProfiling.getProfilingPerPhase(Phase.PERSISTER).getProfilingPerItem(new FakeScanPersister()).totalTime()).isEqualTo(120L); assertThat(profiler.totalProfiling.getProfilingPerPhase(Phase.POSTJOB).getProfilingPerItem(new FakePostJob()).totalTime()).isEqualTo(90L); } @@ -164,7 +157,6 @@ public class PhasesSumUpTimeProfilerTest { initializerPhase(profiler); sensorPhase(profiler); decoratorPhase(profiler); - persistersPhase(profiler); postJobPhase(profiler); batchStep(profiler); // End of moduleA @@ -234,19 +226,6 @@ public class PhasesSumUpTimeProfilerTest { profiler.onSensorsPhase(sensorsEvent(false)); } - private void persistersPhase(PhasesSumUpTimeProfiler profiler) { - ScanPersister persister = new FakeScanPersister(); - // Start of persister phase - profiler.onPersistersPhase(persistersEvent(true)); - // Start of a ScanPersister - profiler.onPersisterExecution(persisterEvent(persister, true)); - clock.sleep(40); - // End of a ScanPersister - profiler.onPersisterExecution(persisterEvent(persister, false)); - // End of persister phase - profiler.onPersistersPhase(persistersEvent(false)); - } - private void postJobPhase(PhasesSumUpTimeProfiler profiler) { PostJob postJob = new FakePostJob(); // Start of sensor phase @@ -340,26 +319,6 @@ public class PhasesSumUpTimeProfilerTest { }; } - private PersisterExecutionHandler.PersisterExecutionEvent persisterEvent(final ScanPersister persister, final boolean start) { - return new PersisterExecutionHandler.PersisterExecutionEvent() { - - @Override - public boolean isStart() { - return start; - } - - @Override - public boolean isEnd() { - return !start; - } - - @Override - public ScanPersister getPersister() { - return persister; - } - }; - } - private SensorsPhaseEvent sensorsEvent(final boolean start) { return new SensorsPhaseHandler.SensorsPhaseEvent() { @@ -420,26 +379,6 @@ public class PhasesSumUpTimeProfilerTest { }; } - private PersistersPhaseHandler.PersistersPhaseEvent persistersEvent(final boolean start) { - return new PersistersPhaseHandler.PersistersPhaseEvent() { - - @Override - public boolean isStart() { - return start; - } - - @Override - public boolean isEnd() { - return !start; - } - - @Override - public List<ScanPersister> getPersisters() { - return null; - } - }; - } - private DecoratorsPhaseHandler.DecoratorsPhaseEvent decoratorsEvent(final boolean start) { return new DecoratorsPhaseHandler.DecoratorsPhaseEvent() { @@ -528,10 +467,4 @@ public class PhasesSumUpTimeProfilerTest { public void executeOn(Project project, SensorContext context) { } } - - public class FakeScanPersister implements ScanPersister { - @Override - public void persist() { - } - } } 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 8e49ddb719f..a27ce7d2447 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,20 +27,16 @@ 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.issue.internal.DefaultIssue; -import org.sonar.api.issue.internal.FieldDiffs; import org.sonar.api.resources.Project; 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; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.anyString; @@ -52,29 +48,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.<DefaultIssue>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"); @@ -86,7 +80,6 @@ public class IssuesPublisherTest { issue2.setLine(2); issue2.setMessage("msg"); issue2.setEffortToFix(2d); - issue2.setDebt(Duration.create(2)); issue2.setResolution("FIXED"); issue2.setStatus("RESOLVED"); issue2.setChecksum("checksum"); @@ -104,85 +97,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(metadata.getDeletedComponentsCount()).isEqualTo(0); - assertThat(reader.readComponentIssues(1)).hasSize(0); assertThat(reader.readComponentIssues(2)).hasSize(2); - - } - - @Test - public void publishMatadataWithBranch() 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"); - assertThat(metadata.getDeletedComponentsCount()).isEqualTo(0); } - @Test - public void publishIssuesOfDeletedComponents() throws Exception { - - DefaultIssue issue1 = new DefaultIssue(); - issue1.setKey("uuid"); - issue1.setComponentUuid("deletedUuid"); - issue1.setSeverity("MAJOR"); - issue1.setRuleKey(RuleKey.of("repo", "rule")); - DefaultIssue issue2 = new DefaultIssue(); - issue2.setKey("uuid2"); - issue2.setComponentUuid("deletedUuid"); - issue2.setSeverity("MAJOR"); - issue2.setRuleKey(RuleKey.of("repo", "rule")); - issue2.setLine(2); - issue2.setMessage("msg"); - issue2.setEffortToFix(2d); - issue2.setDebt(Duration.create(2)); - issue2.setResolution("FIXED"); - issue2.setStatus("RESOLVED"); - issue2.setChecksum("checksum"); - issue2.setReporter("reporter"); - issue2.setAssignee("assignee"); - issue2.setActionPlanKey("action"); - issue2.setAuthorLogin("author"); - issue2.setCurrentChange(new FieldDiffs().setUserLogin("foo")); - issue2.setCreationDate(new Date()); - issue2.setUpdateDate(new Date()); - issue2.setCloseDate(new Date()); - issue2.setSelectedAt(1234L); - - when(issueCache.byComponent("foo:deleted.php")).thenReturn(Arrays.asList(issue1, issue2)); - - when(issueCache.componentKeys()).thenReturn(Arrays.<Object>asList("foo:deleted.php")); - - File outputDir = temp.newFolder(); - BatchReportWriter writer = new BatchReportWriter(outputDir); - - publisher.publish(writer); - - BatchReportReader reader = new BatchReportReader(outputDir); - Metadata metadata = reader.readMetadata(); - assertThat(metadata.getDeletedComponentsCount()).isEqualTo(1); - - assertThat(reader.readComponentIssues(1)).hasSize(0); - assertThat(reader.readComponentIssues(2)).hasSize(0); - assertThat(reader.readDeletedComponentIssues(1).getComponentUuid()).isEqualTo("deletedUuid"); - assertThat(reader.readDeletedComponentIssues(1).getIssueList()).hasSize(2); - - } } 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 658cafcc62d..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 @@ -19,6 +19,11 @@ */ package org.sonar.batch.report; +import java.io.File; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.List; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -30,23 +35,14 @@ import org.sonar.api.measures.Metric; 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.Project; import org.sonar.api.resources.Resource; -import org.sonar.api.rule.RuleKey; -import org.sonar.api.rules.RulePriority; -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 java.io.File; -import java.util.Arrays; -import java.util.Collections; -import java.util.Date; -import java.util.List; - +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; @@ -85,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) @@ -103,9 +95,6 @@ public class MeasuresPublisherTest { Measure manual = new Measure<>(new Metric<>("manual_metric", ValueType.BOOL)) .setValue(1.0) .setDescription("Manual"); - // Rule measure - RuleMeasure ruleMeasureBySeverity = RuleMeasure.createForPriority(CoreMetrics.NCLOC, RulePriority.BLOCKER, 1.0); - RuleMeasure ruleMeasureByRule = RuleMeasure.createForRule(CoreMetrics.NCLOC, RuleKey.of("squid", "S12345"), 1.0); // Sqale rating have both a value and a data Measure rating = new Measure<>(CoreMetrics.SQALE_RATING) .setValue(2.0) @@ -116,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, ruleMeasureBySeverity, ruleMeasureByRule, rating, longMeasure, stringMeasure)); + when(measureCache.byResource(sampleFile)).thenReturn(asList(measure1, measure2, manual, rating, longMeasure, stringMeasure)); File outputDir = temp.newFolder(); BatchReportWriter writer = new BatchReportWriter(outputDir); @@ -128,10 +116,8 @@ public class MeasuresPublisherTest { assertThat(reader.readComponentMeasures(1)).hasSize(0); List<org.sonar.batch.protocol.output.BatchReport.Measure> 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.<NewActiveRule>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 0575a850182..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 @@ -19,7 +19,8 @@ */ package org.sonar.batch.scan.measure; -import org.sonar.batch.index.AbstractCachesTest; +import java.util.Date; +import java.util.Iterator; import org.apache.commons.lang.builder.EqualsBuilder; import org.junit.Before; import org.junit.Rule; @@ -29,22 +30,13 @@ import org.sonar.api.batch.measure.MetricFinder; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.Measure; import org.sonar.api.measures.Metric.Level; -import org.sonar.api.measures.RuleMeasure; 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.rule.RuleKey; -import org.sonar.api.rules.RulePriority; -import org.sonar.api.technicaldebt.batch.Characteristic; -import org.sonar.api.technicaldebt.batch.Requirement; -import org.sonar.api.technicaldebt.batch.TechnicalDebtModel; -import org.sonar.api.technicaldebt.batch.internal.DefaultCharacteristic; +import org.sonar.batch.index.AbstractCachesTest; import org.sonar.batch.index.Cache.Entry; -import java.util.Date; -import java.util.Iterator; - import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -55,8 +47,6 @@ public class MeasureCacheTest extends AbstractCachesTest { private MetricFinder metricFinder; - private TechnicalDebtModel techDebtModel; - private MeasureCache measureCache; @Before @@ -64,8 +54,7 @@ public class MeasureCacheTest extends AbstractCachesTest { super.start(); metricFinder = mock(MetricFinder.class); when(metricFinder.findByKey(CoreMetrics.NCLOC_KEY)).thenReturn(CoreMetrics.NCLOC); - techDebtModel = mock(TechnicalDebtModel.class); - measureCache = new MeasureCache(caches, metricFinder, techDebtModel); + measureCache = new MeasureCache(caches, metricFinder); } @Test @@ -73,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); @@ -89,13 +77,6 @@ public class MeasureCacheTest extends AbstractCachesTest { assertThat(measureCache.byResource(p)).hasSize(1); assertThat(measureCache.byResource(p).iterator().next()).isEqualTo(m); - - Measure mRule = RuleMeasure.createForPriority(CoreMetrics.CRITICAL_VIOLATIONS, RulePriority.BLOCKER, 1.0); - measureCache.put(p, mRule); - - assertThat(measureCache.entries()).hasSize(2); - - assertThat(measureCache.byResource(p)).hasSize(2); } @Test @@ -112,7 +93,7 @@ public class MeasureCacheTest extends AbstractCachesTest { for (int i = 0; i < 1_048_575; i++) { data.append("a"); } - + m.setData(data.toString()); measureCache.put(p, m); @@ -127,12 +108,6 @@ public class MeasureCacheTest extends AbstractCachesTest { assertThat(measureCache.byResource(p)).hasSize(1); assertThat(measureCache.byResource(p).iterator().next()).isEqualTo(m); - - RuleMeasure mRule = RuleMeasure.createForPriority(CoreMetrics.CRITICAL_VIOLATIONS, RulePriority.BLOCKER, 1.0); - mRule.setRuleKey(RuleKey.of("repo", "rule")); - measureCache.put(p, mRule); - - assertThat(measureCache.entries()).hasSize(2); } /** @@ -166,11 +141,6 @@ public class MeasureCacheTest extends AbstractCachesTest { assertThat(measureCache.byResource(p)).hasSize(1); assertThat(measureCache.byResource(p).iterator().next()).isEqualTo(m); - RuleMeasure mRule = RuleMeasure.createForPriority(CoreMetrics.CRITICAL_VIOLATIONS, RulePriority.BLOCKER, 1.0); - mRule.setRuleKey(RuleKey.of("repo", "rule")); - measureCache.put(p, mRule); - - assertThat(measureCache.entries()).hasSize(2); } @Test @@ -203,17 +173,12 @@ public class MeasureCacheTest extends AbstractCachesTest { assertThat(measureCache.byResource(p)).hasSize(0); Measure m1 = new Measure(CoreMetrics.NCLOC, 1.0); - Measure m2 = new Measure(CoreMetrics.NCLOC, 1.0).setCharacteristic(new DefaultCharacteristic().setKey("charac")); - Measure m3 = new Measure(CoreMetrics.NCLOC, 1.0).setPersonId(2); - Measure m4 = new RuleMeasure(CoreMetrics.NCLOC, RuleKey.of("repo", "rule"), RulePriority.BLOCKER, null); + Measure m2 = new Measure(CoreMetrics.NCLOC, 1.0).setPersonId(2); measureCache.put(p, m1); measureCache.put(p, m2); - measureCache.put(p, m3); - measureCache.put(p, m4); - assertThat(measureCache.entries()).hasSize(4); - - assertThat(measureCache.byResource(p)).hasSize(4); + assertThat(measureCache.entries()).hasSize(2); + assertThat(measureCache.byResource(p)).hasSize(2); } @Test @@ -259,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); @@ -290,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-batch/src/test/java/org/sonar/batch/scan/report/ConsoleReportTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/report/ConsoleReportTest.java index f5a1482e608..fc3355952c0 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/report/ConsoleReportTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/report/ConsoleReportTest.java @@ -25,7 +25,7 @@ import org.junit.Test; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.config.Settings; -import org.sonar.api.issue.internal.DefaultIssue; +import org.sonar.core.issue.DefaultIssue; import org.sonar.api.rule.Severity; import org.sonar.api.utils.log.LogTester; import org.sonar.batch.issue.IssueCache; diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/report/JSONReportTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/report/JSONReportTest.java index 0a346666ad5..afc0d4c39aa 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/report/JSONReportTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/report/JSONReportTest.java @@ -33,7 +33,7 @@ import org.sonar.api.batch.rule.ActiveRules; import org.sonar.api.batch.rule.internal.ActiveRulesBuilder; import org.sonar.api.config.Settings; import org.sonar.api.issue.Issue; -import org.sonar.api.issue.internal.DefaultIssue; +import org.sonar.core.issue.DefaultIssue; import org.sonar.api.platform.Server; import org.sonar.api.resources.Project; import org.sonar.api.resources.Resource; diff --git a/sonar-batch/src/test/java/org/sonar/batch/sensor/DefaultSensorStorageTest.java b/sonar-batch/src/test/java/org/sonar/batch/sensor/DefaultSensorStorageTest.java index b03d9baf3bd..c42ed5031d9 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/sensor/DefaultSensorStorageTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/sensor/DefaultSensorStorageTest.java @@ -169,7 +169,7 @@ public class DefaultSensorStorageTest { public void shouldAddIssueOnFile() { InputFile file = new DefaultInputFile("foo", "src/Foo.php").setLines(4); - ArgumentCaptor<org.sonar.api.issue.internal.DefaultIssue> argumentCaptor = ArgumentCaptor.forClass(org.sonar.api.issue.internal.DefaultIssue.class); + ArgumentCaptor<org.sonar.core.issue.DefaultIssue> argumentCaptor = ArgumentCaptor.forClass(org.sonar.core.issue.DefaultIssue.class); sensorStorage.store(new DefaultIssue() .onFile(file) @@ -180,7 +180,7 @@ public class DefaultSensorStorageTest { verify(moduleIssues).initAndAddIssue(argumentCaptor.capture()); - org.sonar.api.issue.internal.DefaultIssue issue = argumentCaptor.getValue(); + org.sonar.core.issue.DefaultIssue issue = argumentCaptor.getValue(); assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("foo", "bar")); assertThat(issue.message()).isEqualTo("Foo"); assertThat(issue.line()).isEqualTo(3); @@ -192,7 +192,7 @@ public class DefaultSensorStorageTest { public void shouldAddIssueOnDirectory() { InputDir dir = new DefaultInputDir("foo", "src"); - ArgumentCaptor<org.sonar.api.issue.internal.DefaultIssue> argumentCaptor = ArgumentCaptor.forClass(org.sonar.api.issue.internal.DefaultIssue.class); + ArgumentCaptor<org.sonar.core.issue.DefaultIssue> argumentCaptor = ArgumentCaptor.forClass(org.sonar.core.issue.DefaultIssue.class); sensorStorage.store(new DefaultIssue() .onDir(dir) @@ -202,7 +202,7 @@ public class DefaultSensorStorageTest { verify(moduleIssues).initAndAddIssue(argumentCaptor.capture()); - org.sonar.api.issue.internal.DefaultIssue issue = argumentCaptor.getValue(); + org.sonar.core.issue.DefaultIssue issue = argumentCaptor.getValue(); assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("foo", "bar")); assertThat(issue.message()).isEqualTo("Foo"); assertThat(issue.line()).isNull(); @@ -212,7 +212,7 @@ public class DefaultSensorStorageTest { @Test public void shouldAddIssueOnProject() { - ArgumentCaptor<org.sonar.api.issue.internal.DefaultIssue> argumentCaptor = ArgumentCaptor.forClass(org.sonar.api.issue.internal.DefaultIssue.class); + ArgumentCaptor<org.sonar.core.issue.DefaultIssue> argumentCaptor = ArgumentCaptor.forClass(org.sonar.core.issue.DefaultIssue.class); sensorStorage.store(new DefaultIssue() .onProject() @@ -223,7 +223,7 @@ public class DefaultSensorStorageTest { verify(moduleIssues).initAndAddIssue(argumentCaptor.capture()); - org.sonar.api.issue.internal.DefaultIssue issue = argumentCaptor.getValue(); + org.sonar.core.issue.DefaultIssue issue = argumentCaptor.getValue(); assertThat(issue.ruleKey()).isEqualTo(RuleKey.of("foo", "bar")); assertThat(issue.message()).isEqualTo("Foo"); assertThat(issue.line()).isNull(); |