]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6939 ability for plugins to override the decimal scale of float
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Fri, 4 Dec 2015 10:41:15 +0000 (11:41 +0100)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Mon, 7 Dec 2015 16:26:43 +0000 (17:26 +0100)
measures

93 files changed:
it/it-plugins/batch-plugin/src/main/java/com/sonarsource/BatchPlugin.java
it/it-plugins/batch-plugin/src/main/java/com/sonarsource/decimal_scale_of_measures/DecimalScaleMeasureComputer.java [new file with mode: 0644]
it/it-plugins/batch-plugin/src/main/java/com/sonarsource/decimal_scale_of_measures/DecimalScaleMetric.java [new file with mode: 0644]
it/it-plugins/batch-plugin/src/main/java/com/sonarsource/decimal_scale_of_measures/DecimalScaleProperty.java [new file with mode: 0644]
it/it-plugins/batch-plugin/src/main/java/com/sonarsource/decimal_scale_of_measures/DecimalScaleSensor.java [new file with mode: 0644]
it/it-tests/src/test/java/it/Category3Suite.java
it/it-tests/src/test/java/it/measure/DecimalScaleMetricTest.java [new file with mode: 0644]
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/measures/ConstantFloatMeasureSensor.java [deleted file]
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/measures/XooMetrics.java [deleted file]
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/measures/package-info.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/computation/formula/AverageFormula.java
server/sonar-server/src/main/java/org/sonar/server/computation/formula/coverage/CoverageFormula.java
server/sonar-server/src/main/java/org/sonar/server/computation/measure/BatchMeasureToMeasure.java
server/sonar-server/src/main/java/org/sonar/server/computation/measure/Measure.java
server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureDtoToMeasure.java
server/sonar-server/src/main/java/org/sonar/server/computation/measure/api/MeasureComputerContextImpl.java
server/sonar-server/src/main/java/org/sonar/server/computation/metric/Metric.java
server/sonar-server/src/main/java/org/sonar/server/computation/metric/MetricDtoToMetric.java
server/sonar-server/src/main/java/org/sonar/server/computation/metric/MetricImpl.java
server/sonar-server/src/main/java/org/sonar/server/computation/sqale/SqaleMeasuresVisitor.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/CommentMeasuresStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/CustomMeasuresCopyStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/DuplicationMeasuresStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/UnitTestMeasuresStep.java
server/sonar-server/src/main/java/org/sonar/server/metric/ws/MetricJsonWriter.java
server/sonar-server/src/main/java/org/sonar/server/metric/ws/SearchAction.java
server/sonar-server/src/main/java/org/sonar/server/startup/RegisterMetrics.java
server/sonar-server/src/test/java/org/sonar/server/computation/formula/AverageFormulaExecutionTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/formula/AverageFormulaTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/formula/coverage/CoverageUtilsTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/issue/commonrule/CommentDensityRuleTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/issue/commonrule/CoverageRuleTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/measure/BatchMeasureToMeasureTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/measure/BestValueOptimizationTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/measure/MapBasedRawMeasureRepositoryTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/measure/MeasureDtoToMeasureTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/measure/MeasureRepositoryImplTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/measure/MeasureTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/measure/MeasureToMeasureDtoTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/measure/api/MeasureImplTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/metric/MetricImplTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/metric/MetricRepositoryRule.java
server/sonar-server/src/test/java/org/sonar/server/computation/qualitygate/ConditionEvaluatorTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/sqale/ReportSqaleMeasuresVisitorTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/sqale/ViewsSqaleMeasuresVisitorTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/CustomMeasuresCopyStepTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistMeasuresStepTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/ReportComplexityMeasuresStepTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/ReportComputeMeasureVariationsStepTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/ReportCoverageMeasuresStepTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/ReportUnitTestMeasuresStepTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/ViewsComplexityMeasuresStepTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/ViewsComputeMeasureVariationsStepTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/ViewsCoverageMeasuresStepTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/ViewsUnitTestMeasuresStepTest.java
server/sonar-server/src/test/java/org/sonar/server/startup/RegisterMetricsTest.java
server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/disable_undefined_metrics-result.xml
server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/disable_undefined_metrics.xml
server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/enable_disabled_metric-result.xml
server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/enable_disabled_metric.xml
server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/insert_new_metrics-result.xml
server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/update_non_custom_metrics-result.xml
server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/update_non_custom_metrics.xml
server/sonar-web/src/main/webapp/WEB-INF/app/models/project_measure.rb
server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1005_add_decimal_scale_to_metrics.rb [new file with mode: 0644]
sonar-batch/src/test/java/org/sonar/batch/mediumtest/measures/MeasuresMediumTest.java
sonar-db/src/main/java/org/sonar/db/metric/MetricDto.java
sonar-db/src/main/java/org/sonar/db/version/DatabaseVersion.java
sonar-db/src/main/resources/org/sonar/db/metric/MetricMapper.xml
sonar-db/src/main/resources/org/sonar/db/version/rows-h2.sql
sonar-db/src/main/resources/org/sonar/db/version/schema-h2.ddl
sonar-db/src/test/java/org/sonar/db/metric/MetricDaoTest.java
sonar-db/src/test/resources/org/sonar/db/metric/MetricDaoTest/shared.xml
sonar-plugin-api/src/main/java/org/sonar/api/batch/DefaultFormulaContext.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/DefaultFormulaData.java
sonar-plugin-api/src/main/java/org/sonar/api/measures/AverageFormula.java
sonar-plugin-api/src/main/java/org/sonar/api/measures/FormulaContext.java
sonar-plugin-api/src/main/java/org/sonar/api/measures/FormulaData.java
sonar-plugin-api/src/main/java/org/sonar/api/measures/MeanAggregationFormula.java
sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java
sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java
sonar-plugin-api/src/main/java/org/sonar/api/measures/SumChildDistributionFormula.java
sonar-plugin-api/src/main/java/org/sonar/api/measures/SumChildValuesFormula.java
sonar-plugin-api/src/main/java/org/sonar/api/measures/WeightedMeanAggregationFormula.java
sonar-plugin-api/src/test/java/org/sonar/api/batch/DefaultFormulaDataTest.java
sonar-plugin-api/src/test/java/org/sonar/api/measures/AverageFormulaTest.java
sonar-plugin-api/src/test/java/org/sonar/api/measures/MeanAggregationFormulaTest.java
sonar-plugin-api/src/test/java/org/sonar/api/measures/MeasureTest.java
sonar-plugin-api/src/test/java/org/sonar/api/measures/MetricTest.java
sonar-plugin-api/src/test/java/org/sonar/api/measures/SumChildDistributionFormulaTest.java
sonar-plugin-api/src/test/java/org/sonar/api/measures/SumChildValuesFormulaTest.java [deleted file]
sonar-plugin-api/src/test/java/org/sonar/api/measures/WeightedMeanAggregationFormulaTest.java [new file with mode: 0644]

index 7c4c479c64b41f24436f844d4dc4741f328061bb..f26975594f9a827e75f400f5fbc522aa407cf5e0 100644 (file)
@@ -1,5 +1,9 @@
 package com.sonarsource;
 
+import com.sonarsource.decimal_scale_of_measures.DecimalScaleMeasureComputer;
+import com.sonarsource.decimal_scale_of_measures.DecimalScaleMetric;
+import com.sonarsource.decimal_scale_of_measures.DecimalScaleProperty;
+import com.sonarsource.decimal_scale_of_measures.DecimalScaleSensor;
 import java.util.Arrays;
 import java.util.List;
 import org.sonar.api.SonarPlugin;
