@Override
public String getDescription() {
- return "Apply project permissions";
+ return "Apply permissions";
}
}
@Override
public String getDescription() {
- return "Builds the Component tree";
+ return "Build tree of components";
}
}
import org.sonar.server.computation.component.PathAwareCrawler;
import org.sonar.server.computation.component.TreeRootHolder;
import org.sonar.server.computation.formula.Counter;
+import org.sonar.server.computation.formula.CounterInitializationContext;
import org.sonar.server.computation.formula.CreateMeasureContext;
import org.sonar.server.computation.formula.Formula;
import org.sonar.server.computation.formula.FormulaExecutorComponentVisitor;
-import org.sonar.server.computation.formula.CounterInitializationContext;
import org.sonar.server.computation.formula.counter.IntSumCounter;
import org.sonar.server.computation.formula.counter.SumCounter;
import org.sonar.server.computation.measure.Measure;
@Override
public String getDescription() {
- return "Aggregation of comment measures";
+ return "Compute comment measures";
}
}
@Override
public String getDescription() {
- return "Aggregation of complexity measures";
+ return "Compute complexity measures";
}
}
--- /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.step;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.measure.PastMeasureDto;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.component.CrawlerDepthLimit;
+import org.sonar.server.computation.component.DepthTraversalTypeAwareCrawler;
+import org.sonar.server.computation.component.TreeRootHolder;
+import org.sonar.server.computation.component.TypeAwareVisitorAdapter;
+import org.sonar.server.computation.measure.Measure;
+import org.sonar.server.computation.measure.MeasureKey;
+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 com.google.common.collect.FluentIterable.from;
+import static org.sonar.server.computation.component.Component.Type.DIRECTORY;
+import static org.sonar.server.computation.component.Component.Type.SUBVIEW;
+import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;
+
+/**
+ * Set variations on all numeric measures found in the repository.
+ * This step MUST be executed after all steps that create some measures
+ * <p/>
+ * Note that measures on developer are not handle yet.
+ */
+public class ComputeMeasureVariationsStep implements ComputationStep {
+
+ private final DbClient dbClient;
+ private final TreeRootHolder treeRootHolder;
+ private final PeriodsHolder periodsHolder;
+ private final MetricRepository metricRepository;
+ private final MeasureRepository measureRepository;
+
+ private final Function<PastMeasureDto, MeasureKey> pastMeasureToMeasureKey = new Function<PastMeasureDto, MeasureKey>() {
+ @Nullable
+ @Override
+ public MeasureKey apply(@Nonnull PastMeasureDto input) {
+ Metric metric = metricRepository.getById(input.getMetricId());
+ return new MeasureKey(metric.getKey(), input.getCharacteristicId(), input.getRuleId());
+ }
+ };
+
+ public ComputeMeasureVariationsStep(DbClient dbClient, TreeRootHolder treeRootHolder, PeriodsHolder periodsHolder, MetricRepository metricRepository,
+ MeasureRepository measureRepository) {
+ this.dbClient = dbClient;
+ this.treeRootHolder = treeRootHolder;
+ this.periodsHolder = periodsHolder;
+ this.metricRepository = metricRepository;
+ this.measureRepository = measureRepository;
+ }
+
+ @Override
+ public void execute() {
+ DbSession dbSession = dbClient.openSession(false);
+ try {
+ List<Metric> metrics = from(metricRepository.getAll()).filter(NumericMetric.INSTANCE).toList();
+ new DepthTraversalTypeAwareCrawler(new VariationMeasuresVisitor(dbSession, metrics))
+ .visit(treeRootHolder.getRoot());
+ } finally {
+ dbClient.closeSession(dbSession);
+ }
+ }
+
+ private class VariationMeasuresVisitor extends TypeAwareVisitorAdapter {
+
+ private final DbSession session;
+ private final Set<Integer> metricIds;
+ private final Map<String, Metric> metricByKeys;
+
+ public VariationMeasuresVisitor(DbSession session, Iterable<Metric> metrics) {
+ // measures on files are currently purged, so past measures are not available on files
+ super(CrawlerDepthLimit.reportMaxDepth(DIRECTORY).withViewsMaxDepth(SUBVIEW), PRE_ORDER);
+ this.session = session;
+ this.metricIds = from(metrics).transform(MetricDtoToMetricId.INSTANCE).toSet();
+ this.metricByKeys = from(metrics).uniqueIndex(MetricToKey.INSTANCE);
+ }
+
+ @Override
+ public void visitAny(Component component) {
+ MeasuresWithVariationRepository measuresWithVariationRepository = computeMeasuresWithVariations(component);
+ processMeasuresWithVariation(component, measuresWithVariationRepository);
+ }
+
+ private MeasuresWithVariationRepository computeMeasuresWithVariations(Component component) {
+ MeasuresWithVariationRepository measuresWithVariationRepository = new MeasuresWithVariationRepository();
+ for (Period period : periodsHolder.getPeriods()) {
+ List<PastMeasureDto> pastMeasures = dbClient.measureDao()
+ .selectByComponentUuidAndProjectSnapshotIdAndMetricIds(session, component.getUuid(), period.getSnapshotId(), metricIds);
+ setVariationMeasures(component, pastMeasures, period.getIndex(), measuresWithVariationRepository);
+ }
+ return measuresWithVariationRepository;
+ }
+
+ private void processMeasuresWithVariation(Component component, MeasuresWithVariationRepository measuresWithVariationRepository) {
+ for (MeasureWithVariations measureWithVariations : measuresWithVariationRepository.measures()) {
+ Metric metric = measureWithVariations.getMetric();
+ Measure measure = Measure.updatedMeasureBuilder(measureWithVariations.getMeasure())
+ .setVariations(new MeasureVariations(
+ measureWithVariations.getVariation(1),
+ measureWithVariations.getVariation(2),
+ measureWithVariations.getVariation(3),
+ measureWithVariations.getVariation(4),
+ measureWithVariations.getVariation(5)))
+ .create();
+ measureRepository.update(component, metric, measure);
+ }
+ }
+
+ private void setVariationMeasures(Component component, List<PastMeasureDto> pastMeasures, int period, MeasuresWithVariationRepository measuresWithVariationRepository) {
+ Map<MeasureKey, PastMeasureDto> pastMeasuresByMeasureKey = from(pastMeasures).uniqueIndex(pastMeasureToMeasureKey);
+ for (Map.Entry<String, Measure> entry : measureRepository.getRawMeasures(component).entries()) {
+ String metricKey = entry.getKey();
+ Measure measure = entry.getValue();
+ PastMeasureDto pastMeasure = pastMeasuresByMeasureKey.get(new MeasureKey(metricKey, measure.getCharacteristicId(), measure.getRuleId()));
+ if (pastMeasure != null && pastMeasure.hasValue()) {
+ Metric metric = metricByKeys.get(metricKey);
+ measuresWithVariationRepository.add(metric, measure, period, computeVariation(measure, pastMeasure.getValue()));
+ }
+ }
+ }
+ }
+
+ private static double computeVariation(Measure measure, Double pastValue) {
+ switch (measure.getValueType()) {
+ case INT:
+ return measure.getIntValue() - pastValue;
+ case LONG:
+ return measure.getLongValue() - pastValue;
+ case DOUBLE:
+ return measure.getDoubleValue() - pastValue;
+ case BOOLEAN:
+ return (measure.getBooleanValue() ? 1d : 0d) - pastValue;
+ default:
+ throw new IllegalArgumentException("Unsupported Measure.ValueType " + measure.getValueType());
+ }
+ }
+
+ private static final class MeasuresWithVariationRepository {
+
+ private final Map<MeasureKey, MeasureWithVariations> measuresWithVariations = new HashMap<>();
+
+ public void add(Metric metric, final Measure measure, int variationIndex, double variationValue) {
+ MeasureKey measureKey = new MeasureKey(metric.getKey(), measure.getCharacteristicId(), measure.getRuleId());
+ MeasureWithVariations measureWithVariations = measuresWithVariations.get(measureKey);
+ if (measureWithVariations == null) {
+ measureWithVariations = new MeasureWithVariations(metric, measure);
+ measuresWithVariations.put(measureKey, measureWithVariations);
+ }
+ measureWithVariations.setVariation(variationIndex, variationValue);
+ }
+
+ public Collection<MeasureWithVariations> measures() {
+ return measuresWithVariations.values();
+ }
+ }
+
+ private static final class MeasureWithVariations {
+ private final Metric metric;
+ private final Measure measure;
+ private final Double[] variations = new Double[5];
+
+ public MeasureWithVariations(Metric metric, Measure measure) {
+ this.metric = metric;
+ this.measure = measure;
+ }
+
+ public Measure getMeasure() {
+ return measure;
+ }
+
+ public Metric getMetric() {
+ return metric;
+ }
+
+ public void setVariation(int index, @Nullable Double value) {
+ variations[index - 1] = value;
+ }
+
+ @CheckForNull
+ public Double getVariation(int index) {
+ return variations[index - 1];
+ }
+ }
+
+ private enum MetricDtoToMetricId implements Function<Metric, Integer> {
+ INSTANCE;
+
+ @Nullable
+ @Override
+ public Integer apply(@Nonnull Metric metric) {
+ return metric.getId();
+ }
+ }
+
+ private enum MetricToKey implements Function<Metric, String> {
+ INSTANCE;
+
+ @Nullable
+ @Override
+ public String apply(@Nonnull Metric metric) {
+ return metric.getKey();
+ }
+ }
+
+ private enum NumericMetric implements Predicate<Metric> {
+ INSTANCE;
+
+ @Override
+ public boolean apply(@Nonnull Metric metric) {
+ Measure.ValueType valueType = metric.getType().getValueType();
+ return Measure.ValueType.INT.equals(valueType)
+ || Measure.ValueType.LONG.equals(valueType)
+ || Measure.ValueType.DOUBLE.equals(valueType)
+ || Measure.ValueType.BOOLEAN.equals(valueType);
+ }
+ }
+
+ @Override
+ public String getDescription() {
+ return "Compute measure variations";
+ }
+}
@Override
public String getDescription() {
- return "Computes Quality Profile measures";
+ return "Compute Quality Profile measures";
}
}
@Override
public String getDescription() {
- return "Aggregation of coverage measures";
+ return "Compute coverage measures";
}
}
import org.sonar.server.computation.component.PathAwareCrawler;
import org.sonar.server.computation.component.TreeRootHolder;
import org.sonar.server.computation.formula.Counter;
+import org.sonar.server.computation.formula.CounterInitializationContext;
import org.sonar.server.computation.formula.CreateMeasureContext;
import org.sonar.server.computation.formula.Formula;
import org.sonar.server.computation.formula.FormulaExecutorComponentVisitor;
import org.sonar.server.computation.formula.counter.IntSumCounter;
-import org.sonar.server.computation.formula.CounterInitializationContext;
import org.sonar.server.computation.measure.Measure;
import org.sonar.server.computation.measure.MeasureRepository;
import org.sonar.server.computation.metric.Metric;
@Override
public String getDescription() {
- return "Aggregation of duplication measures";
+ return "Compute duplication measures";
}
}
@Override
public String getDescription() {
- return "Execute Visitors";
+ return "Execute visitors";
}
}
--- /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.step;
+
+import java.io.File;
+import java.io.IOException;
+import org.apache.commons.io.FileUtils;
+import org.sonar.api.utils.TempFolder;
+import org.sonar.api.utils.ZipUtils;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.server.computation.CeTask;
+import org.sonar.server.computation.ReportFiles;
+import org.sonar.server.computation.batch.MutableBatchReportDirectoryHolder;
+
+/**
+ * Extracts the content zip file of the {@link org.sonar.server.computation.CeTask} to a temp directory and adds a {@link File}
+ * representing that temp directory to the {@link MutableBatchReportDirectoryHolder}.
+ */
+public class ExtractReportStep implements ComputationStep {
+ private static final Logger LOG = Loggers.get(ExtractReportStep.class);
+
+ private final ReportFiles reportFiles;
+ private final CeTask task;
+ private final TempFolder tempFolder;
+ private final MutableBatchReportDirectoryHolder reportDirectoryHolder;
+
+ public ExtractReportStep(ReportFiles reportFiles, CeTask task, TempFolder tempFolder,
+ MutableBatchReportDirectoryHolder reportDirectoryHolder) {
+ this.reportFiles = reportFiles;
+ this.task = task;
+ this.tempFolder = tempFolder;
+ this.reportDirectoryHolder = reportDirectoryHolder;
+ }
+
+ @Override
+ public void execute() {
+ File dir = tempFolder.newDir();
+ File zip = reportFiles.fileForUuid(task.getUuid());
+ try {
+ ZipUtils.unzip(zip, dir);
+ reportDirectoryHolder.setDirectory(dir);
+ LOG.info("Analysis report extracted | size={} | compressed={}",
+ FileUtils.byteCountToDisplaySize(FileUtils.sizeOf(dir)), FileUtils.byteCountToDisplaySize(FileUtils.sizeOf(zip)));
+ } catch (IOException e) {
+ throw new IllegalStateException(String.format("Fail to unzip %s into %s", zip, dir), e);
+ }
+ }
+
+ @Override
+ public String getDescription() {
+ return "Extract report";
+ }
+
+}
+++ /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.step;
-
-import com.google.common.base.Predicate;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import javax.annotation.Nonnull;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rule.RuleStatus;
-import org.sonar.batch.protocol.output.BatchReport;
-import org.sonar.core.util.CloseableIterator;
-import org.sonar.server.computation.batch.BatchReportReader;
-import org.sonar.server.computation.issue.Rule;
-import org.sonar.server.computation.issue.RuleRepository;
-import org.sonar.server.computation.qualityprofile.ActiveRule;
-import org.sonar.server.computation.qualityprofile.ActiveRulesHolderImpl;
-
-import static com.google.common.collect.FluentIterable.from;
-
-public class FeedActiveRulesStep implements ComputationStep {
-
- private final BatchReportReader batchReportReader;
- private final ActiveRulesHolderImpl activeRulesHolder;
- private final RuleRepository ruleRepository;
-
- public FeedActiveRulesStep(BatchReportReader batchReportReader, ActiveRulesHolderImpl activeRulesHolder, RuleRepository ruleRepository) {
- this.batchReportReader = batchReportReader;
- this.activeRulesHolder = activeRulesHolder;
- this.ruleRepository = ruleRepository;
- }
-
- @Override
- public void execute() {
- List<ActiveRule> activeRules = new ArrayList<>();
- try (CloseableIterator<BatchReport.ActiveRule> batchActiveRules = batchReportReader.readActiveRules()) {
- while (batchActiveRules.hasNext()) {
- BatchReport.ActiveRule batchActiveRule = batchActiveRules.next();
- activeRules.add(convert(batchActiveRule));
- }
- }
-
- List<ActiveRule> validActiveRules = from(activeRules).filter(new IsValid()).toList();
- activeRulesHolder.set(validActiveRules);
- }
-
- private class IsValid implements Predicate<ActiveRule> {
- @Override
- public boolean apply(@Nonnull ActiveRule input) {
- if (ruleRepository.hasKey(input.getRuleKey())) {
- Rule rule = ruleRepository.getByKey(input.getRuleKey());
- return rule.getStatus() != RuleStatus.REMOVED;
- }
- return false;
- }
- }
-
- @Override
- public String getDescription() {
- return getClass().getSimpleName();
- }
-
- private ActiveRule convert(BatchReport.ActiveRule input) {
- RuleKey key = RuleKey.of(input.getRuleRepository(), input.getRuleKey());
- Map<String, String> params = new HashMap<>();
- for (BatchReport.ActiveRule.ActiveRuleParam inputParam : input.getParamList()) {
- params.put(inputParam.getKey(), inputParam.getValue());
- }
- return new ActiveRule(key, input.getSeverity().name(), params);
- }
-}
+++ /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.step;
-
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.debt.CharacteristicDto;
-import org.sonar.server.computation.debt.Characteristic;
-import org.sonar.server.computation.debt.CharacteristicImpl;
-import org.sonar.server.computation.debt.MutableDebtModelHolder;
-
-import static com.google.common.base.Predicates.not;
-import static com.google.common.collect.FluentIterable.from;
-
-/**
- * Populates the {@link org.sonar.server.computation.debt.DebtModelHolder}
- */
-public class FeedDebtModelStep implements ComputationStep {
-
- private final DbClient dbClient;
- private final MutableDebtModelHolder mutableDebtModelHolder;
-
- public FeedDebtModelStep(DbClient dbClient, MutableDebtModelHolder mutableDebtModelHolder) {
- this.dbClient = dbClient;
- this.mutableDebtModelHolder = mutableDebtModelHolder;
- }
-
- @Override
- public void execute() {
- DbSession session = dbClient.openSession(false);
- try {
- feedDebtModel(session);
- } finally {
- session.close();
- }
- }
-
- private void feedDebtModel(DbSession session) {
- List<CharacteristicDto> characteristicDtos = dbClient.debtCharacteristicDao().selectEnabledCharacteristics(session);
- Map<Integer, CharacteristicDto> rootCharacteristicsById = from(characteristicDtos)
- .filter(IsRootPredicate.INSTANCE)
- .uniqueIndex(CharacteristicDtoToId.INSTANCE);
-
- for (Map.Entry<Integer, Collection<CharacteristicDto>> entry : from(characteristicDtos)
- .filter(not(IsRootPredicate.INSTANCE))
- .index(CharacteristicDtoToParentId.INSTANCE)
- .asMap().entrySet()) {
- mutableDebtModelHolder.addCharacteristics(
- toCharacteristic(rootCharacteristicsById.get(entry.getKey())),
- from(entry.getValue()).transform(CharacteristicDtoToCharacteristic.INSTANCE)
- );
- }
- }
-
- private static Characteristic toCharacteristic(CharacteristicDto dto) {
- return new CharacteristicImpl(dto.getId(), dto.getKey(), dto.getParentId());
- }
-
- private enum CharacteristicDtoToId implements Function<CharacteristicDto, Integer> {
- INSTANCE;
-
- @Nullable
- @Override
- public Integer apply(@Nonnull CharacteristicDto dto) {
- return dto.getId();
- }
- }
-
- private enum CharacteristicDtoToCharacteristic implements Function<CharacteristicDto, Characteristic> {
- INSTANCE;
-
- @Nullable
- @Override
- public Characteristic apply(@Nonnull CharacteristicDto characteristicDto) {
- return toCharacteristic(characteristicDto);
- }
- }
-
- private enum CharacteristicDtoToParentId implements Function<CharacteristicDto, Integer> {
- INSTANCE;
-
- @Nullable
- @Override
- public Integer apply(@Nonnull CharacteristicDto characteristicDto) {
- Integer parentId = characteristicDto.getParentId();
- return parentId == null ? characteristicDto.getId() : parentId;
- }
- }
-
- private enum IsRootPredicate implements Predicate<CharacteristicDto> {
- INSTANCE;
-
- @Override
- public boolean apply(@Nonnull CharacteristicDto characteristicDto) {
- return characteristicDto.getParentId() == null;
- }
- }
-
- @Override
- public String getDescription() {
- return "Feed technical debt model";
- }
-}
+++ /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.step;
-
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import org.sonar.api.ce.measure.MeasureComputer;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.measures.Metrics;
-import org.sonar.api.utils.dag.DirectAcyclicGraph;
-import org.sonar.server.computation.measure.MutableMeasureComputersHolder;
-import org.sonar.server.computation.measure.api.MeasureComputerDefinitionImpl;
-import org.sonar.server.computation.measure.api.MeasureComputerWrapper;
-
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.FluentIterable.from;
-import static org.sonar.api.ce.measure.MeasureComputer.MeasureComputerDefinition;
-import static org.sonar.api.ce.measure.MeasureComputer.MeasureComputerDefinitionContext;
-
-public class FeedMeasureComputers implements ComputationStep {
-
- private static final Set<String> CORE_METRIC_KEYS = from(CoreMetrics.getMetrics()).transform(MetricToKey.INSTANCE).toSet();
- private Set<String> pluginMetricKeys;
-
- private final MutableMeasureComputersHolder measureComputersHolder;
- private final MeasureComputer[] measureComputers;
-
- public FeedMeasureComputers(MutableMeasureComputersHolder measureComputersHolder, Metrics[] metricsRepositories, MeasureComputer[] measureComputers) {
- this.measureComputersHolder = measureComputersHolder;
- this.measureComputers = measureComputers;
- this.pluginMetricKeys = from(Arrays.asList(metricsRepositories))
- .transformAndConcat(MetricsToMetricList.INSTANCE)
- .transform(MetricToKey.INSTANCE)
- .toSet();
- }
-
- /**
- * Constructor override used by Pico to instantiate the class when no plugin is defining metrics
- */
- public FeedMeasureComputers(MutableMeasureComputersHolder measureComputersHolder, MeasureComputer[] measureComputers) {
- this(measureComputersHolder, new Metrics[] {}, measureComputers);
- }
-
- /**
- * Constructor override used by Pico to instantiate the class when no plugin is defining measure computers
- */
- public FeedMeasureComputers(MutableMeasureComputersHolder measureComputersHolder, Metrics[] metricsRepositories) {
- this(measureComputersHolder, metricsRepositories, new MeasureComputer[] {});
- }
-
- /**
- * Constructor override used by Pico to instantiate the class when no plugin is defining metrics neither measure computers
- */
- public FeedMeasureComputers(MutableMeasureComputersHolder measureComputersHolder) {
- this(measureComputersHolder, new Metrics[] {}, new MeasureComputer[] {});
- }
-
- @Override
- public void execute() {
- List<MeasureComputerWrapper> wrappers = from(Arrays.asList(measureComputers)).transform(ToMeasureWrapper.INSTANCE).toList();
- validateMetrics(wrappers);
- measureComputersHolder.setMeasureComputers(sortComputers(wrappers));
- }
-
- private static Iterable<MeasureComputerWrapper> sortComputers(List<MeasureComputerWrapper> wrappers) {
- Map<String, MeasureComputerWrapper> computersByOutputMetric = new HashMap<>();
- Map<String, MeasureComputerWrapper> computersByInputMetric = new HashMap<>();
- feedComputersByMetric(wrappers, computersByOutputMetric, computersByInputMetric);
- ToComputerByKey toComputerByOutputMetricKey = new ToComputerByKey(computersByOutputMetric);
- ToComputerByKey toComputerByInputMetricKey = new ToComputerByKey(computersByInputMetric);
-
- DirectAcyclicGraph dag = new DirectAcyclicGraph();
- for (MeasureComputerWrapper computer : wrappers) {
- dag.add(computer);
- for (MeasureComputerWrapper dependency : getDependencies(computer, toComputerByOutputMetricKey)) {
- dag.add(computer, dependency);
- }
- for (MeasureComputerWrapper generates : getDependents(computer, toComputerByInputMetricKey)) {
- dag.add(generates, computer);
- }
- }
- return dag.sort();
- }
-
- private static void feedComputersByMetric(List<MeasureComputerWrapper> wrappers, Map<String, MeasureComputerWrapper> computersByOutputMetric,
- Map<String, MeasureComputerWrapper> computersByInputMetric) {
- for (MeasureComputerWrapper computer : wrappers) {
- for (String outputMetric : computer.getDefinition().getOutputMetrics()) {
- computersByOutputMetric.put(outputMetric, computer);
- }
- for (String inputMetric : computer.getDefinition().getInputMetrics()) {
- computersByInputMetric.put(inputMetric, computer);
- }
- }
- }
-
- private void validateMetrics(List<MeasureComputerWrapper> wrappers) {
- from(wrappers).transformAndConcat(ToInputMetrics.INSTANCE).filter(new ValidateInputMetric()).size();
- from(wrappers).transformAndConcat(ToOutputMetrics.INSTANCE).filter(new ValidateOutputMetric()).size();
- from(wrappers).filter(new ValidateUniqueOutputMetric()).size();
- }
-
- private static Iterable<MeasureComputerWrapper> getDependencies(MeasureComputerWrapper measureComputer, ToComputerByKey toComputerByOutputMetricKey) {
- // Remove null computer because a computer can depend on a metric that is only generated by a sensor or on a core metrics
- return from(measureComputer.getDefinition().getInputMetrics()).transform(toComputerByOutputMetricKey).filter(Predicates.notNull());
- }
-
- private static Iterable<MeasureComputerWrapper> getDependents(MeasureComputerWrapper measureComputer, ToComputerByKey toComputerByInputMetricKey) {
- return from(measureComputer.getDefinition().getInputMetrics()).transform(toComputerByInputMetricKey);
- }
-
- private static class ToComputerByKey implements Function<String, MeasureComputerWrapper> {
- private final Map<String, MeasureComputerWrapper> computersByMetric;
-
- private ToComputerByKey(Map<String, MeasureComputerWrapper> computersByMetric) {
- this.computersByMetric = computersByMetric;
- }
-
- @Override
- public MeasureComputerWrapper apply(@Nonnull String metricKey) {
- return computersByMetric.get(metricKey);
- }
- }
-
- private enum MetricToKey implements Function<Metric, String> {
- INSTANCE;
-
- @Nullable
- @Override
- public String apply(@Nonnull Metric input) {
- return input.key();
- }
- }
-
- private enum MetricsToMetricList implements Function<Metrics, List<Metric>> {
- INSTANCE;
-
- @Override
- public List<Metric> apply(@Nonnull Metrics input) {
- return input.getMetrics();
- }
- }
-
- private enum ToMeasureWrapper implements Function<MeasureComputer, MeasureComputerWrapper> {
- INSTANCE;
-
- private final MeasureComputerDefinitionContextImpl context = new MeasureComputerDefinitionContextImpl();
-
- @Override
- public MeasureComputerWrapper apply(@Nonnull MeasureComputer measureComputer) {
- MeasureComputerDefinition def = measureComputer.define(context);
- return new MeasureComputerWrapper(measureComputer, validateDef(def));
- }
-
- private static MeasureComputerDefinition validateDef(MeasureComputerDefinition def) {
- if (def instanceof MeasureComputerDefinitionImpl) {
- return def;
- }
- // If the computer has not been created by the builder, we recreate it to make sure it's valid
- Set<String> inputMetrics = def.getInputMetrics();
- Set<String> outputMetrics = def.getOutputMetrics();
- return new MeasureComputerDefinitionImpl.BuilderImpl()
- .setInputMetrics(from(inputMetrics).toArray(String.class))
- .setOutputMetrics(from(outputMetrics).toArray(String.class))
- .build();
- }
- }
-
- private enum ToInputMetrics implements Function<MeasureComputerWrapper, Collection<String>> {
- INSTANCE;
-
- @Override
- public Collection<String> apply(@Nonnull MeasureComputerWrapper input) {
- return input.getDefinition().getInputMetrics();
- }
- }
-
- private class ValidateInputMetric implements Predicate<String> {
- @Override
- public boolean apply(@Nonnull String metric) {
- checkState(pluginMetricKeys.contains(metric) || CORE_METRIC_KEYS.contains(metric),
- String.format("Metric '%s' cannot be used as an input metric as it's not a core metric and no plugin declare this metric", metric));
- return true;
- }
- }
-
- private enum ToOutputMetrics implements Function<MeasureComputerWrapper, Collection<String>> {
- INSTANCE;
-
- @Override
- public Collection<String> apply(@Nonnull MeasureComputerWrapper input) {
- return input.getDefinition().getOutputMetrics();
- }
- }
-
- private class ValidateOutputMetric implements Predicate<String> {
- @Override
- public boolean apply(@Nonnull String metric) {
- checkState(!CORE_METRIC_KEYS.contains(metric), String.format("Metric '%s' cannot be used as an output metric as it's a core metric", metric));
- checkState(pluginMetricKeys.contains(metric), String.format("Metric '%s' cannot be used as an output metric as no plugin declare this metric", metric));
- return true;
- }
- }
-
- private static class ValidateUniqueOutputMetric implements Predicate<MeasureComputerWrapper> {
- private Set<String> allOutputMetrics = new HashSet<>();
-
- @Override
- public boolean apply(@Nonnull MeasureComputerWrapper wrapper ) {
- for (String outputMetric : wrapper.getDefinition().getOutputMetrics()) {
- checkState(!allOutputMetrics.contains(outputMetric),
- String.format("Output metric '%s' is already defined by another measure computer '%s'", outputMetric, wrapper.getComputer()));
- allOutputMetrics.add(outputMetric);
- }
- return true;
- }
- }
-
- private static class MeasureComputerDefinitionContextImpl implements MeasureComputerDefinitionContext {
- @Override
- public MeasureComputerDefinition.Builder newDefinitionBuilder() {
- return new MeasureComputerDefinitionImpl.BuilderImpl();
- }
- }
-
- @Override
- public String getDescription() {
- return "Feed measure computers";
- }
-}
+++ /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.step;
-
-import com.google.common.base.Optional;
-import com.google.common.base.Strings;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.config.Settings;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.SnapshotDto;
-import org.sonar.db.component.SnapshotQuery;
-import org.sonar.server.computation.analysis.AnalysisMetadataHolder;
-import org.sonar.server.computation.component.Component;
-import org.sonar.server.computation.component.DepthTraversalTypeAwareCrawler;
-import org.sonar.server.computation.component.SettingsRepository;
-import org.sonar.server.computation.component.TreeRootHolder;
-import org.sonar.server.computation.component.TypeAwareVisitorAdapter;
-import org.sonar.server.computation.period.Period;
-import org.sonar.server.computation.period.PeriodsHolderImpl;
-
-import static org.sonar.db.component.SnapshotQuery.SORT_FIELD.BY_DATE;
-import static org.sonar.db.component.SnapshotQuery.SORT_ORDER.ASC;
-import static org.sonar.db.component.SnapshotQuery.SORT_ORDER.DESC;
-import static org.sonar.server.computation.component.Component.Type.PROJECT;
-import static org.sonar.server.computation.component.Component.Type.VIEW;
-import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;
-import static org.sonar.server.computation.component.CrawlerDepthLimit.reportMaxDepth;
-
-/**
- * Populates the {@link org.sonar.server.computation.period.PeriodsHolder}
- * <p/>
- * Here is how these periods are computed :
- * - Read the 5 period properties ${@link CoreProperties#TIMEMACHINE_PERIOD_PREFIX}
- * - Try to find the matching snapshots from the properties
- * - If a snapshot is found, a new period is added to the repository
- */
-public class FeedPeriodsStep implements ComputationStep {
-
- private static final Logger LOG = Loggers.get(FeedPeriodsStep.class);
-
- private static final int NUMBER_OF_PERIODS = 5;
-
- private final DbClient dbClient;
- private final SettingsRepository settingsRepository;
- private final TreeRootHolder treeRootHolder;
- private final AnalysisMetadataHolder analysisMetadataHolder;
- private final PeriodsHolderImpl periodsHolder;
-
- public FeedPeriodsStep(DbClient dbClient, SettingsRepository settingsRepository, TreeRootHolder treeRootHolder, AnalysisMetadataHolder analysisMetadataHolder,
- PeriodsHolderImpl periodsHolder) {
- this.dbClient = dbClient;
- this.settingsRepository = settingsRepository;
- this.treeRootHolder = treeRootHolder;
- this.analysisMetadataHolder = analysisMetadataHolder;
- this.periodsHolder = periodsHolder;
- }
-
- @Override
- public void execute() {
- new DepthTraversalTypeAwareCrawler(
- new TypeAwareVisitorAdapter(reportMaxDepth(PROJECT).withViewsMaxDepth(VIEW), PRE_ORDER) {
- @Override
- public void visitProject(Component project) {
- execute(project);
- }
-
- @Override
- public void visitView(Component view) {
- execute(view);
- }
- }).visit(treeRootHolder.getRoot());
- }
-
- public void execute(Component projectOrView) {
- DbSession session = dbClient.openSession(false);
- try {
- periodsHolder.setPeriods(buildPeriods(projectOrView, session));
- } finally {
- dbClient.closeSession(session);
- }
- }
-
- private List<Period> buildPeriods(Component projectOrView, DbSession session) {
- Optional<ComponentDto> projectDto = dbClient.componentDao().selectByKey(session, projectOrView.getKey());
- // No project on first analysis, no period
- if (!projectDto.isPresent()) {
- return Collections.emptyList();
- }
-
- boolean isReportType = projectOrView.getType().isReportType();
- PeriodResolver periodResolver = new PeriodResolver(session, projectDto.get().getId(), analysisMetadataHolder.getAnalysisDate().getTime(),
- isReportType ? projectOrView.getReportAttributes().getVersion() : null,
- isReportType ? Qualifiers.PROJECT : Qualifiers.VIEW);
-
- Settings settings = settingsRepository.getSettings(projectOrView);
- List<Period> periods = new ArrayList<>(5);
- for (int index = 1; index <= NUMBER_OF_PERIODS; index++) {
- Period period = periodResolver.resolve(index, settings);
- // SONAR-4700 Add a past snapshot only if it exists
- if (period != null) {
- periods.add(period);
- }
- }
- return periods;
- }
-
- private class PeriodResolver {
-
- private final DbSession session;
- private final long projectId;
- private final long analysisDate;
- @CheckForNull
- private final String currentVersion;
- private final String qualifier;
-
- public PeriodResolver(DbSession session, long projectId, long analysisDate, @Nullable String currentVersion, String qualifier) {
- this.session = session;
- this.projectId = projectId;
- this.analysisDate = analysisDate;
- this.currentVersion = currentVersion;
- this.qualifier = qualifier;
- }
-
- @CheckForNull
- public Period resolve(int index, Settings settings) {
- String propertyValue = getPropertyValue(qualifier, settings, index);
- if (StringUtils.isBlank(propertyValue)) {
- return null;
- }
- Period period = resolve(index, propertyValue);
- if (period == null && StringUtils.isNotBlank(propertyValue)) {
- LOG.debug("Property " + CoreProperties.TIMEMACHINE_PERIOD_PREFIX + index + " is not valid: " + propertyValue);
- }
- return period;
- }
-
- @CheckForNull
- private Period resolve(int index, String property) {
- Integer days = tryToResolveByDays(property);
- if (days != null) {
- return findByDays(index, days);
- }
- Date date = tryToResolveByDate(property);
- if (date != null) {
- return findByDate(index, date);
- }
- if (StringUtils.equals(CoreProperties.TIMEMACHINE_MODE_PREVIOUS_ANALYSIS, property)) {
- return findByPreviousAnalysis(index);
- }
- if (StringUtils.equals(CoreProperties.TIMEMACHINE_MODE_PREVIOUS_VERSION, property)) {
- return findByPreviousVersion(index);
- }
- return findByVersion(index, property);
- }
-
- private Period findByDate(int index, Date date) {
- SnapshotDto snapshot = findFirstSnapshot(session, createCommonQuery(projectId).setCreatedAfter(date.getTime()).setSort(BY_DATE, ASC));
- if (snapshot == null) {
- return null;
- }
- LOG.debug("Compare to date {} (analysis of {})", formatDate(date.getTime()), formatDate(snapshot.getCreatedAt()));
- return new Period(index, CoreProperties.TIMEMACHINE_MODE_DATE, DateUtils.formatDate(date), snapshot.getCreatedAt(), snapshot.getId());
- }
-
- @CheckForNull
- private Period findByDays(int index, int days) {
- List<SnapshotDto> snapshots = dbClient.snapshotDao().selectSnapshotsByQuery(session, createCommonQuery(projectId).setCreatedBefore(analysisDate).setSort(BY_DATE, ASC));
- long targetDate = DateUtils.addDays(new Date(analysisDate), -days).getTime();
- SnapshotDto snapshot = findNearestSnapshotToTargetDate(snapshots, targetDate);
- if (snapshot == null) {
- return null;
- }
- LOG.debug("Compare over {} days ({}, analysis of {})", String.valueOf(days), formatDate(targetDate), formatDate(snapshot.getCreatedAt()));
- return new Period(index, CoreProperties.TIMEMACHINE_MODE_DAYS, String.valueOf(days), snapshot.getCreatedAt(), snapshot.getId());
- }
-
- @CheckForNull
- private Period findByPreviousAnalysis(int index) {
- SnapshotDto snapshot = findFirstSnapshot(session, createCommonQuery(projectId).setCreatedBefore(analysisDate).setIsLast(true).setSort(BY_DATE, DESC));
- if (snapshot == null) {
- return null;
- }
- LOG.debug("Compare to previous analysis ({})", formatDate(snapshot.getCreatedAt()));
- return new Period(index, CoreProperties.TIMEMACHINE_MODE_PREVIOUS_ANALYSIS, formatDate(snapshot.getCreatedAt()), snapshot.getCreatedAt(), snapshot.getId());
- }
-
- @CheckForNull
- private Period findByPreviousVersion(int index) {
- if (currentVersion == null) {
- return null;
- }
- List<SnapshotDto> snapshotDtos = dbClient.snapshotDao().selectPreviousVersionSnapshots(session, projectId, currentVersion);
- if (snapshotDtos.isEmpty()) {
- return null;
- }
- SnapshotDto snapshotDto = snapshotDtos.get(0);
- LOG.debug("Compare to previous version ({})", formatDate(snapshotDto.getCreatedAt()));
- return new Period(index, CoreProperties.TIMEMACHINE_MODE_PREVIOUS_VERSION, snapshotDto.getVersion(), snapshotDto.getCreatedAt(), snapshotDto.getId());
- }
-
- @CheckForNull
- private Period findByVersion(int index, String version) {
- SnapshotDto snapshot = findFirstSnapshot(session, createCommonQuery(projectId).setVersion(version).setSort(BY_DATE, DESC));
- if (snapshot == null) {
- return null;
- }
- LOG.debug("Compare to version ({}) ({})", version, formatDate(snapshot.getCreatedAt()));
- return new Period(index, CoreProperties.TIMEMACHINE_MODE_VERSION, version, snapshot.getCreatedAt(), snapshot.getId());
- }
-
- @CheckForNull
- private SnapshotDto findFirstSnapshot(DbSession session, SnapshotQuery query) {
- List<SnapshotDto> snapshots = dbClient.snapshotDao().selectSnapshotsByQuery(session, query);
- if (!snapshots.isEmpty()) {
- return snapshots.get(0);
- }
- return null;
- }
- }
-
- @CheckForNull
- private static Integer tryToResolveByDays(String property) {
- try {
- return Integer.parseInt(property);
- } catch (NumberFormatException e) {
- // Nothing to, it means that the property is not a number of days
- return null;
- }
- }
-
- @CheckForNull
- private static Date tryToResolveByDate(String property) {
- try {
- return DateUtils.parseDate(property);
- } catch (Exception e) {
- // Nothing to, it means that the property is not a date
- return null;
- }
- }
-
- @CheckForNull
- private static SnapshotDto findNearestSnapshotToTargetDate(List<SnapshotDto> snapshots, Long targetDate) {
- long bestDistance = Long.MAX_VALUE;
- SnapshotDto nearest = null;
- for (SnapshotDto snapshot : snapshots) {
- long distance = Math.abs(snapshot.getCreatedAt() - targetDate);
- if (distance <= bestDistance) {
- bestDistance = distance;
- nearest = snapshot;
- }
- }
- return nearest;
- }
-
- private static SnapshotQuery createCommonQuery(Long projectId) {
- return new SnapshotQuery().setComponentId(projectId).setStatus(SnapshotDto.STATUS_PROCESSED);
- }
-
- private static String formatDate(long date) {
- return DateUtils.formatDate(org.apache.commons.lang.time.DateUtils.truncate(new Date(date), Calendar.SECOND));
- }
-
- private static String getPropertyValue(@Nullable String qualifier, Settings settings, int index) {
- String value = settings.getString(CoreProperties.TIMEMACHINE_PERIOD_PREFIX + index);
- // For periods 4 and 5 we're also searching for a property prefixed by the qualifier
- if (index > 3 && Strings.isNullOrEmpty(value)) {
- value = settings.getString(CoreProperties.TIMEMACHINE_PERIOD_PREFIX + index + "." + qualifier);
- }
- return value;
- }
-
- @Override
- public String getDescription() {
- return "Feed differential periods";
- }
-}
+++ /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.step;
-
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.measure.PastMeasureDto;
-import org.sonar.server.computation.component.Component;
-import org.sonar.server.computation.component.CrawlerDepthLimit;
-import org.sonar.server.computation.component.DepthTraversalTypeAwareCrawler;
-import org.sonar.server.computation.component.TreeRootHolder;
-import org.sonar.server.computation.component.TypeAwareVisitorAdapter;
-import org.sonar.server.computation.measure.Measure;
-import org.sonar.server.computation.measure.MeasureKey;
-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 com.google.common.collect.FluentIterable.from;
-import static org.sonar.server.computation.component.Component.Type.DIRECTORY;
-import static org.sonar.server.computation.component.Component.Type.SUBVIEW;
-import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;
-
-/**
- * Set variations on all numeric measures found in the repository.
- * This step MUST be executed after all steps that create some measures
- * <p/>
- * Note that measures on developer are not handle yet.
- */
-public class FillMeasuresWithVariationsStep implements ComputationStep {
-
- private final DbClient dbClient;
- private final TreeRootHolder treeRootHolder;
- private final PeriodsHolder periodsHolder;
- private final MetricRepository metricRepository;
- private final MeasureRepository measureRepository;
-
- private final Function<PastMeasureDto, MeasureKey> pastMeasureToMeasureKey = new Function<PastMeasureDto, MeasureKey>() {
- @Nullable
- @Override
- public MeasureKey apply(@Nonnull PastMeasureDto input) {
- Metric metric = metricRepository.getById(input.getMetricId());
- return new MeasureKey(metric.getKey(), input.getCharacteristicId(), input.getRuleId());
- }
- };
-
- public FillMeasuresWithVariationsStep(DbClient dbClient, TreeRootHolder treeRootHolder, PeriodsHolder periodsHolder, MetricRepository metricRepository,
- MeasureRepository measureRepository) {
- this.dbClient = dbClient;
- this.treeRootHolder = treeRootHolder;
- this.periodsHolder = periodsHolder;
- this.metricRepository = metricRepository;
- this.measureRepository = measureRepository;
- }
-
- @Override
- public void execute() {
- DbSession dbSession = dbClient.openSession(false);
- try {
- List<Metric> metrics = from(metricRepository.getAll()).filter(NumericMetric.INSTANCE).toList();
- new DepthTraversalTypeAwareCrawler(new VariationMeasuresVisitor(dbSession, metrics))
- .visit(treeRootHolder.getRoot());
- } finally {
- dbClient.closeSession(dbSession);
- }
- }
-
- private class VariationMeasuresVisitor extends TypeAwareVisitorAdapter {
-
- private final DbSession session;
- private final Set<Integer> metricIds;
- private final Map<String, Metric> metricByKeys;
-
- public VariationMeasuresVisitor(DbSession session, Iterable<Metric> metrics) {
- // measures on files are currently purged, so past measures are not available on files
- super(CrawlerDepthLimit.reportMaxDepth(DIRECTORY).withViewsMaxDepth(SUBVIEW), PRE_ORDER);
- this.session = session;
- this.metricIds = from(metrics).transform(MetricDtoToMetricId.INSTANCE).toSet();
- this.metricByKeys = from(metrics).uniqueIndex(MetricToKey.INSTANCE);
- }
-
- @Override
- public void visitAny(Component component) {
- MeasuresWithVariationRepository measuresWithVariationRepository = computeMeasuresWithVariations(component);
- processMeasuresWithVariation(component, measuresWithVariationRepository);
- }
-
- private MeasuresWithVariationRepository computeMeasuresWithVariations(Component component) {
- MeasuresWithVariationRepository measuresWithVariationRepository = new MeasuresWithVariationRepository();
- for (Period period : periodsHolder.getPeriods()) {
- List<PastMeasureDto> pastMeasures = dbClient.measureDao()
- .selectByComponentUuidAndProjectSnapshotIdAndMetricIds(session, component.getUuid(), period.getSnapshotId(), metricIds);
- setVariationMeasures(component, pastMeasures, period.getIndex(), measuresWithVariationRepository);
- }
- return measuresWithVariationRepository;
- }
-
- private void processMeasuresWithVariation(Component component, MeasuresWithVariationRepository measuresWithVariationRepository) {
- for (MeasureWithVariations measureWithVariations : measuresWithVariationRepository.measures()) {
- Metric metric = measureWithVariations.getMetric();
- Measure measure = Measure.updatedMeasureBuilder(measureWithVariations.getMeasure())
- .setVariations(new MeasureVariations(
- measureWithVariations.getVariation(1),
- measureWithVariations.getVariation(2),
- measureWithVariations.getVariation(3),
- measureWithVariations.getVariation(4),
- measureWithVariations.getVariation(5)))
- .create();
- measureRepository.update(component, metric, measure);
- }
- }
-
- private void setVariationMeasures(Component component, List<PastMeasureDto> pastMeasures, int period, MeasuresWithVariationRepository measuresWithVariationRepository) {
- Map<MeasureKey, PastMeasureDto> pastMeasuresByMeasureKey = from(pastMeasures).uniqueIndex(pastMeasureToMeasureKey);
- for (Map.Entry<String, Measure> entry : measureRepository.getRawMeasures(component).entries()) {
- String metricKey = entry.getKey();
- Measure measure = entry.getValue();
- PastMeasureDto pastMeasure = pastMeasuresByMeasureKey.get(new MeasureKey(metricKey, measure.getCharacteristicId(), measure.getRuleId()));
- if (pastMeasure != null && pastMeasure.hasValue()) {
- Metric metric = metricByKeys.get(metricKey);
- measuresWithVariationRepository.add(metric, measure, period, computeVariation(measure, pastMeasure.getValue()));
- }
- }
- }
- }
-
- private static double computeVariation(Measure measure, Double pastValue) {
- switch (measure.getValueType()) {
- case INT:
- return measure.getIntValue() - pastValue;
- case LONG:
- return measure.getLongValue() - pastValue;
- case DOUBLE:
- return measure.getDoubleValue() - pastValue;
- case BOOLEAN:
- return (measure.getBooleanValue() ? 1d : 0d) - pastValue;
- default:
- throw new IllegalArgumentException("Unsupported Measure.ValueType " + measure.getValueType());
- }
- }
-
- private static final class MeasuresWithVariationRepository {
-
- private final Map<MeasureKey, MeasureWithVariations> measuresWithVariations = new HashMap<>();
-
- public void add(Metric metric, final Measure measure, int variationIndex, double variationValue) {
- MeasureKey measureKey = new MeasureKey(metric.getKey(), measure.getCharacteristicId(), measure.getRuleId());
- MeasureWithVariations measureWithVariations = measuresWithVariations.get(measureKey);
- if (measureWithVariations == null) {
- measureWithVariations = new MeasureWithVariations(metric, measure);
- measuresWithVariations.put(measureKey, measureWithVariations);
- }
- measureWithVariations.setVariation(variationIndex, variationValue);
- }
-
- public Collection<MeasureWithVariations> measures() {
- return measuresWithVariations.values();
- }
- }
-
- private static final class MeasureWithVariations {
- private final Metric metric;
- private final Measure measure;
- private final Double[] variations = new Double[5];
-
- public MeasureWithVariations(Metric metric, Measure measure) {
- this.metric = metric;
- this.measure = measure;
- }
-
- public Measure getMeasure() {
- return measure;
- }
-
- public Metric getMetric() {
- return metric;
- }
-
- public void setVariation(int index, @Nullable Double value) {
- variations[index - 1] = value;
- }
-
- @CheckForNull
- public Double getVariation(int index) {
- return variations[index - 1];
- }
- }
-
- private enum MetricDtoToMetricId implements Function<Metric, Integer> {
- INSTANCE;
-
- @Nullable
- @Override
- public Integer apply(@Nonnull Metric metric) {
- return metric.getId();
- }
- }
-
- private enum MetricToKey implements Function<Metric, String> {
- INSTANCE;
-
- @Nullable
- @Override
- public String apply(@Nonnull Metric metric) {
- return metric.getKey();
- }
- }
-
- private enum NumericMetric implements Predicate<Metric> {
- INSTANCE;
-
- @Override
- public boolean apply(@Nonnull Metric metric) {
- Measure.ValueType valueType = metric.getType().getValueType();
- return Measure.ValueType.INT.equals(valueType)
- || Measure.ValueType.LONG.equals(valueType)
- || Measure.ValueType.DOUBLE.equals(valueType)
- || Measure.ValueType.BOOLEAN.equals(valueType);
- }
- }
-
- @Override
- public String getDescription() {
- return "Compute differential measures";
- }
-}
@Override
public String getDescription() {
- return "Compute language distribution measures";
+ return "Compute language distribution";
}
}
--- /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.step;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.debt.CharacteristicDto;
+import org.sonar.server.computation.debt.Characteristic;
+import org.sonar.server.computation.debt.CharacteristicImpl;
+import org.sonar.server.computation.debt.MutableDebtModelHolder;
+
+import static com.google.common.base.Predicates.not;
+import static com.google.common.collect.FluentIterable.from;
+
+/**
+ * Populates the {@link org.sonar.server.computation.debt.DebtModelHolder}
+ */
+public class LoadDebtModelStep implements ComputationStep {
+
+ private final DbClient dbClient;
+ private final MutableDebtModelHolder mutableDebtModelHolder;
+
+ public LoadDebtModelStep(DbClient dbClient, MutableDebtModelHolder mutableDebtModelHolder) {
+ this.dbClient = dbClient;
+ this.mutableDebtModelHolder = mutableDebtModelHolder;
+ }
+
+ @Override
+ public void execute() {
+ DbSession session = dbClient.openSession(false);
+ try {
+ feedDebtModel(session);
+ } finally {
+ session.close();
+ }
+ }
+
+ private void feedDebtModel(DbSession session) {
+ List<CharacteristicDto> characteristicDtos = dbClient.debtCharacteristicDao().selectEnabledCharacteristics(session);
+ Map<Integer, CharacteristicDto> rootCharacteristicsById = from(characteristicDtos)
+ .filter(IsRootPredicate.INSTANCE)
+ .uniqueIndex(CharacteristicDtoToId.INSTANCE);
+
+ for (Map.Entry<Integer, Collection<CharacteristicDto>> entry : from(characteristicDtos)
+ .filter(not(IsRootPredicate.INSTANCE))
+ .index(CharacteristicDtoToParentId.INSTANCE)
+ .asMap().entrySet()) {
+ mutableDebtModelHolder.addCharacteristics(
+ toCharacteristic(rootCharacteristicsById.get(entry.getKey())),
+ from(entry.getValue()).transform(CharacteristicDtoToCharacteristic.INSTANCE)
+ );
+ }
+ }
+
+ private static Characteristic toCharacteristic(CharacteristicDto dto) {
+ return new CharacteristicImpl(dto.getId(), dto.getKey(), dto.getParentId());
+ }
+
+ private enum CharacteristicDtoToId implements Function<CharacteristicDto, Integer> {
+ INSTANCE;
+
+ @Nullable
+ @Override
+ public Integer apply(@Nonnull CharacteristicDto dto) {
+ return dto.getId();
+ }
+ }
+
+ private enum CharacteristicDtoToCharacteristic implements Function<CharacteristicDto, Characteristic> {
+ INSTANCE;
+
+ @Nullable
+ @Override
+ public Characteristic apply(@Nonnull CharacteristicDto characteristicDto) {
+ return toCharacteristic(characteristicDto);
+ }
+ }
+
+ private enum CharacteristicDtoToParentId implements Function<CharacteristicDto, Integer> {
+ INSTANCE;
+
+ @Nullable
+ @Override
+ public Integer apply(@Nonnull CharacteristicDto characteristicDto) {
+ Integer parentId = characteristicDto.getParentId();
+ return parentId == null ? characteristicDto.getId() : parentId;
+ }
+ }
+
+ private enum IsRootPredicate implements Predicate<CharacteristicDto> {
+ INSTANCE;
+
+ @Override
+ public boolean apply(@Nonnull CharacteristicDto characteristicDto) {
+ return characteristicDto.getParentId() == null;
+ }
+ }
+
+ @Override
+ public String getDescription() {
+ return "Load debt model";
+ }
+}
--- /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.step;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.sonar.api.ce.measure.MeasureComputer;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.measures.Metrics;
+import org.sonar.api.utils.dag.DirectAcyclicGraph;
+import org.sonar.server.computation.measure.MutableMeasureComputersHolder;
+import org.sonar.server.computation.measure.api.MeasureComputerDefinitionImpl;
+import org.sonar.server.computation.measure.api.MeasureComputerWrapper;
+
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.FluentIterable.from;
+import static org.sonar.api.ce.measure.MeasureComputer.MeasureComputerDefinition;
+import static org.sonar.api.ce.measure.MeasureComputer.MeasureComputerDefinitionContext;
+
+public class LoadMeasureComputersStep implements ComputationStep {
+
+ private static final Set<String> CORE_METRIC_KEYS = from(CoreMetrics.getMetrics()).transform(MetricToKey.INSTANCE).toSet();
+ private Set<String> pluginMetricKeys;
+
+ private final MutableMeasureComputersHolder measureComputersHolder;
+ private final MeasureComputer[] measureComputers;
+
+ public LoadMeasureComputersStep(MutableMeasureComputersHolder measureComputersHolder, Metrics[] metricsRepositories, MeasureComputer[] measureComputers) {
+ this.measureComputersHolder = measureComputersHolder;
+ this.measureComputers = measureComputers;
+ this.pluginMetricKeys = from(Arrays.asList(metricsRepositories))
+ .transformAndConcat(MetricsToMetricList.INSTANCE)
+ .transform(MetricToKey.INSTANCE)
+ .toSet();
+ }
+
+ /**
+ * Constructor override used by Pico to instantiate the class when no plugin is defining metrics
+ */
+ public LoadMeasureComputersStep(MutableMeasureComputersHolder measureComputersHolder, MeasureComputer[] measureComputers) {
+ this(measureComputersHolder, new Metrics[] {}, measureComputers);
+ }
+
+ /**
+ * Constructor override used by Pico to instantiate the class when no plugin is defining measure computers
+ */
+ public LoadMeasureComputersStep(MutableMeasureComputersHolder measureComputersHolder, Metrics[] metricsRepositories) {
+ this(measureComputersHolder, metricsRepositories, new MeasureComputer[] {});
+ }
+
+ /**
+ * Constructor override used by Pico to instantiate the class when no plugin is defining metrics neither measure computers
+ */
+ public LoadMeasureComputersStep(MutableMeasureComputersHolder measureComputersHolder) {
+ this(measureComputersHolder, new Metrics[] {}, new MeasureComputer[] {});
+ }
+
+ @Override
+ public void execute() {
+ List<MeasureComputerWrapper> wrappers = from(Arrays.asList(measureComputers)).transform(ToMeasureWrapper.INSTANCE).toList();
+ validateMetrics(wrappers);
+ measureComputersHolder.setMeasureComputers(sortComputers(wrappers));
+ }
+
+ private static Iterable<MeasureComputerWrapper> sortComputers(List<MeasureComputerWrapper> wrappers) {
+ Map<String, MeasureComputerWrapper> computersByOutputMetric = new HashMap<>();
+ Map<String, MeasureComputerWrapper> computersByInputMetric = new HashMap<>();
+ feedComputersByMetric(wrappers, computersByOutputMetric, computersByInputMetric);
+ ToComputerByKey toComputerByOutputMetricKey = new ToComputerByKey(computersByOutputMetric);
+ ToComputerByKey toComputerByInputMetricKey = new ToComputerByKey(computersByInputMetric);
+
+ DirectAcyclicGraph dag = new DirectAcyclicGraph();
+ for (MeasureComputerWrapper computer : wrappers) {
+ dag.add(computer);
+ for (MeasureComputerWrapper dependency : getDependencies(computer, toComputerByOutputMetricKey)) {
+ dag.add(computer, dependency);
+ }
+ for (MeasureComputerWrapper generates : getDependents(computer, toComputerByInputMetricKey)) {
+ dag.add(generates, computer);
+ }
+ }
+ return dag.sort();
+ }
+
+ private static void feedComputersByMetric(List<MeasureComputerWrapper> wrappers, Map<String, MeasureComputerWrapper> computersByOutputMetric,
+ Map<String, MeasureComputerWrapper> computersByInputMetric) {
+ for (MeasureComputerWrapper computer : wrappers) {
+ for (String outputMetric : computer.getDefinition().getOutputMetrics()) {
+ computersByOutputMetric.put(outputMetric, computer);
+ }
+ for (String inputMetric : computer.getDefinition().getInputMetrics()) {
+ computersByInputMetric.put(inputMetric, computer);
+ }
+ }
+ }
+
+ private void validateMetrics(List<MeasureComputerWrapper> wrappers) {
+ from(wrappers).transformAndConcat(ToInputMetrics.INSTANCE).filter(new ValidateInputMetric()).size();
+ from(wrappers).transformAndConcat(ToOutputMetrics.INSTANCE).filter(new ValidateOutputMetric()).size();
+ from(wrappers).filter(new ValidateUniqueOutputMetric()).size();
+ }
+
+ private static Iterable<MeasureComputerWrapper> getDependencies(MeasureComputerWrapper measureComputer, ToComputerByKey toComputerByOutputMetricKey) {
+ // Remove null computer because a computer can depend on a metric that is only generated by a sensor or on a core metrics
+ return from(measureComputer.getDefinition().getInputMetrics()).transform(toComputerByOutputMetricKey).filter(Predicates.notNull());
+ }
+
+ private static Iterable<MeasureComputerWrapper> getDependents(MeasureComputerWrapper measureComputer, ToComputerByKey toComputerByInputMetricKey) {
+ return from(measureComputer.getDefinition().getInputMetrics()).transform(toComputerByInputMetricKey);
+ }
+
+ private static class ToComputerByKey implements Function<String, MeasureComputerWrapper> {
+ private final Map<String, MeasureComputerWrapper> computersByMetric;
+
+ private ToComputerByKey(Map<String, MeasureComputerWrapper> computersByMetric) {
+ this.computersByMetric = computersByMetric;
+ }
+
+ @Override
+ public MeasureComputerWrapper apply(@Nonnull String metricKey) {
+ return computersByMetric.get(metricKey);
+ }
+ }
+
+ private enum MetricToKey implements Function<Metric, String> {
+ INSTANCE;
+
+ @Nullable
+ @Override
+ public String apply(@Nonnull Metric input) {
+ return input.key();
+ }
+ }
+
+ private enum MetricsToMetricList implements Function<Metrics, List<Metric>> {
+ INSTANCE;
+
+ @Override
+ public List<Metric> apply(@Nonnull Metrics input) {
+ return input.getMetrics();
+ }
+ }
+
+ private enum ToMeasureWrapper implements Function<MeasureComputer, MeasureComputerWrapper> {
+ INSTANCE;
+
+ private final MeasureComputerDefinitionContextImpl context = new MeasureComputerDefinitionContextImpl();
+
+ @Override
+ public MeasureComputerWrapper apply(@Nonnull MeasureComputer measureComputer) {
+ MeasureComputerDefinition def = measureComputer.define(context);
+ return new MeasureComputerWrapper(measureComputer, validateDef(def));
+ }
+
+ private static MeasureComputerDefinition validateDef(MeasureComputerDefinition def) {
+ if (def instanceof MeasureComputerDefinitionImpl) {
+ return def;
+ }
+ // If the computer has not been created by the builder, we recreate it to make sure it's valid
+ Set<String> inputMetrics = def.getInputMetrics();
+ Set<String> outputMetrics = def.getOutputMetrics();
+ return new MeasureComputerDefinitionImpl.BuilderImpl()
+ .setInputMetrics(from(inputMetrics).toArray(String.class))
+ .setOutputMetrics(from(outputMetrics).toArray(String.class))
+ .build();
+ }
+ }
+
+ private enum ToInputMetrics implements Function<MeasureComputerWrapper, Collection<String>> {
+ INSTANCE;
+
+ @Override
+ public Collection<String> apply(@Nonnull MeasureComputerWrapper input) {
+ return input.getDefinition().getInputMetrics();
+ }
+ }
+
+ private class ValidateInputMetric implements Predicate<String> {
+ @Override
+ public boolean apply(@Nonnull String metric) {
+ checkState(pluginMetricKeys.contains(metric) || CORE_METRIC_KEYS.contains(metric),
+ String.format("Metric '%s' cannot be used as an input metric as it's not a core metric and no plugin declare this metric", metric));
+ return true;
+ }
+ }
+
+ private enum ToOutputMetrics implements Function<MeasureComputerWrapper, Collection<String>> {
+ INSTANCE;
+
+ @Override
+ public Collection<String> apply(@Nonnull MeasureComputerWrapper input) {
+ return input.getDefinition().getOutputMetrics();
+ }
+ }
+
+ private class ValidateOutputMetric implements Predicate<String> {
+ @Override
+ public boolean apply(@Nonnull String metric) {
+ checkState(!CORE_METRIC_KEYS.contains(metric), String.format("Metric '%s' cannot be used as an output metric as it's a core metric", metric));
+ checkState(pluginMetricKeys.contains(metric), String.format("Metric '%s' cannot be used as an output metric as no plugin declare this metric", metric));
+ return true;
+ }
+ }
+
+ private static class ValidateUniqueOutputMetric implements Predicate<MeasureComputerWrapper> {
+ private Set<String> allOutputMetrics = new HashSet<>();
+
+ @Override
+ public boolean apply(@Nonnull MeasureComputerWrapper wrapper ) {
+ for (String outputMetric : wrapper.getDefinition().getOutputMetrics()) {
+ checkState(!allOutputMetrics.contains(outputMetric),
+ String.format("Output metric '%s' is already defined by another measure computer '%s'", outputMetric, wrapper.getComputer()));
+ allOutputMetrics.add(outputMetric);
+ }
+ return true;
+ }
+ }
+
+ private static class MeasureComputerDefinitionContextImpl implements MeasureComputerDefinitionContext {
+ @Override
+ public MeasureComputerDefinition.Builder newDefinitionBuilder() {
+ return new MeasureComputerDefinitionImpl.BuilderImpl();
+ }
+ }
+
+ @Override
+ public String getDescription() {
+ return "Load measure computers";
+ }
+}
--- /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.step;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Strings;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Settings;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.SnapshotDto;
+import org.sonar.db.component.SnapshotQuery;
+import org.sonar.server.computation.analysis.AnalysisMetadataHolder;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.component.DepthTraversalTypeAwareCrawler;
+import org.sonar.server.computation.component.SettingsRepository;
+import org.sonar.server.computation.component.TreeRootHolder;
+import org.sonar.server.computation.component.TypeAwareVisitorAdapter;
+import org.sonar.server.computation.period.Period;
+import org.sonar.server.computation.period.PeriodsHolderImpl;
+
+import static org.sonar.db.component.SnapshotQuery.SORT_FIELD.BY_DATE;
+import static org.sonar.db.component.SnapshotQuery.SORT_ORDER.ASC;
+import static org.sonar.db.component.SnapshotQuery.SORT_ORDER.DESC;
+import static org.sonar.server.computation.component.Component.Type.PROJECT;
+import static org.sonar.server.computation.component.Component.Type.VIEW;
+import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;
+import static org.sonar.server.computation.component.CrawlerDepthLimit.reportMaxDepth;
+
+/**
+ * Populates the {@link org.sonar.server.computation.period.PeriodsHolder}
+ * <p/>
+ * Here is how these periods are computed :
+ * - Read the 5 period properties ${@link CoreProperties#TIMEMACHINE_PERIOD_PREFIX}
+ * - Try to find the matching snapshots from the properties
+ * - If a snapshot is found, a new period is added to the repository
+ */
+public class LoadPeriodsStep implements ComputationStep {
+
+ private static final Logger LOG = Loggers.get(LoadPeriodsStep.class);
+
+ private static final int NUMBER_OF_PERIODS = 5;
+
+ private final DbClient dbClient;
+ private final SettingsRepository settingsRepository;
+ private final TreeRootHolder treeRootHolder;
+ private final AnalysisMetadataHolder analysisMetadataHolder;
+ private final PeriodsHolderImpl periodsHolder;
+
+ public LoadPeriodsStep(DbClient dbClient, SettingsRepository settingsRepository, TreeRootHolder treeRootHolder, AnalysisMetadataHolder analysisMetadataHolder,
+ PeriodsHolderImpl periodsHolder) {
+ this.dbClient = dbClient;
+ this.settingsRepository = settingsRepository;
+ this.treeRootHolder = treeRootHolder;
+ this.analysisMetadataHolder = analysisMetadataHolder;
+ this.periodsHolder = periodsHolder;
+ }
+
+ @Override
+ public void execute() {
+ new DepthTraversalTypeAwareCrawler(
+ new TypeAwareVisitorAdapter(reportMaxDepth(PROJECT).withViewsMaxDepth(VIEW), PRE_ORDER) {
+ @Override
+ public void visitProject(Component project) {
+ execute(project);
+ }
+
+ @Override
+ public void visitView(Component view) {
+ execute(view);
+ }
+ }).visit(treeRootHolder.getRoot());
+ }
+
+ public void execute(Component projectOrView) {
+ DbSession session = dbClient.openSession(false);
+ try {
+ periodsHolder.setPeriods(buildPeriods(projectOrView, session));
+ } finally {
+ dbClient.closeSession(session);
+ }
+ }
+
+ private List<Period> buildPeriods(Component projectOrView, DbSession session) {
+ Optional<ComponentDto> projectDto = dbClient.componentDao().selectByKey(session, projectOrView.getKey());
+ // No project on first analysis, no period
+ if (!projectDto.isPresent()) {
+ return Collections.emptyList();
+ }
+
+ boolean isReportType = projectOrView.getType().isReportType();
+ PeriodResolver periodResolver = new PeriodResolver(session, projectDto.get().getId(), analysisMetadataHolder.getAnalysisDate().getTime(),
+ isReportType ? projectOrView.getReportAttributes().getVersion() : null,
+ isReportType ? Qualifiers.PROJECT : Qualifiers.VIEW);
+
+ Settings settings = settingsRepository.getSettings(projectOrView);
+ List<Period> periods = new ArrayList<>(5);
+ for (int index = 1; index <= NUMBER_OF_PERIODS; index++) {
+ Period period = periodResolver.resolve(index, settings);
+ // SONAR-4700 Add a past snapshot only if it exists
+ if (period != null) {
+ periods.add(period);
+ }
+ }
+ return periods;
+ }
+
+ private class PeriodResolver {
+
+ private final DbSession session;
+ private final long projectId;
+ private final long analysisDate;
+ @CheckForNull
+ private final String currentVersion;
+ private final String qualifier;
+
+ public PeriodResolver(DbSession session, long projectId, long analysisDate, @Nullable String currentVersion, String qualifier) {
+ this.session = session;
+ this.projectId = projectId;
+ this.analysisDate = analysisDate;
+ this.currentVersion = currentVersion;
+ this.qualifier = qualifier;
+ }
+
+ @CheckForNull
+ public Period resolve(int index, Settings settings) {
+ String propertyValue = getPropertyValue(qualifier, settings, index);
+ if (StringUtils.isBlank(propertyValue)) {
+ return null;
+ }
+ Period period = resolve(index, propertyValue);
+ if (period == null && StringUtils.isNotBlank(propertyValue)) {
+ LOG.debug("Property " + CoreProperties.TIMEMACHINE_PERIOD_PREFIX + index + " is not valid: " + propertyValue);
+ }
+ return period;
+ }
+
+ @CheckForNull
+ private Period resolve(int index, String property) {
+ Integer days = tryToResolveByDays(property);
+ if (days != null) {
+ return findByDays(index, days);
+ }
+ Date date = DateUtils.parseDateQuietly(property);
+ if (date != null) {
+ return findByDate(index, date);
+ }
+ if (StringUtils.equals(CoreProperties.TIMEMACHINE_MODE_PREVIOUS_ANALYSIS, property)) {
+ return findByPreviousAnalysis(index);
+ }
+ if (StringUtils.equals(CoreProperties.TIMEMACHINE_MODE_PREVIOUS_VERSION, property)) {
+ return findByPreviousVersion(index);
+ }
+ return findByVersion(index, property);
+ }
+
+ private Period findByDate(int index, Date date) {
+ SnapshotDto snapshot = findFirstSnapshot(session, createCommonQuery(projectId).setCreatedAfter(date.getTime()).setSort(BY_DATE, ASC));
+ if (snapshot == null) {
+ return null;
+ }
+ LOG.debug("Compare to date {} (analysis of {})", formatDate(date.getTime()), formatDate(snapshot.getCreatedAt()));
+ return new Period(index, CoreProperties.TIMEMACHINE_MODE_DATE, DateUtils.formatDate(date), snapshot.getCreatedAt(), snapshot.getId());
+ }
+
+ @CheckForNull
+ private Period findByDays(int index, int days) {
+ List<SnapshotDto> snapshots = dbClient.snapshotDao().selectSnapshotsByQuery(session, createCommonQuery(projectId).setCreatedBefore(analysisDate).setSort(BY_DATE, ASC));
+ long targetDate = DateUtils.addDays(new Date(analysisDate), -days).getTime();
+ SnapshotDto snapshot = findNearestSnapshotToTargetDate(snapshots, targetDate);
+ if (snapshot == null) {
+ return null;
+ }
+ LOG.debug("Compare over {} days ({}, analysis of {})", String.valueOf(days), formatDate(targetDate), formatDate(snapshot.getCreatedAt()));
+ return new Period(index, CoreProperties.TIMEMACHINE_MODE_DAYS, String.valueOf(days), snapshot.getCreatedAt(), snapshot.getId());
+ }
+
+ @CheckForNull
+ private Period findByPreviousAnalysis(int index) {
+ SnapshotDto snapshot = findFirstSnapshot(session, createCommonQuery(projectId).setCreatedBefore(analysisDate).setIsLast(true).setSort(BY_DATE, DESC));
+ if (snapshot == null) {
+ return null;
+ }
+ LOG.debug("Compare to previous analysis ({})", formatDate(snapshot.getCreatedAt()));
+ return new Period(index, CoreProperties.TIMEMACHINE_MODE_PREVIOUS_ANALYSIS, formatDate(snapshot.getCreatedAt()), snapshot.getCreatedAt(), snapshot.getId());
+ }
+
+ @CheckForNull
+ private Period findByPreviousVersion(int index) {
+ if (currentVersion == null) {
+ return null;
+ }
+ List<SnapshotDto> snapshotDtos = dbClient.snapshotDao().selectPreviousVersionSnapshots(session, projectId, currentVersion);
+ if (snapshotDtos.isEmpty()) {
+ return null;
+ }
+ SnapshotDto snapshotDto = snapshotDtos.get(0);
+ LOG.debug("Compare to previous version ({})", formatDate(snapshotDto.getCreatedAt()));
+ return new Period(index, CoreProperties.TIMEMACHINE_MODE_PREVIOUS_VERSION, snapshotDto.getVersion(), snapshotDto.getCreatedAt(), snapshotDto.getId());
+ }
+
+ @CheckForNull
+ private Period findByVersion(int index, String version) {
+ SnapshotDto snapshot = findFirstSnapshot(session, createCommonQuery(projectId).setVersion(version).setSort(BY_DATE, DESC));
+ if (snapshot == null) {
+ return null;
+ }
+ LOG.debug("Compare to version ({}) ({})", version, formatDate(snapshot.getCreatedAt()));
+ return new Period(index, CoreProperties.TIMEMACHINE_MODE_VERSION, version, snapshot.getCreatedAt(), snapshot.getId());
+ }
+
+ @CheckForNull
+ private SnapshotDto findFirstSnapshot(DbSession session, SnapshotQuery query) {
+ List<SnapshotDto> snapshots = dbClient.snapshotDao().selectSnapshotsByQuery(session, query);
+ if (!snapshots.isEmpty()) {
+ return snapshots.get(0);
+ }
+ return null;
+ }
+ }
+
+ @CheckForNull
+ private static Integer tryToResolveByDays(String property) {
+ try {
+ return Integer.parseInt(property);
+ } catch (NumberFormatException e) {
+ // Nothing to, it means that the property is not a number of days
+ return null;
+ }
+ }
+
+ @CheckForNull
+ private static SnapshotDto findNearestSnapshotToTargetDate(List<SnapshotDto> snapshots, Long targetDate) {
+ long bestDistance = Long.MAX_VALUE;
+ SnapshotDto nearest = null;
+ for (SnapshotDto snapshot : snapshots) {
+ long distance = Math.abs(snapshot.getCreatedAt() - targetDate);
+ if (distance <= bestDistance) {
+ bestDistance = distance;
+ nearest = snapshot;
+ }
+ }
+ return nearest;
+ }
+
+ private static SnapshotQuery createCommonQuery(Long projectId) {
+ return new SnapshotQuery().setComponentId(projectId).setStatus(SnapshotDto.STATUS_PROCESSED);
+ }
+
+ private static String formatDate(long date) {
+ return DateUtils.formatDate(org.apache.commons.lang.time.DateUtils.truncate(new Date(date), Calendar.SECOND));
+ }
+
+ private static String getPropertyValue(@Nullable String qualifier, Settings settings, int index) {
+ String value = settings.getString(CoreProperties.TIMEMACHINE_PERIOD_PREFIX + index);
+ // For periods 4 and 5 we're also searching for a property prefixed by the qualifier
+ if (index > 3 && Strings.isNullOrEmpty(value)) {
+ value = settings.getString(CoreProperties.TIMEMACHINE_PERIOD_PREFIX + index + "." + qualifier);
+ }
+ return value;
+ }
+
+ @Override
+ public String getDescription() {
+ return "Load differential periods";
+ }
+}
--- /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.step;
+
+import com.google.common.base.Optional;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.config.Settings;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.component.CrawlerDepthLimit;
+import org.sonar.server.computation.component.DepthTraversalTypeAwareCrawler;
+import org.sonar.server.computation.component.SettingsRepository;
+import org.sonar.server.computation.component.TreeRootHolder;
+import org.sonar.server.computation.component.TypeAwareVisitorAdapter;
+import org.sonar.server.computation.qualitygate.MutableQualityGateHolder;
+import org.sonar.server.computation.qualitygate.QualityGate;
+import org.sonar.server.computation.qualitygate.QualityGateService;
+
+import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;
+
+/**
+ * This step retrieves the QualityGate and stores it in
+ * {@link MutableQualityGateHolder}.
+ */
+public class LoadQualityGateStep implements ComputationStep {
+ private static final Logger LOGGER = Loggers.get(LoadQualityGateStep.class);
+
+ private static final String PROPERTY_QUALITY_GATE = "sonar.qualitygate";
+
+ private final TreeRootHolder treeRootHolder;
+ private final SettingsRepository settingsRepository;
+ private final QualityGateService qualityGateService;
+ private final MutableQualityGateHolder qualityGateHolder;
+
+ public LoadQualityGateStep(TreeRootHolder treeRootHolder, SettingsRepository settingsRepository,
+ QualityGateService qualityGateService, MutableQualityGateHolder qualityGateHolder) {
+ this.treeRootHolder = treeRootHolder;
+ this.settingsRepository = settingsRepository;
+ this.qualityGateService = qualityGateService;
+ this.qualityGateHolder = qualityGateHolder;
+ }
+
+ @Override
+ public void execute() {
+ new DepthTraversalTypeAwareCrawler(
+ new TypeAwareVisitorAdapter(CrawlerDepthLimit.PROJECT, PRE_ORDER) {
+ @Override
+ public void visitProject(Component project) {
+ executeForProject(project);
+ }
+ }).visit(treeRootHolder.getRoot());
+ }
+
+ private void executeForProject(Component project) {
+ String projectKey = project.getKey();
+ Settings settings = settingsRepository.getSettings(project);
+ String qualityGateSetting = settings.getString(PROPERTY_QUALITY_GATE);
+
+ if (qualityGateSetting == null || StringUtils.isBlank(qualityGateSetting)) {
+ LOGGER.debug("No quality gate is configured for project " + projectKey);
+ qualityGateHolder.setNoQualityGate();
+ return;
+ }
+
+ try {
+ long qualityGateId = Long.parseLong(qualityGateSetting);
+ Optional<QualityGate> qualityGate = qualityGateService.findById(qualityGateId);
+ if (qualityGate.isPresent()) {
+ qualityGateHolder.setQualityGate(qualityGate.get());
+ } else {
+ qualityGateHolder.setNoQualityGate();
+ }
+ } catch (NumberFormatException e) {
+ throw new IllegalStateException(
+ String.format("Unsupported value (%s) in property %s", qualityGateSetting, PROPERTY_QUALITY_GATE),
+ e);
+ }
+ }
+
+ @Override
+ public String getDescription() {
+ return "Load Quality gate";
+ }
+}
--- /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.step;
+
+import com.google.common.base.Predicate;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Nonnull;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.RuleStatus;
+import org.sonar.batch.protocol.output.BatchReport;
+import org.sonar.core.util.CloseableIterator;
+import org.sonar.server.computation.batch.BatchReportReader;
+import org.sonar.server.computation.issue.Rule;
+import org.sonar.server.computation.issue.RuleRepository;
+import org.sonar.server.computation.qualityprofile.ActiveRule;
+import org.sonar.server.computation.qualityprofile.ActiveRulesHolderImpl;
+
+import static com.google.common.collect.FluentIterable.from;
+
+public class LoadQualityProfilesStep implements ComputationStep {
+
+ private final BatchReportReader batchReportReader;
+ private final ActiveRulesHolderImpl activeRulesHolder;
+ private final RuleRepository ruleRepository;
+
+ public LoadQualityProfilesStep(BatchReportReader batchReportReader, ActiveRulesHolderImpl activeRulesHolder, RuleRepository ruleRepository) {
+ this.batchReportReader = batchReportReader;
+ this.activeRulesHolder = activeRulesHolder;
+ this.ruleRepository = ruleRepository;
+ }
+
+ @Override
+ public void execute() {
+ List<ActiveRule> activeRules = new ArrayList<>();
+ try (CloseableIterator<BatchReport.ActiveRule> batchActiveRules = batchReportReader.readActiveRules()) {
+ while (batchActiveRules.hasNext()) {
+ BatchReport.ActiveRule batchActiveRule = batchActiveRules.next();
+ activeRules.add(convert(batchActiveRule));
+ }
+ }
+
+ List<ActiveRule> validActiveRules = from(activeRules).filter(new IsValid()).toList();
+ activeRulesHolder.set(validActiveRules);
+ }
+
+ private class IsValid implements Predicate<ActiveRule> {
+ @Override
+ public boolean apply(@Nonnull ActiveRule input) {
+ if (ruleRepository.hasKey(input.getRuleKey())) {
+ Rule rule = ruleRepository.getByKey(input.getRuleKey());
+ return rule.getStatus() != RuleStatus.REMOVED;
+ }
+ return false;
+ }
+ }
+
+ @Override
+ public String getDescription() {
+ return "Load quality profiles";
+ }
+
+ private static ActiveRule convert(BatchReport.ActiveRule input) {
+ RuleKey key = RuleKey.of(input.getRuleRepository(), input.getRuleKey());
+ Map<String, String> params = new HashMap<>();
+ for (BatchReport.ActiveRule.ActiveRuleParam inputParam : input.getParamList()) {
+ params.put(inputParam.getKey(), inputParam.getValue());
+ }
+ return new ActiveRule(key, input.getSeverity().name(), params);
+ }
+}
@Override
public String getDescription() {
- return "Computation of New Coverage measures";
+ return "Compute new coverage";
}
private static class NewLinesAndConditionsCoverageFormula extends NewLinesAndConditionsFormula {
@Override
public String getDescription() {
- return "Persist component links";
+ return "Persist events";
}
private class PersistEventComponentVisitor extends TypeAwareVisitorAdapter {
@Override
public String getDescription() {
- return "Persist file sources";
+ return "Persist sources";
}
}
@Override
public String getDescription() {
- return "Persist component links";
+ return "Persist project links";
}
}
@Override
public String getDescription() {
- return "Purge datastores";
+ return "Purge db";
}
}
@Override
public String getDescription() {
- return "Generate Quality Gate Events";
+ return "Generate Quality gate events";
}
}
+++ /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.step;
-
-import com.google.common.base.Optional;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.config.Settings;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.server.computation.component.Component;
-import org.sonar.server.computation.component.CrawlerDepthLimit;
-import org.sonar.server.computation.component.DepthTraversalTypeAwareCrawler;
-import org.sonar.server.computation.component.SettingsRepository;
-import org.sonar.server.computation.component.TreeRootHolder;
-import org.sonar.server.computation.component.TypeAwareVisitorAdapter;
-import org.sonar.server.computation.qualitygate.MutableQualityGateHolder;
-import org.sonar.server.computation.qualitygate.QualityGate;
-import org.sonar.server.computation.qualitygate.QualityGateService;
-
-import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;
-
-/**
- * This step retrieves the QualityGate and stores it in
- * {@link MutableQualityGateHolder}.
- */
-public class QualityGateLoadingStep implements ComputationStep {
- private static final Logger LOGGER = Loggers.get(QualityGateLoadingStep.class);
-
- private static final String PROPERTY_QUALITY_GATE = "sonar.qualitygate";
-
- private final TreeRootHolder treeRootHolder;
- private final SettingsRepository settingsRepository;
- private final QualityGateService qualityGateService;
- private final MutableQualityGateHolder qualityGateHolder;
-
- public QualityGateLoadingStep(TreeRootHolder treeRootHolder, SettingsRepository settingsRepository,
- QualityGateService qualityGateService, MutableQualityGateHolder qualityGateHolder) {
- this.treeRootHolder = treeRootHolder;
- this.settingsRepository = settingsRepository;
- this.qualityGateService = qualityGateService;
- this.qualityGateHolder = qualityGateHolder;
- }
-
- @Override
- public void execute() {
- new DepthTraversalTypeAwareCrawler(
- new TypeAwareVisitorAdapter(CrawlerDepthLimit.PROJECT, PRE_ORDER) {
- @Override
- public void visitProject(Component project) {
- executeForProject(project);
- }
- }).visit(treeRootHolder.getRoot());
- }
-
- private void executeForProject(Component project) {
- String projectKey = project.getKey();
- Settings settings = settingsRepository.getSettings(project);
- String qualityGateSetting = settings.getString(PROPERTY_QUALITY_GATE);
-
- if (qualityGateSetting == null || StringUtils.isBlank(qualityGateSetting)) {
- LOGGER.debug("No quality gate is configured for project " + projectKey);
- qualityGateHolder.setNoQualityGate();
- return;
- }
-
- try {
- long qualityGateId = Long.parseLong(qualityGateSetting);
- Optional<QualityGate> qualityGate = qualityGateService.findById(qualityGateId);
- if (qualityGate.isPresent()) {
- qualityGateHolder.setQualityGate(qualityGate.get());
- } else {
- qualityGateHolder.setNoQualityGate();
- }
- } catch (NumberFormatException e) {
- throw new IllegalStateException(
- String.format("Unsupported value (%s) in property %s", qualityGateSetting, PROPERTY_QUALITY_GATE),
- e);
- }
- }
-
- @Override
- public String getDescription() {
- return "Retrieve Quality Gate";
- }
-}
* {@link CoreMetrics#ALERT_STATUS_KEY}</li>
* </ul>
*
- * It must be executed after the computation of differential measures {@link FillMeasuresWithVariationsStep}
+ * It must be executed after the computation of differential measures {@link ComputeMeasureVariationsStep}
*/
public class QualityGateMeasuresStep implements ComputationStep {
@Override
public String getDescription() {
- return "Compute Quality Profile events";
+ return "Generate Quality profile events";
}
}
import com.google.common.collect.Iterables;
import java.util.Arrays;
import java.util.List;
+import javax.annotation.Nonnull;
import org.sonar.server.computation.container.ComputeEngineContainer;
/**
public List<Class<? extends ComputationStep>> orderedStepClasses() {
return Arrays.asList(
// extract report to a temp directory
- ReportExtractionStep.class,
+ ExtractReportStep.class,
// Builds Component tree
BuildComponentTreeStep.class,
FillComponentsStep.class,
ValidateProjectStep.class,
- FeedDebtModelStep.class,
- FeedActiveRulesStep.class,
+ LoadDebtModelStep.class,
+ LoadQualityProfilesStep.class,
// load project related stuffs
- QualityGateLoadingStep.class,
- FeedPeriodsStep.class,
+ LoadQualityGateStep.class,
+ LoadPeriodsStep.class,
// data computation
SizeMeasuresStep.class,
UnitTestMeasuresStep.class,
ComplexityMeasuresStep.class,
- FeedMeasureComputers.class,
+ LoadMeasureComputersStep.class,
ExecuteVisitorsStep.class,
// Must be executed after computation of all measures
- FillMeasuresWithVariationsStep.class,
+ ComputeMeasureVariationsStep.class,
// Must be executed after computation of differential measures
QualityGateMeasuresStep.class,
public Iterable<ComputationStep> instances() {
return Iterables.transform(orderedStepClasses(), new Function<Class<? extends ComputationStep>, ComputationStep>() {
@Override
- public ComputationStep apply(Class<? extends ComputationStep> input) {
+ public ComputationStep apply(@Nonnull Class<? extends ComputationStep> input) {
ComputationStep computationStepType = computeEngineContainer.getComponentByType(input);
if (computationStepType == null) {
throw new IllegalStateException(String.format("Component not found: %s", 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.step;
-
-import java.io.File;
-import java.io.IOException;
-import org.apache.commons.io.FileUtils;
-import org.sonar.api.utils.TempFolder;
-import org.sonar.api.utils.ZipUtils;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-import org.sonar.server.computation.CeTask;
-import org.sonar.server.computation.ReportFiles;
-import org.sonar.server.computation.batch.MutableBatchReportDirectoryHolder;
-
-/**
- * Extracts the content zip file of the {@link org.sonar.server.computation.CeTask} to a temp directory and adds a {@link File}
- * representing that temp directory to the {@link MutableBatchReportDirectoryHolder}.
- */
-public class ReportExtractionStep implements ComputationStep {
- private static final Logger LOG = Loggers.get(ReportExtractionStep.class);
-
- private final ReportFiles reportFiles;
- private final CeTask task;
- private final TempFolder tempFolder;
- private final MutableBatchReportDirectoryHolder reportDirectoryHolder;
-
- public ReportExtractionStep(ReportFiles reportFiles, CeTask task, TempFolder tempFolder,
- MutableBatchReportDirectoryHolder reportDirectoryHolder) {
- this.reportFiles = reportFiles;
- this.task = task;
- this.tempFolder = tempFolder;
- this.reportDirectoryHolder = reportDirectoryHolder;
- }
-
- @Override
- public void execute() {
- File dir = tempFolder.newDir();
- File zip = reportFiles.fileForUuid(task.getUuid());
- try {
- ZipUtils.unzip(zip, dir);
- reportDirectoryHolder.setDirectory(dir);
- LOG.info("Analysis report extracted | size={} | compressed={}",
- FileUtils.byteCountToDisplaySize(FileUtils.sizeOf(dir)), FileUtils.byteCountToDisplaySize(FileUtils.sizeOf(zip)));
- } catch (IOException e) {
- throw new IllegalStateException(String.format("Fail to unzip %s into %s", zip, dir), e);
- }
- }
-
- @Override
- public String getDescription() {
- return "Uncompress report";
- }
-
-}
@Override
public String getDescription() {
- return "File and Directory measures";
+ return "Compute size measures";
}
private class FileAndDirectoryMeasureVisitor extends PathAwareVisitorAdapter<Counter> {
package org.sonar.server.computation.step;
import java.util.List;
-import org.sonar.db.component.SnapshotDto;
+import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.MyBatis;
import org.sonar.db.component.SnapshotDao;
+import org.sonar.db.component.SnapshotDto;
import org.sonar.server.computation.component.Component;
import org.sonar.server.computation.component.DbIdsRepository;
import org.sonar.server.computation.component.TreeRootHolder;
-import org.sonar.db.DbClient;
import static org.sonar.db.component.SnapshotDao.isLast;
@Override
public String getDescription() {
- return "Switch last snapshot flag";
+ return "Enable snapshot";
}
private void disablePreviousSnapshot(DbSession session, long reportSnapshotId) {
import org.sonar.server.computation.component.PathAwareCrawler;
import org.sonar.server.computation.component.TreeRootHolder;
import org.sonar.server.computation.formula.Counter;
+import org.sonar.server.computation.formula.CounterInitializationContext;
import org.sonar.server.computation.formula.CreateMeasureContext;
import org.sonar.server.computation.formula.Formula;
import org.sonar.server.computation.formula.FormulaExecutorComponentVisitor;
-import org.sonar.server.computation.formula.CounterInitializationContext;
import org.sonar.server.computation.formula.counter.IntSumCounter;
import org.sonar.server.computation.measure.Measure;
import org.sonar.server.computation.measure.MeasureRepository;
@Override
public String getDescription() {
- return "Aggregation of comment measures";
+ return "Compute test measures";
}
}
import java.util.List;
import java.util.Map;
import javax.annotation.CheckForNull;
-import org.sonar.api.config.Settings;
import org.sonar.api.utils.MessageException;
import org.sonar.batch.protocol.output.BatchReport;
import org.sonar.core.component.ComponentKeys;
private static final Joiner MESSAGES_JOINER = Joiner.on("\n o ");
private final DbClient dbClient;
- private final Settings settings;
private final BatchReportReader reportReader;
private final TreeRootHolder treeRootHolder;
- public ValidateProjectStep(DbClient dbClient, Settings settings, BatchReportReader reportReader, TreeRootHolder treeRootHolder) {
+ public ValidateProjectStep(DbClient dbClient, BatchReportReader reportReader, TreeRootHolder treeRootHolder) {
this.dbClient = dbClient;
- this.settings = settings;
this.reportReader = reportReader;
this.treeRootHolder = treeRootHolder;
}
throw MessageException.of("Validation of project failed:\n o " + MESSAGES_JOINER.join(visitor.validationMessages));
}
} finally {
- session.close();
+ dbClient.closeSession(session);
}
}
@Override
public String getDescription() {
- return "Validate project and modules keys";
+ return "Validate project";
}
private class ValidateProjectsVisitor extends TypeAwareVisitorAdapter {
// Project key is already used as a module of another project
ComponentDto anotherBaseProject = componentDao.selectOrFailByUuid(session, baseProject.get().projectUuid());
validationMessages.add(String.format("The project \"%s\" is already defined in SonarQube but as a module of project \"%s\". "
- + "If you really want to stop directly analysing project \"%s\", please first delete it from SonarQube and then relaunch the analysis of project \"%s\".",
+ + "If you really want to stop directly analysing project \"%s\", please first delete it from SonarQube and then relaunch the analysis of project \"%s\".",
rawProjectKey, anotherBaseProject.key(), anotherBaseProject.key(), rawProjectKey));
}
}
Long lastAnalysisDate = snapshotDto != null ? snapshotDto.getCreatedAt() : null;
if (lastAnalysisDate != null && currentAnalysisDate <= snapshotDto.getCreatedAt()) {
validationMessages.add(String.format("Date of analysis cannot be older than the date of the last known analysis on this project. Value: \"%s\". " +
- "Latest analysis: \"%s\". It's only possible to rebuild the past in a chronological order.",
+ "Latest analysis: \"%s\". It's only possible to rebuild the past in a chronological order.",
formatDateTime(new Date(currentAnalysisDate)), formatDateTime(new Date(lastAnalysisDate))));
}
}
if (baseModule.projectUuid().equals(baseModule.uuid())) {
// module is actually a project
validationMessages.add(String.format("The project \"%s\" is already defined in SonarQube but not as a module of project \"%s\". "
- + "If you really want to stop directly analysing project \"%s\", please first delete it from SonarQube and then relaunch the analysis of project \"%s\".",
+ + "If you really want to stop directly analysing project \"%s\", please first delete it from SonarQube and then relaunch the analysis of project \"%s\".",
rawModuleKey, rawProjectKey, rawModuleKey, rawProjectKey));
}
}
import org.sonar.api.utils.System2;
import org.sonar.api.utils.internal.TempFolderCleaner;
import org.sonar.core.config.CorePropertyDefinitions;
-import org.sonar.core.config.Logback;
import org.sonar.core.util.UuidFactoryImpl;
import org.sonar.db.DaoModule;
import org.sonar.db.DatabaseChecker;
add(
ServerSettings.class,
ServerImpl.class,
- Logback.class,
UuidFactoryImpl.INSTANCE,
EmbeddedDatabaseFactory.class,
DefaultDatabase.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.server.computation.step;
-
-import com.google.common.base.Optional;
-import org.assertj.core.data.MapEntry;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.rule.RuleStatus;
-import org.sonar.api.rule.Severity;
-import org.sonar.batch.protocol.Constants;
-import org.sonar.batch.protocol.output.BatchReport;
-import org.sonar.server.computation.batch.BatchReportReaderRule;
-import org.sonar.server.computation.issue.DumbRule;
-import org.sonar.server.computation.issue.RuleRepositoryRule;
-import org.sonar.server.computation.qualityprofile.ActiveRule;
-import org.sonar.server.computation.qualityprofile.ActiveRulesHolderImpl;
-
-import static java.util.Arrays.asList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.db.rule.RuleTesting.XOO_X1;
-import static org.sonar.db.rule.RuleTesting.XOO_X2;
-
-public class FeedActiveRulesStepTest {
-
- @Rule
- public TemporaryFolder temp = new TemporaryFolder();
-
- @Rule
- public BatchReportReaderRule batchReportReader = new BatchReportReaderRule();
-
- @Rule
- public RuleRepositoryRule ruleRepository = new RuleRepositoryRule();
-
- ActiveRulesHolderImpl activeRulesHolder = new ActiveRulesHolderImpl();
- FeedActiveRulesStep underTest = new FeedActiveRulesStep(batchReportReader, activeRulesHolder, ruleRepository);
-
- @Test
- public void feed_active_rules() throws Exception {
- ruleRepository.add(XOO_X1);
- ruleRepository.add(XOO_X2);
-
- BatchReport.ActiveRule.Builder batch1 = BatchReport.ActiveRule.newBuilder()
- .setRuleRepository(XOO_X1.repository()).setRuleKey(XOO_X1.rule())
- .setSeverity(Constants.Severity.BLOCKER);
- batch1.addParamBuilder().setKey("p1").setValue("v1").build();
-
- BatchReport.ActiveRule.Builder batch2 = BatchReport.ActiveRule.newBuilder()
- .setRuleRepository(XOO_X2.repository()).setRuleKey(XOO_X2.rule()).setSeverity(Constants.Severity.MAJOR);
- batchReportReader.putActiveRules(asList(batch1.build(), batch2.build()));
-
- underTest.execute();
-
- assertThat(activeRulesHolder.getAll()).hasSize(2);
-
- Optional<ActiveRule> ar1 = activeRulesHolder.get(XOO_X1);
- assertThat(ar1.get().getSeverity()).isEqualTo(Severity.BLOCKER);
- assertThat(ar1.get().getParams()).containsExactly(MapEntry.entry("p1", "v1"));
-
- Optional<ActiveRule> ar2 = activeRulesHolder.get(XOO_X2);
- assertThat(ar2.get().getSeverity()).isEqualTo(Severity.MAJOR);
- assertThat(ar2.get().getParams()).isEmpty();
- }
-
- @Test
- public void ignore_rules_with_status_REMOVED() throws Exception {
- ruleRepository.add(new DumbRule(XOO_X1).setStatus(RuleStatus.REMOVED));
-
- BatchReport.ActiveRule.Builder batch1 = BatchReport.ActiveRule.newBuilder()
- .setRuleRepository(XOO_X1.repository()).setRuleKey(XOO_X1.rule())
- .setSeverity(Constants.Severity.BLOCKER);
- batchReportReader.putActiveRules(asList(batch1.build()));
-
- underTest.execute();
-
- assertThat(activeRulesHolder.getAll()).isEmpty();
- }
-
- @Test
- public void ignore_not_found_rules() throws Exception {
- BatchReport.ActiveRule.Builder batch1 = BatchReport.ActiveRule.newBuilder()
- .setRuleRepository(XOO_X1.repository()).setRuleKey(XOO_X1.rule())
- .setSeverity(Constants.Severity.BLOCKER);
- batchReportReader.putActiveRules(asList(batch1.build()));
-
- underTest.execute();
-
- assertThat(activeRulesHolder.getAll()).isEmpty();
- }
-}
MutableDebtModelHolder debtModelHolder = new DebtModelHolderImpl();
- FeedDebtModelStep underTest;
+ LoadDebtModelStep underTest;
@Before
public void setUp() {
dbTester.truncateTables();
dbSession = dbClient.openSession(false);
- underTest = new FeedDebtModelStep(dbClient, debtModelHolder);
+ underTest = new LoadDebtModelStep(dbClient, debtModelHolder);
}
@After
@Test
public void support_core_metrics_as_input_metrics() throws Exception {
MeasureComputer[] computers = new MeasureComputer[] {newMeasureComputer(array(NCLOC_KEY), array(NEW_METRIC_1))};
- ComputationStep underTest = new FeedMeasureComputers(holder, array(new TestMetrics()), computers);
+ ComputationStep underTest = new LoadMeasureComputersStep(holder, array(new TestMetrics()), computers);
underTest.execute();
assertThat(holder.getMeasureComputers()).hasSize(1);
@Test
public void support_plugin_metrics_as_input_metrics() throws Exception {
MeasureComputer[] computers = new MeasureComputer[] {newMeasureComputer(array(NEW_METRIC_1), array(NEW_METRIC_2))};
- ComputationStep underTest = new FeedMeasureComputers(holder, array(new TestMetrics()), computers);
+ ComputationStep underTest = new LoadMeasureComputersStep(holder, array(new TestMetrics()), computers);
underTest.execute();
assertThat(holder.getMeasureComputers()).hasSize(1);
MeasureComputer measureComputer3 = newMeasureComputer(array(NEW_METRIC_2), array(NEW_METRIC_3));
MeasureComputer[] computers = new MeasureComputer[] {measureComputer1, measureComputer2, measureComputer3};
- ComputationStep underTest = new FeedMeasureComputers(holder, array(new TestMetrics()), computers);
+ ComputationStep underTest = new LoadMeasureComputersStep(holder, array(new TestMetrics()), computers);
underTest.execute();
List<MeasureComputerWrapper> result = newArrayList(holder.getMeasureComputers());
MeasureComputer measureComputer3 = newMeasureComputer(array(NEW_METRIC_2), array(NEW_METRIC_3));
MeasureComputer[] computers = new MeasureComputer[] {measureComputer1, measureComputer2, measureComputer3};
- ComputationStep underTest = new FeedMeasureComputers(holder, array(new TestMetrics()), computers);
+ ComputationStep underTest = new LoadMeasureComputersStep(holder, array(new TestMetrics()), computers);
underTest.execute();
List<MeasureComputerWrapper> result = newArrayList(holder.getMeasureComputers());
thrown.expectMessage("Metric 'unknown' cannot be used as an input metric as it's not a core metric and no plugin declare this metric");
MeasureComputer[] computers = new MeasureComputer[] {newMeasureComputer(array("unknown"), array(NEW_METRIC_4))};
- ComputationStep underTest = new FeedMeasureComputers(holder, array(new TestMetrics()), computers);
+ ComputationStep underTest = new LoadMeasureComputersStep(holder, array(new TestMetrics()), computers);
underTest.execute();
}
thrown.expectMessage("Metric 'unknown' cannot be used as an output metric as no plugin declare this metric");
MeasureComputer[] computers = new MeasureComputer[] {newMeasureComputer(array(NEW_METRIC_4), array("unknown"))};
- ComputationStep underTest = new FeedMeasureComputers(holder, array(new TestMetrics()), computers);
+ ComputationStep underTest = new LoadMeasureComputersStep(holder, array(new TestMetrics()), computers);
underTest.execute();
}
thrown.expectMessage("Metric 'ncloc' cannot be used as an output metric as it's a core metric");
MeasureComputer[] computers = new MeasureComputer[] {newMeasureComputer(array(NEW_METRIC_4), array(NCLOC_KEY))};
- ComputationStep underTest = new FeedMeasureComputers(holder, array(new TestMetrics()), computers);
+ ComputationStep underTest = new LoadMeasureComputersStep(holder, array(new TestMetrics()), computers);
underTest.execute();
}
@Test
public void not_fail_if_input_metrics_are_same_as_output_metrics() throws Exception {
MeasureComputer[] computers = new MeasureComputer[] {newMeasureComputer(array(NEW_METRIC_1), array(NEW_METRIC_1))};
- ComputationStep underTest = new FeedMeasureComputers(holder, array(new TestMetrics()), computers);
+ ComputationStep underTest = new LoadMeasureComputersStep(holder, array(new TestMetrics()), computers);
underTest.execute();
assertThat(holder.getMeasureComputers()).hasSize(1);
@Test
public void return_empty_list_when_no_measure_computers() throws Exception {
- ComputationStep underTest = new FeedMeasureComputers(holder, array(new TestMetrics()));
+ ComputationStep underTest = new LoadMeasureComputersStep(holder, array(new TestMetrics()));
underTest.execute();
assertThat(holder.getMeasureComputers()).isEmpty();
@Test
public void return_empty_list_when_no_metrics_neither_measure_computers() throws Exception {
- ComputationStep underTest = new FeedMeasureComputers(holder);
+ ComputationStep underTest = new LoadMeasureComputersStep(holder);
underTest.execute();
assertThat(holder.getMeasureComputers()).isEmpty();
thrown.expectMessage("Metric 'metric1' cannot be used as an output metric as no plugin declare this metric");
MeasureComputer[] computers = new MeasureComputer[] {newMeasureComputer(array(NCLOC_KEY), array(NEW_METRIC_1))};
- ComputationStep underTest = new FeedMeasureComputers(holder, computers);
+ ComputationStep underTest = new LoadMeasureComputersStep(holder, computers);
underTest.execute();
}
thrown.expectMessage("Output metric 'metric1' is already defined by another measure computer 'TestMeasureComputer'");
MeasureComputer[] computers = new MeasureComputer[] {newMeasureComputer(array(NCLOC_KEY), array(NEW_METRIC_1)), newMeasureComputer(array(CLASSES_KEY), array(NEW_METRIC_1))};
- ComputationStep underTest = new FeedMeasureComputers(holder, array(new TestMetrics()), computers);
+ ComputationStep underTest = new LoadMeasureComputersStep(holder, array(new TestMetrics()), computers);
underTest.execute();
}
};
MeasureComputer[] computers = new MeasureComputer[] {measureComputer};
- ComputationStep underTest = new FeedMeasureComputers(holder, array(new TestMetrics()), computers);
+ ComputationStep underTest = new LoadMeasureComputersStep(holder, array(new TestMetrics()), computers);
underTest.execute();
}
Settings settings = new Settings();
SettingsRepository settingsRepository = mock(SettingsRepository.class);
- FeedPeriodsStep underTest;
+ LoadPeriodsStep underTest;
@Override
protected ComputationStep step() {
public void setUp() throws Exception {
analysisMetadataHolder.setAnalysisDate(DATE_FORMAT.parse("2008-11-30"));
- underTest = new FeedPeriodsStep(dbClient, settingsRepository, treeRootHolder, analysisMetadataHolder, periodsHolder);
+ underTest = new LoadPeriodsStep(dbClient, settingsRepository, treeRootHolder, analysisMetadataHolder, periodsHolder);
}
private void setupRoot(Component root) {
--- /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.step;
+
+import com.google.common.base.Optional;
+import org.assertj.core.data.MapEntry;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.rule.RuleStatus;
+import org.sonar.api.rule.Severity;
+import org.sonar.batch.protocol.Constants;
+import org.sonar.batch.protocol.output.BatchReport;
+import org.sonar.server.computation.batch.BatchReportReaderRule;
+import org.sonar.server.computation.issue.DumbRule;
+import org.sonar.server.computation.issue.RuleRepositoryRule;
+import org.sonar.server.computation.qualityprofile.ActiveRule;
+import org.sonar.server.computation.qualityprofile.ActiveRulesHolderImpl;
+
+import static java.util.Arrays.asList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.db.rule.RuleTesting.XOO_X1;
+import static org.sonar.db.rule.RuleTesting.XOO_X2;
+
+public class LoadQualityProfilesStepTest {
+
+ @Rule
+ public BatchReportReaderRule batchReportReader = new BatchReportReaderRule();
+
+ @Rule
+ public RuleRepositoryRule ruleRepository = new RuleRepositoryRule();
+
+ ActiveRulesHolderImpl activeRulesHolder = new ActiveRulesHolderImpl();
+ LoadQualityProfilesStep underTest = new LoadQualityProfilesStep(batchReportReader, activeRulesHolder, ruleRepository);
+
+ @Test
+ public void feed_active_rules() throws Exception {
+ ruleRepository.add(XOO_X1);
+ ruleRepository.add(XOO_X2);
+
+ BatchReport.ActiveRule.Builder batch1 = BatchReport.ActiveRule.newBuilder()
+ .setRuleRepository(XOO_X1.repository()).setRuleKey(XOO_X1.rule())
+ .setSeverity(Constants.Severity.BLOCKER);
+ batch1.addParamBuilder().setKey("p1").setValue("v1").build();
+
+ BatchReport.ActiveRule.Builder batch2 = BatchReport.ActiveRule.newBuilder()
+ .setRuleRepository(XOO_X2.repository()).setRuleKey(XOO_X2.rule()).setSeverity(Constants.Severity.MAJOR);
+ batchReportReader.putActiveRules(asList(batch1.build(), batch2.build()));
+
+ underTest.execute();
+
+ assertThat(activeRulesHolder.getAll()).hasSize(2);
+
+ Optional<ActiveRule> ar1 = activeRulesHolder.get(XOO_X1);
+ assertThat(ar1.get().getSeverity()).isEqualTo(Severity.BLOCKER);
+ assertThat(ar1.get().getParams()).containsExactly(MapEntry.entry("p1", "v1"));
+
+ Optional<ActiveRule> ar2 = activeRulesHolder.get(XOO_X2);
+ assertThat(ar2.get().getSeverity()).isEqualTo(Severity.MAJOR);
+ assertThat(ar2.get().getParams()).isEmpty();
+ }
+
+ @Test
+ public void ignore_rules_with_status_REMOVED() throws Exception {
+ ruleRepository.add(new DumbRule(XOO_X1).setStatus(RuleStatus.REMOVED));
+
+ BatchReport.ActiveRule.Builder batch1 = BatchReport.ActiveRule.newBuilder()
+ .setRuleRepository(XOO_X1.repository()).setRuleKey(XOO_X1.rule())
+ .setSeverity(Constants.Severity.BLOCKER);
+ batchReportReader.putActiveRules(asList(batch1.build()));
+
+ underTest.execute();
+
+ assertThat(activeRulesHolder.getAll()).isEmpty();
+ }
+
+ @Test
+ public void ignore_not_found_rules() throws Exception {
+ BatchReport.ActiveRule.Builder batch1 = BatchReport.ActiveRule.newBuilder()
+ .setRuleRepository(XOO_X1.repository()).setRuleKey(XOO_X1.rule())
+ .setSeverity(Constants.Severity.BLOCKER);
+ batchReportReader.putActiveRules(asList(batch1.build()));
+
+ underTest.execute();
+
+ assertThat(activeRulesHolder.getAll()).isEmpty();
+ }
+}
private SettingsRepository settingsRepository = mock(SettingsRepository.class);
private QualityGateService qualityGateService = mock(QualityGateService.class);
- private QualityGateLoadingStep underTest = new QualityGateLoadingStep(treeRootHolder, settingsRepository, qualityGateService, mutableQualityGateHolder);
+ private LoadQualityGateStep underTest = new LoadQualityGateStep(treeRootHolder, settingsRepository, qualityGateService, mutableQualityGateHolder);
@Test
public void execute_sets_default_QualityGate_when_project_has_no_settings() {
@Test
public void instances_throws_ISE_if_container_does_not_have_any_step() throws Exception {
expectedException.expect(IllegalStateException.class);
- expectedException.expectMessage("Component not found: class org.sonar.server.computation.step.ReportExtractionStep");
+ expectedException.expectMessage("Component not found: " + ExtractReportStep.class);
ComputeEngineContainerImpl computeEngineContainer = new ComputeEngineContainerImpl(new ComponentContainer(), new ContainerPopulator<ComputeEngineContainer>() {
@Override
expectedException.expect(IllegalStateException.class);
expectedException.expectMessage("Component not found: class org.sonar.server.computation.step.BuildComponentTreeStep");
- final ReportExtractionStep reportExtractionStep = mock(ReportExtractionStep.class);
+ final ExtractReportStep reportExtractionStep = mock(ExtractReportStep.class);
ComponentContainer componentContainer = new ComponentContainer() {
{
addSingleton(reportExtractionStep);
--- /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.step;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.ComponentTesting;
+import org.sonar.db.component.SnapshotDto;
+import org.sonar.db.measure.MeasureDto;
+import org.sonar.server.computation.batch.BatchReportReaderRule;
+import org.sonar.server.computation.batch.TreeRootHolderRule;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.component.ReportComponent;
+import org.sonar.server.computation.measure.Measure;
+import org.sonar.server.computation.measure.MeasureRepositoryRule;
+import org.sonar.server.computation.metric.Metric;
+import org.sonar.server.computation.metric.MetricImpl;
+import org.sonar.server.computation.metric.MetricRepositoryRule;
+import org.sonar.server.computation.period.Period;
+import org.sonar.server.computation.period.PeriodsHolderRule;
+import org.sonar.test.DbTests;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.server.component.SnapshotTesting.createForComponent;
+import static org.sonar.server.component.SnapshotTesting.createForProject;
+
+@Category(DbTests.class)
+public class ReportComputeMeasureVariationsStepTest {
+
+ static final Metric ISSUES_METRIC = new MetricImpl(1, "violations", "violations", Metric.MetricType.INT);
+ static final Metric DEBT_METRIC = new MetricImpl(2, "sqale_index", "sqale_index", Metric.MetricType.WORK_DUR);
+ static final Metric FILE_COMPLEXITY_METRIC = new MetricImpl(3, "file_complexity", "file_complexity", Metric.MetricType.FLOAT);
+ static final Metric BUILD_BREAKER_METRIC = new MetricImpl(4, "build_breaker", "build_breaker", Metric.MetricType.BOOL);
+
+ static final ComponentDto PROJECT_DTO = ComponentTesting.newProjectDto();
+
+ static final Component PROJECT = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(PROJECT_DTO.uuid()).build();
+
+ @Rule
+ public DbTester dbTester = DbTester.create(System2.INSTANCE);
+
+ @Rule
+ public BatchReportReaderRule reportReader = new BatchReportReaderRule();
+
+ @Rule
+ public PeriodsHolderRule periodsHolder = new PeriodsHolderRule();
+
+ @Rule
+ public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
+
+ @Rule
+ public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
+ .add(ISSUES_METRIC)
+ .add(DEBT_METRIC)
+ .add(FILE_COMPLEXITY_METRIC)
+ .add(BUILD_BREAKER_METRIC);
+
+ @Rule
+ public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
+
+ DbSession session = dbTester.getSession();
+
+ DbClient dbClient = dbTester.getDbClient();
+
+ ComputeMeasureVariationsStep underTest;
+
+ @Before
+ public void setUp() {
+ dbTester.truncateTables();
+ dbClient.componentDao().insert(session, PROJECT_DTO);
+ session.commit();
+
+ underTest = new ComputeMeasureVariationsStep(dbClient, treeRootHolder, periodsHolder, metricRepository, measureRepository);
+ }
+
+ @Test
+ public void do_nothing_when_no_raw_measure() {
+ SnapshotDto period1ProjectSnapshot = createForProject(PROJECT_DTO);
+ dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
+ dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 60d));
+ session.commit();
+
+ periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
+
+ treeRootHolder.setRoot(PROJECT);
+
+ underTest.execute();
+
+ assertThat(measureRepository.getRawMeasures(PROJECT).keys()).isEmpty();
+ }
+
+ @Test
+ public void do_nothing_when_no_period() {
+ Component project = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(PROJECT_DTO.uuid()).build();
+ treeRootHolder.setRoot(project);
+ periodsHolder.setPeriods();
+
+ underTest.execute();
+
+ assertThat(measureRepository.getRawMeasures(project).keys()).isEmpty();
+ }
+
+ @Test
+ public void set_variation() {
+ // Project
+ SnapshotDto period1ProjectSnapshot = createForProject(PROJECT_DTO);
+ dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
+ dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 60d));
+
+ // Directory
+ ComponentDto directoryDto = ComponentTesting.newDirectory(PROJECT_DTO, "dir");
+ dbClient.componentDao().insert(session, directoryDto);
+ SnapshotDto period1DirectorySnapshot = createForComponent(directoryDto, period1ProjectSnapshot);
+ dbClient.snapshotDao().insert(session, period1DirectorySnapshot);
+ dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), directoryDto.getId(), period1DirectorySnapshot.getId(), 10d));
+ session.commit();
+
+ periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
+
+ Component directory = ReportComponent.builder(Component.Type.DIRECTORY, 2).setUuid(directoryDto.uuid()).build();
+ Component project = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(PROJECT_DTO.uuid()).addChildren(directory).build();
+ treeRootHolder.setRoot(project);
+
+ addRawMeasure(project, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
+ addRawMeasure(directory, ISSUES_METRIC, Measure.newMeasureBuilder().create(20, null));
+
+ underTest.execute();
+
+ assertThat(measureRepository.getRawMeasure(project, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(20d);
+ assertThat(measureRepository.getRawMeasure(directory, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(10d);
+ }
+
+ @Test
+ public void set_variations_on_all_periods() {
+ SnapshotDto period1ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
+ SnapshotDto period2ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
+ SnapshotDto period3ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
+ SnapshotDto period4ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
+ SnapshotDto period5ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
+ dbClient.snapshotDao().insert(session, period1ProjectSnapshot, period2ProjectSnapshot, period3ProjectSnapshot, period4ProjectSnapshot, period5ProjectSnapshot);
+
+ dbClient.measureDao().insert(session,
+ newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 0d),
+ newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period2ProjectSnapshot.getId(), 20d),
+ newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period3ProjectSnapshot.getId(), 40d),
+ newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period4ProjectSnapshot.getId(), 80d),
+ newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period5ProjectSnapshot.getId(), 100d));
+ session.commit();
+
+ periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot),
+ newPeriod(2, period2ProjectSnapshot),
+ newPeriod(3, period3ProjectSnapshot),
+ newPeriod(4, period4ProjectSnapshot),
+ newPeriod(5, period5ProjectSnapshot));
+
+ treeRootHolder.setRoot(PROJECT);
+
+ addRawMeasure(PROJECT, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
+
+ underTest.execute();
+
+ assertThat(measureRepository.getRawMeasures(PROJECT).keys()).hasSize(1);
+
+ Measure measure = measureRepository.getRawMeasure(PROJECT, ISSUES_METRIC).get();
+ assertThat(measure.hasVariations()).isTrue();
+ assertThat(measure.getVariations().getVariation1()).isEqualTo(80d);
+ assertThat(measure.getVariations().getVariation2()).isEqualTo(60d);
+ assertThat(measure.getVariations().getVariation3()).isEqualTo(40d);
+ assertThat(measure.getVariations().getVariation4()).isEqualTo(0d);
+ assertThat(measure.getVariations().getVariation5()).isEqualTo(-20d);
+ }
+
+ @Test
+ public void set_variation_on_all_numeric_metrics() {
+ SnapshotDto period1ProjectSnapshot = createForProject(PROJECT_DTO);
+ dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
+ dbClient.measureDao().insert(session,
+ newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 60d),
+ newMeasureDto(DEBT_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 10d),
+ newMeasureDto(FILE_COMPLEXITY_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 2d),
+ newMeasureDto(BUILD_BREAKER_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 1d)
+ );
+ session.commit();
+
+ periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
+
+ treeRootHolder.setRoot(PROJECT);
+
+ addRawMeasure(PROJECT, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
+ addRawMeasure(PROJECT, DEBT_METRIC, Measure.newMeasureBuilder().create(5L, null));
+ addRawMeasure(PROJECT, FILE_COMPLEXITY_METRIC, Measure.newMeasureBuilder().create(3d, null));
+ addRawMeasure(PROJECT, BUILD_BREAKER_METRIC, Measure.newMeasureBuilder().create(false, null));
+
+ underTest.execute();
+
+ assertThat(measureRepository.getRawMeasures(PROJECT).keys()).hasSize(4);
+
+ assertThat(measureRepository.getRawMeasure(PROJECT, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(20d);
+ assertThat(measureRepository.getRawMeasure(PROJECT, DEBT_METRIC).get().getVariations().getVariation1()).isEqualTo(-5d);
+ assertThat(measureRepository.getRawMeasure(PROJECT, FILE_COMPLEXITY_METRIC).get().getVariations().getVariation1()).isEqualTo(1d);
+ assertThat(measureRepository.getRawMeasure(PROJECT, BUILD_BREAKER_METRIC).get().getVariations().getVariation1()).isEqualTo(-1d);
+ }
+
+ private static MeasureDto newMeasureDto(int metricId, long projectId, long snapshotId, double value) {
+ return new MeasureDto().setMetricId(metricId).setComponentId(projectId).setSnapshotId(snapshotId).setValue(value);
+ }
+
+ private static Period newPeriod(int index, SnapshotDto snapshotDto) {
+ return new Period(index, "mode", null, snapshotDto.getCreatedAt(), snapshotDto.getId());
+ }
+
+ private void addRawMeasure(Component component, Metric metric, Measure measure) {
+ measureRepository.addRawMeasure(component.getReportAttributes().getRef(), metric.getKey(), measure);
+ }
+}
+++ /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.step;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.SnapshotDto;
-import org.sonar.db.measure.MeasureDto;
-import org.sonar.db.component.ComponentTesting;
-import org.sonar.server.computation.batch.BatchReportReaderRule;
-import org.sonar.server.computation.batch.TreeRootHolderRule;
-import org.sonar.server.computation.component.Component;
-import org.sonar.server.computation.component.ReportComponent;
-import org.sonar.server.computation.measure.Measure;
-import org.sonar.server.computation.measure.MeasureRepositoryRule;
-import org.sonar.server.computation.metric.Metric;
-import org.sonar.server.computation.metric.MetricImpl;
-import org.sonar.server.computation.metric.MetricRepositoryRule;
-import org.sonar.server.computation.period.Period;
-import org.sonar.server.computation.period.PeriodsHolderRule;
-import org.sonar.test.DbTests;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.server.component.SnapshotTesting.createForComponent;
-import static org.sonar.server.component.SnapshotTesting.createForProject;
-
-@Category(DbTests.class)
-public class ReportFillMeasuresWithVariationsStepTest {
-
- static final Metric ISSUES_METRIC = new MetricImpl(1, "violations", "violations", Metric.MetricType.INT);
- static final Metric DEBT_METRIC = new MetricImpl(2, "sqale_index", "sqale_index", Metric.MetricType.WORK_DUR);
- static final Metric FILE_COMPLEXITY_METRIC = new MetricImpl(3, "file_complexity", "file_complexity", Metric.MetricType.FLOAT);
- static final Metric BUILD_BREAKER_METRIC = new MetricImpl(4, "build_breaker", "build_breaker", Metric.MetricType.BOOL);
-
- static final ComponentDto PROJECT_DTO = ComponentTesting.newProjectDto();
-
- static final Component PROJECT = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(PROJECT_DTO.uuid()).build();
-
- @Rule
- public DbTester dbTester = DbTester.create(System2.INSTANCE);
-
- @Rule
- public BatchReportReaderRule reportReader = new BatchReportReaderRule();
-
- @Rule
- public PeriodsHolderRule periodsHolder = new PeriodsHolderRule();
-
- @Rule
- public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
-
- @Rule
- public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
- .add(ISSUES_METRIC)
- .add(DEBT_METRIC)
- .add(FILE_COMPLEXITY_METRIC)
- .add(BUILD_BREAKER_METRIC);
-
- @Rule
- public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
-
- DbSession session = dbTester.getSession();
-
- DbClient dbClient = dbTester.getDbClient();
-
- FillMeasuresWithVariationsStep underTest;
-
- @Before
- public void setUp() {
- dbTester.truncateTables();
- dbClient.componentDao().insert(session, PROJECT_DTO);
- session.commit();
-
- underTest = new FillMeasuresWithVariationsStep(dbClient, treeRootHolder, periodsHolder, metricRepository, measureRepository);
- }
-
- @Test
- public void do_nothing_when_no_raw_measure() {
- SnapshotDto period1ProjectSnapshot = createForProject(PROJECT_DTO);
- dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
- dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 60d));
- session.commit();
-
- periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
-
- treeRootHolder.setRoot(PROJECT);
-
- underTest.execute();
-
- assertThat(measureRepository.getRawMeasures(PROJECT).keys()).isEmpty();
- }
-
- @Test
- public void do_nothing_when_no_period() {
- Component project = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(PROJECT_DTO.uuid()).build();
- treeRootHolder.setRoot(project);
- periodsHolder.setPeriods();
-
- underTest.execute();
-
- assertThat(measureRepository.getRawMeasures(project).keys()).isEmpty();
- }
-
- @Test
- public void set_variation() {
- // Project
- SnapshotDto period1ProjectSnapshot = createForProject(PROJECT_DTO);
- dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
- dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 60d));
-
- // Directory
- ComponentDto directoryDto = ComponentTesting.newDirectory(PROJECT_DTO, "dir");
- dbClient.componentDao().insert(session, directoryDto);
- SnapshotDto period1DirectorySnapshot = createForComponent(directoryDto, period1ProjectSnapshot);
- dbClient.snapshotDao().insert(session, period1DirectorySnapshot);
- dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), directoryDto.getId(), period1DirectorySnapshot.getId(), 10d));
- session.commit();
-
- periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
-
- Component directory = ReportComponent.builder(Component.Type.DIRECTORY, 2).setUuid(directoryDto.uuid()).build();
- Component project = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid(PROJECT_DTO.uuid()).addChildren(directory).build();
- treeRootHolder.setRoot(project);
-
- addRawMeasure(project, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
- addRawMeasure(directory, ISSUES_METRIC, Measure.newMeasureBuilder().create(20, null));
-
- underTest.execute();
-
- assertThat(measureRepository.getRawMeasure(project, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(20d);
- assertThat(measureRepository.getRawMeasure(directory, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(10d);
- }
-
- @Test
- public void set_variations_on_all_periods() {
- SnapshotDto period1ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
- SnapshotDto period2ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
- SnapshotDto period3ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
- SnapshotDto period4ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
- SnapshotDto period5ProjectSnapshot = createForProject(PROJECT_DTO).setLast(false);
- dbClient.snapshotDao().insert(session, period1ProjectSnapshot, period2ProjectSnapshot, period3ProjectSnapshot, period4ProjectSnapshot, period5ProjectSnapshot);
-
- dbClient.measureDao().insert(session,
- newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 0d),
- newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period2ProjectSnapshot.getId(), 20d),
- newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period3ProjectSnapshot.getId(), 40d),
- newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period4ProjectSnapshot.getId(), 80d),
- newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period5ProjectSnapshot.getId(), 100d));
- session.commit();
-
- periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot),
- newPeriod(2, period2ProjectSnapshot),
- newPeriod(3, period3ProjectSnapshot),
- newPeriod(4, period4ProjectSnapshot),
- newPeriod(5, period5ProjectSnapshot));
-
- treeRootHolder.setRoot(PROJECT);
-
- addRawMeasure(PROJECT, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
-
- underTest.execute();
-
- assertThat(measureRepository.getRawMeasures(PROJECT).keys()).hasSize(1);
-
- Measure measure = measureRepository.getRawMeasure(PROJECT, ISSUES_METRIC).get();
- assertThat(measure.hasVariations()).isTrue();
- assertThat(measure.getVariations().getVariation1()).isEqualTo(80d);
- assertThat(measure.getVariations().getVariation2()).isEqualTo(60d);
- assertThat(measure.getVariations().getVariation3()).isEqualTo(40d);
- assertThat(measure.getVariations().getVariation4()).isEqualTo(0d);
- assertThat(measure.getVariations().getVariation5()).isEqualTo(-20d);
- }
-
- @Test
- public void set_variation_on_all_numeric_metrics() {
- SnapshotDto period1ProjectSnapshot = createForProject(PROJECT_DTO);
- dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
- dbClient.measureDao().insert(session,
- newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 60d),
- newMeasureDto(DEBT_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 10d),
- newMeasureDto(FILE_COMPLEXITY_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 2d),
- newMeasureDto(BUILD_BREAKER_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 1d)
- );
- session.commit();
-
- periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
-
- treeRootHolder.setRoot(PROJECT);
-
- addRawMeasure(PROJECT, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
- addRawMeasure(PROJECT, DEBT_METRIC, Measure.newMeasureBuilder().create(5L, null));
- addRawMeasure(PROJECT, FILE_COMPLEXITY_METRIC, Measure.newMeasureBuilder().create(3d, null));
- addRawMeasure(PROJECT, BUILD_BREAKER_METRIC, Measure.newMeasureBuilder().create(false, null));
-
- underTest.execute();
-
- assertThat(measureRepository.getRawMeasures(PROJECT).keys()).hasSize(4);
-
- assertThat(measureRepository.getRawMeasure(PROJECT, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(20d);
- assertThat(measureRepository.getRawMeasure(PROJECT, DEBT_METRIC).get().getVariations().getVariation1()).isEqualTo(-5d);
- assertThat(measureRepository.getRawMeasure(PROJECT, FILE_COMPLEXITY_METRIC).get().getVariations().getVariation1()).isEqualTo(1d);
- assertThat(measureRepository.getRawMeasure(PROJECT, BUILD_BREAKER_METRIC).get().getVariations().getVariation1()).isEqualTo(-1d);
- }
-
- private static MeasureDto newMeasureDto(int metricId, long projectId, long snapshotId, double value) {
- return new MeasureDto().setMetricId(metricId).setComponentId(projectId).setSnapshotId(snapshotId).setValue(value);
- }
-
- private static Period newPeriod(int index, SnapshotDto snapshotDto) {
- return new Period(index, "mode", null, snapshotDto.getCreatedAt(), snapshotDto.getId());
- }
-
- private void addRawMeasure(Component component, Metric metric, Measure measure) {
- measureRepository.addRawMeasure(component.getReportAttributes().getRef(), metric.getKey(), measure);
- }
-}
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.rules.ExpectedException;
-import org.sonar.api.config.Settings;
import org.sonar.api.utils.MessageException;
import org.sonar.api.utils.System2;
import org.sonar.batch.protocol.Constants;
DbClient dbClient = dbTester.getDbClient();
- Settings settings;
-
- ValidateProjectStep underTest;
+ ValidateProjectStep underTest = new ValidateProjectStep(dbClient, reportReader, treeRootHolder);
@Before
public void setUp() {
dbTester.truncateTables();
- settings = new Settings();
-
- underTest = new ValidateProjectStep(dbClient, settings, reportReader, treeRootHolder);
}
@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.step;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.ComponentTesting;
+import org.sonar.db.component.SnapshotDto;
+import org.sonar.db.measure.MeasureDto;
+import org.sonar.server.computation.batch.BatchReportReaderRule;
+import org.sonar.server.computation.batch.TreeRootHolderRule;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.component.ViewsComponent;
+import org.sonar.server.computation.measure.Measure;
+import org.sonar.server.computation.measure.MeasureRepositoryRule;
+import org.sonar.server.computation.metric.Metric;
+import org.sonar.server.computation.metric.MetricImpl;
+import org.sonar.server.computation.metric.MetricRepositoryRule;
+import org.sonar.server.computation.period.Period;
+import org.sonar.server.computation.period.PeriodsHolderRule;
+import org.sonar.test.DbTests;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.server.component.SnapshotTesting.createForComponent;
+import static org.sonar.server.component.SnapshotTesting.createForProject;
+import static org.sonar.server.component.SnapshotTesting.createForView;
+
+@Category(DbTests.class)
+public class ViewsComputeMeasureVariationsStepTest {
+
+ static final Metric ISSUES_METRIC = new MetricImpl(1, "violations", "violations", Metric.MetricType.INT);
+ static final Metric DEBT_METRIC = new MetricImpl(2, "sqale_index", "sqale_index", Metric.MetricType.WORK_DUR);
+ static final Metric FILE_COMPLEXITY_METRIC = new MetricImpl(3, "file_complexity", "file_complexity", Metric.MetricType.FLOAT);
+ static final Metric BUILD_BREAKER_METRIC = new MetricImpl(4, "build_breaker", "build_breaker", Metric.MetricType.BOOL);
+
+ static final ComponentDto VIEW_DTO = ComponentTesting.newView();
+
+ static final Component VIEW = ViewsComponent.builder(Component.Type.VIEW, 1).setUuid(VIEW_DTO.uuid()).build();
+
+ @Rule
+ public DbTester dbTester = DbTester.create(System2.INSTANCE);
+
+ @Rule
+ public BatchReportReaderRule reportReader = new BatchReportReaderRule();
+
+ @Rule
+ public PeriodsHolderRule periodsHolder = new PeriodsHolderRule();
+
+ @Rule
+ public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
+
+ @Rule
+ public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
+ .add(ISSUES_METRIC)
+ .add(DEBT_METRIC)
+ .add(FILE_COMPLEXITY_METRIC)
+ .add(BUILD_BREAKER_METRIC);
+
+ @Rule
+ public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
+
+ DbSession session = dbTester.getSession();
+
+ DbClient dbClient = dbTester.getDbClient();
+
+ ComputeMeasureVariationsStep underTest;
+
+ @Before
+ public void setUp() {
+ dbTester.truncateTables();
+ dbClient.componentDao().insert(session, VIEW_DTO);
+ session.commit();
+
+ underTest = new ComputeMeasureVariationsStep(dbClient, treeRootHolder, periodsHolder, metricRepository, measureRepository);
+ }
+
+ @Test
+ public void do_nothing_when_no_raw_measure() {
+ SnapshotDto period1ViewSnapshot = createForView(VIEW_DTO);
+ dbClient.snapshotDao().insert(session, period1ViewSnapshot);
+ dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 60d));
+ session.commit();
+
+ periodsHolder.setPeriods(newPeriod(1, period1ViewSnapshot));
+
+ treeRootHolder.setRoot(VIEW);
+
+ underTest.execute();
+
+ assertThat(measureRepository.getRawMeasures(VIEW).keys()).isEmpty();
+ }
+
+ @Test
+ public void do_nothing_when_no_period() {
+ Component view = ViewsComponent.builder(Component.Type.VIEW, 1).setUuid(VIEW_DTO.uuid()).build();
+ treeRootHolder.setRoot(view);
+ periodsHolder.setPeriods();
+
+ underTest.execute();
+
+ assertThat(measureRepository.getRawMeasures(view).keys()).isEmpty();
+ }
+
+ @Test
+ public void set_variation() {
+ // View
+ SnapshotDto period1ViewSnapshot = createForView(VIEW_DTO);
+ dbClient.snapshotDao().insert(session, period1ViewSnapshot);
+ dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 60d));
+
+ // SubView
+ ComponentDto subviewDto = ComponentTesting.newSubView(VIEW_DTO, "dir", "key");
+ dbClient.componentDao().insert(session, subviewDto);
+ SnapshotDto period1SubviewSnapshot = createForComponent(subviewDto, period1ViewSnapshot);
+ dbClient.snapshotDao().insert(session, period1SubviewSnapshot);
+ dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), subviewDto.getId(), period1SubviewSnapshot.getId(), 10d));
+ session.commit();
+
+ periodsHolder.setPeriods(newPeriod(1, period1ViewSnapshot));
+
+ Component subview = ViewsComponent.builder(Component.Type.SUBVIEW, 2).setUuid(subviewDto.uuid()).build();
+ Component view = ViewsComponent.builder(Component.Type.VIEW, 1).setUuid(VIEW_DTO.uuid()).addChildren(subview).build();
+ treeRootHolder.setRoot(view);
+
+ addRawMeasure(view, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
+ addRawMeasure(subview, ISSUES_METRIC, Measure.newMeasureBuilder().create(20, null));
+
+ underTest.execute();
+
+ assertThat(measureRepository.getRawMeasure(view, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(20d);
+ assertThat(measureRepository.getRawMeasure(subview, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(10d);
+ }
+
+ @Test
+ public void set_variations_on_all_periods() {
+ SnapshotDto period1ViewSnapshot = createForProject(VIEW_DTO).setLast(false);
+ SnapshotDto period2ViewSnapshot = createForProject(VIEW_DTO).setLast(false);
+ SnapshotDto period3ViewSnapshot = createForProject(VIEW_DTO).setLast(false);
+ SnapshotDto period4ViewSnapshot = createForProject(VIEW_DTO).setLast(false);
+ SnapshotDto period5ViewSnapshot = createForProject(VIEW_DTO).setLast(false);
+ dbClient.snapshotDao().insert(session, period1ViewSnapshot, period2ViewSnapshot, period3ViewSnapshot, period4ViewSnapshot, period5ViewSnapshot);
+
+ dbClient.measureDao().insert(session,
+ newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 0d),
+ newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period2ViewSnapshot.getId(), 20d),
+ newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period3ViewSnapshot.getId(), 40d),
+ newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period4ViewSnapshot.getId(), 80d),
+ newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period5ViewSnapshot.getId(), 100d));
+ session.commit();
+
+ periodsHolder.setPeriods(newPeriod(1, period1ViewSnapshot),
+ newPeriod(2, period2ViewSnapshot),
+ newPeriod(3, period3ViewSnapshot),
+ newPeriod(4, period4ViewSnapshot),
+ newPeriod(5, period5ViewSnapshot));
+
+ treeRootHolder.setRoot(VIEW);
+
+ addRawMeasure(VIEW, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
+
+ underTest.execute();
+
+ assertThat(measureRepository.getRawMeasures(VIEW).keys()).hasSize(1);
+
+ Measure measure = measureRepository.getRawMeasure(VIEW, ISSUES_METRIC).get();
+ assertThat(measure.hasVariations()).isTrue();
+ assertThat(measure.getVariations().getVariation1()).isEqualTo(80d);
+ assertThat(measure.getVariations().getVariation2()).isEqualTo(60d);
+ assertThat(measure.getVariations().getVariation3()).isEqualTo(40d);
+ assertThat(measure.getVariations().getVariation4()).isEqualTo(0d);
+ assertThat(measure.getVariations().getVariation5()).isEqualTo(-20d);
+ }
+
+ @Test
+ public void set_variation_on_all_numeric_metrics() {
+ SnapshotDto period1ViewSnapshot = createForProject(VIEW_DTO);
+ dbClient.snapshotDao().insert(session, period1ViewSnapshot);
+ dbClient.measureDao().insert(session,
+ newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 60d),
+ newMeasureDto(DEBT_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 10d),
+ newMeasureDto(FILE_COMPLEXITY_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 2d),
+ newMeasureDto(BUILD_BREAKER_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 1d)
+ );
+ session.commit();
+
+ periodsHolder.setPeriods(newPeriod(1, period1ViewSnapshot));
+
+ treeRootHolder.setRoot(VIEW);
+
+ addRawMeasure(VIEW, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
+ addRawMeasure(VIEW, DEBT_METRIC, Measure.newMeasureBuilder().create(5L, null));
+ addRawMeasure(VIEW, FILE_COMPLEXITY_METRIC, Measure.newMeasureBuilder().create(3d, null));
+ addRawMeasure(VIEW, BUILD_BREAKER_METRIC, Measure.newMeasureBuilder().create(false, null));
+
+ underTest.execute();
+
+ assertThat(measureRepository.getRawMeasures(VIEW).keys()).hasSize(4);
+
+ assertThat(measureRepository.getRawMeasure(VIEW, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(20d);
+ assertThat(measureRepository.getRawMeasure(VIEW, DEBT_METRIC).get().getVariations().getVariation1()).isEqualTo(-5d);
+ assertThat(measureRepository.getRawMeasure(VIEW, FILE_COMPLEXITY_METRIC).get().getVariations().getVariation1()).isEqualTo(1d);
+ assertThat(measureRepository.getRawMeasure(VIEW, BUILD_BREAKER_METRIC).get().getVariations().getVariation1()).isEqualTo(-1d);
+ }
+
+ private static MeasureDto newMeasureDto(int metricId, long projectId, long snapshotId, double value) {
+ return new MeasureDto().setMetricId(metricId).setComponentId(projectId).setSnapshotId(snapshotId).setValue(value);
+ }
+
+ private static Period newPeriod(int index, SnapshotDto snapshotDto) {
+ return new Period(index, "mode", null, snapshotDto.getCreatedAt(), snapshotDto.getId());
+ }
+
+ private void addRawMeasure(Component component, Metric metric, Measure measure) {
+ measureRepository.add(component, metric, measure);
+ }
+}
+++ /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.step;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.ComponentTesting;
-import org.sonar.db.component.SnapshotDto;
-import org.sonar.db.measure.MeasureDto;
-import org.sonar.server.computation.batch.BatchReportReaderRule;
-import org.sonar.server.computation.batch.TreeRootHolderRule;
-import org.sonar.server.computation.component.Component;
-import org.sonar.server.computation.component.ViewsComponent;
-import org.sonar.server.computation.measure.Measure;
-import org.sonar.server.computation.measure.MeasureRepositoryRule;
-import org.sonar.server.computation.metric.Metric;
-import org.sonar.server.computation.metric.MetricImpl;
-import org.sonar.server.computation.metric.MetricRepositoryRule;
-import org.sonar.server.computation.period.Period;
-import org.sonar.server.computation.period.PeriodsHolderRule;
-import org.sonar.test.DbTests;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.server.component.SnapshotTesting.createForComponent;
-import static org.sonar.server.component.SnapshotTesting.createForProject;
-import static org.sonar.server.component.SnapshotTesting.createForView;
-
-@Category(DbTests.class)
-public class ViewsFillMeasuresWithVariationsStepTest {
-
- static final Metric ISSUES_METRIC = new MetricImpl(1, "violations", "violations", Metric.MetricType.INT);
- static final Metric DEBT_METRIC = new MetricImpl(2, "sqale_index", "sqale_index", Metric.MetricType.WORK_DUR);
- static final Metric FILE_COMPLEXITY_METRIC = new MetricImpl(3, "file_complexity", "file_complexity", Metric.MetricType.FLOAT);
- static final Metric BUILD_BREAKER_METRIC = new MetricImpl(4, "build_breaker", "build_breaker", Metric.MetricType.BOOL);
-
- static final ComponentDto VIEW_DTO = ComponentTesting.newView();
-
- static final Component VIEW = ViewsComponent.builder(Component.Type.VIEW, 1).setUuid(VIEW_DTO.uuid()).build();
-
- @Rule
- public DbTester dbTester = DbTester.create(System2.INSTANCE);
-
- @Rule
- public BatchReportReaderRule reportReader = new BatchReportReaderRule();
-
- @Rule
- public PeriodsHolderRule periodsHolder = new PeriodsHolderRule();
-
- @Rule
- public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
-
- @Rule
- public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
- .add(ISSUES_METRIC)
- .add(DEBT_METRIC)
- .add(FILE_COMPLEXITY_METRIC)
- .add(BUILD_BREAKER_METRIC);
-
- @Rule
- public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
-
- DbSession session = dbTester.getSession();
-
- DbClient dbClient = dbTester.getDbClient();
-
- FillMeasuresWithVariationsStep underTest;
-
- @Before
- public void setUp() {
- dbTester.truncateTables();
- dbClient.componentDao().insert(session, VIEW_DTO);
- session.commit();
-
- underTest = new FillMeasuresWithVariationsStep(dbClient, treeRootHolder, periodsHolder, metricRepository, measureRepository);
- }
-
- @Test
- public void do_nothing_when_no_raw_measure() {
- SnapshotDto period1ViewSnapshot = createForView(VIEW_DTO);
- dbClient.snapshotDao().insert(session, period1ViewSnapshot);
- dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 60d));
- session.commit();
-
- periodsHolder.setPeriods(newPeriod(1, period1ViewSnapshot));
-
- treeRootHolder.setRoot(VIEW);
-
- underTest.execute();
-
- assertThat(measureRepository.getRawMeasures(VIEW).keys()).isEmpty();
- }
-
- @Test
- public void do_nothing_when_no_period() {
- Component view = ViewsComponent.builder(Component.Type.VIEW, 1).setUuid(VIEW_DTO.uuid()).build();
- treeRootHolder.setRoot(view);
- periodsHolder.setPeriods();
-
- underTest.execute();
-
- assertThat(measureRepository.getRawMeasures(view).keys()).isEmpty();
- }
-
- @Test
- public void set_variation() {
- // View
- SnapshotDto period1ViewSnapshot = createForView(VIEW_DTO);
- dbClient.snapshotDao().insert(session, period1ViewSnapshot);
- dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 60d));
-
- // SubView
- ComponentDto subviewDto = ComponentTesting.newSubView(VIEW_DTO, "dir", "key");
- dbClient.componentDao().insert(session, subviewDto);
- SnapshotDto period1SubviewSnapshot = createForComponent(subviewDto, period1ViewSnapshot);
- dbClient.snapshotDao().insert(session, period1SubviewSnapshot);
- dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), subviewDto.getId(), period1SubviewSnapshot.getId(), 10d));
- session.commit();
-
- periodsHolder.setPeriods(newPeriod(1, period1ViewSnapshot));
-
- Component subview = ViewsComponent.builder(Component.Type.SUBVIEW, 2).setUuid(subviewDto.uuid()).build();
- Component view = ViewsComponent.builder(Component.Type.VIEW, 1).setUuid(VIEW_DTO.uuid()).addChildren(subview).build();
- treeRootHolder.setRoot(view);
-
- addRawMeasure(view, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
- addRawMeasure(subview, ISSUES_METRIC, Measure.newMeasureBuilder().create(20, null));
-
- underTest.execute();
-
- assertThat(measureRepository.getRawMeasure(view, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(20d);
- assertThat(measureRepository.getRawMeasure(subview, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(10d);
- }
-
- @Test
- public void set_variations_on_all_periods() {
- SnapshotDto period1ViewSnapshot = createForProject(VIEW_DTO).setLast(false);
- SnapshotDto period2ViewSnapshot = createForProject(VIEW_DTO).setLast(false);
- SnapshotDto period3ViewSnapshot = createForProject(VIEW_DTO).setLast(false);
- SnapshotDto period4ViewSnapshot = createForProject(VIEW_DTO).setLast(false);
- SnapshotDto period5ViewSnapshot = createForProject(VIEW_DTO).setLast(false);
- dbClient.snapshotDao().insert(session, period1ViewSnapshot, period2ViewSnapshot, period3ViewSnapshot, period4ViewSnapshot, period5ViewSnapshot);
-
- dbClient.measureDao().insert(session,
- newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 0d),
- newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period2ViewSnapshot.getId(), 20d),
- newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period3ViewSnapshot.getId(), 40d),
- newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period4ViewSnapshot.getId(), 80d),
- newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period5ViewSnapshot.getId(), 100d));
- session.commit();
-
- periodsHolder.setPeriods(newPeriod(1, period1ViewSnapshot),
- newPeriod(2, period2ViewSnapshot),
- newPeriod(3, period3ViewSnapshot),
- newPeriod(4, period4ViewSnapshot),
- newPeriod(5, period5ViewSnapshot));
-
- treeRootHolder.setRoot(VIEW);
-
- addRawMeasure(VIEW, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
-
- underTest.execute();
-
- assertThat(measureRepository.getRawMeasures(VIEW).keys()).hasSize(1);
-
- Measure measure = measureRepository.getRawMeasure(VIEW, ISSUES_METRIC).get();
- assertThat(measure.hasVariations()).isTrue();
- assertThat(measure.getVariations().getVariation1()).isEqualTo(80d);
- assertThat(measure.getVariations().getVariation2()).isEqualTo(60d);
- assertThat(measure.getVariations().getVariation3()).isEqualTo(40d);
- assertThat(measure.getVariations().getVariation4()).isEqualTo(0d);
- assertThat(measure.getVariations().getVariation5()).isEqualTo(-20d);
- }
-
- @Test
- public void set_variation_on_all_numeric_metrics() {
- SnapshotDto period1ViewSnapshot = createForProject(VIEW_DTO);
- dbClient.snapshotDao().insert(session, period1ViewSnapshot);
- dbClient.measureDao().insert(session,
- newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 60d),
- newMeasureDto(DEBT_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 10d),
- newMeasureDto(FILE_COMPLEXITY_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 2d),
- newMeasureDto(BUILD_BREAKER_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 1d)
- );
- session.commit();
-
- periodsHolder.setPeriods(newPeriod(1, period1ViewSnapshot));
-
- treeRootHolder.setRoot(VIEW);
-
- addRawMeasure(VIEW, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
- addRawMeasure(VIEW, DEBT_METRIC, Measure.newMeasureBuilder().create(5L, null));
- addRawMeasure(VIEW, FILE_COMPLEXITY_METRIC, Measure.newMeasureBuilder().create(3d, null));
- addRawMeasure(VIEW, BUILD_BREAKER_METRIC, Measure.newMeasureBuilder().create(false, null));
-
- underTest.execute();
-
- assertThat(measureRepository.getRawMeasures(VIEW).keys()).hasSize(4);
-
- assertThat(measureRepository.getRawMeasure(VIEW, ISSUES_METRIC).get().getVariations().getVariation1()).isEqualTo(20d);
- assertThat(measureRepository.getRawMeasure(VIEW, DEBT_METRIC).get().getVariations().getVariation1()).isEqualTo(-5d);
- assertThat(measureRepository.getRawMeasure(VIEW, FILE_COMPLEXITY_METRIC).get().getVariations().getVariation1()).isEqualTo(1d);
- assertThat(measureRepository.getRawMeasure(VIEW, BUILD_BREAKER_METRIC).get().getVariations().getVariation1()).isEqualTo(-1d);
- }
-
- private static MeasureDto newMeasureDto(int metricId, long projectId, long snapshotId, double value) {
- return new MeasureDto().setMetricId(metricId).setComponentId(projectId).setSnapshotId(snapshotId).setValue(value);
- }
-
- private static Period newPeriod(int index, SnapshotDto snapshotDto) {
- return new Period(index, "mode", null, snapshotDto.getCreatedAt(), snapshotDto.getId());
- }
-
- private void addRawMeasure(Component component, Metric metric, Measure measure) {
- measureRepository.add(component, metric, measure);
- }
-}
*/
package org.sonar.batch.bootstrap;
-import javax.annotation.CheckForNull;
-
-import org.sonar.batch.analysis.DefaultAnalysisMode;
-import org.sonar.batch.cache.PersistentCacheProvider;
-import org.sonar.batch.cache.WSLoader.LoadStrategy;
-import org.sonar.batch.analysis.AnalysisProperties;
-import org.sonar.batch.cache.StrategyWSLoaderProvider;
-import org.sonar.batch.cache.ProjectSyncContainer;
-import org.sonar.batch.rule.RulesLoader;
-import org.sonar.batch.rule.DefaultRulesLoader;
-import org.sonar.batch.rule.RulesProvider;
-
import java.util.List;
import java.util.Map;
-
+import javax.annotation.CheckForNull;
import org.sonar.api.CoreProperties;
import org.sonar.api.SonarPlugin;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.UriReader;
+import org.sonar.batch.analysis.AnalysisProperties;
+import org.sonar.batch.analysis.DefaultAnalysisMode;
+import org.sonar.batch.cache.PersistentCacheProvider;
+import org.sonar.batch.cache.ProjectSyncContainer;
+import org.sonar.batch.cache.StrategyWSLoaderProvider;
+import org.sonar.batch.cache.WSLoader.LoadStrategy;
import org.sonar.batch.index.CachesManager;
import org.sonar.batch.platform.DefaultServer;
import org.sonar.batch.repository.DefaultGlobalRepositoriesLoader;
import org.sonar.batch.repository.GlobalRepositoriesLoader;
import org.sonar.batch.repository.GlobalRepositoriesProvider;
+import org.sonar.batch.rule.DefaultRulesLoader;
+import org.sonar.batch.rule.RulesLoader;
+import org.sonar.batch.rule.RulesProvider;
import org.sonar.batch.scan.ProjectScanContainer;
-import org.sonar.core.config.Logback;
import org.sonar.core.platform.ComponentContainer;
import org.sonar.core.platform.PluginClassloaderFactory;
import org.sonar.core.platform.PluginInfo;
GlobalSettings.class,
new RulesProvider(),
ServerClient.class,
- Logback.class,
DefaultServer.class,
new GlobalTempFolderProvider(),
DefaultHttpDownloader.class,
*/
package org.sonar.batch.bootstrap;
-import org.sonar.api.batch.BatchSide;
-
-import org.junit.Rule;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.CoreProperties;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
-import org.junit.Test;
-import org.sonar.api.utils.TempFolder;
-import org.sonar.core.config.Logback;
-
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.batch.BatchSide;
+import org.sonar.api.utils.TempFolder;
+import org.sonar.core.util.UuidFactory;
import static org.assertj.core.api.Assertions.assertThat;
public void should_add_components() {
GlobalContainer container = createContainer(Collections.emptyList());
- assertThat(container.getComponentByType(Logback.class)).isNotNull();
+ assertThat(container.getComponentByType(UuidFactory.class)).isNotNull();
assertThat(container.getComponentByType(TempFolder.class)).isNotNull();
}
import org.apache.commons.io.IOUtils;
import org.slf4j.LoggerFactory;
import org.sonar.api.batch.BatchSide;
-import org.sonar.api.server.ServerSide;
/**
* Configure Logback
* @since 2.12
*/
@BatchSide
-@ServerSide
public class Logback {
+ private Logback() {
+ // only statics
+ }
+
public static void configure(String classloaderPath, Map<String, String> substitutionVariables) {
InputStream input = Logback.class.getResourceAsStream(classloaderPath);
if (input == null) {
* Parse format {@link #DATE_FORMAT}. This method never throws exception.
*
* @param s any string
- * @return the date, null if parsing error or null string
+ * @return the date, {@code null} if parsing error or if parameter is {@code null}
* @since 3.0
*/
+ @CheckForNull
public static Date parseDateQuietly(@Nullable String s) {
Date date = null;
if (s != null) {
* Parse format {@link #DATETIME_FORMAT}. This method never throws exception.
*
* @param s any string
- * @return the datetime, null if parsing error or null string
+ * @return the datetime, {@code null} if parsing error or if parameter is {@code null}
*/
+ @CheckForNull
public static Date parseDateTimeQuietly(@Nullable String s) {
Date datetime = null;
if (s != null) {