--- /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.formula;
+
+import java.util.List;
+
+public interface CoreFormulaRepository {
+
+ List<Formula> getFormulas();
+
+}
import static org.sonar.api.measures.CoreMetrics.GENERATED_NCLOC_KEY;
import static org.sonar.api.measures.CoreMetrics.STATEMENTS_KEY;
-public class CoreFormulaRepositoryImpl implements FormulaRepository {
+public class CoreFormulaRepositoryImpl implements CoreFormulaRepository {
private static final List<Formula> FORMULAS = ImmutableList.<Formula>of(
// TODO When all decorators will be moved to CE, uncomment commented lines to activate all formulas and remove formulas declaration in
package org.sonar.server.computation.formula;
import com.google.common.base.Optional;
+import java.util.List;
import org.sonar.server.computation.measure.Measure;
+import org.sonar.server.computation.period.Period;
public interface CounterContext {
Optional<Measure> getMeasure(String metricKey);
+ /**
+ * Lists of Periods defined for the current project. They can be used to aggregate values of MeasureVariations.
+ */
+ List<Period> getPeriods();
+
}
--- /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.formula;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.CheckForNull;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.component.PathAwareVisitor;
+import org.sonar.server.computation.measure.Measure;
+import org.sonar.server.computation.measure.MeasureRepository;
+import org.sonar.server.computation.metric.Metric;
+import org.sonar.server.computation.metric.MetricRepository;
+import org.sonar.server.computation.period.Period;
+import org.sonar.server.computation.period.PeriodsHolder;
+
+import static java.util.Objects.requireNonNull;
+
+public class FormulaExecutorComponentVisitor extends PathAwareVisitor<FormulaExecutorComponentVisitor.Counters> {
+ private static final PathAwareVisitor.SimpleStackElementFactory<Counters> COUNTERS_FACTORY = new PathAwareVisitor.SimpleStackElementFactory<Counters>() {
+
+ @Override
+ public Counters createForAny(Component component) {
+ return new Counters();
+ }
+
+ @Override
+ public Counters createForFile(Component component) {
+ // No need to create a counter on file levels
+ return null;
+ }
+ };
+
+ @CheckForNull
+ private final PeriodsHolder periodsHolder;
+ private final MetricRepository metricRepository;
+ private final MeasureRepository measureRepository;
+ private final List<Formula> formulas;
+
+ private FormulaExecutorComponentVisitor(Builder builder, List<Formula> formulas) {
+ super(Component.Type.FILE, Order.POST_ORDER, COUNTERS_FACTORY);
+ this.periodsHolder = builder.periodsHolder;
+ this.measureRepository = builder.measureRepository;
+ this.metricRepository = builder.metricRepository;
+ this.formulas = ImmutableList.copyOf(formulas);
+ }
+
+ public static Builder newBuilder(MetricRepository metricRepository, MeasureRepository measureRepository) {
+ return new Builder(metricRepository, measureRepository);
+ }
+
+ public static class Builder {
+ private final MetricRepository metricRepository;
+ private final MeasureRepository measureRepository;
+ @CheckForNull
+ private PeriodsHolder periodsHolder;
+
+ private Builder(MetricRepository metricRepository, MeasureRepository measureRepository) {
+ this.metricRepository = requireNonNull(metricRepository);
+ this.measureRepository = requireNonNull(measureRepository);
+ }
+
+ public Builder create(MetricRepository metricRepository, MeasureRepository measureRepository) {
+ return new Builder(metricRepository, measureRepository);
+ }
+
+ public Builder withVariationSupport(PeriodsHolder periodsHolder) {
+ this.periodsHolder = requireNonNull(periodsHolder);
+ return this;
+ }
+
+ public FormulaExecutorComponentVisitor buildFor(List<Formula> formulas) {
+ return new FormulaExecutorComponentVisitor(this, formulas);
+ }
+ }
+
+
+
+ @Override
+ protected void visitProject(Component project, Path<FormulaExecutorComponentVisitor.Counters> path) {
+ processNotFile(project, path);
+ }
+
+ @Override
+ protected void visitModule(Component module, Path<FormulaExecutorComponentVisitor.Counters> path) {
+ processNotFile(module, path);
+ }
+
+ @Override
+ protected void visitDirectory(Component directory, Path<FormulaExecutorComponentVisitor.Counters> path) {
+ processNotFile(directory, path);
+ }
+
+ @Override
+ protected void visitFile(Component file, Path<FormulaExecutorComponentVisitor.Counters> path) {
+ processFile(file, path);
+ }
+
+ private void processNotFile(Component component, Path<FormulaExecutorComponentVisitor.Counters> path) {
+ for (Formula formula : formulas) {
+ Counter counter = path.current().getCounter(formula.getOutputMetricKey());
+ // If there were no file under this node, the counter won't be initialized
+ if (counter != null) {
+ addNewMeasure(component, formula, counter);
+ aggregateToParent(path, formula, counter);
+ }
+ }
+ }
+
+ private void processFile(Component file, Path<FormulaExecutorComponentVisitor.Counters> path) {
+ CounterContext counterContext = new CounterContextImpl(file);
+ for (Formula formula : formulas) {
+ Counter counter = formula.createNewCounter();
+ counter.aggregate(counterContext);
+ addNewMeasure(file, formula, counter);
+ aggregateToParent(path, formula, counter);
+ }
+ }
+
+ private void addNewMeasure(Component component, Formula formula, Counter counter) {
+ Metric metric = metricRepository.getByKey(formula.getOutputMetricKey());
+ Optional<Measure> measure = formula.createMeasure(counter, component.getType());
+ if (measure.isPresent()) {
+ measureRepository.add(component, metric, measure.get());
+ }
+ }
+
+ private void aggregateToParent(Path<FormulaExecutorComponentVisitor.Counters> path, Formula formula, Counter currentCounter) {
+ if (!path.isRoot()) {
+ path.parent().aggregate(formula.getOutputMetricKey(), currentCounter);
+ }
+ }
+
+ private class CounterContextImpl implements CounterContext {
+ private final Component file;
+
+ public CounterContextImpl(Component file) {
+ this.file = file;
+ }
+
+ @Override
+ public Optional<Measure> getMeasure(String metricKey) {
+ return measureRepository.getRawMeasure(file, metricRepository.getByKey(metricKey));
+ }
+
+ @Override
+ public List<Period> getPeriods() {
+ return periodsHolder.getPeriods();
+ }
+ }
+
+ public static class Counters {
+ Map<String, Counter> countersByFormula = new HashMap<>();
+
+ public void aggregate(String metricKey, Counter childCounter) {
+ Counter counter = countersByFormula.get(metricKey);
+ if (counter == null) {
+ countersByFormula.put(metricKey, childCounter);
+ } else {
+ counter.aggregate(childCounter);
+ }
+ }
+
+ /**
+ * Counter can be null on a level when it has not been fed by children levels
+ */
+ @CheckForNull
+ public Counter getCounter(String metricKey) {
+ return countersByFormula.get(metricKey);
+ }
+ }
+}
+++ /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.formula;
-
-import java.util.List;
-
-public interface FormulaRepository {
-
- List<Formula> getFormulas();
-
-}
--- /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.formula.counter;
+
+import com.google.common.base.Optional;
+import javax.annotation.Nullable;
+import org.sonar.server.computation.formula.Counter;
+import org.sonar.server.computation.measure.MeasureVariations;
+import org.sonar.server.computation.period.PeriodsHolder;
+
+import static org.sonar.server.computation.period.PeriodsHolder.MAX_NUMBER_OF_PERIODS;
+
+/**
+ * Convenience class wrapping a double to compute the value of a MeasureVariation as an double and know it is has ever
+ * been set.
+ * <p>
+ * Basically, this class will be used in a {@link Counter} implementation as an array property which can be easily
+ * creating using method {@link #newArray()}.
+ * </p>
+ */
+public class DoubleVariationValue {
+ private boolean set = false;
+ private double value = 0L;
+
+ public void increment(double increment) {
+ this.value += increment;
+ this.set = true;
+ }
+
+ public void increment(@Nullable DoubleVariationValue value) {
+ if (value != null) {
+ increment(value.value);
+ }
+ }
+
+ public boolean isSet() {
+ return set;
+ }
+
+ public double getValue() {
+ return value;
+ }
+
+ /**
+ * Creates a new Array of {@link DoubleVariationValue} of size {@link PeriodsHolder#MAX_NUMBER_OF_PERIODS},
+ * initialized with newly creates {@link DoubleVariationValue} instances.
+ */
+ public static Array newArray() {
+ return new Array();
+ }
+
+ public static class Array {
+ private final DoubleVariationValue[] values;
+
+ public Array() {
+ this.values = new DoubleVariationValue[MAX_NUMBER_OF_PERIODS];
+ for (int i = 0; i < MAX_NUMBER_OF_PERIODS; i++) {
+ this.values[i] = new DoubleVariationValue();
+ }
+ }
+
+ public void increment(int index, double value) {
+ this.values[index].increment(value);
+ }
+
+ public void incrementAll(Array source) {
+ for (int i = 0; i < this.values.length; i++) {
+ if (source.values[i].isSet()) {
+ this.values[i].increment(source.values[i]);
+ }
+ }
+ }
+
+ /**
+ * Creates a new MeasureVariations from the current array.
+ *
+ * @throws IllegalArgumentException if none of the {@link DoubleVariationValue} in the array is set
+ */
+ public Optional<MeasureVariations> toMeasureVariations() {
+ if (!isAnySet()) {
+ return Optional.absent();
+ }
+ Double[] variations = new Double[values.length];
+ for (int i = 0; i < values.length; i++) {
+ if (values[i].isSet()) {
+ variations[i] = (double) values[i].getValue();
+ }
+ }
+ return Optional.of(new MeasureVariations(variations));
+ }
+
+ private boolean isAnySet() {
+ for (DoubleVariationValue value : values) {
+ if (value.isSet()) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+}
--- /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.formula.counter;
+
+import com.google.common.base.Optional;
+import javax.annotation.Nullable;
+import org.sonar.server.computation.formula.Counter;
+import org.sonar.server.computation.measure.MeasureVariations;
+import org.sonar.server.computation.period.PeriodsHolder;
+
+import static org.sonar.server.computation.period.PeriodsHolder.MAX_NUMBER_OF_PERIODS;
+
+/**
+ * Convenience class wrapping a int to compute the value of a MeasureVariation as an int and know it is has ever been
+ * set.
+ * <p>
+ * Basically, this class will be used in a {@link Counter} implementation as an array property which can be easily
+ * creating using method {@link #newArray()}.
+ * </p>
+ */
+public class IntVariationValue {
+ private boolean set = false;
+ private int value = 0;
+
+ public void increment(int increment) {
+ this.value += increment;
+ this.set = true;
+ }
+
+ public void increment(@Nullable IntVariationValue value) {
+ if (value != null) {
+ increment(value.value);
+ }
+ }
+
+ public boolean isSet() {
+ return set;
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ /**
+ * Creates a new Array of {@link IntVariationValue} of size {@link PeriodsHolder#MAX_NUMBER_OF_PERIODS},
+ * initialized with newly creates {@link IntVariationValue} instances.
+ */
+ public static Array newArray() {
+ return new Array();
+ }
+
+ public static class Array {
+ private final IntVariationValue[] values;
+
+ public Array() {
+ this.values = new IntVariationValue[MAX_NUMBER_OF_PERIODS];
+ for (int i = 0; i < MAX_NUMBER_OF_PERIODS; i++) {
+ this.values[i] = new IntVariationValue();
+ }
+ }
+
+ public void increment(int index, int value) {
+ this.values[index].increment(value);
+ }
+
+ public void incrementAll(Array source) {
+ for (int i = 0; i < this.values.length; i++) {
+ if (source.values[i].isSet()) {
+ this.values[i].increment(source.values[i]);
+ }
+ }
+ }
+
+ /**
+ * Creates a new MeasureVariations from the current array.
+ *
+ * @throws IllegalArgumentException if none of the {@link IntVariationValue} in the array is set
+ */
+ public Optional<MeasureVariations> toMeasureVariations() {
+ if (!isAnySet()) {
+ return Optional.absent();
+ }
+ Double[] variations = new Double[values.length];
+ for (int i = 0; i < values.length; i++) {
+ if (values[i].isSet()) {
+ variations[i] = (double) values[i].getValue();
+ }
+ }
+ return Optional.of(new MeasureVariations(variations));
+ }
+
+ private boolean isAnySet() {
+ for (IntVariationValue value : values) {
+ if (value.isSet()) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+}
--- /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.formula.counter;
+
+import com.google.common.base.Optional;
+import javax.annotation.Nullable;
+import org.sonar.server.computation.measure.MeasureVariations;
+import org.sonar.server.computation.period.PeriodsHolder;
+
+/**
+ * Convenience class wrapping a long to compute the value of a MeasureVariation as an long and know it is has ever been
+ * set.
+ * <p>
+ * Basically, this class will be used in a {@link Counter} implementation as an array property which can be easily
+ * creating using method {@link #newArray()}.
+ * </p>
+ */
+import static org.sonar.server.computation.period.PeriodsHolder.MAX_NUMBER_OF_PERIODS;
+
+public class LongVariationValue {
+ private boolean set = false;
+ private long value = 0L;
+
+ public void increment(long increment) {
+ this.value += increment;
+ this.set = true;
+ }
+
+ public void increment(@Nullable LongVariationValue value) {
+ if (value != null) {
+ increment(value.value);
+ }
+ }
+
+ public boolean isSet() {
+ return set;
+ }
+
+ public long getValue() {
+ return value;
+ }
+
+ /**
+ * Creates a new Array of {@link LongVariationValue} of size {@link PeriodsHolder#MAX_NUMBER_OF_PERIODS},
+ * initialized with newly creates {@link LongVariationValue} instances.
+ */
+ public static Array newArray() {
+ return new Array();
+ }
+
+ public static class Array {
+ private final LongVariationValue[] values;
+
+ public Array() {
+ this.values = new LongVariationValue[MAX_NUMBER_OF_PERIODS];
+ for (int i = 0; i < MAX_NUMBER_OF_PERIODS; i++) {
+ this.values[i] = new LongVariationValue();
+ }
+ }
+
+ public void increment(int index, long value) {
+ this.values[index].increment(value);
+ }
+
+ public void incrementAll(Array source) {
+ for (int i = 0; i < this.values.length; i++) {
+ if (source.values[i].isSet()) {
+ this.values[i].increment(source.values[i]);
+ }
+ }
+ }
+
+ /**
+ * Creates a new MeasureVariations from the current array.
+ *
+ * @throws IllegalArgumentException if none of the {@link LongVariationValue} in the array is set
+ */
+ public Optional<MeasureVariations> toMeasureVariations() {
+ if (!isAnySet()) {
+ return Optional.absent();
+ }
+ Double[] variations = new Double[values.length];
+ for (int i = 0; i < values.length; i++) {
+ if (values[i].isSet()) {
+ variations[i] = (double) values[i].getValue();
+ }
+ }
+ return Optional.of(new MeasureVariations(variations));
+ }
+
+ private boolean isAnySet() {
+ for (LongVariationValue value : values) {
+ if (value.isSet()) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+}
// data computation
IntegrateIssuesStep.class,
+ CoreMetricFormulaExecutorStep.class,
CustomMeasuresCopyStep.class,
- ComputeFormulaMeasuresStep.class,
// SQALE measures depend on issues
SqaleMeasuresStep.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 java.util.HashMap;
-import java.util.Map;
-import javax.annotation.CheckForNull;
-import org.sonar.server.computation.component.Component;
-import org.sonar.server.computation.component.ComponentVisitor;
-import org.sonar.server.computation.component.PathAwareVisitor;
-import org.sonar.server.computation.component.TreeRootHolder;
-import org.sonar.server.computation.formula.Counter;
-import org.sonar.server.computation.formula.CounterContext;
-import org.sonar.server.computation.formula.Formula;
-import org.sonar.server.computation.formula.FormulaRepository;
-import org.sonar.server.computation.measure.Measure;
-import org.sonar.server.computation.measure.MeasureRepository;
-import org.sonar.server.computation.metric.Metric;
-import org.sonar.server.computation.metric.MetricRepository;
-
-public class ComputeFormulaMeasuresStep implements ComputationStep {
-
- private final TreeRootHolder treeRootHolder;
- private final MeasureRepository measureRepository;
- private final MetricRepository metricRepository;
- private final FormulaRepository formulaRepository;
-
- public ComputeFormulaMeasuresStep(TreeRootHolder treeRootHolder, MeasureRepository measureRepository, MetricRepository metricRepository, FormulaRepository formulaRepository) {
- this.treeRootHolder = treeRootHolder;
- this.measureRepository = measureRepository;
- this.metricRepository = metricRepository;
- this.formulaRepository = formulaRepository;
- }
-
- @Override
- public void execute() {
- new ComputeFormulaMeasureVisitor().visit(treeRootHolder.getRoot());
- }
-
- private class ComputeFormulaMeasureVisitor extends PathAwareVisitor<Counters> {
-
- public ComputeFormulaMeasureVisitor() {
- super(Component.Type.FILE, ComponentVisitor.Order.POST_ORDER, new SimpleStackElementFactory<Counters>() {
-
- @Override
- public Counters createForAny(Component component) {
- return new Counters();
- }
-
- @Override
- public Counters createForFile(Component component) {
- // No need to create a counter on file levels
- return null;
- }
- });
- }
-
- @Override
- protected void visitProject(Component project, Path<Counters> path) {
- processNotFile(project, path);
- }
-
- @Override
- protected void visitModule(Component module, Path<Counters> path) {
- processNotFile(module, path);
- }
-
- @Override
- protected void visitDirectory(Component directory, Path<Counters> path) {
- processNotFile(directory, path);
- }
-
- @Override
- protected void visitFile(Component file, Path<Counters> path) {
- processFile(file, path);
- }
-
- private void processNotFile(Component component, PathAwareVisitor.Path<Counters> path) {
- for (Formula formula : formulaRepository.getFormulas()) {
- Counter counter = path.current().getCounter(formula.getOutputMetricKey());
- // If there were no file under this node, the counter won't be initialized
- if (counter != null) {
- addNewMeasure(component, formula, counter);
- aggregateToParent(path, formula, counter);
- }
- }
- }
-
- private void processFile(Component file, PathAwareVisitor.Path<Counters> path) {
- CounterContext counterContext = new CounterContextImpl(file);
- for (Formula formula : formulaRepository.getFormulas()) {
- Counter counter = newCounter(formula);
- counter.aggregate(counterContext);
- addNewMeasure(file, formula, counter);
- aggregateToParent(path, formula, counter);
- }
- }
-
- private void addNewMeasure(Component component, Formula formula, Counter counter) {
- Metric metric = metricRepository.getByKey(formula.getOutputMetricKey());
- Optional<Measure> measure = formula.createMeasure(counter, component.getType());
- if (measure.isPresent()) {
- measureRepository.add(component, metric, measure.get());
- }
- }
-
- private void aggregateToParent(PathAwareVisitor.Path<Counters> path, Formula formula, Counter currentCounter) {
- if (!path.isRoot()) {
- path.parent().aggregate(formula.getOutputMetricKey(), currentCounter);
- }
- }
- }
-
- private static Counter newCounter(Formula formula) {
- return formula.createNewCounter();
- }
-
- @Override
- public String getDescription() {
- return "Compute formula measures";
- }
-
- private static class Counters {
- Map<String, Counter> countersByMetricKey = new HashMap<>();
-
- public void aggregate(String metricKey, Counter childCounter) {
- Counter counter = countersByMetricKey.get(metricKey);
- if (counter == null) {
- countersByMetricKey.put(metricKey, childCounter);
- } else {
- counter.aggregate(childCounter);
- }
- }
-
- /**
- * Counter can be null on a level when it has not been fed by children levels
- */
- @CheckForNull
- public Counter getCounter(String metricKey) {
- return countersByMetricKey.get(metricKey);
- }
- }
-
- private class CounterContextImpl implements CounterContext {
-
- private final Component file;
-
- public CounterContextImpl(Component file) {
- this.file = file;
- }
-
- @Override
- public Optional<Measure> getMeasure(String metricKey) {
- return measureRepository.getRawMeasure(file, metricRepository.getByKey(metricKey));
- }
- }
-}
--- /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.sonar.server.computation.component.TreeRootHolder;
+import org.sonar.server.computation.formula.CoreFormulaRepository;
+import org.sonar.server.computation.formula.FormulaExecutorComponentVisitor;
+import org.sonar.server.computation.measure.MeasureRepository;
+import org.sonar.server.computation.metric.MetricRepository;
+
+public class CoreMetricFormulaExecutorStep implements ComputationStep {
+
+ private final TreeRootHolder treeRootHolder;
+ private final MetricRepository metricRepository;
+ private final MeasureRepository measureRepository;
+ private final CoreFormulaRepository coreFormulaRepository;
+
+ public CoreMetricFormulaExecutorStep(TreeRootHolder treeRootHolder,
+ MetricRepository metricRepository, MeasureRepository measureRepository,
+ CoreFormulaRepository coreFormulaRepository) {
+ this.treeRootHolder = treeRootHolder;
+ this.metricRepository = metricRepository;
+ this.measureRepository = measureRepository;
+ this.coreFormulaRepository = coreFormulaRepository;
+ }
+
+ @Override
+ public void execute() {
+ FormulaExecutorComponentVisitor.newBuilder(metricRepository, measureRepository)
+ .buildFor(coreFormulaRepository.getFormulas())
+ .visit(treeRootHolder.getRoot());
+ }
+
+ @Override
+ public String getDescription() {
+ return "Execute formula to compute measures of Core metrics";
+ }
+
+}
--- /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.formula;
+
+import com.google.common.collect.Lists;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.server.computation.batch.TreeRootHolderRule;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.component.DumbComponent;
+import org.sonar.server.computation.measure.MeasureRepositoryRule;
+import org.sonar.server.computation.metric.MetricRepositoryRule;
+import org.sonar.server.computation.period.PeriodsHolderRule;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.api.measures.CoreMetrics.COMPLEXITY_IN_FUNCTIONS_KEY;
+import static org.sonar.api.measures.CoreMetrics.FUNCTIONS_KEY;
+import static org.sonar.api.measures.CoreMetrics.FUNCTION_COMPLEXITY_KEY;
+import static org.sonar.server.computation.component.Component.Type.DIRECTORY;
+import static org.sonar.server.computation.component.Component.Type.MODULE;
+import static org.sonar.server.computation.component.Component.Type.PROJECT;
+import static org.sonar.server.computation.component.DumbComponent.builder;
+import static org.sonar.server.computation.measure.Measure.newMeasureBuilder;
+import static org.sonar.server.computation.measure.MeasureRepoEntry.entryOf;
+import static org.sonar.server.computation.measure.MeasureRepoEntry.toEntries;
+
+public class AverageFormulaExecutionTest {
+
+ @Rule
+ public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
+ @Rule
+ public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
+ .add(CoreMetrics.FUNCTION_COMPLEXITY)
+ .add(CoreMetrics.COMPLEXITY_IN_FUNCTIONS)
+ .add(CoreMetrics.FUNCTIONS);
+ @Rule
+ public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
+ @Rule
+ public PeriodsHolderRule periodsHolder = new PeriodsHolderRule();
+
+ FormulaExecutorComponentVisitor sut;
+
+ @Before
+ public void setUp() throws Exception {
+ sut = FormulaExecutorComponentVisitor.newBuilder(metricRepository, measureRepository)
+ .buildFor(Lists.<Formula>newArrayList(
+ AverageFormula.Builder.newBuilder()
+ .setOutputMetricKey(FUNCTION_COMPLEXITY_KEY)
+ .setMainMetricKey(COMPLEXITY_IN_FUNCTIONS_KEY)
+ .setByMetricKey(FUNCTIONS_KEY)
+ .build()));
+ }
+
+ @Test
+ public void add_measures() {
+ DumbComponent project = builder(PROJECT, 1)
+ .addChildren(
+ builder(MODULE, 11)
+ .addChildren(
+ builder(DIRECTORY, 111)
+ .addChildren(
+ builder(Component.Type.FILE, 1111).build(),
+ builder(Component.Type.FILE, 1112).build()
+ ).build()
+ ).build(),
+ builder(MODULE, 12)
+ .addChildren(
+ builder(DIRECTORY, 121)
+ .addChildren(
+ builder(Component.Type.FILE, 1211).build()
+ ).build()
+ ).build()
+ ).build();
+
+ treeRootHolder.setRoot(project);
+
+ measureRepository.addRawMeasure(1111, COMPLEXITY_IN_FUNCTIONS_KEY, newMeasureBuilder().create(5));
+ measureRepository.addRawMeasure(1111, FUNCTIONS_KEY, newMeasureBuilder().create(2));
+
+ measureRepository.addRawMeasure(1112, COMPLEXITY_IN_FUNCTIONS_KEY, newMeasureBuilder().create(1));
+ measureRepository.addRawMeasure(1112, FUNCTIONS_KEY, newMeasureBuilder().create(1));
+
+ measureRepository.addRawMeasure(1211, COMPLEXITY_IN_FUNCTIONS_KEY, newMeasureBuilder().create(9));
+ measureRepository.addRawMeasure(1211, FUNCTIONS_KEY, newMeasureBuilder().create(2));
+
+ sut.visit(project);
+
+ assertThat(toEntries(measureRepository.getNewRawMeasures(1))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(3d)));
+ assertThat(toEntries(measureRepository.getNewRawMeasures(11))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(2d)));
+ assertThat(toEntries(measureRepository.getNewRawMeasures(111))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(2d)));
+ assertThat(toEntries(measureRepository.getNewRawMeasures(1111))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(2.5d)));
+ assertThat(toEntries(measureRepository.getNewRawMeasures(1112))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(1d)));
+ assertThat(toEntries(measureRepository.getNewRawMeasures(12))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(4.5d)));
+ assertThat(toEntries(measureRepository.getNewRawMeasures(121))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(4.5d)));
+ assertThat(toEntries(measureRepository.getNewRawMeasures(1211))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(4.5d)));
+ }
+
+}
+++ /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.formula;
-
-import com.google.common.collect.Lists;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.server.computation.batch.TreeRootHolderRule;
-import org.sonar.server.computation.component.Component;
-import org.sonar.server.computation.component.DumbComponent;
-import org.sonar.server.computation.measure.MeasureRepositoryRule;
-import org.sonar.server.computation.metric.MetricRepositoryRule;
-import org.sonar.server.computation.step.ComputeFormulaMeasuresStep;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.sonar.api.measures.CoreMetrics.COMPLEXITY_IN_FUNCTIONS_KEY;
-import static org.sonar.api.measures.CoreMetrics.FUNCTIONS_KEY;
-import static org.sonar.api.measures.CoreMetrics.FUNCTION_COMPLEXITY_KEY;
-import static org.sonar.server.computation.component.Component.Type.DIRECTORY;
-import static org.sonar.server.computation.component.Component.Type.MODULE;
-import static org.sonar.server.computation.component.Component.Type.PROJECT;
-import static org.sonar.server.computation.component.DumbComponent.builder;
-import static org.sonar.server.computation.measure.Measure.newMeasureBuilder;
-import static org.sonar.server.computation.measure.MeasureRepoEntry.entryOf;
-import static org.sonar.server.computation.measure.MeasureRepoEntry.toEntries;
-
-public class AverageFormulaStepTest {
-
- @Rule
- public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
-
- @Rule
- public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
- .add(CoreMetrics.FUNCTION_COMPLEXITY)
- .add(CoreMetrics.COMPLEXITY_IN_FUNCTIONS)
- .add(CoreMetrics.FUNCTIONS);
-
- @Rule
- public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
-
- ComputeFormulaMeasuresStep sut;
-
- @Before
- public void setUp() {
- FormulaRepository formulaRepository = mock(FormulaRepository.class);
- when(formulaRepository.getFormulas()).thenReturn(Lists.<Formula>newArrayList(
- AverageFormula.Builder.newBuilder()
- .setOutputMetricKey(FUNCTION_COMPLEXITY_KEY)
- .setMainMetricKey(COMPLEXITY_IN_FUNCTIONS_KEY)
- .setByMetricKey(FUNCTIONS_KEY)
- .build()));
- sut = new ComputeFormulaMeasuresStep(treeRootHolder, measureRepository, metricRepository, formulaRepository);
- }
-
- @Test
- public void add_measures() {
- DumbComponent project = builder(PROJECT, 1)
- .addChildren(
- builder(MODULE, 11)
- .addChildren(
- builder(DIRECTORY, 111)
- .addChildren(
- builder(Component.Type.FILE, 1111).build(),
- builder(Component.Type.FILE, 1112).build()
- ).build()
- ).build(),
- builder(MODULE, 12)
- .addChildren(
- builder(DIRECTORY, 121)
- .addChildren(
- builder(Component.Type.FILE, 1211).build()
- ).build()
- ).build()
- ).build();
-
- treeRootHolder.setRoot(project);
-
- measureRepository.addRawMeasure(1111, COMPLEXITY_IN_FUNCTIONS_KEY, newMeasureBuilder().create(5));
- measureRepository.addRawMeasure(1111, FUNCTIONS_KEY, newMeasureBuilder().create(2));
-
- measureRepository.addRawMeasure(1112, COMPLEXITY_IN_FUNCTIONS_KEY, newMeasureBuilder().create(1));
- measureRepository.addRawMeasure(1112, FUNCTIONS_KEY, newMeasureBuilder().create(1));
-
- measureRepository.addRawMeasure(1211, COMPLEXITY_IN_FUNCTIONS_KEY, newMeasureBuilder().create(9));
- measureRepository.addRawMeasure(1211, FUNCTIONS_KEY, newMeasureBuilder().create(2));
-
- sut.execute();
-
- assertThat(toEntries(measureRepository.getNewRawMeasures(1))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(3d)));
- assertThat(toEntries(measureRepository.getNewRawMeasures(11))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(2d)));
- assertThat(toEntries(measureRepository.getNewRawMeasures(111))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(2d)));
- assertThat(toEntries(measureRepository.getNewRawMeasures(1111))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(2.5d)));
- assertThat(toEntries(measureRepository.getNewRawMeasures(1112))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(1d)));
- assertThat(toEntries(measureRepository.getNewRawMeasures(12))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(4.5d)));
- assertThat(toEntries(measureRepository.getNewRawMeasures(121))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(4.5d)));
- assertThat(toEntries(measureRepository.getNewRawMeasures(1211))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(4.5d)));
- }
-
-}
--- /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.formula;
+
+import com.google.common.collect.Lists;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.server.computation.batch.TreeRootHolderRule;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.component.DumbComponent;
+import org.sonar.server.computation.measure.MeasureRepositoryRule;
+import org.sonar.server.computation.metric.MetricRepositoryRule;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.guava.api.Assertions.assertThat;
+import static org.sonar.api.measures.CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION_KEY;
+import static org.sonar.server.computation.component.Component.Type.DIRECTORY;
+import static org.sonar.server.computation.component.Component.Type.MODULE;
+import static org.sonar.server.computation.component.Component.Type.PROJECT;
+import static org.sonar.server.computation.component.DumbComponent.builder;
+import static org.sonar.server.computation.measure.Measure.newMeasureBuilder;
+import static org.sonar.server.computation.measure.MeasureRepoEntry.entryOf;
+import static org.sonar.server.computation.measure.MeasureRepoEntry.toEntries;
+
+public class DistributionFormulaExecutionTest {
+
+ @Rule
+ public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
+ @Rule
+ public MetricRepositoryRule metricRepository = new MetricRepositoryRule().add(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION);
+ @Rule
+ public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
+
+ FormulaExecutorComponentVisitor sut;
+
+ @Before
+ public void setUp() throws Exception {
+ sut = FormulaExecutorComponentVisitor.newBuilder(metricRepository, measureRepository)
+ .buildFor(Lists.<Formula>newArrayList(new DistributionFormula(FUNCTION_COMPLEXITY_DISTRIBUTION_KEY)));
+ }
+
+ @Test
+ public void add_measures() {
+ DumbComponent project = builder(PROJECT, 1)
+ .addChildren(
+ builder(MODULE, 11)
+ .addChildren(
+ builder(DIRECTORY, 111)
+ .addChildren(
+ builder(Component.Type.FILE, 1111).build(),
+ builder(Component.Type.FILE, 1112).build()
+ ).build()
+ ).build(),
+ builder(MODULE, 12)
+ .addChildren(
+ builder(DIRECTORY, 121)
+ .addChildren(
+ builder(Component.Type.FILE, 1211).build()
+ ).build()
+ ).build()
+ ).build();
+
+ treeRootHolder.setRoot(project);
+
+ measureRepository.addRawMeasure(1111, FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0.5=3;3.5=5;6.5=9"));
+ measureRepository.addRawMeasure(1112, FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0.5=0;3.5=2;6.5=1"));
+ measureRepository.addRawMeasure(1211, FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0.5=1;3.5=3;6.5=2"));
+
+ sut.visit(project);
+
+ assertThat(toEntries(measureRepository.getNewRawMeasures(1))).containsOnly(entryOf(FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0.5=4;3.5=10;6.5=12")));
+ assertThat(toEntries(measureRepository.getNewRawMeasures(11))).containsOnly(entryOf(FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0.5=3;3.5=7;6.5=10")));
+ assertThat(toEntries(measureRepository.getNewRawMeasures(111))).containsOnly(entryOf(FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0.5=3;3.5=7;6.5=10")));
+ assertThat(measureRepository.getNewRawMeasures(1111)).isEmpty();
+ assertThat(measureRepository.getNewRawMeasures(1112)).isEmpty();
+ assertThat(toEntries(measureRepository.getNewRawMeasures(12))).containsOnly(entryOf(FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0.5=1;3.5=3;6.5=2")));
+ assertThat(toEntries(measureRepository.getNewRawMeasures(121))).containsOnly(entryOf(FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0.5=1;3.5=3;6.5=2")));
+ assertThat(measureRepository.getNewRawMeasures(1211)).isEmpty();
+ }
+
+}
+++ /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.formula;
-
-import com.google.common.collect.Lists;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.server.computation.batch.TreeRootHolderRule;
-import org.sonar.server.computation.component.Component;
-import org.sonar.server.computation.component.DumbComponent;
-import org.sonar.server.computation.measure.MeasureRepositoryRule;
-import org.sonar.server.computation.metric.MetricRepositoryRule;
-import org.sonar.server.computation.step.ComputeFormulaMeasuresStep;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.guava.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.sonar.api.measures.CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION_KEY;
-import static org.sonar.server.computation.component.Component.Type.DIRECTORY;
-import static org.sonar.server.computation.component.Component.Type.MODULE;
-import static org.sonar.server.computation.component.Component.Type.PROJECT;
-import static org.sonar.server.computation.component.DumbComponent.builder;
-import static org.sonar.server.computation.measure.Measure.newMeasureBuilder;
-import static org.sonar.server.computation.measure.MeasureRepoEntry.entryOf;
-import static org.sonar.server.computation.measure.MeasureRepoEntry.toEntries;
-
-public class DistributionFormulaStepTest {
-
- @Rule
- public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
-
- @Rule
- public MetricRepositoryRule metricRepository = new MetricRepositoryRule().add(CoreMetrics.FUNCTION_COMPLEXITY_DISTRIBUTION);
-
- @Rule
- public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
-
- ComputeFormulaMeasuresStep sut;
-
- @Before
- public void setUp() {
- FormulaRepository formulaRepository = mock(FormulaRepository.class);
- when(formulaRepository.getFormulas()).thenReturn(Lists.<Formula>newArrayList(new DistributionFormula(FUNCTION_COMPLEXITY_DISTRIBUTION_KEY)));
- sut = new ComputeFormulaMeasuresStep(treeRootHolder, measureRepository, metricRepository, formulaRepository);
- }
-
- @Test
- public void add_measures() {
- DumbComponent project = builder(PROJECT, 1)
- .addChildren(
- builder(MODULE, 11)
- .addChildren(
- builder(DIRECTORY, 111)
- .addChildren(
- builder(Component.Type.FILE, 1111).build(),
- builder(Component.Type.FILE, 1112).build()
- ).build()
- ).build(),
- builder(MODULE, 12)
- .addChildren(
- builder(DIRECTORY, 121)
- .addChildren(
- builder(Component.Type.FILE, 1211).build()
- ).build()
- ).build()
- ).build();
-
- treeRootHolder.setRoot(project);
-
- measureRepository.addRawMeasure(1111, FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0.5=3;3.5=5;6.5=9"));
- measureRepository.addRawMeasure(1112, FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0.5=0;3.5=2;6.5=1"));
- measureRepository.addRawMeasure(1211, FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0.5=1;3.5=3;6.5=2"));
-
- sut.execute();
-
- assertThat(toEntries(measureRepository.getNewRawMeasures(1))).containsOnly(entryOf(FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0.5=4;3.5=10;6.5=12")));
- assertThat(toEntries(measureRepository.getNewRawMeasures(11))).containsOnly(entryOf(FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0.5=3;3.5=7;6.5=10")));
- assertThat(toEntries(measureRepository.getNewRawMeasures(111))).containsOnly(entryOf(FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0.5=3;3.5=7;6.5=10")));
- assertThat(measureRepository.getNewRawMeasures(1111)).isEmpty();
- assertThat(measureRepository.getNewRawMeasures(1112)).isEmpty();
- assertThat(toEntries(measureRepository.getNewRawMeasures(12))).containsOnly(entryOf(FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0.5=1;3.5=3;6.5=2")));
- assertThat(toEntries(measureRepository.getNewRawMeasures(121))).containsOnly(entryOf(FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, newMeasureBuilder().create("0.5=1;3.5=3;6.5=2")));
- assertThat(measureRepository.getNewRawMeasures(1211)).isEmpty();
- }
-
-}
--- /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.formula;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+import org.assertj.guava.api.Assertions;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.server.computation.batch.TreeRootHolderRule;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.component.DumbComponent;
+import org.sonar.server.computation.formula.counter.IntVariationValue;
+import org.sonar.server.computation.measure.Measure;
+import org.sonar.server.computation.measure.MeasureRepositoryRule;
+import org.sonar.server.computation.measure.MeasureVariations;
+import org.sonar.server.computation.metric.MetricRepositoryRule;
+import org.sonar.server.computation.period.Period;
+import org.sonar.server.computation.period.PeriodsHolderRule;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.guava.api.Assertions.assertThat;
+import static org.sonar.api.measures.CoreMetrics.LINES_KEY;
+import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY;
+import static org.sonar.api.measures.CoreMetrics.NEW_IT_COVERAGE_KEY;
+import static org.sonar.api.measures.CoreMetrics.NEW_LINES_TO_COVER_KEY;
+import static org.sonar.server.computation.component.Component.Type.DIRECTORY;
+import static org.sonar.server.computation.component.Component.Type.MODULE;
+import static org.sonar.server.computation.component.Component.Type.PROJECT;
+import static org.sonar.server.computation.component.DumbComponent.builder;
+import static org.sonar.server.computation.measure.Measure.newMeasureBuilder;
+import static org.sonar.server.computation.measure.MeasureRepoEntry.entryOf;
+import static org.sonar.server.computation.measure.MeasureRepoEntry.toEntries;
+
+public class FormulaExecutorComponentVisitorTest {
+ public static final DumbComponent BALANCED_COMPONENT_TREE = DumbComponent.builder(PROJECT, 1)
+ .addChildren(
+ DumbComponent.builder(MODULE, 11)
+ .addChildren(
+ DumbComponent.builder(DIRECTORY, 111)
+ .addChildren(
+ builder(Component.Type.FILE, 1111).build(),
+ builder(Component.Type.FILE, 1112).build()
+ ).build()
+ ).build(),
+ DumbComponent.builder(MODULE, 12)
+ .addChildren(
+ DumbComponent.builder(DIRECTORY, 121)
+ .addChildren(
+ builder(Component.Type.FILE, 1211).build()
+ ).build()
+ ).build()
+ ).build();
+ @Rule
+ public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
+ @Rule
+ public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
+ .add(CoreMetrics.LINES)
+ .add(CoreMetrics.NCLOC)
+ .add(CoreMetrics.NEW_LINES_TO_COVER)
+ .add(CoreMetrics.NEW_IT_COVERAGE);
+ @Rule
+ public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
+ @Rule
+ public PeriodsHolderRule periodsHolder = new PeriodsHolderRule()
+ .setPeriods(new Period(2, "some mode", null, 95l, 756l));
+
+ FormulaExecutorComponentVisitor underTest = FormulaExecutorComponentVisitor.newBuilder(metricRepository, measureRepository)
+ .withVariationSupport(periodsHolder)
+ .buildFor(ImmutableList.<Formula>of(new FakeFormula(), new FakeVariationFormula()));
+
+ @Test
+ public void verify_aggregation_on_value() throws Exception {
+ treeRootHolder.setRoot(BALANCED_COMPONENT_TREE);
+
+ measureRepository.addRawMeasure(1111, LINES_KEY, newMeasureBuilder().create(10));
+ measureRepository.addRawMeasure(1112, LINES_KEY, newMeasureBuilder().create(8));
+ measureRepository.addRawMeasure(1211, LINES_KEY, newMeasureBuilder().create(2));
+
+ underTest.visit(BALANCED_COMPONENT_TREE);
+
+ assertThat(toEntries(measureRepository.getNewRawMeasures(1))).containsOnly(entryOf(NCLOC_KEY, newMeasureBuilder().create(20)));
+ assertThat(toEntries(measureRepository.getNewRawMeasures(11))).containsOnly(entryOf(NCLOC_KEY, newMeasureBuilder().create(18)));
+ assertThat(toEntries(measureRepository.getNewRawMeasures(111))).containsOnly(entryOf(NCLOC_KEY, newMeasureBuilder().create(18)));
+ assertThat(toEntries(measureRepository.getNewRawMeasures(1111))).containsOnly(entryOf(NCLOC_KEY, newMeasureBuilder().create(10)));
+ assertThat(toEntries(measureRepository.getNewRawMeasures(1112))).containsOnly(entryOf(NCLOC_KEY, newMeasureBuilder().create(8)));
+ assertThat(toEntries(measureRepository.getNewRawMeasures(12))).containsOnly(entryOf(NCLOC_KEY, newMeasureBuilder().create(2)));
+ assertThat(toEntries(measureRepository.getNewRawMeasures(121))).containsOnly(entryOf(NCLOC_KEY, newMeasureBuilder().create(2)));
+ assertThat(toEntries(measureRepository.getNewRawMeasures(1211))).containsOnly(entryOf(NCLOC_KEY, newMeasureBuilder().create(2)));
+ }
+
+ @Test
+ public void verify_aggregation_on_variations() throws Exception {
+ treeRootHolder.setRoot(BALANCED_COMPONENT_TREE);
+
+ measureRepository.addRawMeasure(1111, NEW_LINES_TO_COVER_KEY, createMeasureWithVariation(10));
+ measureRepository.addRawMeasure(1112, NEW_LINES_TO_COVER_KEY, createMeasureWithVariation(8));
+ measureRepository.addRawMeasure(1211, NEW_LINES_TO_COVER_KEY, createMeasureWithVariation(2));
+
+ underTest.visit(BALANCED_COMPONENT_TREE);
+
+ assertThat(toEntries(measureRepository.getNewRawMeasures(1))).containsOnly(entryOf(NEW_IT_COVERAGE_KEY, createMeasureWithVariation(20)));
+ assertThat(toEntries(measureRepository.getNewRawMeasures(11))).containsOnly(entryOf(NEW_IT_COVERAGE_KEY, createMeasureWithVariation(18)));
+ assertThat(toEntries(measureRepository.getNewRawMeasures(111))).containsOnly(entryOf(NEW_IT_COVERAGE_KEY, createMeasureWithVariation(18)));
+ assertThat(toEntries(measureRepository.getNewRawMeasures(1111))).containsOnly(entryOf(NEW_IT_COVERAGE_KEY, createMeasureWithVariation(10)));
+ assertThat(toEntries(measureRepository.getNewRawMeasures(1112))).containsOnly(entryOf(NEW_IT_COVERAGE_KEY, createMeasureWithVariation(8)));
+ assertThat(toEntries(measureRepository.getNewRawMeasures(12))).containsOnly(entryOf(NEW_IT_COVERAGE_KEY, createMeasureWithVariation(2)));
+ assertThat(toEntries(measureRepository.getNewRawMeasures(121))).containsOnly(entryOf(NEW_IT_COVERAGE_KEY, createMeasureWithVariation(2)));
+ assertThat(toEntries(measureRepository.getNewRawMeasures(1211))).containsOnly(entryOf(NEW_IT_COVERAGE_KEY, createMeasureWithVariation(2)));
+ }
+
+ private static Measure createMeasureWithVariation(double variation2Value) {
+ return newMeasureBuilder().setVariations(new MeasureVariations(null, null, variation2Value)).createNoValue();
+ }
+
+ @Test
+ public void add_no_measure() throws Exception {
+ DumbComponent project = DumbComponent.builder(PROJECT, 1)
+ .addChildren(
+ DumbComponent.builder(MODULE, 11)
+ .addChildren(
+ DumbComponent.builder(DIRECTORY, 111)
+ .addChildren(
+ builder(Component.Type.FILE, 1111).build()
+ ).build()
+ ).build()
+ ).build();
+ treeRootHolder.setRoot(project);
+
+ underTest.visit(project);
+
+ Assertions.assertThat(measureRepository.getNewRawMeasures(1)).isEmpty();
+ Assertions.assertThat(measureRepository.getNewRawMeasures(11)).isEmpty();
+ Assertions.assertThat(measureRepository.getNewRawMeasures(111)).isEmpty();
+ Assertions.assertThat(measureRepository.getNewRawMeasures(1111)).isEmpty();
+ }
+
+ @Test
+ public void add_no_measure_when_no_file() throws Exception {
+ DumbComponent project = DumbComponent.builder(PROJECT, 1)
+ .addChildren(
+ DumbComponent.builder(MODULE, 11)
+ .addChildren(
+ DumbComponent.builder(DIRECTORY, 111).build()
+ ).build()
+ ).build();
+ treeRootHolder.setRoot(project);
+
+ underTest.visit(project);
+
+ assertThat(measureRepository.getNewRawMeasures(1)).isEmpty();
+ assertThat(measureRepository.getNewRawMeasures(11)).isEmpty();
+ assertThat(measureRepository.getNewRawMeasures(111)).isEmpty();
+ }
+
+ private static class FakeFormula implements Formula<FakeCounter> {
+
+ @Override
+ public FakeCounter createNewCounter() {
+ return new FakeCounter();
+ }
+
+ @Override
+ public Optional<Measure> createMeasure(FakeCounter counter, Component.Type componentType) {
+ if (counter.value <= 0) {
+ return Optional.absent();
+ }
+ return Optional.of(Measure.newMeasureBuilder().create(counter.value));
+ }
+
+ @Override
+ public String getOutputMetricKey() {
+ return NCLOC_KEY;
+ }
+ }
+
+ private static class FakeCounter implements Counter<FakeCounter> {
+ private int value = 0;
+
+ @Override
+ public void aggregate(FakeCounter counter) {
+ this.value += counter.value;
+ }
+
+ @Override
+ public void aggregate(CounterContext counterContext) {
+ Optional<Measure> measureOptional = counterContext.getMeasure(LINES_KEY);
+ if (measureOptional.isPresent()) {
+ value += measureOptional.get().getIntValue();
+ }
+ }
+ }
+
+ private static class FakeVariationFormula implements Formula<FakeVariationCounter> {
+
+ @Override
+ public FakeVariationCounter createNewCounter() {
+ return new FakeVariationCounter();
+ }
+
+ @Override
+ public Optional<Measure> createMeasure(FakeVariationCounter counter, Component.Type componentType) {
+ Optional<MeasureVariations> measureVariations = counter.values.toMeasureVariations();
+ if (measureVariations.isPresent()) {
+ return Optional.of(
+ newMeasureBuilder()
+ .setVariations(measureVariations.get())
+ .createNoValue()
+ );
+ }
+ return Optional.absent();
+ }
+
+ @Override
+ public String getOutputMetricKey() {
+ return NEW_IT_COVERAGE_KEY;
+ }
+ }
+
+ private static class FakeVariationCounter implements Counter<FakeVariationCounter> {
+ private final IntVariationValue.Array values = IntVariationValue.newArray();
+
+ @Override
+ public void aggregate(FakeVariationCounter counter) {
+ values.incrementAll(counter.values);
+ }
+
+ @Override
+ public void aggregate(CounterContext counterContext) {
+ Optional<Measure> measureOptional = counterContext.getMeasure(NEW_LINES_TO_COVER_KEY);
+ if (!measureOptional.isPresent()) {
+ return;
+ }
+ for (Period period : counterContext.getPeriods()) {
+ this.values.increment(
+ period.getIndex(),
+ (int) measureOptional.get().getVariations().getVariation(period.getIndex() + 1));
+ }
+ }
+ }
+
+}
--- /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.formula;
+
+import com.google.common.collect.Lists;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.server.computation.batch.TreeRootHolderRule;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.component.DumbComponent;
+import org.sonar.server.computation.measure.MeasureRepositoryRule;
+import org.sonar.server.computation.metric.MetricRepositoryRule;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.guava.api.Assertions.assertThat;
+import static org.sonar.api.measures.CoreMetrics.LINES_KEY;
+import static org.sonar.server.computation.component.Component.Type.DIRECTORY;
+import static org.sonar.server.computation.component.Component.Type.MODULE;
+import static org.sonar.server.computation.component.Component.Type.PROJECT;
+import static org.sonar.server.computation.component.DumbComponent.builder;
+import static org.sonar.server.computation.measure.Measure.newMeasureBuilder;
+import static org.sonar.server.computation.measure.MeasureRepoEntry.entryOf;
+import static org.sonar.server.computation.measure.MeasureRepoEntry.toEntries;
+
+public class SumFormulaExecutionTest {
+
+ @Rule
+ public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
+ @Rule
+ public MetricRepositoryRule metricRepository = new MetricRepositoryRule().add(CoreMetrics.LINES);
+ @Rule
+ public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
+
+ FormulaExecutorComponentVisitor sut;
+
+ @Before
+ public void setUp() throws Exception {
+ sut = FormulaExecutorComponentVisitor.newBuilder(metricRepository, measureRepository)
+ .buildFor(Lists.<Formula>newArrayList(new SumFormula(LINES_KEY)));
+ }
+
+ @Test
+ public void add_measures() {
+ DumbComponent project = builder(PROJECT, 1)
+ .addChildren(
+ builder(MODULE, 11)
+ .addChildren(
+ builder(DIRECTORY, 111)
+ .addChildren(
+ builder(Component.Type.FILE, 1111).build(),
+ builder(Component.Type.FILE, 1112).build()
+ ).build()
+ ).build(),
+ builder(MODULE, 12)
+ .addChildren(
+ builder(DIRECTORY, 121)
+ .addChildren(
+ builder(Component.Type.FILE, 1211).build()
+ ).build()
+ ).build()
+ ).build();
+
+ treeRootHolder.setRoot(project);
+
+ measureRepository.addRawMeasure(1111, LINES_KEY, newMeasureBuilder().create(10));
+ measureRepository.addRawMeasure(1112, LINES_KEY, newMeasureBuilder().create(8));
+ measureRepository.addRawMeasure(1211, LINES_KEY, newMeasureBuilder().create(2));
+
+ sut.visit(project);
+
+ assertThat(toEntries(measureRepository.getNewRawMeasures(1))).containsOnly(entryOf(LINES_KEY, newMeasureBuilder().create(20)));
+ assertThat(toEntries(measureRepository.getNewRawMeasures(11))).containsOnly(entryOf(LINES_KEY, newMeasureBuilder().create(18)));
+ assertThat(toEntries(measureRepository.getNewRawMeasures(111))).containsOnly(entryOf(LINES_KEY, newMeasureBuilder().create(18)));
+ assertThat(measureRepository.getNewRawMeasures(1111)).isEmpty();
+ assertThat(measureRepository.getNewRawMeasures(1112)).isEmpty();
+ assertThat(toEntries(measureRepository.getNewRawMeasures(12))).containsOnly(entryOf(LINES_KEY, newMeasureBuilder().create(2)));
+ assertThat(toEntries(measureRepository.getNewRawMeasures(121))).containsOnly(entryOf(LINES_KEY, newMeasureBuilder().create(2)));
+ assertThat(measureRepository.getNewRawMeasures(1211)).isEmpty();
+ }
+
+}
+++ /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.formula;
-
-import com.google.common.collect.Lists;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.server.computation.batch.TreeRootHolderRule;
-import org.sonar.server.computation.component.Component;
-import org.sonar.server.computation.component.DumbComponent;
-import org.sonar.server.computation.measure.MeasureRepositoryRule;
-import org.sonar.server.computation.metric.MetricRepositoryRule;
-import org.sonar.server.computation.step.ComputeFormulaMeasuresStep;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.guava.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.sonar.api.measures.CoreMetrics.LINES_KEY;
-import static org.sonar.server.computation.component.Component.Type.DIRECTORY;
-import static org.sonar.server.computation.component.Component.Type.MODULE;
-import static org.sonar.server.computation.component.Component.Type.PROJECT;
-import static org.sonar.server.computation.component.DumbComponent.builder;
-import static org.sonar.server.computation.measure.Measure.newMeasureBuilder;
-import static org.sonar.server.computation.measure.MeasureRepoEntry.entryOf;
-import static org.sonar.server.computation.measure.MeasureRepoEntry.toEntries;
-
-public class SumFormulaStepTest {
-
- @Rule
- public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
-
- @Rule
- public MetricRepositoryRule metricRepository = new MetricRepositoryRule().add(CoreMetrics.LINES);
-
- @Rule
- public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
-
- ComputeFormulaMeasuresStep sut;
-
- @Before
- public void setUp() {
- FormulaRepository formulaRepository = mock(FormulaRepository.class);
- when(formulaRepository.getFormulas()).thenReturn(Lists.<Formula>newArrayList(new SumFormula(LINES_KEY)));
- sut = new ComputeFormulaMeasuresStep(treeRootHolder, measureRepository, metricRepository, formulaRepository);
- }
-
- @Test
- public void add_measures() {
- DumbComponent project = builder(PROJECT, 1)
- .addChildren(
- builder(MODULE, 11)
- .addChildren(
- builder(DIRECTORY, 111)
- .addChildren(
- builder(Component.Type.FILE, 1111).build(),
- builder(Component.Type.FILE, 1112).build()
- ).build()
- ).build(),
- builder(MODULE, 12)
- .addChildren(
- builder(DIRECTORY, 121)
- .addChildren(
- builder(Component.Type.FILE, 1211).build()
- ).build()
- ).build()
- ).build();
-
- treeRootHolder.setRoot(project);
-
- measureRepository.addRawMeasure(1111, LINES_KEY, newMeasureBuilder().create(10));
- measureRepository.addRawMeasure(1112, LINES_KEY, newMeasureBuilder().create(8));
- measureRepository.addRawMeasure(1211, LINES_KEY, newMeasureBuilder().create(2));
-
- sut.execute();
-
- assertThat(toEntries(measureRepository.getNewRawMeasures(1))).containsOnly(entryOf(LINES_KEY, newMeasureBuilder().create(20)));
- assertThat(toEntries(measureRepository.getNewRawMeasures(11))).containsOnly(entryOf(LINES_KEY, newMeasureBuilder().create(18)));
- assertThat(toEntries(measureRepository.getNewRawMeasures(111))).containsOnly(entryOf(LINES_KEY, newMeasureBuilder().create(18)));
- assertThat(measureRepository.getNewRawMeasures(1111)).isEmpty();
- assertThat(measureRepository.getNewRawMeasures(1112)).isEmpty();
- assertThat(toEntries(measureRepository.getNewRawMeasures(12))).containsOnly(entryOf(LINES_KEY, newMeasureBuilder().create(2)));
- assertThat(toEntries(measureRepository.getNewRawMeasures(121))).containsOnly(entryOf(LINES_KEY, newMeasureBuilder().create(2)));
- assertThat(measureRepository.getNewRawMeasures(1211)).isEmpty();
- }
-
-}
this.delegate = new PeriodsHolderImpl();
}
- public void setPeriods(Period... periods) {
+ public PeriodsHolderRule setPeriods(Period... periods) {
delegate = new PeriodsHolderImpl();
delegate.setPeriods(Arrays.asList(periods));
+ return this;
}
@Override
+++ /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.collect.Lists;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.server.computation.batch.TreeRootHolderRule;
-import org.sonar.server.computation.component.Component;
-import org.sonar.server.computation.component.DumbComponent;
-import org.sonar.server.computation.formula.Counter;
-import org.sonar.server.computation.formula.CounterContext;
-import org.sonar.server.computation.formula.Formula;
-import org.sonar.server.computation.formula.FormulaRepository;
-import org.sonar.server.computation.measure.Measure;
-import org.sonar.server.computation.measure.MeasureRepositoryRule;
-import org.sonar.server.computation.metric.MetricRepositoryRule;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.guava.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.sonar.server.computation.component.Component.Type.DIRECTORY;
-import static org.sonar.server.computation.component.Component.Type.MODULE;
-import static org.sonar.server.computation.component.Component.Type.PROJECT;
-import static org.sonar.server.computation.component.DumbComponent.builder;
-import static org.sonar.server.computation.measure.Measure.newMeasureBuilder;
-import static org.sonar.server.computation.measure.MeasureRepoEntry.entryOf;
-import static org.sonar.server.computation.measure.MeasureRepoEntry.toEntries;
-
-public class ComputeFormulaMeasuresStepTest {
-
- @Rule
- public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
-
- @Rule
- public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
- .add(CoreMetrics.LINES)
- .add(CoreMetrics.NCLOC);
-
- @Rule
- public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
-
- ComputeFormulaMeasuresStep sut;
-
- @Before
- public void setUp() {
- FormulaRepository formulaRepository = mock(FormulaRepository.class);
- when(formulaRepository.getFormulas()).thenReturn(Lists.<Formula>newArrayList(new FakeFormula()));
- sut = new ComputeFormulaMeasuresStep(treeRootHolder, measureRepository, metricRepository, formulaRepository);
- }
-
- @Test
- public void add_measures() {
- DumbComponent project = DumbComponent.builder(PROJECT, 1)
- .addChildren(
- DumbComponent.builder(MODULE, 11)
- .addChildren(
- DumbComponent.builder(DIRECTORY, 111)
- .addChildren(
- builder(Component.Type.FILE, 1111).build(),
- builder(Component.Type.FILE, 1112).build()
- ).build()
- ).build(),
- DumbComponent.builder(MODULE, 12)
- .addChildren(
- DumbComponent.builder(DIRECTORY, 121)
- .addChildren(
- builder(Component.Type.FILE, 1211).build()
- ).build()
- ).build()
- ).build();
-
- treeRootHolder.setRoot(project);
-
- measureRepository.addRawMeasure(1111, CoreMetrics.LINES_KEY, newMeasureBuilder().create(10));
- measureRepository.addRawMeasure(1112, CoreMetrics.LINES_KEY, newMeasureBuilder().create(8));
- measureRepository.addRawMeasure(1211, CoreMetrics.LINES_KEY, newMeasureBuilder().create(2));
-
- sut.execute();
-
- assertThat(toEntries(measureRepository.getNewRawMeasures(1))).containsOnly(entryOf(CoreMetrics.NCLOC_KEY, newMeasureBuilder().create(20)));
- assertThat(toEntries(measureRepository.getNewRawMeasures(11))).containsOnly(entryOf(CoreMetrics.NCLOC_KEY, newMeasureBuilder().create(18)));
- assertThat(toEntries(measureRepository.getNewRawMeasures(111))).containsOnly(entryOf(CoreMetrics.NCLOC_KEY, newMeasureBuilder().create(18)));
- assertThat(toEntries(measureRepository.getNewRawMeasures(1111))).containsOnly(entryOf(CoreMetrics.NCLOC_KEY, newMeasureBuilder().create(10)));
- assertThat(toEntries(measureRepository.getNewRawMeasures(1112))).containsOnly(entryOf(CoreMetrics.NCLOC_KEY, newMeasureBuilder().create(8)));
- assertThat(toEntries(measureRepository.getNewRawMeasures(12))).containsOnly(entryOf(CoreMetrics.NCLOC_KEY, newMeasureBuilder().create(2)));
- assertThat(toEntries(measureRepository.getNewRawMeasures(121))).containsOnly(entryOf(CoreMetrics.NCLOC_KEY, newMeasureBuilder().create(2)));
- assertThat(toEntries(measureRepository.getNewRawMeasures(1211))).containsOnly(entryOf(CoreMetrics.NCLOC_KEY, newMeasureBuilder().create(2)));
- }
-
- @Test
- public void add_no_measure() {
- DumbComponent project = DumbComponent.builder(PROJECT, 1)
- .addChildren(
- DumbComponent.builder(MODULE, 11)
- .addChildren(
- DumbComponent.builder(DIRECTORY, 111)
- .addChildren(
- builder(Component.Type.FILE, 1111).build()
- ).build()
- ).build()
- ).build();
-
- treeRootHolder.setRoot(project);
-
- sut.execute();
-
- assertThat(measureRepository.getNewRawMeasures(1)).isEmpty();
- assertThat(measureRepository.getNewRawMeasures(11)).isEmpty();
- assertThat(measureRepository.getNewRawMeasures(111)).isEmpty();
- assertThat(measureRepository.getNewRawMeasures(1111)).isEmpty();
- }
-
- @Test
- public void add_no_measure_when_no_file() {
- DumbComponent project = DumbComponent.builder(PROJECT, 1)
- .addChildren(
- DumbComponent.builder(MODULE, 11)
- .addChildren(
- DumbComponent.builder(DIRECTORY, 111).build()
- ).build()
- ).build();
-
- treeRootHolder.setRoot(project);
-
- sut.execute();
-
- assertThat(measureRepository.getNewRawMeasures(1)).isEmpty();
- assertThat(measureRepository.getNewRawMeasures(11)).isEmpty();
- assertThat(measureRepository.getNewRawMeasures(111)).isEmpty();
- }
-
- @Test
- public void add_no_measure_on_module_without_file() {
- DumbComponent project = DumbComponent.builder(PROJECT, 1)
- .addChildren(
- DumbComponent.builder(MODULE, 11)
- .addChildren(
- DumbComponent.builder(DIRECTORY, 111).build()
- ).build(),
- DumbComponent.builder(MODULE, 12)
- .addChildren(
- DumbComponent.builder(DIRECTORY, 121)
- .addChildren(
- builder(Component.Type.FILE, 1211).build()
- ).build()
- ).build()
- ).build();
- treeRootHolder.setRoot(project);
- measureRepository.addRawMeasure(1211, CoreMetrics.LINES_KEY, newMeasureBuilder().create(10));
-
- sut.execute();
-
- assertThat(toEntries(measureRepository.getNewRawMeasures(1))).containsOnly(entryOf(CoreMetrics.NCLOC_KEY, newMeasureBuilder().create(10)));
- assertThat(measureRepository.getNewRawMeasures(11)).isEmpty();
- assertThat(measureRepository.getNewRawMeasures(111)).isEmpty();
- assertThat(toEntries(measureRepository.getNewRawMeasures(12))).containsOnly(entryOf(CoreMetrics.NCLOC_KEY, newMeasureBuilder().create(10)));
- assertThat(toEntries(measureRepository.getNewRawMeasures(121))).containsOnly(entryOf(CoreMetrics.NCLOC_KEY, newMeasureBuilder().create(10)));
- assertThat(toEntries(measureRepository.getNewRawMeasures(1211))).containsOnly(entryOf(CoreMetrics.NCLOC_KEY, newMeasureBuilder().create(10)));
- }
-
- private static class FakeFormula implements Formula<FakeCounter> {
-
- @Override
- public FakeCounter createNewCounter() {
- return new FakeCounter();
- }
-
- @Override
- public Optional<Measure> createMeasure(FakeCounter counter, Component.Type componentType) {
- if (counter.value <= 0) {
- return Optional.absent();
- }
- return Optional.of(Measure.newMeasureBuilder().create(counter.value));
- }
-
- @Override
- public String getOutputMetricKey() {
- return CoreMetrics.NCLOC_KEY;
- }
- }
-
- private static class FakeCounter implements Counter<FakeCounter> {
-
- private int value = 0;
-
- @Override
- public void aggregate(FakeCounter counter) {
- this.value += counter.value;
- }
-
- @Override
- public void aggregate(CounterContext counterContext) {
- Optional<Measure> measureOptional = counterContext.getMeasure(CoreMetrics.LINES_KEY);
- if (measureOptional.isPresent()) {
- value += measureOptional.get().getIntValue();
- }
- }
- }
-}
--- /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.Rule;
+import org.junit.Test;
+import org.sonar.server.computation.batch.TreeRootHolderRule;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.component.DumbComponent;
+import org.sonar.server.computation.formula.CoreFormulaRepository;
+import org.sonar.server.computation.measure.MeasureRepository;
+import org.sonar.server.computation.metric.MetricRepository;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+public class CoreMetricFormulaExecutorStepTest {
+ @Rule
+ public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
+
+ @Test
+ public void verify_execute_formulas_from_CoreFormulaRepository() {
+ CoreFormulaRepository coreFormulaRepository = mock(CoreFormulaRepository.class);
+ treeRootHolder.setRoot(DumbComponent.builder(Component.Type.PROJECT, 1).build());
+
+ CoreMetricFormulaExecutorStep underTest = new CoreMetricFormulaExecutorStep(treeRootHolder,
+ mock(MetricRepository.class), mock(MeasureRepository.class), coreFormulaRepository);
+
+ underTest.execute();
+
+ verify(coreFormulaRepository, times(1)).getFormulas();
+ }
+}