@@ -8,6 +12,12 @@ public class BatchPlugin extends SonarPlugin {
 
   public List getExtensions() {
     return Arrays.asList(
+      // SONAR-6939 decimal_scale_of_measures
+      DecimalScaleMeasureComputer.class,
+      DecimalScaleMetric.class,
+      DecimalScaleSensor.class,
+      DecimalScaleProperty.definition(),
+
       DumpSettingsInitializer.class,
       RaiseMessageException.class,
       TempFolderExtension.class,
diff --git a/it/it-plugins/batch-plugin/src/main/java/com/sonarsource/decimal_scale_of_measures/DecimalScaleMeasureComputer.java b/it/it-plugins/batch-plugin/src/main/java/com/sonarsource/decimal_scale_of_measures/DecimalScaleMeasureComputer.java
new file mode 100644 (file)
index 0000000..f3dc985
--- /dev/null
@@ -0,0 +1,34 @@
+package com.sonarsource.decimal_scale_of_measures;
+
+import org.sonar.api.ce.measure.Measure;
+import org.sonar.api.ce.measure.MeasureComputer;
+
+public class DecimalScaleMeasureComputer implements MeasureComputer {
+
+  @Override
+  public MeasureComputerDefinition define(MeasureComputerDefinitionContext defContext) {
+    return defContext.newDefinitionBuilder()
+      // Output metrics must contains at least one metric
+      .setOutputMetrics(DecimalScaleMetric.KEY)
+
+      .build();
+  }
+
+  @Override
+  public void compute(MeasureComputerContext context) {
+    if (context.getMeasure(DecimalScaleMetric.KEY) == null) {
+      Iterable<Measure> childMeasures = context.getChildrenMeasures(DecimalScaleMetric.KEY);
+      int count = 0;
+      double total = 0.0;
+      for (Measure childMeasure : childMeasures) {
+        count++;
+        total += childMeasure.getDoubleValue();
+      }
+      double value = 0.0;
+      if (count > 0) {
+        value = total / count;
+      }
+      context.addMeasure(DecimalScaleMetric.KEY, value);
+    }
+  }
+}
diff --git a/it/it-plugins/batch-plugin/src/main/java/com/sonarsource/decimal_scale_of_measures/DecimalScaleMetric.java b/it/it-plugins/batch-plugin/src/main/java/com/sonarsource/decimal_scale_of_measures/DecimalScaleMetric.java
new file mode 100644 (file)
index 0000000..ef12e05
--- /dev/null
@@ -0,0 +1,25 @@
+package com.sonarsource.decimal_scale_of_measures;
+
+import java.util.Collections;
+import java.util.List;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.measures.Metrics;
+
+public class DecimalScaleMetric implements Metrics {
+
+  public static final String KEY = "decimal_scale";
+
+  private static final Metric METRIC = new Metric.Builder(KEY, "Decimal Scale", Metric.ValueType.FLOAT)
+    .setDescription("Numeric metric with overridden decimal scale")
+    .setDecimalScale(4)
+    .create();
+
+  @Override
+  public List getMetrics() {
+    return Collections.singletonList(definition());
+  }
+
+  public static Metric definition() {
+    return METRIC;
+  }
+}
diff --git a/it/it-plugins/batch-plugin/src/main/java/com/sonarsource/decimal_scale_of_measures/DecimalScaleProperty.java b/it/it-plugins/batch-plugin/src/main/java/com/sonarsource/decimal_scale_of_measures/DecimalScaleProperty.java
new file mode 100644 (file)
index 0000000..5fa85e7
--- /dev/null
@@ -0,0 +1,13 @@
+package com.sonarsource.decimal_scale_of_measures;
+
+import org.sonar.api.PropertyType;
+import org.sonar.api.config.PropertyDefinition;
+
+public class DecimalScaleProperty {
+
+  public static final String KEY = "sonar.scanner.feedDecimalScaleMetric";
+
+  public static PropertyDefinition definition() {
+    return PropertyDefinition.builder(KEY).name("Enable test decimal_scale_of_measures").type(PropertyType.BOOLEAN).defaultValue(String.valueOf(false)).build();
+  }
+}
diff --git a/it/it-plugins/batch-plugin/src/main/java/com/sonarsource/decimal_scale_of_measures/DecimalScaleSensor.java b/it/it-plugins/batch-plugin/src/main/java/com/sonarsource/decimal_scale_of_measures/DecimalScaleSensor.java
new file mode 100644 (file)
index 0000000..c6fe8c6
--- /dev/null
@@ -0,0 +1,36 @@
+package com.sonarsource.decimal_scale_of_measures;
+
+import org.sonar.api.batch.Sensor;
+import org.sonar.api.batch.SensorContext;
+import org.sonar.api.batch.fs.FilePredicate;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.resources.Project;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+
+public class DecimalScaleSensor implements Sensor {
+  private static final Logger LOG = Loggers.get(DecimalScaleSensor.class);
+
+  @Override
+  public boolean shouldExecuteOnProject(Project project) {
+    return true;
+  }
+
+  @Override
+  public void analyse(Project module, SensorContext context) {
+    if (context.settings().getBoolean(DecimalScaleProperty.KEY)) {
+      FilePredicate all = context.fileSystem().predicates().all();
+      Iterable<InputFile> files = context.fileSystem().inputFiles(all);
+      double value = 0.0001;
+      for (InputFile file : files) {
+        LOG.info("Value for {}: {}", file.relativePath(), value);
+        context.newMeasure()
+          .on(file)
+          .forMetric(DecimalScaleMetric.definition())
+          .withValue(value)
+          .save();
+        value += 0.0001;
+      }
+    }
+  }
+}
index 61bfc18575acbafbee92e2a0d7425495408ced5d..cd1f4974f5c815fcd02dc8149eff696a7bf6180d 100644 (file)
@@ -7,6 +7,7 @@ package it;
 
 import com.sonar.orchestrator.Orchestrator;
 import it.analysis.*;
+import it.measure.DecimalScaleMetricTest;
 import org.junit.ClassRule;
 import org.junit.runner.RunWith;
 import org.junit.runners.Suite;
@@ -29,7 +30,9 @@ import static util.ItUtils.xooPlugin;
   BatchTest.class,
   IssuesModeTest.class,
   SettingsEncryptionTest.class,
-  ReportDumpTest.class
+  ReportDumpTest.class,
+  // measures
+  DecimalScaleMetricTest.class
 })
 public class Category3Suite {
 
@@ -45,7 +48,7 @@ public class Category3Suite {
     // Used by IssuesModeTest
     .addPlugin(pluginArtifact("access-secured-props-plugin"))
 
-    // used by TempFolderTest
+    // used by TempFolderTest and DecimalScaleMetricTest
     .addPlugin(pluginArtifact("batch-plugin"))
 
     // used by ExtensionLifecycleTest
diff --git a/it/it-tests/src/test/java/it/measure/DecimalScaleMetricTest.java b/it/it-tests/src/test/java/it/measure/DecimalScaleMetricTest.java
new file mode 100644 (file)
index 0000000..63c7160
--- /dev/null
@@ -0,0 +1,39 @@
+package it.measure;
+
+import com.sonar.orchestrator.Orchestrator;
+import it.Category3Suite;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.wsclient.services.Resource;
+import org.sonar.wsclient.services.ResourceQuery;
+import util.ItUtils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * SONAR-6939
+ */
+public class DecimalScaleMetricTest {
+
+  /**
+   * Requires the plugin "batch-plugin" 
+   */
+  @ClassRule
+  public static Orchestrator orchestrator = Category3Suite.ORCHESTRATOR;
+
+  @Test
+  public void override_decimal_scale_of_numeric_metric() {
+    String projectKey = "DecimalScaleMetricTest.override_decimal_scale_of_numeric_metric";
+    // see DecimalScaleMetric
+    String metricKey = "decimal_scale";
+    ItUtils.runProjectAnalysis(orchestrator, "shared/xoo-sample",
+      "sonar.projectKey", projectKey,
+      "sonar.scanner.feedDecimalScaleMetric", String.valueOf(true));
+
+    Resource resource = orchestrator.getServer().getWsClient()
+      .find(ResourceQuery.createForMetrics(projectKey, metricKey));
+    // Ability to define decimal scale of metrics was introduced in v5.3. By default it is 1.
+    assertThat(resource.getMeasureValue(metricKey)).isEqualTo(0.0001);
+    assertThat(resource.getMeasureFormattedValue(metricKey, null)).isEqualTo("0.0001");
+  }
+}
index a2cb7066e0a4044b7f6395ce72824af453834a9a..598be59d3dc73d3564076cf0121b7d20f33b001f 100644 (file)
@@ -32,8 +32,6 @@ import org.sonar.xoo.lang.SymbolReferencesSensor;
 import org.sonar.xoo.lang.SyntaxHighlightingSensor;
 import org.sonar.xoo.lang.XooCpdMapping;
 import org.sonar.xoo.lang.XooTokenizer;
-import org.sonar.xoo.measures.ConstantFloatMeasureSensor;
-import org.sonar.xoo.measures.XooMetrics;
 import org.sonar.xoo.rule.ChecksSensor;
 import org.sonar.xoo.rule.CreateIssueByInternalKeySensor;
 import org.sonar.xoo.rule.DeprecatedResourceApiSensor;
@@ -115,10 +113,6 @@ public class XooPlugin extends SonarPlugin {
       TestExecutionSensor.class,
       CoveragePerTestSensor.class,
 
-      // Measures
-      XooMetrics.class,
-      ConstantFloatMeasureSensor.class,
-
       // Other
       XooProjectBuilder.class,
       XooPostJob.class);
diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/measures/ConstantFloatMeasureSensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/measures/ConstantFloatMeasureSensor.java
deleted file mode 100644 (file)
index 416efe2..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.xoo.measures;
-
-import org.sonar.api.batch.Sensor;
-import org.sonar.api.batch.SensorContext;
-import org.sonar.api.batch.fs.FileSystem;
-import org.sonar.api.batch.fs.InputFile;
-import org.sonar.api.config.Settings;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.resources.Project;
-import org.sonar.xoo.Xoo;
-
-/**
- * Save a constant float measure on each XOO source file
- */
-public class ConstantFloatMeasureSensor implements Sensor {
-
-  public static final String SONAR_XOO_ENABLE_FLOAT_SENSOR = "sonar.xoo.enableFloatSensor";
-  public static final String SONAR_XOO_FLOAT_PRECISION = "sonar.xoo.floatPrecision";
-
-  public static final double CONSTANT_VALUE = 1.2345678910111213d;
-
-  private final FileSystem fs;
-  private final Settings settings;
-
-  public ConstantFloatMeasureSensor(FileSystem fs, Settings settings) {
-    this.fs = fs;
-    this.settings = settings;
-  }
-
-  @Override
-  public boolean shouldExecuteOnProject(Project project) {
-    return fs.hasFiles(fs.predicates().hasLanguage(Xoo.KEY)) && settings.getBoolean(
-      SONAR_XOO_ENABLE_FLOAT_SENSOR);
-  }
-
-  @Override
-  public void analyse(Project project, SensorContext context) {
-    Measure<?> floatMeasure = settings.hasKey(SONAR_XOO_FLOAT_PRECISION)
-      ? new Measure<>(XooMetrics.CONSTANT_FLOAT_MEASURE, CONSTANT_VALUE, settings.getInt(SONAR_XOO_FLOAT_PRECISION))
-      : new Measure<>(XooMetrics.CONSTANT_FLOAT_MEASURE, CONSTANT_VALUE);
-    for (InputFile inputFile : getSourceFiles()) {
-      context.saveMeasure(inputFile, floatMeasure);
-    }
-  }
-
-  private Iterable<InputFile> getSourceFiles() {
-    return fs.inputFiles(fs.predicates().and(fs.predicates().hasLanguage(Xoo.KEY), fs.predicates().hasType(InputFile.Type.MAIN)));
-  }
-
-  @Override
-  public String toString() {
-    return getClass().getSimpleName();
-  }
-}
diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/measures/XooMetrics.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/measures/XooMetrics.java
deleted file mode 100644 (file)
index 511baf2..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.xoo.measures;
-
-import com.google.common.collect.Lists;
-import java.util.List;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.measures.Metrics;
-
-public final class XooMetrics implements Metrics {
-
-  public static final String CONSTANT_FLOAT_MEASURE_KEY = "xoo_constant_float_measure";
-
-  public static final Metric<Float> CONSTANT_FLOAT_MEASURE = new Metric.Builder(CONSTANT_FLOAT_MEASURE_KEY, "Constant float measure", Metric.ValueType.FLOAT)
-    .setDescription("Return always the same float measure for every components")
-    .setDirection(Metric.DIRECTION_WORST)
-    .setDomain(CoreMetrics.DOMAIN_GENERAL)
-    .create();
-
-  @Override
-  public List<Metric> getMetrics() {
-    return Lists.<Metric>newArrayList(CONSTANT_FLOAT_MEASURE);
-  }
-}
diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/measures/package-info.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/measures/package-info.java
deleted file mode 100644 (file)
index 53dbecc..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.
- */
-
-@ParametersAreNonnullByDefault
-package org.sonar.xoo.measures;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
index 1506751c82e8876fe6212a33242870d2bb00411c..f2456fb68a326407788facd81f223ae44f6446d7 100644 (file)
@@ -56,7 +56,7 @@ public class AverageFormula implements Formula<AverageFormula.AverageCounter> {
       double mainValue = mainValueOptional.get();
       double byValue = byValueOptional.get();
       if (byValue > 0d) {
-        return Optional.of(Measure.newMeasureBuilder().create(mainValue / byValue));
+        return Optional.of(Measure.newMeasureBuilder().create(mainValue / byValue, context.getMetric().getDecimalScale()));
       }
     }
     return Optional.absent();
@@ -78,7 +78,7 @@ public class AverageFormula implements Formula<AverageFormula.AverageCounter> {
       // prevents instantiation outside static method
     }
 
-    public static Builder newBuilder(){
+    public static Builder newBuilder() {
       return new Builder();
     }
 
index 1521df8f9d09d697d7990fc41b34442cadb5cb56..6f44d2fbc2f385673e6ee05ced2c79019bc2f8ea 100644 (file)
@@ -39,7 +39,7 @@ public abstract class CoverageFormula<T extends ElementsAndCoveredElementsCounte
     long elements = counter.elements;
     long coveredElements = counter.coveredElements;
     if (elements > 0L) {
-      return Optional.of(newMeasureBuilder().create(calculateCoverage(coveredElements, elements)));
+      return Optional.of(newMeasureBuilder().create(calculateCoverage(coveredElements, elements), context.getMetric().getDecimalScale()));
     }
     return Optional.absent();
   }
index a7931c611167b18b212090927c439967f9e921df..9c10dfde0238e2d4fa003dc17e55721e08f47e42 100644 (file)
@@ -75,7 +75,10 @@ public class BatchMeasureToMeasure {
     if (!batchMeasure.hasDoubleValue()) {
       return toNoValueMeasure(builder, batchMeasure);
     }
-    return of(builder.create(batchMeasure.getDoubleValue(), data));
+    return of(builder.create(batchMeasure.getDoubleValue(),
+      // Decimals are not truncated in scanner report, so an arbitrary decimal scale is applied when reading values from report
+      org.sonar.api.measures.Metric.MAX_DECIMAL_SCALE,
+      data));
   }
 
   private static Optional<Measure> toBooleanMeasure(Measure.NewMeasureBuilder builder, BatchReport.Measure batchMeasure, @Nullable String data) {
index 0891ca0e1378d936c1823769b8c3fbdd38a682b6..ffb4ead08098c04e2749287c39e9b32df09aa671 100644 (file)
@@ -34,11 +34,6 @@ import static java.util.Objects.requireNonNull;
 
 public final class Measure {
 
-  /**
-   * Default precision when saving a double value type
-   */
-  private static final int DEFAULT_PRECISION = 1;
-
   public enum ValueType {
     NO_VALUE, BOOLEAN, INT, LONG, DOUBLE, STRING, LEVEL
   }
@@ -94,12 +89,11 @@ public final class Measure {
   private Measure(ValueType valueType, @Nullable Integer ruleId, @Nullable Integer characteristicId, @Nullable Developer developer,
     @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;
     this.developer = developer;
-    this.value = scale(value);
+    this.value = value;
     this.data = data;
     this.dataLevel = dataLevel;
     this.description = description;
@@ -107,15 +101,6 @@ public final class Measure {
     this.variations = variations;
   }
 
-  @CheckForNull
-  private static Double scale(@Nullable Double value) {
-    if (value == null) {
-      return null;
-    }
-    BigDecimal bd = BigDecimal.valueOf(value);
-    return bd.setScale(DEFAULT_PRECISION, RoundingMode.HALF_UP).doubleValue();
-  }
-
   public static NewMeasureBuilder newMeasureBuilder() {
     return new NewMeasureBuilder();
   }
@@ -217,12 +202,14 @@ public final class Measure {
       return create(value, null);
     }
 
-    public Measure create(double value, @Nullable String data) {
-      return new Measure(ValueType.DOUBLE, ruleId, characteristicId, developer, value, data, null, description, qualityGateStatus, variations);
+    public Measure create(double value, int decimalScale, @Nullable String data) {
+      checkArgument(!Double.isNaN(value), "NaN is not allowed as a Measure value");
+      double scaledValue = scale(value, decimalScale);
+      return new Measure(ValueType.DOUBLE, ruleId, characteristicId, developer, scaledValue, data, null, description, qualityGateStatus, variations);
     }
 
-    public Measure create(double value) {
-      return create(value, null);
+    public Measure create(double value, int decimalScale) {
+      return create(value, decimalScale, null);
     }
 
     public Measure create(String value) {
@@ -468,4 +455,9 @@ public final class Measure {
       .add("description", description)
       .toString();
   }
+
+  private static double scale(double value, int decimalScale) {
+    BigDecimal bd = BigDecimal.valueOf(value);
+    return bd.setScale(decimalScale, RoundingMode.HALF_UP).doubleValue();
+  }
 }
index 68a598d4d2a9dfb0446beba814e4f9a148b2d8ba..b029e98ba53914ca5d4d7c2a94d22b7f1662dadc 100644 (file)
@@ -75,7 +75,9 @@ public class MeasureDtoToMeasure {
     if (value == null) {
       return toNoValueMeasure(measureDto);
     }
-    return of(setCommonProperties(Measure.newMeasureBuilder(), measureDto).create(value.doubleValue(), data));
+
+    return of(setCommonProperties(Measure.newMeasureBuilder(), measureDto)
+      .create(value.doubleValue(), org.sonar.api.measures.Metric.MAX_DECIMAL_SCALE, data));
   }
 
   private static Optional<Measure> toBooleanMeasure(MeasureDto measureDto, @Nullable Double value, String data) {
index 13d3a9a4578a91ca79bf5147610d87540168fa8d..3449aad39ffe4c36646406d0e276d1dd075ae749 100644 (file)
@@ -151,7 +151,7 @@ public class MeasureComputerContextImpl implements MeasureComputerContext {
   public void addMeasure(String metricKey, double value) {
     Metric metric = metricRepository.getByKey(metricKey);
     validateAddMeasure(metric);
-    measureRepository.add(internalComponent, metric, newMeasureBuilder().create(value));
+    measureRepository.add(internalComponent, metric, newMeasureBuilder().create(value, metric.getDecimalScale()));
   }
 
   @Override
index ee6771b6cfe2a597be1eb113872de5e76edc1132..3c096d6960962736ca83bc167bca1df119513a99 100644 (file)
@@ -49,6 +49,12 @@ public interface Metric {
   @CheckForNull
   Double getBestValue();
 
+  /**
+   * The decimal scale of float measures. Returned value is greater than or equal zero.
+   * @throws IllegalStateException if the value type is not decimal (see {@link org.sonar.server.computation.measure.Measure.ValueType}
+   */
+  int getDecimalScale();
+
   enum MetricType {
     INT(Measure.ValueType.INT),
     MILLISEC(Measure.ValueType.LONG),
index cfce85a40476e499c875fabce77ae16850f0e5b0..eed9a9583990fb4c7902b5e6b54a204f8973273d 100644 (file)
@@ -22,15 +22,27 @@ package org.sonar.server.computation.metric;
 import com.google.common.base.Function;
 import javax.annotation.Nonnull;
 import org.sonar.db.metric.MetricDto;
+import org.sonar.server.computation.measure.Measure;
+
+import static com.google.common.base.Objects.firstNonNull;
 
 enum MetricDtoToMetric implements Function<MetricDto, Metric> {
   INSTANCE;
 
+  private static final int DEFAULT_DECIMAL_SCALE = 1;
+
   @Override
   @Nonnull
   public Metric apply(@Nonnull MetricDto metricDto) {
+    Metric.MetricType metricType = Metric.MetricType.valueOf(metricDto.getValueType());
+    Integer decimalScale = null;
+    if (metricType.getValueType() == Measure.ValueType.DOUBLE) {
+      decimalScale = firstNonNull(metricDto.getDecimalScale(), DEFAULT_DECIMAL_SCALE);
+    }
+
     return new MetricImpl(
-      metricDto.getId(), metricDto.getKey(), metricDto.getShortName(), Metric.MetricType.valueOf(metricDto.getValueType()),
+      metricDto.getId(), metricDto.getKey(), metricDto.getShortName(), metricType,
+      decimalScale,
       metricDto.getBestValue(), metricDto.isOptimizedBestValue());
   }
 }
index 0e8980d53ea9140d3d5f9d6b34301718e9acc8bb..df4119120758d098433415789b447a7581c12e8c 100644 (file)
  */
 package org.sonar.server.computation.metric;
 
-import java.util.Objects;
+import com.google.common.base.Objects;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
+import org.sonar.server.computation.measure.Measure;
 
 import static com.google.common.base.Preconditions.checkArgument;
-import static java.util.Objects.requireNonNull;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
 
 @Immutable
 public final class MetricImpl implements Metric {
@@ -34,20 +36,26 @@ public final class MetricImpl implements Metric {
   private final String key;
   private final String name;
   private final MetricType type;
+  private final Integer decimalScale;
   private final Double bestValue;
   private final boolean bestValueOptimized;
 
   public MetricImpl(int id, String key, String name, MetricType type) {
-    this(id, key, name, type, null, false);
+    this(id, key, name, type, null, null, false);
   }
 
-  public MetricImpl(int id, String key, String name, MetricType type,
+  public MetricImpl(int id, String key, String name, MetricType type, @Nullable Integer decimalScale,
     @Nullable Double bestValue, boolean bestValueOptimized) {
     checkArgument(!bestValueOptimized || bestValue != null, "A BestValue must be specified if Metric is bestValueOptimized");
     this.id = id;
-    this.key = requireNonNull(key);
-    this.name = requireNonNull(name);
-    this.type = requireNonNull(type);
+    this.key = checkNotNull(key);
+    this.name = checkNotNull(name);
+    this.type = checkNotNull(type);
+    if (type.getValueType() == Measure.ValueType.DOUBLE) {
+      this.decimalScale = Objects.firstNonNull(decimalScale, org.sonar.api.measures.Metric.DEFAULT_DECIMAL_SCALE);
+    } else {
+      this.decimalScale = decimalScale;
+    }
     this.bestValueOptimized = bestValueOptimized;
     this.bestValue = bestValue;
   }
@@ -72,6 +80,12 @@ public final class MetricImpl implements Metric {
     return type;
   }
 
+  @Override
+  public int getDecimalScale() {
+    checkState(decimalScale != null, "Decimal scale is not defined on metric %s", key);
+    return decimalScale;
+  }
+
   @Override
   @CheckForNull
   public Double getBestValue() {
@@ -92,7 +106,7 @@ public final class MetricImpl implements Metric {
       return false;
     }
     MetricImpl metric = (MetricImpl) o;
-    return Objects.equals(key, metric.key);
+    return Objects.equal(key, metric.key);
   }
 
   @Override
index 7ebcf4ea813ebf476c0f6b8489dcb3dbcc92f5f4..cc2cb24ad3f2afca42d8d5560246a1b42d1332b5 100644 (file)
@@ -129,7 +129,7 @@ public class SqaleMeasuresVisitor extends PathAwareVisitorAdapter<SqaleMeasuresV
   }
 
   private void saveDebtRatioMeasure(Component component, double density) {
-    measureRepository.add(component, debtRatioMetric, newMeasureBuilder().create(100.0 * density));
+    measureRepository.add(component, debtRatioMetric, newMeasureBuilder().create(100.0 * density, debtRatioMetric.getDecimalScale()));
   }
 
   private void saveSqaleRatingMeasure(Component component, double density) {
index 883960d4aa9dc553a7068c5b5f090880b78a9d99..1ca58fd3a1f90d2273e64184b7e8c64ebd00f772 100644 (file)
@@ -112,7 +112,7 @@ public class CommentMeasuresStep implements ComputationStep {
           double divisor = nclocs + comments;
           if (divisor > 0d) {
             double value = 100d * (comments / divisor);
-            return Optional.of(Measure.newMeasureBuilder().create(value));
+            return Optional.of(Measure.newMeasureBuilder().create(value, context.getMetric().getDecimalScale()));
           }
         }
       }
@@ -155,7 +155,7 @@ public class CommentMeasuresStep implements ComputationStep {
         if (publicApis > 0d) {
           double documentedAPI = publicApis - publicUndocumentedApis;
           double value = 100d * (documentedAPI / publicApis);
-          return Optional.of(Measure.newMeasureBuilder().create(value));
+          return Optional.of(Measure.newMeasureBuilder().create(value, context.getMetric().getDecimalScale()));
         }
       }
       return Optional.absent();
index 2cf7e865d0f19adf1399d2f1cf0e932779178e6c..60eff65c48974c6f73d3e5df10f9ef5d0b0346e1 100644 (file)
@@ -92,7 +92,7 @@ public class CustomMeasuresCopyStep implements ComputationStep {
         return Measure.newMeasureBuilder().create((long) dto.getValue());
       case FLOAT:
       case PERCENT:
-        return Measure.newMeasureBuilder().create(dto.getValue());
+        return Measure.newMeasureBuilder().create(dto.getValue(), metric.getDecimalScale());
       case BOOL:
         return Measure.newMeasureBuilder().create(NumberUtils.compare(dto.getValue(), 1.0) == 0);
       case LEVEL:
index 2d60d64a37b5fd4a93139b6a5b6ff1b81263a973..897d7f231b720123efe79952774d154305d1dd07 100644 (file)
@@ -209,7 +209,7 @@ public class DuplicationMeasuresStep implements ComputationStep {
       Optional<Integer> nbLines = getNbLinesFromLocOrNcloc(context);
       if (nbLines.isPresent() && nbLines.get() > 0) {
         double density = Math.min(100d, 100d * duplicatedLines / nbLines.get());
-        return Optional.of(Measure.newMeasureBuilder().create(density));
+        return Optional.of(Measure.newMeasureBuilder().create(density, context.getMetric().getDecimalScale()));
       }
       return Optional.absent();
     }
index 61a87ac128353b177d62d731f8516e067277e51d..47d67790df342c94cf7345f6d5bec273fecc7a67 100644 (file)
@@ -92,7 +92,7 @@ public class UnitTestMeasuresStep implements ComputationStep {
         case TEST_FAILURES_KEY:
           return createMeasure(context.getComponent().getType(), counter.testsFailuresCounter.getValue());
         case TEST_SUCCESS_DENSITY_KEY:
-          return createDensityMeasure(counter);
+          return createDensityMeasure(counter, context.getMetric().getDecimalScale());
         default:
           throw new IllegalStateException(String.format("Metric '%s' is not supported", metricKey));
       }
@@ -105,7 +105,7 @@ public class UnitTestMeasuresStep implements ComputationStep {
       return Optional.absent();
     }
 
-    private static Optional<Measure> createDensityMeasure(UnitTestsCounter counter) {
+    private static Optional<Measure> createDensityMeasure(UnitTestsCounter counter, int decimalScale) {
       if (isPositive(counter.testsCounter.getValue(), true)
         && isPositive(counter.testsErrorsCounter.getValue(), false)
         && isPositive(counter.testsFailuresCounter.getValue(), false)) {
@@ -113,7 +113,7 @@ public class UnitTestMeasuresStep implements ComputationStep {
         int errors = counter.testsErrorsCounter.getValue().get();
         int failures = counter.testsFailuresCounter.getValue().get();
         double density = (errors + failures) * 100d / tests;
-        return Optional.of(Measure.newMeasureBuilder().create(100d - density));
+        return Optional.of(Measure.newMeasureBuilder().create(100d - density, decimalScale));
       }
       return Optional.absent();
     }
index fc9ad5b259661a14a62aafc4ea29efbde7f1d680..ceb6b9357bc462a1ffd24256a6ca32c13f52e6af 100644 (file)
@@ -40,7 +40,9 @@ public class MetricJsonWriter {
   public static final String FIELD_QUALITATIVE = "qualitative";
   public static final String FIELD_HIDDEN = "hidden";
   public static final String FIELD_CUSTOM = "custom";
-  public static final Set<String> OPTIONAL_FIELDS = ImmutableSet.of(FIELD_NAME, FIELD_DESCRIPTION, FIELD_DOMAIN, FIELD_DIRECTION, FIELD_QUALITATIVE, FIELD_HIDDEN, FIELD_CUSTOM);
+  public static final String FIELD_DECIMAL_SCALE = "decimalScale";
+  public static final Set<String> OPTIONAL_FIELDS = ImmutableSet.of(FIELD_NAME, FIELD_DESCRIPTION, FIELD_DOMAIN,
+    FIELD_DIRECTION, FIELD_QUALITATIVE, FIELD_HIDDEN, FIELD_CUSTOM, FIELD_DECIMAL_SCALE);
   public static final Set<String> MANDATORY_FIELDS = ImmutableSet.of(FIELD_ID, FIELD_KEY, FIELD_NAME, FIELD_DOMAIN, FIELD_TYPE);
   public static final Set<String> ALL_FIELDS = ImmutableSet.copyOf(Sets.union(MANDATORY_FIELDS, OPTIONAL_FIELDS));
 
@@ -69,6 +71,7 @@ public class MetricJsonWriter {
     writeIfNeeded(json, metric.isQualitative(), FIELD_QUALITATIVE, fieldsToReturn);
     writeIfNeeded(json, metric.isHidden(), FIELD_HIDDEN, fieldsToReturn);
     writeIfNeeded(json, metric.isUserManaged(), FIELD_CUSTOM, fieldsToReturn);
+    writeIfNeeded(json, metric.getDecimalScale(), FIELD_DECIMAL_SCALE, fieldsToReturn);
     json.endObject();
   }
 }
index 118230d5fa122b82bd90a2f6b299a364c9b5ca58..03aa5e668b72e0401d263a61ce6f2a678390d75b 100644 (file)
@@ -52,8 +52,6 @@ public class SearchAction implements MetricsWsAction {
 
   public static final String PARAM_IS_CUSTOM = "isCustom";
 
-  private static final Set<String> OPTIONAL_FIELDS = newHashSet(FIELD_NAME, FIELD_DESCRIPTION, FIELD_DOMAIN, FIELD_TYPE, FIELD_DIRECTION, FIELD_QUALITATIVE, FIELD_HIDDEN,
-    FIELD_CUSTOM);
   private final Set<String> allPossibleFields;
 
   private final DbClient dbClient;
@@ -61,7 +59,7 @@ public class SearchAction implements MetricsWsAction {
   public SearchAction(DbClient dbClient) {
     this.dbClient = dbClient;
     Set<String> possibleFields = newHashSet(FIELD_ID, FIELD_KEY);
-    possibleFields.addAll(OPTIONAL_FIELDS);
+    possibleFields.addAll(MetricJsonWriter.OPTIONAL_FIELDS);
     allPossibleFields = possibleFields;
   }
 
@@ -72,7 +70,7 @@ public class SearchAction implements MetricsWsAction {
       .setDescription("Search for metrics")
       .setResponseExample(getClass().getResource("example-search.json"))
       .addPagingParams(100)
-      .addFieldsParam(OPTIONAL_FIELDS)
+      .addFieldsParam(MetricJsonWriter.OPTIONAL_FIELDS)
       .setHandler(this);
 
     action.createParam(PARAM_IS_CUSTOM)
index 9f3746bf4642cd5657e6a1df0fcd37a2ea0f357b..34a7138a4736af4f953111b6671d930c7340c46e 100644 (file)
@@ -156,6 +156,7 @@ public class RegisterMetrics {
       dto.setUserManaged(metric.getUserManaged());
       dto.setWorstValue(metric.getWorstValue());
       dto.setDeleteHistoricalData(metric.getDeleteHistoricalData());
+      dto.setDecimalScale(metric.getDecimalScale());
       return dto;
     }
   }
index abf260cde66dcbd2ff19e6638e8ef320da039dfa..f34cca2d52d27bb66ad26005d034c3d9694a334b 100644 (file)
@@ -107,14 +107,14 @@ public class AverageFormulaExecutionTest {
 
     new PathAwareCrawler<>(underTest).visit(project);
 
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(1))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(3d)));
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(11))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(2d)));
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(111))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(2d)));
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(1111))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(2.5d)));
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(1112))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(1d)));
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(12))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(4.5d)));
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(121))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(4.5d)));
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(1211))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(4.5d)));
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(1))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(3d, 1)));
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(11))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(2d, 1)));
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(111))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(2d, 1)));
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(1111))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(2.5d, 1)));
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(1112))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(1d, 1)));
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(12))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(4.5d, 1)));
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(121))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(4.5d, 1)));
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(1211))).containsOnly(entryOf(FUNCTION_COMPLEXITY_KEY, newMeasureBuilder().create(4.5d, 1)));
   }
 
   @Test
