@@ -91,6 +91,7 @@ public final class Measure { | |||
private Measure(ValueType valueType, @Nullable Integer ruleId, @Nullable Integer characteristicId, | |||
@Nullable Double value, @Nullable String data, @Nullable Level dataLevel, | |||
@Nullable String description, @Nullable QualityGateStatus qualityGateStatus, @Nullable MeasureVariations variations) { | |||
checkArgument(value == null || !Double.isNaN(value), "Nan is not allowed as a Measure value"); | |||
this.valueType = valueType; | |||
this.ruleId = ruleId; | |||
this.characteristicId = characteristicId; | |||
@@ -107,7 +108,6 @@ public final class Measure { | |||
if (value == null) { | |||
return null; | |||
} | |||
checkArgument(!Double.isNaN(value), "Measure value can not be NaN"); | |||
BigDecimal bd = BigDecimal.valueOf(value); | |||
return bd.setScale(DEFAULT_PRECISION, RoundingMode.HALF_UP).doubleValue(); | |||
} |
@@ -32,11 +32,16 @@ import static com.google.common.collect.FluentIterable.from; | |||
@Immutable | |||
public final class MeasureVariations { | |||
private static final String NAN_ERROR_MESSAGE = "NaN is not allowed in MeasureVariation"; | |||
private final Double[] variations = new Double[5]; | |||
public MeasureVariations(Double... variations) { | |||
checkArgument(variations.length <= 5, "There can not be more than 5 variations"); | |||
checkArgument(!from(Arrays.asList(variations)).filter(notNull()).isEmpty(), "There must be at least one variation"); | |||
for (Double variation : variations) { | |||
checkArgument(variation == null || !Double.isNaN(variation), NAN_ERROR_MESSAGE); | |||
} | |||
System.arraycopy(variations, 0, this.variations, 0, variations.length); | |||
} | |||
@@ -57,6 +62,7 @@ public final class MeasureVariations { | |||
@Deprecated | |||
public Builder setVariation(int index, double variation) { | |||
checkArgument(index > 0 && index < 6, "Variation index must be >= 1 and <= 5"); | |||
checkArgument(!Double.isNaN(variation), NAN_ERROR_MESSAGE); | |||
int arrayIndex = index - 1; | |||
checkState(variations[arrayIndex] == null, String.format("Variation for Period %s has already been set", index)); | |||
variations[arrayIndex] = variation; | |||
@@ -66,6 +72,7 @@ public final class MeasureVariations { | |||
public Builder setVariation(Period period, double variation) { | |||
int arrayIndex = period.getIndex() - 1; | |||
checkState(variations[arrayIndex] == null, String.format("Variation for Period %s has already been set", period.getIndex())); | |||
checkArgument(!Double.isNaN(variation), NAN_ERROR_MESSAGE); | |||
variations[arrayIndex] = variation; | |||
return this; | |||
} | |||
@@ -110,14 +117,14 @@ public final class MeasureVariations { | |||
return hasVariation(5); | |||
} | |||
private void checkHasVariation(int i) { | |||
if (!hasVariation(i)) { | |||
throw new IllegalStateException(String.format("Variation %s has not been set", i)); | |||
private void checkHasVariation(int periodIndex) { | |||
if (!hasVariation(periodIndex)) { | |||
throw new IllegalStateException(String.format("Variation %s has not been set", periodIndex)); | |||
} | |||
} | |||
public boolean hasVariation(int i) { | |||
return variations[i - 1] != null; | |||
public boolean hasVariation(int periodIndex) { | |||
return variations[periodIndex - 1] != null; | |||
} | |||
public double getVariation1() { |
@@ -57,7 +57,7 @@ public class MeasureTest { | |||
private static final int SOME_CHARACTERISTIC_ID = 42; | |||
@Rule | |||
public final ExpectedException executionException = ExpectedException.none(); | |||
public final ExpectedException expectedException = ExpectedException.none(); | |||
@DataProvider | |||
public static Object[][] all_but_INT_MEASURE() { | |||
@@ -107,16 +107,16 @@ public class MeasureTest { | |||
@Test | |||
public void forRule_throw_UOE_if_characteristicId_is_already_set() { | |||
executionException.expect(UnsupportedOperationException.class); | |||
executionException.expectMessage("A measure can not be associated to both a Characteristic and a Rule"); | |||
expectedException.expect(UnsupportedOperationException.class); | |||
expectedException.expectMessage("A measure can not be associated to both a Characteristic and a Rule"); | |||
newMeasureBuilder().forCharacteristic(SOME_CHARACTERISTIC_ID).forRule(SOME_RULE_ID); | |||
} | |||
@Test | |||
public void forCharacteristic_throw_UOE_if_ruleKey_is_already_set() { | |||
executionException.expect(UnsupportedOperationException.class); | |||
executionException.expectMessage("A measure can not be associated to both a Characteristic and a Rule"); | |||
expectedException.expect(UnsupportedOperationException.class); | |||
expectedException.expectMessage("A measure can not be associated to both a Characteristic and a Rule"); | |||
newMeasureBuilder().forRule(SOME_RULE_ID).forCharacteristic(SOME_CHARACTERISTIC_ID); | |||
} | |||
@@ -348,6 +348,22 @@ public class MeasureTest { | |||
assertThat(newMeasureBuilder().create(30.1d).getDoubleValue()).isEqualTo(30.1d); | |||
} | |||
@Test | |||
public void create_with_double_value_throws_IAE_if_value_is_NaN() { | |||
expectedException.expect(IllegalArgumentException.class); | |||
expectedException.expectMessage("Nan is not allowed as a Measure value"); | |||
newMeasureBuilder().create(Double.NaN); | |||
} | |||
@Test | |||
public void create_with_double_value_data_throws_IAE_if_value_is_NaN() { | |||
expectedException.expect(IllegalArgumentException.class); | |||
expectedException.expectMessage("Nan is not allowed as a Measure value"); | |||
newMeasureBuilder().create(Double.NaN, "some data"); | |||
} | |||
private enum WrapInArray implements Function<Measure, Measure[]> { | |||
INSTANCE; | |||
@@ -32,6 +32,7 @@ import static org.sonar.server.computation.measure.MeasureVariations.newMeasureV | |||
public class MeasureVariationsTest { | |||
public static final String NO_VARIATION_ERROR_MESSAGE = "There must be at least one variation"; | |||
public static final String NAN_ERROR_MESSAGE = "NaN is not allowed in MeasureVariation"; | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
@@ -91,6 +92,46 @@ public class MeasureVariationsTest { | |||
new MeasureVariations((Double) null, (Double) null, (Double) null, (Double) null, (Double) null); | |||
} | |||
@Test | |||
public void constructor_throws_IAE_if_any_arg_1_is_NaN() { | |||
expectedException.expect(IllegalArgumentException.class); | |||
expectedException.expectMessage(NAN_ERROR_MESSAGE); | |||
new MeasureVariations(Double.NaN); | |||
} | |||
@Test | |||
public void constructor_throws_IAE_if_any_arg_2_is_NaN() { | |||
expectedException.expect(IllegalArgumentException.class); | |||
expectedException.expectMessage(NAN_ERROR_MESSAGE); | |||
new MeasureVariations(1d, Double.NaN); | |||
} | |||
@Test | |||
public void constructor_throws_IAE_if_any_arg_3_is_NaN() { | |||
expectedException.expect(IllegalArgumentException.class); | |||
expectedException.expectMessage(NAN_ERROR_MESSAGE); | |||
new MeasureVariations(1d, 2d, Double.NaN); | |||
} | |||
@Test | |||
public void constructor_throws_IAE_if_any_arg_4_is_NaN() { | |||
expectedException.expect(IllegalArgumentException.class); | |||
expectedException.expectMessage(NAN_ERROR_MESSAGE); | |||
new MeasureVariations(1d, 2d, 3d, Double.NaN); | |||
} | |||
@Test | |||
public void constructor_throws_IAE_if_any_arg_5_is_NaN() { | |||
expectedException.expect(IllegalArgumentException.class); | |||
expectedException.expectMessage(NAN_ERROR_MESSAGE); | |||
new MeasureVariations(1d, 2d, 3d, 5d, Double.NaN); | |||
} | |||
@Test | |||
public void verify_has_variationX_and_getVariationX() { | |||
verifyAsVariations(new MeasureVariations(1d), 1d, null, null, null, null); | |||
@@ -243,12 +284,12 @@ public class MeasureVariationsTest { | |||
@Test | |||
public void verify_MeasureVariations_built_by_builder() { | |||
MeasureVariations variations = newMeasureVariationsBuilder() | |||
.setVariation(1, 1d) | |||
.setVariation(2, 2d) | |||
.setVariation(3, 3d) | |||
.setVariation(4, 4d) | |||
.setVariation(5, 5d) | |||
.build(); | |||
.setVariation(1, 1d) | |||
.setVariation(2, 2d) | |||
.setVariation(3, 3d) | |||
.setVariation(4, 4d) | |||
.setVariation(5, 5d) | |||
.build(); | |||
verifyAsVariations(variations, 1d, 2d, 3d, 4d, 5d); | |||
} | |||
@@ -276,6 +317,30 @@ public class MeasureVariationsTest { | |||
} | |||
} | |||
@Test | |||
public void builder_setVariation_for_index_throws_IAE_if_value_is_NaN() { | |||
for (int i = 1; i <= PeriodsHolder.MAX_NUMBER_OF_PERIODS; i++) { | |||
try { | |||
newMeasureVariationsBuilder().setVariation(i, Double.NaN); | |||
fail("An IAE should have been raised"); | |||
} catch (IllegalArgumentException e) { | |||
assertThat(e).hasMessage(NAN_ERROR_MESSAGE); | |||
} | |||
} | |||
} | |||
@Test | |||
public void builder_setVariation_for_Period_throws_IAE_if_value_is_NaN() { | |||
for (int i = 1; i <= PeriodsHolder.MAX_NUMBER_OF_PERIODS; i++) { | |||
try { | |||
newMeasureVariationsBuilder().setVariation(createPeriod(i), Double.NaN); | |||
fail("An IAE should have been raised"); | |||
} catch (IllegalArgumentException e) { | |||
assertThat(e).hasMessage(NAN_ERROR_MESSAGE); | |||
} | |||
} | |||
} | |||
private static Period createPeriod(int i) { | |||
return new Period(i, "mode " + i, null, 100L + i, 952L + i); | |||
} |