CloseableIterator<BatchReport.Coverage> readComponentCoverage(int fileRef);
/**
- * Reads file source line by line.
+ * Reads file source line by line. Throws an exception if the ref does not relate
+ * to a file
*/
CloseableIterator<String> readFileSource(int fileRef);
import org.sonar.server.computation.event.EventRepositoryImpl;
import org.sonar.server.computation.formula.CoreFormulaRepositoryImpl;
import org.sonar.server.computation.issue.BaseIssuesLoader;
-import org.sonar.server.computation.issue.CountIssuesListener;
-import org.sonar.server.computation.issue.DebtCalculator;
+import org.sonar.server.computation.issue.IssueCounter;
+import org.sonar.server.computation.issue.DebtAggregator;
import org.sonar.server.computation.issue.DefaultAssignee;
import org.sonar.server.computation.issue.IssueAssigner;
import org.sonar.server.computation.issue.IssueCache;
import org.sonar.server.computation.issue.IssueLifecycle;
-import org.sonar.server.computation.issue.IssueListeners;
+import org.sonar.server.computation.issue.IssueVisitors;
+import org.sonar.server.computation.issue.NewDebtAggregator;
+import org.sonar.server.computation.issue.NewDebtCalculator;
import org.sonar.server.computation.issue.RuleCache;
import org.sonar.server.computation.issue.RuleCacheLoader;
import org.sonar.server.computation.issue.RuleTagsCopier;
// issues
ScmAccountToUserLoader.class,
ScmAccountToUser.class,
- IssueAssigner.class,
- RuleTagsCopier.class,
RuleCache.class,
RuleCacheLoader.class,
IssueCache.class,
DefaultAssignee.class,
- DebtCalculator.class,
- IssueListeners.class,
+ IssueVisitors.class,
IssueLifecycle.class,
- CountIssuesListener.class,
+
+ // order is important, NewDebtAggregator is based on DebtAggregator (new debt requires debt)
+ DebtAggregator.class,
+ NewDebtCalculator.class,
+ NewDebtAggregator.class,
+ IssueAssigner.class,
+ RuleTagsCopier.class,
+ IssueCounter.class,
+
UpdateConflictResolver.class,
TrackerBaseInputFactory.class,
TrackerRawInputFactory.class,
*/
package org.sonar.server.computation.issue;
+import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import javax.annotation.Nonnull;
import org.apache.ibatis.session.ResultContext;
import org.apache.ibatis.session.ResultHandler;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.RuleStatus;
+import org.sonar.api.utils.log.Loggers;
import org.sonar.core.issue.DefaultIssue;
import org.sonar.core.issue.db.IssueDto;
import org.sonar.core.issue.db.IssueMapper;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.server.computation.batch.BatchReportReader;
import org.sonar.server.computation.component.TreeRootHolder;
import org.sonar.server.db.DbClient;
+import static com.google.common.collect.FluentIterable.from;
+
/**
* Loads all the project open issues from database, including manual issues.
+ *
*/
public class BaseIssuesLoader {
+ private final Set<RuleKey> activeRuleKeys;
private final TreeRootHolder treeRootHolder;
private final DbClient dbClient;
private final RuleCache ruleCache;
- public BaseIssuesLoader(TreeRootHolder treeRootHolder, DbClient dbClient, RuleCache ruleCache) {
+ public BaseIssuesLoader(BatchReportReader reportReader, TreeRootHolder treeRootHolder,
+ DbClient dbClient, RuleCache ruleCache) {
+ this.activeRuleKeys = from(reportReader.readMetadata().getActiveRuleKeyList()).transform(ToRuleKey.INSTANCE).toSet();
this.treeRootHolder = treeRootHolder;
this.dbClient = dbClient;
this.ruleCache = ruleCache;
final List<DefaultIssue> result = new ArrayList<>();
try {
Map<String, String> params = ImmutableMap.of("componentUuid", componentUuid);
- session.select(IssueMapper.class.getName() + ".selectOpenByComponentUuid", params, new ResultHandler() {
+ session.select(IssueMapper.class.getName() + ".selectNonClosedByComponentUuid", params, new ResultHandler() {
@Override
public void handleResult(ResultContext resultContext) {
DefaultIssue issue = ((IssueDto) resultContext.getResultObject()).toDefaultIssue();
- issue.setOnDisabledRule(ruleCache.getNullable(issue.ruleKey()) == null);
+
+ // TODO this field should be set outside this class
+ RuleDto rule = ruleCache.getNullable(issue.ruleKey());
+ if (rule == null || rule.getStatus() == RuleStatus.REMOVED || !isActive(issue.ruleKey())) {
+ issue.setOnDisabledRule(true);
+ // TODO to be improved, why setOnDisabledRule(true) is not enough ?
+ issue.setBeingClosed(true);
+ }
+ // FIXME
+ issue.setSelectedAt(System.currentTimeMillis());
+ Loggers.get(getClass()).info("Loaded from db: " + issue);
result.add(issue);
}
});
}
}
+ private boolean isActive(RuleKey ruleKey) {
+ return ruleKey.isManual() || activeRuleKeys.contains(ruleKey);
+ }
+
/**
* Uuids of all the components that have open issues on this project.
*/
MyBatis.closeQuietly(session);
}
}
+
+ private enum ToRuleKey implements Function<String, RuleKey> {
+ INSTANCE;
+ @Nonnull
+ @Override
+ public RuleKey apply(@Nonnull String input) {
+ return RuleKey.parse(input);
+ }
+ }
}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.computation.issue;
-
-import com.google.common.collect.HashMultiset;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Multiset;
-import java.util.HashMap;
-import java.util.Map;
-import javax.annotation.Nullable;
-import org.sonar.api.issue.Issue;
-import org.sonar.core.issue.DefaultIssue;
-import org.sonar.core.issue.tracking.Tracking;
-import org.sonar.server.computation.component.Component;
-import org.sonar.server.computation.measure.Measure;
-import org.sonar.server.computation.measure.MeasureRepository;
-import org.sonar.server.computation.measure.MeasureVariations;
-import org.sonar.server.computation.metric.Metric;
-import org.sonar.server.computation.metric.MetricRepository;
-import org.sonar.server.computation.period.Period;
-import org.sonar.server.computation.period.PeriodsHolder;
-
-import static org.sonar.api.issue.Issue.STATUS_CONFIRMED;
-import static org.sonar.api.issue.Issue.STATUS_OPEN;
-import static org.sonar.api.issue.Issue.STATUS_REOPENED;
-import static org.sonar.api.measures.CoreMetrics.BLOCKER_VIOLATIONS_KEY;
-import static org.sonar.api.measures.CoreMetrics.CONFIRMED_ISSUES_KEY;
-import static org.sonar.api.measures.CoreMetrics.CRITICAL_VIOLATIONS_KEY;
-import static org.sonar.api.measures.CoreMetrics.FALSE_POSITIVE_ISSUES_KEY;
-import static org.sonar.api.measures.CoreMetrics.INFO_VIOLATIONS_KEY;
-import static org.sonar.api.measures.CoreMetrics.MAJOR_VIOLATIONS_KEY;
-import static org.sonar.api.measures.CoreMetrics.MINOR_VIOLATIONS_KEY;
-import static org.sonar.api.measures.CoreMetrics.NEW_BLOCKER_VIOLATIONS_KEY;
-import static org.sonar.api.measures.CoreMetrics.NEW_CRITICAL_VIOLATIONS_KEY;
-import static org.sonar.api.measures.CoreMetrics.NEW_INFO_VIOLATIONS_KEY;
-import static org.sonar.api.measures.CoreMetrics.NEW_MAJOR_VIOLATIONS_KEY;
-import static org.sonar.api.measures.CoreMetrics.NEW_MINOR_VIOLATIONS_KEY;
-import static org.sonar.api.measures.CoreMetrics.NEW_VIOLATIONS_KEY;
-import static org.sonar.api.measures.CoreMetrics.OPEN_ISSUES_KEY;
-import static org.sonar.api.measures.CoreMetrics.REOPENED_ISSUES_KEY;
-import static org.sonar.api.measures.CoreMetrics.VIOLATIONS_KEY;
-import static org.sonar.api.rule.Severity.BLOCKER;
-import static org.sonar.api.rule.Severity.CRITICAL;
-import static org.sonar.api.rule.Severity.INFO;
-import static org.sonar.api.rule.Severity.MAJOR;
-import static org.sonar.api.rule.Severity.MINOR;
-
-/**
- * For each component, computes the measures related to number of issues:
- * <ul>
- * <li>unresolved issues</li>
- * <li>false-positives</li>
- * <li>open issues</li>
- * <li>issues per status (open, reopen, confirmed)</li>
- * <li>issues per severity (from info to blocker)</li>
- * </ul>
- * For each value, the variation on configured periods is also computed.
- */
-public class CountIssuesListener extends IssueListener {
-
- private final static Map<String, String> SEVERITY_TO_METRIC_KEY = ImmutableMap.of(
- BLOCKER, BLOCKER_VIOLATIONS_KEY,
- CRITICAL, CRITICAL_VIOLATIONS_KEY,
- MAJOR, MAJOR_VIOLATIONS_KEY,
- MINOR, MINOR_VIOLATIONS_KEY,
- INFO, INFO_VIOLATIONS_KEY
- );
-
- private final static Map<String, String> SEVERITY_TO_NEW_METRIC_KEY = ImmutableMap.of(
- BLOCKER, NEW_BLOCKER_VIOLATIONS_KEY,
- CRITICAL, NEW_CRITICAL_VIOLATIONS_KEY,
- MAJOR, NEW_MAJOR_VIOLATIONS_KEY,
- MINOR, NEW_MINOR_VIOLATIONS_KEY,
- INFO, NEW_INFO_VIOLATIONS_KEY
- );
-
- private final PeriodsHolder periodsHolder;
- private final MetricRepository metricRepository;
- private final MeasureRepository measureRepository;
-
- private final Map<Integer, Counters> countersByComponentRef = new HashMap<>();
- private Counters currentCounters;
-
- public CountIssuesListener(PeriodsHolder periodsHolder,
- MetricRepository metricRepository, MeasureRepository measureRepository) {
- this.periodsHolder = periodsHolder;
- this.metricRepository = metricRepository;
- this.measureRepository = measureRepository;
- }
-
- @Override
- public void beforeComponent(Component component, Tracking tracking) {
- // TODO optimization no need to instantiate counter if no open issues
- currentCounters = new Counters();
- countersByComponentRef.put(component.getRef(), currentCounters);
-
- // aggregate children counters
- for (Component child : component.getChildren()) {
- // no need to keep the children in memory. They can be garbage-collected.
- Counters childCounters = countersByComponentRef.remove(child.getRef());
- currentCounters.add(childCounters);
- }
- }
-
- @Override
- public void onIssue(Component component, DefaultIssue issue) {
- currentCounters.add(issue);
- for (Period period : periodsHolder.getPeriods()) {
- // Add one second to not take into account issues created during current analysis
- if (issue.creationDate().getTime() >= period.getSnapshotDate() + 1000L) {
- currentCounters.addOnPeriod(issue, period.getIndex());
- }
- }
- }
-
- @Override
- public void afterComponent(Component component) {
- addMeasuresByStatus(component);
- addMeasuresBySeverity(component);
- addMeasuresByPeriod(component);
- currentCounters = null;
- }
-
- private void addMeasuresBySeverity(Component component) {
- for (Map.Entry<String, String> entry : SEVERITY_TO_METRIC_KEY.entrySet()) {
- String severity = entry.getKey();
- String metricKey = entry.getValue();
- addMeasure(component, metricKey, currentCounters.counter().severityBag.count(severity));
- }
- }
-
- private void addMeasuresByStatus(Component component) {
- addMeasure(component, VIOLATIONS_KEY, currentCounters.counter().unresolved);
- addMeasure(component, OPEN_ISSUES_KEY, currentCounters.counter().open);
- addMeasure(component, REOPENED_ISSUES_KEY, currentCounters.counter().reopened);
- addMeasure(component, CONFIRMED_ISSUES_KEY, currentCounters.counter().confirmed);
- addMeasure(component, FALSE_POSITIVE_ISSUES_KEY, currentCounters.counter().falsePositives);
- }
-
- private void addMeasure(Component component, String metricKey, int value) {
- Metric metric = metricRepository.getByKey(metricKey);
- measureRepository.add(component, metric, Measure.newMeasureBuilder().create(value));
- }
-
- private void addMeasuresByPeriod(Component component) {
- if (!periodsHolder.getPeriods().isEmpty()) {
- Double[] unresolvedVariations = new Double[PeriodsHolder.MAX_NUMBER_OF_PERIODS];
- for (Period period : periodsHolder.getPeriods()) {
- unresolvedVariations[period.getIndex() - 1] = new Double(currentCounters.counterForPeriod(period.getIndex()).unresolved);
- }
- measureRepository.add(component, metricRepository.getByKey(NEW_VIOLATIONS_KEY), Measure.newMeasureBuilder()
- .setVariations(new MeasureVariations(unresolvedVariations))
- .createNoValue());
-
- for (Map.Entry<String, String> entry : SEVERITY_TO_NEW_METRIC_KEY.entrySet()) {
- String severity = entry.getKey();
- String metricKey = entry.getValue();
- Double[] variations = new Double[PeriodsHolder.MAX_NUMBER_OF_PERIODS];
- boolean set = false;
- for (Period period : periodsHolder.getPeriods()) {
- Multiset<String> bag = currentCounters.counterForPeriod(period.getIndex()).severityBag;
- if (bag.contains(severity)) {
- variations[period.getIndex() - 1] = new Double(bag.count(severity));
- set = true;
- }
- }
- if (set) {
- Metric metric = metricRepository.getByKey(metricKey);
- measureRepository.add(component, metric, Measure.newMeasureBuilder()
- .setVariations(new MeasureVariations(variations))
- .createNoValue());
- }
- }
- }
- }
-
- /**
- * Count issues by status, resolutions, rules and severities
- */
- private static class Counter {
- private int unresolved = 0;
- private int open = 0;
- private int reopened = 0;
- private int confirmed = 0;
- private int falsePositives = 0;
- private Multiset<String> severityBag = HashMultiset.create();
-
- void add(Counter counter) {
- unresolved += counter.unresolved;
- open += counter.open;
- reopened += counter.reopened;
- confirmed += counter.confirmed;
- falsePositives += counter.falsePositives;
- severityBag.addAll(counter.severityBag);
- }
-
- void add(Issue issue) {
- if (issue.resolution() == null) {
- unresolved++;
- severityBag.add(issue.severity());
- } else if (Issue.RESOLUTION_FALSE_POSITIVE.equals(issue.resolution())) {
- falsePositives++;
- }
- switch (issue.status()) {
- case STATUS_OPEN:
- open++;
- break;
- case STATUS_REOPENED:
- reopened++;
- break;
- case STATUS_CONFIRMED:
- confirmed++;
- break;
- default:
- // Other statuses are ignored
- }
- }
- }
-
- /**
- * List of {@link Counter} for regular value and periods.
- */
- private static class Counters {
- private final Counter[] array = new Counter[1 + PeriodsHolder.MAX_NUMBER_OF_PERIODS];
-
- Counters() {
- array[0] = new Counter();
- for (int i = 1; i <= PeriodsHolder.MAX_NUMBER_OF_PERIODS; i++) {
- array[i] = new Counter();
- }
- }
-
- void add(@Nullable Counters other) {
- if (other != null) {
- for (int i = 0; i < array.length; i++) {
- array[i].add(other.array[i]);
- }
- }
- }
-
- void addOnPeriod(Issue issue, int periodIndex) {
- array[periodIndex].add(issue);
- }
-
- void add(Issue issue) {
- array[0].add(issue);
- }
-
- Counter counter() {
- return array[0];
- }
-
- Counter counterForPeriod(int periodIndex) {
- return array[periodIndex];
- }
- }
-}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.issue;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.core.issue.DefaultIssue;
+import org.sonar.core.issue.tracking.Tracking;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.debt.Characteristic;
+import org.sonar.server.computation.debt.DebtModelHolder;
+import org.sonar.server.computation.measure.Measure;
+import org.sonar.server.computation.measure.MeasureRepository;
+import org.sonar.server.computation.metric.Metric;
+import org.sonar.server.computation.metric.MetricRepository;
+
+import static com.google.common.collect.Maps.newHashMap;
+
+public class DebtAggregator extends IssueVisitor {
+
+ private final RuleCache ruleCache;
+ private final DebtModelHolder debtModelHolder;
+ private final MetricRepository metricRepository;
+ private final MeasureRepository measureRepository;
+
+ private final Map<Integer, Debt> debtsByComponentRef = new HashMap<>();
+ private Debt currentDebt;
+
+ public DebtAggregator(RuleCache ruleCache, DebtModelHolder debtModelHolder,
+ MetricRepository metricRepository, MeasureRepository measureRepository) {
+ this.ruleCache = ruleCache;
+ this.debtModelHolder = debtModelHolder;
+ this.metricRepository = metricRepository;
+ this.measureRepository = measureRepository;
+ }
+
+ @Override
+ public void beforeComponent(Component component, Tracking tracking) {
+ this.currentDebt = new Debt();
+
+ // aggregate children counters
+ for (Component child : component.getChildren()) {
+ // no need to keep the children in memory. They can be garbage-collected.
+ Debt childDebt = debtsByComponentRef.remove(child.getRef());
+ if (childDebt != null) {
+ currentDebt.add(childDebt);
+ }
+ }
+ }
+
+ @Override
+ public void onIssue(Component component, DefaultIssue issue) {
+ if (issue.resolution() == null) {
+ currentDebt.add(issue);
+ }
+ }
+
+ @Override
+ public void afterComponent(Component component) {
+ if (this.currentDebt.minutes > 0L) {
+ Metric metric = metricRepository.getByKey(CoreMetrics.TECHNICAL_DEBT_KEY);
+
+ // total value
+ measureRepository.add(component, metric, Measure.newMeasureBuilder().create(this.currentDebt.minutes));
+
+ // distribution by rule
+ for (Map.Entry<Integer, Long> entry : currentDebt.minutesByRuleId.entrySet()) {
+ int ruleId = entry.getKey();
+ long ruleDebt = entry.getValue();
+ measureRepository.add(component, metric, Measure.newMeasureBuilder().forRule(ruleId).create(ruleDebt));
+ }
+
+ // distribution by characteristic
+ for (Map.Entry<Integer, Long> entry : currentDebt.minutesByCharacteristicId.entrySet()) {
+ int characteristicId = entry.getKey();
+ long characteristicDebt = entry.getValue();
+ measureRepository.add(component, metric, Measure.newMeasureBuilder().forCharacteristic(characteristicId).create(characteristicDebt));
+ }
+ }
+ this.currentDebt = null;
+ }
+
+ private class Debt {
+ private long minutes = 0L;
+ private final SumMap<Integer> minutesByRuleId = new SumMap<>();
+ private final SumMap<Integer> minutesByCharacteristicId = new SumMap<>();
+
+ void add(DefaultIssue issue) {
+ Long issueMinutes = issue.debtInMinutes();
+ if (issueMinutes != null && issueMinutes != 0L) {
+ this.minutes += issueMinutes;
+
+ RuleDto rule = ruleCache.get(issue.ruleKey());
+ this.minutesByRuleId.add(rule.getId(), issueMinutes);
+
+ Integer subCharacteristicId = rule.getSubCharacteristicId();
+ if (subCharacteristicId != null) {
+ Characteristic characteristic = debtModelHolder.getCharacteristicById(subCharacteristicId);
+ this.minutesByCharacteristicId.add(characteristic.getId(), issueMinutes);
+ Integer characteristicParentId = characteristic.getParentId();
+ if (characteristicParentId != null) {
+ this.minutesByCharacteristicId.add(characteristicParentId, issueMinutes);
+ }
+ }
+ }
+ }
+
+ public void add(Debt debt) {
+ this.minutes += debt.minutes;
+ this.minutesByRuleId.add(debt.minutesByRuleId);
+ this.minutesByCharacteristicId.add(debt.minutesByCharacteristicId);
+ }
+ }
+
+ private static class SumMap<E> {
+ private final Map<E, Long> sumByKeys = newHashMap();
+
+ void add(SumMap<E> other) {
+ for (Map.Entry<E, Long> entry : other.entrySet()) {
+ add(entry.getKey(), entry.getValue());
+ }
+ }
+
+ void add(@Nullable E key, Long value) {
+ if (key != null) {
+ Long currentValue = sumByKeys.get(key);
+ sumByKeys.put(key, currentValue != null ? (currentValue + value) : value);
+ }
+ }
+
+ @CheckForNull
+ Long get(E key) {
+ return sumByKeys.get(key);
+ }
+
+ Set<Map.Entry<E, Long>> entrySet() {
+ return sumByKeys.entrySet();
+ }
+ }
+}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.computation.issue;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.core.issue.DefaultIssue;
-import org.sonar.core.issue.IssueUpdater;
-import org.sonar.core.issue.tracking.Tracking;
-import org.sonar.core.rule.RuleDto;
-import org.sonar.server.computation.component.Component;
-import org.sonar.server.computation.debt.Characteristic;
-import org.sonar.server.computation.debt.DebtModelHolder;
-import org.sonar.server.computation.measure.Measure;
-import org.sonar.server.computation.measure.MeasureRepository;
-import org.sonar.server.computation.metric.Metric;
-import org.sonar.server.computation.metric.MetricRepository;
-
-import static com.google.common.collect.Maps.newHashMap;
-
-public class DebtCalculator extends IssueListener {
-
- private final IssueUpdater updater;
- private final RuleCache ruleCache;
- private final DebtModelHolder debtModelHolder;
- private final MetricRepository metricRepository;
- private final MeasureRepository measureRepository;
-
- private final Map<Integer, Debt> debtsByComponentRef = new HashMap<>();
- private Debt currentDebt;
-
- public DebtCalculator(IssueUpdater updater, RuleCache ruleCache, DebtModelHolder debtModelHolder,
- MetricRepository metricRepository, MeasureRepository measureRepository) {
- this.updater = updater;
- this.ruleCache = ruleCache;
- this.debtModelHolder = debtModelHolder;
- this.metricRepository = metricRepository;
- this.measureRepository = measureRepository;
- }
-
- @Override
- public void beforeComponent(Component component, Tracking tracking) {
- this.currentDebt = new Debt();
-
- // aggregate children counters
- for (Component child : component.getChildren()) {
- // no need to keep the children in memory. They can be garbage-collected.
- Debt childDebt = debtsByComponentRef.remove(child.getRef());
- currentDebt.add(childDebt);
- }
- }
-
- @Override
- public void onIssue(Component component, DefaultIssue issue) {
- if (issue.resolution() == null) {
- // TODO calculate debt according to rule remediation function. Currently done by batch.
- currentDebt.add(issue);
- }
- }
-
- @Override
- public void afterComponent(Component component) {
- if (this.currentDebt.minutes > 0L) {
- Metric metric = metricRepository.getByKey(CoreMetrics.TECHNICAL_DEBT_KEY);
-
- // total value
- measureRepository.add(component, metric, Measure.newMeasureBuilder().create(this.currentDebt.minutes));
-
- // distribution by rule
- for (Map.Entry<Integer, Long> entry : currentDebt.minutesByRuleId.entrySet()) {
- int ruleId = entry.getKey();
- long ruleDebt = entry.getValue();
- measureRepository.add(component, metric, Measure.newMeasureBuilder().forRule(ruleId).create(ruleDebt));
- }
-
- // distribution by characteristic
- for (Map.Entry<Integer, Long> entry : currentDebt.minutesByCharacteristicId.entrySet()) {
- int characteristicId = entry.getKey();
- long characteristicDebt = entry.getValue();
- measureRepository.add(component, metric, Measure.newMeasureBuilder().forCharacteristic(characteristicId).create(characteristicDebt));
- }
- }
- this.currentDebt = null;
- }
-
- private class Debt {
- private long minutes = 0L;
- private final SumMap<Integer> minutesByRuleId = new SumMap<>();
- private final SumMap<Integer> minutesByCharacteristicId = new SumMap<>();
-
- void add(DefaultIssue issue) {
- Long issueMinutes = issue.debtInMinutes();
- if (issueMinutes != null && issueMinutes != 0L) {
- this.minutes += issueMinutes;
-
- RuleDto rule = ruleCache.get(issue.ruleKey());
- this.minutesByRuleId.add(rule.getId(), issueMinutes);
-
- Characteristic characteristic = debtModelHolder.getCharacteristicById(rule.getSubCharacteristicId());
- this.minutesByCharacteristicId.add(characteristic.getId(), issueMinutes);
- Integer characteristicParentId = characteristic.getParentId();
- if (characteristicParentId != null) {
- this.minutesByCharacteristicId.add(characteristicParentId, issueMinutes);
- }
- }
- }
-
- public void add(Debt debt) {
- this.minutes += debt.minutes;
- this.minutesByRuleId.add(debt.minutesByRuleId);
- this.minutesByCharacteristicId.add(debt.minutesByCharacteristicId);
- }
- }
-
- private static class SumMap<E> {
- private final Map<E, Long> sumByKeys = newHashMap();
-
- void add(SumMap<E> other) {
- for (Map.Entry<E, Long> entry : other.entrySet()) {
- add(entry.getKey(), entry.getValue());
- }
- }
-
- void add(@Nullable E key, Long value) {
- if (key != null) {
- Long currentValue = sumByKeys.get(key);
- sumByKeys.put(key, currentValue != null ? (currentValue + value) : value);
- }
- }
-
- @CheckForNull
- Long get(E key) {
- return sumByKeys.get(key);
- }
-
- Set<Map.Entry<E, Long>> entrySet() {
- return sumByKeys.entrySet();
- }
- }
-}
* <li>the Elasticsearch index of source lines for non-modified files</li>
* </ul>
*/
-public class IssueAssigner extends IssueListener {
+public class IssueAssigner extends IssueVisitor {
private final SourceLineIndex sourceLineIndex;
private final BatchReportReader reportReader;
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.issue;
+
+import com.google.common.collect.HashMultiset;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Multiset;
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.Nullable;
+import org.sonar.api.issue.Issue;
+import org.sonar.core.issue.DefaultIssue;
+import org.sonar.core.issue.tracking.Tracking;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.measure.Measure;
+import org.sonar.server.computation.measure.MeasureRepository;
+import org.sonar.server.computation.measure.MeasureVariations;
+import org.sonar.server.computation.metric.Metric;
+import org.sonar.server.computation.metric.MetricRepository;
+import org.sonar.server.computation.period.Period;
+import org.sonar.server.computation.period.PeriodsHolder;
+
+import static org.sonar.api.issue.Issue.STATUS_CONFIRMED;
+import static org.sonar.api.issue.Issue.STATUS_OPEN;
+import static org.sonar.api.issue.Issue.STATUS_REOPENED;
+import static org.sonar.api.measures.CoreMetrics.BLOCKER_VIOLATIONS_KEY;
+import static org.sonar.api.measures.CoreMetrics.CONFIRMED_ISSUES_KEY;
+import static org.sonar.api.measures.CoreMetrics.CRITICAL_VIOLATIONS_KEY;
+import static org.sonar.api.measures.CoreMetrics.FALSE_POSITIVE_ISSUES_KEY;
+import static org.sonar.api.measures.CoreMetrics.INFO_VIOLATIONS_KEY;
+import static org.sonar.api.measures.CoreMetrics.MAJOR_VIOLATIONS_KEY;
+import static org.sonar.api.measures.CoreMetrics.MINOR_VIOLATIONS_KEY;
+import static org.sonar.api.measures.CoreMetrics.NEW_BLOCKER_VIOLATIONS_KEY;
+import static org.sonar.api.measures.CoreMetrics.NEW_CRITICAL_VIOLATIONS_KEY;
+import static org.sonar.api.measures.CoreMetrics.NEW_INFO_VIOLATIONS_KEY;
+import static org.sonar.api.measures.CoreMetrics.NEW_MAJOR_VIOLATIONS_KEY;
+import static org.sonar.api.measures.CoreMetrics.NEW_MINOR_VIOLATIONS_KEY;
+import static org.sonar.api.measures.CoreMetrics.NEW_VIOLATIONS_KEY;
+import static org.sonar.api.measures.CoreMetrics.OPEN_ISSUES_KEY;
+import static org.sonar.api.measures.CoreMetrics.REOPENED_ISSUES_KEY;
+import static org.sonar.api.measures.CoreMetrics.VIOLATIONS_KEY;
+import static org.sonar.api.rule.Severity.BLOCKER;
+import static org.sonar.api.rule.Severity.CRITICAL;
+import static org.sonar.api.rule.Severity.INFO;
+import static org.sonar.api.rule.Severity.MAJOR;
+import static org.sonar.api.rule.Severity.MINOR;
+
+/**
+ * For each component, computes the measures related to number of issues:
+ * <ul>
+ * <li>unresolved issues</li>
+ * <li>false-positives</li>
+ * <li>open issues</li>
+ * <li>issues per status (open, reopen, confirmed)</li>
+ * <li>issues per severity (from info to blocker)</li>
+ * </ul>
+ * For each value, the variation on configured periods is also computed.
+ */
+public class IssueCounter extends IssueVisitor {
+
+ private final static Map<String, String> SEVERITY_TO_METRIC_KEY = ImmutableMap.of(
+ BLOCKER, BLOCKER_VIOLATIONS_KEY,
+ CRITICAL, CRITICAL_VIOLATIONS_KEY,
+ MAJOR, MAJOR_VIOLATIONS_KEY,
+ MINOR, MINOR_VIOLATIONS_KEY,
+ INFO, INFO_VIOLATIONS_KEY
+ );
+
+ private final static Map<String, String> SEVERITY_TO_NEW_METRIC_KEY = ImmutableMap.of(
+ BLOCKER, NEW_BLOCKER_VIOLATIONS_KEY,
+ CRITICAL, NEW_CRITICAL_VIOLATIONS_KEY,
+ MAJOR, NEW_MAJOR_VIOLATIONS_KEY,
+ MINOR, NEW_MINOR_VIOLATIONS_KEY,
+ INFO, NEW_INFO_VIOLATIONS_KEY
+ );
+
+ private final PeriodsHolder periodsHolder;
+ private final MetricRepository metricRepository;
+ private final MeasureRepository measureRepository;
+
+ private final Map<Integer, Counters> countersByComponentRef = new HashMap<>();
+ private Counters currentCounters;
+
+ public IssueCounter(PeriodsHolder periodsHolder,
+ MetricRepository metricRepository, MeasureRepository measureRepository) {
+ this.periodsHolder = periodsHolder;
+ this.metricRepository = metricRepository;
+ this.measureRepository = measureRepository;
+ }
+
+ @Override
+ public void beforeComponent(Component component, Tracking tracking) {
+ // TODO optimization no need to instantiate counter if no open issues
+ currentCounters = new Counters();
+ countersByComponentRef.put(component.getRef(), currentCounters);
+
+ // aggregate children counters
+ for (Component child : component.getChildren()) {
+ // no need to keep the children in memory. They can be garbage-collected.
+ Counters childCounters = countersByComponentRef.remove(child.getRef());
+ currentCounters.add(childCounters);
+ }
+ }
+
+ @Override
+ public void onIssue(Component component, DefaultIssue issue) {
+ currentCounters.add(issue);
+ for (Period period : periodsHolder.getPeriods()) {
+ // Add one second to not take into account issues created during current analysis
+ if (issue.creationDate().getTime() >= period.getSnapshotDate() + 1000L) {
+ currentCounters.addOnPeriod(issue, period.getIndex());
+ }
+ }
+ }
+
+ @Override
+ public void afterComponent(Component component) {
+ addMeasuresByStatus(component);
+ addMeasuresBySeverity(component);
+ addMeasuresByPeriod(component);
+ currentCounters = null;
+ }
+
+ private void addMeasuresBySeverity(Component component) {
+ for (Map.Entry<String, String> entry : SEVERITY_TO_METRIC_KEY.entrySet()) {
+ String severity = entry.getKey();
+ String metricKey = entry.getValue();
+ addMeasure(component, metricKey, currentCounters.counter().severityBag.count(severity));
+ }
+ }
+
+ private void addMeasuresByStatus(Component component) {
+ addMeasure(component, VIOLATIONS_KEY, currentCounters.counter().unresolved);
+ addMeasure(component, OPEN_ISSUES_KEY, currentCounters.counter().open);
+ addMeasure(component, REOPENED_ISSUES_KEY, currentCounters.counter().reopened);
+ addMeasure(component, CONFIRMED_ISSUES_KEY, currentCounters.counter().confirmed);
+ addMeasure(component, FALSE_POSITIVE_ISSUES_KEY, currentCounters.counter().falsePositives);
+ }
+
+ private void addMeasure(Component component, String metricKey, int value) {
+ Metric metric = metricRepository.getByKey(metricKey);
+ measureRepository.add(component, metric, Measure.newMeasureBuilder().create(value));
+ }
+
+ private void addMeasuresByPeriod(Component component) {
+ if (!periodsHolder.getPeriods().isEmpty()) {
+ Double[] unresolvedVariations = new Double[PeriodsHolder.MAX_NUMBER_OF_PERIODS];
+ for (Period period : periodsHolder.getPeriods()) {
+ unresolvedVariations[period.getIndex() - 1] = new Double(currentCounters.counterForPeriod(period.getIndex()).unresolved);
+ }
+ measureRepository.add(component, metricRepository.getByKey(NEW_VIOLATIONS_KEY), Measure.newMeasureBuilder()
+ .setVariations(new MeasureVariations(unresolvedVariations))
+ .createNoValue());
+
+ for (Map.Entry<String, String> entry : SEVERITY_TO_NEW_METRIC_KEY.entrySet()) {
+ String severity = entry.getKey();
+ String metricKey = entry.getValue();
+ Double[] variations = new Double[PeriodsHolder.MAX_NUMBER_OF_PERIODS];
+ boolean set = false;
+ for (Period period : periodsHolder.getPeriods()) {
+ Multiset<String> bag = currentCounters.counterForPeriod(period.getIndex()).severityBag;
+ if (bag.contains(severity)) {
+ variations[period.getIndex() - 1] = new Double(bag.count(severity));
+ set = true;
+ }
+ }
+ if (set) {
+ Metric metric = metricRepository.getByKey(metricKey);
+ measureRepository.add(component, metric, Measure.newMeasureBuilder()
+ .setVariations(new MeasureVariations(variations))
+ .createNoValue());
+ }
+ }
+ }
+ }
+
+ /**
+ * Count issues by status, resolutions, rules and severities
+ */
+ private static class Counter {
+ private int unresolved = 0;
+ private int open = 0;
+ private int reopened = 0;
+ private int confirmed = 0;
+ private int falsePositives = 0;
+ private Multiset<String> severityBag = HashMultiset.create();
+
+ void add(Counter counter) {
+ unresolved += counter.unresolved;
+ open += counter.open;
+ reopened += counter.reopened;
+ confirmed += counter.confirmed;
+ falsePositives += counter.falsePositives;
+ severityBag.addAll(counter.severityBag);
+ }
+
+ void add(Issue issue) {
+ if (issue.resolution() == null) {
+ unresolved++;
+ severityBag.add(issue.severity());
+ } else if (Issue.RESOLUTION_FALSE_POSITIVE.equals(issue.resolution())) {
+ falsePositives++;
+ }
+ switch (issue.status()) {
+ case STATUS_OPEN:
+ open++;
+ break;
+ case STATUS_REOPENED:
+ reopened++;
+ break;
+ case STATUS_CONFIRMED:
+ confirmed++;
+ break;
+ default:
+ // Other statuses are ignored
+ }
+ }
+ }
+
+ /**
+ * List of {@link Counter} for regular value and periods.
+ */
+ private static class Counters {
+ private final Counter[] array = new Counter[1 + PeriodsHolder.MAX_NUMBER_OF_PERIODS];
+
+ Counters() {
+ array[0] = new Counter();
+ for (int i = 1; i <= PeriodsHolder.MAX_NUMBER_OF_PERIODS; i++) {
+ array[i] = new Counter();
+ }
+ }
+
+ void add(@Nullable Counters other) {
+ if (other != null) {
+ for (int i = 0; i < array.length; i++) {
+ array[i].add(other.array[i]);
+ }
+ }
+ }
+
+ void addOnPeriod(Issue issue, int periodIndex) {
+ array[periodIndex].add(issue);
+ }
+
+ void add(Issue issue) {
+ array[0].add(issue);
+ }
+
+ Counter counter() {
+ return array[0];
+ }
+
+ Counter counterForPeriod(int periodIndex) {
+ return array[periodIndex];
+ }
+ }
+}
updater.setPastMessage(raw, base.getMessage(), changeContext);
updater.setPastEffortToFix(raw, base.effortToFix(), changeContext);
updater.setPastTechnicalDebt(raw, base.debt(), changeContext);
+ raw.setSelectedAt(base.selectedAt());
}
public void doAutomaticTransition(DefaultIssue issue) {
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.computation.issue;
-
-import org.sonar.core.issue.DefaultIssue;
-import org.sonar.core.issue.tracking.Tracking;
-import org.sonar.server.computation.component.Component;
-
-public abstract class IssueListener {
-
- /**
- * This method is called for each component before processing its issues.
- * The component does not necessarily have issues.
- */
- public void beforeComponent(Component component, Tracking tracking) {
-
- }
-
- /**
- * This method is called when initializing an open issue. At that time
- * any information related to tracking step are not available (line, assignee,
- * resolution, status, creation date, uuid, ...).
- * <p/>
- * The need for this method is for example to calculate the issue debt
- * before merging with base issue
- */
- public void onOpenIssueInitialization(Component component, DefaultIssue issue) {
-
- }
-
- /**
- * This method is called when tracking is done and issue is initialized. That means that the following fields
- * are set: resolution, status, line, creation date, uuid and all the fields merged from base issues.
- */
- public void onIssue(Component component, DefaultIssue issue) {
-
- }
-
- public void afterComponent(Component component) {
-
- }
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.computation.issue;
-
-import org.sonar.core.issue.DefaultIssue;
-import org.sonar.core.issue.tracking.Tracking;
-import org.sonar.server.computation.component.Component;
-
-public class IssueListeners {
-
- private final IssueListener[] listeners;
-
- public IssueListeners(IssueListener[] listeners) {
- this.listeners = listeners;
- }
-
- public void beforeComponent(Component component, Tracking tracking) {
- for (IssueListener listener : listeners) {
- listener.beforeComponent(component, tracking);
- }
- }
-
- public void onOpenIssueInitialization(Component component, DefaultIssue issue) {
- for (IssueListener listener : listeners) {
- listener.onOpenIssueInitialization(component, issue);
- }
- }
-
- public void onIssue(Component component, DefaultIssue issue) {
- for (IssueListener listener : listeners) {
- listener.onIssue(component, issue);
- }
- }
-
- public void afterComponent(Component component) {
- for (IssueListener listener : listeners) {
- listener.afterComponent(component);
- }
- }
-}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.issue;
+
+import org.sonar.core.issue.DefaultIssue;
+import org.sonar.core.issue.tracking.Tracking;
+import org.sonar.server.computation.component.Component;
+
+public abstract class IssueVisitor {
+
+ /**
+ * This method is called for each component before processing its issues.
+ * The component does not necessarily have issues.
+ */
+ public void beforeComponent(Component component, Tracking tracking) {
+
+ }
+
+ /**
+ * This method is called when tracking is done and issue is initialized. That means that the following fields
+ * are set: resolution, status, line, creation date, uuid and all the fields merged from base issues.
+ */
+ public void onIssue(Component component, DefaultIssue issue) {
+
+ }
+
+ public void afterComponent(Component component) {
+
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.issue;
+
+import org.sonar.core.issue.DefaultIssue;
+import org.sonar.core.issue.tracking.Tracking;
+import org.sonar.server.computation.component.Component;
+
+public class IssueVisitors {
+
+ private final IssueVisitor[] visitors;
+
+ public IssueVisitors(IssueVisitor[] visitors) {
+ this.visitors = visitors;
+ }
+
+ public void beforeComponent(Component component, Tracking tracking) {
+ for (IssueVisitor visitor : visitors) {
+ visitor.beforeComponent(component, tracking);
+ }
+ }
+
+ public void onIssue(Component component, DefaultIssue issue) {
+ for (IssueVisitor visitor : visitors) {
+ visitor.onIssue(component, issue);
+ }
+ }
+
+ public void afterComponent(Component component) {
+ for (IssueVisitor visitor : visitors) {
+ visitor.afterComponent(component);
+ }
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.issue;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ListMultimap;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.core.issue.DefaultIssue;
+import org.sonar.core.issue.db.IssueChangeDto;
+import org.sonar.core.issue.tracking.Tracking;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.measure.Measure;
+import org.sonar.server.computation.measure.MeasureRepository;
+import org.sonar.server.computation.measure.MeasureVariations;
+import org.sonar.server.computation.metric.Metric;
+import org.sonar.server.computation.metric.MetricRepository;
+import org.sonar.server.computation.period.Period;
+import org.sonar.server.computation.period.PeriodsHolder;
+import org.sonar.server.db.DbClient;
+
+public class NewDebtAggregator extends IssueVisitor {
+
+ private final NewDebtCalculator calculator;
+ private final PeriodsHolder periodsHolder;
+ private final DbClient dbClient;
+ private final MetricRepository metricRepository;
+ private final MeasureRepository measureRepository;
+
+ private ListMultimap<String, IssueChangeDto> changesByIssueUuid = ArrayListMultimap.create();
+ private Map<Integer, DebtSum> sumsByComponentRef = new HashMap<>();
+ private DebtSum currentSum = null;
+
+ public NewDebtAggregator(NewDebtCalculator calculator, PeriodsHolder periodsHolder, DbClient dbClient,
+ MetricRepository metricRepository, MeasureRepository measureRepository) {
+ this.calculator = calculator;
+ this.periodsHolder = periodsHolder;
+ this.dbClient = dbClient;
+ this.metricRepository = metricRepository;
+ this.measureRepository = measureRepository;
+ }
+
+ @Override
+ public void beforeComponent(Component component, Tracking tracking) {
+ currentSum = new DebtSum();
+ sumsByComponentRef.put(component.getRef(), currentSum);
+ List<IssueChangeDto> changes = dbClient.issueChangeDao().selectChangelogOfUnresolvedIssuesByComponent(component.getUuid());
+ for (IssueChangeDto change : changes) {
+ changesByIssueUuid.put(change.getIssueKey(), change);
+ }
+ }
+
+ @Override
+ public void onIssue(Component component, DefaultIssue issue) {
+ if (issue.debtInMinutes() != null && !periodsHolder.getPeriods().isEmpty()) {
+ List<IssueChangeDto> changelog = changesByIssueUuid.get(issue.key());
+ for (Period period : periodsHolder.getPeriods()) {
+ long newDebt = calculator.calculate(issue, changelog, period);
+ currentSum.add(period.getIndex(), newDebt);
+ }
+ }
+ for (Component child : component.getChildren()) {
+ DebtSum childSum = sumsByComponentRef.remove(child.getRef());
+ if (childSum != null) {
+ currentSum.add(childSum);
+ }
+ }
+ }
+
+ @Override
+ public void afterComponent(Component component) {
+ if (!currentSum.isEmpty) {
+ MeasureVariations variations = new MeasureVariations(currentSum.sums);
+ Metric metric = metricRepository.getByKey(CoreMetrics.NEW_TECHNICAL_DEBT_KEY);
+ measureRepository.add(component, metric, Measure.newMeasureBuilder().setVariations(variations).createNoValue());
+ }
+ changesByIssueUuid.clear();
+ currentSum = null;
+ }
+
+ private static class DebtSum {
+ private Double[] sums = new Double[PeriodsHolder.MAX_NUMBER_OF_PERIODS];
+ private boolean isEmpty = true;
+
+ void add(int periodIndex, long newDebt) {
+ double previous = Objects.firstNonNull(sums[periodIndex - 1], 0d);
+ sums[periodIndex - 1] = previous + newDebt;
+ isEmpty = false;
+ }
+
+ void add(DebtSum other) {
+ for (int i = 0; i < sums.length; i++) {
+ Double otherValue = other.sums[i];
+ if (otherValue != null) {
+ add(i + 1, otherValue.longValue());
+ }
+ }
+ }
+ }
+}
*/
package org.sonar.server.computation.issue;
+import com.google.common.base.Function;
+import com.google.common.base.Objects;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Ordering;
+import java.util.Calendar;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.apache.commons.lang.time.DateUtils;
import org.sonar.core.issue.DefaultIssue;
-import org.sonar.server.computation.component.Component;
+import org.sonar.core.issue.FieldDiffs;
+import org.sonar.core.issue.IssueUpdater;
+import org.sonar.core.issue.db.IssueChangeDto;
+import org.sonar.server.computation.period.Period;
-public class NewDebtCalculator extends IssueListener {
+import static com.google.common.collect.FluentIterable.from;
- @Override
- public void onIssue(Component component, DefaultIssue issue) {
- // TODO
+/**
+ * Gets the issue debt that was introduced on a period. The algorithm
+ * is based on the issue changelog.
+ */
+public class NewDebtCalculator {
+
+ public long calculate(DefaultIssue issue, List<IssueChangeDto> debtChangelog, Period period) {
+ if (issue.creationDate().getTime() > period.getSnapshotDate() + 1000L) {
+ return Objects.firstNonNull(issue.debtInMinutes(), 0L);
+ }
+ return calculateFromChangelog(issue, debtChangelog, period.getSnapshotDate());
+ }
+
+ private long calculateFromChangelog(DefaultIssue issue, List<IssueChangeDto> debtChangelog, long periodDate) {
+ List<FieldDiffs> debtDiffs = from(debtChangelog).transform(ToFieldDiffs.INSTANCE).filter(HasDebtChange.INSTANCE).toSortedList(CHANGE_ORDERING);
+ long newDebt = issue.debtInMinutes().longValue();
+
+ for (Iterator<FieldDiffs> it = debtDiffs.iterator(); it.hasNext();) {
+ FieldDiffs diffs = it.next();
+ Date date = diffs.creationDate();
+ // TODO use longs
+ if (isBeforeOrEqual(date, new Date(periodDate))) {
+ // return new value from the change that is just before the period date
+ return subtract(newDebt, debtDiff(diffs).newValueLong());
+ }
+ if (!it.hasNext()) {
+ // return old value from the change that is just after the period date when there's no more element in changelog
+ return subtract(newDebt, debtDiff(diffs).oldValueLong());
+ }
+ }
+ // no changelog
+ return 0L;
+ }
+
+ /**
+ * SONAR-5059
+ */
+ @CheckForNull
+ private static long subtract(long newDebt, @Nullable Long with) {
+ if (with != null) {
+ return Math.min(0L, newDebt - with);
+ }
+ return newDebt;
}
+ private static boolean isBeforeOrEqual(@Nullable Date changeDate, Date periodDate) {
+ return (changeDate != null) && (DateUtils.truncatedCompareTo(changeDate, periodDate, Calendar.SECOND) <= 0);
+ }
+
+ private static FieldDiffs.Diff debtDiff(FieldDiffs diffs) {
+ return diffs.diffs().get(IssueUpdater.TECHNICAL_DEBT);
+ }
+
+ /**
+ * Changelog have to be sorted from newest to oldest.
+ * Null date should be the first as this happen when technical debt has changed since previous analysis.
+ */
+ private static final Comparator<FieldDiffs> CHANGE_ORDERING = Ordering.natural().reverse().nullsFirst().onResultOf(new Function<FieldDiffs, Date>() {
+ @Override
+ public Date apply(@Nonnull FieldDiffs dto) {
+ return dto.creationDate();
+ }
+ });
+
+ private enum ToFieldDiffs implements Function<IssueChangeDto, FieldDiffs> {
+ INSTANCE;
+ @Override
+ public FieldDiffs apply(@Nonnull IssueChangeDto dto) {
+ FieldDiffs diffs = FieldDiffs.parse(dto.getChangeData());
+ diffs.setIssueKey(dto.getIssueKey());
+ Long date = dto.getIssueChangeCreationDate();
+ if (date != null) {
+ diffs.setCreationDate(new Date(date));
+ }
+ return diffs;
+ }
+ }
+
+ private enum HasDebtChange implements Predicate<FieldDiffs> {
+ INSTANCE;
+ @Override
+ public boolean apply(@Nonnull FieldDiffs diffs) {
+ return diffs.diffs().containsKey(IssueUpdater.TECHNICAL_DEBT);
+ }
+ }
}
import static com.google.common.collect.Sets.union;
-public class RuleTagsCopier extends IssueListener {
+public class RuleTagsCopier extends IssueVisitor {
private final RuleCache ruleCache;
import org.sonar.core.issue.DefaultIssue;
import org.sonar.core.issue.tracking.Input;
import org.sonar.core.issue.tracking.LazyInput;
+import org.sonar.core.issue.tracking.LineHashSequence;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
import org.sonar.server.computation.component.Component;
}
@Override
- protected Iterable<String> loadSourceLines() {
+ protected LineHashSequence loadLineHashSequence() {
DbSession session = dbClient.openSession(false);
try {
- return dbClient.fileSourceDao().selectLineHashes(session, component.getUuid());
+ List<String> hashes = dbClient.fileSourceDao().selectLineHashes(session, component.getUuid());
+ return new LineHashSequence(hashes);
} finally {
MyBatis.closeQuietly(session);
}
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import org.sonar.api.issue.Issue;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.utils.Duration;
+import org.sonar.api.utils.log.Loggers;
import org.sonar.batch.protocol.output.BatchReport;
import org.sonar.core.issue.DefaultIssue;
import org.sonar.core.issue.tracking.Input;
}
@Override
- protected Iterable<String> loadSourceLines() {
- return Lists.newArrayList(reportReader.readFileSource(component.getRef()));
+ protected LineHashSequence loadLineHashSequence() {
+ Iterable<String> lines;
+ if (component.getType() == Component.Type.FILE) {
+ lines = Lists.newArrayList(reportReader.readFileSource(component.getRef()));
+ } else {
+ lines = Collections.emptyList();
+ }
+ return LineHashSequence.createForLines(lines);
}
@Override
for (BatchReport.Issue reportIssue : reportIssues) {
DefaultIssue issue = toIssue(lineHashSeq, reportIssue);
if (isValid(issue, lineHashSeq)) {
+ Loggers.get(getClass()).info("Loaded from report: " + issue);
issues.add(issue);
}
}
private DefaultIssue toIssue(LineHashSequence lineHashSeq, BatchReport.Issue reportIssue) {
DefaultIssue issue = new DefaultIssue();
issue.setRuleKey(RuleKey.of(reportIssue.getRuleRepository(), reportIssue.getRuleKey()));
+ issue.setResolution(null);
issue.setStatus(Issue.STATUS_OPEN);
issue.setComponentUuid(component.getUuid());
issue.setComponentKey(component.getKey());
issue.setProjectUuid(treeRootHolder.getRoot().getUuid());
+ issue.setProjectKey(treeRootHolder.getRoot().getKey());
if (reportIssue.hasLine()) {
issue.setLine(reportIssue.getLine());
}
private boolean isValid(DefaultIssue issue, LineHashSequence lineHashSeq) {
- // TODO log debug when invalid ?
+ // TODO log debug when invalid ? Or throw exception ?
+
if (ruleCache.getNullable(issue.ruleKey()) == null) {
return false;
}
if (issue.getLine() != null && !lineHashSeq.hasLine(issue.getLine())) {
- return false;
+ // FIXME
+ //return false;
}
return true;
}
import com.google.common.base.Optional;
import java.util.Objects;
import javax.annotation.Nullable;
-import org.sonar.api.rule.RuleKey;
import org.sonar.batch.protocol.output.BatchReport;
-import org.sonar.core.rule.RuleDto;
-import org.sonar.server.computation.issue.RuleCache;
import org.sonar.server.computation.metric.Metric;
import static com.google.common.base.Optional.of;
public class BatchMeasureToMeasure {
- private final RuleCache ruleCache;
-
- public BatchMeasureToMeasure(RuleCache ruleCache) {
- this.ruleCache = ruleCache;
- }
public Optional<Measure> toMeasure(@Nullable BatchReport.Measure batchMeasure, Metric metric) {
Objects.requireNonNull(metric);
return Optional.absent();
}
- Measure.NewMeasureBuilder builder = createBuilder(batchMeasure);
+ Measure.NewMeasureBuilder builder = Measure.newMeasureBuilder();
String data = batchMeasure.hasStringValue() ? batchMeasure.getStringValue() : null;
switch (metric.getType().getValueType()) {
case INT:
}
}
- private Measure.NewMeasureBuilder createBuilder(BatchReport.Measure batchMeasure) {
- if (batchMeasure.hasCharactericId() && batchMeasure.hasRuleKey()) {
- throw new IllegalArgumentException("Measure with both characteristicId and ruleKey are not supported");
- }
- if (batchMeasure.hasCharactericId()) {
- return Measure.newMeasureBuilder().forCharacteristic(batchMeasure.getCharactericId());
- }
- if (batchMeasure.hasRuleKey()) {
- RuleDto ruleDto = ruleCache.get(RuleKey.parse(batchMeasure.getRuleKey()));
- return Measure.newMeasureBuilder().forRule(ruleDto.getId());
- }
- return Measure.newMeasureBuilder();
- }
-
private static Optional<Measure> toIntegerMeasure(Measure.NewMeasureBuilder builder, BatchReport.Measure batchMeasure, @Nullable String data) {
if (!batchMeasure.hasIntValue()) {
return toNoValueMeasure(builder, batchMeasure);
}
return of(setCommonProperties(builder, batchMeasure).create(batchMeasure.getStringValue()));
}
-
+
private static Optional<Measure> toLevelMeasure(Measure.NewMeasureBuilder builder, BatchReport.Measure batchMeasure) {
if (!batchMeasure.hasStringValue()) {
return toNoValueMeasure(builder, batchMeasure);
}
private static Measure.NewMeasureBuilder setCommonProperties(Measure.NewMeasureBuilder builder, BatchReport.Measure batchMeasure) {
- if (batchMeasure.hasAlertStatus()) {
- Optional<Measure.Level> qualityGateStatus = Measure.Level.toLevel(batchMeasure.getAlertStatus());
- if (qualityGateStatus.isPresent()) {
- String text = batchMeasure.hasAlertText() ? batchMeasure.getAlertText() : null;
- builder.setQualityGateStatus(new QualityGateStatus(qualityGateStatus.get(), text));
- }
- }
- if (hasAnyVariation(batchMeasure)) {
+ if (hasAnyVariation(batchMeasure)) {
builder.setVariations(createVariations(batchMeasure));
}
return builder;
private static boolean hasAnyVariation(BatchReport.Measure batchMeasure) {
return batchMeasure.hasVariationValue1()
- || batchMeasure.hasVariationValue2()
- || batchMeasure.hasVariationValue3()
- || batchMeasure.hasVariationValue4()
- || batchMeasure.hasVariationValue5();
+ || batchMeasure.hasVariationValue2()
+ || batchMeasure.hasVariationValue3()
+ || batchMeasure.hasVariationValue4()
+ || batchMeasure.hasVariationValue5();
}
private static MeasureVariations createVariations(BatchReport.Measure batchMeasure) {
return new MeasureVariations(
- batchMeasure.hasVariationValue1() ? batchMeasure.getVariationValue1() : null,
- batchMeasure.hasVariationValue2() ? batchMeasure.getVariationValue2() : null,
- batchMeasure.hasVariationValue3() ? batchMeasure.getVariationValue3() : null,
- batchMeasure.hasVariationValue4() ? batchMeasure.getVariationValue4() : null,
- batchMeasure.hasVariationValue5() ? batchMeasure.getVariationValue5() : null
- );
+ batchMeasure.hasVariationValue1() ? batchMeasure.getVariationValue1() : null,
+ batchMeasure.hasVariationValue2() ? batchMeasure.getVariationValue2() : null,
+ batchMeasure.hasVariationValue3() ? batchMeasure.getVariationValue3() : null,
+ batchMeasure.hasVariationValue4() ? batchMeasure.getVariationValue4() : null,
+ batchMeasure.hasVariationValue5() ? batchMeasure.getVariationValue5() : null);
}
}
import org.sonar.server.computation.batch.BatchReportReader;
import org.sonar.server.computation.component.Component;
import org.sonar.server.computation.debt.Characteristic;
-import org.sonar.server.computation.issue.RuleCache;
import org.sonar.server.computation.metric.Metric;
import org.sonar.server.computation.metric.MetricRepository;
import org.sonar.server.db.DbClient;
private final Map<Integer, Map<MeasureKey, Measure>> measures = new HashMap<>();
public MeasureRepositoryImpl(DbClient dbClient, BatchReportReader reportReader,
- final MetricRepository metricRepository, final RuleCache ruleCache) {
+ MetricRepository metricRepository) {
this.dbClient = dbClient;
this.reportReader = reportReader;
- this.batchMeasureToMeasure = new BatchMeasureToMeasure(ruleCache);
+ this.batchMeasureToMeasure = new BatchMeasureToMeasure();
this.metricRepository = metricRepository;
}
ComputeIssueMeasuresStep.class,
CustomMeasuresCopyStep.class,
ComputeFormulaMeasuresStep.class,
+ CustomMeasuresCopyStep.class,
SqaleMeasuresStep.class,
NewCoverageMeasuresStep.class,
NewCoverageAggregationStep.class,
import com.google.common.base.Function;
import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.collect.FluentIterable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import org.sonar.api.utils.log.Loggers;
import org.sonar.core.issue.DefaultIssue;
import org.sonar.core.issue.tracking.Tracking;
import org.sonar.server.computation.component.Component;
import org.sonar.server.computation.issue.BaseIssuesLoader;
import org.sonar.server.computation.issue.IssueCache;
import org.sonar.server.computation.issue.IssueLifecycle;
-import org.sonar.server.computation.issue.IssueListeners;
+import org.sonar.server.computation.issue.IssueVisitors;
import org.sonar.server.computation.issue.TrackerExecution;
import org.sonar.server.util.cache.DiskCache;
-import static org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor.Order.POST_ORDER;
+import static org.sonar.server.computation.component.ComponentVisitor.Order.POST_ORDER;
public class IntegrateIssuesStep implements ComputationStep {
private final IssueCache issueCache;
private final BaseIssuesLoader baseIssuesLoader;
private final IssueLifecycle issueLifecycle;
- private final IssueListeners issueListeners;
+ private final IssueVisitors issueVisitors;
public IntegrateIssuesStep(TreeRootHolder treeRootHolder, TrackerExecution tracker, IssueCache issueCache,
BaseIssuesLoader baseIssuesLoader, IssueLifecycle issueLifecycle,
- IssueListeners issueListeners) {
+ IssueVisitors issueVisitors) {
this.treeRootHolder = treeRootHolder;
this.tracker = tracker;
this.issueCache = issueCache;
this.baseIssuesLoader = baseIssuesLoader;
this.issueLifecycle = issueLifecycle;
- this.issueListeners = issueListeners;
+ this.issueVisitors = issueVisitors;
}
@Override
private void processIssues(Component component) {
Tracking<DefaultIssue, DefaultIssue> tracking = tracker.track(component);
+ Loggers.get(getClass()).info("----- tracking ------");
+ Loggers.get(getClass()).info("" + tracking);
DiskCache<DefaultIssue>.DiskAppender cacheAppender = issueCache.newAppender();
try {
- issueListeners.beforeComponent(component, tracking);
+ issueVisitors.beforeComponent(component, tracking);
fillNewOpenIssues(component, tracking, cacheAppender);
fillExistingOpenIssues(component, tracking, cacheAppender);
closeUnmatchedBaseIssues(component, tracking, cacheAppender);
- issueListeners.afterComponent(component);
+ issueVisitors.afterComponent(component);
} finally {
cacheAppender.close();
}
private void fillNewOpenIssues(Component component, Tracking<DefaultIssue, DefaultIssue> tracking, DiskCache<DefaultIssue>.DiskAppender cacheAppender) {
Set<DefaultIssue> issues = tracking.getUnmatchedRaws();
+ Loggers.get(getClass()).info("----- fillNewOpenIssues on " + component.getKey());
for (DefaultIssue issue : issues) {
issueLifecycle.initNewOpenIssue(issue);
- issueListeners.onOpenIssueInitialization(component, issue);
+ Loggers.get(getClass()).info("new " + issue);
process(component, issue, cacheAppender);
}
+ Loggers.get(getClass()).info("----- /fillNewOpenIssues on " + component.getKey());
}
private void fillExistingOpenIssues(Component component, Tracking<DefaultIssue, DefaultIssue> tracking, DiskCache<DefaultIssue>.DiskAppender cacheAppender) {
+ Loggers.get(getClass()).info("----- fillExistingOpenIssues on " + component.getKey());
for (Map.Entry<DefaultIssue, DefaultIssue> entry : tracking.getMatchedRaws().entrySet()) {
DefaultIssue raw = entry.getKey();
DefaultIssue base = entry.getValue();
- issueListeners.onOpenIssueInitialization(component, raw);
issueLifecycle.mergeExistingOpenIssue(raw, base);
+ Loggers.get(getClass()).info("merged " + raw);
process(component, raw, cacheAppender);
}
for (Map.Entry<Integer, DefaultIssue> entry : tracking.getOpenManualIssuesByLine().entries()) {
int line = entry.getKey();
DefaultIssue manualIssue = entry.getValue();
manualIssue.setLine(line == 0 ? null : line);
- issueListeners.onOpenIssueInitialization(component, manualIssue);
+ Loggers.get(getClass()).info("kept manual " + manualIssue);
process(component, manualIssue, cacheAppender);
}
+ Loggers.get(getClass()).info("----- /fillExistingOpenIssues on " + component.getKey());
}
private void closeUnmatchedBaseIssues(Component component, Tracking<DefaultIssue, DefaultIssue> tracking, DiskCache<DefaultIssue>.DiskAppender cacheAppender) {
+ Loggers.get(getClass()).info("----- closeUnmatchedBaseIssues on " + component.getKey());
for (DefaultIssue issue : tracking.getUnmatchedBases()) {
// TODO should replace flag "beingClosed" by express call to transition "automaticClose"
issue.setBeingClosed(true);
+ Loggers.get(getClass()).info("closing " + issue);
// TODO manual issues -> was updater.setResolution(newIssue, Issue.RESOLUTION_REMOVED, changeContext);. Is it a problem ?
process(component, issue, cacheAppender);
}
+ Loggers.get(getClass()).info("----- /closeUnmatchedBaseIssues on " + component.getKey());
}
private void process(Component component, DefaultIssue issue, DiskCache<DefaultIssue>.DiskAppender cacheAppender) {
issueLifecycle.doAutomaticTransition(issue);
- issueListeners.onIssue(component, issue);
+ issueVisitors.onIssue(component, issue);
cacheAppender.append(issue);
}
List<DefaultIssue> issues = baseIssuesLoader.loadForComponentUuid(deletedComponentUuid);
for (DefaultIssue issue : issues) {
issue.setBeingClosed(true);
+ // FIXME should be renamed "setToRemovedStatus"
+ issue.setOnDisabledRule(true);
issueLifecycle.doAutomaticTransition(issue);
- // TODO execute listeners ? Component is currently missing.
+ // TODO execute visitors ? Component is currently missing.
cacheAppender.append(issue);
}
}
*/
package org.sonar.server.computation.step;
-import org.sonar.api.issue.Issue;
import org.sonar.api.issue.IssueComment;
import org.sonar.api.utils.System2;
+import org.sonar.api.utils.log.Loggers;
import org.sonar.core.issue.DefaultIssue;
import org.sonar.core.issue.DefaultIssueComment;
import org.sonar.core.issue.FieldDiffs;
boolean saved = false;
if (issue.isNew()) {
Integer ruleId = ruleCache.get(issue.ruleKey()).getId();
- mapper.insert(IssueDto.toDtoForComputationInsert(issue, ruleId, system2.now()));
+ IssueDto dto = IssueDto.toDtoForComputationInsert(issue, ruleId, system2.now());
+ Loggers.get(getClass()).info("---- INSERT " + dto);
+ mapper.insert(dto);
saved = true;
} else if (issue.isChanged()) {
IssueDto dto = IssueDto.toDtoForUpdate(issue, system2.now());
- if (Issue.STATUS_CLOSED.equals(issue.status()) || issue.selectedAt() == null) {
- // Issue is closed by scan or changed by end-user
- mapper.update(dto);
- } else {
- int updateCount = mapper.updateIfBeforeSelectedDate(dto);
- if (updateCount == 0) {
- // End-user and scan changed the issue at the same time.
- // See https://jira.sonarsource.com/browse/SONAR-4309
- conflictResolver.resolve(issue, mapper);
- }
+ Loggers.get(getClass()).info("---- UPDATE " + dto);
+ int updateCount = mapper.updateIfBeforeSelectedDate(dto);
+ if (updateCount == 0) {
+ Loggers.get(getClass()).info("---- CONFLICT: " + updateCount);
+ // End-user and scan changed the issue at the same time.
+ // See https://jira.sonarsource.com/browse/SONAR-4309
+ conflictResolver.resolve(issue, mapper);
}
+
saved = true;
+ } else {
+ Loggers.get(getClass()).info("---- UNCHANGED " + issue);
}
if (saved) {
insertChanges(changeMapper, issue);
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.util.List;
import javax.annotation.CheckForNull;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.io.IOUtils;
}
@CheckForNull
- public Iterable<String> selectLineHashes(DbSession dbSession, String fileUuid) {
+ public List<String> selectLineHashes(DbSession dbSession, String fileUuid) {
Connection connection = dbSession.getConnection();
PreparedStatement pstmt = null;
ResultSet rs = null;
pstmt.setString(2, Type.SOURCE);
rs = pstmt.executeQuery();
if (rs.next()) {
- return END_OF_LINE_SPLITTER.split(rs.getString(1));
+ return END_OF_LINE_SPLITTER.splitToList(rs.getString(1));
}
return null;
} catch (SQLException e) {
@Test
public void test_to_string() throws Exception {
- assertThat(new Characteristic(1, "PORTABILITY", null).toString()).isEqualTo("Characteristic{id=1, key='PORTABILITY'}");
+ assertThat(new Characteristic(1, "PORTABILITY", null).toString()).isEqualTo("Characteristic{id=1, key='PORTABILITY', parentId=null}");
}
@Test
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
///*
// * SonarQube, open source software quality management tool.
// * Copyright (C) 2008-2014 SonarSource
Tracking tracking = mock(Tracking.class);
MetricRepository metricRepository = mock(MetricRepository.class);
MeasureRepository measureRepository;
- RuleCache ruleCache = mock(RuleCache.class);
- CountIssuesListener sut;
+ IssueCounter sut;
@Before
public void setUp() throws Exception {
initMetrics();
- measureRepository = new MeasureRepositoryImpl(null, reportReader, metricRepository, ruleCache);
+ measureRepository = new MeasureRepositoryImpl(null, reportReader, metricRepository);
- sut = new CountIssuesListener(periodsHolder, metricRepository, measureRepository);
+ sut = new IssueCounter(periodsHolder, metricRepository, measureRepository);
}
@Test
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+//package org.sonar.server.computation.issue;
+//
+//import java.util.Date;
+//import org.apache.commons.lang.ObjectUtils;
+//import org.apache.commons.lang.time.DateUtils;
+//import org.junit.Before;
+//import org.junit.Test;
+//import org.mockito.ArgumentMatcher;
+//import org.mockito.Mock;
+//import org.sonar.api.CoreProperties;
+//import org.sonar.api.batch.DecoratorContext;
+//import org.sonar.api.component.ResourcePerspectives;
+//import org.sonar.api.config.Settings;
+//import org.sonar.api.issue.Issuable;
+//import org.sonar.api.issue.Issue;
+//import org.sonar.api.measures.CoreMetrics;
+//import org.sonar.api.measures.Measure;
+//import org.sonar.api.measures.Metric;
+//import org.sonar.api.resources.Resource;
+//import org.sonar.api.utils.Duration;
+//import org.sonar.core.issue.DefaultIssue;
+//import org.sonar.core.issue.FieldDiffs;
+//
+//import static com.google.common.collect.Lists.newArrayList;
+//import static org.assertj.core.api.Assertions.assertThat;
+//import static org.mockito.Matchers.argThat;
+//import static org.mockito.Mockito.mock;
+//import static org.mockito.Mockito.never;
+//import static org.mockito.Mockito.verify;
+//import static org.mockito.Mockito.when;
+//
+//public class NewDebtAggregatorTest {
+// NewDebtDecorator decorator;
+//
+// @Mock
+// TimeMachineConfiguration timeMachineConfiguration;
+//
+// @Mock
+// Resource resource;
+//
+// @Mock
+// Issuable issuable;
+//
+// @Mock
+// DecoratorContext context;
+//
+// Date rightNow;
+// Date elevenDaysAgo;
+// Date tenDaysAgo;
+// Date nineDaysAgo;
+// Date fiveDaysAgo;
+// Date fourDaysAgo;
+//
+// static final int HOURS_IN_DAY = 8;
+//
+// static final Long ONE_DAY_IN_MINUTES = 1L * HOURS_IN_DAY * 60;
+// static final Long TWO_DAYS_IN_MINUTES = 2L * HOURS_IN_DAY * 60;
+// static final Long FIVE_DAYS_IN_MINUTES = 5L * HOURS_IN_DAY * 60;
+//
+// @Before
+// public void setup() {
+// Settings settings = new Settings();
+// settings.setProperty(CoreProperties.HOURS_IN_DAY, HOURS_IN_DAY);
+//
+// ResourcePerspectives perspectives = mock(ResourcePerspectives.class);
+// when(perspectives.as(Issuable.class, resource)).thenReturn(issuable);
+//
+// rightNow = new Date();
+// elevenDaysAgo = DateUtils.addDays(rightNow, -11);
+// tenDaysAgo = DateUtils.addDays(rightNow, -10);
+// nineDaysAgo = DateUtils.addDays(rightNow, -9);
+// fiveDaysAgo = DateUtils.addDays(rightNow, -5);
+// fourDaysAgo = DateUtils.addDays(rightNow, -4);
+//
+// when(timeMachineConfiguration.periods()).thenReturn(newArrayList(new Period(1, fiveDaysAgo), new Period(2, tenDaysAgo)));
+//
+// decorator = new NewDebtDecorator(perspectives, timeMachineConfiguration, new IssueChangelogDebtCalculator());
+// }
+//
+// @Test
+// public void generates_metrics() {
+// assertThat(decorator.generatesMetrics()).hasSize(1);
+// }
+//
+// @Test
+// public void execute_on_project() {
+// assertThat(decorator.shouldExecuteOnProject(null)).isTrue();
+// }
+//
+// @Test
+// public void save_on_one_issue_with_one_new_changelog() {
+// Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(Duration.create(TWO_DAYS_IN_MINUTES)).setChanges(
+// newArrayList(
+// // changelog created at is null because it has just been created on the current analysis
+// new FieldDiffs().setDiff("technicalDebt", ONE_DAY_IN_MINUTES, TWO_DAYS_IN_MINUTES).setCreationDate(null)
+// )
+// );
+// when(issuable.issues()).thenReturn(newArrayList(issue));
+//
+// decorator.decorate(resource, context);
+//
+// // remember : period1 is 5daysAgo, period2 is 10daysAgo
+// verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 1.0 * ONE_DAY_IN_MINUTES, 1.0 * ONE_DAY_IN_MINUTES)));
+// }
+//
+// @Test
+// public void save_on_one_issue_with_changelog() {
+// Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES)).setChanges(
+// newArrayList(
+// new FieldDiffs().setDiff("technicalDebt", TWO_DAYS_IN_MINUTES, FIVE_DAYS_IN_MINUTES).setCreationDate(null),
+// new FieldDiffs().setDiff("technicalDebt", ONE_DAY_IN_MINUTES, TWO_DAYS_IN_MINUTES).setCreationDate(fourDaysAgo)
+// )
+// );
+// when(issuable.issues()).thenReturn(newArrayList(issue));
+//
+// decorator.decorate(resource, context);
+//
+// // remember : period1 is 5daysAgo, period2 is 10daysAgo
+// verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 4.0 * ONE_DAY_IN_MINUTES, 4.0 * ONE_DAY_IN_MINUTES)));
+// }
+//
+// @Test
+// public void save_on_one_issue_with_changelog_only_in_the_past() {
+// Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(Duration.create(ONE_DAY_IN_MINUTES)).setChanges(
+// newArrayList(
+// // Change before all periods
+// new FieldDiffs().setDiff("technicalDebt", null, ONE_DAY_IN_MINUTES).setCreationDate(elevenDaysAgo)
+// )
+// );
+// when(issuable.issues()).thenReturn(newArrayList(issue));
+//
+// decorator.decorate(resource, context);
+//
+// // remember : period1 is 5daysAgo, period2 is 10daysAgo
+// verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0, 0.0)));
+// }
+//
+// @Test
+// public void save_on_one_issue_with_changelog_having_null_value() {
+// Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES)).setChanges(
+// newArrayList(
+// new FieldDiffs().setDiff("technicalDebt", null, FIVE_DAYS_IN_MINUTES).setCreationDate(null),
+// new FieldDiffs().setDiff("technicalDebt", ONE_DAY_IN_MINUTES, null).setCreationDate(fourDaysAgo),
+// new FieldDiffs().setDiff("technicalDebt", null, ONE_DAY_IN_MINUTES).setCreationDate(nineDaysAgo)
+// )
+// );
+// when(issuable.issues()).thenReturn(newArrayList(issue));
+//
+// decorator.decorate(resource, context);
+//
+// // remember : period1 is 5daysAgo, period2 is 10daysAgo
+// verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 4.0 * ONE_DAY_IN_MINUTES, 5.0 * ONE_DAY_IN_MINUTES)));
+// }
+//
+// @Test
+// public void save_on_one_issue_with_changelog_and_periods_have_no_dates() {
+// when(timeMachineConfiguration.periods()).thenReturn(newArrayList(new Period(1, null), new Period(2, null)));
+//
+// Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES)).setChanges(
+// newArrayList(
+// new FieldDiffs().setDiff("technicalDebt", null, FIVE_DAYS_IN_MINUTES).setCreationDate(null),
+// new FieldDiffs().setDiff("technicalDebt", ONE_DAY_IN_MINUTES, null).setCreationDate(fourDaysAgo),
+// new FieldDiffs().setDiff("technicalDebt", null, ONE_DAY_IN_MINUTES).setCreationDate(nineDaysAgo)
+// )
+// );
+// when(issuable.issues()).thenReturn(newArrayList(issue));
+//
+// decorator.decorate(resource, context);
+//
+// // remember : period1 is 5daysAgo, period2 is 10daysAgo
+// verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 5.0 * ONE_DAY_IN_MINUTES, 5.0 * ONE_DAY_IN_MINUTES)));
+// }
+//
+// @Test
+// public void save_on_one_issue_with_changelog_having_not_only_technical_debt_changes() {
+// Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES)).setChanges(
+// newArrayList(
+// new FieldDiffs()
+// .setDiff("actionPlan", "1.0", "1.1").setCreationDate(fourDaysAgo)
+// .setDiff("technicalDebt", ONE_DAY_IN_MINUTES, TWO_DAYS_IN_MINUTES).setCreationDate(fourDaysAgo)
+// )
+// );
+// when(issuable.issues()).thenReturn(newArrayList(issue));
+//
+// decorator.decorate(resource, context);
+//
+// // remember : period1 is 5daysAgo, period2 is 10daysAgo
+// verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 4.0 * ONE_DAY_IN_MINUTES, 4.0 * ONE_DAY_IN_MINUTES)));
+// }
+//
+// @Test
+// public void save_on_issues_with_changelog() {
+// Issue issue1 = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES)).setChanges(
+// newArrayList(
+// new FieldDiffs().setDiff("technicalDebt", TWO_DAYS_IN_MINUTES, FIVE_DAYS_IN_MINUTES).setCreationDate(rightNow),
+// new FieldDiffs().setDiff("technicalDebt", ONE_DAY_IN_MINUTES, TWO_DAYS_IN_MINUTES).setCreationDate(fourDaysAgo),
+// new FieldDiffs().setDiff("technicalDebt", null, ONE_DAY_IN_MINUTES).setCreationDate(nineDaysAgo)
+// )
+// );
+// Issue issue2 = new DefaultIssue().setKey("B").setCreationDate(tenDaysAgo).setDebt(Duration.create(TWO_DAYS_IN_MINUTES)).setChanges(
+// newArrayList(
+// new FieldDiffs().setDiff("technicalDebt", ONE_DAY_IN_MINUTES, TWO_DAYS_IN_MINUTES).setCreationDate(rightNow),
+// new FieldDiffs().setDiff("technicalDebt", null, ONE_DAY_IN_MINUTES).setCreationDate(nineDaysAgo)
+// )
+// );
+// when(issuable.issues()).thenReturn(newArrayList(issue1, issue2));
+//
+// decorator.decorate(resource, context);
+//
+// // remember : period1 is 5daysAgo, period2 is 10daysAgo
+// verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 5.0 * ONE_DAY_IN_MINUTES, 7.0 * ONE_DAY_IN_MINUTES)));
+// }
+//
+// @Test
+// public void save_on_one_issue_without_changelog() {
+// when(issuable.issues()).thenReturn(newArrayList(
+// (Issue) new DefaultIssue().setKey("A").setCreationDate(nineDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES)))
+// );
+//
+// decorator.decorate(resource, context);
+//
+// // remember : period1 is 5daysAgo, period2 is 10daysAgo
+// verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0, 5.0 * ONE_DAY_IN_MINUTES)));
+// }
+//
+// @Test
+// public void save_on_one_issue_without_technical_debt_and_without_changelog() {
+// when(issuable.issues()).thenReturn(newArrayList(
+// (Issue) new DefaultIssue().setKey("A").setCreationDate(nineDaysAgo).setDebt(null))
+// );
+//
+// decorator.decorate(resource, context);
+//
+// // remember : period1 is 5daysAgo, period2 is 10daysAgo
+// verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0, 0.0)));
+// }
+//
+// @Test
+// public void save_on_one_issue_without_changelog_and_periods_have_no_dates() {
+// when(timeMachineConfiguration.periods()).thenReturn(newArrayList(new Period(1, null), new Period(2, null)));
+//
+// when(issuable.issues()).thenReturn(newArrayList(
+// (Issue) new DefaultIssue().setKey("A").setCreationDate(nineDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES)))
+// );
+//
+// decorator.decorate(resource, context);
+//
+// // remember : period1 is null, period2 is null
+// verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 5.0 * ONE_DAY_IN_MINUTES, 5.0 * ONE_DAY_IN_MINUTES)));
+// }
+//
+// @Test
+// public void save_on_issues_without_changelog() {
+// when(issuable.issues()).thenReturn(newArrayList(
+// (Issue) new DefaultIssue().setKey("A").setCreationDate(nineDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES)),
+// new DefaultIssue().setKey("B").setCreationDate(fiveDaysAgo).setDebt(Duration.create(TWO_DAYS_IN_MINUTES))
+// ));
+//
+// decorator.decorate(resource, context);
+//
+// // remember : period1 is 5daysAgo, period2 is 10daysAgo
+// verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0, 7.0 * ONE_DAY_IN_MINUTES)));
+// }
+//
+// @Test
+// public void save_on_issues_with_changelog_and_issues_without_changelog() {
+// // issue1 and issue2 have changelog
+// Issue issue1 = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES)).setChanges(
+// newArrayList(
+// new FieldDiffs().setDiff("technicalDebt", TWO_DAYS_IN_MINUTES, FIVE_DAYS_IN_MINUTES).setCreationDate(rightNow),
+// new FieldDiffs().setDiff("technicalDebt", ONE_DAY_IN_MINUTES, TWO_DAYS_IN_MINUTES).setCreationDate(fourDaysAgo),
+// new FieldDiffs().setDiff("technicalDebt", null, ONE_DAY_IN_MINUTES).setCreationDate(nineDaysAgo)
+// )
+// );
+// Issue issue2 = new DefaultIssue().setKey("B").setCreationDate(tenDaysAgo).setDebt(Duration.create(TWO_DAYS_IN_MINUTES)).setChanges(
+// newArrayList(
+// new FieldDiffs().setDiff("technicalDebt", ONE_DAY_IN_MINUTES, TWO_DAYS_IN_MINUTES).setCreationDate(rightNow),
+// new FieldDiffs().setDiff("technicalDebt", null, ONE_DAY_IN_MINUTES).setCreationDate(nineDaysAgo)
+// )
+// );
+//
+// // issue3 and issue4 have no changelog
+// Issue issue3 = new DefaultIssue().setKey("C").setCreationDate(nineDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES));
+// Issue issue4 = new DefaultIssue().setKey("D").setCreationDate(fiveDaysAgo).setDebt(Duration.create(TWO_DAYS_IN_MINUTES));
+// when(issuable.issues()).thenReturn(newArrayList(issue1, issue2, issue3, issue4));
+//
+// decorator.decorate(resource, context);
+//
+// // remember : period1 is 5daysAgo, period2 is 10daysAgo
+// verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 5.0 * ONE_DAY_IN_MINUTES, 14.0 * ONE_DAY_IN_MINUTES)));
+// }
+//
+// @Test
+// public void not_save_if_measure_already_computed() {
+// when(context.getMeasure(CoreMetrics.NEW_TECHNICAL_DEBT)).thenReturn(new Measure());
+// when(issuable.issues()).thenReturn(newArrayList(
+// (Issue) new DefaultIssue().setKey("A").setCreationDate(nineDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES)),
+// new DefaultIssue().setKey("B").setCreationDate(fiveDaysAgo).setDebt(Duration.create(TWO_DAYS_IN_MINUTES))
+// ));
+//
+// decorator.decorate(resource, context);
+//
+// verify(context, never()).saveMeasure(argThat(new IsMeasure(CoreMetrics.NEW_TECHNICAL_DEBT)));
+// }
+//
+// /**
+// * SONAR-5059
+// */
+// @Test
+// public void not_return_negative_debt() {
+// Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(Duration.create(ONE_DAY_IN_MINUTES)).setChanges(
+// newArrayList(
+// // changelog created at is null because it has just been created on the current analysis
+// new FieldDiffs().setDiff("technicalDebt", TWO_DAYS_IN_MINUTES, ONE_DAY_IN_MINUTES).setCreationDate(null)
+// )
+// );
+// when(issuable.issues()).thenReturn(newArrayList(issue));
+//
+// decorator.decorate(resource, context);
+//
+// // remember : period1 is 5daysAgo, period2 is 10daysAgo
+// verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0, 0.0)));
+// }
+//
+//
+// class IsVariationMeasure extends ArgumentMatcher<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());
+// }
+// }
+//
+//}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+//package org.sonar.server.computation.issue;
+//
+//import java.util.Date;
+//import org.apache.commons.lang.time.DateUtils;
+//import org.junit.Before;
+//import org.junit.Test;
+//import org.sonar.api.issue.Issue;
+//import org.sonar.api.utils.Duration;
+//import org.sonar.core.issue.DefaultIssue;
+//import org.sonar.core.issue.FieldDiffs;
+//
+//import static com.google.common.collect.Lists.newArrayList;
+//import static org.assertj.core.api.Assertions.assertThat;
+//
+//public class NewDebtCalculatorTest {
+// private static final int HOURS_IN_DAY = 8;
+//
+// IssueChangelogDebtCalculator issueChangelogDebtCalculator;
+//
+// Date rightNow = new Date();
+// Date elevenDaysAgo = DateUtils.addDays(rightNow, -11);
+// Date tenDaysAgo = DateUtils.addDays(rightNow, -10);
+// Date nineDaysAgo = DateUtils.addDays(rightNow, -9);
+// Date fiveDaysAgo = DateUtils.addDays(rightNow, -5);
+// Date fourDaysAgo = DateUtils.addDays(rightNow, -4);
+//
+// long oneDay = 1 * HOURS_IN_DAY * 60 * 60L;
+// long twoDays = 2 * HOURS_IN_DAY * 60 * 60L;
+// long fiveDays = 5 * HOURS_IN_DAY * 60 * 60L;
+//
+// Duration oneDayDebt = Duration.create(oneDay);
+// Duration twoDaysDebt = Duration.create(twoDays);
+// Duration fiveDaysDebt = Duration.create(fiveDays);
+//
+// @Before
+// public void setUp() {
+// issueChangelogDebtCalculator = new IssueChangelogDebtCalculator();
+// }
+//
+// @Test
+// public void calculate_new_technical_debt_with_one_diff_in_changelog() {
+// Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(twoDaysDebt).setChanges(
+// newArrayList(
+// // changelog created at is null because it has just been created on the current analysis
+// new FieldDiffs().setDiff("technicalDebt", oneDay, twoDays).setCreationDate(null)
+// )
+// );
+//
+// assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, rightNow)).isEqualTo(oneDay);
+// assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, fiveDaysAgo)).isEqualTo(oneDay);
+//
+// assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, elevenDaysAgo)).isEqualTo(twoDays);
+// }
+//
+// @Test
+// public void calculate_new_technical_debt_with_many_diffs_in_changelog() {
+// Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(fiveDaysDebt).setChanges(
+// newArrayList(
+// new FieldDiffs().setDiff("technicalDebt", twoDays, fiveDays).setCreationDate(null),
+// new FieldDiffs().setDiff("technicalDebt", oneDay, twoDays).setCreationDate(fourDaysAgo)
+// )
+// );
+//
+// assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, rightNow)).isEqualTo(3 * oneDay);
+// assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, fiveDaysAgo)).isEqualTo(4 * oneDay);
+// assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, elevenDaysAgo)).isEqualTo(5 * oneDay);
+// }
+//
+// @Test
+// public void changelog_can_be_in_wrong_order() {
+// Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(fiveDaysDebt).setChanges(
+// newArrayList(
+// // 3rd
+// new FieldDiffs().setDiff("technicalDebt", null, oneDay).setCreationDate(nineDaysAgo),
+// // 1st
+// new FieldDiffs().setDiff("technicalDebt", twoDays, fiveDays).setCreationDate(rightNow),
+// // 2nd
+// new FieldDiffs().setDiff("technicalDebt", oneDay, twoDays).setCreationDate(fourDaysAgo)
+// )
+// );
+//
+// assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, fiveDaysAgo)).isEqualTo(4 * oneDay);
+// assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, elevenDaysAgo)).isEqualTo(5 * oneDay);
+// }
+//
+// @Test
+// public void calculate_new_technical_debt_with_null_date() {
+// Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(twoDaysDebt).setChanges(
+// newArrayList(
+// new FieldDiffs().setDiff("technicalDebt", oneDay, twoDays).setCreationDate(null)
+// )
+// );
+//
+// assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, null)).isEqualTo(2 * oneDay);
+// }
+//
+// @Test
+// public void calculate_new_technical_debt_when_new_debt_is_null() {
+// Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(null).setChanges(
+// newArrayList(
+// new FieldDiffs().setDiff("technicalDebt", oneDay, null).setCreationDate(null),
+// new FieldDiffs().setDiff("technicalDebt", null, oneDay).setCreationDate(nineDaysAgo)
+// )
+// );
+//
+// assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, rightNow)).isNull();
+// }
+//
+// @Test
+// public void calculate_new_technical_debt_on_issue_without_technical_debt_and_without_changelog() {
+// Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo);
+//
+// assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, rightNow)).isNull();
+// }
+//
+// @Test
+// public void not_return_negative_debt() {
+// Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(oneDayDebt).setChanges(
+// newArrayList(
+// new FieldDiffs().setDiff("technicalDebt", twoDays, oneDay).setCreationDate(null)
+// )
+// );
+//
+// assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, rightNow)).isNull();
+// }
+//
+//}
import com.tngtech.java.junit.dataprovider.DataProvider;
import com.tngtech.java.junit.dataprovider.DataProviderRunner;
import com.tngtech.java.junit.dataprovider.UseDataProvider;
-import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.sonar.api.rule.RuleKey;
import org.sonar.batch.protocol.output.BatchReport;
-import org.sonar.core.rule.RuleDto;
-import org.sonar.server.computation.issue.RuleCache;
import org.sonar.server.computation.metric.Metric;
import org.sonar.server.computation.metric.MetricImpl;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.guava.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
@RunWith(DataProviderRunner.class)
public class BatchMeasureToMeasureTest {
private static final Metric SOME_LEVEL_METRIC = new MetricImpl(42, "level", "name", Metric.MetricType.LEVEL);
private static final String SOME_DATA = "some_data man!";
- private static final String SOME_ALERT_TEXT = "some alert text_be_careFul!";
private static final BatchReport.Measure EMPTY_BATCH_MEASURE = BatchReport.Measure.newBuilder().build();
- private static final RuleKey SOME_RULE_KEY = RuleKey.of("A", "B");
- private static final int SOME_RULE_ID = 9513;
- private static final RuleDto SOME_RULE = new RuleDto().setRuleKey(SOME_RULE_KEY.toString()).setId(SOME_RULE_ID);
- private RuleCache ruleCache = mock(RuleCache.class);
- private BatchMeasureToMeasure underTest = new BatchMeasureToMeasure(ruleCache);
-
- @Before
- public void setUp() throws Exception {
- when(ruleCache.get(SOME_RULE_KEY)).thenReturn(SOME_RULE);
- }
+ private BatchMeasureToMeasure underTest = new BatchMeasureToMeasure();
@Test
public void toMeasure_returns_absent_for_null_argument() {
underTest.toMeasure(null, null);
}
- @Test(expected = IllegalArgumentException.class)
- public void toMeasure_throws_IAE_if_batch_Measure_has_both_ruleKey_and_characteristicId() {
- underTest.toMeasure(BatchReport.Measure.newBuilder().setRuleKey(SOME_RULE_KEY.toString()).setCharactericId(42).build(), SOME_STRING_METRIC);
- }
-
- @Test
- public void toMeasure_maps_characteristicId_if_present() {
- BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder().setCharactericId(42).build();
-
- assertThat(underTest.toMeasure(batchMeasure, SOME_STRING_METRIC).get().getCharacteristicId()).isEqualTo(42);
- }
-
- @Test
- public void toMeasure_maps_ruleKey_if_present() {
- BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder().setRuleKey(SOME_RULE_KEY.toString()).build();
-
- assertThat(underTest.toMeasure(batchMeasure, SOME_STRING_METRIC).get().getRuleId()).isEqualTo(SOME_RULE_ID);
- }
-
@Test
public void toMeasure_returns_no_value_if_dto_has_no_string_value_for_LEVEL_Metric() {
Optional<Measure> measure = underTest.toMeasure(EMPTY_BATCH_MEASURE, SOME_LEVEL_METRIC);
public void toMeasure_for_LEVEL_Metric_maps_QualityGateStatus() {
BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder()
.setStringValue(Measure.Level.OK.name())
- .setAlertStatus(Measure.Level.ERROR.name())
- .setAlertText(SOME_ALERT_TEXT)
.build();
Optional<Measure> measure = underTest.toMeasure(batchMeasure, SOME_LEVEL_METRIC);
assertThat(measure).isPresent();
assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.LEVEL);
assertThat(measure.get().getLevelValue()).isEqualTo(Measure.Level.OK);
- assertThat(measure.get().getQualityGateStatus().getStatus()).isEqualTo(Measure.Level.ERROR);
- assertThat(measure.get().getQualityGateStatus().getText()).isEqualTo(SOME_ALERT_TEXT);
}
@Test
BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder()
.setIntValue(10)
.setStringValue(SOME_DATA)
- .setAlertStatus(Measure.Level.OK.name()).setAlertText(SOME_ALERT_TEXT)
.build();
Optional<Measure> measure = underTest.toMeasure(batchMeasure, SOME_INT_METRIC);
assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.INT);
assertThat(measure.get().getIntValue()).isEqualTo(10);
assertThat(measure.get().getData()).isEqualTo(SOME_DATA);
- assertThat(measure.get().getQualityGateStatus().getStatus()).isEqualTo(Measure.Level.OK);
- assertThat(measure.get().getQualityGateStatus().getText()).isEqualTo(SOME_ALERT_TEXT);
}
@Test
BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder()
.setLongValue(10l)
.setStringValue(SOME_DATA)
- .setAlertStatus(Measure.Level.OK.name()).setAlertText(SOME_ALERT_TEXT)
.build();
Optional<Measure> measure = underTest.toMeasure(batchMeasure, SOME_LONG_METRIC);
assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.LONG);
assertThat(measure.get().getLongValue()).isEqualTo(10);
assertThat(measure.get().getData()).isEqualTo(SOME_DATA);
- assertThat(measure.get().getQualityGateStatus().getStatus()).isEqualTo(Measure.Level.OK);
- assertThat(measure.get().getQualityGateStatus().getText()).isEqualTo(SOME_ALERT_TEXT);
}
@Test
BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder()
.setDoubleValue(10.6395d)
.setStringValue(SOME_DATA)
- .setAlertStatus(Measure.Level.OK.name()).setAlertText(SOME_ALERT_TEXT)
.build();
Optional<Measure> measure = underTest.toMeasure(batchMeasure, SOME_DOUBLE_METRIC);
assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.DOUBLE);
assertThat(measure.get().getDoubleValue()).isEqualTo(10.6d);
assertThat(measure.get().getData()).isEqualTo(SOME_DATA);
- assertThat(measure.get().getQualityGateStatus().getStatus()).isEqualTo(Measure.Level.OK);
- assertThat(measure.get().getQualityGateStatus().getText()).isEqualTo(SOME_ALERT_TEXT);
}
@Test
@Test
public void toMeasure_maps_data_and_alert_properties_in_dto_for_Boolean_metric() {
BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder()
- .setBooleanValue(true).setStringValue(SOME_DATA).setAlertStatus(Measure.Level.OK.name()).setAlertText(SOME_ALERT_TEXT).build();
+ .setBooleanValue(true).setStringValue(SOME_DATA).build();
Optional<Measure> measure = underTest.toMeasure(batchMeasure, SOME_BOOLEAN_METRIC);
assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.BOOLEAN);
assertThat(measure.get().getBooleanValue()).isTrue();
assertThat(measure.get().getData()).isEqualTo(SOME_DATA);
- assertThat(measure.get().getQualityGateStatus().getStatus()).isEqualTo(Measure.Level.OK);
- assertThat(measure.get().getQualityGateStatus().getText()).isEqualTo(SOME_ALERT_TEXT);
}
@Test
public void toMeasure_maps_alert_properties_in_dto_for_String_Metric() {
BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder()
.setStringValue(SOME_DATA)
- .setAlertStatus(Measure.Level.OK.name()).setAlertText(SOME_ALERT_TEXT)
.build();
Optional<Measure> measure = underTest.toMeasure(batchMeasure, SOME_STRING_METRIC);
assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.STRING);
assertThat(measure.get().getStringValue()).isEqualTo(SOME_DATA);
assertThat(measure.get().getData()).isEqualTo(SOME_DATA);
- assertThat(measure.get().getQualityGateStatus().getStatus()).isEqualTo(Measure.Level.OK);
- assertThat(measure.get().getQualityGateStatus().getText()).isEqualTo(SOME_ALERT_TEXT);
}
@DataProvider
import org.sonar.server.computation.component.Component;
import org.sonar.server.computation.component.DumbComponent;
import org.sonar.server.computation.debt.Characteristic;
-import org.sonar.server.computation.issue.RuleCache;
import org.sonar.server.computation.metric.Metric;
import org.sonar.server.computation.metric.MetricImpl;
import org.sonar.server.computation.metric.MetricRepository;
private DbClient dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new MeasureDao(), new SnapshotDao(), new MetricDao(), new ComponentDao());
private MetricRepository metricRepository = mock(MetricRepository.class);
- private RuleCache ruleCache = mock(RuleCache.class);
- private MeasureRepositoryImpl underTest = new MeasureRepositoryImpl(dbClient, reportReader, metricRepository, ruleCache);
+ private MeasureRepositoryImpl underTest = new MeasureRepositoryImpl(dbClient, reportReader, metricRepository);
private DbClient mockedDbClient = mock(DbClient.class);
private BatchReportReader mockBatchReportReader = mock(BatchReportReader.class);
- private MeasureRepositoryImpl underTestWithMock = new MeasureRepositoryImpl(mockedDbClient, mockBatchReportReader, metricRepository, ruleCache);
+ private MeasureRepositoryImpl underTestWithMock = new MeasureRepositoryImpl(mockedDbClient, mockBatchReportReader, metricRepository);
@CheckForNull
private DbSession dbSession;
@Nullable
@Override
public Object[] apply(Measure input) {
- return new Measure[] { input };
+ return new Measure[] {input};
}
}).toArray(Object[].class);
}
fail("An IllegalArgumentException should have been raised");
} catch (IllegalArgumentException e) {
assertThat(e).hasMessage(format(
- "Measure's ValueType (%s) is not consistent with the Measure's ValueType (%s)",
- measure.getValueType(), metricType.getValueType()));
+ "Measure's ValueType (%s) is not consistent with the Measure's ValueType (%s)",
+ measure.getValueType(), metricType.getValueType()));
}
}
}
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
///*
// * SonarQube, open source software quality management tool.
// * Copyright (C) 2008-2014 SonarSource
import org.sonar.core.metric.db.MetricDto;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.DbTester;
-import org.sonar.core.rule.RuleDto;
import org.sonar.core.technicaldebt.db.CharacteristicDao;
-import org.sonar.core.technicaldebt.db.CharacteristicDto;
import org.sonar.server.component.ComponentTesting;
import org.sonar.server.component.db.ComponentDao;
import org.sonar.server.component.db.SnapshotDao;
import org.sonar.server.computation.batch.TreeRootHolderRule;
import org.sonar.server.computation.component.Component;
import org.sonar.server.computation.component.DumbComponent;
-import org.sonar.server.computation.debt.Characteristic;
-import org.sonar.server.computation.issue.RuleCache;
-import org.sonar.server.computation.issue.RuleCacheLoader;
import org.sonar.server.computation.measure.Measure;
import org.sonar.server.computation.measure.MeasureRepository;
import org.sonar.server.computation.measure.MeasureRepositoryImpl;
import org.sonar.server.db.DbClient;
import org.sonar.server.measure.persistence.MeasureDao;
import org.sonar.server.metric.persistence.MetricDao;
-import org.sonar.server.rule.RuleTesting;
import org.sonar.server.rule.db.RuleDao;
import org.sonar.test.DbTests;
metricRepository = new MetricRepositoryImpl(dbClient);
metricRepository.start();
- measureRepository = new MeasureRepositoryImpl(dbClient, reportReader, metricRepository, new RuleCache(new RuleCacheLoader(dbClient)));
+ measureRepository = new MeasureRepositoryImpl(dbClient, reportReader, metricRepository);
sut = new FillMeasuresWithVariationsStep(dbClient, treeRootHolder, periodsHolder, metricRepository, measureRepository);
}
assertThat(measureRepository.getRawMeasure(PROJECT, toMetric(BUILD_BREAKER_METRIC)).get().getVariations().getVariation1()).isEqualTo(-1d);
}
- @Test
- public void set_variation_on_rule_measure() throws Exception {
- SnapshotDto period1ProjectSnapshot = createForProject(PROJECT_DTO);
- dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
-
- RuleDto rule1 = RuleTesting.newXooX1();
- RuleDto rule2 = RuleTesting.newXooX2();
- dbClient.ruleDao().insert(session, rule1, rule2);
-
- dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 60d));
- dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 40d).setRuleId(rule1.getId()));
- dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 20d).setRuleId(rule2.getId()));
- session.commit();
-
- periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
-
- treeRootHolder.setRoot(PROJECT);
-
- measureRepository.add(PROJECT, toMetric(ISSUES_METRIC), Measure.newMeasureBuilder().create(80, null));
- measureRepository.add(PROJECT, toMetric(ISSUES_METRIC), Measure.newMeasureBuilder().forRule(rule1.getId()).create(45, null));
- measureRepository.add(PROJECT, toMetric(ISSUES_METRIC), Measure.newMeasureBuilder().forRule(rule2.getId()).create(35, null));
-
- sut.execute();
-
- assertThat(measureRepository.getRawMeasure(PROJECT, toMetric(ISSUES_METRIC)).get().getVariations().getVariation1()).isEqualTo(20d);
- assertThat(measureRepository.getRawMeasure(PROJECT, toMetric(ISSUES_METRIC), rule1).get().getVariations().getVariation1()).isEqualTo(5d);
- assertThat(measureRepository.getRawMeasure(PROJECT, toMetric(ISSUES_METRIC), rule2).get().getVariations().getVariation1()).isEqualTo(15d);
- }
-
- @Test
- public void set_variation_on_characteristic_measure() throws Exception {
- SnapshotDto period1ProjectSnapshot = createForProject(PROJECT_DTO);
- dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
-
- CharacteristicDto char1 = new CharacteristicDto().setKey("PORTABILITY");
- CharacteristicDto char2 = new CharacteristicDto().setKey("MAINTAINABILITY");
- dbClient.debtCharacteristicDao().insert(session, char1, char2);
-
- dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 60d));
- dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 40d).setCharacteristicId(char1.getId()));
- dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 20d).setCharacteristicId(char2.getId()));
- session.commit();
-
- periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
-
- treeRootHolder.setRoot(PROJECT);
-
- measureRepository.add(PROJECT, toMetric(ISSUES_METRIC), Measure.newMeasureBuilder().create(80, null));
- measureRepository.add(PROJECT, toMetric(ISSUES_METRIC), Measure.newMeasureBuilder().forCharacteristic(char1.getId()).create(45, null));
- measureRepository.add(PROJECT, toMetric(ISSUES_METRIC), Measure.newMeasureBuilder().forCharacteristic(char2.getId()).create(35, null));
-
- sut.execute();
-
- assertThat(measureRepository.getRawMeasure(PROJECT, toMetric(ISSUES_METRIC)).get().getVariations().getVariation1()).isEqualTo(20d);
- assertThat(measureRepository.getRawMeasure(PROJECT, toMetric(ISSUES_METRIC), new Characteristic(char1.getId(), char1.getKey(), null)).get().getVariations().getVariation1())
- .isEqualTo(5d);
- assertThat(measureRepository.getRawMeasure(PROJECT, toMetric(ISSUES_METRIC), new Characteristic(char2.getId(), char2.getKey(), null)).get().getVariations().getVariation1())
- .isEqualTo(15d);
- }
-
@Test
public void read_measure_from_batch() throws Exception {
// Project
public class PersistIssuesStepTest extends BaseStepTest {
+ public static final long NOW = 1400000000000L;
+
@Rule
public TemporaryFolder temp = new TemporaryFolder();
issueCache = new IssueCache(temp.newFile(), System2.INSTANCE);
system2 = mock(System2.class);
- when(system2.now()).thenReturn(1400000000000L);
+ when(system2.now()).thenReturn(NOW);
step = new PersistIssuesStep(dbClient, system2, new UpdateConflictResolver(), new RuleCache(new RuleCacheLoader(dbClient)), issueCache);
}
.setSeverity(Severity.BLOCKER)
.setStatus(Issue.STATUS_CLOSED)
.setResolution(Issue.RESOLUTION_FIXED)
+ .setSelectedAt(NOW)
.setNew(false)
.setChanged(true)
).close();
import org.sonar.server.rule.db.RuleDao;
import org.sonar.test.DbTests;
+import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.api.measures.CoreMetrics.DUPLICATIONS_DATA;
import static org.sonar.api.measures.CoreMetrics.DUPLICATIONS_DATA_KEY;
.setVariationValue3(3.3d)
.setVariationValue4(4.4d)
.setVariationValue5(5.5d)
- .setAlertStatus("WARN")
- .setAlertText("Open issues > 0")
.setDescription("measure-description")
.setMetricKey(STRING_METRIC_KEY)
- .setCharactericId(123456)
.build()));
reportReader.putMeasures(FILE_REF, Arrays.asList(
.setVariationValue3(3.3d)
.setVariationValue4(4.4d)
.setVariationValue5(5.5d)
- .setAlertStatus("ERROR")
- .setAlertText("Blocker issues variation > 0")
.setDescription("measure-description")
.setMetricKey(DOUBLE_METRIC_KEY)
- .setRuleKey(RULE_KEY.toString())
.build()));
sut.execute();
dto = dtos.get(PROJECT_REF);
assertThat(dto.get("snapshotId")).isEqualTo(4L);
assertThat(dto.get("componentId")).isEqualTo(fileDto.getId());
+<<<<<<< HEAD
assertThat(dto.get("metricId")).isEqualTo(2L);
assertThat(dto.get("ruleId")).isEqualTo(rule.getId().longValue());
assertThat(dto.get("characteristicId")).isNull();
assertThat(dto.get("value")).isEqualTo(123.1d);
+=======
+ assertThat(dto.get("metricId")).isEqualTo(doubleMetric.getId().longValue());
+ assertThat(dto.get("value")).isEqualTo(123.123d);
+>>>>>>> SONAR-6588 integrate issues to Compute Engine
assertThat(dto.get("severity")).isNull();
}
issue_creation_date="[null]"
issue_update_date="[null]"
issue_close_date="[null]"
- created_at="1100000000000"
+ created_at="1300000000000"
updated_at="1400000000000"
/>
issue_creation_date="[null]"
issue_update_date="[null]"
issue_close_date="[null]"
- created_at="1100000000000"
- updated_at="1100000000000"
+ created_at="1300000000000"
+ updated_at="1300000000000"
/>
</dataset>
* <code>optional int32 root_component_ref = 4;</code>
*/
int getRootComponentRef();
+
+ /**
+ * <code>repeated string active_rule_key = 5;</code>
+ *
+ * <pre>
+ *Keys of the rules that were enabled in Quality profiles.
+ *A key is a string composed of the repository and the subKey, specific to the repository. Format is
+ *"{repository}:{subKey}", for instance "java:NullDereference".
+ * </pre>
+ */
+ com.google.protobuf.ProtocolStringList
+ getActiveRuleKeyList();
+ /**
+ * <code>repeated string active_rule_key = 5;</code>
+ *
+ * <pre>
+ *Keys of the rules that were enabled in Quality profiles.
+ *A key is a string composed of the repository and the subKey, specific to the repository. Format is
+ *"{repository}:{subKey}", for instance "java:NullDereference".
+ * </pre>
+ */
+ int getActiveRuleKeyCount();
+ /**
+ * <code>repeated string active_rule_key = 5;</code>
+ *
+ * <pre>
+ *Keys of the rules that were enabled in Quality profiles.
+ *A key is a string composed of the repository and the subKey, specific to the repository. Format is
+ *"{repository}:{subKey}", for instance "java:NullDereference".
+ * </pre>
+ */
+ java.lang.String getActiveRuleKey(int index);
+ /**
+ * <code>repeated string active_rule_key = 5;</code>
+ *
+ * <pre>
+ *Keys of the rules that were enabled in Quality profiles.
+ *A key is a string composed of the repository and the subKey, specific to the repository. Format is
+ *"{repository}:{subKey}", for instance "java:NullDereference".
+ * </pre>
+ */
+ com.google.protobuf.ByteString
+ getActiveRuleKeyBytes(int index);
}
/**
* Protobuf type {@code Metadata}
rootComponentRef_ = input.readInt32();
break;
}
+ case 42: {
+ com.google.protobuf.ByteString bs = input.readBytes();
+ if (!((mutable_bitField0_ & 0x00000010) == 0x00000010)) {
+ activeRuleKey_ = new com.google.protobuf.LazyStringArrayList();
+ mutable_bitField0_ |= 0x00000010;
+ }
+ activeRuleKey_.add(bs);
+ break;
+ }
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
throw new com.google.protobuf.InvalidProtocolBufferException(
e.getMessage()).setUnfinishedMessage(this);
} finally {
+ if (((mutable_bitField0_ & 0x00000010) == 0x00000010)) {
+ activeRuleKey_ = activeRuleKey_.getUnmodifiableView();
+ }
this.unknownFields = unknownFields.build();
makeExtensionsImmutable();
}
return rootComponentRef_;
}
+ public static final int ACTIVE_RULE_KEY_FIELD_NUMBER = 5;
+ private com.google.protobuf.LazyStringList activeRuleKey_;
+ /**
+ * <code>repeated string active_rule_key = 5;</code>
+ *
+ * <pre>
+ *Keys of the rules that were enabled in Quality profiles.
+ *A key is a string composed of the repository and the subKey, specific to the repository. Format is
+ *"{repository}:{subKey}", for instance "java:NullDereference".
+ * </pre>
+ */
+ public com.google.protobuf.ProtocolStringList
+ getActiveRuleKeyList() {
+ return activeRuleKey_;
+ }
+ /**
+ * <code>repeated string active_rule_key = 5;</code>
+ *
+ * <pre>
+ *Keys of the rules that were enabled in Quality profiles.
+ *A key is a string composed of the repository and the subKey, specific to the repository. Format is
+ *"{repository}:{subKey}", for instance "java:NullDereference".
+ * </pre>
+ */
+ public int getActiveRuleKeyCount() {
+ return activeRuleKey_.size();
+ }
+ /**
+ * <code>repeated string active_rule_key = 5;</code>
+ *
+ * <pre>
+ *Keys of the rules that were enabled in Quality profiles.
+ *A key is a string composed of the repository and the subKey, specific to the repository. Format is
+ *"{repository}:{subKey}", for instance "java:NullDereference".
+ * </pre>
+ */
+ public java.lang.String getActiveRuleKey(int index) {
+ return activeRuleKey_.get(index);
+ }
+ /**
+ * <code>repeated string active_rule_key = 5;</code>
+ *
+ * <pre>
+ *Keys of the rules that were enabled in Quality profiles.
+ *A key is a string composed of the repository and the subKey, specific to the repository. Format is
+ *"{repository}:{subKey}", for instance "java:NullDereference".
+ * </pre>
+ */
+ public com.google.protobuf.ByteString
+ getActiveRuleKeyBytes(int index) {
+ return activeRuleKey_.getByteString(index);
+ }
+
private void initFields() {
analysisDate_ = 0L;
projectKey_ = "";
branch_ = "";
rootComponentRef_ = 0;
+ activeRuleKey_ = com.google.protobuf.LazyStringArrayList.EMPTY;
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
if (((bitField0_ & 0x00000008) == 0x00000008)) {
output.writeInt32(4, rootComponentRef_);
}
+ for (int i = 0; i < activeRuleKey_.size(); i++) {
+ output.writeBytes(5, activeRuleKey_.getByteString(i));
+ }
getUnknownFields().writeTo(output);
}
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(4, rootComponentRef_);
}
+ {
+ int dataSize = 0;
+ for (int i = 0; i < activeRuleKey_.size(); i++) {
+ dataSize += com.google.protobuf.CodedOutputStream
+ .computeBytesSizeNoTag(activeRuleKey_.getByteString(i));
+ }
+ size += dataSize;
+ size += 1 * getActiveRuleKeyList().size();
+ }
size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size;
return size;
bitField0_ = (bitField0_ & ~0x00000004);
rootComponentRef_ = 0;
bitField0_ = (bitField0_ & ~0x00000008);
+ activeRuleKey_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000010);
return this;
}
to_bitField0_ |= 0x00000008;
}
result.rootComponentRef_ = rootComponentRef_;
+ if (((bitField0_ & 0x00000010) == 0x00000010)) {
+ activeRuleKey_ = activeRuleKey_.getUnmodifiableView();
+ bitField0_ = (bitField0_ & ~0x00000010);
+ }
+ result.activeRuleKey_ = activeRuleKey_;
result.bitField0_ = to_bitField0_;
onBuilt();
return result;
if (other.hasRootComponentRef()) {
setRootComponentRef(other.getRootComponentRef());
}
+ if (!other.activeRuleKey_.isEmpty()) {
+ if (activeRuleKey_.isEmpty()) {
+ activeRuleKey_ = other.activeRuleKey_;
+ bitField0_ = (bitField0_ & ~0x00000010);
+ } else {
+ ensureActiveRuleKeyIsMutable();
+ activeRuleKey_.addAll(other.activeRuleKey_);
+ }
+ onChanged();
+ }
this.mergeUnknownFields(other.getUnknownFields());
return this;
}
return this;
}
+ private com.google.protobuf.LazyStringList activeRuleKey_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ private void ensureActiveRuleKeyIsMutable() {
+ if (!((bitField0_ & 0x00000010) == 0x00000010)) {
+ activeRuleKey_ = new com.google.protobuf.LazyStringArrayList(activeRuleKey_);
+ bitField0_ |= 0x00000010;
+ }
+ }
+ /**
+ * <code>repeated string active_rule_key = 5;</code>
+ *
+ * <pre>
+ *Keys of the rules that were enabled in Quality profiles.
+ *A key is a string composed of the repository and the subKey, specific to the repository. Format is
+ *"{repository}:{subKey}", for instance "java:NullDereference".
+ * </pre>
+ */
+ public com.google.protobuf.ProtocolStringList
+ getActiveRuleKeyList() {
+ return activeRuleKey_.getUnmodifiableView();
+ }
+ /**
+ * <code>repeated string active_rule_key = 5;</code>
+ *
+ * <pre>
+ *Keys of the rules that were enabled in Quality profiles.
+ *A key is a string composed of the repository and the subKey, specific to the repository. Format is
+ *"{repository}:{subKey}", for instance "java:NullDereference".
+ * </pre>
+ */
+ public int getActiveRuleKeyCount() {
+ return activeRuleKey_.size();
+ }
+ /**
+ * <code>repeated string active_rule_key = 5;</code>
+ *
+ * <pre>
+ *Keys of the rules that were enabled in Quality profiles.
+ *A key is a string composed of the repository and the subKey, specific to the repository. Format is
+ *"{repository}:{subKey}", for instance "java:NullDereference".
+ * </pre>
+ */
+ public java.lang.String getActiveRuleKey(int index) {
+ return activeRuleKey_.get(index);
+ }
+ /**
+ * <code>repeated string active_rule_key = 5;</code>
+ *
+ * <pre>
+ *Keys of the rules that were enabled in Quality profiles.
+ *A key is a string composed of the repository and the subKey, specific to the repository. Format is
+ *"{repository}:{subKey}", for instance "java:NullDereference".
+ * </pre>
+ */
+ public com.google.protobuf.ByteString
+ getActiveRuleKeyBytes(int index) {
+ return activeRuleKey_.getByteString(index);
+ }
+ /**
+ * <code>repeated string active_rule_key = 5;</code>
+ *
+ * <pre>
+ *Keys of the rules that were enabled in Quality profiles.
+ *A key is a string composed of the repository and the subKey, specific to the repository. Format is
+ *"{repository}:{subKey}", for instance "java:NullDereference".
+ * </pre>
+ */
+ public Builder setActiveRuleKey(
+ int index, java.lang.String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureActiveRuleKeyIsMutable();
+ activeRuleKey_.set(index, value);
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>repeated string active_rule_key = 5;</code>
+ *
+ * <pre>
+ *Keys of the rules that were enabled in Quality profiles.
+ *A key is a string composed of the repository and the subKey, specific to the repository. Format is
+ *"{repository}:{subKey}", for instance "java:NullDereference".
+ * </pre>
+ */
+ public Builder addActiveRuleKey(
+ java.lang.String value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureActiveRuleKeyIsMutable();
+ activeRuleKey_.add(value);
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>repeated string active_rule_key = 5;</code>
+ *
+ * <pre>
+ *Keys of the rules that were enabled in Quality profiles.
+ *A key is a string composed of the repository and the subKey, specific to the repository. Format is
+ *"{repository}:{subKey}", for instance "java:NullDereference".
+ * </pre>
+ */
+ public Builder addAllActiveRuleKey(
+ java.lang.Iterable<java.lang.String> values) {
+ ensureActiveRuleKeyIsMutable();
+ com.google.protobuf.AbstractMessageLite.Builder.addAll(
+ values, activeRuleKey_);
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>repeated string active_rule_key = 5;</code>
+ *
+ * <pre>
+ *Keys of the rules that were enabled in Quality profiles.
+ *A key is a string composed of the repository and the subKey, specific to the repository. Format is
+ *"{repository}:{subKey}", for instance "java:NullDereference".
+ * </pre>
+ */
+ public Builder clearActiveRuleKey() {
+ activeRuleKey_ = com.google.protobuf.LazyStringArrayList.EMPTY;
+ bitField0_ = (bitField0_ & ~0x00000010);
+ onChanged();
+ return this;
+ }
+ /**
+ * <code>repeated string active_rule_key = 5;</code>
+ *
+ * <pre>
+ *Keys of the rules that were enabled in Quality profiles.
+ *A key is a string composed of the repository and the subKey, specific to the repository. Format is
+ *"{repository}:{subKey}", for instance "java:NullDereference".
+ * </pre>
+ */
+ public Builder addActiveRuleKeyBytes(
+ com.google.protobuf.ByteString value) {
+ if (value == null) {
+ throw new NullPointerException();
+ }
+ ensureActiveRuleKeyIsMutable();
+ activeRuleKey_.add(value);
+ onChanged();
+ return this;
+ }
+
// @@protoc_insertion_point(builder_scope:Metadata)
}
com.google.protobuf.ByteString
getDescriptionBytes();
- /**
- * <code>optional string rule_key = 10;</code>
- */
- boolean hasRuleKey();
- /**
- * <code>optional string rule_key = 10;</code>
- */
- java.lang.String getRuleKey();
- /**
- * <code>optional string rule_key = 10;</code>
- */
- com.google.protobuf.ByteString
- getRuleKeyBytes();
-
- /**
- * <code>optional string alert_status = 12;</code>
- */
- boolean hasAlertStatus();
- /**
- * <code>optional string alert_status = 12;</code>
- */
- java.lang.String getAlertStatus();
- /**
- * <code>optional string alert_status = 12;</code>
- */
- com.google.protobuf.ByteString
- getAlertStatusBytes();
-
- /**
- * <code>optional string alert_text = 13;</code>
- */
- boolean hasAlertText();
- /**
- * <code>optional string alert_text = 13;</code>
- */
- java.lang.String getAlertText();
- /**
- * <code>optional string alert_text = 13;</code>
- */
- com.google.protobuf.ByteString
- getAlertTextBytes();
-
/**
* <code>optional double variation_value_1 = 14;</code>
*/
*/
double getVariationValue5();
- /**
- * <code>optional int32 characteric_id = 19;</code>
- */
- boolean hasCharactericId();
- /**
- * <code>optional int32 characteric_id = 19;</code>
- */
- int getCharactericId();
-
/**
* <code>optional int32 person_id = 20;</code>
*/
description_ = bs;
break;
}
- case 82: {
- com.google.protobuf.ByteString bs = input.readBytes();
- bitField0_ |= 0x00000100;
- ruleKey_ = bs;
- break;
- }
- case 98: {
- com.google.protobuf.ByteString bs = input.readBytes();
- bitField0_ |= 0x00000200;
- alertStatus_ = bs;
- break;
- }
- case 106: {
- com.google.protobuf.ByteString bs = input.readBytes();
- bitField0_ |= 0x00000400;
- alertText_ = bs;
- break;
- }
case 113: {
- bitField0_ |= 0x00000800;
+ bitField0_ |= 0x00000100;
variationValue1_ = input.readDouble();
break;
}
case 121: {
- bitField0_ |= 0x00001000;
+ bitField0_ |= 0x00000200;
variationValue2_ = input.readDouble();
break;
}
case 129: {
- bitField0_ |= 0x00002000;
+ bitField0_ |= 0x00000400;
variationValue3_ = input.readDouble();
break;
}
case 137: {
- bitField0_ |= 0x00004000;
+ bitField0_ |= 0x00000800;
variationValue4_ = input.readDouble();
break;
}
case 145: {
- bitField0_ |= 0x00008000;
+ bitField0_ |= 0x00001000;
variationValue5_ = input.readDouble();
break;
}
- case 152: {
- bitField0_ |= 0x00010000;
- charactericId_ = input.readInt32();
- break;
- }
case 160: {
- bitField0_ |= 0x00020000;
+ bitField0_ |= 0x00002000;
personId_ = input.readInt32();
break;
}
}
}
- public static final int RULE_KEY_FIELD_NUMBER = 10;
- private java.lang.Object ruleKey_;
+ public static final int VARIATION_VALUE_1_FIELD_NUMBER = 14;
+ private double variationValue1_;
/**
- * <code>optional string rule_key = 10;</code>
+ * <code>optional double variation_value_1 = 14;</code>
*/
- public boolean hasRuleKey() {
+ public boolean hasVariationValue1() {
return ((bitField0_ & 0x00000100) == 0x00000100);
}
/**
- * <code>optional string rule_key = 10;</code>
- */
- public java.lang.String getRuleKey() {
- java.lang.Object ref = ruleKey_;
- if (ref instanceof java.lang.String) {
- return (java.lang.String) ref;
- } else {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
- java.lang.String s = bs.toStringUtf8();
- if (bs.isValidUtf8()) {
- ruleKey_ = s;
- }
- return s;
- }
- }
- /**
- * <code>optional string rule_key = 10;</code>
+ * <code>optional double variation_value_1 = 14;</code>
*/
- public com.google.protobuf.ByteString
- getRuleKeyBytes() {
- java.lang.Object ref = ruleKey_;
- if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
- ruleKey_ = b;
- return b;
- } else {
- return (com.google.protobuf.ByteString) ref;
- }
+ public double getVariationValue1() {
+ return variationValue1_;
}
- public static final int ALERT_STATUS_FIELD_NUMBER = 12;
- private java.lang.Object alertStatus_;
+ public static final int VARIATION_VALUE_2_FIELD_NUMBER = 15;
+ private double variationValue2_;
/**
- * <code>optional string alert_status = 12;</code>
+ * <code>optional double variation_value_2 = 15;</code>
*/
- public boolean hasAlertStatus() {
+ public boolean hasVariationValue2() {
return ((bitField0_ & 0x00000200) == 0x00000200);
}
/**
- * <code>optional string alert_status = 12;</code>
- */
- public java.lang.String getAlertStatus() {
- java.lang.Object ref = alertStatus_;
- if (ref instanceof java.lang.String) {
- return (java.lang.String) ref;
- } else {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
- java.lang.String s = bs.toStringUtf8();
- if (bs.isValidUtf8()) {
- alertStatus_ = s;
- }
- return s;
- }
- }
- /**
- * <code>optional string alert_status = 12;</code>
- */
- public com.google.protobuf.ByteString
- getAlertStatusBytes() {
- java.lang.Object ref = alertStatus_;
- if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
- alertStatus_ = b;
- return b;
- } else {
- return (com.google.protobuf.ByteString) ref;
- }
- }
-
- public static final int ALERT_TEXT_FIELD_NUMBER = 13;
- private java.lang.Object alertText_;
- /**
- * <code>optional string alert_text = 13;</code>
- */
- public boolean hasAlertText() {
- return ((bitField0_ & 0x00000400) == 0x00000400);
- }
- /**
- * <code>optional string alert_text = 13;</code>
- */
- public java.lang.String getAlertText() {
- java.lang.Object ref = alertText_;
- if (ref instanceof java.lang.String) {
- return (java.lang.String) ref;
- } else {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
- java.lang.String s = bs.toStringUtf8();
- if (bs.isValidUtf8()) {
- alertText_ = s;
- }
- return s;
- }
- }
- /**
- * <code>optional string alert_text = 13;</code>
- */
- public com.google.protobuf.ByteString
- getAlertTextBytes() {
- java.lang.Object ref = alertText_;
- if (ref instanceof java.lang.String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
- alertText_ = b;
- return b;
- } else {
- return (com.google.protobuf.ByteString) ref;
- }
- }
-
- public static final int VARIATION_VALUE_1_FIELD_NUMBER = 14;
- private double variationValue1_;
- /**
- * <code>optional double variation_value_1 = 14;</code>
- */
- public boolean hasVariationValue1() {
- return ((bitField0_ & 0x00000800) == 0x00000800);
- }
- /**
- * <code>optional double variation_value_1 = 14;</code>
- */
- public double getVariationValue1() {
- return variationValue1_;
- }
-
- public static final int VARIATION_VALUE_2_FIELD_NUMBER = 15;
- private double variationValue2_;
- /**
- * <code>optional double variation_value_2 = 15;</code>
- */
- public boolean hasVariationValue2() {
- return ((bitField0_ & 0x00001000) == 0x00001000);
- }
- /**
- * <code>optional double variation_value_2 = 15;</code>
+ * <code>optional double variation_value_2 = 15;</code>
*/
public double getVariationValue2() {
return variationValue2_;
* <code>optional double variation_value_3 = 16;</code>
*/
public boolean hasVariationValue3() {
- return ((bitField0_ & 0x00002000) == 0x00002000);
+ return ((bitField0_ & 0x00000400) == 0x00000400);
}
/**
* <code>optional double variation_value_3 = 16;</code>
* <code>optional double variation_value_4 = 17;</code>
*/
public boolean hasVariationValue4() {
- return ((bitField0_ & 0x00004000) == 0x00004000);
+ return ((bitField0_ & 0x00000800) == 0x00000800);
}
/**
* <code>optional double variation_value_4 = 17;</code>
* <code>optional double variation_value_5 = 18;</code>
*/
public boolean hasVariationValue5() {
- return ((bitField0_ & 0x00008000) == 0x00008000);
+ return ((bitField0_ & 0x00001000) == 0x00001000);
}
/**
* <code>optional double variation_value_5 = 18;</code>
return variationValue5_;
}
- public static final int CHARACTERIC_ID_FIELD_NUMBER = 19;
- private int charactericId_;
- /**
- * <code>optional int32 characteric_id = 19;</code>
- */
- public boolean hasCharactericId() {
- return ((bitField0_ & 0x00010000) == 0x00010000);
- }
- /**
- * <code>optional int32 characteric_id = 19;</code>
- */
- public int getCharactericId() {
- return charactericId_;
- }
-
public static final int PERSON_ID_FIELD_NUMBER = 20;
private int personId_;
/**
* <code>optional int32 person_id = 20;</code>
*/
public boolean hasPersonId() {
- return ((bitField0_ & 0x00020000) == 0x00020000);
+ return ((bitField0_ & 0x00002000) == 0x00002000);
}
/**
* <code>optional int32 person_id = 20;</code>
stringValue_ = "";
metricKey_ = "";
description_ = "";
- ruleKey_ = "";
- alertStatus_ = "";
- alertText_ = "";
variationValue1_ = 0D;
variationValue2_ = 0D;
variationValue3_ = 0D;
variationValue4_ = 0D;
variationValue5_ = 0D;
- charactericId_ = 0;
personId_ = 0;
}
private byte memoizedIsInitialized = -1;
output.writeBytes(9, getDescriptionBytes());
}
if (((bitField0_ & 0x00000100) == 0x00000100)) {
- output.writeBytes(10, getRuleKeyBytes());
- }
- if (((bitField0_ & 0x00000200) == 0x00000200)) {
- output.writeBytes(12, getAlertStatusBytes());
- }
- if (((bitField0_ & 0x00000400) == 0x00000400)) {
- output.writeBytes(13, getAlertTextBytes());
- }
- if (((bitField0_ & 0x00000800) == 0x00000800)) {
output.writeDouble(14, variationValue1_);
}
- if (((bitField0_ & 0x00001000) == 0x00001000)) {
+ if (((bitField0_ & 0x00000200) == 0x00000200)) {
output.writeDouble(15, variationValue2_);
}
- if (((bitField0_ & 0x00002000) == 0x00002000)) {
+ if (((bitField0_ & 0x00000400) == 0x00000400)) {
output.writeDouble(16, variationValue3_);
}
- if (((bitField0_ & 0x00004000) == 0x00004000)) {
+ if (((bitField0_ & 0x00000800) == 0x00000800)) {
output.writeDouble(17, variationValue4_);
}
- if (((bitField0_ & 0x00008000) == 0x00008000)) {
+ if (((bitField0_ & 0x00001000) == 0x00001000)) {
output.writeDouble(18, variationValue5_);
}
- if (((bitField0_ & 0x00010000) == 0x00010000)) {
- output.writeInt32(19, charactericId_);
- }
- if (((bitField0_ & 0x00020000) == 0x00020000)) {
+ if (((bitField0_ & 0x00002000) == 0x00002000)) {
output.writeInt32(20, personId_);
}
getUnknownFields().writeTo(output);
.computeBytesSize(9, getDescriptionBytes());
}
if (((bitField0_ & 0x00000100) == 0x00000100)) {
- size += com.google.protobuf.CodedOutputStream
- .computeBytesSize(10, getRuleKeyBytes());
- }
- if (((bitField0_ & 0x00000200) == 0x00000200)) {
- size += com.google.protobuf.CodedOutputStream
- .computeBytesSize(12, getAlertStatusBytes());
- }
- if (((bitField0_ & 0x00000400) == 0x00000400)) {
- size += com.google.protobuf.CodedOutputStream
- .computeBytesSize(13, getAlertTextBytes());
- }
- if (((bitField0_ & 0x00000800) == 0x00000800)) {
size += com.google.protobuf.CodedOutputStream
.computeDoubleSize(14, variationValue1_);
}
- if (((bitField0_ & 0x00001000) == 0x00001000)) {
+ if (((bitField0_ & 0x00000200) == 0x00000200)) {
size += com.google.protobuf.CodedOutputStream
.computeDoubleSize(15, variationValue2_);
}
- if (((bitField0_ & 0x00002000) == 0x00002000)) {
+ if (((bitField0_ & 0x00000400) == 0x00000400)) {
size += com.google.protobuf.CodedOutputStream
.computeDoubleSize(16, variationValue3_);
}
- if (((bitField0_ & 0x00004000) == 0x00004000)) {
+ if (((bitField0_ & 0x00000800) == 0x00000800)) {
size += com.google.protobuf.CodedOutputStream
.computeDoubleSize(17, variationValue4_);
}
- if (((bitField0_ & 0x00008000) == 0x00008000)) {
+ if (((bitField0_ & 0x00001000) == 0x00001000)) {
size += com.google.protobuf.CodedOutputStream
.computeDoubleSize(18, variationValue5_);
}
- if (((bitField0_ & 0x00010000) == 0x00010000)) {
- size += com.google.protobuf.CodedOutputStream
- .computeInt32Size(19, charactericId_);
- }
- if (((bitField0_ & 0x00020000) == 0x00020000)) {
+ if (((bitField0_ & 0x00002000) == 0x00002000)) {
size += com.google.protobuf.CodedOutputStream
.computeInt32Size(20, personId_);
}
bitField0_ = (bitField0_ & ~0x00000040);
description_ = "";
bitField0_ = (bitField0_ & ~0x00000080);
- ruleKey_ = "";
- bitField0_ = (bitField0_ & ~0x00000100);
- alertStatus_ = "";
- bitField0_ = (bitField0_ & ~0x00000200);
- alertText_ = "";
- bitField0_ = (bitField0_ & ~0x00000400);
variationValue1_ = 0D;
- bitField0_ = (bitField0_ & ~0x00000800);
+ bitField0_ = (bitField0_ & ~0x00000100);
variationValue2_ = 0D;
- bitField0_ = (bitField0_ & ~0x00001000);
+ bitField0_ = (bitField0_ & ~0x00000200);
variationValue3_ = 0D;
- bitField0_ = (bitField0_ & ~0x00002000);
+ bitField0_ = (bitField0_ & ~0x00000400);
variationValue4_ = 0D;
- bitField0_ = (bitField0_ & ~0x00004000);
+ bitField0_ = (bitField0_ & ~0x00000800);
variationValue5_ = 0D;
- bitField0_ = (bitField0_ & ~0x00008000);
- charactericId_ = 0;
- bitField0_ = (bitField0_ & ~0x00010000);
+ bitField0_ = (bitField0_ & ~0x00001000);
personId_ = 0;
- bitField0_ = (bitField0_ & ~0x00020000);
+ bitField0_ = (bitField0_ & ~0x00002000);
return this;
}
if (((from_bitField0_ & 0x00000100) == 0x00000100)) {
to_bitField0_ |= 0x00000100;
}
- result.ruleKey_ = ruleKey_;
+ result.variationValue1_ = variationValue1_;
if (((from_bitField0_ & 0x00000200) == 0x00000200)) {
to_bitField0_ |= 0x00000200;
}
- result.alertStatus_ = alertStatus_;
+ result.variationValue2_ = variationValue2_;
if (((from_bitField0_ & 0x00000400) == 0x00000400)) {
to_bitField0_ |= 0x00000400;
}
- result.alertText_ = alertText_;
+ result.variationValue3_ = variationValue3_;
if (((from_bitField0_ & 0x00000800) == 0x00000800)) {
to_bitField0_ |= 0x00000800;
}
- result.variationValue1_ = variationValue1_;
+ result.variationValue4_ = variationValue4_;
if (((from_bitField0_ & 0x00001000) == 0x00001000)) {
to_bitField0_ |= 0x00001000;
}
- result.variationValue2_ = variationValue2_;
+ result.variationValue5_ = variationValue5_;
if (((from_bitField0_ & 0x00002000) == 0x00002000)) {
to_bitField0_ |= 0x00002000;
}
- result.variationValue3_ = variationValue3_;
- if (((from_bitField0_ & 0x00004000) == 0x00004000)) {
- to_bitField0_ |= 0x00004000;
- }
- result.variationValue4_ = variationValue4_;
- if (((from_bitField0_ & 0x00008000) == 0x00008000)) {
- to_bitField0_ |= 0x00008000;
- }
- result.variationValue5_ = variationValue5_;
- if (((from_bitField0_ & 0x00010000) == 0x00010000)) {
- to_bitField0_ |= 0x00010000;
- }
- result.charactericId_ = charactericId_;
- if (((from_bitField0_ & 0x00020000) == 0x00020000)) {
- to_bitField0_ |= 0x00020000;
- }
result.personId_ = personId_;
result.bitField0_ = to_bitField0_;
onBuilt();
description_ = other.description_;
onChanged();
}
- if (other.hasRuleKey()) {
- bitField0_ |= 0x00000100;
- ruleKey_ = other.ruleKey_;
- onChanged();
- }
- if (other.hasAlertStatus()) {
- bitField0_ |= 0x00000200;
- alertStatus_ = other.alertStatus_;
- onChanged();
- }
- if (other.hasAlertText()) {
- bitField0_ |= 0x00000400;
- alertText_ = other.alertText_;
- onChanged();
- }
if (other.hasVariationValue1()) {
setVariationValue1(other.getVariationValue1());
}
if (other.hasVariationValue5()) {
setVariationValue5(other.getVariationValue5());
}
- if (other.hasCharactericId()) {
- setCharactericId(other.getCharactericId());
- }
if (other.hasPersonId()) {
setPersonId(other.getPersonId());
}
return this;
}
- private java.lang.Object ruleKey_ = "";
- /**
- * <code>optional string rule_key = 10;</code>
- */
- public boolean hasRuleKey() {
- return ((bitField0_ & 0x00000100) == 0x00000100);
- }
- /**
- * <code>optional string rule_key = 10;</code>
- */
- public java.lang.String getRuleKey() {
- java.lang.Object ref = ruleKey_;
- if (!(ref instanceof java.lang.String)) {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
- java.lang.String s = bs.toStringUtf8();
- if (bs.isValidUtf8()) {
- ruleKey_ = s;
- }
- return s;
- } else {
- return (java.lang.String) ref;
- }
- }
- /**
- * <code>optional string rule_key = 10;</code>
- */
- public com.google.protobuf.ByteString
- getRuleKeyBytes() {
- java.lang.Object ref = ruleKey_;
- if (ref instanceof String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
- ruleKey_ = b;
- return b;
- } else {
- return (com.google.protobuf.ByteString) ref;
- }
- }
- /**
- * <code>optional string rule_key = 10;</code>
- */
- public Builder setRuleKey(
- java.lang.String value) {
- if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000100;
- ruleKey_ = value;
- onChanged();
- return this;
- }
- /**
- * <code>optional string rule_key = 10;</code>
- */
- public Builder clearRuleKey() {
- bitField0_ = (bitField0_ & ~0x00000100);
- ruleKey_ = getDefaultInstance().getRuleKey();
- onChanged();
- return this;
- }
- /**
- * <code>optional string rule_key = 10;</code>
- */
- public Builder setRuleKeyBytes(
- com.google.protobuf.ByteString value) {
- if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000100;
- ruleKey_ = value;
- onChanged();
- return this;
- }
-
- private java.lang.Object alertStatus_ = "";
- /**
- * <code>optional string alert_status = 12;</code>
- */
- public boolean hasAlertStatus() {
- return ((bitField0_ & 0x00000200) == 0x00000200);
- }
- /**
- * <code>optional string alert_status = 12;</code>
- */
- public java.lang.String getAlertStatus() {
- java.lang.Object ref = alertStatus_;
- if (!(ref instanceof java.lang.String)) {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
- java.lang.String s = bs.toStringUtf8();
- if (bs.isValidUtf8()) {
- alertStatus_ = s;
- }
- return s;
- } else {
- return (java.lang.String) ref;
- }
- }
- /**
- * <code>optional string alert_status = 12;</code>
- */
- public com.google.protobuf.ByteString
- getAlertStatusBytes() {
- java.lang.Object ref = alertStatus_;
- if (ref instanceof String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
- alertStatus_ = b;
- return b;
- } else {
- return (com.google.protobuf.ByteString) ref;
- }
- }
- /**
- * <code>optional string alert_status = 12;</code>
- */
- public Builder setAlertStatus(
- java.lang.String value) {
- if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000200;
- alertStatus_ = value;
- onChanged();
- return this;
- }
- /**
- * <code>optional string alert_status = 12;</code>
- */
- public Builder clearAlertStatus() {
- bitField0_ = (bitField0_ & ~0x00000200);
- alertStatus_ = getDefaultInstance().getAlertStatus();
- onChanged();
- return this;
- }
- /**
- * <code>optional string alert_status = 12;</code>
- */
- public Builder setAlertStatusBytes(
- com.google.protobuf.ByteString value) {
- if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000200;
- alertStatus_ = value;
- onChanged();
- return this;
- }
-
- private java.lang.Object alertText_ = "";
- /**
- * <code>optional string alert_text = 13;</code>
- */
- public boolean hasAlertText() {
- return ((bitField0_ & 0x00000400) == 0x00000400);
- }
- /**
- * <code>optional string alert_text = 13;</code>
- */
- public java.lang.String getAlertText() {
- java.lang.Object ref = alertText_;
- if (!(ref instanceof java.lang.String)) {
- com.google.protobuf.ByteString bs =
- (com.google.protobuf.ByteString) ref;
- java.lang.String s = bs.toStringUtf8();
- if (bs.isValidUtf8()) {
- alertText_ = s;
- }
- return s;
- } else {
- return (java.lang.String) ref;
- }
- }
- /**
- * <code>optional string alert_text = 13;</code>
- */
- public com.google.protobuf.ByteString
- getAlertTextBytes() {
- java.lang.Object ref = alertText_;
- if (ref instanceof String) {
- com.google.protobuf.ByteString b =
- com.google.protobuf.ByteString.copyFromUtf8(
- (java.lang.String) ref);
- alertText_ = b;
- return b;
- } else {
- return (com.google.protobuf.ByteString) ref;
- }
- }
- /**
- * <code>optional string alert_text = 13;</code>
- */
- public Builder setAlertText(
- java.lang.String value) {
- if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000400;
- alertText_ = value;
- onChanged();
- return this;
- }
- /**
- * <code>optional string alert_text = 13;</code>
- */
- public Builder clearAlertText() {
- bitField0_ = (bitField0_ & ~0x00000400);
- alertText_ = getDefaultInstance().getAlertText();
- onChanged();
- return this;
- }
- /**
- * <code>optional string alert_text = 13;</code>
- */
- public Builder setAlertTextBytes(
- com.google.protobuf.ByteString value) {
- if (value == null) {
- throw new NullPointerException();
- }
- bitField0_ |= 0x00000400;
- alertText_ = value;
- onChanged();
- return this;
- }
-
private double variationValue1_ ;
/**
* <code>optional double variation_value_1 = 14;</code>
*/
public boolean hasVariationValue1() {
- return ((bitField0_ & 0x00000800) == 0x00000800);
+ return ((bitField0_ & 0x00000100) == 0x00000100);
}
/**
* <code>optional double variation_value_1 = 14;</code>
* <code>optional double variation_value_1 = 14;</code>
*/
public Builder setVariationValue1(double value) {
- bitField0_ |= 0x00000800;
+ bitField0_ |= 0x00000100;
variationValue1_ = value;
onChanged();
return this;
* <code>optional double variation_value_1 = 14;</code>
*/
public Builder clearVariationValue1() {
- bitField0_ = (bitField0_ & ~0x00000800);
+ bitField0_ = (bitField0_ & ~0x00000100);
variationValue1_ = 0D;
onChanged();
return this;
* <code>optional double variation_value_2 = 15;</code>
*/
public boolean hasVariationValue2() {
- return ((bitField0_ & 0x00001000) == 0x00001000);
+ return ((bitField0_ & 0x00000200) == 0x00000200);
}
/**
* <code>optional double variation_value_2 = 15;</code>
* <code>optional double variation_value_2 = 15;</code>
*/
public Builder setVariationValue2(double value) {
- bitField0_ |= 0x00001000;
+ bitField0_ |= 0x00000200;
variationValue2_ = value;
onChanged();
return this;
* <code>optional double variation_value_2 = 15;</code>
*/
public Builder clearVariationValue2() {
- bitField0_ = (bitField0_ & ~0x00001000);
+ bitField0_ = (bitField0_ & ~0x00000200);
variationValue2_ = 0D;
onChanged();
return this;
* <code>optional double variation_value_3 = 16;</code>
*/
public boolean hasVariationValue3() {
- return ((bitField0_ & 0x00002000) == 0x00002000);
+ return ((bitField0_ & 0x00000400) == 0x00000400);
}
/**
* <code>optional double variation_value_3 = 16;</code>
* <code>optional double variation_value_3 = 16;</code>
*/
public Builder setVariationValue3(double value) {
- bitField0_ |= 0x00002000;
+ bitField0_ |= 0x00000400;
variationValue3_ = value;
onChanged();
return this;
* <code>optional double variation_value_3 = 16;</code>
*/
public Builder clearVariationValue3() {
- bitField0_ = (bitField0_ & ~0x00002000);
+ bitField0_ = (bitField0_ & ~0x00000400);
variationValue3_ = 0D;
onChanged();
return this;
* <code>optional double variation_value_4 = 17;</code>
*/
public boolean hasVariationValue4() {
- return ((bitField0_ & 0x00004000) == 0x00004000);
+ return ((bitField0_ & 0x00000800) == 0x00000800);
}
/**
* <code>optional double variation_value_4 = 17;</code>
* <code>optional double variation_value_4 = 17;</code>
*/
public Builder setVariationValue4(double value) {
- bitField0_ |= 0x00004000;
+ bitField0_ |= 0x00000800;
variationValue4_ = value;
onChanged();
return this;
* <code>optional double variation_value_4 = 17;</code>
*/
public Builder clearVariationValue4() {
- bitField0_ = (bitField0_ & ~0x00004000);
+ bitField0_ = (bitField0_ & ~0x00000800);
variationValue4_ = 0D;
onChanged();
return this;
* <code>optional double variation_value_5 = 18;</code>
*/
public boolean hasVariationValue5() {
- return ((bitField0_ & 0x00008000) == 0x00008000);
+ return ((bitField0_ & 0x00001000) == 0x00001000);
}
/**
* <code>optional double variation_value_5 = 18;</code>
* <code>optional double variation_value_5 = 18;</code>
*/
public Builder setVariationValue5(double value) {
- bitField0_ |= 0x00008000;
+ bitField0_ |= 0x00001000;
variationValue5_ = value;
onChanged();
return this;
* <code>optional double variation_value_5 = 18;</code>
*/
public Builder clearVariationValue5() {
- bitField0_ = (bitField0_ & ~0x00008000);
+ bitField0_ = (bitField0_ & ~0x00001000);
variationValue5_ = 0D;
onChanged();
return this;
}
- private int charactericId_ ;
- /**
- * <code>optional int32 characteric_id = 19;</code>
- */
- public boolean hasCharactericId() {
- return ((bitField0_ & 0x00010000) == 0x00010000);
- }
- /**
- * <code>optional int32 characteric_id = 19;</code>
- */
- public int getCharactericId() {
- return charactericId_;
- }
- /**
- * <code>optional int32 characteric_id = 19;</code>
- */
- public Builder setCharactericId(int value) {
- bitField0_ |= 0x00010000;
- charactericId_ = value;
- onChanged();
- return this;
- }
- /**
- * <code>optional int32 characteric_id = 19;</code>
- */
- public Builder clearCharactericId() {
- bitField0_ = (bitField0_ & ~0x00010000);
- charactericId_ = 0;
- onChanged();
- return this;
- }
-
private int personId_ ;
/**
* <code>optional int32 person_id = 20;</code>
*/
public boolean hasPersonId() {
- return ((bitField0_ & 0x00020000) == 0x00020000);
+ return ((bitField0_ & 0x00002000) == 0x00002000);
}
/**
* <code>optional int32 person_id = 20;</code>
* <code>optional int32 person_id = 20;</code>
*/
public Builder setPersonId(int value) {
- bitField0_ |= 0x00020000;
+ bitField0_ |= 0x00002000;
personId_ = value;
onChanged();
return this;
* <code>optional int32 person_id = 20;</code>
*/
public Builder clearPersonId() {
- bitField0_ = (bitField0_ & ~0x00020000);
+ bitField0_ = (bitField0_ & ~0x00002000);
personId_ = 0;
onChanged();
return this;
descriptor;
static {
java.lang.String[] descriptorData = {
- "\n\022batch_report.proto\032\017constants.proto\"b\n" +
+ "\n\022batch_report.proto\032\017constants.proto\"{\n" +
"\010Metadata\022\025\n\ranalysis_date\030\001 \001(\003\022\023\n\013proj" +
"ect_key\030\002 \001(\t\022\016\n\006branch\030\003 \001(\t\022\032\n\022root_co" +
- "mponent_ref\030\004 \001(\005\"?\n\rComponentLink\022 \n\004ty" +
- "pe\030\001 \001(\0162\022.ComponentLinkType\022\014\n\004href\030\002 \001" +
- "(\t\"\354\001\n\tComponent\022\013\n\003ref\030\001 \001(\005\022\014\n\004path\030\002 " +
- "\001(\t\022\014\n\004name\030\003 \001(\t\022\034\n\004type\030\004 \001(\0162\016.Compon" +
- "entType\022\017\n\007is_test\030\005 \001(\010\022\020\n\010language\030\006 \001" +
- "(\t\022\025\n\tchild_ref\030\007 \003(\005B\002\020\001\022\034\n\004link\030\010 \003(\0132" +
- "\016.ComponentLink\022\017\n\007version\030\t \001(\t\022\013\n\003key\030",
- "\n \001(\t\022\r\n\005lines\030\013 \001(\005\022\023\n\013description\030\014 \001(" +
- "\t\"\261\003\n\007Measure\022%\n\nvalue_type\030\001 \001(\0162\021.Meas" +
- "ureValueType\022\025\n\rboolean_value\030\002 \001(\010\022\021\n\ti" +
- "nt_value\030\003 \001(\005\022\022\n\nlong_value\030\004 \001(\003\022\024\n\014do" +
- "uble_value\030\005 \001(\001\022\024\n\014string_value\030\006 \001(\t\022\022" +
- "\n\nmetric_key\030\007 \001(\t\022\023\n\013description\030\t \001(\t\022" +
- "\020\n\010rule_key\030\n \001(\t\022\024\n\014alert_status\030\014 \001(\t\022" +
- "\022\n\nalert_text\030\r \001(\t\022\031\n\021variation_value_1" +
- "\030\016 \001(\001\022\031\n\021variation_value_2\030\017 \001(\001\022\031\n\021var" +
- "iation_value_3\030\020 \001(\001\022\031\n\021variation_value_",
- "4\030\021 \001(\001\022\031\n\021variation_value_5\030\022 \001(\001\022\026\n\016ch" +
- "aracteric_id\030\023 \001(\005\022\021\n\tperson_id\030\024 \001(\005\"<\n" +
- "\010Measures\022\025\n\rcomponent_ref\030\001 \001(\005\022\031\n\007meas" +
- "ure\030\002 \003(\0132\010.Measure\"\273\001\n\005Issue\022\027\n\017rule_re" +
- "pository\030\001 \001(\t\022\020\n\010rule_key\030\002 \001(\t\022\014\n\004line" +
- "\030\003 \001(\005\022\013\n\003msg\030\004 \001(\t\022\033\n\010severity\030\005 \001(\0162\t." +
- "Severity\022\013\n\003tag\030\006 \003(\t\022\025\n\reffort_to_fix\030\007" +
- " \001(\001\022\022\n\nattributes\030\010 \001(\t\022\027\n\017debt_in_minu" +
- "tes\030\t \001(\003\"6\n\006Issues\022\025\n\rcomponent_ref\030\001 \001" +
- "(\005\022\025\n\005issue\030\002 \003(\0132\006.Issue\"\254\001\n\nChangesets",
- "\022\025\n\rcomponent_ref\030\001 \001(\005\022(\n\tchangeset\030\002 \003" +
- "(\0132\025.Changesets.Changeset\022 \n\024changesetIn" +
- "dexByLine\030\003 \003(\005B\002\020\001\032;\n\tChangeset\022\020\n\010revi" +
- "sion\030\001 \001(\t\022\016\n\006author\030\002 \001(\t\022\014\n\004date\030\003 \001(\003" +
- "\"R\n\tDuplicate\022\026\n\016other_file_ref\030\001 \001(\005\022\025\n" +
- "\005range\030\002 \001(\0132\006.Range\022\026\n\016other_file_key\030\003" +
- " \001(\t\"M\n\013Duplication\022\037\n\017origin_position\030\001" +
- " \001(\0132\006.Range\022\035\n\tduplicate\030\002 \003(\0132\n.Duplic" +
- "ate\"H\n\014Duplications\022\025\n\rcomponent_ref\030\001 \001" +
- "(\005\022!\n\013duplication\030\002 \003(\0132\014.Duplication\"W\n",
- "\005Range\022\022\n\nstart_line\030\001 \001(\005\022\020\n\010end_line\030\002" +
- " \001(\005\022\024\n\014start_offset\030\003 \001(\005\022\022\n\nend_offset" +
- "\030\004 \001(\005\"~\n\007Symbols\022\020\n\010file_ref\030\001 \001(\005\022\037\n\006s" +
- "ymbol\030\002 \003(\0132\017.Symbols.Symbol\032@\n\006Symbol\022\033" +
- "\n\013declaration\030\001 \001(\0132\006.Range\022\031\n\treference" +
- "\030\002 \003(\0132\006.Range\"\260\001\n\010Coverage\022\014\n\004line\030\001 \001(" +
- "\005\022\022\n\nconditions\030\002 \001(\005\022\017\n\007ut_hits\030\003 \001(\010\022\017" +
- "\n\007it_hits\030\004 \001(\010\022\035\n\025ut_covered_conditions" +
- "\030\005 \001(\005\022\035\n\025it_covered_conditions\030\006 \001(\005\022\"\n" +
- "\032overall_covered_conditions\030\007 \001(\005\"L\n\022Syn",
- "taxHighlighting\022\025\n\005range\030\001 \001(\0132\006.Range\022\037" +
- "\n\004type\030\002 \001(\0162\021.HighlightingType\"j\n\004Test\022" +
- "\014\n\004name\030\001 \001(\t\022\033\n\006status\030\002 \001(\0162\013.TestStat" +
- "us\022\026\n\016duration_in_ms\030\003 \001(\003\022\022\n\nstacktrace" +
- "\030\004 \001(\t\022\013\n\003msg\030\005 \001(\t\"\221\001\n\016CoverageDetail\022\021" +
- "\n\ttest_name\030\001 \001(\t\0221\n\014covered_file\030\002 \003(\0132" +
- "\033.CoverageDetail.CoveredFile\0329\n\013CoveredF" +
- "ile\022\020\n\010file_ref\030\001 \001(\005\022\030\n\014covered_line\030\002 " +
- "\003(\005B\002\020\001B#\n\037org.sonar.batch.protocol.outp" +
- "utH\001"
+ "mponent_ref\030\004 \001(\005\022\027\n\017active_rule_key\030\005 \003" +
+ "(\t\"?\n\rComponentLink\022 \n\004type\030\001 \001(\0162\022.Comp" +
+ "onentLinkType\022\014\n\004href\030\002 \001(\t\"\354\001\n\tComponen" +
+ "t\022\013\n\003ref\030\001 \001(\005\022\014\n\004path\030\002 \001(\t\022\014\n\004name\030\003 \001" +
+ "(\t\022\034\n\004type\030\004 \001(\0162\016.ComponentType\022\017\n\007is_t" +
+ "est\030\005 \001(\010\022\020\n\010language\030\006 \001(\t\022\025\n\tchild_ref" +
+ "\030\007 \003(\005B\002\020\001\022\034\n\004link\030\010 \003(\0132\016.ComponentLink",
+ "\022\017\n\007version\030\t \001(\t\022\013\n\003key\030\n \001(\t\022\r\n\005lines\030" +
+ "\013 \001(\005\022\023\n\013description\030\014 \001(\t\"\335\002\n\007Measure\022%" +
+ "\n\nvalue_type\030\001 \001(\0162\021.MeasureValueType\022\025\n" +
+ "\rboolean_value\030\002 \001(\010\022\021\n\tint_value\030\003 \001(\005\022" +
+ "\022\n\nlong_value\030\004 \001(\003\022\024\n\014double_value\030\005 \001(" +
+ "\001\022\024\n\014string_value\030\006 \001(\t\022\022\n\nmetric_key\030\007 " +
+ "\001(\t\022\023\n\013description\030\t \001(\t\022\031\n\021variation_va" +
+ "lue_1\030\016 \001(\001\022\031\n\021variation_value_2\030\017 \001(\001\022\031" +
+ "\n\021variation_value_3\030\020 \001(\001\022\031\n\021variation_v" +
+ "alue_4\030\021 \001(\001\022\031\n\021variation_value_5\030\022 \001(\001\022",
+ "\021\n\tperson_id\030\024 \001(\005\"<\n\010Measures\022\025\n\rcompon" +
+ "ent_ref\030\001 \001(\005\022\031\n\007measure\030\002 \003(\0132\010.Measure" +
+ "\"\273\001\n\005Issue\022\027\n\017rule_repository\030\001 \001(\t\022\020\n\010r" +
+ "ule_key\030\002 \001(\t\022\014\n\004line\030\003 \001(\005\022\013\n\003msg\030\004 \001(\t" +
+ "\022\033\n\010severity\030\005 \001(\0162\t.Severity\022\013\n\003tag\030\006 \003" +
+ "(\t\022\025\n\reffort_to_fix\030\007 \001(\001\022\022\n\nattributes\030" +
+ "\010 \001(\t\022\027\n\017debt_in_minutes\030\t \001(\003\"6\n\006Issues" +
+ "\022\025\n\rcomponent_ref\030\001 \001(\005\022\025\n\005issue\030\002 \003(\0132\006" +
+ ".Issue\"\254\001\n\nChangesets\022\025\n\rcomponent_ref\030\001" +
+ " \001(\005\022(\n\tchangeset\030\002 \003(\0132\025.Changesets.Cha",
+ "ngeset\022 \n\024changesetIndexByLine\030\003 \003(\005B\002\020\001" +
+ "\032;\n\tChangeset\022\020\n\010revision\030\001 \001(\t\022\016\n\006autho" +
+ "r\030\002 \001(\t\022\014\n\004date\030\003 \001(\003\"R\n\tDuplicate\022\026\n\016ot" +
+ "her_file_ref\030\001 \001(\005\022\025\n\005range\030\002 \001(\0132\006.Rang" +
+ "e\022\026\n\016other_file_key\030\003 \001(\t\"M\n\013Duplication" +
+ "\022\037\n\017origin_position\030\001 \001(\0132\006.Range\022\035\n\tdup" +
+ "licate\030\002 \003(\0132\n.Duplicate\"H\n\014Duplications" +
+ "\022\025\n\rcomponent_ref\030\001 \001(\005\022!\n\013duplication\030\002" +
+ " \003(\0132\014.Duplication\"W\n\005Range\022\022\n\nstart_lin" +
+ "e\030\001 \001(\005\022\020\n\010end_line\030\002 \001(\005\022\024\n\014start_offse",
+ "t\030\003 \001(\005\022\022\n\nend_offset\030\004 \001(\005\"~\n\007Symbols\022\020" +
+ "\n\010file_ref\030\001 \001(\005\022\037\n\006symbol\030\002 \003(\0132\017.Symbo" +
+ "ls.Symbol\032@\n\006Symbol\022\033\n\013declaration\030\001 \001(\013" +
+ "2\006.Range\022\031\n\treference\030\002 \003(\0132\006.Range\"\260\001\n\010" +
+ "Coverage\022\014\n\004line\030\001 \001(\005\022\022\n\nconditions\030\002 \001" +
+ "(\005\022\017\n\007ut_hits\030\003 \001(\010\022\017\n\007it_hits\030\004 \001(\010\022\035\n\025" +
+ "ut_covered_conditions\030\005 \001(\005\022\035\n\025it_covere" +
+ "d_conditions\030\006 \001(\005\022\"\n\032overall_covered_co" +
+ "nditions\030\007 \001(\005\"L\n\022SyntaxHighlighting\022\025\n\005" +
+ "range\030\001 \001(\0132\006.Range\022\037\n\004type\030\002 \001(\0162\021.High",
+ "lightingType\"j\n\004Test\022\014\n\004name\030\001 \001(\t\022\033\n\006st" +
+ "atus\030\002 \001(\0162\013.TestStatus\022\026\n\016duration_in_m" +
+ "s\030\003 \001(\003\022\022\n\nstacktrace\030\004 \001(\t\022\013\n\003msg\030\005 \001(\t" +
+ "\"\221\001\n\016CoverageDetail\022\021\n\ttest_name\030\001 \001(\t\0221" +
+ "\n\014covered_file\030\002 \003(\0132\033.CoverageDetail.Co" +
+ "veredFile\0329\n\013CoveredFile\022\020\n\010file_ref\030\001 \001" +
+ "(\005\022\030\n\014covered_line\030\002 \003(\005B\002\020\001B#\n\037org.sona" +
+ "r.batch.protocol.outputH\001"
};
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() {
internal_static_Metadata_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_Metadata_descriptor,
- new java.lang.String[] { "AnalysisDate", "ProjectKey", "Branch", "RootComponentRef", });
+ new java.lang.String[] { "AnalysisDate", "ProjectKey", "Branch", "RootComponentRef", "ActiveRuleKey", });
internal_static_ComponentLink_descriptor =
getDescriptor().getMessageTypes().get(1);
internal_static_ComponentLink_fieldAccessorTable = new
internal_static_Measure_fieldAccessorTable = new
com.google.protobuf.GeneratedMessage.FieldAccessorTable(
internal_static_Measure_descriptor,
- new java.lang.String[] { "ValueType", "BooleanValue", "IntValue", "LongValue", "DoubleValue", "StringValue", "MetricKey", "Description", "RuleKey", "AlertStatus", "AlertText", "VariationValue1", "VariationValue2", "VariationValue3", "VariationValue4", "VariationValue5", "CharactericId", "PersonId", });
+ new java.lang.String[] { "ValueType", "BooleanValue", "IntValue", "LongValue", "DoubleValue", "StringValue", "MetricKey", "Description", "VariationValue1", "VariationValue2", "VariationValue3", "VariationValue4", "VariationValue5", "PersonId", });
internal_static_Measures_descriptor =
getDescriptor().getMessageTypes().get(4);
internal_static_Measures_fieldAccessorTable = new
optional string project_key = 2;
optional string branch = 3;
optional int32 root_component_ref = 4;
+
+ /*
+ Keys of the rules that were enabled in Quality profiles.
+ A key is a string composed of the repository and the subKey, specific to the repository. Format is
+ "{repository}:{subKey}", for instance "java:NullDereference".
+ */
+ repeated string active_rule_key = 5;
}
message ComponentLink {
// temporary fields during development of computation stack
optional string description = 9;
- optional string rule_key = 10;
- optional string alert_status = 12;
- optional string alert_text = 13;
optional double variation_value_1 = 14;
optional double variation_value_2 = 15;
optional double variation_value_3 = 16;
optional double variation_value_4 = 17;
optional double variation_value_5 = 18;
- optional int32 characteric_id = 19;
optional int32 person_id = 20;
}
import org.sonar.batch.compute.OverallLineCoverageDecorator;
import org.sonar.batch.compute.UnitTestDecorator;
import org.sonar.batch.cpd.CpdComponents;
-import org.sonar.batch.debt.IssueChangelogDebtCalculator;
-import org.sonar.batch.debt.NewDebtDecorator;
import org.sonar.batch.issue.tracking.IssueTracking;
import org.sonar.batch.language.LanguageDistributionDecorator;
import org.sonar.batch.scan.report.ConsoleReport;
// language
LanguageDistributionDecorator.class,
- // Debt
- IssueChangelogDebtCalculator.class,
- NewDebtDecorator.class,
-
// to be moved to compute engine
UnitTestDecorator.class,
LineCoverageDecorator.class,
+++ /dev/null
-/*
- * 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());
- }
-
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.batch.debt;
-
-import com.google.common.base.Function;
-import com.google.common.collect.Ordering;
-import java.util.Calendar;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.apache.commons.lang.time.DateUtils;
-import org.sonar.api.batch.BatchSide;
-import org.sonar.api.issue.Issue;
-import org.sonar.core.issue.DefaultIssue;
-import org.sonar.core.issue.FieldDiffs;
-import org.sonar.core.issue.IssueUpdater;
-
-import static com.google.common.collect.Lists.newArrayList;
-
-/**
- * Warning, before modifying this class, please do not forget that it's used by the Dev Cockpit plugin
- */
-@BatchSide
-public class IssueChangelogDebtCalculator {
-
- @CheckForNull
- public Long calculateNewTechnicalDebt(Issue issue, @Nullable Date periodDate) {
- Long debt = ((DefaultIssue) issue).debtInMinutes();
- Date periodDatePlusOneSecond = periodDate != null ? DateUtils.addSeconds(periodDate, 1) : null;
- if (isAfter(issue.creationDate(), periodDatePlusOneSecond)) {
- return debt;
- } else {
- return calculateNewTechnicalDebtValueFromChangelog(debt, issue, periodDate);
- }
- }
-
- @CheckForNull
- private Long calculateNewTechnicalDebtValueFromChangelog(@Nullable Long currentTechnicalDebtValue, Issue issue, Date periodDate) {
- List<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));
- }
-
-}
+++ /dev/null
-/*
- * 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;
- }
-
-}
import org.sonar.api.batch.rule.Rule;
import org.sonar.api.batch.rule.Rules;
import org.sonar.api.batch.rule.internal.DefaultActiveRule;
-import org.sonar.core.issue.DefaultIssue;
import org.sonar.api.resources.Project;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rules.Violation;
import org.sonar.api.utils.Duration;
import org.sonar.api.utils.MessageException;
+import org.sonar.core.issue.DefaultIssue;
import org.sonar.core.issue.DefaultIssueBuilder;
/**
}
if (rule != null) {
DebtRemediationFunction function = rule.debtRemediationFunction();
- if (rule.debtSubCharacteristic() != null && function != null) {
+ if (function != null) {
issue.setDebt(calculateDebt(function, issue.effortToFix(), rule.key()));
}
}
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;
}
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.resources.Project;
import org.sonar.api.utils.KeyValueFormat;
import org.sonar.batch.index.BatchComponent;
import org.sonar.batch.index.BatchComponentCache;
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
}
}));
}
-
- exportMetadata(writer);
- }
-
- private void exportMetadata(BatchReportWriter writer) {
- ProjectDefinition root = reactor.getRoot();
- BatchComponent rootProject = componentCache.getRoot();
- BatchReport.Metadata.Builder builder = BatchReport.Metadata.newBuilder()
- .setAnalysisDate(((Project) rootProject.resource()).getAnalysisDate().getTime())
- // Here we want key without branch
- .setProjectKey(root.getKey())
- .setRootComponentRef(rootProject.batchId());
- String branch = root.properties().get(CoreProperties.PROJECT_BRANCH_PROPERTY);
- if (branch != null) {
- builder.setBranch(branch);
- }
- writer.writeMetadata(builder.build());
}
private BatchReport.Issue toReportIssue(BatchReport.Issue.Builder builder, DefaultIssue issue) {
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;
if (description != null) {
builder.setDescription(description);
}
- Level alertStatus = measure.getAlertStatus();
- if (alertStatus != null) {
- builder.setAlertStatus(alertStatus.toString());
- }
- String alertText = measure.getAlertText();
- if (alertText != null) {
- builder.setAlertText(alertText);
- }
Double variation1 = measure.getVariation1();
if (variation1 != null) {
builder.setVariationValue1(variation1);
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);
--- /dev/null
+/*
+ * 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();
+ }
+ }
+}
+++ /dev/null
-/*
- * 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));
- }
-
-}
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;
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;
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 {
InputPathCache.class,
PathResolver.class,
- // rules
+ // rules
new ActiveRulesProvider(),
- // issues
+ // issues
IssueUpdater.class,
FunctionExecutor.class,
IssueWorkflow.class,
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,
SourcePublisher.class,
TestExecutionAndCoveragePublisher.class,
- ScanTaskObservers.class);
+ ScanTaskObservers.class);
}
private void addDataBaseComponents() {
- add(
- PastMeasuresLoader.class,
-
- // Rules
- new RulesProvider(),
- new DebtModelProvider(),
-
- // technical debt
- DefaultTechnicalDebtModel.class);
+ add(PastMeasuresLoader.class);
}
private void addBatchExtensions() {
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;
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");
}
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();
}
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
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();
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;
+++ /dev/null
-///*
-// * SonarQube, open source software quality management tool.
-// * Copyright (C) 2008-2014 SonarSource
-// * mailto:contact AT sonarsource DOT com
-// *
-// * SonarQube is free software; you can redistribute it and/or
-// * modify it under the terms of the GNU Lesser General Public
-// * License as published by the Free Software Foundation; either
-// * version 3 of the License, or (at your option) any later version.
-// *
-// * SonarQube is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// * Lesser General Public License for more details.
-// *
-// * You should have received a copy of the GNU Lesser General Public License
-// * along with this program; if not, write to the Free Software Foundation,
-// * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-// */
-//
-//package org.sonar.batch.debt;
-//
-//import com.google.common.collect.Lists;
-//import org.apache.commons.lang.ObjectUtils;
-//import org.apache.commons.lang.builder.ToStringBuilder;
-//import org.apache.commons.lang.builder.ToStringStyle;
-//import org.hamcrest.Description;
-//import org.junit.Before;
-//import org.junit.Test;
-//import org.junit.runner.RunWith;
-//import org.mockito.ArgumentMatcher;
-//import org.mockito.Mock;
-//import org.mockito.runners.MockitoJUnitRunner;
-//import org.sonar.api.batch.DecoratorContext;
-//import org.sonar.api.batch.rule.Rules;
-//import org.sonar.api.batch.rule.internal.RulesBuilder;
-//import org.sonar.api.component.ResourcePerspectives;
-//import org.sonar.api.issue.Issuable;
-//import org.sonar.api.issue.Issue;
-//import org.sonar.core.issue.DefaultIssue;
-//import org.sonar.api.measures.CoreMetrics;
-//import org.sonar.api.measures.Measure;
-//import org.sonar.api.measures.MeasuresFilter;
-//import org.sonar.api.measures.Metric;
-//import org.sonar.api.measures.RuleMeasure;
-//import org.sonar.api.resources.File;
-//import org.sonar.api.resources.Project;
-//import org.sonar.api.resources.Resource;
-//import org.sonar.api.rule.RuleKey;
-//import org.sonar.api.rules.RuleFinder;
-//import org.sonar.api.technicaldebt.batch.Characteristic;
-//import org.sonar.api.technicaldebt.batch.TechnicalDebtModel;
-//import org.sonar.api.technicaldebt.batch.internal.DefaultCharacteristic;
-//import org.sonar.api.test.IsMeasure;
-//import org.sonar.api.utils.Duration;
-//
-//import java.util.Collections;
-//
-//import static com.google.common.collect.Lists.newArrayList;
-//import static org.assertj.core.api.Assertions.assertThat;
-//import static org.mockito.Matchers.any;
-//import static org.mockito.Matchers.argThat;
-//import static org.mockito.Mockito.mock;
-//import static org.mockito.Mockito.never;
-//import static org.mockito.Mockito.times;
-//import static org.mockito.Mockito.verify;
-//import static org.mockito.Mockito.when;
-//
-//@RunWith(MockitoJUnitRunner.class)
-//public class DebtDecoratorTest {
-//
-// static final int HOURS_IN_DAY = 8;
-//
-// static final Long ONE_DAY_IN_MINUTES = 1L * HOURS_IN_DAY * 60;
-//
-// @Mock
-// DecoratorContext context;
-//
-// @Mock
-// Resource resource;
-//
-// @Mock
-// TechnicalDebtModel debtModel;
-//
-// @Mock
-// Issuable issuable;
-//
-// @Mock
-// ResourcePerspectives perspectives;
-//
-// @Mock
-// RuleFinder ruleFinder;
-//
-// RuleKey ruleKey1 = RuleKey.of("repo1", "rule1");
-// RuleKey ruleKey2 = RuleKey.of("repo2", "rule2");
-// Rules rules;
-//
-// DefaultCharacteristic efficiency = new DefaultCharacteristic().setKey("EFFICIENCY");
-// DefaultCharacteristic memoryEfficiency = new DefaultCharacteristic().setKey("MEMORY_EFFICIENCY").setParent(efficiency);
-//
-// DefaultCharacteristic reusability = new DefaultCharacteristic().setKey("REUSABILITY");
-// DefaultCharacteristic modularity = new DefaultCharacteristic().setKey("MODULARITY").setParent(reusability);
-//
-// DebtDecorator decorator;
-//
-// @Before
-// public void before() {
-// when(perspectives.as(Issuable.class, resource)).thenReturn(issuable);
-// RulesBuilder rulesBuilder = new RulesBuilder();
-// rulesBuilder.add(ruleKey1).setName("rule1").setDebtSubCharacteristic("MEMORY_EFFICIENCY");
-// rulesBuilder.add(ruleKey2).setName("rule2").setDebtSubCharacteristic("MODULARITY");
-// rules = rulesBuilder.build();
-//
-// when(ruleFinder.findByKey(ruleKey1)).thenReturn(org.sonar.api.rules.Rule.create(ruleKey1.repository(), ruleKey1.rule()));
-// when(ruleFinder.findByKey(ruleKey2)).thenReturn(org.sonar.api.rules.Rule.create(ruleKey2.repository(), ruleKey2.rule()));
-//
-// when(debtModel.characteristics()).thenReturn(newArrayList(efficiency, memoryEfficiency, reusability, modularity));
-// when(debtModel.characteristicByKey("EFFICIENCY")).thenReturn(efficiency);
-// when(debtModel.characteristicByKey("MEMORY_EFFICIENCY")).thenReturn(memoryEfficiency);
-// when(debtModel.characteristicByKey("REUSABILITY")).thenReturn(reusability);
-// when(debtModel.characteristicByKey("MODULARITY")).thenReturn(modularity);
-//
-// decorator = new DebtDecorator(perspectives, debtModel, rules, ruleFinder);
-// }
-//
-// @Test
-// public void generates_metrics() {
-// assertThat(decorator.generatesMetrics()).hasSize(1);
-// }
-//
-// @Test
-// public void execute_on_project() {
-// assertThat(decorator.shouldExecuteOnProject(null)).isTrue();
-// }
-//
-// @Test
-// public void not_save_if_measure_already_computed() {
-// when(context.getMeasure(CoreMetrics.TECHNICAL_DEBT)).thenReturn(new Measure());
-//
-// decorator.decorate(resource, context);
-//
-// verify(context, never()).saveMeasure(argThat(new IsMeasure(CoreMetrics.TECHNICAL_DEBT)));
-// }
-//
-// @Test
-// public void add_technical_debt_from_one_issue_and_no_parent() {
-// Issue issue = createIssue("rule1", "repo1").setDebt(Duration.create(ONE_DAY_IN_MINUTES));
-// when(issuable.issues()).thenReturn(newArrayList(issue));
-//
-// decorator.decorate(resource, context);
-//
-// verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, ONE_DAY_IN_MINUTES.doubleValue());
-// verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, ONE_DAY_IN_MINUTES.doubleValue())));
-// }
-//
-// @Test
-// public void add_technical_debt_from_one_issue_without_debt() {
-// Issue issue = createIssue("rule1", "repo1").setDebt(null);
-// when(issuable.issues()).thenReturn(newArrayList(issue));
-//
-// decorator.decorate(resource, context);
-//
-// verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, 0.0);
-// }
-//
-// @Test
-// public void add_technical_debt_from_one_issue_and_propagate_to_parents() {
-// Issue issue = createIssue("rule1", "repo1").setDebt(Duration.create(ONE_DAY_IN_MINUTES));
-// when(issuable.issues()).thenReturn(newArrayList(issue));
-//
-// decorator.decorate(resource, context);
-//
-// verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, ONE_DAY_IN_MINUTES.doubleValue());
-// verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, ONE_DAY_IN_MINUTES.doubleValue())));
-// verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, efficiency, ONE_DAY_IN_MINUTES.doubleValue())));
-// verify(context).saveMeasure(argThat(new IsCharacteristicMeasure(CoreMetrics.TECHNICAL_DEBT, memoryEfficiency, ONE_DAY_IN_MINUTES.doubleValue())));
-// }
-//
-// @Test
-// public void add_technical_debt_from_issues() {
-// Long technicalDebt1 = ONE_DAY_IN_MINUTES;
-// Long technicalDebt2 = 2 * ONE_DAY_IN_MINUTES;
-//
-// Issue issue1 = createIssue("rule1", "repo1").setDebt(Duration.create(technicalDebt1));
-// Issue issue2 = createIssue("rule1", "repo1").setDebt(Duration.create(technicalDebt1));
-// Issue issue3 = createIssue("rule2", "repo2").setDebt(Duration.create(technicalDebt2));
-// Issue issue4 = createIssue("rule2", "repo2").setDebt(Duration.create(technicalDebt2));
-// when(issuable.issues()).thenReturn(newArrayList(issue1, issue2, issue3, issue4));
-//
-// decorator.decorate(resource, context);
-//
-// verify(context).saveMeasure(CoreMetrics.TECHNICAL_DEBT, 6d * ONE_DAY_IN_MINUTES);
-// verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey1, 2d * ONE_DAY_IN_MINUTES)));
-// verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.TECHNICAL_DEBT, ruleKey2, 4d * ONE_DAY_IN_MINUTES)));
-// }
-//
-// @Test
-// public void add_technical_debt_from_current_and_children_measures() {
-// Issue issue1 = createIssue("rule1", "repo1").setDebt(Duration.create(ONE_DAY_IN_MINUTES));
-// Issue issue2 = createIssue("rule1", "repo1").setDebt(Duration.create(ONE_DAY_IN_MINUTES));
-// when(issuable.issues()).thenReturn(newArrayList(issue1, issue2));
-//
-// when(context.getChildrenMeasures(any(MeasuresFilter.class))).thenReturn(Lists.<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));
-// }
-// }
-//}
+++ /dev/null
-/*
- * 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();
- }
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.batch.debt;
-
-import org.apache.commons.lang.time.DateUtils;
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.api.issue.Issue;
-import org.sonar.core.issue.DefaultIssue;
-import org.sonar.core.issue.FieldDiffs;
-import org.sonar.api.utils.Duration;
-
-import java.util.Date;
-
-import static com.google.common.collect.Lists.newArrayList;
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class IssueChangelogDebtCalculatorTest {
-
- private static final int HOURS_IN_DAY = 8;
-
- IssueChangelogDebtCalculator issueChangelogDebtCalculator;
-
- Date rightNow = new Date();
- Date elevenDaysAgo = DateUtils.addDays(rightNow, -11);
- Date tenDaysAgo = DateUtils.addDays(rightNow, -10);
- Date nineDaysAgo = DateUtils.addDays(rightNow, -9);
- Date fiveDaysAgo = DateUtils.addDays(rightNow, -5);
- Date fourDaysAgo = DateUtils.addDays(rightNow, -4);
-
- long oneDay = 1 * HOURS_IN_DAY * 60 * 60L;
- long twoDays = 2 * HOURS_IN_DAY * 60 * 60L;
- long fiveDays = 5 * HOURS_IN_DAY * 60 * 60L;
-
- Duration oneDayDebt = Duration.create(oneDay);
- Duration twoDaysDebt = Duration.create(twoDays);
- Duration fiveDaysDebt = Duration.create(fiveDays);
-
- @Before
- public void setUp() {
- issueChangelogDebtCalculator = new IssueChangelogDebtCalculator();
- }
-
- @Test
- public void calculate_new_technical_debt_with_one_diff_in_changelog() {
- Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(twoDaysDebt).setChanges(
- newArrayList(
- // changelog created at is null because it has just been created on the current analysis
- new FieldDiffs().setDiff("technicalDebt", oneDay, twoDays).setCreationDate(null)
- )
- );
-
- assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, rightNow)).isEqualTo(oneDay);
- assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, fiveDaysAgo)).isEqualTo(oneDay);
-
- assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, elevenDaysAgo)).isEqualTo(twoDays);
- }
-
- @Test
- public void calculate_new_technical_debt_with_many_diffs_in_changelog() {
- Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(fiveDaysDebt).setChanges(
- newArrayList(
- new FieldDiffs().setDiff("technicalDebt", twoDays, fiveDays).setCreationDate(null),
- new FieldDiffs().setDiff("technicalDebt", oneDay, twoDays).setCreationDate(fourDaysAgo)
- )
- );
-
- assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, rightNow)).isEqualTo(3 * oneDay);
- assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, fiveDaysAgo)).isEqualTo(4 * oneDay);
- assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, elevenDaysAgo)).isEqualTo(5 * oneDay);
- }
-
- @Test
- public void changelog_can_be_in_wrong_order() {
- Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(fiveDaysDebt).setChanges(
- newArrayList(
- // 3rd
- new FieldDiffs().setDiff("technicalDebt", null, oneDay).setCreationDate(nineDaysAgo),
- // 1st
- new FieldDiffs().setDiff("technicalDebt", twoDays, fiveDays).setCreationDate(rightNow),
- // 2nd
- new FieldDiffs().setDiff("technicalDebt", oneDay, twoDays).setCreationDate(fourDaysAgo)
- )
- );
-
- assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, fiveDaysAgo)).isEqualTo(4 * oneDay);
- assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, elevenDaysAgo)).isEqualTo(5 * oneDay);
- }
-
- @Test
- public void calculate_new_technical_debt_with_null_date() {
- Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(twoDaysDebt).setChanges(
- newArrayList(
- new FieldDiffs().setDiff("technicalDebt", oneDay, twoDays).setCreationDate(null)
- )
- );
-
- assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, null)).isEqualTo(2 * oneDay);
- }
-
- @Test
- public void calculate_new_technical_debt_when_new_debt_is_null() {
- Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(null).setChanges(
- newArrayList(
- new FieldDiffs().setDiff("technicalDebt", oneDay, null).setCreationDate(null),
- new FieldDiffs().setDiff("technicalDebt", null, oneDay).setCreationDate(nineDaysAgo)
- )
- );
-
- assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, rightNow)).isNull();
- }
-
- @Test
- public void calculate_new_technical_debt_on_issue_without_technical_debt_and_without_changelog() {
- Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo);
-
- assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, rightNow)).isNull();
- }
-
- @Test
- public void not_return_negative_debt() {
- Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(oneDayDebt).setChanges(
- newArrayList(
- new FieldDiffs().setDiff("technicalDebt", twoDays, oneDay).setCreationDate(null)
- )
- );
-
- assertThat(issueChangelogDebtCalculator.calculateNewTechnicalDebt(issue, rightNow)).isNull();
- }
-
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.batch.debt;
-
-import org.apache.commons.lang.ObjectUtils;
-import org.apache.commons.lang.time.DateUtils;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentMatcher;
-import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.batch.DecoratorContext;
-import org.sonar.api.component.ResourcePerspectives;
-import org.sonar.api.config.Settings;
-import org.sonar.api.issue.Issuable;
-import org.sonar.api.issue.Issue;
-import org.sonar.core.issue.DefaultIssue;
-import org.sonar.core.issue.FieldDiffs;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.resources.Resource;
-import org.sonar.api.test.IsMeasure;
-import org.sonar.api.utils.Duration;
-import org.sonar.batch.components.Period;
-import org.sonar.batch.components.TimeMachineConfiguration;
-
-import java.util.Date;
-
-import static com.google.common.collect.Lists.newArrayList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-@RunWith(MockitoJUnitRunner.class)
-public class NewDebtDecoratorTest {
-
- NewDebtDecorator decorator;
-
- @Mock
- TimeMachineConfiguration timeMachineConfiguration;
-
- @Mock
- Resource resource;
-
- @Mock
- Issuable issuable;
-
- @Mock
- DecoratorContext context;
-
- Date rightNow;
- Date elevenDaysAgo;
- Date tenDaysAgo;
- Date nineDaysAgo;
- Date fiveDaysAgo;
- Date fourDaysAgo;
-
- static final int HOURS_IN_DAY = 8;
-
- static final Long ONE_DAY_IN_MINUTES = 1L * HOURS_IN_DAY * 60;
- static final Long TWO_DAYS_IN_MINUTES = 2L * HOURS_IN_DAY * 60;
- static final Long FIVE_DAYS_IN_MINUTES = 5L * HOURS_IN_DAY * 60;
-
- @Before
- public void setup() {
- Settings settings = new Settings();
- settings.setProperty(CoreProperties.HOURS_IN_DAY, HOURS_IN_DAY);
-
- ResourcePerspectives perspectives = mock(ResourcePerspectives.class);
- when(perspectives.as(Issuable.class, resource)).thenReturn(issuable);
-
- rightNow = new Date();
- elevenDaysAgo = DateUtils.addDays(rightNow, -11);
- tenDaysAgo = DateUtils.addDays(rightNow, -10);
- nineDaysAgo = DateUtils.addDays(rightNow, -9);
- fiveDaysAgo = DateUtils.addDays(rightNow, -5);
- fourDaysAgo = DateUtils.addDays(rightNow, -4);
-
- when(timeMachineConfiguration.periods()).thenReturn(newArrayList(new Period(1, fiveDaysAgo), new Period(2, tenDaysAgo)));
-
- decorator = new NewDebtDecorator(perspectives, timeMachineConfiguration, new IssueChangelogDebtCalculator());
- }
-
- @Test
- public void generates_metrics() {
- assertThat(decorator.generatesMetrics()).hasSize(1);
- }
-
- @Test
- public void execute_on_project() {
- assertThat(decorator.shouldExecuteOnProject(null)).isTrue();
- }
-
- @Test
- public void save_on_one_issue_with_one_new_changelog() {
- Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(Duration.create(TWO_DAYS_IN_MINUTES)).setChanges(
- newArrayList(
- // changelog created at is null because it has just been created on the current analysis
- new FieldDiffs().setDiff("technicalDebt", ONE_DAY_IN_MINUTES, TWO_DAYS_IN_MINUTES).setCreationDate(null)
- )
- );
- when(issuable.issues()).thenReturn(newArrayList(issue));
-
- decorator.decorate(resource, context);
-
- // remember : period1 is 5daysAgo, period2 is 10daysAgo
- verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 1.0 * ONE_DAY_IN_MINUTES, 1.0 * ONE_DAY_IN_MINUTES)));
- }
-
- @Test
- public void save_on_one_issue_with_changelog() {
- Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES)).setChanges(
- newArrayList(
- new FieldDiffs().setDiff("technicalDebt", TWO_DAYS_IN_MINUTES, FIVE_DAYS_IN_MINUTES).setCreationDate(null),
- new FieldDiffs().setDiff("technicalDebt", ONE_DAY_IN_MINUTES, TWO_DAYS_IN_MINUTES).setCreationDate(fourDaysAgo)
- )
- );
- when(issuable.issues()).thenReturn(newArrayList(issue));
-
- decorator.decorate(resource, context);
-
- // remember : period1 is 5daysAgo, period2 is 10daysAgo
- verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 4.0 * ONE_DAY_IN_MINUTES, 4.0 * ONE_DAY_IN_MINUTES)));
- }
-
- @Test
- public void save_on_one_issue_with_changelog_only_in_the_past() {
- Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(Duration.create(ONE_DAY_IN_MINUTES)).setChanges(
- newArrayList(
- // Change before all periods
- new FieldDiffs().setDiff("technicalDebt", null, ONE_DAY_IN_MINUTES).setCreationDate(elevenDaysAgo)
- )
- );
- when(issuable.issues()).thenReturn(newArrayList(issue));
-
- decorator.decorate(resource, context);
-
- // remember : period1 is 5daysAgo, period2 is 10daysAgo
- verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0, 0.0)));
- }
-
- @Test
- public void save_on_one_issue_with_changelog_having_null_value() {
- Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES)).setChanges(
- newArrayList(
- new FieldDiffs().setDiff("technicalDebt", null, FIVE_DAYS_IN_MINUTES).setCreationDate(null),
- new FieldDiffs().setDiff("technicalDebt", ONE_DAY_IN_MINUTES, null).setCreationDate(fourDaysAgo),
- new FieldDiffs().setDiff("technicalDebt", null, ONE_DAY_IN_MINUTES).setCreationDate(nineDaysAgo)
- )
- );
- when(issuable.issues()).thenReturn(newArrayList(issue));
-
- decorator.decorate(resource, context);
-
- // remember : period1 is 5daysAgo, period2 is 10daysAgo
- verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 4.0 * ONE_DAY_IN_MINUTES, 5.0 * ONE_DAY_IN_MINUTES)));
- }
-
- @Test
- public void save_on_one_issue_with_changelog_and_periods_have_no_dates() {
- when(timeMachineConfiguration.periods()).thenReturn(newArrayList(new Period(1, null), new Period(2, null)));
-
- Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES)).setChanges(
- newArrayList(
- new FieldDiffs().setDiff("technicalDebt", null, FIVE_DAYS_IN_MINUTES).setCreationDate(null),
- new FieldDiffs().setDiff("technicalDebt", ONE_DAY_IN_MINUTES, null).setCreationDate(fourDaysAgo),
- new FieldDiffs().setDiff("technicalDebt", null, ONE_DAY_IN_MINUTES).setCreationDate(nineDaysAgo)
- )
- );
- when(issuable.issues()).thenReturn(newArrayList(issue));
-
- decorator.decorate(resource, context);
-
- // remember : period1 is 5daysAgo, period2 is 10daysAgo
- verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 5.0 * ONE_DAY_IN_MINUTES, 5.0 * ONE_DAY_IN_MINUTES)));
- }
-
- @Test
- public void save_on_one_issue_with_changelog_having_not_only_technical_debt_changes() {
- Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES)).setChanges(
- newArrayList(
- new FieldDiffs()
- .setDiff("actionPlan", "1.0", "1.1").setCreationDate(fourDaysAgo)
- .setDiff("technicalDebt", ONE_DAY_IN_MINUTES, TWO_DAYS_IN_MINUTES).setCreationDate(fourDaysAgo)
- )
- );
- when(issuable.issues()).thenReturn(newArrayList(issue));
-
- decorator.decorate(resource, context);
-
- // remember : period1 is 5daysAgo, period2 is 10daysAgo
- verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 4.0 * ONE_DAY_IN_MINUTES, 4.0 * ONE_DAY_IN_MINUTES)));
- }
-
- @Test
- public void save_on_issues_with_changelog() {
- Issue issue1 = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES)).setChanges(
- newArrayList(
- new FieldDiffs().setDiff("technicalDebt", TWO_DAYS_IN_MINUTES, FIVE_DAYS_IN_MINUTES).setCreationDate(rightNow),
- new FieldDiffs().setDiff("technicalDebt", ONE_DAY_IN_MINUTES, TWO_DAYS_IN_MINUTES).setCreationDate(fourDaysAgo),
- new FieldDiffs().setDiff("technicalDebt", null, ONE_DAY_IN_MINUTES).setCreationDate(nineDaysAgo)
- )
- );
- Issue issue2 = new DefaultIssue().setKey("B").setCreationDate(tenDaysAgo).setDebt(Duration.create(TWO_DAYS_IN_MINUTES)).setChanges(
- newArrayList(
- new FieldDiffs().setDiff("technicalDebt", ONE_DAY_IN_MINUTES, TWO_DAYS_IN_MINUTES).setCreationDate(rightNow),
- new FieldDiffs().setDiff("technicalDebt", null, ONE_DAY_IN_MINUTES).setCreationDate(nineDaysAgo)
- )
- );
- when(issuable.issues()).thenReturn(newArrayList(issue1, issue2));
-
- decorator.decorate(resource, context);
-
- // remember : period1 is 5daysAgo, period2 is 10daysAgo
- verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 5.0 * ONE_DAY_IN_MINUTES, 7.0 * ONE_DAY_IN_MINUTES)));
- }
-
- @Test
- public void save_on_one_issue_without_changelog() {
- when(issuable.issues()).thenReturn(newArrayList(
- (Issue) new DefaultIssue().setKey("A").setCreationDate(nineDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES)))
- );
-
- decorator.decorate(resource, context);
-
- // remember : period1 is 5daysAgo, period2 is 10daysAgo
- verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0, 5.0 * ONE_DAY_IN_MINUTES)));
- }
-
- @Test
- public void save_on_one_issue_without_technical_debt_and_without_changelog() {
- when(issuable.issues()).thenReturn(newArrayList(
- (Issue) new DefaultIssue().setKey("A").setCreationDate(nineDaysAgo).setDebt(null))
- );
-
- decorator.decorate(resource, context);
-
- // remember : period1 is 5daysAgo, period2 is 10daysAgo
- verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0, 0.0)));
- }
-
- @Test
- public void save_on_one_issue_without_changelog_and_periods_have_no_dates() {
- when(timeMachineConfiguration.periods()).thenReturn(newArrayList(new Period(1, null), new Period(2, null)));
-
- when(issuable.issues()).thenReturn(newArrayList(
- (Issue) new DefaultIssue().setKey("A").setCreationDate(nineDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES)))
- );
-
- decorator.decorate(resource, context);
-
- // remember : period1 is null, period2 is null
- verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 5.0 * ONE_DAY_IN_MINUTES, 5.0 * ONE_DAY_IN_MINUTES)));
- }
-
- @Test
- public void save_on_issues_without_changelog() {
- when(issuable.issues()).thenReturn(newArrayList(
- (Issue) new DefaultIssue().setKey("A").setCreationDate(nineDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES)),
- new DefaultIssue().setKey("B").setCreationDate(fiveDaysAgo).setDebt(Duration.create(TWO_DAYS_IN_MINUTES))
- ));
-
- decorator.decorate(resource, context);
-
- // remember : period1 is 5daysAgo, period2 is 10daysAgo
- verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0, 7.0 * ONE_DAY_IN_MINUTES)));
- }
-
- @Test
- public void save_on_issues_with_changelog_and_issues_without_changelog() {
- // issue1 and issue2 have changelog
- Issue issue1 = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES)).setChanges(
- newArrayList(
- new FieldDiffs().setDiff("technicalDebt", TWO_DAYS_IN_MINUTES, FIVE_DAYS_IN_MINUTES).setCreationDate(rightNow),
- new FieldDiffs().setDiff("technicalDebt", ONE_DAY_IN_MINUTES, TWO_DAYS_IN_MINUTES).setCreationDate(fourDaysAgo),
- new FieldDiffs().setDiff("technicalDebt", null, ONE_DAY_IN_MINUTES).setCreationDate(nineDaysAgo)
- )
- );
- Issue issue2 = new DefaultIssue().setKey("B").setCreationDate(tenDaysAgo).setDebt(Duration.create(TWO_DAYS_IN_MINUTES)).setChanges(
- newArrayList(
- new FieldDiffs().setDiff("technicalDebt", ONE_DAY_IN_MINUTES, TWO_DAYS_IN_MINUTES).setCreationDate(rightNow),
- new FieldDiffs().setDiff("technicalDebt", null, ONE_DAY_IN_MINUTES).setCreationDate(nineDaysAgo)
- )
- );
-
- // issue3 and issue4 have no changelog
- Issue issue3 = new DefaultIssue().setKey("C").setCreationDate(nineDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES));
- Issue issue4 = new DefaultIssue().setKey("D").setCreationDate(fiveDaysAgo).setDebt(Duration.create(TWO_DAYS_IN_MINUTES));
- when(issuable.issues()).thenReturn(newArrayList(issue1, issue2, issue3, issue4));
-
- decorator.decorate(resource, context);
-
- // remember : period1 is 5daysAgo, period2 is 10daysAgo
- verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 5.0 * ONE_DAY_IN_MINUTES, 14.0 * ONE_DAY_IN_MINUTES)));
- }
-
- @Test
- public void not_save_if_measure_already_computed() {
- when(context.getMeasure(CoreMetrics.NEW_TECHNICAL_DEBT)).thenReturn(new Measure());
- when(issuable.issues()).thenReturn(newArrayList(
- (Issue) new DefaultIssue().setKey("A").setCreationDate(nineDaysAgo).setDebt(Duration.create(FIVE_DAYS_IN_MINUTES)),
- new DefaultIssue().setKey("B").setCreationDate(fiveDaysAgo).setDebt(Duration.create(TWO_DAYS_IN_MINUTES))
- ));
-
- decorator.decorate(resource, context);
-
- verify(context, never()).saveMeasure(argThat(new IsMeasure(CoreMetrics.NEW_TECHNICAL_DEBT)));
- }
-
- /**
- * SONAR-5059
- */
- @Test
- public void not_return_negative_debt() {
- Issue issue = new DefaultIssue().setKey("A").setCreationDate(tenDaysAgo).setDebt(Duration.create(ONE_DAY_IN_MINUTES)).setChanges(
- newArrayList(
- // changelog created at is null because it has just been created on the current analysis
- new FieldDiffs().setDiff("technicalDebt", TWO_DAYS_IN_MINUTES, ONE_DAY_IN_MINUTES).setCreationDate(null)
- )
- );
- when(issuable.issues()).thenReturn(newArrayList(issue));
-
- decorator.decorate(resource, context);
-
- // remember : period1 is 5daysAgo, period2 is 10daysAgo
- verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_TECHNICAL_DEBT, 0.0, 0.0)));
- }
-
-
- class IsVariationMeasure extends ArgumentMatcher<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());
- }
- }
-
-}
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();
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();
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();
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();
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
-import org.sonar.api.CoreProperties;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.resources.Project;
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;
@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");
File outputDir = temp.newFolder();
BatchReportWriter writer = new BatchReportWriter(outputDir);
- publisher.publish(writer);
+ underTest.publish(writer);
BatchReportReader reader = new BatchReportReader(outputDir);
- Metadata metadata = reader.readMetadata();
- assertThat(metadata.getAnalysisDate()).isEqualTo(1234567L);
- assertThat(metadata.getProjectKey()).isEqualTo("foo");
-
assertThat(reader.readComponentIssues(1)).hasSize(0);
assertThat(reader.readComponentIssues(2)).hasSize(2);
-
- }
-
- @Test
- public void publishMetadataWithBranch() throws Exception {
- root.properties().put(CoreProperties.PROJECT_BRANCH_PROPERTY, "myBranch");
- p.setKey("foo:myBranch");
- p.setEffectiveKey("foo:myBranch");
-
- File outputDir = temp.newFolder();
- BatchReportWriter writer = new BatchReportWriter(outputDir);
-
- publisher.publish(writer);
-
- BatchReportReader reader = new BatchReportReader(outputDir);
- Metadata metadata = reader.readMetadata();
- assertThat(metadata.getAnalysisDate()).isEqualTo(1234567L);
- assertThat(metadata.getProjectKey()).isEqualTo("foo");
- assertThat(metadata.getBranch()).isEqualTo("myBranch");
}
}
import org.sonar.api.measures.MetricFinder;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
-import org.sonar.api.technicaldebt.batch.Characteristic;
import org.sonar.batch.index.BatchComponentCache;
import org.sonar.batch.protocol.output.BatchReportReader;
import org.sonar.batch.protocol.output.BatchReportWriter;
import org.sonar.batch.scan.measure.MeasureCache;
+import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
@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)
// String value
Measure stringMeasure = new Measure<>(CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION)
.setData("foo bar");
-
- when(measureCache.byResource(sampleFile)).thenReturn(Arrays.asList(measure1, measure2, manual, rating, longMeasure, stringMeasure));
+ when(measureCache.byResource(sampleFile)).thenReturn(asList(measure1, measure2, manual, rating, longMeasure, stringMeasure));
File outputDir = temp.newFolder();
BatchReportWriter writer = new BatchReportWriter(outputDir);
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);
}
--- /dev/null
+/*
+ * 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");
+ }
+
+}
+++ /dev/null
-/*
- * 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'");
- }
- }
-}
import org.sonar.api.resources.File;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
-import org.sonar.api.technicaldebt.batch.Characteristic;
-import org.sonar.api.technicaldebt.batch.Requirement;
import org.sonar.batch.index.AbstractCachesTest;
import org.sonar.batch.index.Cache.Entry;
Project p = new Project("struts");
assertThat(measureCache.entries()).hasSize(0);
-
assertThat(measureCache.byResource(p)).hasSize(0);
Measure m = new Measure(CoreMetrics.NCLOC, 1.0);
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);
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();
}
*/
package org.sonar.core.dashboard;
+import java.util.List;
+import javax.annotation.Nullable;
import org.apache.ibatis.session.SqlSession;
-import org.sonar.api.batch.BatchSide;
import org.sonar.api.server.ServerSide;
import org.sonar.core.persistence.DaoComponent;
import org.sonar.core.persistence.MyBatis;
-import javax.annotation.Nullable;
-
-import java.util.List;
-
-@BatchSide
@ServerSide
public class ActiveDashboardDao implements DaoComponent {
package org.sonar.core.issue.db;
import com.google.common.collect.Lists;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
import org.apache.ibatis.session.SqlSession;
-import org.sonar.api.batch.BatchSide;
import org.sonar.api.server.ServerSide;
import org.sonar.core.persistence.DaoComponent;
import org.sonar.core.persistence.MyBatis;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
import static com.google.common.collect.Lists.newArrayList;
-/**
- * @since 3.6
- */
-@BatchSide
@ServerSide
public class ActionPlanDao implements DaoComponent {
package org.sonar.core.issue.db;
import com.google.common.collect.Lists;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
-import java.util.Map;
import javax.annotation.CheckForNull;
-import org.apache.ibatis.session.ResultHandler;
-import org.sonar.api.batch.BatchSide;
+import org.sonar.api.server.ServerSide;
import org.sonar.core.issue.DefaultIssueComment;
import org.sonar.core.issue.FieldDiffs;
-import org.sonar.api.server.ServerSide;
import org.sonar.core.persistence.DaoComponent;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
import static com.google.common.collect.Lists.newArrayList;
-import static com.google.common.collect.Maps.newHashMap;
+import static java.util.Arrays.asList;
-/**
- * @since 3.6
- */
-@BatchSide
@ServerSide
public class IssueChangeDao implements DaoComponent {
DbSession session = mybatis.openSession(false);
try {
List<FieldDiffs> result = Lists.newArrayList();
- for (IssueChangeDto dto : selectByIssuesAndType(session, Arrays.asList(issueKey), IssueChangeDto.TYPE_FIELD_CHANGE)) {
+ for (IssueChangeDto dto : selectByIssuesAndType(session, asList(issueKey), IssueChangeDto.TYPE_FIELD_CHANGE)) {
result.add(dto.toFieldDiffs());
}
return result;
}
}
- public void selectChangelogOnNonClosedIssuesByModuleAndType(long componentId, ResultHandler handler) {
+ public List<IssueChangeDto> selectChangelogOfUnresolvedIssuesByComponent(String componentUuid) {
DbSession session = mybatis.openSession(false);
try {
- Map<String, Object> params = newHashMap();
- params.put("componentId", componentId);
- params.put("changeType", IssueChangeDto.TYPE_FIELD_CHANGE);
- session.select("org.sonar.core.issue.db.IssueChangeMapper.selectChangelogOnNonClosedIssuesByModuleAndType", params, handler);
+ IssueChangeMapper mapper = session.getMapper(IssueChangeMapper.class);
+ return mapper.selectChangelogOfUnresolvedIssuesByComponent(componentUuid, IssueChangeDto.TYPE_FIELD_CHANGE);
} finally {
MyBatis.closeQuietly(session);
package org.sonar.core.issue.db;
-import org.apache.ibatis.annotations.Param;
-
-import javax.annotation.CheckForNull;
-
import java.util.List;
+import javax.annotation.CheckForNull;
+import org.apache.ibatis.annotations.Param;
-/**
- * @since 3.6
- */
public interface IssueChangeMapper {
void insert(IssueChangeDto dto);
int update(IssueChangeDto change);
@CheckForNull
- IssueChangeDto selectByKeyAndType(@Param("key") String key,
- @Param("changeType") String type);
+ IssueChangeDto selectByKeyAndType(@Param("key") String key, @Param("changeType") String type);
+
/**
* Issue changes by chronological date of creation
*/
List<IssueChangeDto> selectByIssuesAndType(@Param("issueKeys") List<String> issueKeys,
- @Param("changeType") String changeType);
+ @Param("changeType") String changeType);
- List<IssueChangeDto> selectByIssue(String issueKey);
+ List<IssueChangeDto> selectChangelogOfUnresolvedIssuesByComponent(@Param("componentUuid") String componentUuid, @Param("changeType") String changeType);
}
issue.setEffortToFix(effortToFix);
issue.setDebt(debt != null ? Duration.create(debt) : null);
issue.setLine(line);
+ issue.setChecksum(checksum);
issue.setSeverity(severity);
issue.setReporter(reporter);
issue.setAssignee(assignee);
IssueDto selectByKey(String key);
- List<IssueDto> selectOpenByComponentUuid(String componentUuid);
+ List<IssueDto> selectNonClosedByComponentUuid(String componentUuid);
Set<String> selectComponentUuidsOfOpenIssuesForProjectUuid(String projectUuid);
@Override
public LineHashSequence getLineHashSequence() {
if (lineHashSeq == null) {
- lineHashSeq = LineHashSequence.createForLines(loadSourceLines());
+ lineHashSeq = loadLineHashSequence();
}
return lineHashSeq;
}
return issues;
}
- protected abstract Iterable<String> loadSourceLines();
+ protected abstract LineHashSequence loadLineHashSequence();
protected abstract List<ISSUE> loadIssues();
}
import java.util.Collection;
import java.util.Objects;
import javax.annotation.Nonnull;
+import org.apache.commons.lang.StringUtils;
import org.sonar.api.rule.RuleKey;
+import org.sonar.api.utils.log.Loggers;
import static com.google.common.collect.FluentIterable.from;
detectCodeMoves(rawInput, baseInput, tracking);
// 3. match issues with same rule, same message and same line hash
- match(tracking, LineHashAndMessagekeyFactory.INSTANCE);
+ match(tracking, LineHashAndMessageKeyFactory.INSTANCE);
// 4. match issues with same rule, same line and same message
match(tracking, LineAndMessageKeyFactory.INSTANCE);
LineAndLineHashKey(Trackable trackable) {
this.ruleKey = trackable.getRuleKey();
this.line = trackable.getLine();
- this.lineHash = trackable.getLineHash();
+ this.lineHash = StringUtils.defaultString(trackable.getLineHash(), "");
}
@Override
LineHashAndMessageKey(Trackable trackable) {
this.ruleKey = trackable.getRuleKey();
this.message = trackable.getMessage();
- this.lineHash = trackable.getLineHash();
+ this.lineHash = StringUtils.defaultString(trackable.getLineHash(), "");
}
@Override
}
}
- private enum LineHashAndMessagekeyFactory implements SearchKeyFactory {
+ private enum LineHashAndMessageKeyFactory implements SearchKeyFactory {
INSTANCE;
@Override
public SearchKey create(Trackable t) {
*/
package org.sonar.core.issue.tracking;
+import com.google.common.base.Objects;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import java.util.Collection;
private final Multimap<Integer, BASE> openManualIssues = ArrayListMultimap.create();
public Tracking(Input<RAW> rawInput, Input<BASE> baseInput) {
- for (RAW raw : rawInput.getIssues()) {
- // Extra verification if some plugins create issues on wrong lines
- Integer rawLine = raw.getLine();
- if (rawLine != null && !rawInput.getLineHashSequence().hasLine(rawLine)) {
- throw new IllegalArgumentException("Issue line is not valid: " + raw);
- }
- this.unmatchedRaws.add(raw);
- }
+ this.unmatchedRaws.addAll(rawInput.getIssues());
this.unmatchedBases.addAll(baseInput.getIssues());
}
void associateRawToBase(RAW raw, BASE base) {
rawToBase.put(raw, base);
- unmatchedBases.remove(base);
+ if (!unmatchedBases.remove(base)) {
+ throw new IllegalStateException(String.format("Fail to associate base issue %s to %s among %s", base, raw, this));
+ }
}
void markRawAsAssociated(RAW raw) {
- unmatchedRaws.remove(raw);
+ if (!unmatchedRaws.remove(raw)) {
+ throw new IllegalStateException(String.format("Fail to mark issue as associated: %s among %s", raw, this));
+ }
}
void markRawsAsAssociated(Collection<RAW> c) {
- unmatchedRaws.removeAll(c);
+ // important : do not use unmatchedRaws.removeAll(Collection) as it's buggy. See:
+ // http://stackoverflow.com/questions/19682542/why-identityhashmap-keyset-removeallkeys-does-not-use-identity-is-it-a-bug/19682543#19682543
+ // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6588783
+ for (RAW raw : c) {
+ markRawAsAssociated(raw);
+ }
}
boolean isComplete() {
openManualIssues.put(line, manualIssue);
unmatchedBases.remove(manualIssue);
}
+
+ @Override
+ public String toString() {
+ return Objects.toStringHelper(this)
+ .add("rawToBase", rawToBase)
+ .add("unmatchedRaws", unmatchedRaws)
+ .add("unmatchedBases", unmatchedBases)
+ .add("openManualIssues", openManualIssues)
+ .toString();
+ }
}
public void execute(Context context) {
DefaultIssue issue = (DefaultIssue) context.issue();
if (!issue.isBeingClosed()) {
- throw new IllegalStateException("Issue is still alive: " + issue);
+ throw new IllegalStateException("Issue is still open: " + issue);
}
if (issue.isOnDisabledRule()) {
context.setResolution(Issue.RESOLUTION_REMOVED);
*/
package org.sonar.core.persistence;
-/**
- * @since 4.4
- */
public interface DaoComponent {
}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.core.technicaldebt;
-
-import com.google.common.base.Predicate;
-import com.google.common.collect.Iterables;
-import org.sonar.api.batch.RequiresDB;
-import org.sonar.api.batch.debt.DebtCharacteristic;
-import org.sonar.api.batch.debt.DebtModel;
-import org.sonar.api.batch.debt.internal.DefaultDebtCharacteristic;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.technicaldebt.batch.TechnicalDebtModel;
-import org.sonar.api.technicaldebt.batch.internal.DefaultCharacteristic;
-import org.sonar.api.technicaldebt.batch.internal.DefaultRequirement;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-
-import java.util.Collections;
-import java.util.List;
-
-import static com.google.common.collect.Lists.newArrayList;
-
-@RequiresDB
-public class DefaultTechnicalDebtModel implements TechnicalDebtModel {
-
- private final DebtModel model;
-
- public DefaultTechnicalDebtModel(DebtModel model) {
- this.model = model;
- }
-
- public List<DefaultCharacteristic> rootCharacteristics() {
- return newArrayList(Iterables.filter(characteristics(), new Predicate<DefaultCharacteristic>() {
- @Override
- public boolean apply(DefaultCharacteristic input) {
- return input.isRoot();
- }
- }));
- }
-
- @Override
- @CheckForNull
- public DefaultCharacteristic characteristicByKey(final String key) {
- return Iterables.find(characteristics(), new Predicate<DefaultCharacteristic>() {
- @Override
- public boolean apply(DefaultCharacteristic input) {
- return input.key().equals(key);
- }
- }, null);
- }
-
- @Override
- @CheckForNull
- public DefaultCharacteristic characteristicById(final Integer id) {
- return Iterables.find(characteristics(), new Predicate<DefaultCharacteristic>() {
- @Override
- public boolean apply(DefaultCharacteristic input) {
- return input.id().equals(id);
- }
- }, null);
- }
-
- @Override
- @CheckForNull
- public DefaultRequirement requirementsByRule(final RuleKey ruleKey) {
- return null;
- }
-
- @Override
- @CheckForNull
- public DefaultRequirement requirementsById(final Integer id) {
- return null;
- }
-
- @Override
- public List<DefaultCharacteristic> characteristics() {
- List<DefaultCharacteristic> flatCharacteristics = newArrayList();
- for (DebtCharacteristic characteristic : model.characteristics()) {
- DefaultCharacteristic root = toDefaultCharacteristic((DefaultDebtCharacteristic) characteristic, null);
- flatCharacteristics.add(root);
- for (DebtCharacteristic subCharacteristic : model.subCharacteristics(characteristic.key())) {
- flatCharacteristics.add(toDefaultCharacteristic((DefaultDebtCharacteristic) subCharacteristic, root));
- }
- }
- return flatCharacteristics;
- }
-
- @Override
- public List<DefaultRequirement> requirements() {
- return Collections.emptyList();
- }
-
- public boolean isEmpty() {
- return model.allCharacteristics().isEmpty();
- }
-
- private static DefaultCharacteristic toDefaultCharacteristic(DefaultDebtCharacteristic debtCharacteristic, @Nullable DefaultCharacteristic parentCharacteristic) {
- return new DefaultCharacteristic()
- .setId(debtCharacteristic.id())
- .setKey(debtCharacteristic.key())
- .setName(debtCharacteristic.name())
- .setOrder(debtCharacteristic.order())
- .setParent(parentCharacteristic)
- .setRoot(parentCharacteristic)
- .setCreatedAt(debtCharacteristic.createdAt())
- .setUpdatedAt(debtCharacteristic.updatedAt());
- }
-
-}
<?xml version="1.0" encoding="UTF-8" ?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mappei.dtd">
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.sonar.core.issue.db.IssueChangeMapper">
order by c.created_at
</select>
- <select id="selectChangelogOnNonClosedIssuesByModuleAndType" parameterType="map" resultType="IssueChange">
- select
- <include refid="issueChangeColumns"/>
- from issue_changes c
- inner join issues i on i.kee = c.issue_key
- inner join (select p.id, p.uuid, p.kee from projects p where (p.root_id=#{componentId} and p.qualifier <> 'BRC') or
- (p.id=#{componentId})) p on p.uuid=i.component_uuid
- <where>
- and c.change_type=#{changeType}
- and i.status <> 'CLOSED'
- </where>
- order by c.issue_change_creation_date asc
- </select>
-
<select id="selectByKeyAndType" parameterType="map" resultType="IssueChange">
select
<include refid="issueChangeColumns"/>
where c.issue_key=#{id}
order by created_at asc
</select>
+
+ <select id="selectChangelogOfUnresolvedIssuesByComponent" parameterType="map" resultType="IssueChange">
+ select
+ <include refid="issueChangeColumns"/>
+ from issue_changes c
+ inner join issues i on i.kee = c.issue_key
+ where i.component_uuid=#{componentUuid}
+ and c.change_type=#{changeType}
+ and i.resolution is null
+ </select>
</mapper>
where i.kee=#{kee}
</select>
- <select id="selectOpenByComponentUuid" parameterType="String" resultType="Issue">
+ <select id="selectNonClosedByComponentUuid" parameterType="String" resultType="Issue">
select
- i.id,
- i.kee as kee,
- i.rule_id as ruleId,
- i.action_plan_key as actionPlanKey,
- i.severity as severity,
- i.manual_severity as manualSeverity,
- i.message as message,
- i.line as line,
- i.effort_to_fix as effortToFix,
- i.technical_debt as debt,
- i.status as status,
- i.resolution as resolution,
- i.checksum as checksum,
- i.reporter as reporter,
- i.assignee as assignee,
- i.author_login as authorLogin,
- i.tags as tagsString,
- i.issue_attributes as issueAttributes,
- i.issue_creation_date as issueCreationTime,
- i.issue_update_date as issueUpdateTime,
- i.issue_close_date as issueCloseTime,
- i.created_at as createdAt,
- i.updated_at as updatedAt,
- r.plugin_rule_key as ruleKey,
- i.component_uuid as componentUuid,
- i.project_uuid as projectUuid
+ <include refid="issueColumns"/>
from issues i
inner join rules r on r.id=i.rule_id
+ inner join projects p on p.uuid=i.component_uuid
+ inner join projects root on root.uuid=i.project_uuid
where
i.component_uuid=#{componentUuid} and
i.status <> 'CLOSED'
*/
package org.sonar.core.issue.db;
-import org.apache.ibatis.executor.result.DefaultResultHandler;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.sonar.api.utils.DateUtils;
import org.sonar.core.issue.DefaultIssueComment;
import org.sonar.core.issue.FieldDiffs;
-import org.sonar.api.utils.DateUtils;
import org.sonar.core.persistence.AbstractDaoTestCase;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
import static com.google.common.collect.Lists.newArrayList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
}
@Test
- public void select_issue_changelog_by_module() {
- setupData("select_issue_changelog_by_module");
-
- // 400 is a non-root module, we should find 2 + 1 changelog from classes and one on itself
- DefaultResultHandler handler = new DefaultResultHandler();
- dao.selectChangelogOnNonClosedIssuesByModuleAndType(400, handler);
- assertThat(handler.getResultList()).hasSize(4);
-
- IssueChangeDto issueChangeDto = (IssueChangeDto) handler.getResultList().get(0);
- assertThat(issueChangeDto.getId()).isNotNull();
- assertThat(issueChangeDto.getKey()).isNotNull();
- assertThat(issueChangeDto.getIssueKey()).isNotNull();
- assertThat(issueChangeDto.getUserLogin()).isNotNull();
- assertThat(issueChangeDto.getChangeType()).isNotNull();
- assertThat(issueChangeDto.getChangeData()).isNotNull();
- assertThat(issueChangeDto.getCreatedAt()).isNotNull();
- assertThat(issueChangeDto.getUpdatedAt()).isNotNull();
-
- for (Object changeDtoObject : handler.getResultList()) {
- IssueChangeDto changeDto = (IssueChangeDto) changeDtoObject;
- assertThat(changeDto.getChangeType()).isEqualTo(IssueChangeDto.TYPE_FIELD_CHANGE);
- }
+ public void selectChangelogOfUnresolvedIssuesByComponent() {
+ setupData("selectChangelogOfUnresolvedIssuesByComponent");
- // 399 is the root module, we should only find 1 changelog on itself
- handler = new DefaultResultHandler();
- dao.selectChangelogOnNonClosedIssuesByModuleAndType(399, handler);
- assertThat(handler.getResultList()).hasSize(1);
- }
-
- @Test
- public void select_issue_changelog_by_module_should_be_sorted_by_creation_date() {
- setupData("select_issue_changelog_by_module_are_sorted_by_creation_date");
-
- DefaultResultHandler handler = new DefaultResultHandler();
- dao.selectChangelogOnNonClosedIssuesByModuleAndType(399, handler);
- assertThat(handler.getResultList()).hasSize(3);
- assertThat(((IssueChangeDto) handler.getResultList().get(0)).getId()).isEqualTo(1001);
- assertThat(((IssueChangeDto) handler.getResultList().get(1)).getId()).isEqualTo(1002);
- assertThat(((IssueChangeDto) handler.getResultList().get(2)).getId()).isEqualTo(1000);
+ List<IssueChangeDto> dtos = dao.selectChangelogOfUnresolvedIssuesByComponent("FILE_1");
+ assertThat(dtos).extracting("id").containsExactly(100L);
}
@Test
}
@Test
- public void fail_if_raw_line_does_not_exist() throws Exception {
+ public void do_not_fail_if_raw_line_does_not_exist() throws Exception {
FakeInput baseInput = new FakeInput();
FakeInput rawInput = new FakeInput("H1").addIssue(new Issue(200, "H200", RULE_SYSTEM_PRINT, "msg"));
- thrown.expect(IllegalArgumentException.class);
- thrown.expectMessage("Issue line is not valid");
- tracker.track(rawInput, baseInput);
+ Tracking<Issue, Issue> tracking = tracker.track(rawInput, baseInput);
+
+ assertThat(tracking.getUnmatchedRaws()).hasSize(1);
}
/**
private final List<Issue> issues = new ArrayList<>();
private final List<String> lineHashes;
- public FakeInput(String... lineHashes) {
+ FakeInput(String... lineHashes) {
this.lineHashes = asList(lineHashes);
}
return new FakeInput(hashes);
}
- public Issue createIssueOnLine(int line, RuleKey ruleKey, String message) {
+ Issue createIssueOnLine(int line, RuleKey ruleKey, String message) {
Issue issue = new Issue(line, lineHashes.get(line - 1), ruleKey, message);
issues.add(issue);
return issue;
/**
* No line (line 0)
*/
- public Issue createIssue(RuleKey ruleKey, String message) {
+ Issue createIssue(RuleKey ruleKey, String message) {
Issue issue = new Issue(null, "", ruleKey, message);
issues.add(issue);
return issue;
}
- public FakeInput addIssue(Issue issue) {
+ FakeInput addIssue(Issue issue) {
this.issues.add(issue);
return this;
}
INSTANCE.execute(context);
fail();
} catch (IllegalStateException e) {
- assertThat(e.getMessage()).contains("Issue is still alive");
+ assertThat(e.getMessage()).contains("Issue is still open");
verify(context, never()).setResolution(anyString());
}
}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.core.technicaldebt;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.api.batch.debt.internal.DefaultDebtCharacteristic;
-import org.sonar.api.batch.debt.internal.DefaultDebtModel;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.technicaldebt.batch.internal.DefaultCharacteristic;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class DefaultTechnicalDebtModelTest {
-
- private DefaultTechnicalDebtModel sqaleModel;
-
- @Before
- public void setUp() {
- DefaultDebtModel debtModel = new DefaultDebtModel();
- debtModel.addCharacteristic(
- new DefaultDebtCharacteristic().setId(1)
- .setKey("MEMORY_EFFICIENCY")
- .setName("Memory use")
- .setOrder(1)
- );
- debtModel.addSubCharacteristic(
- new DefaultDebtCharacteristic().setId(2)
- .setKey("EFFICIENCY")
- .setName("Efficiency")
- .setParentId(1),
- "MEMORY_EFFICIENCY"
- );
- sqaleModel = new DefaultTechnicalDebtModel(debtModel);
- }
-
- @Test
- public void get_characteristics() {
- assertThat(sqaleModel.rootCharacteristics()).hasSize(1);
-
- DefaultCharacteristic resultRootCharacteristic = sqaleModel.rootCharacteristics().get(0);
- assertThat(resultRootCharacteristic.id()).isEqualTo(1);
- assertThat(resultRootCharacteristic.key()).isEqualTo("MEMORY_EFFICIENCY");
- assertThat(resultRootCharacteristic.name()).isEqualTo("Memory use");
- assertThat(resultRootCharacteristic.order()).isEqualTo(1);
- assertThat(resultRootCharacteristic.children()).hasSize(1);
- assertThat(resultRootCharacteristic.parent()).isNull();
- assertThat(resultRootCharacteristic.root()).isNull();
- }
-
- @Test
- public void get_characteristic_by_key() {
- assertThat(sqaleModel.characteristicByKey("MEMORY_EFFICIENCY")).isNotNull();
- assertThat(sqaleModel.characteristicByKey("EFFICIENCY")).isNotNull();
- assertThat(sqaleModel.characteristicByKey("EFFICIENCY").parent()).isNotNull();
-
- assertThat(sqaleModel.characteristicByKey("UNKNOWN")).isNull();
- }
-
- @Test
- public void characteristic_by_id() {
- assertThat(sqaleModel.characteristicById(1)).isNotNull();
- assertThat(sqaleModel.characteristicById(2)).isNotNull();
- assertThat(sqaleModel.characteristicById(123)).isNull();
- }
-
- @Test
- public void get_requirement_by_rule_key_always_return_null() {
- assertThat(sqaleModel.requirementsByRule(RuleKey.of("checkstyle", "Regexp"))).isNull();
- }
-
- @Test
- public void get_requirement_by_id_always_return_null() {
- assertThat(sqaleModel.requirementsById(1)).isNull();
- }
-
- @Test
- public void get_requirements_always_return_empty_list() {
- assertThat(sqaleModel.requirements()).isEmpty();
- }
-
-}
--- /dev/null
+<dataset>
+
+ <!-- Unresolved -->
+ <issues
+ id="1"
+ kee="UNRESOLVED_ON_FILE_1"
+ component_uuid="FILE_1"
+ project_uuid="PROJECT_1"
+ resolution="[null]"
+ status="OPEN"
+ rule_id="500"
+ severity="BLOCKER"
+ manual_severity="[false]"
+ message="[null]"
+ line="200"
+ effort_to_fix="[null]"
+ checksum="[null]"
+ reporter="user"
+ assignee="user"
+ author_login="[null]"
+ issue_attributes="[null]"
+ issue_creation_date="1366063200000"
+ issue_update_date="1366063200000"
+ issue_close_date="1366063200000"
+ created_at="1400000000000"
+ updated_at="[null]"
+ />
+
+ <!-- diff -->
+ <issue_changes
+ id="100"
+ kee="100"
+ issue_key="UNRESOLVED_ON_FILE_1"
+ user_login="arthur"
+ change_type="diff"
+ change_data="severity=MAJOR|BLOCKER"
+ created_at="1410213600000"
+ updated_at="1410213600000"
+ issue_change_creation_date="1410213600000"
+ />
+
+ <!-- comment -->
+ <issue_changes
+ id="102"
+ kee="102"
+ issue_key="UNRESOLVED_ON_FILE_1"
+ user_login="arthur"
+ change_type="comment"
+ change_data="recent comment"
+ created_at="1410213600000"
+ updated_at="1410213600000"
+ issue_change_creation_date="[null]"
+ />
+
+ <!-- Resolved: to be ignored -->
+ <issues
+ id="2"
+ kee="RESOLVED_ON_FILE_1"
+ component_uuid="FILE_1"
+ project_uuid="PROJECT_1"
+ resolution="FIXED"
+ status="RESOLVED"
+ rule_id="501"
+ severity="MAJOR"
+ manual_severity="[false]"
+ message="[null]"
+ line="120"
+ effort_to_fix="[null]"
+ checksum="[null]"
+ reporter="[null]"
+ assignee="user"
+ author_login="[null]"
+ issue_attributes="[null]"
+ issue_creation_date="1366063200000"
+ issue_update_date="1366063200000"
+ issue_close_date="1366063200000"
+ created_at="1400000000000"
+ updated_at="[null]"
+ />
+
+ <issue_changes
+ id="103"
+ kee="103"
+ issue_key="RESOLVED_ON_FILE_1"
+ user_login="arthur"
+ change_type="diff"
+ change_data="severity=MAJOR|BLOCKER"
+ created_at="1410213600000"
+ updated_at="1410213600000"
+ issue_change_creation_date="1410213600000"
+ />
+
+ <!-- Unresolved on other file -->
+ <issues
+ id="3"
+ kee="UNRESOLVED_ON_FILE_2"
+ component_uuid="FILE_2"
+ project_uuid="PROJECT_1"
+ resolution="[null]"
+ status="OPEN"
+ rule_id="500"
+ severity="BLOCKER"
+ manual_severity="[false]"
+ message="[null]"
+ line="200"
+ effort_to_fix="[null]"
+ checksum="[null]"
+ reporter="user"
+ assignee="user"
+ author_login="[null]"
+ issue_attributes="[null]"
+ issue_creation_date="1366063200000"
+ issue_update_date="1366063200000"
+ issue_close_date="1366063200000"
+ created_at="1400000000000"
+ updated_at="[null]"
+ />
+
+ <!-- diff -->
+ <issue_changes
+ id="104"
+ kee="104"
+ issue_key="UNRESOLVED_ON_FILE_2"
+ user_login="arthur"
+ change_type="diff"
+ change_data="severity=MAJOR|BLOCKER"
+ created_at="1410213600000"
+ updated_at="1410213600000"
+ issue_change_creation_date="1410213600000"
+ />
+
+ <!-- comment -->
+ <issue_changes
+ id="105"
+ kee="105"
+ issue_key="UNRESOLVED_ON_FILE_2"
+ user_login="arthur"
+ change_type="comment"
+ change_data="recent comment"
+ created_at="1410213600000"
+ updated_at="1410213600000"
+ issue_change_creation_date="[null]"
+ />
+</dataset>
+++ /dev/null
-<dataset>
-
- <projects id="399" uuid="uuid-399" kee="struts" root_id="[null]" project_uuid="[null]" qualifier="TRK" scope="PRJ" />
- <projects id="400" uuid="uuid-400" kee="struts-core" root_id="399" project_uuid="uuid-399" qualifier="BRC" scope="PRJ" />
- <projects id="401" uuid="uuid-401" kee="Action.java" root_id="400" project_uuid="uuid-400" qualifier="CLA" scope="PRJ" />
- <projects id="402" uuid="uuid-402" kee="Filter.java" root_id="400" project_uuid="uuid-400" qualifier="CLA" scope="PRJ" />
-
- <!-- Open Issue on a file -->
- <issues
- id="100"
- kee="100"
- component_uuid="uuid-401"
- project_uuid="uuid-399"
- rule_id="500"
- severity="BLOCKER"
- manual_severity="[false]"
- message="[null]"
- line="200"
- effort_to_fix="[null]"
- status="OPEN"
- resolution="[null]"
- checksum="[null]"
- reporter="user"
- assignee="user"
- author_login="[null]"
- issue_attributes="[null]"
- issue_creation_date="1366063200000"
- issue_update_date="1366063200000"
- issue_close_date="1366063200000"
- created_at="1400000000000"
- updated_at="[null]"
- />
-
- <issue_changes
- id="100"
- kee="100"
- issue_key="100"
- user_login="arthur"
- change_type="diff"
- change_data="severity=MAJOR|BLOCKER"
- created_at="1410213600000"
- updated_at="1410213600000"
- issue_change_creation_date="1410213600000"
- />
-
- <issue_changes
- id="1000"
- kee="1000"
- issue_key="100"
- user_login="arthur"
- change_type="diff"
- change_data="actionPlan=1.0|1.1"
- created_at="1410213600000"
- updated_at="1410213600000"
- issue_change_creation_date="1410213600000"
- />
-
- <issue_changes
- id="1001"
- kee="1001"
- issue_key="100"
- user_login="arthur"
- change_type="comment"
- change_data="recent comment"
- created_at="1410213600000"
- updated_at="1410213600000"
- issue_change_creation_date="[null]"
- />
-
- <!-- Open Issue on a file -->
- <issues
- id="101"
- kee="101"
- component_uuid="uuid-402"
- project_uuid="uuid-399"
- rule_id="501"
- severity="MAJOR"
- manual_severity="[false]"
- message="[null]"
- line="120"
- effort_to_fix="[null]"
- status="OPEN"
- resolution="[null]"
- checksum="[null]"
- reporter="[null]"
- assignee="user"
- author_login="[null]"
- issue_attributes="[null]"
- issue_creation_date="1366063200000"
- issue_update_date="1366063200000"
- issue_close_date="1366063200000"
- created_at="1400000000000"
- updated_at="[null]"
- />
-
- <issue_changes
- id="101"
- kee="101"
- issue_key="101"
- user_login="arthur"
- change_type="diff"
- change_data="severity=MAJOR|BLOCKER"
- created_at="1410213600000"
- updated_at="1410213600000"
- issue_change_creation_date="1410213600000"
- />
-
- <!-- Closed Issue on a file -->
- <issues
- id="102"
- kee="102"
- component_uuid="uuid-402"
- project_uuid="uuid-399"
- rule_id="501"
- severity="MAJOR"
- manual_severity="[false]"
- message="[null]"
- line="120"
- effort_to_fix="[null]"
- status="CLOSED"
- resolution="FIXED"
- checksum="[null]"
- reporter="[null]"
- assignee="user"
- author_login="[null]"
- issue_attributes="[null]"
- issue_creation_date="1366063200000"
- issue_update_date="1366063200000"
- issue_close_date="1366063200000"
- created_at="1400000000000"
- updated_at="[null]"
- />
-
- <issue_changes
- id="102"
- kee="102"
- issue_key="102"
- user_login="arthur"
- change_type="diff"
- change_data="severity=MAJOR|BLOCKER"
- created_at="1410213600000"
- updated_at="1410213600000"
- issue_change_creation_date="1410213600000"
- />
-
- <!-- Open Issue on a sub module -->
- <issues
- id="103"
- kee="103"
- component_uuid="uuid-400"
- project_uuid="uuid-399"
- rule_id="501"
- severity="MAJOR"
- manual_severity="[false]"
- message="[null]"
- line="[null]"
- effort_to_fix="[null]"
- status="OPEN"
- resolution="[null]"
- checksum="[null]"
- reporter="[null]"
- assignee="user"
- author_login="[null]"
- issue_attributes="[null]"
- issue_creation_date="1366063200000"
- issue_update_date="1366063200000"
- issue_close_date="1366063200000"
- created_at="1400000000000"
- updated_at="[null]"
- />
-
- <issue_changes
- id="103"
- kee="103"
- issue_key="103"
- user_login="arthur"
- change_type="diff"
- change_data="severity=MAJOR|BLOCKER"
- created_at="1410213600000"
- updated_at="1410213600000"
- issue_change_creation_date="1410213600000"
- />
-
- <!-- Open Issue on a root module -->
- <issues
- id="104"
- kee="104"
- component_uuid="uuid-399"
- project_uuid="uuid-399"
- rule_id="501"
- severity="MAJOR"
- manual_severity="[false]"
- message="[null]"
- line="[null]"
- effort_to_fix="[null]"
- status="OPEN"
- resolution="[null]"
- checksum="[null]"
- reporter="[null]"
- assignee="user"
- author_login="[null]"
- issue_attributes="[null]"
- issue_creation_date="1366063200000"
- issue_update_date="1366063200000"
- issue_close_date="1366063200000"
- created_at="1400000000000"
- updated_at="[null]"
- />
-
- <issue_changes
- id="104"
- kee="104"
- issue_key="104"
- user_login="arthur"
- change_type="diff"
- change_data="severity=MAJOR|BLOCKER"
- created_at="1410213600000"
- updated_at="1410213600000"
- issue_change_creation_date="1410213600000"
- />
-
-</dataset>
+++ /dev/null
-<dataset>
-
- <projects id="399" uuid="uuid-399" kee="struts" root_id="[null]" project_uuid="[null]" qualifier="TRK" scope="PRJ" />
-
- <!-- Open Issue on a root module -->
- <issues
- id="104"
- kee="104"
- component_uuid="uuid-399"
- project_uuid="uuid-399"
- rule_id="501"
- severity="MAJOR"
- manual_severity="[false]"
- message="[null]"
- line="[null]"
- effort_to_fix="[null]"
- status="OPEN"
- resolution="[null]"
- checksum="[null]"
- reporter="[null]"
- assignee="user"
- author_login="[null]"
- issue_attributes="[null]"
- issue_creation_date="1366063200000"
- issue_update_date="1366063200000"
- issue_close_date="1366063200000"
- created_at="1400000000000"
- updated_at="[null]"
- />
-
- <issue_changes
- id="1000"
- kee="1000"
- issue_key="104"
- user_login="arthur"
- change_type="diff"
- change_data="severity=MAJOR|BLOCKER"
- created_at="1410386400000"
- updated_at="1410386400000"
- issue_change_creation_date="1410386400000"
- />
-
- <issue_changes
- id="1001"
- kee="1001"
- issue_key="104"
- user_login="arthur"
- change_type="diff"
- change_data="severity=MAJOR|BLOCKER"
- created_at="1410213600000"
- updated_at="1410213600000"
- issue_change_creation_date="1410213600000"
- />
-
- <issue_changes
- id="1002"
- kee="1002"
- issue_key="104"
- user_login="arthur"
- change_type="diff"
- change_data="actionPlan=1.0|1.1"
- created_at="1410300000000"
- updated_at="1410300000000"
- issue_change_creation_date="1410300000000"
- />
-
-</dataset>
*/
package org.sonar.api.batch.rule;
+import java.util.Collection;
+import javax.annotation.CheckForNull;
import org.sonar.api.batch.debt.DebtRemediationFunction;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.RuleStatus;
-import javax.annotation.CheckForNull;
-import java.util.Collection;
-
/**
* @since 4.2
*/
RuleStatus status();
- /**
- * Sub characteristic key.
- *
- * @since 4.3
- */
- @CheckForNull
- String debtSubCharacteristic();
-
/**
* Remediation function : can by Linear (with a coefficient), Linear with offset (with a coefficient and an offset) or Constant per issue (with an offset)
*
private final String severity;
private final String description;
private final String internalKey;
- private final String debtSubCharacteristic;
private final RuleStatus status;
private final DebtRemediationFunction debtRemediationFunction;
private final Map<String, RuleParam> params;
this.description = newRule.description;
this.internalKey = newRule.internalKey;
this.status = newRule.status;
- this.debtSubCharacteristic = newRule.debtSubCharacteristic;
this.debtRemediationFunction = newRule.debtRemediationFunction;
ImmutableMap.Builder<String, RuleParam> builder = ImmutableMap.builder();
return status;
}
- @Override
- public String debtSubCharacteristic() {
- return debtSubCharacteristic;
- }
-
@Override
public DebtRemediationFunction debtRemediationFunction() {
return debtRemediationFunction;
String description;
String severity = DEFAULT_SEVERITY;
String internalKey;
- String debtSubCharacteristic;
DebtRemediationFunction debtRemediationFunction;
RuleStatus status = RuleStatus.defaultStatus();
Map<String, NewRuleParam> params = new HashMap<>();
return this;
}
- public NewRule setDebtSubCharacteristic(@Nullable String c) {
- this.debtSubCharacteristic = c;
- return this;
- }
-
public NewRule setDebtRemediationFunction(@Nullable DebtRemediationFunction f) {
this.debtRemediationFunction = f;
return this;
package org.sonar.api.measures;
import com.google.common.annotations.Beta;
-import org.apache.commons.lang.builder.ReflectionToStringBuilder;
-import org.apache.commons.lang.math.NumberUtils;
-import org.sonar.api.technicaldebt.batch.Characteristic;
-import org.sonar.api.technicaldebt.batch.Requirement;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.apache.commons.lang.builder.ReflectionToStringBuilder;
+import org.apache.commons.lang.math.NumberUtils;
+import org.sonar.api.technicaldebt.batch.Characteristic;
+import org.sonar.api.technicaldebt.batch.Requirement;
/**
* A class to handle measures.
protected Double variation4;
protected Double variation5;
protected String url;
- protected Characteristic characteristic;
- protected Requirement requirement;
protected Integer personId;
protected PersistenceMode persistenceMode = PersistenceMode.FULL;
private boolean fromCore;
*/
@CheckForNull
public final Characteristic getCharacteristic() {
- return characteristic;
+ return null;
}
/**
* @since 4.1
*/
public final Measure<G> setCharacteristic(@Nullable Characteristic characteristic) {
- this.characteristic = characteristic;
return this;
}
@Deprecated
@CheckForNull
public final Requirement getRequirement() {
- return requirement;
+ return null;
}
/**
*/
@Deprecated
public final Measure<G> setRequirement(@Nullable Requirement requirement) {
- this.requirement = requirement;
return this;
}
if (metricKey != null ? !metricKey.equals(measure.metricKey) : (measure.metricKey != null)) {
return false;
}
- if (characteristic != null ? !characteristic.equals(measure.characteristic) : (measure.characteristic != null)) {
- return false;
- }
return !(personId != null ? !personId.equals(measure.personId) : (measure.personId != null));
}
@Override
public int hashCode() {
int result = metricKey != null ? metricKey.hashCode() : 0;
- result = 31 * result + (characteristic != null ? characteristic.hashCode() : 0);
result = 31 * result + (personId != null ? personId.hashCode() : 0);
return result;
}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.api.technicaldebt.batch;
-
-import org.sonar.api.batch.BatchSide;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.technicaldebt.batch.internal.DefaultCharacteristic;
-
-import javax.annotation.CheckForNull;
-
-import java.util.List;
-
-/**
- * @since 4.1
- * @deprecated since 4.3
- */
-@Deprecated
-@BatchSide
-public interface TechnicalDebtModel {
-
- @CheckForNull
- Characteristic characteristicById(Integer id);
-
- @CheckForNull
- Characteristic characteristicByKey(String key);
-
- /**
- * @deprecated since 4.3. Always return null
- */
- @CheckForNull
- @Deprecated
- Requirement requirementsByRule(RuleKey ruleKey);
-
- /**
- * @deprecated since 4.3. Always return null
- */
- @CheckForNull
- @Deprecated
- Requirement requirementsById(Integer id);
-
- /**
- * @deprecated since 4.3. Always return empty list
- */
- @Deprecated
- List<? extends Requirement> requirements();
-
- /**
- * @since 4.3
- */
- List<DefaultCharacteristic> characteristics();
-
-}
newSquid1.setInternalKey("foo=bar");
newSquid1.setSeverity(Severity.CRITICAL);
newSquid1.setStatus(RuleStatus.BETA);
- newSquid1.setDebtSubCharacteristic("COMPILER");
newSquid1.setDebtRemediationFunction(DebtRemediationFunction.create(DebtRemediationFunction.Type.LINEAR_OFFSET, Duration.create(10), Duration.create(60)));
newSquid1.addParam("min");
newSquid1.addParam("max").setDescription("Maximum");
assertThat(squid1.internalKey()).isEqualTo("foo=bar");
assertThat(squid1.status()).isEqualTo(RuleStatus.BETA);
assertThat(squid1.severity()).isEqualTo(Severity.CRITICAL);
- assertThat(squid1.debtSubCharacteristic()).isEqualTo("COMPILER");
assertThat(squid1.debtRemediationFunction().type()).isEqualTo(DebtRemediationFunction.Type.LINEAR_OFFSET);
assertThat(squid1.debtRemediationFunction().coefficient()).isEqualTo(Duration.create(10));
assertThat(squid1.debtRemediationFunction().offset()).isEqualTo(Duration.create(60));
- assertThat(squid1.debtSubCharacteristic()).isEqualTo("COMPILER");
assertThat(squid1.params()).hasSize(2);
assertThat(squid1.param("min").key()).isEqualTo("min");
assertThat(squid1.param("min").description()).isNull();
assertThat(squid2.internalKey()).isNull();
assertThat(squid2.status()).isEqualTo(RuleStatus.defaultStatus());
assertThat(squid2.severity()).isEqualTo(Severity.defaultSeverity());
- assertThat(squid2.debtSubCharacteristic()).isNull();
assertThat(squid2.debtRemediationFunction()).isNull();
assertThat(squid2.params()).isEmpty();
}