index 32ad48aac48c54c88598c2065d8007f2d08b58ba..5e34ba931466645c2ac07327a15e46da9760ef5f 100644 (file)
@@ -245,7 +245,7 @@ public class AverageFormulaTest {
   }
 
   private void addMeasure(String metricKey, double value) {
-    when(counterInitializationContext.getMeasure(metricKey)).thenReturn(Optional.of(Measure.newMeasureBuilder().create(value)));
+    when(counterInitializationContext.getMeasure(metricKey)).thenReturn(Optional.of(Measure.newMeasureBuilder().create(value, 1)));
   }
 
   private void addMeasure(String metricKey, int value) {
index 9be8edbbae1f0bb0b0b147cad2a2c6c57fd1cea1..6269d2af2ff5b73f5d946a50bf40a9808cb68598 100644 (file)
@@ -87,7 +87,7 @@ public class CoverageUtilsTest {
     expectedException.expect(IllegalStateException.class);
     expectedException.expectMessage("value can not be converted to long because current value type is a DOUBLE");
 
-    fileAggregateContext.put(SOME_METRIC_KEY, newMeasureBuilder().create(152d));
+    fileAggregateContext.put(SOME_METRIC_KEY, newMeasureBuilder().create(152d, 1));
 
     getLongMeasureValue(fileAggregateContext, SOME_METRIC_KEY);
   }
index ac9c83e0451e9e7441f0db9e2fc8ea1e93748de9..6ec8488893969860e745257fde876fb2fe91216e 100644 (file)
@@ -72,7 +72,7 @@ public class CommentDensityRuleTest {
   @Test
   public void no_issues_if_enough_comments() {
     activeRuleHolder.put(new ActiveRule(RULE_KEY, Severity.CRITICAL, ImmutableMap.of(CommonRuleKeys.INSUFFICIENT_COMMENT_DENSITY_PROPERTY, "25")));
-    measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.COMMENT_LINES_DENSITY_KEY, Measure.newMeasureBuilder().create(90.0));
+    measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.COMMENT_LINES_DENSITY_KEY, Measure.newMeasureBuilder().create(90.0, 1));
 
     DefaultIssue issue = underTest.processFile(FILE, "java");
 
@@ -82,7 +82,7 @@ public class CommentDensityRuleTest {
   @Test
   public void issue_if_not_enough_comments() {
     activeRuleHolder.put(new ActiveRule(RULE_KEY, Severity.CRITICAL, ImmutableMap.of(CommonRuleKeys.INSUFFICIENT_COMMENT_DENSITY_PROPERTY, "25")));
-    measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.COMMENT_LINES_DENSITY_KEY, Measure.newMeasureBuilder().create(10.0));
+    measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.COMMENT_LINES_DENSITY_KEY, Measure.newMeasureBuilder().create(10.0, 1));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.COMMENT_LINES_KEY, Measure.newMeasureBuilder().create(40));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.NCLOC_KEY, Measure.newMeasureBuilder().create(360));
 
@@ -99,7 +99,7 @@ public class CommentDensityRuleTest {
   @Test
   public void issue_if_not_enough_comments__test_ceil() {
     activeRuleHolder.put(new ActiveRule(RULE_KEY, Severity.CRITICAL, ImmutableMap.of(CommonRuleKeys.INSUFFICIENT_COMMENT_DENSITY_PROPERTY, "25")));
-    measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.COMMENT_LINES_DENSITY_KEY, Measure.newMeasureBuilder().create(0.0));
+    measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.COMMENT_LINES_DENSITY_KEY, Measure.newMeasureBuilder().create(0.0, 1));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.COMMENT_LINES_KEY, Measure.newMeasureBuilder().create(0));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.NCLOC_KEY, Measure.newMeasureBuilder().create(1));
 
@@ -121,7 +121,7 @@ public class CommentDensityRuleTest {
     thrown.expectMessage("Minimum density of rule [common-java:InsufficientCommentDensity] is incorrect. Got [100] but must be strictly less than 100.");
 
     activeRuleHolder.put(new ActiveRule(RULE_KEY, Severity.CRITICAL, ImmutableMap.of(CommonRuleKeys.INSUFFICIENT_COMMENT_DENSITY_PROPERTY, "100")));
-    measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.COMMENT_LINES_DENSITY_KEY, Measure.newMeasureBuilder().create(0.0));
+    measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.COMMENT_LINES_DENSITY_KEY, Measure.newMeasureBuilder().create(0.0, 1));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.COMMENT_LINES_KEY, Measure.newMeasureBuilder().create(0));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), CoreMetrics.NCLOC_KEY, Measure.newMeasureBuilder().create(1));
 
index 68d6c59e9dbd828e8a5ce79b7ae8eaa79fb2819b..be3e3850d1876f88843b0d2edcf8db90f8cdb6c3 100644 (file)
@@ -86,7 +86,7 @@ public abstract class CoverageRuleTest {
   @Test
   public void no_issue_if_enough_coverage() {
     activeRuleHolder.put(new ActiveRule(getRuleKey(), Severity.CRITICAL, ImmutableMap.of(getMinPropertyKey(), "65")));
-    measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), getCoverageMetricKey(), Measure.newMeasureBuilder().create(90.0));
+    measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), getCoverageMetricKey(), Measure.newMeasureBuilder().create(90.0, 1));
 
     DefaultIssue issue = underTest.processFile(FILE, "java");
 
@@ -96,7 +96,7 @@ public abstract class CoverageRuleTest {
   @Test
   public void issue_if_coverage_is_too_low() {
     activeRuleHolder.put(new ActiveRule(getRuleKey(), Severity.CRITICAL, ImmutableMap.of(getMinPropertyKey(), "65")));
-    measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), getCoverageMetricKey(), Measure.newMeasureBuilder().create(20.0));
+    measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), getCoverageMetricKey(), Measure.newMeasureBuilder().create(20.0, 1));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), getUncoveredMetricKey(), Measure.newMeasureBuilder().create(40));
     measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), getToCoverMetricKey(), Measure.newMeasureBuilder().create(50));
 
@@ -123,7 +123,7 @@ public abstract class CoverageRuleTest {
   @Test
   public void ignored_if_rule_is_deactivated() {
     // coverage is too low, but rule is not activated
-    measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), getCoverageMetricKey(), Measure.newMeasureBuilder().create(20.0));
+    measureRepository.addRawMeasure(FILE.getReportAttributes().getRef(), getCoverageMetricKey(), Measure.newMeasureBuilder().create(20.0, 1));
 
     DefaultIssue issue = underTest.processFile(FILE, "java");
 
index ff5b90b606df332ad7d28f71aa09fa41484d37a5..08cc3c6b9cf5f6581da74d9df95c948a9cfc0a15 100644 (file)
@@ -203,7 +203,7 @@ public class BatchMeasureToMeasureTest {
 
     assertThat(measure.isPresent()).isTrue();
     assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.DOUBLE);
-    assertThat(measure.get().getDoubleValue()).isEqualTo(10.6d);
+    assertThat(measure.get().getDoubleValue()).isEqualTo(10.6395d);
     assertThat(measure.get().getData()).isEqualTo(SOME_DATA);
   }
 
index 90491dd2cc046810dcc39bfe1f138af1a965e3a1..9e3e2117e576639ff1529293911837dc9b7aa3ec 100644 (file)
@@ -145,9 +145,9 @@ public class BestValueOptimizationTest {
   public void verify_value_comparison_for_double_metric() {
     Predicate<Measure> underTest = BestValueOptimization.from(createMetric(Metric.MetricType.FLOAT, 36.5d), FILE_COMPONENT);
 
-    assertThat(underTest.apply(newMeasureBuilder().create(36.5d))).isTrue();
-    assertThat(underTest.apply(newMeasureBuilder().setVariations(SOME_EMPTY_VARIATIONS).create(36.5d))).isTrue();
-    assertThat(underTest.apply(newMeasureBuilder().create(36.6d))).isFalse();
+    assertThat(underTest.apply(newMeasureBuilder().create(36.5d, 1))).isTrue();
+    assertThat(underTest.apply(newMeasureBuilder().setVariations(SOME_EMPTY_VARIATIONS).create(36.5d, 1))).isTrue();
+    assertThat(underTest.apply(newMeasureBuilder().create(36.6d, 1))).isFalse();
   }
 
   @Test
@@ -165,6 +165,6 @@ public class BestValueOptimizationTest {
   }
 
   private static MetricImpl createMetric(Metric.MetricType metricType, double bestValue) {
-    return new MetricImpl(metricType.hashCode() + (int) bestValue, "key" + metricType + bestValue, "name" + metricType + bestValue, metricType, bestValue, true);
+    return new MetricImpl(metricType.hashCode() + (int) bestValue, "key" + metricType + bestValue, "name" + metricType + bestValue, metricType, null, bestValue, true);
   }
 }
