package org.sonar.server.computation.formula;
import com.google.common.base.Optional;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
import org.sonar.server.computation.component.CrawlerDepthLimit;
import org.sonar.server.computation.formula.counter.IntSumCounter;
import org.sonar.server.computation.formula.counter.LongSumCounter;
public abstract class SumFormula<T extends SumCounter<U, T>, U extends Number> implements Formula<T> {
protected final String metricKey;
+ @CheckForNull
+ protected final U defaultInputValue;
- public SumFormula(String metricKey) {
+ public SumFormula(String metricKey, @Nullable U defaultInputValue) {
this.metricKey = requireNonNull(metricKey, "Metric key cannot be null");
+ this.defaultInputValue = defaultInputValue;
}
public static IntSumFormula createIntSumFormula(String metricKey) {
- return new IntSumFormula(metricKey);
+ return createIntSumFormula(metricKey, null);
+ }
+
+ public static IntSumFormula createIntSumFormula(String metricKey, @Nullable Integer defaultInputValue) {
+ return new IntSumFormula(metricKey, defaultInputValue);
}
public static class IntSumFormula extends SumFormula<IntSumCounter, Integer> {
- private IntSumFormula(String metricKey) {
- super(metricKey);
+ private IntSumFormula(String metricKey, @Nullable Integer defaultInputValue) {
+ super(metricKey, defaultInputValue);
}
@Override
public IntSumCounter createNewCounter() {
- return new IntSumCounter(metricKey);
+ return new IntSumCounter(metricKey, defaultInputValue);
}
@Override
}
public static LongSumFormula createLongSumFormula(String metricKey) {
- return new LongSumFormula(metricKey);
+ return createLongSumFormula(metricKey, null);
+ }
+
+ public static LongSumFormula createLongSumFormula(String metricKey, @Nullable Long defaultInputValue) {
+ return new LongSumFormula(metricKey, defaultInputValue);
}
public static class LongSumFormula extends SumFormula<LongSumCounter, Long> {
- private LongSumFormula(String metricKey) {
- super(metricKey);
+ private LongSumFormula(String metricKey, @Nullable Long defaultInputValue) {
+ super(metricKey, defaultInputValue);
}
@Override
public LongSumCounter createNewCounter() {
- return new LongSumCounter(metricKey);
+ return new LongSumCounter(metricKey, defaultInputValue);
}
@Override
package org.sonar.server.computation.formula.counter;
import com.google.common.base.Optional;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
import org.sonar.server.computation.formula.CounterInitializationContext;
import org.sonar.server.computation.measure.Measure;
+import static java.util.Objects.requireNonNull;
+
/**
* Simple counter that do the sum of an integer measure
*/
public class IntSumCounter implements SumCounter<Integer, IntSumCounter> {
private final String metricKey;
+ @CheckForNull
+ private final Integer defaultInputValue;
private int value = 0;
private boolean initialized = false;
public IntSumCounter(String metricKey) {
- this.metricKey = metricKey;
+ this(metricKey, null);
+ }
+
+ public IntSumCounter(String metricKey, @Nullable Integer defaultInputValue) {
+ this.metricKey = requireNonNull(metricKey, "metricKey can not be null");
+ this.defaultInputValue = defaultInputValue;
}
@Override
Optional<Measure> measureOptional = context.getMeasure(metricKey);
if (measureOptional.isPresent()) {
addValue(measureOptional.get().getIntValue());
+ } else if (defaultInputValue != null) {
+ addValue(defaultInputValue);
}
}
package org.sonar.server.computation.formula.counter;
import com.google.common.base.Optional;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
import org.sonar.server.computation.formula.CounterInitializationContext;
import org.sonar.server.computation.measure.Measure;
+import static java.util.Objects.requireNonNull;
+
/**
* Simple counter that do the sum of an integer measure
*/
public class LongSumCounter implements SumCounter<Long, LongSumCounter> {
private final String metricKey;
+ @CheckForNull
+ private final Long defaultInputValue;
private long value = 0;
private boolean initialized = false;
public LongSumCounter(String metricKey) {
- this.metricKey = metricKey;
+ this(metricKey, null);
+ }
+
+ public LongSumCounter(String metricKey, @Nullable Long defaultInputValue) {
+ this.metricKey = requireNonNull(metricKey, "metricKey can not be null");
+ this.defaultInputValue = defaultInputValue;
}
@Override
Optional<Measure> measureOptional = context.getMeasure(metricKey);
if (measureOptional.isPresent()) {
addValue(measureOptional.get().getLongValue());
+ } else if (defaultInputValue != null) {
+ addValue(defaultInputValue);
}
}
package org.sonar.server.computation.formula;
import com.google.common.base.Optional;
+import javax.annotation.Nullable;
import org.assertj.guava.api.Assertions;
import org.junit.Rule;
import org.junit.Test;
public class IntSumFormulaTest {
private static final IntSumFormula INT_SUM_FORMULA = createIntSumFormula(LINES_KEY);
+ private static final IntSumFormula INT_SUM_FORMULA_NULL_DEFAULT_INPUT_VALUE = createIntSumFormula(LINES_KEY, null);
+ private static final IntSumFormula INT_SUM_FORMULA_DEFAULT_INPUT_VALUE_15 = createIntSumFormula(LINES_KEY, 15);
@Rule
public ExpectedException thrown = ExpectedException.none();
- CounterInitializationContext counterInitializationContext = mock(CounterInitializationContext.class);
CreateMeasureContext projectCreateMeasureContext = new DumbCreateMeasureContext(
- ReportComponent.builder(Component.Type.PROJECT, 1).build(), mock(Metric.class), mock(PeriodsHolder.class));
+ ReportComponent.builder(Component.Type.PROJECT, 1).build(), mock(Metric.class), mock(PeriodsHolder.class));
CreateMeasureContext fileCreateMeasureContext = new DumbCreateMeasureContext(
- ReportComponent.builder(Component.Type.FILE, 2).build(), mock(Metric.class), mock(PeriodsHolder.class));
+ ReportComponent.builder(Component.Type.FILE, 2).build(), mock(Metric.class), mock(PeriodsHolder.class));
@Test
public void check_create_new_counter_class() {
@Test
public void check_output_metric_key_is_lines() {
assertThat(INT_SUM_FORMULA.getOutputMetricKeys()).containsOnly(LINES_KEY);
+ assertThat(INT_SUM_FORMULA_DEFAULT_INPUT_VALUE_15.getOutputMetricKeys()).containsOnly(LINES_KEY);
+ assertThat(INT_SUM_FORMULA_NULL_DEFAULT_INPUT_VALUE.getOutputMetricKeys()).containsOnly(LINES_KEY);
}
@Test
- public void create_measure() {
+ public void create_measure_when_initialized_and_input_measure_exists() {
IntSumCounter counter = INT_SUM_FORMULA.createNewCounter();
- addMeasure(LINES_KEY, 10);
- counter.initialize(counterInitializationContext);
+ counter.initialize(createMeasureInInitContext(10));
- assertThat(INT_SUM_FORMULA.createMeasure(counter, projectCreateMeasureContext).get().getIntValue()).isEqualTo(10);
+ assertCreateMeasureValue(counter, 10);
}
@Test
- public void create_measure_when_counter_is_aggregating_from_another_counter() {
- IntSumCounter anotherCounter = INT_SUM_FORMULA.createNewCounter();
- addMeasure(LINES_KEY, 10);
- anotherCounter.initialize(counterInitializationContext);
-
+ public void does_not_create_measure_when_only_initialized_and_input_measure_does_not_exist() {
IntSumCounter counter = INT_SUM_FORMULA.createNewCounter();
- counter.aggregate(anotherCounter);
+ does_not_create_measure_when_only_initialized_and_input_measure_does_not_exist(counter);
+ }
+
+ @Test
+ public void does_not_create_measure_when_only_initialized_and_input_measure_does_not_exist_and_defaultInputValue_is_null() {
+ IntSumCounter counter = INT_SUM_FORMULA_NULL_DEFAULT_INPUT_VALUE.createNewCounter();
+ does_not_create_measure_when_only_initialized_and_input_measure_does_not_exist(counter);
+ }
+
+ private void does_not_create_measure_when_only_initialized_and_input_measure_does_not_exist(IntSumCounter counter) {
+ counter.initialize(createNoMeasureInInitContext());
- assertThat(INT_SUM_FORMULA.createMeasure(counter, projectCreateMeasureContext).get().getIntValue()).isEqualTo(10);
+ assertCreateNoMeasure(counter);
}
@Test
- public void not_create_measure_on_file() {
- IntSumCounter counter = INT_SUM_FORMULA.createNewCounter();
- addMeasure(LINES_KEY, 10);
- counter.initialize(counterInitializationContext);
+ public void creates_measure_when_only_initialized_and_input_measure_does_not_exist_and_defaultInputValue_is_non_null() {
+ IntSumCounter counter = INT_SUM_FORMULA_DEFAULT_INPUT_VALUE_15.createNewCounter();
+ counter.initialize(createNoMeasureInInitContext());
- Assertions.assertThat(INT_SUM_FORMULA.createMeasure(counter, fileCreateMeasureContext)).isAbsent();
+ assertCreateMeasureValue(counter, 15);
}
@Test
- public void do_not_create_measures_when_no_values() {
- IntSumCounter counter = INT_SUM_FORMULA.createNewCounter();
- when(counterInitializationContext.getMeasure(LINES_KEY)).thenReturn(Optional.<Measure>absent());
- counter.initialize(counterInitializationContext);
+ public void create_measure_sum_of_init_and_aggregated_other_counter_when_input_measure_exists() {
+ create_measure_sum_of_init_and_aggregated_other_counter(INT_SUM_FORMULA.createNewCounter(), 10, 30);
+ create_measure_sum_of_init_and_aggregated_other_counter(INT_SUM_FORMULA_NULL_DEFAULT_INPUT_VALUE.createNewCounter(), 10, 30);
+ create_measure_sum_of_init_and_aggregated_other_counter(INT_SUM_FORMULA_DEFAULT_INPUT_VALUE_15.createNewCounter(), 10, 30);
+ }
+
+ @Test
+ public void create_measure_when_aggregated_other_counter_but_input_measure_does_not_exist() {
+ create_measure_sum_of_init_and_aggregated_other_counter(INT_SUM_FORMULA.createNewCounter(), null, 20);
+ create_measure_sum_of_init_and_aggregated_other_counter(INT_SUM_FORMULA_NULL_DEFAULT_INPUT_VALUE.createNewCounter(), null, 20);
+ create_measure_sum_of_init_and_aggregated_other_counter(INT_SUM_FORMULA_DEFAULT_INPUT_VALUE_15.createNewCounter(), null, 35);
+ }
+
+ private void create_measure_sum_of_init_and_aggregated_other_counter(IntSumCounter counter, @Nullable Integer inputMeasure, int expectedMeasureValue) {
+ // init with value 10
+ if (inputMeasure != null) {
+ counter.initialize(createMeasureInInitContext(10));
+ } else {
+ counter.initialize(createNoMeasureInInitContext());
+ }
+ // second counter with value 20
+ IntSumCounter anotherCounter = INT_SUM_FORMULA.createNewCounter();
+ anotherCounter.initialize(createMeasureInInitContext(20));
+ counter.aggregate(anotherCounter);
+
+ assertCreateMeasureValue(counter, expectedMeasureValue);
+ }
+
+ @Test
+ public void initialize_does_not_create_measure_on_file() {
+ initialize_does_not_create_measure_on_file(INT_SUM_FORMULA.createNewCounter());
+ initialize_does_not_create_measure_on_file(INT_SUM_FORMULA_NULL_DEFAULT_INPUT_VALUE.createNewCounter());
+ initialize_does_not_create_measure_on_file(INT_SUM_FORMULA_DEFAULT_INPUT_VALUE_15.createNewCounter());
+ }
+
+ private void assertCreateNoMeasure(IntSumCounter counter) {
Assertions.assertThat(INT_SUM_FORMULA.createMeasure(counter, projectCreateMeasureContext)).isAbsent();
}
- private void addMeasure(String metricKey, int value) {
- when(counterInitializationContext.getMeasure(metricKey)).thenReturn(Optional.of(Measure.newMeasureBuilder().create(value)));
+ private void assertCreateMeasureValue(IntSumCounter counter, int expectMeasureValue) {
+ assertThat(INT_SUM_FORMULA.createMeasure(counter, projectCreateMeasureContext).get().getIntValue()).isEqualTo(expectMeasureValue);
+ }
+
+ private void initialize_does_not_create_measure_on_file(IntSumCounter counter) {
+ counter.initialize(createMeasureInInitContext(10));
+
+ Assertions.assertThat(INT_SUM_FORMULA.createMeasure(counter, fileCreateMeasureContext)).isAbsent();
+ }
+
+ private static CounterInitializationContext createMeasureInInitContext(int value) {
+ CounterInitializationContext initContext = mock(CounterInitializationContext.class);
+ when(initContext.getMeasure(LINES_KEY)).thenReturn(Optional.of(Measure.newMeasureBuilder().create(value)));
+ return initContext;
+ }
+
+ private static CounterInitializationContext createNoMeasureInInitContext() {
+ CounterInitializationContext initContext = mock(CounterInitializationContext.class);
+ when(initContext.getMeasure(LINES_KEY)).thenReturn(Optional.<Measure>absent());
+ return initContext;
}
}
package org.sonar.server.computation.formula;
import com.google.common.base.Optional;
+import javax.annotation.Nullable;
import org.assertj.guava.api.Assertions;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.server.computation.component.Component;
import org.sonar.server.computation.component.ReportComponent;
-import org.sonar.server.computation.formula.SumFormula.LongSumFormula;
import org.sonar.server.computation.formula.counter.LongSumCounter;
import org.sonar.server.computation.measure.Measure;
import org.sonar.server.computation.metric.Metric;
public class LongSumFormulaTest {
- private static final LongSumFormula LONG_SUM_FORMULA = createLongSumFormula(LINES_KEY);
- private static final long MEASURE_VALUE = 10;
+ private static final SumFormula.LongSumFormula LONG_SUM_FORMULA = createLongSumFormula(LINES_KEY);
+ private static final SumFormula.LongSumFormula LONG_SUM_FORMULA_NULL_DEFAULT_INPUT_VALUE = createLongSumFormula(LINES_KEY, null);
+ private static final SumFormula.LongSumFormula LONG_SUM_FORMULA_DEFAULT_INPUT_VALUE_15 = createLongSumFormula(LINES_KEY, 15L);
@Rule
public ExpectedException thrown = ExpectedException.none();
- CounterInitializationContext counterInitializationContext = mock(CounterInitializationContext.class);
CreateMeasureContext projectCreateMeasureContext = new DumbCreateMeasureContext(
- ReportComponent.builder(Component.Type.PROJECT, 1).build(), mock(Metric.class), mock(PeriodsHolder.class));
+ ReportComponent.builder(Component.Type.PROJECT, 1).build(), mock(Metric.class), mock(PeriodsHolder.class));
CreateMeasureContext fileCreateMeasureContext = new DumbCreateMeasureContext(
- ReportComponent.builder(Component.Type.FILE, 2).build(), mock(Metric.class), mock(PeriodsHolder.class));
+ ReportComponent.builder(Component.Type.FILE, 2).build(), mock(Metric.class), mock(PeriodsHolder.class));
@Test
public void check_create_new_counter_class() {
@Test
public void check_output_metric_key_is_lines() {
assertThat(LONG_SUM_FORMULA.getOutputMetricKeys()).containsOnly(LINES_KEY);
+ assertThat(LONG_SUM_FORMULA_DEFAULT_INPUT_VALUE_15.getOutputMetricKeys()).containsOnly(LINES_KEY);
+ assertThat(LONG_SUM_FORMULA_NULL_DEFAULT_INPUT_VALUE.getOutputMetricKeys()).containsOnly(LINES_KEY);
}
@Test
- public void create_measure() {
+ public void create_measure_when_initialized_and_input_measure_exists() {
LongSumCounter counter = LONG_SUM_FORMULA.createNewCounter();
- addMeasure(LINES_KEY, MEASURE_VALUE);
- counter.initialize(counterInitializationContext);
+ counter.initialize(createMeasureInInitContext(10));
- assertThat(LONG_SUM_FORMULA.createMeasure(counter, projectCreateMeasureContext).get().getLongValue()).isEqualTo(MEASURE_VALUE);
+ assertCreateMeasureValue(counter, 10);
}
@Test
- public void create_measure_when_counter_is_aggregating_from_another_counter() {
- LongSumCounter anotherCounter = LONG_SUM_FORMULA.createNewCounter();
- addMeasure(LINES_KEY, MEASURE_VALUE);
- anotherCounter.initialize(counterInitializationContext);
-
+ public void does_not_create_measure_when_only_initialized_and_input_measure_does_not_exist() {
LongSumCounter counter = LONG_SUM_FORMULA.createNewCounter();
- counter.aggregate(anotherCounter);
+ does_not_create_measure_when_only_initialized_and_input_measure_does_not_exist(counter);
+ }
+
+ @Test
+ public void does_not_create_measure_when_only_initialized_and_input_measure_does_not_exist_and_defaultInputValue_is_null() {
+ LongSumCounter counter = LONG_SUM_FORMULA_NULL_DEFAULT_INPUT_VALUE.createNewCounter();
+ does_not_create_measure_when_only_initialized_and_input_measure_does_not_exist(counter);
+ }
+
+ private void does_not_create_measure_when_only_initialized_and_input_measure_does_not_exist(LongSumCounter counter) {
+ counter.initialize(createNoMeasureInInitContext());
- assertThat(LONG_SUM_FORMULA.createMeasure(counter, projectCreateMeasureContext).get().getLongValue()).isEqualTo(MEASURE_VALUE);
+ assertCreateNoMeasure(counter);
}
@Test
- public void not_create_measure_on_file() {
- LongSumCounter counter = LONG_SUM_FORMULA.createNewCounter();
- addMeasure(LINES_KEY, MEASURE_VALUE);
- counter.initialize(counterInitializationContext);
+ public void creates_measure_when_only_initialized_and_input_measure_does_not_exist_and_defaultInputValue_is_non_null() {
+ LongSumCounter counter = LONG_SUM_FORMULA_DEFAULT_INPUT_VALUE_15.createNewCounter();
+ counter.initialize(createNoMeasureInInitContext());
- Assertions.assertThat(LONG_SUM_FORMULA.createMeasure(counter, fileCreateMeasureContext)).isAbsent();
+ assertCreateMeasureValue(counter, 15);
}
@Test
- public void do_not_create_measures_when_no_values() {
- LongSumCounter counter = LONG_SUM_FORMULA.createNewCounter();
- when(counterInitializationContext.getMeasure(LINES_KEY)).thenReturn(Optional.<Measure>absent());
- counter.initialize(counterInitializationContext);
+ public void create_measure_sum_of_init_and_aggregated_other_counter_when_input_measure_exists() {
+ create_measure_sum_of_init_and_aggregated_other_counter(LONG_SUM_FORMULA.createNewCounter(), 10L, 30);
+ create_measure_sum_of_init_and_aggregated_other_counter(LONG_SUM_FORMULA_NULL_DEFAULT_INPUT_VALUE.createNewCounter(), 10L, 30);
+ create_measure_sum_of_init_and_aggregated_other_counter(LONG_SUM_FORMULA_DEFAULT_INPUT_VALUE_15.createNewCounter(), 10L, 30);
+ }
+
+ private void create_measure_sum_of_init_and_aggregated_other_counter(LongSumCounter counter, @Nullable Long inputMeasure, long expectedMeasureValue) {
+ // init with value 10
+ if (inputMeasure != null) {
+ counter.initialize(createMeasureInInitContext(10));
+ } else {
+ counter.initialize(createNoMeasureInInitContext());
+ }
+
+ // second counter with value 20
+ LongSumCounter anotherCounter = LONG_SUM_FORMULA.createNewCounter();
+ anotherCounter.initialize(createMeasureInInitContext(20));
+ counter.aggregate(anotherCounter);
+ assertCreateMeasureValue(counter, expectedMeasureValue);
+ }
+
+ @Test
+ public void create_measure_when_aggregated_other_counter_but_input_measure_does_not_exist() {
+ create_measure_sum_of_init_and_aggregated_other_counter(LONG_SUM_FORMULA.createNewCounter(), null, 20);
+ create_measure_sum_of_init_and_aggregated_other_counter(LONG_SUM_FORMULA_NULL_DEFAULT_INPUT_VALUE.createNewCounter(), null, 20);
+ create_measure_sum_of_init_and_aggregated_other_counter(LONG_SUM_FORMULA_DEFAULT_INPUT_VALUE_15.createNewCounter(), null, 35);
+ }
+
+ @Test
+ public void initialize_does_not_create_measure_on_file() {
+ initialize_does_not_create_measure_on_file(LONG_SUM_FORMULA.createNewCounter());
+ initialize_does_not_create_measure_on_file(LONG_SUM_FORMULA_NULL_DEFAULT_INPUT_VALUE.createNewCounter());
+ initialize_does_not_create_measure_on_file(LONG_SUM_FORMULA_DEFAULT_INPUT_VALUE_15.createNewCounter());
+ }
+
+ private void assertCreateNoMeasure(LongSumCounter counter) {
Assertions.assertThat(LONG_SUM_FORMULA.createMeasure(counter, projectCreateMeasureContext)).isAbsent();
}
- private void addMeasure(String metricKey, long value) {
- when(counterInitializationContext.getMeasure(metricKey)).thenReturn(Optional.of(Measure.newMeasureBuilder().create(value)));
+ private void assertCreateMeasureValue(LongSumCounter counter, long expectMeasureValue) {
+ assertThat(LONG_SUM_FORMULA.createMeasure(counter, projectCreateMeasureContext).get().getLongValue()).isEqualTo(expectMeasureValue);
+ }
+
+ private void initialize_does_not_create_measure_on_file(LongSumCounter counter) {
+ counter.initialize(createMeasureInInitContext(10));
+
+ Assertions.assertThat(LONG_SUM_FORMULA.createMeasure(counter, fileCreateMeasureContext)).isAbsent();
+ }
+
+ private static CounterInitializationContext createMeasureInInitContext(long value) {
+ CounterInitializationContext initContext = mock(CounterInitializationContext.class);
+ when(initContext.getMeasure(LINES_KEY)).thenReturn(Optional.of(Measure.newMeasureBuilder().create(value)));
+ return initContext;
+ }
+
+ private static CounterInitializationContext createNoMeasureInInitContext() {
+ CounterInitializationContext initContext = mock(CounterInitializationContext.class);
+ when(initContext.getMeasure(LINES_KEY)).thenReturn(Optional.<Measure>absent());
+ return initContext;
}
}