]> source.dussan.org Git - sonarqube.git/commitdiff
fix VariationValue, avoid the int index pitfall by using the Period class directly
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Mon, 6 Jul 2015 08:53:49 +0000 (10:53 +0200)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Thu, 9 Jul 2015 07:24:48 +0000 (09:24 +0200)
server/sonar-server/src/main/java/org/sonar/server/computation/formula/counter/DoubleVariationValue.java
server/sonar-server/src/main/java/org/sonar/server/computation/formula/counter/IntVariationValue.java
server/sonar-server/src/main/java/org/sonar/server/computation/formula/counter/LongVariationValue.java
server/sonar-server/src/test/java/org/sonar/server/computation/formula/FormulaExecutorComponentVisitorTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/formula/counter/DoubleVariationValueArrayTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/computation/formula/counter/DoubleVariationValueTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/computation/formula/counter/IntVariationValueArrayTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/computation/formula/counter/IntVariationValueTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/computation/formula/counter/LongVariationValueArrayTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/computation/formula/counter/LongVariationValueTest.java [new file with mode: 0644]

index b2b39340fd94d21b80cf27a14cb45a060fe42d6d..964ecf43eb34f2430730c389645798ac9f3eec9c 100644 (file)
@@ -23,6 +23,7 @@ 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.Period;
 import org.sonar.server.computation.period.PeriodsHolder;
 
 import static org.sonar.server.computation.period.PeriodsHolder.MAX_NUMBER_OF_PERIODS;