index f30cc3a0e6e86e22b093cb4c96e9a67b342532b7..5354fc51f669c45805ed137fe936bcdeb250c440 100644 (file)
@@ -156,7 +156,7 @@ public class MapBasedRawMeasureRepositoryTest {
   private static final List<Measure> MEASURES = ImmutableList.of(
     Measure.newMeasureBuilder().create(1),
     Measure.newMeasureBuilder().create(1l),
-    Measure.newMeasureBuilder().create(1d),
+    Measure.newMeasureBuilder().create(1d, 1),
     Measure.newMeasureBuilder().create(true),
     Measure.newMeasureBuilder().create(false),
     Measure.newMeasureBuilder().create("sds"),
index f5acb7726debcdb5a8ccf104935183c2cccccbe3..dbd60e52b24d771f6c847325ec947436ba711351 100644 (file)
@@ -23,6 +23,7 @@ import com.google.common.base.Optional;
 import com.tngtech.java.junit.dataprovider.DataProvider;
 import com.tngtech.java.junit.dataprovider.DataProviderRunner;
 import com.tngtech.java.junit.dataprovider.UseDataProvider;
+import org.assertj.core.data.Offset;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
@@ -239,7 +240,7 @@ public class MeasureDtoToMeasureTest {
 
     assertThat(measure.isPresent()).isTrue();
     assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.DOUBLE);
-    assertThat(measure.get().getDoubleValue()).isEqualTo(10.6d);
+    assertThat(measure.get().getDoubleValue()).isEqualTo(10.6395d);
     assertThat(measure.get().getData()).isEqualTo(SOME_DATA);
     assertThat(measure.get().getQualityGateStatus().getStatus()).isEqualTo(Level.OK);
     assertThat(measure.get().getQualityGateStatus().getText()).isEqualTo(SOME_ALERT_TEXT);
@@ -340,4 +341,15 @@ public class MeasureDtoToMeasureTest {
     assertThat(measure.get().getVariations().hasVariation4()).isFalse();
     assertThat(measure.get().getVariations().getVariation5()).isEqualTo(5);
   }
+
+  @Test
+  public void toMeasure_should_not_loose_decimals_of_float_values() {
+    MetricImpl metric = new MetricImpl(42, "double", "name", Metric.MetricType.FLOAT, 5, null, false);
+    MeasureDto measureDto = new MeasureDto()
+      .setValue(0.12345);
+
+    Optional<Measure> measure = underTest.toMeasure(measureDto, metric);
+
+    assertThat(measure.get().getDoubleValue()).isEqualTo(0.12345, Offset.offset(0.000001));
+  }
 }
index d75b8a93496d62bb253f5b74eb8d352c86fcbf86..456e79ef79d725707c67a931df583d79522d1824 100644 (file)
@@ -233,7 +233,7 @@ public class MeasureRepositoryImplTest {
   private static final List<Measure> MEASURES = ImmutableList.of(
     Measure.newMeasureBuilder().create(1),
     Measure.newMeasureBuilder().create(1l),
-    Measure.newMeasureBuilder().create(1d),
+    Measure.newMeasureBuilder().create(1d, 1),
     Measure.newMeasureBuilder().create(true),
     Measure.newMeasureBuilder().create(false),
     Measure.newMeasureBuilder().create("sds"),
index f95d131e427d14df5787382c37b460ae62da6dc8..4c93db5619dd64bad5790966d23f2a661ac36f33 100644 (file)
@@ -44,7 +44,7 @@ public class MeasureTest {
 
   private static final Measure INT_MEASURE = newMeasureBuilder().create((int) 1);
   private static final Measure LONG_MEASURE = newMeasureBuilder().create(1l);
-  private static final Measure DOUBLE_MEASURE = newMeasureBuilder().create(1d);
+  private static final Measure DOUBLE_MEASURE = newMeasureBuilder().create(1d, 1);
   private static final Measure STRING_MEASURE = newMeasureBuilder().create("some_sT ring");
   private static final Measure TRUE_MEASURE = newMeasureBuilder().create(true);
   private static final Measure FALSE_MEASURE = newMeasureBuilder().create(false);
@@ -296,7 +296,7 @@ public class MeasureTest {
     assertThat(newMeasureBuilder().setQualityGateStatus(someStatus).create(false, null).getQualityGateStatus()).isEqualTo(someStatus);
     assertThat(newMeasureBuilder().setQualityGateStatus(someStatus).create((int) 1, null).getQualityGateStatus()).isEqualTo(someStatus);
     assertThat(newMeasureBuilder().setQualityGateStatus(someStatus).create((long) 1, null).getQualityGateStatus()).isEqualTo(someStatus);
-    assertThat(newMeasureBuilder().setQualityGateStatus(someStatus).create((double) 1, null).getQualityGateStatus()).isEqualTo(someStatus);
+    assertThat(newMeasureBuilder().setQualityGateStatus(someStatus).create((double) 1, 1, null).getQualityGateStatus()).isEqualTo(someStatus);
     assertThat(newMeasureBuilder().setQualityGateStatus(someStatus).create("str").getQualityGateStatus()).isEqualTo(someStatus);
     assertThat(newMeasureBuilder().setQualityGateStatus(someStatus).create(Measure.Level.OK).getQualityGateStatus()).isEqualTo(someStatus);
   }
@@ -361,7 +361,7 @@ public class MeasureTest {
     assertThat(newMeasureBuilder().create(false, someData).getData()).isEqualTo(someData);
     assertThat(newMeasureBuilder().create((int) 1, someData).getData()).isEqualTo(someData);
     assertThat(newMeasureBuilder().create((long) 1, someData).getData()).isEqualTo(someData);
-    assertThat(newMeasureBuilder().create((double) 1, someData).getData()).isEqualTo(someData);
+    assertThat(newMeasureBuilder().create((double) 1, 1, someData).getData()).isEqualTo(someData);
   }
 
   @Test
@@ -371,26 +371,26 @@ public class MeasureTest {
 
   @Test
   public void double_values_are_scaled_to_1_digit_and_round() {
-    assertThat(newMeasureBuilder().create(30.27777d).getDoubleValue()).isEqualTo(30.3d);
-    assertThat(newMeasureBuilder().create(30d).getDoubleValue()).isEqualTo(30d);
-    assertThat(newMeasureBuilder().create(30.01d).getDoubleValue()).isEqualTo(30d);
-    assertThat(newMeasureBuilder().create(30.1d).getDoubleValue()).isEqualTo(30.1d);
+    assertThat(newMeasureBuilder().create(30.27777d, 1).getDoubleValue()).isEqualTo(30.3d);
+    assertThat(newMeasureBuilder().create(30d, 1).getDoubleValue()).isEqualTo(30d);
+    assertThat(newMeasureBuilder().create(30.01d, 1).getDoubleValue()).isEqualTo(30d);
+    assertThat(newMeasureBuilder().create(30.1d, 1).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");
+    expectedException.expectMessage("NaN is not allowed as a Measure value");
 
-    newMeasureBuilder().create(Double.NaN);
+    newMeasureBuilder().create(Double.NaN, 1);
   }
 
   @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");
+    expectedException.expectMessage("NaN is not allowed as a Measure value");
 
-    newMeasureBuilder().create(Double.NaN, "some data");
+    newMeasureBuilder().create(Double.NaN, 1, "some data");
   }
 
 }
index 409673b7a056da82ebe6e2662985b103dac7eef8..7245fce8da615e5d3ce89103889f678ed3e49fea 100644 (file)
@@ -81,7 +81,7 @@ public class MeasureToMeasureDtoTest {
         { Measure.newMeasureBuilder().create(true, SOME_DATA), SOME_BOOLEAN_METRIC},
         { Measure.newMeasureBuilder().create(1, SOME_DATA), SOME_INT_METRIC},
         { Measure.newMeasureBuilder().create((long) 1, SOME_DATA), SOME_LONG_METRIC},
-        { Measure.newMeasureBuilder().create((double) 2, SOME_DATA), SOME_DOUBLE_METRIC},
+        { Measure.newMeasureBuilder().create((double) 2, 1, SOME_DATA), SOME_DOUBLE_METRIC},
         { Measure.newMeasureBuilder().create(SOME_STRING), SOME_STRING_METRIC},
         { Measure.newMeasureBuilder().create(Measure.Level.OK), SOME_LEVEL_METRIC}
     };
@@ -210,7 +210,7 @@ public class MeasureToMeasureDtoTest {
 
   @Test
   public void toMeasureDto_maps_value_and_data_from_data_field_for_DOUBLE_metric() {
-    MeasureDto trueMeasureDto = underTest.toMeasureDto(Measure.newMeasureBuilder().create((double) 789, SOME_DATA), SOME_DOUBLE_METRIC, SOME_COMPONENT);
+    MeasureDto trueMeasureDto = underTest.toMeasureDto(Measure.newMeasureBuilder().create((double) 789, 1, SOME_DATA), SOME_DOUBLE_METRIC, SOME_COMPONENT);
 
     assertThat(trueMeasureDto.getValue()).isEqualTo(789);
     assertThat(trueMeasureDto.getData()).isEqualTo(SOME_DATA);
index c6b11e3fdbd10a2517a1952922b8540b5d409791..2f9714ce981645d89c6af2cf62e87a2af50a4d2d 100644 (file)
@@ -43,13 +43,13 @@ public class MeasureImplTest {
     thrown.expect(IllegalStateException.class);
     thrown.expectMessage("Value can not be converted to int because current value type is a DOUBLE");
 
-    MeasureImpl measure = new MeasureImpl(Measure.newMeasureBuilder().create(1d));
+    MeasureImpl measure = new MeasureImpl(Measure.newMeasureBuilder().create(1d, 1));
     measure.getIntValue();
   }
 
   @Test
   public void get_double_value() throws Exception {
-    MeasureImpl measure = new MeasureImpl(Measure.newMeasureBuilder().create(1d));
+    MeasureImpl measure = new MeasureImpl(Measure.newMeasureBuilder().create(1d, 1));
     assertThat(measure.getDoubleValue()).isEqualTo(1d);
   }
 
@@ -103,7 +103,7 @@ public class MeasureImplTest {
     thrown.expect(IllegalStateException.class);
     thrown.expectMessage("Value can not be converted to boolean because current value type is a DOUBLE");
 
-    MeasureImpl measure = new MeasureImpl(Measure.newMeasureBuilder().create(1d));
+    MeasureImpl measure = new MeasureImpl(Measure.newMeasureBuilder().create(1d, 1));
     measure.getBooleanValue();
   }
 
index 3b6cac89f3601878f373cd480cb5b75ce9214b0e..839f6692f3a3ef137bea89fd3a0d870a74dacfb5 100644 (file)
@@ -53,7 +53,7 @@ public class MetricImplTest {
     expectedException.expect(IllegalArgumentException.class);
     expectedException.expectMessage("A BestValue must be specified if Metric is bestValueOptimized");
 
-    new MetricImpl(SOME_ID, SOME_KEY, SOME_NAME, Metric.MetricType.INT, null, true);
+    new MetricImpl(SOME_ID, SOME_KEY, SOME_NAME, Metric.MetricType.INT, 1, null, true);
   }
 
   @Test
@@ -72,8 +72,8 @@ public class MetricImplTest {
 
     assertThat(new MetricImpl(SOME_ID, SOME_KEY, SOME_NAME, Metric.MetricType.FLOAT)).isEqualTo(expected);
     assertThat(new MetricImpl(SOME_ID, SOME_KEY, SOME_NAME, Metric.MetricType.STRING)).isEqualTo(expected);
-    assertThat(new MetricImpl(SOME_ID, SOME_KEY, SOME_NAME, Metric.MetricType.STRING, 0d, true)).isEqualTo(expected);
-    assertThat(new MetricImpl(SOME_ID, SOME_KEY, SOME_NAME, Metric.MetricType.STRING, null, false)).isEqualTo(expected);
+    assertThat(new MetricImpl(SOME_ID, SOME_KEY, SOME_NAME, Metric.MetricType.STRING, null, 0d, true)).isEqualTo(expected);
+    assertThat(new MetricImpl(SOME_ID, SOME_KEY, SOME_NAME, Metric.MetricType.STRING, null, null, false)).isEqualTo(expected);
     assertThat(new MetricImpl(SOME_ID, "some other key", SOME_NAME, Metric.MetricType.FLOAT)).isNotEqualTo(expected);
   }
 
@@ -87,7 +87,7 @@ public class MetricImplTest {
 
   @Test
   public void all_fields_are_displayed_in_toString() {
-    assertThat(new MetricImpl(SOME_ID, SOME_KEY, SOME_NAME, Metric.MetricType.FLOAT, 951d, true).toString())
+    assertThat(new MetricImpl(SOME_ID, SOME_KEY, SOME_NAME, Metric.MetricType.FLOAT, 1, 951d, true).toString())
       .isEqualTo("MetricImpl{id=42, key=key, name=name, type=FLOAT, bestValue=951.0, bestValueOptimized=true}");
 
   }
index 8d77c4c7eb5e8de63cca5e9eb8a3af7d8df6b9d6..2b51faf2c010f9f65f58130ab05fd30910280bb4 100644 (file)
@@ -62,6 +62,7 @@ public class MetricRepositoryRule extends ExternalResource implements MetricRepo
     return new MetricImpl(
       id, coreMetric.getKey(), coreMetric.getName(),
       convert(coreMetric.getType()),
+      coreMetric.getDecimalScale(),
       coreMetric.getBestValue(), coreMetric.isOptimizedBestValue());
   }
 
index 246aa59975eb9da60d71bedf411e62e3d01b0868..03fc4c87bd30b64999e0008a5955da67b2c0f0dd 100644 (file)
@@ -54,7 +54,7 @@ public class ConditionEvaluatorTest {
   public void testInputNumbers() {
     try {
       Metric metric = createMetric(MetricType.FLOAT);
-      Measure measure = newMeasureBuilder().create(10.2d, null);
+      Measure measure = newMeasureBuilder().create(10.2d, 1, null);
       underTest.evaluate(createErrorCondition(metric, LESS_THAN, "20"), measure);
     } catch (NumberFormatException ex) {
       fail();
@@ -70,7 +70,7 @@ public class ConditionEvaluatorTest {
 
     try {
       Metric metric = createMetric(MetricType.PERCENT);
-      Measure measure = newMeasureBuilder().create(10.2d, null);
+      Measure measure = newMeasureBuilder().create(10.2d, 1, null);
       underTest.evaluate(createErrorCondition(metric, LESS_THAN, "20.1"), measure);
     } catch (NumberFormatException ex) {
       fail();
@@ -88,7 +88,7 @@ public class ConditionEvaluatorTest {
   @Test
   public void testEquals_for_double() {
     Metric metric = createMetric(MetricType.FLOAT);
-    Measure measure = newMeasureBuilder().create(10.2d, null);
+    Measure measure = newMeasureBuilder().create(10.2d, 1, null);
 
     assertThat(underTest.evaluate(createErrorCondition(metric, EQUALS, "10.2"), measure)).hasLevel(ERROR).hasValue(10.2d);
     assertThat(underTest.evaluate(createErrorCondition(metric, EQUALS, "10.1"), measure)).hasLevel(OK).hasValue(10.2d);
@@ -106,7 +106,7 @@ public class ConditionEvaluatorTest {
   @Test
   public void testNotEquals_for_double() {
     Metric metric = createMetric(MetricType.FLOAT);
-    Measure measure = newMeasureBuilder().create(10.2d, null);
+    Measure measure = newMeasureBuilder().create(10.2d, 1, null);
 
     assertThat(underTest.evaluate(createErrorCondition(metric, NOT_EQUALS, "10.2"), measure)).hasLevel(OK).hasValue(10.2d);
     assertThat(underTest.evaluate(createErrorCondition(metric, NOT_EQUALS, "10.1"), measure)).hasLevel(ERROR).hasValue(10.2d);
@@ -124,7 +124,7 @@ public class ConditionEvaluatorTest {
   @Test
   public void testGreater() {
     Metric metric = createMetric(MetricType.FLOAT);
-    Measure measure = newMeasureBuilder().create(10.2d, null);
+    Measure measure = newMeasureBuilder().create(10.2d, 1, null);
 
     assertThat(underTest.evaluate(createErrorCondition(metric, GREATER_THAN, "10.1"), measure)).hasLevel(ERROR).hasValue(10.2d);
     assertThat(underTest.evaluate(createErrorCondition(metric, GREATER_THAN, "10.2"), measure)).hasLevel(OK).hasValue(10.2d);
@@ -134,7 +134,7 @@ public class ConditionEvaluatorTest {
   @Test
   public void testSmaller() {
     Metric metric = createMetric(MetricType.FLOAT);
-    Measure measure = newMeasureBuilder().create(10.2d, null);
+    Measure measure = newMeasureBuilder().create(10.2d, 1, null);
 
     assertThat(underTest.evaluate(createErrorCondition(metric, LESS_THAN, "10.1"), measure)).hasLevel(OK).hasValue(10.2d);
     assertThat(underTest.evaluate(createErrorCondition(metric, LESS_THAN, "10.2"), measure)).hasLevel(OK).hasValue(10.2d);
@@ -144,7 +144,7 @@ public class ConditionEvaluatorTest {
   @Test
   public void testEquals_Percent() {
     Metric metric = createMetric(MetricType.PERCENT);
-    Measure measure = newMeasureBuilder().create(10.2d, null);
+    Measure measure = newMeasureBuilder().create(10.2d, 1, null);
 
     assertThat(underTest.evaluate(createErrorCondition(metric, EQUALS, "10.2"), measure)).hasLevel(ERROR).hasValue(10.2d);
   }
@@ -152,7 +152,7 @@ public class ConditionEvaluatorTest {
   @Test
   public void testEquals_Float() {
     Metric metric = createMetric(MetricType.PERCENT);
-    Measure measure = newMeasureBuilder().create(10.2d, null);
+    Measure measure = newMeasureBuilder().create(10.2d, 1, null);
 
     assertThat(underTest.evaluate(createErrorCondition(metric, EQUALS, "10.2"), measure)).hasLevel(ERROR).hasValue(10.2d);
   }
@@ -235,7 +235,7 @@ public class ConditionEvaluatorTest {
   @Test
   public void testErrorAndWarningLevel() {
     Metric metric = createMetric(MetricType.FLOAT);
-    Measure measure = newMeasureBuilder().create(10.2d, null);
+    Measure measure = newMeasureBuilder().create(10.2d, 1, null);
 
     assertThat(underTest.evaluate(createErrorCondition(metric, EQUALS, "10.2"), measure)).hasLevel(ERROR);
     assertThat(underTest.evaluate(createErrorCondition(metric, EQUALS, "10.1"), measure)).hasLevel(OK);
index b06cbc2f62117fa18387273190565941aff99b28..777658b202ab2f28bf3c276c32686be3bf719dd4 100644 (file)
@@ -95,7 +95,7 @@ public class ReportSqaleMeasuresVisitorTest {
     assertThat(toEntries(measureRepository.getRawMeasures(root)))
       .containsOnly(
         entryOf(DEVELOPMENT_COST_KEY, newMeasureBuilder().create("0")),
-        entryOf(SQALE_DEBT_RATIO_KEY, newMeasureBuilder().create(0d)),
+        entryOf(SQALE_DEBT_RATIO_KEY, newMeasureBuilder().create(0d, 1)),
         entryOf(SQALE_RATING_KEY, createSqaleRatingMeasure(A)));
   }
 
@@ -238,7 +238,7 @@ public class ReportSqaleMeasuresVisitorTest {
   private void verifyComponentMeasures(int componentRef, long expectedDevCost, double expectedDebtRatio, SqaleRatingGrid.SqaleRating expectedRating) {
     assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef))).containsOnly(
       entryOf(DEVELOPMENT_COST_KEY, newMeasureBuilder().create(Long.toString(expectedDevCost))),
-      entryOf(SQALE_DEBT_RATIO_KEY, newMeasureBuilder().create(expectedDebtRatio * 100.0)),
+      entryOf(SQALE_DEBT_RATIO_KEY, newMeasureBuilder().create(expectedDebtRatio * 100.0, 1)),
       entryOf(SQALE_RATING_KEY, createSqaleRatingMeasure(expectedRating)));
   }
 
index cdb5ed97f590361b4c3b958f955b183af9b3b365..ed74622a39c136d56d4d12bf394a07c2ecc2668c 100644 (file)
@@ -111,7 +111,7 @@ public class ViewsSqaleMeasuresVisitorTest {
     assertThat(toEntries(measureRepository.getRawMeasures(root)))
       .containsOnly(
         entryOf(DEVELOPMENT_COST_KEY, newMeasureBuilder().create("0")),
-        entryOf(SQALE_DEBT_RATIO_KEY, newMeasureBuilder().create(0d)),
+        entryOf(SQALE_DEBT_RATIO_KEY, newMeasureBuilder().create(0d, 1)),
         entryOf(SQALE_RATING_KEY, createSqaleRatingMeasure(A)));
   }
 
@@ -152,7 +152,7 @@ public class ViewsSqaleMeasuresVisitorTest {
   private void assertNewRawMeasures(int componentRef, long debt, long devCost, SqaleRatingGrid.SqaleRating sqaleRating) {
     assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef))).containsOnly(
       entryOf(DEVELOPMENT_COST_KEY, newMeasureBuilder().create(String.valueOf(devCost))),
-      entryOf(SQALE_DEBT_RATIO_KEY, newMeasureBuilder().create(debt / (double) devCost * 100.0)),
+      entryOf(SQALE_DEBT_RATIO_KEY, newMeasureBuilder().create(debt / (double) devCost * 100.0, 1)),
       entryOf(SQALE_RATING_KEY, createSqaleRatingMeasure(sqaleRating)));
   }
 
index e37f49682d5a351b315fa6bc2673ca128d79e373..741d477ca2069ed03631f0aa48960b423858ae5c 100644 (file)
@@ -220,7 +220,7 @@ public class CustomMeasuresCopyStepTest {
   }
 
   private void assertRawMeasureValue(int componentRef, String metricKey, double value) {
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef))).containsOnly(entryOf(metricKey, newMeasureBuilder().create(value)));
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef))).containsOnly(entryOf(metricKey, newMeasureBuilder().create(value, 1)));
   }
 
   private void assertRawMeasureValue(int componentRef, String metricKey, String value) {
index cd2a159dce9756161e0e551df529ef207bec66a5..55c2735313948628717fbe9f7126479023959a58 100644 (file)
@@ -190,7 +190,7 @@ public class PersistMeasuresStepTest extends BaseStepTest {
     measureRepository.addRawMeasure(ROOT_REF, STRING_METRIC_KEY, newMeasureBuilder().create("measure-data"));
     measureRepository.addRawMeasure(INTERMEDIATE_1_REF, INT_METRIC_KEY, newMeasureBuilder().create(12));
     measureRepository.addRawMeasure(INTERMEDIATE_2_REF, LONG_METRIC_KEY, newMeasureBuilder().create(9635L));
-    measureRepository.addRawMeasure(LEAF_REF, DOUBLE_METRIC_KEY, newMeasureBuilder().create(123.123d));
+    measureRepository.addRawMeasure(LEAF_REF, DOUBLE_METRIC_KEY, newMeasureBuilder().create(123.123d, 1));
 
     underTest.execute();
 
@@ -271,7 +271,7 @@ public class PersistMeasuresStepTest extends BaseStepTest {
             .setVariation(createPeriod(4), 4.4d)
             .setVariation(createPeriod(5), 5.5d)
             .build())
-        .create(10d));
+        .create(10d, 1));
 
     underTest.execute();
 
index 7f6b0921a69a29683b6d722896f0aef35bffd84a..878e4f521ff8418241197f95ac29f434d0cf29f4 100644 (file)
@@ -204,14 +204,14 @@ public class ReportComplexityMeasuresStepTest {
 
     underTest.execute();
 
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_1_REF))).contains(entryOf(metricKey, newMeasureBuilder().create(2.5)));
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_2_REF))).contains(entryOf(metricKey, newMeasureBuilder().create(1d)));
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_1_REF))).contains(entryOf(metricKey, newMeasureBuilder().create(2.5, 1)));
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_2_REF))).contains(entryOf(metricKey, newMeasureBuilder().create(1d, 1)));
 
     double expectedNonFileValue = 2d;
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(DIRECTORY_REF))).contains(entryOf(metricKey, newMeasureBuilder().create(expectedNonFileValue)));
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(SUB_MODULE_REF))).contains(entryOf(metricKey, newMeasureBuilder().create(expectedNonFileValue)));
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(MODULE_REF))).contains(entryOf(metricKey, newMeasureBuilder().create(expectedNonFileValue)));
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(ROOT_REF))).contains(entryOf(metricKey, newMeasureBuilder().create(expectedNonFileValue)));
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(DIRECTORY_REF))).contains(entryOf(metricKey, newMeasureBuilder().create(expectedNonFileValue, 1)));
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(SUB_MODULE_REF))).contains(entryOf(metricKey, newMeasureBuilder().create(expectedNonFileValue, 1)));
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(MODULE_REF))).contains(entryOf(metricKey, newMeasureBuilder().create(expectedNonFileValue, 1)));
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(ROOT_REF))).contains(entryOf(metricKey, newMeasureBuilder().create(expectedNonFileValue, 1)));
   }
 
 }
index 07f848adc1fd8573c3cb2f9c8a3f075d97685869..784a61035013bd359e331defdf39dbf7510741e1 100644 (file)
@@ -211,7 +211,7 @@ public class ReportComputeMeasureVariationsStepTest {
 
     addRawMeasure(PROJECT, ISSUES_METRIC, newMeasureBuilder().create(80, null));
     addRawMeasure(PROJECT, DEBT_METRIC, newMeasureBuilder().create(5L, null));
-    addRawMeasure(PROJECT, FILE_COMPLEXITY_METRIC, newMeasureBuilder().create(3d, null));
+    addRawMeasure(PROJECT, FILE_COMPLEXITY_METRIC, newMeasureBuilder().create(3d, 1, null));
     addRawMeasure(PROJECT, BUILD_BREAKER_METRIC, newMeasureBuilder().create(false, null));
 
     underTest.execute();
index 220773de571d455bca1987830e62e1c6013670c4..736c808e9fc8d2ddfe3e2603467041d286e5f5e7 100644 (file)
@@ -204,19 +204,19 @@ public class ReportCoverageMeasuresStepTest {
     underTest.execute();
 
     assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_1_REF))).contains(
-      entryOf(codeCoverageKey, newMeasureBuilder().create(98.8d)),
-      entryOf(lineCoverageKey, newMeasureBuilder().create(99d)),
-      entryOf(branchCoverageKey, newMeasureBuilder().create(97d)));
+      entryOf(codeCoverageKey, newMeasureBuilder().create(98.8d, 1)),
+      entryOf(lineCoverageKey, newMeasureBuilder().create(99d, 1)),
+      entryOf(branchCoverageKey, newMeasureBuilder().create(97d, 1)));
     assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_2_REF))).contains(
-      entryOf(codeCoverageKey, newMeasureBuilder().create(91d)),
-      entryOf(lineCoverageKey, newMeasureBuilder().create(90d)),
-      entryOf(branchCoverageKey, newMeasureBuilder().create(96d)));
+      entryOf(codeCoverageKey, newMeasureBuilder().create(91d, 1)),
+      entryOf(lineCoverageKey, newMeasureBuilder().create(90d, 1)),
+      entryOf(branchCoverageKey, newMeasureBuilder().create(96d, 1)));
     assertThat(toEntries(measureRepository.getAddedRawMeasures(UNIT_TEST_FILE_REF))).isEmpty();
 
     MeasureRepoEntry[] nonFileRepoEntries = {
-      entryOf(codeCoverageKey, newMeasureBuilder().create(95.5d)),
-      entryOf(lineCoverageKey, newMeasureBuilder().create(95.4d)),
-      entryOf(branchCoverageKey, newMeasureBuilder().create(96.4d))
+      entryOf(codeCoverageKey, newMeasureBuilder().create(95.5d, 1)),
+      entryOf(lineCoverageKey, newMeasureBuilder().create(95.4d, 1)),
+      entryOf(branchCoverageKey, newMeasureBuilder().create(96.4d, 1))
     };
 
     assertThat(toEntries(measureRepository.getAddedRawMeasures(DIRECTORY_REF))).contains(nonFileRepoEntries);
index 9da9e10ec1e9f34d84ba517304750552ee0bcc13..ba9c3ab4d7a67084807d6492fe2a24e1ad32d8fb 100644 (file)
@@ -130,12 +130,12 @@ public class ReportUnitTestMeasuresStepTest {
 
     underTest.execute();
 
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_1_REF))).contains(entryOf(TEST_SUCCESS_DENSITY_KEY, newMeasureBuilder().create(40d)));
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_2_REF))).contains(entryOf(TEST_SUCCESS_DENSITY_KEY, newMeasureBuilder().create(70d)));
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(DIRECTORY_REF))).contains(entryOf(TEST_SUCCESS_DENSITY_KEY, newMeasureBuilder().create(60d)));
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(SUB_MODULE_REF))).contains(entryOf(TEST_SUCCESS_DENSITY_KEY, newMeasureBuilder().create(60d)));
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(MODULE_REF))).contains(entryOf(TEST_SUCCESS_DENSITY_KEY, newMeasureBuilder().create(60d)));
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(ROOT_REF))).contains(entryOf(TEST_SUCCESS_DENSITY_KEY, newMeasureBuilder().create(60d)));
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_1_REF))).contains(entryOf(TEST_SUCCESS_DENSITY_KEY, newMeasureBuilder().create(40d, 1)));
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(FILE_2_REF))).contains(entryOf(TEST_SUCCESS_DENSITY_KEY, newMeasureBuilder().create(70d, 1)));
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(DIRECTORY_REF))).contains(entryOf(TEST_SUCCESS_DENSITY_KEY, newMeasureBuilder().create(60d, 1)));
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(SUB_MODULE_REF))).contains(entryOf(TEST_SUCCESS_DENSITY_KEY, newMeasureBuilder().create(60d, 1)));
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(MODULE_REF))).contains(entryOf(TEST_SUCCESS_DENSITY_KEY, newMeasureBuilder().create(60d, 1)));
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(ROOT_REF))).contains(entryOf(TEST_SUCCESS_DENSITY_KEY, newMeasureBuilder().create(60d, 1)));
   }
 
   @Test
