aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>2015-08-14 10:42:05 +0200
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>2015-08-24 14:00:31 +0200
commit1d4769cd6fa1e0efad4b83d57581c535a1fab7a2 (patch)
treec32f423915b3be6edfd0483aee99a943d9632825
parentbd01fdc61798dcacd76d0963888a91f20b437507 (diff)
downloadsonarqube-1d4769cd6fa1e0efad4b83d57581c535a1fab7a2.tar.gz
sonarqube-1d4769cd6fa1e0efad4b83d57581c535a1fab7a2.zip
create delegate for Map based impl of MeasureRepository
allows to share the code with Views plugin
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/measure/MapBasedRawMeasureRepository.java194
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureRepositoryImpl.java130
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/measure/MapBasedRawMeasureRepositoryTest.java346
3 files changed, 556 insertions, 114 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MapBasedRawMeasureRepository.java b/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MapBasedRawMeasureRepository.java
new file mode 100644
index 00000000000..c1a82cd5dfb
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MapBasedRawMeasureRepository.java
@@ -0,0 +1,194 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.measure;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.SetMultimap;
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.Nullable;
+import org.sonar.db.rule.RuleDto;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.debt.Characteristic;
+import org.sonar.server.computation.metric.Metric;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.lang.String.format;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Map based implementation of MeasureRepository which supports only raw measures.
+ *
+ * Intended to be used as a delegate of other MeasureRepository implementations (hence the final keyword).
+ */
+public final class MapBasedRawMeasureRepository<T> implements MeasureRepository {
+ private final Function<Component, T> componentToKey;
+ private final Map<T, Map<MeasureKey, Measure>> measures = new HashMap<>();
+
+ public MapBasedRawMeasureRepository(Function<Component, T> componentToKey) {
+ this.componentToKey = requireNonNull(componentToKey);
+ }
+
+ /**
+ * @throws UnsupportedOperationException all the time, not supported
+ */
+ @Override
+ public Optional<Measure> getBaseMeasure(Component component, Metric metric) {
+ throw new UnsupportedOperationException("This implementation of MeasureRepository supports only raw measures");
+ }
+
+ @Override
+ public Optional<Measure> getRawMeasure(final Component component, final Metric metric) {
+ // fail fast
+ requireNonNull(component);
+ requireNonNull(metric);
+
+ return find(component, metric, null, null);
+ }
+
+ @Override
+ public Optional<Measure> getRawMeasure(Component component, Metric metric, RuleDto rule) {
+ // fail fast
+ requireNonNull(component);
+ requireNonNull(metric);
+ requireNonNull(rule);
+
+ return find(component, metric, rule, null);
+ }
+
+ @Override
+ public Optional<Measure> getRawMeasure(Component component, Metric metric, Characteristic characteristic) {
+ // fail fast
+ requireNonNull(component);
+ requireNonNull(metric);
+ requireNonNull(characteristic);
+
+ return find(component, metric, null, characteristic);
+ }
+
+ @Override
+ public void add(Component component, Metric metric, Measure measure) {
+ requireNonNull(component);
+ checkValueTypeConsistency(metric, measure);
+
+ Optional<Measure> existingMeasure = find(component, metric, measure);
+ if (existingMeasure.isPresent()) {
+ throw new UnsupportedOperationException(
+ format(
+ "a measure can be set only once for a specific Component (key=%s), Metric (key=%s)%s. Use update method",
+ component.getKey(),
+ metric.getKey(),
+ buildRuleOrCharacteristicMsgPart(measure)));
+ }
+ add(component, metric, measure, OverridePolicy.OVERRIDE);
+ }
+
+ @Override
+ public void update(Component component, Metric metric, Measure measure) {
+ requireNonNull(component);
+ checkValueTypeConsistency(metric, measure);
+
+ Optional<Measure> existingMeasure = find(component, metric, measure);
+ if (!existingMeasure.isPresent()) {
+ throw new UnsupportedOperationException(
+ format(
+ "a measure can be updated only if one already exists for a specific Component (key=%s), Metric (key=%s)%s. Use add method",
+ component.getKey(),
+ metric.getKey(),
+ buildRuleOrCharacteristicMsgPart(measure)));
+ }
+ add(component, metric, measure, OverridePolicy.OVERRIDE);
+ }
+
+ private static void checkValueTypeConsistency(Metric metric, Measure measure) {
+ checkArgument(
+ measure.getValueType() == Measure.ValueType.NO_VALUE || measure.getValueType() == metric.getType().getValueType(),
+ format(
+ "Measure's ValueType (%s) is not consistent with the Metric's ValueType (%s)",
+ measure.getValueType(), metric.getType().getValueType()));
+ }
+
+ private static String buildRuleOrCharacteristicMsgPart(Measure measure) {
+ if (measure.getRuleId() != null) {
+ return " and rule (id=" + measure.getRuleId() + ")";
+ }
+ if (measure.getCharacteristicId() != null) {
+ return " and Characteristic (id=" + measure.getCharacteristicId() + ")";
+ }
+ return "";
+ }
+
+ @Override
+ public SetMultimap<String, Measure> getRawMeasures(Component component) {
+ T componentKey = componentToKey.apply(component);
+ Map<MeasureKey, Measure> rawMeasures = measures.get(componentKey);
+ if (rawMeasures == null) {
+ return ImmutableSetMultimap.of();
+ }
+
+ ImmutableSetMultimap.Builder<String, Measure> builder = ImmutableSetMultimap.builder();
+ for (Map.Entry<MeasureKey, Measure> entry : rawMeasures.entrySet()) {
+ builder.put(entry.getKey().getMetricKey(), entry.getValue());
+ }
+ return builder.build();
+ }
+
+ private Optional<Measure> find(Component component, Metric metric, @Nullable RuleDto rule, @Nullable Characteristic characteristic) {
+ T componentKey = componentToKey.apply(component);
+ Map<MeasureKey, Measure> measuresPerMetric = measures.get(componentKey);
+ if (measuresPerMetric == null) {
+ return Optional.absent();
+ }
+ return Optional.fromNullable(measuresPerMetric.get(new MeasureKey(metric.getKey(), rule, characteristic)));
+ }
+
+ private Optional<Measure> find(Component component, Metric metric, Measure measure) {
+ T componentKey = componentToKey.apply(component);
+ Map<MeasureKey, Measure> measuresPerMetric = measures.get(componentKey);
+ if (measuresPerMetric == null) {
+ return Optional.absent();
+ }
+ return Optional.fromNullable(measuresPerMetric.get(new MeasureKey(metric.getKey(), measure.getRuleId(), measure.getCharacteristicId())));
+ }
+
+ public void add(Component component, Metric metric, Measure measure, OverridePolicy overridePolicy) {
+ requireNonNull(component);
+ requireNonNull(measure);
+ requireNonNull(measure);
+ requireNonNull(overridePolicy);
+
+ T componentKey = componentToKey.apply(component);
+ Map<MeasureKey, Measure> measuresPerMetric = measures.get(componentKey);
+ if (measuresPerMetric == null) {
+ measuresPerMetric = new HashMap<>();
+ measures.put(componentKey, measuresPerMetric);
+ }
+ MeasureKey key = new MeasureKey(metric.getKey(), measure.getRuleId(), measure.getCharacteristicId());
+ if (!measuresPerMetric.containsKey(key) || overridePolicy == OverridePolicy.OVERRIDE) {
+ measuresPerMetric.put(key, measure);
+ }
+ }
+
+ public enum OverridePolicy {
+ OVERRIDE, DO_NOT_OVERRIDE
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureRepositoryImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureRepositoryImpl.java
index 4a921fcd32e..417fbbcf43e 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureRepositoryImpl.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureRepositoryImpl.java
@@ -19,14 +19,11 @@
*/
package org.sonar.server.computation.measure;
+import com.google.common.base.Function;
import com.google.common.base.Optional;
-import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.SetMultimap;
-import java.util.HashMap;
import java.util.HashSet;
-import java.util.Map;
import java.util.Set;
-import javax.annotation.Nullable;
import org.sonar.batch.protocol.output.BatchReport;
import org.sonar.core.util.CloseableIterator;
import org.sonar.db.DbClient;
@@ -36,15 +33,20 @@ import org.sonar.db.rule.RuleDto;
import org.sonar.server.computation.batch.BatchReportReader;
import org.sonar.server.computation.component.Component;
import org.sonar.server.computation.debt.Characteristic;
+import org.sonar.server.computation.measure.MapBasedRawMeasureRepository.OverridePolicy;
import org.sonar.server.computation.metric.Metric;
import org.sonar.server.computation.metric.MetricRepository;
import org.sonar.server.computation.metric.ReportMetricValidator;
-import static com.google.common.base.Preconditions.checkArgument;
-import static java.lang.String.format;
import static java.util.Objects.requireNonNull;
public class MeasureRepositoryImpl implements MeasureRepository {
+ private final MapBasedRawMeasureRepository<Integer> delegate = new MapBasedRawMeasureRepository<>(new Function<Component, Integer>() {
+ @Override
+ public Integer apply(Component o) {
+ return o.getReportAttributes().getRef();
+ }
+ });
private final DbClient dbClient;
private final BatchReportReader reportReader;
private final BatchMeasureToMeasure batchMeasureToMeasure;
@@ -53,7 +55,6 @@ public class MeasureRepositoryImpl implements MeasureRepository {
private final MeasureDtoToMeasure measureDtoToMeasure = new MeasureDtoToMeasure();
private final Set<Integer> loadedComponents = new HashSet<>();
- private final Map<Integer, Map<MeasureKey, Measure>> measures = new HashMap<>();
public MeasureRepositoryImpl(DbClient dbClient, BatchReportReader reportReader, MetricRepository metricRepository, ReportMetricValidator reportMetricValidator) {
this.dbClient = dbClient;
@@ -77,107 +78,40 @@ public class MeasureRepositoryImpl implements MeasureRepository {
@Override
public Optional<Measure> getRawMeasure(final Component component, final Metric metric) {
- // fail fast
- requireNonNull(component);
- requireNonNull(metric);
-
- Optional<Measure> local = findLocal(component, metric, null, null);
+ Optional<Measure> local = delegate.getRawMeasure(component, metric);
if (local.isPresent()) {
return local;
}
// look up in batch after loading (if not yet loaded) measures from batch
loadBatchMeasuresForComponent(component);
- return findLocal(component, metric, null, null);
+ return delegate.getRawMeasure(component, metric);
}
@Override
public Optional<Measure> getRawMeasure(Component component, Metric metric, RuleDto rule) {
- // fail fast
- requireNonNull(component);
- requireNonNull(metric);
- requireNonNull(rule);
-
- return findLocal(component, metric, rule, null);
+ return delegate.getRawMeasure(component, metric, rule);
}
@Override
public Optional<Measure> getRawMeasure(Component component, Metric metric, Characteristic characteristic) {
- // fail fast
- requireNonNull(component);
- requireNonNull(metric);
- requireNonNull(characteristic);
-
- return findLocal(component, metric, null, characteristic);
+ return delegate.getRawMeasure(component, metric, characteristic);
}
@Override
public void add(Component component, Metric metric, Measure measure) {
- requireNonNull(component);
- checkValueTypeConsistency(metric, measure);
-
- Optional<Measure> existingMeasure = findLocal(component, metric, measure);
- if (existingMeasure.isPresent()) {
- throw new UnsupportedOperationException(
- format(
- "a measure can be set only once for a specific Component (key=%s), Metric (key=%s)%s. Use update method",
- component.getKey(),
- metric.getKey(),
- buildRuleOrCharacteristicMsgPart(measure)
- ));
- }
- addLocal(component, metric, measure, OverridePolicy.OVERRIDE);
+ delegate.add(component, metric, measure);
}
@Override
public void update(Component component, Metric metric, Measure measure) {
- requireNonNull(component);
- checkValueTypeConsistency(metric, measure);
-
- Optional<Measure> existingMeasure = findLocal(component, metric, measure);
- if (!existingMeasure.isPresent()) {
- throw new UnsupportedOperationException(
- format(
- "a measure can be updated only if one already exists for a specific Component (key=%s), Metric (key=%s)%s. Use add method",
- component.getKey(),
- metric.getKey(),
- buildRuleOrCharacteristicMsgPart(measure)
- ));
- }
- addLocal(component, metric, measure, OverridePolicy.OVERRIDE);
- }
-
- private static void checkValueTypeConsistency(Metric metric, Measure measure) {
- checkArgument(
- measure.getValueType() == Measure.ValueType.NO_VALUE || measure.getValueType() == metric.getType().getValueType(),
- format(
- "Measure's ValueType (%s) is not consistent with the Metric's ValueType (%s)",
- measure.getValueType(), metric.getType().getValueType()));
- }
-
- private static String buildRuleOrCharacteristicMsgPart(Measure measure) {
- if (measure.getRuleId() != null) {
- return " and rule (id=" + measure.getRuleId() + ")";
- }
- if (measure.getCharacteristicId() != null) {
- return " and Characteristic (id=" + measure.getCharacteristicId() + ")";
- }
- return "";
+ delegate.update(component, metric, measure);
}
@Override
public SetMultimap<String, Measure> getRawMeasures(Component component) {
loadBatchMeasuresForComponent(component);
- Map<MeasureKey, Measure> rawMeasures = measures.get(component.getReportAttributes().getRef());
- if (rawMeasures == null) {
- return ImmutableSetMultimap.of();
- }
-
- ImmutableSetMultimap.Builder<String, Measure> builder = ImmutableSetMultimap.builder();
- for (Map.Entry<MeasureKey, Measure> entry : rawMeasures.entrySet()) {
- builder.put(entry.getKey().getMetricKey(), entry.getValue());
- }
- return builder.build();
+ return delegate.getRawMeasures(component);
}
private void loadBatchMeasuresForComponent(Component component) {
@@ -191,43 +125,11 @@ public class MeasureRepositoryImpl implements MeasureRepository {
String metricKey = batchMeasure.getMetricKey();
if (reportMetricValidator.validate(metricKey)) {
Metric metric = metricRepository.getByKey(metricKey);
- addLocal(component, metric, batchMeasureToMeasure.toMeasure(batchMeasure, metric).get(), OverridePolicy.DO_NOT_OVERRIDE);
+ delegate.add(component, metric, batchMeasureToMeasure.toMeasure(batchMeasure, metric).get(), OverridePolicy.DO_NOT_OVERRIDE);
}
}
}
loadedComponents.add(component.getReportAttributes().getRef());
}
- private Optional<Measure> findLocal(Component component, Metric metric,
- @Nullable RuleDto rule, @Nullable Characteristic characteristic) {
- Map<MeasureKey, Measure> measuresPerMetric = measures.get(component.getReportAttributes().getRef());
- if (measuresPerMetric == null) {
- return Optional.absent();
- }
- return Optional.fromNullable(measuresPerMetric.get(new MeasureKey(metric.getKey(), rule, characteristic)));
- }
-
- private Optional<Measure> findLocal(Component component, Metric metric, Measure measure) {
- Map<MeasureKey, Measure> measuresPerMetric = measures.get(component.getReportAttributes().getRef());
- if (measuresPerMetric == null) {
- return Optional.absent();
- }
- return Optional.fromNullable(measuresPerMetric.get(new MeasureKey(metric.getKey(), measure.getRuleId(), measure.getCharacteristicId())));
- }
-
- private void addLocal(Component component, Metric metric, Measure measure, OverridePolicy overridePolicy) {
- Map<MeasureKey, Measure> measuresPerMetric = measures.get(component.getReportAttributes().getRef());
- if (measuresPerMetric == null) {
- measuresPerMetric = new HashMap<>();
- measures.put(component.getReportAttributes().getRef(), measuresPerMetric);
- }
- MeasureKey key = new MeasureKey(metric.getKey(), measure.getRuleId(), measure.getCharacteristicId());
- if (!measuresPerMetric.containsKey(key) || overridePolicy == OverridePolicy.OVERRIDE) {
- measuresPerMetric.put(key, measure);
- }
- }
-
- private enum OverridePolicy {
- OVERRIDE, DO_NOT_OVERRIDE
- }
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/measure/MapBasedRawMeasureRepositoryTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/measure/MapBasedRawMeasureRepositoryTest.java
new file mode 100644
index 00000000000..3c1ef09111b
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/measure/MapBasedRawMeasureRepositoryTest.java
@@ -0,0 +1,346 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.computation.measure;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.tngtech.java.junit.dataprovider.DataProvider;
+import com.tngtech.java.junit.dataprovider.DataProviderRunner;
+import com.tngtech.java.junit.dataprovider.UseDataProvider;
+import java.util.List;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbTester;
+import org.sonar.db.rule.RuleDto;
+import org.sonar.server.computation.batch.BatchReportReader;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.component.ReportComponent;
+import org.sonar.server.computation.debt.Characteristic;
+import org.sonar.server.computation.metric.Metric;
+import org.sonar.server.computation.metric.MetricImpl;
+import org.sonar.server.computation.metric.MetricRepository;
+import org.sonar.server.computation.metric.ReportMetricValidator;
+
+import static com.google.common.collect.FluentIterable.from;
+import static java.lang.String.format;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.guava.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+@RunWith(DataProviderRunner.class)
+public class MapBasedRawMeasureRepositoryTest {
+ @Rule
+ public DbTester dbTester = DbTester.create(System2.INSTANCE);
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ private static final String FILE_COMPONENT_KEY = "file cpt key";
+ private static final ReportComponent FILE_COMPONENT = ReportComponent.builder(Component.Type.FILE, 1).setKey(FILE_COMPONENT_KEY).build();
+ private static final ReportComponent OTHER_COMPONENT = ReportComponent.builder(Component.Type.FILE, 2).setKey("some other key").build();
+ private static final String METRIC_KEY_1 = "metric 1";
+ private static final String METRIC_KEY_2 = "metric 2";
+ private final Metric metric1 = mock(Metric.class);
+ private final Metric metric2 = mock(Metric.class);
+ private static final Measure SOME_MEASURE = Measure.newMeasureBuilder().create("some value");
+ private static final RuleDto SOME_RULE = RuleDto.createFor(RuleKey.of("A", "1")).setId(963);
+ private static final Characteristic SOME_CHARACTERISTIC = new Characteristic(741, "key", null);
+
+ private ReportMetricValidator reportMetricValidator = mock(ReportMetricValidator.class);
+
+ private MetricRepository metricRepository = mock(MetricRepository.class);
+ private MapBasedRawMeasureRepository<Integer> underTest = new MapBasedRawMeasureRepository<>(new Function<Component, Integer>() {
+ @Override
+ public Integer apply(Component component) {
+ return component.getReportAttributes().getRef();
+ }
+ });
+
+ private DbClient mockedDbClient = mock(DbClient.class);
+ private BatchReportReader mockBatchReportReader = mock(BatchReportReader.class);
+ private MeasureRepositoryImpl underTestWithMock = new MeasureRepositoryImpl(mockedDbClient, mockBatchReportReader, metricRepository, reportMetricValidator);
+
+ @Before
+ public void setUp() {
+ when(metric1.getKey()).thenReturn(METRIC_KEY_1);
+ when(metric1.getType()).thenReturn(Metric.MetricType.STRING);
+ when(metric2.getKey()).thenReturn(METRIC_KEY_2);
+ when(metric2.getType()).thenReturn(Metric.MetricType.STRING);
+
+ // references to metrics are consistent with DB by design
+ when(metricRepository.getByKey(METRIC_KEY_1)).thenReturn(metric1);
+ when(metricRepository.getByKey(METRIC_KEY_2)).thenReturn(metric2);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void add_throws_NPE_if_Component_argument_is_null() {
+ underTest.add(null, metric1, SOME_MEASURE);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void add_throws_NPE_if_Component_metric_is_null() {
+ underTest.add(FILE_COMPONENT, null, SOME_MEASURE);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void add_throws_NPE_if_Component_measure_is_null() {
+ underTest.add(FILE_COMPONENT, metric1, null);
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void add_throws_UOE_if_measure_already_exists() {
+ underTest.add(FILE_COMPONENT, metric1, SOME_MEASURE);
+ underTest.add(FILE_COMPONENT, metric1, SOME_MEASURE);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void update_throws_NPE_if_Component_argument_is_null() {
+ underTest.update(null, metric1, SOME_MEASURE);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void update_throws_NPE_if_Component_metric_is_null() {
+ underTest.update(FILE_COMPONENT, null, SOME_MEASURE);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void update_throws_NPE_if_Component_measure_is_null() {
+ underTest.update(FILE_COMPONENT, metric1, null);
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void update_throws_UOE_if_measure_does_not_exists() {
+ underTest.update(FILE_COMPONENT, metric1, SOME_MEASURE);
+ }
+
+ private static final List<Measure> MEASURES = ImmutableList.of(
+ Measure.newMeasureBuilder().create(1),
+ Measure.newMeasureBuilder().create(1l),
+ Measure.newMeasureBuilder().create(1d),
+ Measure.newMeasureBuilder().create(true),
+ Measure.newMeasureBuilder().create(false),
+ Measure.newMeasureBuilder().create("sds"),
+ Measure.newMeasureBuilder().create(Measure.Level.OK),
+ Measure.newMeasureBuilder().createNoValue()
+ );
+
+ @DataProvider
+ public static Object[][] measures() {
+ return from(MEASURES).transform(new Function<Measure, Object[]>() {
+ @Nullable
+ @Override
+ public Object[] apply(Measure input) {
+ return new Measure[] {input};
+ }
+ }).toArray(Object[].class);
+ }
+
+ @Test
+ public void add_accepts_NO_VALUE_as_measure_arg() {
+ for (Metric.MetricType metricType : Metric.MetricType.values()) {
+ underTest.add(FILE_COMPONENT, new MetricImpl(1, "key" + metricType, "name" + metricType, metricType), Measure.newMeasureBuilder().createNoValue());
+ }
+ }
+
+ @Test
+ @UseDataProvider("measures")
+ public void update_throws_IAE_if_valueType_of_Measure_is_not_the_same_as_the_Metric_valueType_unless_NO_VALUE(Measure measure) {
+ for (Metric.MetricType metricType : Metric.MetricType.values()) {
+ if (metricType.getValueType() == measure.getValueType() || measure.getValueType() == Measure.ValueType.NO_VALUE) {
+ continue;
+ }
+
+ try {
+ final MetricImpl metric = new MetricImpl(1, "key" + metricType, "name" + metricType, metricType);
+ underTest.add(FILE_COMPONENT, metric, getSomeMeasureByValueType(metricType));
+ underTest.update(FILE_COMPONENT, metric, measure);
+ fail("An IllegalArgumentException should have been raised");
+ } catch (IllegalArgumentException e) {
+ assertThat(e).hasMessage(format(
+ "Measure's ValueType (%s) is not consistent with the Metric's ValueType (%s)",
+ measure.getValueType(), metricType.getValueType()));
+ }
+ }
+ }
+
+ @Test
+ public void update_accepts_NO_VALUE_as_measure_arg() {
+ for (Metric.MetricType metricType : Metric.MetricType.values()) {
+ MetricImpl metric = new MetricImpl(1, "key" + metricType, "name" + metricType, metricType);
+ underTest.add(FILE_COMPONENT, metric, getSomeMeasureByValueType(metricType));
+ underTest.update(FILE_COMPONENT, metric, Measure.newMeasureBuilder().createNoValue());
+ }
+ }
+
+ private Measure getSomeMeasureByValueType(final Metric.MetricType metricType) {
+ return from(MEASURES).filter(new Predicate<Measure>() {
+ @Override
+ public boolean apply(@Nonnull Measure input) {
+ return input.getValueType() == metricType.getValueType();
+ }
+ }).first().get();
+ }
+
+ @Test
+ public void update_supports_updating_to_the_same_value() {
+ underTest.add(FILE_COMPONENT, metric1, SOME_MEASURE);
+ underTest.update(FILE_COMPONENT, metric1, SOME_MEASURE);
+ }
+
+ @Test
+ public void update_updates_the_stored_value() {
+ Measure newMeasure = Measure.updatedMeasureBuilder(SOME_MEASURE).create();
+
+ underTest.add(FILE_COMPONENT, metric1, SOME_MEASURE);
+ underTest.update(FILE_COMPONENT, metric1, newMeasure);
+
+ assertThat(underTest.getRawMeasure(FILE_COMPONENT, metric1).get()).isSameAs(newMeasure);
+ }
+
+ @Test
+ public void update_updates_the_stored_value_for_rule() {
+ Measure initialMeasure = Measure.newMeasureBuilder().forRule(123).createNoValue();
+ Measure newMeasure = Measure.updatedMeasureBuilder(initialMeasure).create();
+
+ underTest.add(FILE_COMPONENT, metric1, initialMeasure);
+ underTest.update(FILE_COMPONENT, metric1, newMeasure);
+
+ assertThat(underTest.getRawMeasures(FILE_COMPONENT).get(metric1.getKey()).iterator().next()).isSameAs(newMeasure);
+ }
+
+ @Test
+ public void update_updates_the_stored_value_for_characteristic() {
+ Measure initialMeasure = Measure.newMeasureBuilder().forCharacteristic(952).createNoValue();
+ Measure newMeasure = Measure.updatedMeasureBuilder(initialMeasure).create();
+
+ underTest.add(FILE_COMPONENT, metric1, initialMeasure);
+ underTest.update(FILE_COMPONENT, metric1, newMeasure);
+
+ assertThat(underTest.getRawMeasures(FILE_COMPONENT).get(metric1.getKey()).iterator().next()).isSameAs(newMeasure);
+ }
+
+ @Test
+ public void getRawMeasure_throws_NPE_without_reading_batch_report_if_component_arg_is_null() {
+ try {
+ underTestWithMock.getRawMeasure(null, metric1);
+ fail("an NPE should have been raised");
+ } catch (NullPointerException e) {
+ verifyNoMoreInteractions(mockBatchReportReader);
+ }
+ }
+
+ @Test
+ public void getRawMeasure_throws_NPE_without_reading_batch_report_if_metric_arg_is_null() {
+ try {
+ underTestWithMock.getRawMeasure(FILE_COMPONENT, null);
+ fail("an NPE should have been raised");
+ } catch (NullPointerException e) {
+ verifyNoMoreInteractions(mockBatchReportReader);
+ }
+ }
+
+ @Test
+ public void getRawMeasure_returns_measure_added_through_add_method() {
+ underTest.add(FILE_COMPONENT, metric1, SOME_MEASURE);
+
+ Optional<Measure> res = underTest.getRawMeasure(FILE_COMPONENT, metric1);
+
+ assertThat(res).isPresent();
+ assertThat(res.get()).isSameAs(SOME_MEASURE);
+
+ // make sure we really match on the specified component and metric
+ assertThat(underTest.getRawMeasure(OTHER_COMPONENT, metric1)).isAbsent();
+ assertThat(underTest.getRawMeasure(FILE_COMPONENT, metric2)).isAbsent();
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void getRawMeasure_for_rule_throws_NPE_if_Component_arg_is_null() {
+ underTest.getRawMeasure(null, metric1, SOME_RULE);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void getRawMeasure_for_rule_throws_NPE_if_Metric_arg_is_null() {
+ underTest.getRawMeasure(FILE_COMPONENT, null, SOME_RULE);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void getRawMeasure_for_rule_throws_NPE_if_Characteristic_arg_is_null() {
+ underTest.getRawMeasure(FILE_COMPONENT, metric1, (RuleDto) null);
+ }
+
+ @Test
+ public void getRawMeasure_for_rule_returns_absent_if_repository_is_empty() {
+ assertThat(underTest.getRawMeasure(FILE_COMPONENT, metric1, SOME_RULE)).isAbsent();
+ }
+
+ @Test
+ public void getRawMeasure_for_rule_returns_measure_for_specified_rule() {
+ Measure measure = Measure.newMeasureBuilder().forRule(SOME_RULE.getId()).createNoValue();
+
+ underTest.add(FILE_COMPONENT, metric1, measure);
+ underTest.add(FILE_COMPONENT, metric1, Measure.newMeasureBuilder().forRule(222).createNoValue());
+
+ assertThat(underTest.getRawMeasure(FILE_COMPONENT, metric1, SOME_RULE).get()).isSameAs(measure);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void getRawMeasure_for_characteristic_throws_NPE_if_Component_arg_is_null() {
+ underTest.getRawMeasure(null, metric1, SOME_CHARACTERISTIC);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void getRawMeasure_for_characteristic_throws_NPE_if_Metric_arg_is_null() {
+ underTest.getRawMeasure(FILE_COMPONENT, null, SOME_CHARACTERISTIC);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void getRawMeasure_for_characteristic_throws_NPE_if_Characteristic_arg_is_null() {
+ underTest.getRawMeasure(FILE_COMPONENT, metric1, (Characteristic) null);
+ }
+
+ @Test
+ public void getRawMeasure_for_characteristic_returns_absent_if_repository_is_empty() {
+ assertThat(underTest.getRawMeasure(FILE_COMPONENT, metric1, SOME_CHARACTERISTIC)).isAbsent();
+ }
+
+ @Test
+ public void getRawMeasure_for_characteristic_returns_measure_for_specified_rule() {
+ when(reportMetricValidator.validate(metric1.getKey())).thenReturn(true);
+ Measure measure = Measure.newMeasureBuilder().forCharacteristic(SOME_CHARACTERISTIC.getId()).createNoValue();
+
+ underTest.add(FILE_COMPONENT, metric1, measure);
+ underTest.add(FILE_COMPONENT, metric1, Measure.newMeasureBuilder().forCharacteristic(333).createNoValue());
+
+ assertThat(underTest.getRawMeasure(FILE_COMPONENT, metric1, SOME_CHARACTERISTIC).get()).isSameAs(measure);
+ }
+
+}