@@ -39,15 +40,23 @@ public class DoubleVariationValue {
   private boolean set = false;
   private double value = 0L;
 
-  public void increment(double increment) {
+  /**
+   * @return the current DoubleVariationValue so that chained calls on a specific DoubleVariationValue instance can be done
+   */
+  public DoubleVariationValue increment(double increment) {
     this.value += increment;
     this.set = true;
+    return this;
   }
 
-  public void increment(@Nullable DoubleVariationValue value) {
-    if (value != null) {
+  /**
+   * @return the current DoubleVariationValue so that chained calls on a specific DoubleVariationValue instance can be done
+   */
+  public DoubleVariationValue increment(@Nullable DoubleVariationValue value) {
+    if (value != null && value.isSet()) {
       increment(value.value);
     }
+    return this;
   }
 
   public boolean isSet() {
@@ -76,22 +85,32 @@ public class DoubleVariationValue {
       }
     }
 
-    public void increment(int index, double value) {
-      this.values[index].increment(value);
+    public DoubleVariationValue get(Period period) {
+      return values[period.getIndex() - 1];
+    }
+
+    /**
+     * @return the current Array, so that chained calls on a specific Array instance can be done
+     */
+    public Array increment(Period period, double value) {
+      this.values[period.getIndex() - 1].increment(value);
+      return this;
     }
 
-    public void incrementAll(Array source) {
+    /**
+     * @return the current Array, so that chained calls on a specific Array instance can be done
+     */
+    public Array incrementAll(Array source) {
       for (int i = 0; i < this.values.length; i++) {
         if (source.values[i].isSet()) {
           this.values[i].increment(source.values[i]);
         }
       }
+      return this;
     }
 
     /**
      * 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()) {
@@ -100,15 +119,15 @@ public class DoubleVariationValue {
       Double[] variations = new Double[values.length];
       for (int i = 0; i < values.length; i++) {
         if (values[i].isSet()) {
-          variations[i] = (double) values[i].getValue();
+          variations[i] = values[i].getValue();
         }
       }
       return Optional.of(new MeasureVariations(variations));
     }
 
     private boolean isAnySet() {
-      for (DoubleVariationValue value : values) {
-        if (value.isSet()) {
+      for (DoubleVariationValue variationValue : values) {
+        if (variationValue.isSet()) {
           return true;
         }
       }
index 8bcb5bf4d414038a312538c197f292951ef185d3..e881e65452085e53d216929b370a98a975828cfd 100644 (file)
@@ -23,6 +23,7 @@ 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.Period;
 import org.sonar.server.computation.period.PeriodsHolder;
 
 import static org.sonar.server.computation.period.PeriodsHolder.MAX_NUMBER_OF_PERIODS;
@@ -39,15 +40,23 @@ public class IntVariationValue {
   private boolean set = false;
   private int value = 0;
 
-  public void increment(int increment) {
+  /**
+   * @return the current IntVariationValue so that chained calls on a specific IntVariationValue instance can be done
+   */
+  public IntVariationValue increment(int increment) {
     this.value += increment;
     this.set = true;
+    return this;
   }
 
-  public void increment(@Nullable IntVariationValue value) {
-    if (value != null) {
+  /**
+   * @return the current IntVariationValue so that chained calls on a specific IntVariationValue instance can be done
+   */
+  public IntVariationValue increment(@Nullable IntVariationValue value) {
+    if (value != null && value.isSet()) {
       increment(value.value);
     }
+    return this;
   }
 
   public boolean isSet() {
@@ -76,22 +85,32 @@ public class IntVariationValue {
       }
     }
 
-    public void increment(int index, int value) {
-      this.values[index].increment(value);
+    public IntVariationValue get(Period period) {
+      return values[period.getIndex() - 1];
+    }
+
+    /**
+     * @return the current Array, so that chained calls on a specific Array instance can be done
+     */
+    public Array increment(Period period, int value) {
+      this.values[period.getIndex() - 1].increment(value);
+      return this;
     }
 
-    public void incrementAll(Array source) {
+    /**
+     * @return the current Array, so that chained calls on a specific Array instance can be done
+     */
+    public Array incrementAll(Array source) {
       for (int i = 0; i < this.values.length; i++) {
         if (source.values[i].isSet()) {
           this.values[i].increment(source.values[i]);
         }
       }
+      return this;
     }
 
     /**
      * 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()) {
@@ -107,8 +126,8 @@ public class IntVariationValue {
     }
 
     private boolean isAnySet() {
-      for (IntVariationValue value : values) {
-        if (value.isSet()) {
+      for (IntVariationValue variationValue : values) {
+        if (variationValue.isSet()) {
           return true;
         }
       }
index a79706b4bcf4c21020691fd60f504fa340591eb9..54865e60e3da3ce0adc344fc28513dd63d9e7733 100644 (file)
@@ -21,9 +21,13 @@ 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.Period;
 import org.sonar.server.computation.period.PeriodsHolder;
 
+import static org.sonar.server.computation.period.PeriodsHolder.MAX_NUMBER_OF_PERIODS;
+
 /**
  * Convenience class wrapping a long to compute the value of a MeasureVariation as an long and know it is has ever been
  * set.
@@ -32,21 +36,27 @@ import org.sonar.server.computation.period.PeriodsHolder;
  * 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) {
+  /**
+   * @return the current LongVariationValue so that chained calls on a specific LongVariationValue instance can be done
+   */
+  public LongVariationValue increment(long increment) {
     this.value += increment;
     this.set = true;
+    return this;
   }
 
-  public void increment(@Nullable LongVariationValue value) {
-    if (value != null) {
+  /**
+   * @return the current LongVariationValue so that chained calls on a specific LongVariationValue instance can be done
+   */
+  public LongVariationValue increment(@Nullable LongVariationValue value) {
+    if (value != null && value.isSet()) {
       increment(value.value);
     }
+    return this;
   }
 
   public boolean isSet() {
@@ -75,22 +85,32 @@ public class LongVariationValue {
       }
     }
 
-    public void increment(int index, long value) {
-      this.values[index].increment(value);
+    public LongVariationValue get(Period period) {
+      return values[period.getIndex() - 1];
     }
 
-    public void incrementAll(Array source) {
+    /**
+     * @return the current Array, so that chained calls on a specific Array instance can be done
+     */
+    public Array increment(Period period, long value) {
+      this.values[period.getIndex() - 1].increment(value);
+      return this;
+    }
+
+    /**
+     * @return the current Array, so that chained calls on a specific Array instance can be done
+     */
+    public Array incrementAll(Array source) {
       for (int i = 0; i < this.values.length; i++) {
         if (source.values[i].isSet()) {
           this.values[i].increment(source.values[i]);
         }
       }
+      return this;
     }
 
     /**
      * 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()) {
@@ -106,8 +126,8 @@ public class LongVariationValue {
     }
 
     private boolean isAnySet() {
-      for (LongVariationValue value : values) {
-        if (value.isSet()) {
+      for (LongVariationValue variationValue : values) {
+        if (variationValue.isSet()) {
           return true;
         }
       }
index 5936f1aad9d54303fe87097fdc0cacbd1351874f..2e3ce2701214aeacf35a659c8d344a160bcdbce5 100644 (file)
@@ -22,7 +22,6 @@ 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;
@@ -82,7 +81,7 @@ public class FormulaExecutorComponentVisitorTest {
   public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
   @Rule
   public PeriodsHolderRule periodsHolder = new PeriodsHolderRule()
-    .setPeriods(new Period(2, "some mode", null, 95l, 756l));
+    .setPeriods(new Period(2, "some mode", null, 95l, 756l), new Period(5, "some other mode", null, 756L, 956L));
 
   FormulaExecutorComponentVisitor underTest = FormulaExecutorComponentVisitor.newBuilder(metricRepository, measureRepository)
     .withVariationSupport(periodsHolder)
@@ -112,24 +111,24 @@ public class FormulaExecutorComponentVisitorTest {
   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));
+    measureRepository.addRawMeasure(1111, NEW_LINES_TO_COVER_KEY, createMeasureWithVariation(10, 20));
+    measureRepository.addRawMeasure(1112, NEW_LINES_TO_COVER_KEY, createMeasureWithVariation(8, 16));
+    measureRepository.addRawMeasure(1211, NEW_LINES_TO_COVER_KEY, createMeasureWithVariation(2, 4));
 
     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)));
+    assertThat(toEntries(measureRepository.getNewRawMeasures(1))).containsOnly(entryOf(NEW_IT_COVERAGE_KEY, createMeasureWithVariation(20, 40)));
+    assertThat(toEntries(measureRepository.getNewRawMeasures(11))).containsOnly(entryOf(NEW_IT_COVERAGE_KEY, createMeasureWithVariation(18, 36)));
+    assertThat(toEntries(measureRepository.getNewRawMeasures(111))).containsOnly(entryOf(NEW_IT_COVERAGE_KEY, createMeasureWithVariation(18, 36)));
+    assertThat(toEntries(measureRepository.getNewRawMeasures(1111))).containsOnly(entryOf(NEW_IT_COVERAGE_KEY, createMeasureWithVariation(10, 20)));
+    assertThat(toEntries(measureRepository.getNewRawMeasures(1112))).containsOnly(entryOf(NEW_IT_COVERAGE_KEY, createMeasureWithVariation(8, 16)));
+    assertThat(toEntries(measureRepository.getNewRawMeasures(12))).containsOnly(entryOf(NEW_IT_COVERAGE_KEY, createMeasureWithVariation(2, 4)));
+    assertThat(toEntries(measureRepository.getNewRawMeasures(121))).containsOnly(entryOf(NEW_IT_COVERAGE_KEY, createMeasureWithVariation(2, 4)));
+    assertThat(toEntries(measureRepository.getNewRawMeasures(1211))).containsOnly(entryOf(NEW_IT_COVERAGE_KEY, createMeasureWithVariation(2, 4)));
   }
 
-  private static Measure createMeasureWithVariation(double variation2Value) {
-    return newMeasureBuilder().setVariations(new MeasureVariations(null, null, variation2Value)).createNoValue();
+  private static Measure createMeasureWithVariation(double variation2Value, double variation5Value) {
+    return newMeasureBuilder().setVariations(new MeasureVariations(null, variation2Value, null, null, variation5Value)).createNoValue();
   }
 
   @Test
@@ -148,10 +147,10 @@ public class FormulaExecutorComponentVisitorTest {
 
     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();
+    assertThat(measureRepository.getNewRawMeasures(1)).isEmpty();
+    assertThat(measureRepository.getNewRawMeasures(11)).isEmpty();
+    assertThat(measureRepository.getNewRawMeasures(111)).isEmpty();
+    assertThat(measureRepository.getNewRawMeasures(1111)).isEmpty();
   }
 
   @Test
@@ -252,8 +251,8 @@ public class FormulaExecutorComponentVisitorTest {
       }
       for (Period period : counterContext.getPeriods()) {
         this.values.increment(
-          period.getIndex(),
-          (int) measureOptional.get().getVariations().getVariation(period.getIndex() + 1));
+          period,
+          (int) measureOptional.get().getVariations().getVariation(period.getIndex()));
       }
     }
   }
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/formula/counter/DoubleVariationValueArrayTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/formula/counter/DoubleVariationValueArrayTest.java
new file mode 100644 (file)
index 0000000..4519258
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * 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 com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.junit.Test;
+import org.sonar.server.computation.measure.MeasureVariations;
+import org.sonar.server.computation.period.Period;
+import org.sonar.server.computation.period.PeriodsHolder;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.guava.api.Assertions.assertThat;
+
+public class DoubleVariationValueArrayTest {
+  private static final List<Period> PERIODS;
+
+  static {
+    ImmutableList.Builder<Period> builder = ImmutableList.builder();
+    for (int i = 1; i <= PeriodsHolder.MAX_NUMBER_OF_PERIODS; i++) {
+      builder.add(createPeriod(i));
+    }
+    PERIODS = builder.build();
+  }
+
+  @Test
+  public void newArray_always_returns_a_new_instance() {
+    assertThat(DoubleVariationValue.newArray()).isNotSameAs(DoubleVariationValue.newArray());
+  }
+
+  @Test
+  public void get_returns_unset_DoubleVariationValue_for_each_Period_index() {
+    DoubleVariationValue.Array array = DoubleVariationValue.newArray();
+    for (Period period : PERIODS) {
+      DoubleVariationValue value = array.get(period);
+      verifyUnsetVariationValue(value);
+    }
+  }
+
+  @Test
+  public void get_returns_set_DoubleVariationValue_for_each_Period_index_if_increment_has_been_called() {
+    DoubleVariationValue.Array array = DoubleVariationValue.newArray();
+    for (Period period : PERIODS) {
+      array.increment(period, 66.66);
+      DoubleVariationValue value = array.get(period);
+      verifySetDoubleVariation(value, 66.66);
+    }
+  }
+
+  @Test
+  public void incrementAll_increments_internals_from_all_set_DoubleVariationValue_from_source() {
+    DoubleVariationValue.Array source = DoubleVariationValue.newArray()
+      .increment(createPeriod(2), 20.6)
+      .increment(createPeriod(5), 5.5);
+
+    DoubleVariationValue.Array target = DoubleVariationValue.newArray()
+      .increment(createPeriod(1), 1.7)
+      .increment(createPeriod(5), 30.5);
+    target.incrementAll(source);
+
+    verifySetDoubleVariation(target.get(createPeriod(1)), 1.7);
+    verifySetDoubleVariation(target.get(createPeriod(2)), 20.6);
+    verifyUnsetVariationValue(target.get(createPeriod(3)));
+    verifyUnsetVariationValue(target.get(createPeriod(4)));
+    verifySetDoubleVariation(target.get(createPeriod(5)), 36);
+  }
+
+  @Test
+  public void toMeasureVariations_returns_absent_if_no_DoubleVariationValue_has_been_set() {
+    assertThat(DoubleVariationValue.newArray().toMeasureVariations()).isAbsent();
+  }
+
+  @Test
+  public void toMeasureVariations_returns_value_of_set_DoubleVariationValue_as_double() {
+    Optional<MeasureVariations> variationsOptional = DoubleVariationValue.newArray()
+      .increment(createPeriod(2), 2.6)
+      .increment(createPeriod(5), 15.9)
+      .toMeasureVariations();
+
+    assertThat(variationsOptional).isPresent();
+    MeasureVariations variations = variationsOptional.get();
+    assertThat(variations.hasVariation1()).isFalse();
+    assertThat(variations.getVariation2()).isEqualTo(2.6d);
+    assertThat(variations.hasVariation3()).isFalse();
+    assertThat(variations.hasVariation4()).isFalse();
+    assertThat(variations.getVariation5()).isEqualTo(15.9d);
+  }
+
+  private static void verifyUnsetVariationValue(DoubleVariationValue value) {
+    assertThat(value.isSet()).isFalse();
+    assertThat(value.getValue()).isEqualTo(0);
+  }
+
+  private static void verifySetDoubleVariation(DoubleVariationValue value, double expectedValue) {
+    assertThat(value.isSet()).isTrue();
+    assertThat(value.getValue()).isEqualTo(expectedValue);
+  }
+
+  private static Period createPeriod(int i) {
+    return new Period(i, "mode " + i, null, 100L + i, 753L + i);
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/formula/counter/DoubleVariationValueTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/formula/counter/DoubleVariationValueTest.java
new file mode 100644 (file)
index 0000000..813cc05
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * 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 org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class DoubleVariationValueTest {
+  @Test
+  public void newly_created_DoubleVariationValue_is_unset_and_has_value_0() {
+    verifyUnsetVariationValue(new DoubleVariationValue());
+  }
+
+  @Test
+  public void increment_double_sets_DoubleVariationValue_and_increments_value() {
+    verifySetVariationValue(new DoubleVariationValue().increment(10.6), 10.6);
+  }
+
+  @Test
+  public void increment_DoubleVariationValue_has_no_effect_if_arg_is_null() {
+    verifyUnsetVariationValue(new DoubleVariationValue().increment(null));
+  }
+
+  @Test
+  public void increment_DoubleVariationValue_has_no_effect_if_arg_is_unset() {
+    verifyUnsetVariationValue(new DoubleVariationValue().increment(new DoubleVariationValue()));
+  }
+
+  @Test
+  public void increment_DoubleVariationValue_increments_by_the_value_of_the_arg() {
+    DoubleVariationValue source = new DoubleVariationValue().increment(10);
+    DoubleVariationValue target = new DoubleVariationValue().increment(source);
+
+    verifySetVariationValue(target, 10);
+  }
+
+  @Test
+  public void multiple_calls_to_increment_DoubleVariationValue_increments_by_the_value_of_the_arg() {
+    DoubleVariationValue target = new DoubleVariationValue()
+      .increment(new DoubleVariationValue().increment(35))
+      .increment(new DoubleVariationValue().increment(10));
+
+    verifySetVariationValue(target, 45);
+  }
+
+  @Test
+  public void multiples_calls_to_increment_double_increment_the_value() {
+    DoubleVariationValue variationValue = new DoubleVariationValue()
+      .increment(10.6)
+      .increment(95.4);
+
+    verifySetVariationValue(variationValue, 106);
+  }
+
+  private static void verifyUnsetVariationValue(DoubleVariationValue variationValue) {
+    assertThat(variationValue.isSet()).isFalse();
+    assertThat(variationValue.getValue()).isEqualTo(0);
+  }
+
+  private static void verifySetVariationValue(DoubleVariationValue variationValue, double expected) {
+    assertThat(variationValue.isSet()).isTrue();
+    assertThat(variationValue.getValue()).isEqualTo(expected);
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/formula/counter/IntVariationValueArrayTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/formula/counter/IntVariationValueArrayTest.java
new file mode 100644 (file)
index 0000000..144fc7a
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * 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 com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.junit.Test;
+import org.sonar.server.computation.measure.MeasureVariations;
+import org.sonar.server.computation.period.Period;
+import org.sonar.server.computation.period.PeriodsHolder;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.guava.api.Assertions.assertThat;
+
+public class IntVariationValueArrayTest {
+  private static final List<Period> PERIODS;
+
+  static {
+    ImmutableList.Builder<Period> builder = ImmutableList.builder();
+    for (int i = 1; i <= PeriodsHolder.MAX_NUMBER_OF_PERIODS; i++) {
+      builder.add(createPeriod(i));
+    }
+    PERIODS = builder.build();
+  }
+
+  @Test
+  public void newArray_always_returns_a_new_instance() {
+    assertThat(IntVariationValue.newArray()).isNotSameAs(IntVariationValue.newArray());
+  }
+
+  @Test
+  public void get_returns_unset_IntVariationValue_for_each_Period_index() {
+    IntVariationValue.Array array = IntVariationValue.newArray();
+    for (Period period : PERIODS) {
+      IntVariationValue value = array.get(period);
+      verifyUnsetVariationValue(value);
+    }
+  }
+
+  @Test
+  public void get_returns_set_IntVariationValue_for_each_Period_index_if_increment_has_been_called() {
+    IntVariationValue.Array array = IntVariationValue.newArray();
+    for (Period period : PERIODS) {
+      array.increment(period, 66);
+      IntVariationValue value = array.get(period);
+      verifySetVariationValue(value, 66);
+    }
+  }
+
+  @Test
+  public void incrementAll_increments_internals_from_all_set_IntVariationValue_from_source() {
+    IntVariationValue.Array source = IntVariationValue.newArray()
+      .increment(createPeriod(2), 20)
+      .increment(createPeriod(5), 5);
+
+    IntVariationValue.Array target = IntVariationValue.newArray()
+      .increment(createPeriod(1), 1)
+      .increment(createPeriod(5), 30);
+    target.incrementAll(source);
+
+    verifySetVariationValue(target.get(createPeriod(1)), 1);
+    verifySetVariationValue(target.get(createPeriod(2)), 20);
+    verifyUnsetVariationValue(target.get(createPeriod(3)));
+    verifyUnsetVariationValue(target.get(createPeriod(4)));
+    verifySetVariationValue(target.get(createPeriod(5)), 35);
+  }
+
+  @Test
+  public void toMeasureVariations_returns_absent_if_no_IntVariationValue_has_been_set() {
+    assertThat(IntVariationValue.newArray().toMeasureVariations()).isAbsent();
+  }
+
+  @Test
+  public void toMeasureVariations_returns_value_of_set_IntVariationValue_as_double() {
+    Optional<MeasureVariations> variationsOptional = IntVariationValue.newArray()
+      .increment(createPeriod(2), 2)
+      .increment(createPeriod(5), 15)
+      .toMeasureVariations();
+
+    assertThat(variationsOptional).isPresent();
+    MeasureVariations variations = variationsOptional.get();
+    assertThat(variations.hasVariation1()).isFalse();
+    assertThat(variations.getVariation2()).isEqualTo(2d);
+    assertThat(variations.hasVariation3()).isFalse();
+    assertThat(variations.hasVariation4()).isFalse();
+    assertThat(variations.getVariation5()).isEqualTo(15d);
+  }
+
+  private static void verifyUnsetVariationValue(IntVariationValue value) {
+    assertThat(value.isSet()).isFalse();
+    assertThat(value.getValue()).isEqualTo(0);
+  }
+
+  private static void verifySetVariationValue(IntVariationValue value, int expectedValue) {
+    assertThat(value.isSet()).isTrue();
+    assertThat(value.getValue()).isEqualTo(expectedValue);
+  }
+
+  private static Period createPeriod(int i) {
+    return new Period(i, "mode " + i, null, 100L + i, 753L + i);
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/formula/counter/IntVariationValueTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/formula/counter/IntVariationValueTest.java
new file mode 100644 (file)
index 0000000..e27a02a
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * 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 org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class IntVariationValueTest {
+  @Test
+  public void newly_created_IntVariationValue_is_unset_and_has_value_0() {
+    verifyUnsetVariationValue(new IntVariationValue());
+  }
+
+  @Test
+  public void increment_int_sets_IntVariationValue_and_increments_value() {
+    verifySetVariationValue(new IntVariationValue().increment(10), 10);
+  }
+
+  @Test
+  public void increment_IntVariationValue_has_no_effect_if_arg_is_null() {
+    verifyUnsetVariationValue(new IntVariationValue().increment(null));
+  }
+
+  @Test
+  public void increment_IntVariationValue_has_no_effect_if_arg_is_unset() {
+    verifyUnsetVariationValue(new IntVariationValue().increment(new IntVariationValue()));
+  }
+
+  @Test
+  public void increment_IntVariationValue_increments_by_the_value_of_the_arg() {
+    IntVariationValue source = new IntVariationValue().increment(10);
+    IntVariationValue target = new IntVariationValue().increment(source);
+
+    verifySetVariationValue(target, 10);
+  }
+
+  @Test
+  public void multiple_calls_to_increment_IntVariationValue_increments_by_the_value_of_the_arg() {
+    IntVariationValue target = new IntVariationValue()
+      .increment(new IntVariationValue().increment(35))
+      .increment(new IntVariationValue().increment(10));
+
+    verifySetVariationValue(target, 45);
+  }
+
+  @Test
+  public void multiples_calls_to_increment_int_increment_the_value() {
+    IntVariationValue variationValue = new IntVariationValue()
+      .increment(10)
+      .increment(95);
+
+    verifySetVariationValue(variationValue, 105);
+  }
+
+  private static void verifyUnsetVariationValue(IntVariationValue variationValue) {
+    assertThat(variationValue.isSet()).isFalse();
+    assertThat(variationValue.getValue()).isEqualTo(0);
+  }
+
+  private static void verifySetVariationValue(IntVariationValue variationValue, int expected) {
+    assertThat(variationValue.isSet()).isTrue();
+    assertThat(variationValue.getValue()).isEqualTo(expected);
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/formula/counter/LongVariationValueArrayTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/formula/counter/LongVariationValueArrayTest.java
new file mode 100644 (file)
index 0000000..6715085
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * 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 com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.junit.Test;
+import org.sonar.server.computation.measure.MeasureVariations;
+import org.sonar.server.computation.period.Period;
+import org.sonar.server.computation.period.PeriodsHolder;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.guava.api.Assertions.assertThat;
+
+public class LongVariationValueArrayTest {
+  private static final List<Period> PERIODS;
+
+  static {
+    ImmutableList.Builder<Period> builder = ImmutableList.builder();
+    for (int i = 1; i <= PeriodsHolder.MAX_NUMBER_OF_PERIODS; i++) {
+      builder.add(createPeriod(i));
+    }
+    PERIODS = builder.build();
+  }
+
+  @Test
+  public void newArray_always_returns_a_new_instance() {
+    assertThat(LongVariationValue.newArray()).isNotSameAs(LongVariationValue.newArray());
+  }
+
+  @Test
+  public void get_returns_unset_LongVariationValue_for_each_Period_index() {
+    LongVariationValue.Array array = LongVariationValue.newArray();
+    for (Period period : PERIODS) {
+      LongVariationValue value = array.get(period);
+      verifyUnsetLongVariation(value);
+    }
+  }
+
+  @Test
+  public void get_returns_set_LongVariationValue_for_each_Period_index_if_increment_has_been_called() {
+    LongVariationValue.Array array = LongVariationValue.newArray();
+    for (Period period : PERIODS) {
+      array.increment(period, 66L);
+      LongVariationValue value = array.get(period);
+      verifySetLongVariation(value, 66L);
+    }
+  }
+
+  @Test
+  public void incrementAll_increments_internals_from_all_set_LongVariationValue_from_source() {
+    LongVariationValue.Array source = LongVariationValue.newArray()
+      .increment(createPeriod(2), 20l)
+      .increment(createPeriod(5), 5l);
+
+    LongVariationValue.Array target = LongVariationValue.newArray()
+      .increment(createPeriod(1), 1L)
+      .increment(createPeriod(5), 30L);
+    target.incrementAll(source);
+
+    verifySetLongVariation(target.get(createPeriod(1)), 1L);
+    verifySetLongVariation(target.get(createPeriod(2)), 20L);
+    verifyUnsetLongVariation(target.get(createPeriod(3)));
+    verifyUnsetLongVariation(target.get(createPeriod(4)));
+    verifySetLongVariation(target.get(createPeriod(5)), 35L);
+  }
+
+  @Test
+  public void toMeasureVariations_returns_absent_if_no_LongVariationValue_has_been_set() {
+    assertThat(LongVariationValue.newArray().toMeasureVariations()).isAbsent();
+  }
+
+  @Test
+  public void toMeasureVariations_returns_value_of_set_LongVariationValue_as_double() {
+    Optional<MeasureVariations> variationsOptional = LongVariationValue.newArray()
+      .increment(createPeriod(2), 2L)
+      .increment(createPeriod(5), 15L)
+      .toMeasureVariations();
+
+    assertThat(variationsOptional).isPresent();
+    MeasureVariations variations = variationsOptional.get();
+    assertThat(variations.hasVariation1()).isFalse();
+    assertThat(variations.getVariation2()).isEqualTo(2d);
+    assertThat(variations.hasVariation3()).isFalse();
+    assertThat(variations.hasVariation4()).isFalse();
+    assertThat(variations.getVariation5()).isEqualTo(15d);
+  }
+
+  private static void verifyUnsetLongVariation(LongVariationValue value) {
+    assertThat(value.isSet()).isFalse();
+    assertThat(value.getValue()).isEqualTo(0L);
+  }
+
+  private static void verifySetLongVariation(LongVariationValue value, long expectedValue) {
+    assertThat(value.isSet()).isTrue();
+    assertThat(value.getValue()).isEqualTo(expectedValue);
+  }
+
+  private static Period createPeriod(int i) {
+    return new Period(i, "mode " + i, null, 100L + i, 753L + i);
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/formula/counter/LongVariationValueTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/formula/counter/LongVariationValueTest.java
new file mode 100644 (file)
index 0000000..9782366
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * 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 org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class LongVariationValueTest {
+  @Test
+  public void newly_created_LongVariationValue_is_unset_and_has_value_0() {
+    verifyUnsetVariationValue(new LongVariationValue());
+  }
+
+  @Test
+  public void increment_long_sets_LongVariationValue_and_increments_value() {
+    verifySetVariationValue(new LongVariationValue().increment(10L), 10L);
+  }
+
+  @Test
+  public void increment_LongVariationValue_has_no_effect_if_arg_is_null() {
+    verifyUnsetVariationValue(new LongVariationValue().increment(null));
+  }
+
+  @Test
+  public void increment_LongVariationValue_has_no_effect_if_arg_is_unset() {
+    verifyUnsetVariationValue(new LongVariationValue().increment(new LongVariationValue()));
+  }
+
+  @Test
+  public void increment_LongVariationValue_increments_by_the_value_of_the_arg() {
+    LongVariationValue source = new LongVariationValue().increment(10L);
+    LongVariationValue target = new LongVariationValue().increment(source);
+
+    verifySetVariationValue(target, 10L);
+  }
+
+  @Test
+  public void multiple_calls_to_increment_LongVariationValue_increments_by_the_value_of_the_arg() {
+    LongVariationValue target = new LongVariationValue()
+      .increment(new LongVariationValue().increment(35L))
+      .increment(new LongVariationValue().increment(10L));
+
+    verifySetVariationValue(target, 45L);
+  }
+
+  @Test
+  public void multiples_calls_to_increment_long_increment_the_value() {
+    LongVariationValue variationValue = new LongVariationValue()
+      .increment(10L)
+      .increment(95L);
+
+    verifySetVariationValue(variationValue, 105L);
+  }
+
+  private static void verifyUnsetVariationValue(LongVariationValue variationValue) {
+    assertThat(variationValue.isSet()).isFalse();
+    assertThat(variationValue.getValue()).isEqualTo(0L);
+  }
+
+  private static void verifySetVariationValue(LongVariationValue variationValue, long expected) {
+    assertThat(variationValue.isSet()).isTrue();
+    assertThat(variationValue.getValue()).isEqualTo(expected);
+  }
+}