index dcad4dca23bf8793db664c09ad3475c15c4a9b1b..726f12a1c77b77eb7f7e6d8003b8b2c0ffa7ad20 100644 (file)
@@ -232,7 +232,7 @@ public class ViewsComplexityMeasuresStepTest {
   }
 
   private void assertAddedRawMeasures(int componentRef, String metricKey, double expected) {
-    assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef))).contains(entryOf(metricKey, newMeasureBuilder().create(expected)));
+    assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef))).contains(entryOf(metricKey, newMeasureBuilder().create(expected, 1)));
   }
 
   private void addRawMeasureValue(int componentRef, String metricKey, int value) {
index f498a21c0928e774ede9317f461023cba7857129..e005dceee430ca25311502ce7ae932c6185f8943 100644 (file)
@@ -214,7 +214,7 @@ public class ViewsComputeMeasureVariationsStepTest {
 
     addRawMeasure(VIEW, ISSUES_METRIC, Measure.newMeasureBuilder().create(80, null));
     addRawMeasure(VIEW, DEBT_METRIC, Measure.newMeasureBuilder().create(5L, null));
-    addRawMeasure(VIEW, FILE_COMPLEXITY_METRIC, Measure.newMeasureBuilder().create(3d, null));
+    addRawMeasure(VIEW, FILE_COMPLEXITY_METRIC, Measure.newMeasureBuilder().create(3d, 1));
     addRawMeasure(VIEW, BUILD_BREAKER_METRIC, Measure.newMeasureBuilder().create(false, null));
 
     underTest.execute();
index 9d454dec179e4a307346821fbf6f22bb88ff5aa6..27f6b72affa52d397ffc2fb3c9dfc9754e8595aa 100644 (file)
@@ -215,17 +215,17 @@ public class ViewsCoverageMeasuresStepTest {
     assertThat(toEntries(measureRepository.getAddedRawMeasures(PROJECTVIEW_3_REF))).isEmpty();
 
     MeasureRepoEntry[] subViewRepoEntries = {
-      entryOf(codeCoverageKey, newMeasureBuilder().create(95.5d)),
-      entryOf(lineCoverageKey, newMeasureBuilder().create(95.4d)),
-      entryOf(branchCoverageKey, newMeasureBuilder().create(96.4d))
+      entryOf(codeCoverageKey, newMeasureBuilder().create(95.5d, 1)),
+      entryOf(lineCoverageKey, newMeasureBuilder().create(95.4d, 1)),
+      entryOf(branchCoverageKey, newMeasureBuilder().create(96.4d, 1))
     };
 
     assertThat(toEntries(measureRepository.getAddedRawMeasures(SUB_SUBVIEW_REF))).contains(subViewRepoEntries);
     assertThat(toEntries(measureRepository.getAddedRawMeasures(SUBVIEW_REF))).contains(subViewRepoEntries);
     assertThat(toEntries(measureRepository.getAddedRawMeasures(ROOT_REF))).contains(
-      entryOf(codeCoverageKey, newMeasureBuilder().create(92d)),
-      entryOf(lineCoverageKey, newMeasureBuilder().create(91.2d)),
-      entryOf(branchCoverageKey, newMeasureBuilder().create(96.3d)));
+      entryOf(codeCoverageKey, newMeasureBuilder().create(92d, 1)),
+      entryOf(lineCoverageKey, newMeasureBuilder().create(91.2d, 1)),
+      entryOf(branchCoverageKey, newMeasureBuilder().create(96.3d, 1)));
   }
 
 }
index 0035d6a9ecebcfa6a3cdf737f0d5cb740b113cd9..522d835dc29547377fce7ee459ed880809fd337f 100644 (file)
@@ -276,7 +276,7 @@ public class ViewsUnitTestMeasuresStepTest {
 
   private void assertAddedRawMeasureValue(int componentRef, String metricKey, double value) {
     assertThat(entryOf(metricKey, measureRepository.getAddedRawMeasure(componentRef, metricKey).get()))
-      .isEqualTo(entryOf(metricKey, newMeasureBuilder().create(value)));
+      .isEqualTo(entryOf(metricKey, newMeasureBuilder().create(value, 1)));
   }
 
   private void assertAddedRawMeasureValue(int componentRef, String metricKey, long value) {
index 6f6a63bfa858969b39d0a5e8a5ea3e3c7a3f2e0a..f0d8dee6316edd84c770a8a1593a8b02b29cb964 100644 (file)
@@ -81,6 +81,7 @@ public class RegisterMetricsTest {
       .setQualitative(true)
       .setDomain("new domain")
       .setUserManaged(false)
+      .setDecimalScale(3)
       .setHidden(true)
       .create();
     Metric custom = new Metric.Builder("custom", "New custom", Metric.ValueType.FLOAT)
index dbedde99411fb8b8a5fa5861882445a0e5b39877..fef184f93190cdaffc95fdf6d37ccca275fe73f1 100644 (file)
@@ -3,6 +3,6 @@
   <!-- disabled -->
   <metrics delete_historical_data="[false]" id="1" name="m1" val_type="FLOAT" description="desc1" domain="domain1"
            short_name="One" qualitative="[true]" user_managed="[false]" enabled="[false]" worst_value="[null]"
-           optimized_best_value="[false]" best_value="[null]" direction="1" hidden="[false]"/>
+           optimized_best_value="[false]" best_value="[null]" direction="1" hidden="[false]" decimal_scale="[null]"/>
 
 </dataset>
index b48ad61cd33dfd73a7afeee0920fa16d11b644ce..4ebaa508ddb51fd76b7ece7853c8a3d5ebe5df4d 100644 (file)
@@ -4,6 +4,6 @@
            short_name="One" qualitative="[true]" user_managed="[false]"
            enabled="[true]"
            worst_value="[null]"
-           optimized_best_value="[false]" best_value="[null]" direction="1" hidden="[false]"/>
+           optimized_best_value="[false]" best_value="[null]" direction="1" hidden="[false]" decimal_scale="[null]"/>
 
 </dataset>
index 1f4be94dde4a6d630af0e900a1bb25c32d5009de..91722603b132d5a4940be365754b7ecda9117f80 100644 (file)
@@ -4,6 +4,6 @@
            short_name="New name" qualitative="[true]" user_managed="[false]"
            enabled="[true]"
            worst_value="[null]"
-           optimized_best_value="[false]" best_value="[null]" direction="-1" hidden="[true]"/>
+           optimized_best_value="[false]" best_value="[null]" direction="-1" hidden="[true]" decimal_scale="1"/>
 
 </dataset>
index ad7f1e33933fce119da0bff499fe60bdc55f1087..3935b7ab168f335d049b3f0b44b6f286dedf2483 100644 (file)
@@ -4,6 +4,6 @@
            short_name="One" qualitative="[true]" user_managed="[false]"
            enabled="[false]"
            worst_value="[null]"
-           optimized_best_value="[false]" best_value="[null]" direction="1" hidden="[false]"/>
+           optimized_best_value="[false]" best_value="[null]" direction="1" hidden="[false]" decimal_scale="[null]"/>
 
 </dataset>
index 1bb5088d8e08275dca55b5e57b76af1536f4ed75..a525424ca470f0db565ed1cecbdba9bb5c2e8584 100644 (file)
@@ -2,10 +2,10 @@
 
   <metrics delete_historical_data="[false]" id="1" name="m1" val_type="FLOAT" description="desc1" domain="domain1"
            short_name="One" qualitative="[true]" user_managed="[false]" enabled="[true]" worst_value="[null]"
-           optimized_best_value="[false]" best_value="[null]" direction="1" hidden="[false]"/>
+           optimized_best_value="[false]" best_value="[null]" direction="1" hidden="[false]" decimal_scale="1"/>
   <metrics delete_historical_data="[false]" id="2" name="custom" val_type="FLOAT" description="This is a custom metric"
            domain="[null]"
            short_name="Custom" qualitative="[false]" user_managed="[true]" enabled="[true]" worst_value="[null]"
-           optimized_best_value="[false]" best_value="[null]" direction="0" hidden="[false]"/>
+           optimized_best_value="[false]" best_value="[null]" direction="0" hidden="[false]" decimal_scale="1"/>
 
 </dataset>
index 886e1d2d8f4bcc2806251931c19c0cfd4a0f8f1e..0cb384843c229fff0e5fa9c7b49dcfb0a6515c6a 100644 (file)
@@ -4,12 +4,12 @@
   <metrics delete_historical_data="[false]" id="1" name="m1" val_type="FLOAT" description="new description"
            domain="new domain"
            short_name="New name" qualitative="[true]" user_managed="[false]" enabled="[true]" worst_value="[null]"
-           optimized_best_value="[false]" best_value="[null]" direction="-1" hidden="[true]"/>
+           optimized_best_value="[false]" best_value="[null]" direction="-1" hidden="[true]" decimal_scale="3"/>
 
   <!-- custom metric is unchanged -->
   <metrics delete_historical_data="[false]" id="2" name="custom" val_type="FLOAT" description="This is a custom metric"
            domain="[null]"
            short_name="Custom" qualitative="[false]" user_managed="[true]" enabled="[true]" worst_value="[null]"
-           optimized_best_value="[false]" best_value="[null]" direction="0" hidden="[false]"/>
+           optimized_best_value="[false]" best_value="[null]" direction="0" hidden="[false]" decimal_scale="1"/>
 
 </dataset>
index 483a9cb43c69804b1f62322fa9230d83f3ff5a90..8f52db2d6f5bc8be8c934b19a574b00cf8114612 100644 (file)
@@ -3,10 +3,10 @@
   <metrics delete_historical_data="[false]" id="1" name="m1" val_type="INT" description="old description"
            domain="old domain"
            short_name="old short name" qualitative="[false]" user_managed="[false]" enabled="[true]" worst_value="[null]"
-           optimized_best_value="[false]" best_value="[null]" direction="1" hidden="[false]"/>
+           optimized_best_value="[false]" best_value="[null]" direction="1" hidden="[false]" decimal_scale="[null]"/>
 
   <metrics delete_historical_data="[false]" id="2" name="custom" val_type="FLOAT" description="This is a custom metric"
            domain="[null]"
            short_name="Custom" qualitative="[false]" user_managed="[true]" enabled="[true]" worst_value="[null]"
-           optimized_best_value="[false]" best_value="[null]" direction="0" hidden="[false]"/>
+           optimized_best_value="[false]" best_value="[null]" direction="0" hidden="[false]" decimal_scale="1"/>
 </dataset>
index e3195f67456e02fa955f8eaf80a4f34c9d9d329e..4b42ca50deded2e9bc0d60a0c1296a7de8b14c43 100644 (file)
@@ -79,7 +79,7 @@ class ProjectMeasure < ActiveRecord::Base
       when Metric::VALUE_TYPE_INT
         number_with_precision(value(), :precision => 0)
       when Metric::VALUE_TYPE_FLOAT
-        number_with_precision(value(), :precision => 1)
+        number_with_precision(value(), :precision => (metric().decimal_scale||1))
       when Metric::VALUE_TYPE_PERCENT
         number_to_percentage(value(), {:precision => 1})
       when Metric::VALUE_TYPE_MILLISEC
@@ -108,12 +108,12 @@ class ProjectMeasure < ActiveRecord::Base
       when Metric::VALUE_TYPE_INT
         number_with_precision(val, :precision => 0)
       when Metric::VALUE_TYPE_FLOAT
-        number_with_precision(val, :precision => 1)
+        number_with_precision(val, :precision => (metric().decimal_scale||1))
       when Metric::VALUE_TYPE_PERCENT
         if (options[:variation]==true)
-          number_with_precision(val, :precision => 1)
+          number_with_precision(val, :precision => (metric().decimal_scale||1))
         else
-          number_to_percentage(val, {:precision => 1})
+          number_to_percentage(val, {:precision => (metric().decimal_scale||1)})
         end
       when Metric::VALUE_TYPE_MILLISEC
         millisecs_formatted_value(val)
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1005_add_decimal_scale_to_metrics.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1005_add_decimal_scale_to_metrics.rb
new file mode 100644 (file)
index 0000000..48d0bd5
--- /dev/null
@@ -0,0 +1,33 @@
+#
+# 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.
+#
+
+#
+# SonarQube 5.3
+# SONAR-6939
+#
+class AddDecimalScaleToMetrics < ActiveRecord::Migration
+
+  def self.up
+    add_column 'metrics', 'decimal_scale', :integer, :null => true
+  end
+
+end
+
+
index b78239bac82f5c18a670079a567015ec1fed2934..9212cc46512deb7db568295b2573b85f2af287b6 100644 (file)
@@ -35,8 +35,6 @@ import org.sonar.batch.mediumtest.BatchMediumTester;
 import org.sonar.batch.mediumtest.TaskResult;
 import org.sonar.batch.protocol.output.BatchReport.Measure;
 import org.sonar.xoo.XooPlugin;
-import org.sonar.xoo.measures.ConstantFloatMeasureSensor;
-import org.sonar.xoo.measures.XooMetrics;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.tuple;
@@ -52,7 +50,6 @@ public class MeasuresMediumTest {
   public BatchMediumTester tester = BatchMediumTester.builder()
     .registerPlugin("xoo", new XooPlugin())
     .addDefaultQProfile("xoo", "Sonar Way")
-    .registerMetric(XooMetrics.CONSTANT_FLOAT_MEASURE)
     .build();
 
   @Before
@@ -102,71 +99,6 @@ public class MeasuresMediumTest {
       Tuple.tuple(CoreMetrics.LINES_KEY, 2));
   }
 
-  @Test
-  public void floatMeasuresTruncatedTo1ByDefault() throws IOException {
-    File xooFile = new File(srcDir, "sample.xoo");
-    File xooMeasureFile = new File(srcDir, "sample.xoo.measures");
-    FileUtils.write(xooFile, "Sample xoo\ncontent");
-    FileUtils.write(xooMeasureFile, "lines:20");
-
-    TaskResult result = tester.newTask()
-      .properties(ImmutableMap.<String, String>builder()
-        .put("sonar.task", "scan")
-        .put("sonar.projectBaseDir", baseDir.getAbsolutePath())
-        .put("sonar.projectKey", "com.foo.project")
-        .put("sonar.projectName", "Foo Project")
-        .put("sonar.projectVersion", "1.0-SNAPSHOT")
-        .put("sonar.projectDescription", "Description of Foo Project")
-        .put("sonar.sources", "src")
-        .put("sonar.cpd.xoo.skip", "true")
-        .put(ConstantFloatMeasureSensor.SONAR_XOO_ENABLE_FLOAT_SENSOR, "true")
-        .build())
-      .start();
-
-    Map<String, List<Measure>> allMeasures = result.allMeasures();
-
-    assertThat(allMeasures.get("com.foo.project")).extracting("metricKey", "intValue", "doubleValue", "stringValue").containsOnly(
-      Tuple.tuple(CoreMetrics.QUALITY_PROFILES_KEY, 0, 0.0,
-        "[{\"key\":\"Sonar Way\",\"language\":\"xoo\",\"name\":\"Sonar Way\",\"rulesUpdatedAt\":\"2009-02-13T23:31:31+0000\"}]"));
-
-    assertThat(allMeasures.get("com.foo.project:src/sample.xoo")).extracting("metricKey", "intValue", "doubleValue").containsOnly(
-      Tuple.tuple(CoreMetrics.LINES_KEY, 2, 0.0),
-      Tuple.tuple(XooMetrics.CONSTANT_FLOAT_MEASURE_KEY, 0, 1.2));
-  }
-
-  @Test
-  public void floatMeasuresCustomPrecision() throws IOException {
-    File xooFile = new File(srcDir, "sample.xoo");
-    File xooMeasureFile = new File(srcDir, "sample.xoo.measures");
-    FileUtils.write(xooFile, "Sample xoo\ncontent");
-    FileUtils.write(xooMeasureFile, "lines:20");
-
-    TaskResult result = tester.newTask()
-      .properties(ImmutableMap.<String, String>builder()
-        .put("sonar.task", "scan")
-        .put("sonar.projectBaseDir", baseDir.getAbsolutePath())
-        .put("sonar.projectKey", "com.foo.project")
-        .put("sonar.projectName", "Foo Project")
-        .put("sonar.projectVersion", "1.0-SNAPSHOT")
-        .put("sonar.projectDescription", "Description of Foo Project")
-        .put("sonar.sources", "src")
-        .put("sonar.cpd.xoo.skip", "true")
-        .put(ConstantFloatMeasureSensor.SONAR_XOO_ENABLE_FLOAT_SENSOR, "true")
-        .put(ConstantFloatMeasureSensor.SONAR_XOO_FLOAT_PRECISION, "5")
-        .build())
-      .start();
-
-    Map<String, List<Measure>> allMeasures = result.allMeasures();
-
-    assertThat(allMeasures.get("com.foo.project")).extracting("metricKey", "intValue", "doubleValue", "stringValue").containsOnly(
-      Tuple.tuple(CoreMetrics.QUALITY_PROFILES_KEY, 0, 0.0,
-        "[{\"key\":\"Sonar Way\",\"language\":\"xoo\",\"name\":\"Sonar Way\",\"rulesUpdatedAt\":\"2009-02-13T23:31:31+0000\"}]"));
-
-    assertThat(allMeasures.get("com.foo.project:src/sample.xoo")).extracting("metricKey", "intValue", "doubleValue").containsOnly(
-      Tuple.tuple(CoreMetrics.LINES_KEY, 2, 0.0),
-      Tuple.tuple(XooMetrics.CONSTANT_FLOAT_MEASURE_KEY, 0, 1.23457));
-  }
-
   @Test
   public void computeLinesOnAllFiles() throws IOException {
     File xooFile = new File(srcDir, "sample.xoo");
index 9822dabaa8494e0270bb7b5dbede07d1fd92782a..c5bace1c44733393f9d79701d7497f2031b4e007 100644 (file)
@@ -55,6 +55,8 @@ public class MetricDto {
 
   private boolean enabled;
 
+  private Integer decimalScale;
+
   public Integer getId() {
     return id;
   }
@@ -196,4 +198,13 @@ public class MetricDto {
     return this;
   }
 
+  @CheckForNull
+  public Integer getDecimalScale() {
+    return decimalScale;
+  }
+
+  public MetricDto setDecimalScale(@Nullable Integer i) {
+    this.decimalScale = i;
+    return this;
+  }
 }
index a9180d4e9c86e45d72b51b713861a46ec869d283..7bc2b344ce235ab6261880747a40acb585ba5c87 100644 (file)
@@ -29,7 +29,7 @@ import org.sonar.db.MyBatis;
 
 public class DatabaseVersion {
 
-  public static final int LAST_VERSION = 1003;
+  public static final int LAST_VERSION = 1005;
 
   /**
    * The minimum supported version which can be upgraded. Lower
index adf0d7544cb067844b2cfd7cdff3ca4bd1100b44..58518e16eb782c5079d36df3b570646eb1b296b8 100644 (file)
@@ -18,7 +18,8 @@
     m.best_value as bestValue,
     m.optimized_best_value as optimizedBestValue,
     m.hidden,
-    m.delete_historical_data as deleteHistoricalData
+    m.delete_historical_data as deleteHistoricalData,
+    m.decimal_scale as decimalScale
   </sql>
 
   <select id="selectByKey" parameterType="map" resultType="org.sonar.db.metric.MetricDto">
           keyProperty="id">
     INSERT INTO metrics (
     name, description, direction, domain, short_name, qualitative, val_type, user_managed, enabled, worst_value,
-    best_value, optimized_best_value, hidden, delete_historical_data)
+    best_value, optimized_best_value, hidden, delete_historical_data, decimal_scale)
     VALUES (
     #{kee, jdbcType=VARCHAR}, #{description, jdbcType=VARCHAR}, #{direction, jdbcType=INTEGER},
     #{domain, jdbcType=VARCHAR}, #{shortName, jdbcType=VARCHAR}, #{qualitative, jdbcType=BOOLEAN},
     #{valueType, jdbcType=VARCHAR}, #{userManaged, jdbcType=BOOLEAN}, #{enabled, jdbcType=BOOLEAN},
     #{worstValue, jdbcType=DOUBLE}, #{bestValue, jdbcType=DOUBLE},
-    #{optimizedBestValue, jdbcType=BOOLEAN}, #{hidden, jdbcType=BOOLEAN}, #{deleteHistoricalData, jdbcType=BOOLEAN}
+    #{optimizedBestValue, jdbcType=BOOLEAN}, #{hidden, jdbcType=BOOLEAN}, #{deleteHistoricalData, jdbcType=BOOLEAN},
+    #{decimalScale, jdbcType=INTEGER}
     )
   </insert>
 
     description=#{description, jdbcType=VARCHAR},
     direction=#{direction, jdbcType=INTEGER},
     hidden=#{hidden, jdbcType=BOOLEAN},
-    qualitative=#{qualitative, jdbcType=BOOLEAN}
+    qualitative=#{qualitative, jdbcType=BOOLEAN},
+    decimal_scale=#{decimalScale, jdbcType=INTEGER}
     where id=#{id}
   </update>
 
index 0b770f42727fc2f55292db833764b104d463f692..1e3e3a14b43ea2131201d373360b7403c5cddc38 100644 (file)
@@ -364,6 +364,7 @@ INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1000');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1001');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1002');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1003');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1005');
 
 INSERT INTO USERS(ID, LOGIN, NAME, EMAIL, CRYPTED_PASSWORD, SALT, CREATED_AT, UPDATED_AT, REMEMBER_TOKEN, REMEMBER_TOKEN_EXPIRES_AT) VALUES (1, 'admin', 'Administrator', '', 'a373a0e667abb2604c1fd571eb4ad47fe8cc0878', '48bc4b0d93179b5103fd3885ea9119498e9d161b', '1418215735482', '1418215735482', null, null);
 ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2;
index d71d0d7399d7705a1a3f5d1c4cd008e74770eff1..bda06b21a81565ff4dd3381fc68979f39032ca59 100644 (file)
@@ -351,7 +351,8 @@ CREATE TABLE "METRICS" (
   "BEST_VALUE" DOUBLE,
   "OPTIMIZED_BEST_VALUE" BOOLEAN,
   "HIDDEN" BOOLEAN,
-  "DELETE_HISTORICAL_DATA" BOOLEAN
+  "DELETE_HISTORICAL_DATA" BOOLEAN,
+  "DECIMAL_SCALE" INTEGER
 );
 
 CREATE TABLE "LOADED_TEMPLATES" (
index eb3940fa9aec59ca5bfff2a2dcc89a8b3512f10e..473e83889b5a5e895200480f7761143b63bba7a4 100644 (file)
@@ -82,6 +82,7 @@ public class MetricDaoTest {
     assertThat(result.isDeleteHistoricalData()).isFalse();
     assertThat(result.isHidden()).isFalse();
     assertThat(result.isEnabled()).isTrue();
+    assertThat(result.getDecimalScale()).isEqualTo(3);
 
     // Disabled metrics are returned
     result = underTest.selectByKey(session, "disabled");
index dda5d3bbb88ceb8b35c55ba29ee05289e0acfaac..1a43f8ed39e217c2ec57d84f3e99bd2be95c5a80 100644 (file)
@@ -2,14 +2,14 @@
 
   <metrics id="1" name="ncloc" val_type="INT" description="Non Commenting Lines of Code" domain="Size" short_name="Lines of code"
            qualitative="[false]" enabled="[true]" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="-1" hidden="[false]"
-            delete_historical_data="[false]" user_managed="[false]"/>
+            delete_historical_data="[false]" user_managed="[false]" decimal_scale="[null]"/>
 
   <metrics id="2" name="coverage" val_type="PERCENT" description="Coverage by unit tests" domain="Tests" short_name="Coverage"
            qualitative="[true]" enabled="[true]" worst_value="0" optimized_best_value="[false]" best_value="100" direction="1" hidden="[false]"
-            delete_historical_data="[false]" user_managed="[false]"/>
+            delete_historical_data="[false]" user_managed="[false]" decimal_scale="3"/>
 
   <metrics id="3" name="disabled" val_type="INT" description="[null]" domain="[null]" short_name="disabled"
            qualitative="[false]" enabled="[false]" worst_value="0" optimized_best_value="[true]" best_value="100" direction="1" hidden="[false]"
-            delete_historical_data="[false]" user_managed="[false]"/>
+            delete_historical_data="[false]" user_managed="[false]" decimal_scale="[null]"/>
 
 </dataset>
index 766652028ed822219881cd4df7c1bc8c06c13685..50b1f151b7d630ca3948fccad6932ac1127cb0c6 100644 (file)
  */
 package org.sonar.api.batch;
 
+import org.sonar.api.measures.Formula;
 import org.sonar.api.measures.FormulaContext;
 import org.sonar.api.measures.Metric;
 import org.sonar.api.resources.Resource;
 
 /**
  * @since 1.11
+ * @deprecated since 5.2. Aggregation of measures is provided by {@link org.sonar.api.ce.measure.MeasureComputer}. {@link org.sonar.api.batch.Decorator}
+ * and {@link Formula} are no more supported.
  */
+@Deprecated
 public class DefaultFormulaContext implements FormulaContext {
 
-  private Metric metric;
-  private DecoratorContext decoratorContext;
-
   public DefaultFormulaContext(Metric metric) {
-    this.metric = metric;
   }
 
   @Override
   public Metric getTargetMetric() {
-    return metric;
+    throw fail();
   }
 
   @Override
   public Resource getResource() {
-    return decoratorContext.getResource();
+    throw fail();
   }
 
   public void setMetric(Metric metric) {
-    this.metric = metric;
+    throw fail();
   }
 
   public void setDecoratorContext(DecoratorContext decoratorContext) {
-    this.decoratorContext = decoratorContext;
+    throw fail();
+  }
+
+  private static RuntimeException fail() {
+    throw new UnsupportedOperationException(
+      "Unsupported since version 5.2. Decorators and formulas are not used anymore for aggregation measures. Please use org.sonar.api.ce.measure.MeasureComputer.");
   }
 }
index 1aa4bc24193ef7fc7861619d1377235c4f3ccc95..8e218a00c9cd1a10fde603a40b0b9bcc1c0c3956 100644 (file)
  */
 package org.sonar.api.batch;
 
+import java.util.Collection;
+import org.sonar.api.measures.Formula;
 import org.sonar.api.measures.FormulaData;
 import org.sonar.api.measures.Measure;
 import org.sonar.api.measures.MeasuresFilter;
 import org.sonar.api.measures.Metric;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
 /**
  * @since 1.11
+ * @deprecated since 5.2. Aggregation of measures is provided by {@link org.sonar.api.ce.measure.MeasureComputer}. {@link org.sonar.api.batch.Decorator}
+ * and {@link Formula} are no more supported.
  */
+@Deprecated
 public class DefaultFormulaData implements FormulaData {
 
-  private DecoratorContext decoratorContext;
-
-  public DefaultFormulaData(DecoratorContext decoratorContext) {
-    this.decoratorContext = decoratorContext;
+  public DefaultFormulaData(DecoratorContext unused) {
   }
 
   @Override
   public Measure getMeasure(Metric metric) {
-    return decoratorContext.getMeasure(metric);
+    throw fail();
   }
 
   @Override
   public <M> M getMeasures(MeasuresFilter<M> filter) {
-    return decoratorContext.getMeasures(filter);
+    throw fail();
   }
 
   @Override
   public Collection<Measure> getChildrenMeasures(MeasuresFilter filter) {
-    return decoratorContext.getChildrenMeasures(filter);
+    throw fail();
   }
 
   @Override
   public Collection<Measure> getChildrenMeasures(Metric metric) {
-    return decoratorContext.getChildrenMeasures(metric);
+    throw fail();
   }
 
   @Override
   public Collection<FormulaData> getChildren() {
-    List<FormulaData> result = new ArrayList<>();
-    for (DecoratorContext childContext : decoratorContext.getChildren()) {
-      result.add(new DefaultFormulaData(childContext));
-    }
-    return result;
+    throw fail();
+  }
+
+  private static RuntimeException fail() {
+    throw new UnsupportedOperationException(
+      "Unsupported since version 5.2. Decorators and formulas are not used anymore for aggregation measures. Please use org.sonar.api.ce.measure.MeasureComputer.");
   }
 }
index f029f438918f4e0c3ffe1b0123ea42cbcd665910..2c3af7f5b95506e0cffadd914d2b789552dcad1b 100644 (file)
 package org.sonar.api.measures;
 
 import java.util.List;
-import org.sonar.api.resources.ResourceUtils;
-
-import static com.google.common.collect.Lists.newArrayList;
 
 /**
- * Formula used to compute an average for a given metric A, which is the result of the sum of measures of this metric (A) divided by another metric (B).
- * <p/>
- * For example: to compute the metric "complexity by file", the main metric (A) is "complexity" and the other metric (B) is "file".
- *
  * @since 3.0
- * @deprecated since 5.2 decorators are no more executed on batch side
+ * @deprecated since 5.2. Aggregation of measures is provided by {@link org.sonar.api.ce.measure.MeasureComputer}. {@link org.sonar.api.batch.Decorator}
+ * and {@link Formula} are no more supported.
  */
 @Deprecated
 public class AverageFormula implements Formula {
 
-  private Metric mainMetric;
-  private Metric byMetric;
-  private Metric fallbackMetric;
-
-  /**
-   * This method should be private but it kep package-protected because of AverageComplexityFormula.
-   */
-  AverageFormula(Metric mainMetric, Metric byMetric) {
-    this.mainMetric = mainMetric;
-    this.byMetric = byMetric;
-  }
-
   /**
    * Creates a new {@link AverageFormula} class.
    *
@@ -55,7 +37,7 @@ public class AverageFormula implements Formula {
    * @param by   The metric used to divide the main metric to compute average (ex.: "file" for "complexity by file")
    */
   public static AverageFormula create(Metric main, Metric by) {
-    return new AverageFormula(main, by);
+    return new AverageFormula();
   }
 
   /**
@@ -65,8 +47,7 @@ public class AverageFormula implements Formula {
    * @since 3.6
    */
   public AverageFormula setFallbackForMainMetric(Metric fallbackMetric) {
-    this.fallbackMetric = fallbackMetric;
-    return this;
+    throw fail();
   }
 
   /**
@@ -74,7 +55,7 @@ public class AverageFormula implements Formula {
    */
   @Override
   public List<Metric> dependsUponMetrics() {
-    return fallbackMetric != null ? newArrayList(mainMetric, fallbackMetric, byMetric) : newArrayList(mainMetric, byMetric);
+    throw fail();
   }
 
   /**
@@ -82,56 +63,11 @@ public class AverageFormula implements Formula {
    */
   @Override
   public Measure calculate(FormulaData data, FormulaContext context) {
-    if (!shouldDecorateResource(data, context)) {
-      return null;
-    }
-
-    Measure result;
-    if (ResourceUtils.isFile(context.getResource())) {
-      result = calculateForFile(data, context);
-    } else {
-      result = calculateOnChildren(data, context);
-    }
-    return result;
-  }
-
-  private Measure calculateOnChildren(FormulaData data, FormulaContext context) {
-    Measure result = null;
-
-    double totalByMeasure = 0;
-    double totalMainMeasure = 0;
-    boolean hasApplicableChildren = false;
-
-    for (FormulaData childrenData : data.getChildren()) {
-      Double fallbackMeasure = fallbackMetric != null ? MeasureUtils.getValue(childrenData.getMeasure(fallbackMetric), null) : null;
-      Double childrenByMeasure = MeasureUtils.getValue(childrenData.getMeasure(byMetric), null);
-      Double childrenMainMeasure = MeasureUtils.getValue(childrenData.getMeasure(mainMetric), fallbackMeasure);
-      if (childrenMainMeasure != null && childrenByMeasure != null && childrenByMeasure > 0.0) {
-        totalByMeasure += childrenByMeasure;
-        totalMainMeasure += childrenMainMeasure;
-        hasApplicableChildren = true;
-      }
-    }
-    if (hasApplicableChildren) {
-      result = new Measure(context.getTargetMetric(), totalMainMeasure / totalByMeasure);
-    }
-    return result;
-  }
-
-  private Measure calculateForFile(FormulaData data, FormulaContext context) {
-    Measure result = null;
-
-    Double fallbackMeasure = fallbackMetric != null ? MeasureUtils.getValue(data.getMeasure(fallbackMetric), null) : null;
-    Double byMeasure = MeasureUtils.getValue(data.getMeasure(byMetric), null);
-    Double mainMeasure = MeasureUtils.getValue(data.getMeasure(mainMetric), fallbackMeasure);
-    if (mainMeasure != null && byMeasure != null && byMeasure > 0.0) {
-      result = new Measure(context.getTargetMetric(), mainMeasure / byMeasure);
-    }
-
-    return result;
+    throw fail();
   }
 
-  private static boolean shouldDecorateResource(FormulaData data, FormulaContext context) {
-    return !MeasureUtils.hasValue(data.getMeasure(context.getTargetMetric()));
+  private static RuntimeException fail() {
+    throw new UnsupportedOperationException("Unsupported since version 5.2. Decorators and formulas are not used anymore for aggregation measures. " +
+      "Please use org.sonar.api.ce.measure.MeasureComputer.");
   }
 }
index b3c2fcb524b89325485e11fc414990f110bf3720..2011af669f92c5715b0c0e0abf9f4df68d5ce7de 100644 (file)
@@ -23,7 +23,10 @@ import org.sonar.api.resources.Resource;
 
 /**
  * @since 1.11
+ * @deprecated since 5.2. Aggregation of measures is provided by {@link org.sonar.api.ce.measure.MeasureComputer}. {@link org.sonar.api.batch.Decorator}
+ * and {@link Formula} are no more supported.
  */
+@Deprecated
 public interface FormulaContext {
 
   Metric getTargetMetric();
index 8cf5bb54307ee878749e7e5c4598af8989bfd9ed..459aec61695168b11f62dd5a24d91552c39e4247 100644 (file)
@@ -23,7 +23,10 @@ import java.util.Collection;
 
 /**
  * @since 1.11
+ * @deprecated since 5.2. Aggregation of measures is provided by {@link org.sonar.api.ce.measure.MeasureComputer}. {@link org.sonar.api.batch.Decorator}
+ * and {@link Formula} are no more supported.
  */
+@Deprecated
 public interface FormulaData {
 
   Measure getMeasure(Metric metric);
index f66bf51009d86913427cba89b3732487e5df9b31..22647cca1d55015b18f03e587e47fb5090f4002f 100644 (file)
  */
 package org.sonar.api.measures;
 
-import java.util.Collection;
-import java.util.Collections;
 import java.util.List;
 
 /**
  * @since 2.0
- * @deprecated since 5.2 decorators are no more executed on batch side
+ * @deprecated since 5.2. Aggregation of measures is provided by {@link org.sonar.api.ce.measure.MeasureComputer}. {@link org.sonar.api.batch.Decorator}
+ * and {@link Formula} are no more supported.
  */
 @Deprecated
 public class MeanAggregationFormula implements Formula {
 
-  private boolean forceZeroIfMissingData=false;
-
-  public MeanAggregationFormula(boolean forceZeroIfMissingData) {
-    this.forceZeroIfMissingData = forceZeroIfMissingData;
+  public MeanAggregationFormula(boolean unused) {
   }
 
   public MeanAggregationFormula() {
@@ -42,26 +38,16 @@ public class MeanAggregationFormula implements Formula {
 
   @Override
   public List<Metric> dependsUponMetrics() {
-    return Collections.emptyList();
+    throw fail();
   }
 
   @Override
   public Measure calculate(FormulaData data, FormulaContext context) {
-    double sum=0.0;
-    int count=0;
-    boolean hasValue=false;
-    Collection<Measure> measures = data.getChildrenMeasures(context.getTargetMetric());
-    for (Measure measure : measures) {
-      if (MeasureUtils.hasValue(measure)) {
-        sum+=measure.getValue();
-        count++;
-        hasValue=true;
-      }
-    }
+    throw fail();
+  }
 
-    if (!hasValue && !forceZeroIfMissingData) {
-      return null;
-    }
-    return new Measure(context.getTargetMetric(), (count==0) ? 0.0 : (sum/count));
+  private static RuntimeException fail() {
+    throw new UnsupportedOperationException(
+      "Unsupported since version 5.2. Decorators and formulas are not used anymore for aggregation measures. Please use org.sonar.api.ce.measure.MeasureComputer.");
   }
 }
index 4f2bef50a9fcdda4a9d8f38a443820376e3afcb6..adeae251213b2f9012b35ccd291e4999ba02c2bc 100644 (file)
@@ -21,8 +21,6 @@ package org.sonar.api.measures;
 
 import com.google.common.annotations.Beta;
 import java.io.Serializable;
-import java.math.BigDecimal;
-import java.math.RoundingMode;
 import java.util.Date;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
@@ -43,7 +41,9 @@ public class Measure<G extends Serializable> implements Serializable {
 
   /**
    * Default precision when saving a float type metric
+   * @deprecated in 5.3. Decimal scale is provided by metric, not by measure.
    */
+  @Deprecated
   public static final int DEFAULT_PRECISION = 1;
 
   protected String metricKey;
@@ -322,27 +322,22 @@ public class Measure<G extends Serializable> implements Serializable {
   /**
    * Sets the measure value with a given precision
    *
-   * @param v         the measure value
-   * @param precision the measure value precision
-   * @return the measure object instance
+   * @return {@code this}
+   * @deprecated in 5.3. The decimal scale is given by the metric, not by the measure. Anyway this parameter was enforced to 1 before version 5.3.
    */
-  public Measure<G> setValue(@Nullable Double v, int precision) {
+  @Deprecated
+  public Measure<G> setValue(@Nullable Double v, int decimalScale) {
     if (v != null) {
       if (Double.isNaN(v)) {
         throw new IllegalArgumentException("Measure value can not be NaN");
       }
-      this.value = scaleValue(v, precision);
+      this.value = v;
     } else {
       this.value = null;
     }
     return this;
   }
 
-  private static double scaleValue(double value, int scale) {
-    BigDecimal bd = BigDecimal.valueOf(value);
-    return bd.setScale(scale, RoundingMode.HALF_UP).doubleValue();
-  }
-
   /**
    * @return the data field of the measure
    */
index 949e0ab603c9ff80a18cae1f31a87f126cbf4a58..8fdb94f44a6fe1379ac179aaaba7d5ff0721d861 100644 (file)
@@ -27,18 +27,32 @@ import java.util.List;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
-import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.builder.ReflectionToStringBuilder;
 import org.apache.commons.lang.builder.ToStringStyle;
 import org.sonar.api.batch.BatchSide;
 import org.sonar.api.batch.InstantiationStrategy;
 import org.sonar.api.server.ServerSide;
 
+import static com.google.common.base.Objects.firstNonNull;
+import static com.google.common.base.Preconditions.checkArgument;
+import static org.apache.commons.lang.StringUtils.isNotBlank;
+
 @BatchSide
 @InstantiationStrategy(InstantiationStrategy.PER_BATCH)
 @ServerSide
 public class Metric<G extends Serializable> implements Serializable, org.sonar.api.batch.measure.Metric<G> {
 
+  /**
+   * @since 5.3
+   */
+  public static final int DEFAULT_DECIMAL_SCALE = 1;
+
+  /**
+   * The maximum supported value of scale for decimal metrics
+   * @since 5.3
+   */
+  public static final int MAX_DECIMAL_SCALE = 20;
+
   /**
    * A metric bigger value means a degradation
    */
@@ -126,6 +140,7 @@ public class Metric<G extends Serializable> implements Serializable, org.sonar.a
   private Boolean optimizedBestValue;
   private Boolean hidden = Boolean.FALSE;
   private Boolean deleteHistoricalData;
+  private Integer decimalScale;
 
   private Metric(Builder builder) {
     this.key = builder.key;
@@ -143,6 +158,7 @@ public class Metric<G extends Serializable> implements Serializable, org.sonar.a
     this.formula = builder.formula;
     this.userManaged = builder.userManaged;
     this.deleteHistoricalData = builder.deleteHistoricalData;
+    this.decimalScale = builder.decimalScale;
   }
 
   /**
@@ -208,9 +224,12 @@ public class Metric<G extends Serializable> implements Serializable, org.sonar.a
     this.name = name;
     this.qualitative = qualitative;
     this.userManaged = userManaged;
-    if (ValueType.PERCENT.equals(this.type)) {
+    if (ValueType.PERCENT == this.type) {
       this.bestValue = (direction == DIRECTION_BETTER) ? 100.0 : 0.0;
       this.worstValue = (direction == DIRECTION_BETTER) ? 0.0 : 100.0;
+      this.decimalScale = DEFAULT_DECIMAL_SCALE;
+    } else if (ValueType.FLOAT == this.type) {
+      this.decimalScale = DEFAULT_DECIMAL_SCALE;
     }
   }
 
@@ -492,6 +511,15 @@ public class Metric<G extends Serializable> implements Serializable, org.sonar.a
     return deleteHistoricalData;
   }
 
+  /**
+   * Return the number scale if metric type is {@link ValueType#FLOAT}, else {@code null}
+   * @since 5.3
+   */
+  @CheckForNull
+  public Integer getDecimalScale() {
+    return decimalScale;
+  }
+
   @Override
   public int hashCode() {
     return key.hashCode();
@@ -557,6 +585,7 @@ public class Metric<G extends Serializable> implements Serializable, org.sonar.a
     private boolean hidden = false;
     private boolean userManaged = false;
     private boolean deleteHistoricalData = false;
+    private Integer decimalScale = null;
 
     /**
      * Creates a new {@link Builder} object.
@@ -566,15 +595,9 @@ public class Metric<G extends Serializable> implements Serializable, org.sonar.a
      * @param type the metric type
      */
     public Builder(String key, String name, ValueType type) {
-      if (StringUtils.isBlank(key)) {
-        throw new IllegalArgumentException("Metric key can not be blank");
-      }
-      if (StringUtils.isBlank(name)) {
-        throw new IllegalArgumentException("Metric name can not be blank");
-      }
-      if (type == null) {
-        throw new IllegalArgumentException("Metric type can not be null");
-      }
+      checkArgument(isNotBlank(key), "Metric key can not be blank");
+      checkArgument(isNotBlank(name), "Name of metric %s must be set", key);
+      checkArgument(type != null, "Type of metric %s must be set", key);
       this.key = key;
       this.name = name;
       this.type = type;
@@ -647,11 +670,6 @@ public class Metric<G extends Serializable> implements Serializable, org.sonar.a
      * When a formula is set, sensors/decorators just need to store measures at a specific level and let Sonar run the formula to store
      * measures on the remaining levels.
      *
-     * @see SumChildDistributionFormula
-     * @see SumChildValuesFormula
-     * @see MeanAggregationFormula
-     * @see WeightedMeanAggregationFormula
-     *
      * @param f the formula
      * @return the builder
      *
@@ -740,15 +758,31 @@ public class Metric<G extends Serializable> implements Serializable, org.sonar.a
       return this;
     }
 
+    /**
+     * Scale to be used if the metric has decimal type ({@link ValueType#FLOAT} or {@link ValueType#PERCENT}).
+     * Default is 1. It is not set (({@code null}) on non-decimal metrics.
+     * @since 5.3
+     */
+    public Builder setDecimalScale(int scale) {
+      checkArgument(scale >= 0, "Scale of decimal metric %s must be positive: %d", key, scale);
+      checkArgument(scale <= MAX_DECIMAL_SCALE, "Scale of decimal metric [%s] must be less than or equal %s: %s", key, MAX_DECIMAL_SCALE, scale);
+      this.decimalScale = scale;
+      return this;
+    }
+
     /**
      * Creates a new metric definition based on the properties set on this metric builder.
      *
      * @return a new {@link Metric} object
      */
     public <G extends Serializable> Metric<G> create() {
-      if (ValueType.PERCENT.equals(this.type)) {
+      if (ValueType.PERCENT == this.type) {
         this.bestValue = (direction == DIRECTION_BETTER) ? 100.0 : 0.0;
         this.worstValue = (direction == DIRECTION_BETTER) ? 0.0 : 100.0;
+        this.decimalScale = firstNonNull(decimalScale, DEFAULT_DECIMAL_SCALE);
+
+      } else if (ValueType.FLOAT == this.type) {
+        this.decimalScale = firstNonNull(decimalScale, DEFAULT_DECIMAL_SCALE);
       }
       return new Metric<>(this);
     }
index e75a2f3c119de43db5d5a8dac0d003b02c299303..616eb2cbff7feb2a3f35eeb7abf1aab5a47f3c8a 100644 (file)
  */
 package org.sonar.api.measures;
 
-import java.util.Collection;
-import java.util.Collections;
 import java.util.List;
-import org.sonar.api.resources.Scopes;
 
 /**
  * @since 2.0
  *
  * Used to consolidate a distribution measure throughout the resource tree
- * @deprecated since 5.2 decorators are no more executed on batch side
+ * @deprecated since 5.2. Aggregation of measures is provided by {@link org.sonar.api.ce.measure.MeasureComputer}. {@link org.sonar.api.batch.Decorator}
+ * and {@link Formula} are no more supported.
  */
 @Deprecated
 public class SumChildDistributionFormula implements Formula {
 
-  private String minimumScopeToPersist= Scopes.FILE;
-
   @Override
   public List<Metric> dependsUponMetrics() {
-    return Collections.emptyList();
+    throw fail();
   }
 
   public String getMinimumScopeToPersist() {
-    return minimumScopeToPersist;
+    throw fail();
   }
 
   public SumChildDistributionFormula setMinimumScopeToPersist(String s) {
-    this.minimumScopeToPersist = s;
-    return this;
+    throw fail();
   }
 
   @Override
   public Measure calculate(FormulaData data, FormulaContext context) {
-    Collection<Measure> measures = data.getChildrenMeasures(context.getTargetMetric());
-    if (measures == null || measures.isEmpty()) {
-      return null;
-    }
-    RangeDistributionBuilder distribution = new RangeDistributionBuilder(context.getTargetMetric());
-    for (Measure measure : measures) {
-      distribution.add(measure);
-    }
-    Measure measure = distribution.build();
-    if (!Scopes.isHigherThanOrEquals(context.getResource().getScope(), minimumScopeToPersist)) {
-      measure.setPersistenceMode(PersistenceMode.MEMORY);
-    }
-    return measure;
+    throw fail();
+  }
+
+  private static RuntimeException fail() {
+    throw new UnsupportedOperationException(
+      "Unsupported since version 5.2. Decorators and formulas are not used anymore for aggregation measures. Please use org.sonar.api.ce.measure.MeasureComputer.");
   }
 }
index 37e7abf6a25df52cd63a559e7c0f74802a875f5c..450befdee5a2fa14a2af266cad2664792e499169 100644 (file)
  */
 package org.sonar.api.measures;
 
-import java.util.Collections;
 import java.util.List;
 
 /**
  * @since 1.11
- * @deprecated since 5.2 decorators are no more executed on batch side
+ * @deprecated since 5.2. Aggregation of measures is provided by {@link org.sonar.api.ce.measure.MeasureComputer}. {@link org.sonar.api.batch.Decorator}
+ * and {@link Formula} are no more supported.
  */
 @Deprecated
 public class SumChildValuesFormula implements Formula {
 
-  private boolean saveZeroIfNoChildValues;
-
-  public SumChildValuesFormula(boolean saveZeroIfNoChildValues) {
-    this.saveZeroIfNoChildValues = saveZeroIfNoChildValues;
+  public SumChildValuesFormula(boolean unused) {
   }
 
   @Override
   public List<Metric> dependsUponMetrics() {
-    return Collections.emptyList();
+    throw fail();
   }
 
   @Override
   public Measure calculate(FormulaData data, FormulaContext context) {
-    Double sum = MeasureUtils.sum(saveZeroIfNoChildValues, data.getChildrenMeasures(context.getTargetMetric()));
-    if (sum != null) {
-      return new Measure(context.getTargetMetric(), sum);
-    }
-    return null;
+    throw fail();
+  }
+
+  private static RuntimeException fail() {
+    throw new UnsupportedOperationException(
+      "Unsupported since version 5.2. Decorators and formulas are not used anymore for aggregation measures. Please use org.sonar.api.ce.measure.MeasureComputer.");
   }
 }
index 7be604edaf6ee16539893c4c545296859be8e36c..360eb01ea9e61d4043a3dfc321860df952efdda0 100644 (file)
  */
 package org.sonar.api.measures;
 
-import java.util.Collections;
 import java.util.List;
 
 /**
  * @since 2.0
- * @deprecated since 5.2 decorators are no more executed on batch side
+ * @deprecated since 5.2. Aggregation of measures is provided by {@link org.sonar.api.ce.measure.MeasureComputer}. {@link org.sonar.api.batch.Decorator}
+ * and {@link Formula} are no more supported.
  */
 @Deprecated
 public class WeightedMeanAggregationFormula implements Formula {
 
-  private Metric weightingMetric;
-  private boolean zeroIfNoValues=false;
-
   public WeightedMeanAggregationFormula(Metric weightingMetric, boolean zeroIfNoValues) {
-    this.weightingMetric = weightingMetric;
-    if (weightingMetric==null) {
-      throw new IllegalArgumentException("Metric can not be null");
-    }
-    this.zeroIfNoValues = zeroIfNoValues;
   }
 
   @Override
   public List<Metric> dependsUponMetrics() {
-    return Collections.emptyList();
+    throw fail();
   }
 
   @Override
   public Measure calculate(FormulaData data, FormulaContext context) {
-    double sum=0.0;
-    double count=0.0;
-    boolean hasValue=false;
-
-    for (FormulaData child : data.getChildren()) {
-      Measure measure = child.getMeasure(context.getTargetMetric());
-      Measure weightingMeasure = child.getMeasure(weightingMetric);
-      if (MeasureUtils.haveValues(measure, weightingMeasure)) {
-        sum += measure.getValue() * weightingMeasure.getValue();
-        count += weightingMeasure.getValue();
-        hasValue=true;
-      }
-    }
-
-    if (!hasValue && !zeroIfNoValues) {
-      return null;
-    }
+    throw fail();
+  }
 
-    double result = (Double.doubleToRawLongBits(count)==0L) ? 0.0 : (sum/count);
-    return new Measure(context.getTargetMetric(), result);
+  private static RuntimeException fail() {
+    throw new UnsupportedOperationException(
+      "Unsupported since version 5.2. Decorators and formulas are not used anymore for aggregation measures. Please use org.sonar.api.ce.measure.MeasureComputer.");
   }
 }
-
index 5139aa75edb3874c489099dc0930e5150f82165e..03f6188eea6289682f73d899e157c74909089d06 100644 (file)
@@ -23,42 +23,22 @@ import org.junit.Test;
 import org.sonar.api.measures.MeasuresFilter;
 import org.sonar.api.measures.Metric;
 
-import java.util.Arrays;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
 public class DefaultFormulaDataTest {
 
-  @Test
-  public void isDecoratorContextProxy() {
-    DecoratorContext context = mock(DecoratorContext.class);
-    DefaultFormulaData data = new DefaultFormulaData(context);
-
-    data.getChildrenMeasures(any(MeasuresFilter.class));
-    verify(context).getChildrenMeasures(any(MeasuresFilter.class));
+  DefaultFormulaData underTest = new DefaultFormulaData(null);
 
-    data.getChildrenMeasures(any(Metric.class));
-    verify(context).getChildrenMeasures(any(Metric.class));
-
-    data.getMeasures(any(MeasuresFilter.class));
-    verify(context).getMeasures(any(MeasuresFilter.class));
-
-    data.getMeasure(any(Metric.class));
-    verify(context).getMeasure(any(Metric.class));
+  @Test(expected = UnsupportedOperationException.class)
+  public void fail_if_used_1() {
+    underTest.getChildren();
   }
 
-  @Test
-  public void getChildren() {
-    DecoratorContext context = mock(DecoratorContext.class);
-    DecoratorContext child1 = mock(DecoratorContext.class);
-    DecoratorContext child2 = mock(DecoratorContext.class);
-    when(context.getChildren()).thenReturn(Arrays.asList(child1, child2));
+  @Test(expected = UnsupportedOperationException.class)
+  public void fail_if_used_2() {
+    underTest.getChildrenMeasures((MeasuresFilter) null);
+  }
 
-    DefaultFormulaData data = new DefaultFormulaData(context);
-    assertThat(data.getChildren()).hasSize(2);
+  @Test(expected = UnsupportedOperationException.class)
+  public void fail_if_used_3() {
+    underTest.getChildrenMeasures((Metric) null);
   }
 }
index e4a9c96f57c2c8f1b5de93125f095a34a432b9ae..cc05ee44bbff66296610e91c9d34cd49aab5712c 100644 (file)
  */
 package org.sonar.api.measures;
 
-import org.junit.Before;
 import org.junit.Test;
-import org.sonar.api.resources.File;
-
-import java.util.List;
-
-import static com.google.common.collect.Lists.newArrayList;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
 
 public class AverageFormulaTest {
 
-  private FormulaContext context;
-  private FormulaData data;
+  AverageFormula underTest = new AverageFormula();
 
-  @Before
-  public void before() {
-    context = mock(FormulaContext.class);
-    when(context.getTargetMetric()).thenReturn(CoreMetrics.FUNCTION_COMPLEXITY);
-    data = mock(FormulaData.class);
+  @Test(expected = UnsupportedOperationException.class)
+  public void fail_if_used_1() {
+    underTest.calculate(null, null);
   }
 
-  @Test
-  public void test_depends_upon_metrics() throws Exception {
-    AverageFormula formula = AverageFormula.create(CoreMetrics.COMPLEXITY, CoreMetrics.FUNCTIONS);
-    assertThat(formula.dependsUponMetrics()).containsOnly(CoreMetrics.COMPLEXITY, CoreMetrics.FUNCTIONS);
+  @Test(expected = UnsupportedOperationException.class)
+  public void fail_if_used_2() {
+    underTest.dependsUponMetrics();
   }
 
-  @Test
-  public void test_depends_upon_fallback_metric() throws Exception {
-    AverageFormula formula = AverageFormula.create(CoreMetrics.COMPLEXITY_IN_FUNCTIONS, CoreMetrics.FUNCTIONS).setFallbackForMainMetric(CoreMetrics.COMPLEXITY);
-    assertThat(formula.dependsUponMetrics()).containsOnly(CoreMetrics.COMPLEXITY_IN_FUNCTIONS, CoreMetrics.COMPLEXITY, CoreMetrics.FUNCTIONS);
+  @Test(expected = UnsupportedOperationException.class)
+  public void fail_if_used_3() {
+    underTest.setFallbackForMainMetric(null);
   }
-
-  @Test
-  public void test_average_calculation() {
-    List<FormulaData> childrenData = newArrayList();
-    FormulaData data1 = mock(FormulaData.class);
-    childrenData.add(data1);
-    when(data1.getMeasure(CoreMetrics.FUNCTIONS)).thenReturn(new Measure(CoreMetrics.FUNCTIONS, 43.0));
-    when(data1.getMeasure(CoreMetrics.COMPLEXITY)).thenReturn(new Measure(CoreMetrics.FUNCTIONS, 107.0));
-
-    FormulaData data2 = mock(FormulaData.class);
-    childrenData.add(data2);
-    when(data2.getMeasure(CoreMetrics.FUNCTIONS)).thenReturn(new Measure(CoreMetrics.FUNCTIONS, 127.0));
-    when(data2.getMeasure(CoreMetrics.COMPLEXITY)).thenReturn(new Measure(CoreMetrics.FUNCTIONS, 233.0));
-
-    when(data.getChildren()).thenReturn(childrenData);
-
-    Measure measure = AverageFormula.create(CoreMetrics.COMPLEXITY, CoreMetrics.FUNCTIONS).calculate(data, context);
-
-    assertThat(measure.getValue()).isEqualTo(2.0);
-  }
-
-  @Test
-  public void should_not_compute_if_not_target_metric() {
-    when(data.getMeasure(CoreMetrics.FUNCTION_COMPLEXITY)).thenReturn(new Measure(CoreMetrics.FUNCTION_COMPLEXITY, 2.0));
-    Measure measure = AverageFormula.create(CoreMetrics.COMPLEXITY, CoreMetrics.FUNCTIONS).calculate(data, context);
-    assertThat(measure).isNull();
-  }
-
-  @Test
-  public void test_when_no_children_measures() {
-    List<FormulaData> childrenData = newArrayList();
-    when(data.getChildren()).thenReturn(childrenData);
-    Measure measure = AverageFormula.create(CoreMetrics.COMPLEXITY, CoreMetrics.FUNCTIONS).calculate(data, context);
-    assertThat(measure).isNull();
-  }
-
-  @Test
-  public void test_when_no_complexity_measures() {
-    List<FormulaData> childrenData = newArrayList();
-    FormulaData data1 = mock(FormulaData.class);
-    childrenData.add(data1);
-    when(data1.getMeasure(CoreMetrics.FUNCTIONS)).thenReturn(new Measure(CoreMetrics.FUNCTIONS, 43.0));
-
-    when(data.getChildren()).thenReturn(childrenData);
-    Measure measure = AverageFormula.create(CoreMetrics.COMPLEXITY, CoreMetrics.FUNCTIONS).calculate(data, context);
-
-    assertThat(measure).isNull();
-  }
-
-  @Test
-  public void test_when_no_by_metric_measures() {
-    List<FormulaData> childrenData = newArrayList();
-    FormulaData data1 = mock(FormulaData.class);
-    childrenData.add(data1);
-    when(data1.getMeasure(CoreMetrics.COMPLEXITY)).thenReturn(new Measure(CoreMetrics.COMPLEXITY, 43.0));
-
-    when(data.getChildren()).thenReturn(childrenData);
-    Measure measure = AverageFormula.create(CoreMetrics.COMPLEXITY, CoreMetrics.FUNCTIONS).calculate(data, context);
-
-    assertThat(measure).isNull();
-  }
-
-  @Test
-  public void test_when_mixed_metrics() {
-    List<FormulaData> childrenData = newArrayList();
-    FormulaData data1 = mock(FormulaData.class);
-    childrenData.add(data1);
-    when(data1.getMeasure(CoreMetrics.FUNCTIONS)).thenReturn(new Measure(CoreMetrics.FUNCTIONS, 43.0));
-    when(data1.getMeasure(CoreMetrics.COMPLEXITY)).thenReturn(new Measure(CoreMetrics.COMPLEXITY, 107.0));
-
-    FormulaData data2 = mock(FormulaData.class);
-    childrenData.add(data2);
-    when(data2.getMeasure(CoreMetrics.STATEMENTS)).thenReturn(new Measure(CoreMetrics.STATEMENTS, 127.0));
-    when(data2.getMeasure(CoreMetrics.COMPLEXITY)).thenReturn(new Measure(CoreMetrics.COMPLEXITY, 233.0));
-
-    when(data.getChildren()).thenReturn(childrenData);
-
-    Measure measure = AverageFormula.create(CoreMetrics.COMPLEXITY, CoreMetrics.FUNCTIONS).calculate(data, context);
-
-    assertThat(measure.getValue()).isEqualTo(2.5);
-  }
-
-  @Test
-  public void test_calculation_for_file() {
-    when(data.getMeasure(CoreMetrics.COMPLEXITY)).thenReturn(new Measure(CoreMetrics.COMPLEXITY, 60.0));
-    when(data.getMeasure(CoreMetrics.FUNCTIONS)).thenReturn(new Measure(CoreMetrics.FUNCTIONS, 20.0));
-    when(context.getResource()).thenReturn(File.create("foo"));
-
-    Measure measure = AverageFormula.create(CoreMetrics.COMPLEXITY, CoreMetrics.FUNCTIONS).calculate(data, context);
-    assertThat(measure.getValue()).isEqualTo(3.0);
-  }
-
-  @Test
-  public void should_use_fallback_metric_when_no_data_on_main_metric_for_file() {
-    when(data.getMeasure(CoreMetrics.COMPLEXITY_IN_FUNCTIONS)).thenReturn(null);
-    when(data.getMeasure(CoreMetrics.COMPLEXITY)).thenReturn(new Measure(CoreMetrics.COMPLEXITY, 60.0));
-    when(data.getMeasure(CoreMetrics.FUNCTIONS)).thenReturn(new Measure(CoreMetrics.FUNCTIONS, 20.0));
-    when(context.getResource()).thenReturn(File.create("foo"));
-
-    Measure measure = AverageFormula.create(CoreMetrics.COMPLEXITY_IN_FUNCTIONS, CoreMetrics.FUNCTIONS)
-      .setFallbackForMainMetric(CoreMetrics.COMPLEXITY)
-      .calculate(data, context);
-    assertThat(measure.getValue()).isEqualTo(3.0);
-  }
-
-  @Test
-  public void should_use_main_metric_even_if_fallback_metric_provided() {
-    when(data.getMeasure(CoreMetrics.COMPLEXITY_IN_FUNCTIONS)).thenReturn(new Measure(CoreMetrics.COMPLEXITY, 60.0));
-    when(data.getMeasure(CoreMetrics.COMPLEXITY)).thenReturn(new Measure(CoreMetrics.COMPLEXITY, 42.0));
-    when(data.getMeasure(CoreMetrics.FUNCTIONS)).thenReturn(new Measure(CoreMetrics.FUNCTIONS, 20.0));
-    when(context.getResource()).thenReturn(File.create("foo"));
-
-    Measure measure = AverageFormula.create(CoreMetrics.COMPLEXITY_IN_FUNCTIONS, CoreMetrics.FUNCTIONS)
-      .setFallbackForMainMetric(CoreMetrics.COMPLEXITY)
-      .calculate(data, context);
-    assertThat(measure.getValue()).isEqualTo(3.0);
-  }
-
-  @Test
-  public void should_use_fallback_metric_when_no_data_on_main_metric_for_children() {
-    List<FormulaData> childrenData = newArrayList();
-    FormulaData data1 = mock(FormulaData.class);
-    childrenData.add(data1);
-    when(data1.getMeasure(CoreMetrics.COMPLEXITY_IN_FUNCTIONS)).thenReturn(null);
-    when(data1.getMeasure(CoreMetrics.COMPLEXITY)).thenReturn(new Measure(CoreMetrics.COMPLEXITY, 107.0));
-    when(data1.getMeasure(CoreMetrics.FUNCTIONS)).thenReturn(new Measure(CoreMetrics.FUNCTIONS, 43.0));
-
-    when(data.getChildren()).thenReturn(childrenData);
-
-    Measure measure = AverageFormula.create(CoreMetrics.COMPLEXITY_IN_FUNCTIONS, CoreMetrics.FUNCTIONS)
-      .setFallbackForMainMetric(CoreMetrics.COMPLEXITY)
-      .calculate(data, context);
-
-    assertThat(measure.getValue()).isEqualTo(2.5);
-  }
-
 }
index c1443832c7bc79a77fa8ae5da9a47cc4601885ae..2beec78cdd1b9166e3706fcc278daf1f6bc4d81a 100644 (file)
  */
 package org.sonar.api.measures;
 
-import org.junit.Before;
 import org.junit.Test;
 
-import java.util.Arrays;
-import java.util.Collections;
-
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
 public class MeanAggregationFormulaTest {
 
-  private FormulaContext context;
-  private FormulaData data;
-
-  @Before
-  public void before() {
-    context = mock(FormulaContext.class);
-    data = mock(FormulaData.class);
-  }
-
-  @Test
-  public void calculateChildrenMean() {
-    when(context.getTargetMetric()).thenReturn(CoreMetrics.COVERAGE);
-    when(data.getChildrenMeasures(CoreMetrics.COVERAGE)).thenReturn(Arrays.<Measure>asList(newCoverage(100.0), newCoverage(50.0), newCoverage(30.0)));
-
-    Measure measure = new MeanAggregationFormula().calculate(data, context);
-    assertThat(measure.getValue(), is(60.0));
-  }
-
-  @Test
-  public void doNotForceZero() {
-    when(context.getTargetMetric()).thenReturn(CoreMetrics.COVERAGE);
-    when(data.getChildrenMeasures(CoreMetrics.COVERAGE)).thenReturn(Collections.<Measure>emptyList());
-
-    Measure measure = new MeanAggregationFormula(false).calculate(data, context);
-    assertNull(measure);
-  }
-
-  @Test
-  public void forceZero() {
-    when(context.getTargetMetric()).thenReturn(CoreMetrics.COVERAGE);
-    when(data.getChildrenMeasures(CoreMetrics.COVERAGE)).thenReturn(Collections.<Measure>emptyList());
+  MeanAggregationFormula underTest = new MeanAggregationFormula();
 
-    Measure measure = new MeanAggregationFormula(true).calculate(data, context);
-    assertThat(measure.getValue(), is(0.0));
+  @Test(expected = UnsupportedOperationException.class)
+  public void fail_if_used_1() {
+    underTest.calculate(null, null);
   }
 
-  private Measure newCoverage(double val) {
-    return new Measure(CoreMetrics.COVERAGE, val);
+  @Test(expected = UnsupportedOperationException.class)
+  public void fail_if_used_2() {
+    underTest.dependsUponMetrics();
   }
 }
index 9a33b01caab4f41364f2fa8a21fe5639f0a9fdca..b671a63e9c783315176badeaa0a756719e20c677 100644 (file)
@@ -45,12 +45,6 @@ public class MeasureTest {
     new Measure("metric_key").setValue(Double.NaN);
   }
 
-  @Test
-  public void scaleValue() {
-    assertThat(new Measure(CoreMetrics.COVERAGE, 80.666666).getValue()).isEqualTo(80.7);
-    assertThat(new Measure(CoreMetrics.COVERAGE, 80.666666, 2).getValue()).isEqualTo(80.67);
-  }
-
   @Test
   public void defaultPersistenceModeIsFull() {
     assertThat(new Measure(CoreMetrics.LINES, 32.0).getPersistenceMode()).isEqualTo(PersistenceMode.FULL);
@@ -81,15 +75,6 @@ public class MeasureTest {
     assertThat(new Measure(CoreMetrics.LINES).setValue(3.6).getIntValue()).isEqualTo(3);
   }
 
-  @Test
-  public void valuesAreRoundUp() {
-    assertThat(new Measure(CoreMetrics.COVERAGE, 5.22222222).getValue()).isEqualTo(5.2);
-    assertThat(new Measure(CoreMetrics.COVERAGE, 5.7777777).getValue()).isEqualTo(5.8);
-
-    assertThat(new Measure(CoreMetrics.COVERAGE, 5.22222222, 3).getValue()).isEqualTo(5.222);
-    assertThat(new Measure(CoreMetrics.COVERAGE, 5.7777777, 3).getValue()).isEqualTo(5.778);
-  }
-
   /**
    * Proper definition of equality for measures is important, because used to store them.
    */
index 24ae4b69be724700943dbdb2fe42b020ae6f0a25..0a088f53d3a1ca3e5d14b3ccc0421567e40e6313 100644 (file)
  */
 package org.sonar.api.measures;
 
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.junit.Assert.assertThat;
+import static org.assertj.core.api.Assertions.assertThat;
 
 public class MetricTest {
 
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
   @Test
   public void shouldCreateMetric() {
     Metric metric = new Metric.Builder("foo", "Foo", Metric.ValueType.INT)
-        .setDomain("my domain")
-        .create();
+      .setDomain("my domain")
+      .create();
 
-    assertThat(metric.getKey(), is("foo"));
-    assertThat(metric.getName(), is("Foo"));
-    assertThat(metric.getDomain(), is("my domain"));
+    assertThat(metric.getKey()).isEqualTo("foo");
+    assertThat(metric.getName()).isEqualTo("Foo");
+    assertThat(metric.getDomain()).isEqualTo("my domain");
   }
 
   @Test
   public void shouldCreateMetricWithDefaultValues() {
     Metric metric = new Metric.Builder("foo", "Foo", Metric.ValueType.INT)
-        .create();
-
-    assertThat(metric.getBestValue(), nullValue());
-    assertThat(metric.getDescription(), nullValue());
-    assertThat(metric.getWorstValue(), nullValue());
-    assertThat(metric.getDirection(), is(Metric.DIRECTION_NONE));
-    assertThat(metric.getEnabled(), is(true));
-    assertThat(metric.getFormula(), nullValue());
-    assertThat(metric.getId(), nullValue());
-    assertThat(metric.getUserManaged(), is(false));
-    assertThat(metric.isHidden(), is(false));
-    assertThat(metric.isOptimizedBestValue(), is(false));
+      .create();
+
+    assertThat(metric.getBestValue()).isNull();
+    assertThat(metric.getDescription()).isNull();
+    assertThat(metric.getWorstValue()).isNull();
+    assertThat(metric.getDirection()).isEqualTo(Metric.DIRECTION_NONE);
+    assertThat(metric.getEnabled()).isTrue();
+    assertThat(metric.getFormula()).isNull();
+    assertThat(metric.getId()).isNull();
+    assertThat(metric.getUserManaged()).isFalse();
+    assertThat(metric.isHidden()).isFalse();
+    assertThat(metric.isOptimizedBestValue()).isFalse();
   }
 
   @Test
   public void shouldCreatePercentMetricWithDefaultValues() {
     Metric better = new Metric.Builder("foo", "Foo", Metric.ValueType.PERCENT)
-        .setDirection(Metric.DIRECTION_BETTER)
-        .create();
+      .setDirection(Metric.DIRECTION_BETTER)
+      .create();
     Metric worst = new Metric.Builder("foo", "Foo", Metric.ValueType.PERCENT)
-        .setDirection(Metric.DIRECTION_WORST)
-        .create();
+      .setDirection(Metric.DIRECTION_WORST)
+      .create();
+
+    assertThat(better.getBestValue()).isEqualTo(100.0);
+    assertThat(better.getWorstValue()).isEqualTo(0.0);
+    assertThat(worst.getBestValue()).isEqualTo(0.0);
+    assertThat(worst.getWorstValue()).isEqualTo(100.0);
+  }
+
+  @Test
+  public void override_decimal_scale_of_float_metric() {
+    Metric metric = new Metric.Builder("foo", "Foo", Metric.ValueType.FLOAT)
+      .setDecimalScale(3)
+      .create();
+    assertThat(metric.getDecimalScale()).isEqualTo(3);
+  }
+
+  @Test
+  public void fail_if_decimal_scale_is_greater_than_max_supported_value() {
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Scale of decimal metric [foo] must be less than or equal 20: 21");
 
-    assertThat(better.getBestValue(), is(100.0));
-    assertThat(better.getWorstValue(), is(0.0));
-    assertThat(worst.getBestValue(), is(0.0));
-    assertThat(worst.getWorstValue(), is(100.0));
+    new Metric.Builder("foo", "Foo", Metric.ValueType.FLOAT)
+      .setDecimalScale(Metric.MAX_DECIMAL_SCALE + 1)
+      .create();
   }
 
+  @Test
+  public void override_decimal_scale_of_percent_metric() {
+    Metric metric = new Metric.Builder("foo", "Foo", Metric.ValueType.PERCENT)
+      .setDecimalScale(3)
+      .create();
+    assertThat(metric.getDecimalScale()).isEqualTo(3);
+  }
+
+  @Test
+  public void default_decimal_scale_is_1() {
+    Metric metric = new Metric.Builder("foo", "Foo", Metric.ValueType.FLOAT)
+      .create();
+    assertThat(metric.getDecimalScale()).isEqualTo(1);
+  }
+
+  @Test
+  public void non_decimal_metric_has_no_scale() {
+    Metric metric = new Metric.Builder("foo", "Foo", Metric.ValueType.INT)
+      .create();
+    assertThat(metric.getDecimalScale()).isNull();
+  }
 }
index b4d64fd85514257993e6a1f2a58dd94b0c22a262..e712da3f3124b397079163b589ed5909794b2bc9 100644 (file)
  */
 package org.sonar.api.measures;
 
-import com.google.common.collect.Lists;
-import org.junit.Before;
 import org.junit.Test;
-import org.sonar.api.resources.Directory;
-import org.sonar.api.resources.File;
-import org.sonar.api.resources.Scopes;
-
-import java.util.Collections;
-import java.util.List;
-
-import static junit.framework.Assert.assertNull;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.nullValue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
 
 public class SumChildDistributionFormulaTest {
-  SumChildDistributionFormula formula;
-  FormulaContext context;
-  FormulaData data;
-
-  @Before
-  public void init() {
-    formula = new SumChildDistributionFormula();
-    context = mock(FormulaContext.class);
-    when(context.getResource()).thenReturn(File.create("foo"));
-    data = mock(FormulaData.class);
-  }
-
-  @Test
-  public void testWhenGetChildrenReturnsNull() {
-    when(context.getTargetMetric()).thenReturn(new Metric("foo"));
-    when(data.getChildrenMeasures(new Metric("foo"))).thenReturn(null);
-    assertNull(formula.calculate(data, context));
-  }
-
-  @Test
-  public void testWhenGetChildrenReturnsEmpty() {
-    when(context.getTargetMetric()).thenReturn(new Metric("foo"));
-    when(data.getChildrenMeasures(new Metric("foo"))).thenReturn(Collections.<Measure>emptyList());
-    assertNull(formula.calculate(data, context));
-  }
-
-  @Test
-  public void shouldNotSumDifferentRanges() {
-    Metric m = new Metric("foo", Metric.ValueType.DATA);
-    when(context.getTargetMetric()).thenReturn(m);
-
-    List<Measure> list = Lists.newArrayList(
-      new Measure(m, "1=0;2=2;5=0;10=10;20=2"),
-      new Measure(m, "1=0;2=2;5=0;10=10;30=3")
-      );
-    when(data.getChildrenMeasures(new Metric("foo"))).thenReturn(list);
-    assertThat(formula.calculate(data, context), nullValue());
-  }
 
-  @Test
-  public void shouldSumSameIntRanges() {
-    Metric m = new Metric("foo", Metric.ValueType.DATA);
-    when(context.getTargetMetric()).thenReturn(m);
+  SumChildDistributionFormula underTest = new SumChildDistributionFormula();
 
-    List<Measure> list = Lists.newArrayList(
-      new Measure(m, "1=0;2=2;5=0;10=10;20=2"),
-      new Measure(m, "1=3;2=2;5=3;10=12;20=0")
-      );
-    when(data.getChildrenMeasures(new Metric("foo"))).thenReturn(list);
-    assertThat(formula.calculate(data, context).getData(), is("1=3;2=4;5=3;10=22;20=2"));
+  @Test(expected = UnsupportedOperationException.class)
+  public void fail_if_used_1() {
+    underTest.calculate(null, null);
   }
 
-  @Test
-  public void shouldSumSameDoubleRanges() {
-    initContextWithChildren();
-    assertThat(formula.calculate(data, context).getData(), is("0.5=3;2.5=6"));
+  @Test(expected = UnsupportedOperationException.class)
+  public void fail_if_used_2() {
+    underTest.dependsUponMetrics();
   }
 
-  @Test
-  public void shouldNotPersistWhenScopeLowerThanMinimun() {
-    when(context.getResource()).thenReturn(File.create("org/Foo.java"));
-
-    initContextWithChildren();
-    formula.setMinimumScopeToPersist(Scopes.DIRECTORY);
-
-    Measure distribution = formula.calculate(data, context);
-    assertThat(distribution.getPersistenceMode().useDatabase(), is(false));
-  }
-
-  @Test
-  public void shouldPersistWhenScopeEqualsMinimun() {
-    when(context.getResource()).thenReturn(File.create("org/Foo.java"));
-
-    initContextWithChildren();
-    formula.setMinimumScopeToPersist(Scopes.FILE);
-
-    Measure distribution = formula.calculate(data, context);
-    assertThat(distribution.getPersistenceMode().useDatabase(), is(true));
-  }
-
-  @Test
-  public void shouldPersistWhenScopeHigherThanMinimun() {
-    when(context.getResource()).thenReturn(Directory.create("org/foo"));
-
-    initContextWithChildren();
-    formula.setMinimumScopeToPersist(Scopes.FILE);
-
-    Measure distribution = formula.calculate(data, context);
-    assertThat(distribution.getPersistenceMode().useDatabase(), is(true));
+  @Test(expected = UnsupportedOperationException.class)
+  public void fail_if_used_3() {
+    underTest.getMinimumScopeToPersist();
   }
 
-  private void initContextWithChildren() {
-    Metric m = new Metric("foo", Metric.ValueType.DATA);
-    when(context.getTargetMetric()).thenReturn(m);
-    List<Measure> list = Lists.newArrayList(
-      new Measure(m, "0.5=0;2.5=2"),
-      new Measure(m, "0.5=3;2.5=4")
-      );
-    when(data.getChildrenMeasures(new Metric("foo"))).thenReturn(list);
+  @Test(expected = UnsupportedOperationException.class)
+  public void fail_if_used_4() {
+    underTest.setMinimumScopeToPersist(null);
   }
 }
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/measures/SumChildValuesFormulaTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/measures/SumChildValuesFormulaTest.java
deleted file mode 100644 (file)
index 5bc69ab..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.api.measures;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import java.util.Arrays;
-import java.util.Collections;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class SumChildValuesFormulaTest {
-  private FormulaContext context;
-  private FormulaData data;
-
-  @Before
-  public void before() {
-    context = mock(FormulaContext.class);
-    data = mock(FormulaData.class);
-  }
-
-  @Test
-  public void sumChildValues() {
-    when(context.getTargetMetric()).thenReturn(CoreMetrics.NCLOC);
-    when(data.getChildrenMeasures(CoreMetrics.NCLOC)).thenReturn(
-      Arrays.<Measure>asList(new Measure(CoreMetrics.NCLOC, 100.0), new Measure(CoreMetrics.NCLOC, 50.0)));
-
-    Measure measure = new SumChildValuesFormula(true).calculate(data, context);
-
-    assertThat(measure.getMetric()).isEqualTo(CoreMetrics.NCLOC);
-    assertThat(measure.getValue()).isEqualTo(150.0);
-  }
-
-  @Test
-  public void doNotInsertZero() {
-    when(context.getTargetMetric()).thenReturn(CoreMetrics.NCLOC);
-    when(data.getChildrenMeasures(CoreMetrics.NCLOC)).thenReturn(Collections.<Measure>emptyList());
-
-    Measure measure = new SumChildValuesFormula(false).calculate(data, context);
-
-    assertThat(measure).isNull();
-  }
-
-  @Test
-  public void doInsertZero() {
-    when(context.getTargetMetric()).thenReturn(CoreMetrics.NCLOC);
-    when(data.getChildrenMeasures(CoreMetrics.NCLOC)).thenReturn(Collections.<Measure>emptyList());
-
-    Measure measure = new SumChildValuesFormula(true).calculate(data, context);
-
-    assertThat(measure.getMetric()).isEqualTo(CoreMetrics.NCLOC);
-    assertThat(measure.getValue()).isEqualTo(0.0);
-  }
-}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/measures/WeightedMeanAggregationFormulaTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/measures/WeightedMeanAggregationFormulaTest.java
new file mode 100644 (file)
index 0000000..3aa8d6d
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * 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.api.measures;
+
+import org.junit.Test;
+
+public class WeightedMeanAggregationFormulaTest {
+  WeightedMeanAggregationFormula underTest = new WeightedMeanAggregationFormula(null, false);
+
+  @Test(expected = UnsupportedOperationException.class)
+  public void fail_if_used_1() {
+    underTest.calculate(null, null);
+  }
+
+  @Test(expected = UnsupportedOperationException.class)
+  public void fail_if_used_2() {
+    underTest.dependsUponMetrics();
+  }
+}