import org.sonar.server.computation.language.PlatformLanguageRepository;
import org.sonar.server.computation.measure.MeasureRepositoryImpl;
import org.sonar.server.computation.measure.MetricCache;
+import org.sonar.server.computation.metric.MetricRepositoryImpl;
import org.sonar.server.computation.period.PeriodsHolderImpl;
import org.sonar.server.computation.step.ComputationStep;
import org.sonar.server.computation.step.ComputationSteps;
return Arrays.asList(
ActivityManager.class,
+ // holders
+ BatchReportDirectoryHolderImpl.class,
TreeRootHolderImpl.class,
+ PeriodsHolderImpl.class,
BatchReportReaderImpl.class,
- BatchReportDirectoryHolderImpl.class,
-
// repositories
PlatformLanguageRepository.class,
+ MetricRepositoryImpl.class,
MeasureRepositoryImpl.class,
EventRepositoryImpl.class,
ProjectSettingsRepository.class,
- PeriodsHolderImpl.class,
DbIdsRepository.class,
// issues
--- /dev/null
+/*
+ * 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.Optional;
+import java.util.Objects;
+import javax.annotation.Nullable;
+import org.sonar.batch.protocol.output.BatchReport;
+import org.sonar.server.computation.metric.Metric;
+
+public class BatchMeasureToMeasure {
+
+ public Optional<Measure> toMeasure(@Nullable BatchReport.Measure batchMeasure, Metric metric) {
+ Objects.requireNonNull(metric);
+ if (batchMeasure == null) {
+ return Optional.absent();
+ }
+
+ String data = batchMeasure.hasStringValue() ? batchMeasure.getStringValue() : null;
+ switch (metric.getMetricType().getValueType()) {
+ case INT:
+ return toIntegerMeasure(batchMeasure, data);
+ case LONG:
+ return toLongMeasure(batchMeasure, data);
+ case DOUBLE:
+ return toDoubleMeasure(batchMeasure, data);
+ case BOOLEAN:
+ return toBooleanMeasure(batchMeasure, data);
+ case STRING:
+ return toStringMeasure(batchMeasure);
+ case LEVEL:
+ return toLevelMeasure(batchMeasure);
+ case NO_VALUE:
+ return toNoValueMeasure(batchMeasure);
+ default:
+ throw new IllegalArgumentException("Unsupported Measure.ValueType " + metric.getMetricType().getValueType());
+ }
+ }
+
+ private static Optional<Measure> toIntegerMeasure(BatchReport.Measure batchMeasure, @Nullable String data) {
+ if (!batchMeasure.hasIntValue()) {
+ return toMeasure(MeasureImpl.createNoValue(), batchMeasure);
+ }
+ return toMeasure(MeasureImpl.create(batchMeasure.getIntValue(), data), batchMeasure);
+ }
+
+ private static Optional<Measure> toLongMeasure(BatchReport.Measure batchMeasure, @Nullable String data) {
+ if (!batchMeasure.hasLongValue()) {
+ return toMeasure(MeasureImpl.createNoValue(), batchMeasure);
+ }
+ return toMeasure(MeasureImpl.create(batchMeasure.getLongValue(), data), batchMeasure);
+ }
+
+ private static Optional<Measure> toDoubleMeasure(BatchReport.Measure batchMeasure, @Nullable String data) {
+ if (!batchMeasure.hasDoubleValue()) {
+ return toMeasure(MeasureImpl.createNoValue(), batchMeasure);
+ }
+ return toMeasure(MeasureImpl.create(batchMeasure.getDoubleValue(), data), batchMeasure);
+ }
+
+ private static Optional<Measure> toBooleanMeasure(BatchReport.Measure batchMeasure, @Nullable String data) {
+ if (!batchMeasure.hasBooleanValue()) {
+ return toMeasure(MeasureImpl.createNoValue(), batchMeasure);
+ }
+ return toMeasure(MeasureImpl.create(batchMeasure.getBooleanValue(), data), batchMeasure);
+ }
+
+ private static Optional<Measure> toStringMeasure(BatchReport.Measure batchMeasure) {
+ if (!batchMeasure.hasStringValue()) {
+ return toMeasure(MeasureImpl.createNoValue(), batchMeasure);
+ }
+ return toMeasure(MeasureImpl.create(batchMeasure.getStringValue()), batchMeasure);
+ }
+
+ private static Optional<Measure> toLevelMeasure(BatchReport.Measure batchMeasure) {
+ if (!batchMeasure.hasStringValue()) {
+ return toMeasure(MeasureImpl.createNoValue(), batchMeasure);
+ }
+ Optional<Measure.Level> level = Measure.Level.toLevel(batchMeasure.getStringValue());
+ if (!level.isPresent()) {
+ return toMeasure(MeasureImpl.createNoValue(), batchMeasure);
+ }
+ return toMeasure(MeasureImpl.create(level.get()), batchMeasure);
+ }
+
+ private static Optional<Measure> toNoValueMeasure(BatchReport.Measure batchMeasure) {
+ return toMeasure(MeasureImpl.createNoValue(), batchMeasure);
+ }
+
+ private static Optional<Measure> toMeasure(MeasureImpl measure, BatchReport.Measure batchMeasure) {
+ if (batchMeasure.hasAlertStatus() && !measure.hasQualityGateStatus()) {
+ Optional<Measure.Level> qualityGateStatus = Measure.Level.toLevel(batchMeasure.getAlertStatus());
+ if (qualityGateStatus.isPresent()) {
+ String text = batchMeasure.hasAlertText() ? batchMeasure.getAlertText() : null;
+ measure.setQualityGateStatus(new Measure.QualityGateStatus(qualityGateStatus.get(), text));
+ }
+ }
+ return Optional.of((Measure) measure);
+ }
+
+}
--- /dev/null
+/*
+ * 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.Objects;
+import com.google.common.base.Optional;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
+import static java.util.Objects.requireNonNull;
+
+public interface Measure {
+
+ enum ValueType {
+ NO_VALUE, BOOLEAN, INT, LONG, DOUBLE, STRING, LEVEL
+ }
+
+ enum Level {
+ OK("Green"),
+ WARN("Orange"),
+ ERROR("Red");
+
+ private final String colorName;
+
+ Level(String colorName) {
+ this.colorName = colorName;
+ }
+
+ public String getColorName() {
+ return colorName;
+ }
+
+ public static Optional<Level> toLevel(@Nullable String level) {
+ if (level == null) {
+ return Optional.absent();
+ }
+ try {
+ return Optional.of(Level.valueOf(level));
+ } catch (IllegalArgumentException e) {
+ return Optional.absent();
+ }
+ }
+ }
+
+ /**
+ * A QualityGate status has a level and an optional describing text.
+ */
+ @Immutable
+ final class QualityGateStatus {
+ private final Level status;
+ @CheckForNull
+ private final String text;
+
+ /**
+ * Creates a QualityGateStatus without a text.
+ */
+ public QualityGateStatus(Level status) {
+ this(status, null);
+ }
+
+ /**
+ * Creates a QualityGateStatus with a optional text.
+ */
+ public QualityGateStatus(Level status, @Nullable String text) {
+ this.status = requireNonNull(status);
+ this.text = text;
+ }
+
+ public Level getStatus() {
+ return status;
+ }
+
+ @CheckForNull
+ public String getText() {
+ return text;
+ }
+
+ @Override
+ public String toString() {
+ return Objects.toStringHelper(this)
+ .add("status", status)
+ .add("text", text)
+ .toString();
+ }
+ }
+
+ /**
+ * The type of value stored in the measure.
+ */
+ ValueType getValueType();
+
+ /**
+ * The value of this measure as a boolean if the type is {@link Measure.ValueType#BOOLEAN}.
+ *
+ * @throws IllegalStateException if the value type of the measure is not {@link Measure.ValueType#BOOLEAN}
+ */
+ boolean getBooleanValue();
+
+ /**
+ * The value of this measure as a int if the type is {@link Measure.ValueType#INT}.
+ *
+ * @throws IllegalStateException if the value type of the measure is not {@link Measure.ValueType#INT}
+ */
+ int getIntValue();
+
+ /**
+ * The value of this measure as a long if the type is {@link Measure.ValueType#LONG}.
+ *
+ * @throws IllegalStateException if the value type of the measure is not {@link Measure.ValueType#LONG}
+ */
+ long getLongValue();
+
+ /**
+ * The value of this measure as a double if the type is {@link Measure.ValueType#DOUBLE}.
+ *
+ * @throws IllegalStateException if the value type of the measure is not {@link Measure.ValueType#DOUBLE}
+ */
+ double getDoubleValue();
+
+ /**
+ * The value of this measure as a String if the type is {@link Measure.ValueType#STRING}.
+ *
+ * @throws IllegalStateException if the value type of the measure is not {@link Measure.ValueType#STRING}
+ */
+ String getStringValue();
+
+ /**
+ * The value of this measure as a Level if the type is {@link Measure.ValueType#LEVEL}.
+ *
+ * @throws IllegalStateException if the value type of the measure is not {@link Measure.ValueType#LEVEL}
+ */
+ Level getLevelValue();
+
+ /**
+ * The data of this measure if it exists.
+ * <p>
+ * If the measure type is {@link Measure.ValueType#STRING}, the value returned by this function is the same as {@link #getStringValue()}.
+ * </p>
+ *
+ * @throws IllegalStateException if the value type of the measure is not {@link Measure.ValueType#BOOLEAN}
+ */
+ @CheckForNull
+ String getData();
+
+ /**
+ * Any Measure, which ever is its value type, can have a QualityGate status.
+ */
+ boolean hasQualityGateStatus();
+
+ /**
+ * The QualityGate status for this measure.
+ * <strong>Don't call this method unless you've checked the result of {@link #hasQualityGateStatus()} first</strong>
+ *
+ * @throws IllegalStateException if the measure has no QualityGate status
+ */
+ QualityGateStatus getQualityGateStatus();
+
+}
--- /dev/null
+/*
+ * 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.Optional;
+import java.util.Objects;
+import javax.annotation.Nullable;
+import org.sonar.core.measure.db.MeasureDto;
+import org.sonar.server.computation.metric.Metric;
+
+import static org.sonar.server.computation.measure.Measure.Level.toLevel;
+
+public class MeasureDtoToMeasure {
+
+ public Optional<Measure> toMeasure(@Nullable MeasureDto measureDto, Metric metric) {
+ Objects.requireNonNull(metric);
+ if (measureDto == null) {
+ return Optional.absent();
+ }
+
+ Double value = measureDto.getValue();
+ String data = measureDto.getData();
+ switch (metric.getMetricType().getValueType()) {
+ case INT:
+ return toIntegerMeasure(measureDto, value, data);
+ case LONG:
+ return toLongMeasure(measureDto, value, data);
+ case DOUBLE:
+ return toDoubleMeasure(measureDto, value, data);
+ case BOOLEAN:
+ return toBooleanMeasure(measureDto, value, data);
+ case STRING:
+ return toStringMeasure(measureDto, data);
+ case LEVEL:
+ return toLevelMeasure(measureDto, data);
+ case NO_VALUE:
+ return toNoValueMeasure(measureDto);
+ default:
+ throw new IllegalArgumentException("Unsupported Measure.ValueType " + metric.getMetricType().getValueType());
+ }
+ }
+
+ private static Optional<Measure> toIntegerMeasure(MeasureDto measureDto, @Nullable Double value, String data) {
+ if (value == null) {
+ return toMeasure(MeasureImpl.createNoValue(), measureDto);
+ }
+ return toMeasure(MeasureImpl.create(value.intValue(), data), measureDto);
+ }
+
+ private static Optional<Measure> toLongMeasure(MeasureDto measureDto, @Nullable Double value, String data) {
+ if (value == null) {
+ return toMeasure(MeasureImpl.createNoValue(), measureDto);
+ }
+ return toMeasure(MeasureImpl.create(value.longValue(), data), measureDto);
+ }
+
+ private static Optional<Measure> toDoubleMeasure(MeasureDto measureDto, @Nullable Double value, String data) {
+ if (value == null) {
+ return toMeasure(MeasureImpl.createNoValue(), measureDto);
+ }
+ return toMeasure(MeasureImpl.create(value.doubleValue(), data), measureDto);
+ }
+
+ private static Optional<Measure> toBooleanMeasure(MeasureDto measureDto, @Nullable Double value, String data) {
+ if (value == null) {
+ return toMeasure(MeasureImpl.createNoValue(), measureDto);
+ }
+ return toMeasure(MeasureImpl.create(value == 1.0d, data), measureDto);
+ }
+
+ private static Optional<Measure> toStringMeasure(MeasureDto measureDto, @Nullable String data) {
+ if (data == null) {
+ return toMeasure(MeasureImpl.createNoValue(), measureDto);
+ }
+ return toMeasure(MeasureImpl.create(data), measureDto);
+ }
+
+ private static Optional<Measure> toLevelMeasure(MeasureDto measureDto, @Nullable String data) {
+ if (data == null) {
+ return toMeasure(MeasureImpl.createNoValue(), measureDto);
+ }
+ Optional<Measure.Level> level = toLevel(data);
+ if (!level.isPresent()) {
+ return toMeasure(MeasureImpl.createNoValue(), measureDto);
+ }
+ return toMeasure(MeasureImpl.create(level.get()), measureDto);
+ }
+
+ private static Optional<Measure> toNoValueMeasure(MeasureDto measureDto) {
+ return toMeasure(MeasureImpl.createNoValue(), measureDto);
+ }
+
+ private static Optional<Measure> toMeasure(MeasureImpl measure, MeasureDto measureDto) {
+ if (measureDto.getAlertStatus() != null && !measure.hasQualityGateStatus()) {
+ Optional<Measure.Level> qualityGateStatus = toLevel(measureDto.getAlertStatus());
+ if (qualityGateStatus.isPresent()) {
+ measure.setQualityGateStatus(new Measure.QualityGateStatus(qualityGateStatus.get(), measureDto.getAlertText()));
+ }
+ }
+
+ return Optional.of((Measure) measure);
+ }
+
+}
--- /dev/null
+/*
+ * 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.Preconditions;
+import java.util.Locale;
+import javax.annotation.Nullable;
+
+import static java.util.Objects.requireNonNull;
+
+public final class MeasureImpl implements Measure {
+
+ private final ValueType valueType;
+ @Nullable
+ private final Double value;
+ @Nullable
+ private final String data;
+ @Nullable
+ private final Level dataLevel;
+ @Nullable
+ private QualityGateStatus qualityGateStatus;
+
+ protected MeasureImpl(ValueType valueType, @Nullable Double value, @Nullable String data, @Nullable Level dataLevel) {
+ this.valueType = valueType;
+ this.value = value;
+ this.data = data;
+ this.dataLevel = dataLevel;
+ }
+
+ public static MeasureImpl create(boolean value, @Nullable String data) {
+ return new MeasureImpl(ValueType.BOOLEAN, value ? 1.0d : 0.0d, data, null);
+ }
+
+ public static MeasureImpl create(int value, @Nullable String data) {
+ return new MeasureImpl(ValueType.INT, (double) value, data, null);
+ }
+
+ public static MeasureImpl create(long value, @Nullable String data) {
+ return new MeasureImpl(ValueType.LONG, (double) value, data, null);
+ }
+
+ public static MeasureImpl create(double value, @Nullable String data) {
+ return new MeasureImpl(ValueType.DOUBLE, value, data, null);
+ }
+
+ public static MeasureImpl create(String value) {
+ return new MeasureImpl(ValueType.STRING, null, requireNonNull(value), null);
+ }
+
+ public static MeasureImpl create(Level level) {
+ return new MeasureImpl(ValueType.LEVEL, null, null, requireNonNull(level));
+ }
+
+ public static MeasureImpl createNoValue() {
+ return new MeasureImpl(ValueType.NO_VALUE, null, null, null);
+ }
+
+ @Override
+ public ValueType getValueType() {
+ return valueType;
+ }
+
+ @Override
+ public boolean getBooleanValue() {
+ checkValueType(ValueType.BOOLEAN);
+ return value == 1.0d;
+ }
+
+ @Override
+ public int getIntValue() {
+ checkValueType(ValueType.INT);
+ return value.intValue();
+ }
+
+ @Override
+ public long getLongValue() {
+ checkValueType(ValueType.LONG);
+ return value.longValue();
+ }
+
+ @Override
+ public double getDoubleValue() {
+ checkValueType(ValueType.DOUBLE);
+ return value;
+ }
+
+ @Override
+ public String getStringValue() {
+ checkValueType(ValueType.STRING);
+ return data;
+ }
+
+ @Override
+ public Level getLevelValue() {
+ checkValueType(ValueType.LEVEL);
+ return dataLevel;
+ }
+
+ @Override
+ public String getData() {
+ return data;
+ }
+
+ private void checkValueType(ValueType expected) {
+ if (valueType != expected) {
+ throw new IllegalStateException(
+ String.format(
+ "value can not be converted to %s because current value type is a %s",
+ expected.toString().toLowerCase(Locale.US),
+ valueType
+ ));
+ }
+ }
+
+ public MeasureImpl setQualityGateStatus(QualityGateStatus qualityGateStatus) {
+ this.qualityGateStatus = requireNonNull(qualityGateStatus, "Can not set a null QualityGate status");
+ return this;
+ }
+
+ @Override
+ public boolean hasQualityGateStatus() {
+ return this.qualityGateStatus != null;
+ }
+
+ @Override
+ public QualityGateStatus getQualityGateStatus() {
+ Preconditions.checkState(qualityGateStatus != null, "Measure does not have an QualityGate status");
+ return this.qualityGateStatus;
+ }
+
+}
*/
package org.sonar.server.computation.measure;
-import org.sonar.api.measures.Metric;
-import org.sonar.batch.protocol.output.BatchReport;
-
import com.google.common.base.Optional;
-import org.sonar.core.measure.db.MeasureDto;
+import java.util.Map;
import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.metric.Metric;
+import org.sonar.server.computation.metric.MetricImpl;
public interface MeasureRepository {
- // FIXME should not expose MeasureDto from DAO layer
- Optional<MeasureDto> findPrevious(Component component, Metric<?> metric);
- // FIXME should not expose Measure from BatchReport
- Optional<BatchReport.Measure> findCurrent(Component component, Metric<?> metric);
+ /**
+ * Retrieves the base measure (ie. the one currently existing in DB) for the specified {@link Component} for
+ * the specified {@link MetricImpl} if it exists.
+ *
+ * @throws NullPointerException if either argument is {@code null}
+ */
+ Optional<Measure> getBaseMeasure(Component component, Metric metric);
+
+ /**
+ * Retrieves the measure created during the current analysis for the specified {@link Component} for the specified
+ * {@link MetricImpl} if it exists (ie. one created by the Compute Engine or the Batch).
+ */
+ Optional<Measure> getRawMeasure(Component component, Metric metric);
+
+ /**
+ * @return {@link Measure}s for the specified {@link Component} mapped by their metric key.
+ */
+ Map<String, Measure> getRawMeasures(Component component);
+
+ /**
+ * Adds the specified measure for the specified Component and Metric. There can be no more than one measure for a
+ * specific combination of Component and Metric.
+ *
+ * @throws NullPointerException if any of the argument is null
+ * @throws UnsupportedOperationException when trying to add a measure when one already exists for the specified Component/Metric paar
+ */
+ void add(Component component, Metric metric, Measure measure);
}
*/
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.ImmutableMap;
import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
import javax.annotation.Nonnull;
-import org.sonar.api.measures.Metric;
+import javax.annotation.Nullable;
import org.sonar.batch.protocol.output.BatchReport;
import org.sonar.core.measure.db.MeasureDto;
import org.sonar.core.persistence.DbSession;
import org.sonar.server.computation.batch.BatchReportReader;
import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.metric.Metric;
+import org.sonar.server.computation.metric.MetricRepository;
import org.sonar.server.db.DbClient;
+import static com.google.common.collect.FluentIterable.from;
+import static java.util.Objects.requireNonNull;
+
public class MeasureRepositoryImpl implements MeasureRepository {
private final DbClient dbClient;
private final BatchReportReader reportReader;
+ private final MeasureDtoToMeasure measureDtoToMeasure = new MeasureDtoToMeasure();
+ private final BatchMeasureToMeasure batchMeasureToMeasure = new BatchMeasureToMeasure();
+ private final Function<BatchReport.Measure, Measure> batchMeasureToMeasureFunction;
+ private final Map<Integer, Map<String, Measure>> measures = new HashMap<>();
- public MeasureRepositoryImpl(DbClient dbClient, BatchReportReader reportReader) {
+ public MeasureRepositoryImpl(DbClient dbClient, BatchReportReader reportReader, final MetricRepository metricRepository) {
this.dbClient = dbClient;
this.reportReader = reportReader;
+
+ this.batchMeasureToMeasureFunction = new Function<BatchReport.Measure, Measure>() {
+ @Nullable
+ @Override
+ public Measure apply(@Nonnull BatchReport.Measure input) {
+ return batchMeasureToMeasure.toMeasure(input, metricRepository.getByKey(input.getMetricKey())).get();
+ }
+ };
}
@Override
- public Optional<MeasureDto> findPrevious(Component component, Metric<?> metric) {
+ public Optional<Measure> getBaseMeasure(Component component, Metric metric) {
+ // fail fast
+ requireNonNull(component);
+ requireNonNull(metric);
+
try (DbSession dbSession = dbClient.openSession(false)) {
- return Optional.fromNullable(
- dbClient.measureDao().findByComponentKeyAndMetricKey(dbSession, component.getKey(), metric.getKey())
- );
+ MeasureDto measureDto = dbClient.measureDao().findByComponentKeyAndMetricKey(dbSession, component.getKey(), metric.getKey());
+ return measureDtoToMeasure.toMeasure(measureDto, metric);
}
}
@Override
- public Optional<BatchReport.Measure> findCurrent(Component component, final Metric<?> metric) {
- return Optional.fromNullable(Iterables.find(
+ public Optional<Measure> getRawMeasure(final Component component, final Metric metric) {
+ // fail fast
+ requireNonNull(component);
+ requireNonNull(metric);
+
+ Optional<Measure> local = findLocal(component, metric);
+ if (local.isPresent()) {
+ return local;
+ }
+ return findInBatch(component, metric);
+ }
+
+ private Optional<Measure> findInBatch(Component component, final Metric metric) {
+ BatchReport.Measure batchMeasure = Iterables.find(
reportReader.readComponentMeasures(component.getRef()),
new Predicate<BatchReport.Measure>() {
@Override
return input.getMetricKey().equals(metric.getKey());
}
}
- , null));
+ , null);
+
+ return batchMeasureToMeasure.toMeasure(batchMeasure, metric);
+ }
+
+ @Override
+ public void add(Component component, Metric metric, Measure measure) {
+ requireNonNull(component);
+ requireNonNull(metric);
+ requireNonNull(measure);
+
+ Optional<Measure> existingMeasure = findLocal(component, metric);
+ if (existingMeasure.isPresent()) {
+ throw new UnsupportedOperationException(
+ String.format(
+ "a measure can be set only once for a specific Component (ref=%s) and Metric (key=%s)",
+ component.getRef(),
+ metric.getKey()
+ ));
+ }
+ addLocal(component, metric, measure);
+ }
+
+ @Override
+ public Map<String, Measure> getRawMeasures(Component component) {
+ Map<String, Measure> rawMeasures = measures.get(component.getRef());
+ ImmutableMap<String, BatchReport.Measure> batchMeasures = from(reportReader.readComponentMeasures(component.getRef()))
+ .uniqueIndex(BatchMeasureToMetricKey.INSTANCE);
+
+ if (rawMeasures == null && batchMeasures.isEmpty()) {
+ return Collections.emptyMap();
+ }
+
+ Map<String, Measure> rawMeasuresFromBatch = Maps.transformValues(batchMeasures, batchMeasureToMeasureFunction);
+ if (rawMeasures == null) {
+ return ImmutableMap.copyOf(rawMeasuresFromBatch);
+ }
+
+ ImmutableMap.Builder<String, Measure> builder = ImmutableMap.builder();
+ builder.putAll(rawMeasuresFromBatch);
+ builder.putAll(rawMeasures);
+ return builder.build();
+ }
+
+ private Optional<Measure> findLocal(Component component, Metric metric) {
+ Map<String, Measure> measuresPerMetric = measures.get(component.getRef());
+ if (measuresPerMetric == null) {
+ return Optional.absent();
+ }
+ return Optional.fromNullable(measuresPerMetric.get(metric.getKey()));
+ }
+
+ private void addLocal(Component component, Metric metric, Measure measure) {
+ Map<String, Measure> measuresPerMetric = measures.get(component.getRef());
+ if (measuresPerMetric == null) {
+ measuresPerMetric = new HashMap<>();
+ measures.put(component.getRef(), measuresPerMetric);
+ }
+ measuresPerMetric.put(metric.getKey(), measure);
+ }
+
+ private enum BatchMeasureToMetricKey implements Function<BatchReport.Measure, String> {
+ INSTANCE;
+
+ @Nullable
+ @Override
+ public String apply(@Nonnull BatchReport.Measure input) {
+ return input.getMetricKey();
+ }
}
}
--- /dev/null
+/*
+ * 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.metric;
+
+import org.sonar.server.computation.measure.Measure;
+
+public interface Metric {
+ /**
+ * The Metric's key is its domain identifier.
+ */
+ String getKey();
+
+ String getName();
+
+ MetricType getMetricType();
+
+ enum MetricType {
+ INT(Measure.ValueType.INT),
+ MILLISEC(Measure.ValueType.INT),
+ RATING(Measure.ValueType.INT),
+ WORK_DUR(Measure.ValueType.LONG),
+ FLOAT(Measure.ValueType.DOUBLE),
+ PERCENT(Measure.ValueType.DOUBLE),
+ BOOL(Measure.ValueType.BOOLEAN),
+ STRING(Measure.ValueType.STRING),
+ DISTRIB(Measure.ValueType.STRING),
+ DATA(Measure.ValueType.STRING),
+ LEVEL(Measure.ValueType.LEVEL);
+
+ private final Measure.ValueType valueType;
+
+ MetricType(Measure.ValueType valueType) {
+ this.valueType = valueType;
+ }
+
+ public Measure.ValueType getValueType() {
+ return valueType;
+ }
+ }
+}
--- /dev/null
+/*
+ * 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.metric;
+
+import java.util.Objects;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
+import static java.util.Objects.requireNonNull;
+
+@Immutable
+public final class MetricImpl implements Metric {
+
+ private final String key;
+ private final String name;
+ private final MetricType metricType;
+
+ public MetricImpl(String key, String name, MetricType metricType) {
+ this.key = requireNonNull(key);
+ this.name = requireNonNull(name);
+ this.metricType = requireNonNull(metricType);
+ }
+
+ @Override
+ public String getKey() {
+ return key;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public MetricType getMetricType() {
+ return metricType;
+ }
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ MetricImpl metric = (MetricImpl) o;
+ return Objects.equals(key, metric.key) &&
+ Objects.equals(metricType, metric.metricType);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(key, metricType);
+ }
+
+ @Override
+ public String toString() {
+ return com.google.common.base.Objects.toStringHelper(this)
+ .add("key", key)
+ .add("name", name)
+ .add("metricType", metricType)
+ .toString();
+ }
+}
--- /dev/null
+/*
+ * 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.metric;
+
+public interface MetricRepository {
+
+ /**
+ * Gets the {@link Metric} with the specific key.
+ * <p>Since it does not make sense to encounter a reference (ie. a key) to a Metric during processing of
+ * a new analysis and not finding it in DB (metrics are never deleted), this method will throw an
+ * IllegalStateException if the metric with the specified key can not be found.</p>
+ *
+ * @throws IllegalStateException if no Metric with the specified key is found
+ * @throws NullPointerException if the specified key is {@code null}
+ */
+ Metric getByKey(String key);
+
+}
--- /dev/null
+/*
+ * 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.metric;
+
+import org.sonar.core.metric.db.MetricDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.db.DbClient;
+
+import static java.util.Objects.requireNonNull;
+
+public class MetricRepositoryImpl implements MetricRepository {
+ private final DbClient dbClient;
+
+ public MetricRepositoryImpl(DbClient dbClient) {
+ this.dbClient = dbClient;
+ }
+
+ @Override
+ public Metric getByKey(String key) {
+ requireNonNull(key);
+
+ try (DbSession dbSession = dbClient.openSession(false)) {
+ MetricDto metricDto = dbClient.metricDao().selectNullableByKey(dbSession, key);
+ if (metricDto == null) {
+ throw new IllegalStateException(String.format("Metric with key '%s' does not exist", key));
+ }
+
+ return toMetric(metricDto);
+ }
+ }
+
+ private static Metric toMetric(MetricDto metricDto) {
+ return new MetricImpl(metricDto.getKey(), metricDto.getShortName(), Metric.MetricType.valueOf(metricDto.getValueType()));
+ }
+
+}
--- /dev/null
+/*
+ * 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.server.computation.metric;
+
+import javax.annotation.ParametersAreNonnullByDefault;
import org.sonar.api.notifications.Notification;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
-import org.sonar.batch.protocol.output.BatchReport;
-import org.sonar.core.measure.db.MeasureDto;
import org.sonar.server.computation.component.Component;
import org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor;
import org.sonar.server.computation.component.TreeRootHolder;
import org.sonar.server.computation.event.Event;
import org.sonar.server.computation.event.EventRepository;
+import org.sonar.server.computation.measure.Measure;
import org.sonar.server.computation.measure.MeasureRepository;
+import org.sonar.server.computation.metric.Metric;
+import org.sonar.server.computation.metric.MetricRepository;
import org.sonar.server.notification.NotificationManager;
public class QualityGateEventsStep implements ComputationStep {
- public static final Logger LOGGER = Loggers.get(QualityGateEventsStep.class);
+ private static final Logger LOGGER = Loggers.get(QualityGateEventsStep.class);
+
private final TreeRootHolder treeRootHolder;
- private final EventRepository eventRepository;
+ private final MetricRepository metricRepository;
private final MeasureRepository measureRepository;
+ private final EventRepository eventRepository;
private final NotificationManager notificationManager;
- public QualityGateEventsStep(TreeRootHolder treeRootHolder, EventRepository eventRepository,
- MeasureRepository measureRepository, NotificationManager notificationManager) {
- this.eventRepository = eventRepository;
- this.measureRepository = measureRepository;
+ public QualityGateEventsStep(TreeRootHolder treeRootHolder,
+ MetricRepository metricRepository, MeasureRepository measureRepository, EventRepository eventRepository,
+ NotificationManager notificationManager) {
this.treeRootHolder = treeRootHolder;
+ this.metricRepository = metricRepository;
+ this.measureRepository = measureRepository;
+ this.eventRepository = eventRepository;
this.notificationManager = notificationManager;
}
}
private void executeForProject(Component project) {
- Optional<BatchReport.Measure> statusMeasure = measureRepository.findCurrent(project, CoreMetrics.ALERT_STATUS);
- if (!statusMeasure.isPresent()) {
- return;
- }
- Optional<GateStatus> status = parse(statusMeasure.get().getAlertStatus());
- if (!status.isPresent()) {
+ Metric metric = metricRepository.getByKey(CoreMetrics.ALERT_STATUS_KEY);
+ Optional<Measure> rawStatus = measureRepository.getRawMeasure(project, metric);
+ if (!rawStatus.isPresent() || !rawStatus.get().hasQualityGateStatus()) {
return;
}
- checkStatusChange(project, status.get(), statusMeasure.get().getAlertText());
+ checkQualityGateStatusChange(project, metric, rawStatus.get().getQualityGateStatus());
}
- private void checkStatusChange(Component project, GateStatus status, String description) {
- Optional<MeasureDto> baseMeasure = measureRepository.findPrevious(project, CoreMetrics.ALERT_STATUS);
+ private void checkQualityGateStatusChange(Component project, Metric metric, Measure.QualityGateStatus rawStatus) {
+ Optional<Measure> baseMeasure = measureRepository.getBaseMeasure(project, metric);
if (!baseMeasure.isPresent()) {
- checkStatus(project, status, description);
+ checkNewQualityGate(project, rawStatus);
return;
}
- Optional<GateStatus> baseStatus = parse(baseMeasure.get().getAlertStatus());
- if (!baseStatus.isPresent()) {
- LOGGER.warn(String.format("Base status for project %s is not a supported value. Can not compute Quality Gate event", project.getKey()));
- checkStatus(project, status, description);
+ if (!baseMeasure.get().hasQualityGateStatus()) {
+ LOGGER.warn(String.format("Previous alterStatus for project %s is not a supported value. Can not compute Quality Gate event", project.getKey()));
+ checkNewQualityGate(project, rawStatus);
return;
}
-
- if (baseStatus.get() != status) {
- // The status has changed
- String label = String.format("%s (was %s)", status.getColorName(), baseStatus.get().getColorName());
- createEvent(project, label, description);
- boolean isNewKo = (baseStatus.get() == GateStatus.OK);
- notifyUsers(project, label, description, status, isNewKo);
+ Measure.QualityGateStatus baseStatus = baseMeasure.get().getQualityGateStatus();
+
+ if (baseStatus.getStatus() != rawStatus.getStatus()) {
+ // The QualityGate status has changed
+ String label = String.format("%s (was %s)", rawStatus.getStatus().getColorName(), baseStatus.getStatus().getColorName());
+ createEvent(project, label, rawStatus.getText());
+ boolean isNewKo = (rawStatus.getStatus() == Measure.Level.OK);
+ notifyUsers(project, label, rawStatus, isNewKo);
}
}
- private void checkStatus(Component project, GateStatus status, String description) {
- if (status != GateStatus.OK) {
+ private void checkNewQualityGate(Component project, Measure.QualityGateStatus rawStatus) {
+ if (rawStatus.getStatus() != Measure.Level.OK) {
// There were no defined alerts before, so this one is a new one
- createEvent(project, status.getColorName(), description);
- notifyUsers(project, status.getColorName(), description, status, true);
- }
- }
-
- private static Optional<GateStatus> parse(@Nullable String alertStatus) {
- if (alertStatus == null) {
- return Optional.absent();
- }
-
- try {
- return Optional.of(GateStatus.valueOf(alertStatus));
- } catch (IllegalArgumentException e) {
- LOGGER.error(String.format("Unsupported alertStatus value '%s' can not be parsed to AlertStatus", alertStatus));
- return Optional.absent();
- }
- }
-
- private enum GateStatus {
- OK("Green"), WARN("Orange"), ERROR("Red");
-
- private String colorName;
-
- GateStatus(String colorName) {
- this.colorName = colorName;
- }
-
- public String getColorName() {
- return colorName;
+ createEvent(project, rawStatus.getStatus().getColorName(), rawStatus.getText());
+ // notifyUsers(project, alertName, alertText, alertLevel, true);
}
}
/**
* @param label "Red (was Orange)"
- * @param description text detail, for example "Coverage < 80%"
- * @param status OK, WARN or ERROR
+ * @param rawStatus OK, WARN or ERROR + optional text
*/
- private void notifyUsers(Component project, String label, String description, GateStatus status, boolean isNewAlert) {
+ private void notifyUsers(Component project, String label, Measure.QualityGateStatus rawStatus, boolean isNewAlert) {
Notification notification = new Notification("alerts")
.setDefaultMessage(String.format("Alert on %s: %s", project.getName(), label))
.setFieldValue("projectName", project.getName())
.setFieldValue("projectKey", project.getKey())
.setFieldValue("projectUuid", project.getUuid())
.setFieldValue("alertName", label)
- .setFieldValue("alertText", description)
- .setFieldValue("alertLevel", status.toString())
+ .setFieldValue("alertText", rawStatus.getText())
+ .setFieldValue("alertLevel", rawStatus.getStatus().toString())
.setFieldValue("isNewAlert", Boolean.toString(isNewAlert));
notificationManager.scheduleForSending(notification);
}
- private void createEvent(Component project, String name, String description) {
+ private void createEvent(Component project, String name, @Nullable String description) {
eventRepository.add(project, Event.createAlert(name, null, description));
}
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.resources.Language;
import org.sonar.api.utils.KeyValueFormat;
-import org.sonar.batch.protocol.output.BatchReport;
import org.sonar.core.UtcDateUtils;
-import org.sonar.core.measure.db.MeasureDto;
import org.sonar.server.computation.component.Component;
import org.sonar.server.computation.component.DepthTraversalTypeAwareVisitor;
import org.sonar.server.computation.component.TreeRootHolder;
import org.sonar.server.computation.event.Event;
import org.sonar.server.computation.event.EventRepository;
import org.sonar.server.computation.language.LanguageRepository;
+import org.sonar.server.computation.measure.Measure;
import org.sonar.server.computation.measure.MeasureRepository;
+import org.sonar.server.computation.metric.MetricRepository;
import org.sonar.server.computation.qualityprofile.QPMeasureData;
import org.sonar.server.computation.qualityprofile.QualityProfile;
public class QualityProfileEventsStep implements ComputationStep {
private final TreeRootHolder treeRootHolder;
+ private final MetricRepository metricRepository;
private final MeasureRepository measureRepository;
private final EventRepository eventRepository;
private final LanguageRepository languageRepository;
public QualityProfileEventsStep(TreeRootHolder treeRootHolder,
- MeasureRepository measureRepository, EventRepository eventRepository, LanguageRepository languageRepository) {
+ MetricRepository metricRepository, MeasureRepository measureRepository, LanguageRepository languageRepository,
+ EventRepository eventRepository) {
this.treeRootHolder = treeRootHolder;
+ this.metricRepository = metricRepository;
this.measureRepository = measureRepository;
this.eventRepository = eventRepository;
this.languageRepository = languageRepository;
}
+
@Override
public void execute() {
new DepthTraversalTypeAwareVisitor(Component.Type.PROJECT, POST_ORDER) {
}
private void executeForProject(Component projectComponent) {
- Optional<MeasureDto> previousMeasure = measureRepository.findPrevious(projectComponent, CoreMetrics.QUALITY_PROFILES);
- if (!previousMeasure.isPresent()) {
+ Optional<Measure> baseMeasure = measureRepository.getBaseMeasure(projectComponent, metricRepository.getByKey(CoreMetrics.QUALITY_PROFILES_KEY));
+ if (!baseMeasure.isPresent()) {
// first analysis -> do not generate events
return;
}
- // Load current profiles
- Optional<BatchReport.Measure> currentMeasure = measureRepository.findCurrent(projectComponent, CoreMetrics.QUALITY_PROFILES);
- if (!currentMeasure.isPresent()) {
+ // Load base profiles
+ Optional<Measure> rawMeasure = measureRepository.getRawMeasure(projectComponent, metricRepository.getByKey(CoreMetrics.QUALITY_PROFILES_KEY));
+ if (!rawMeasure.isPresent()) {
throw new IllegalStateException("Missing measure " + CoreMetrics.QUALITY_PROFILES + " for component " + projectComponent.getRef());
}
- Map<String, QualityProfile> currentProfiles = QPMeasureData.fromJson(currentMeasure.get().getStringValue()).getProfilesByKey();
+ Map<String, QualityProfile> rawProfiles = QPMeasureData.fromJson(rawMeasure.get().getStringValue()).getProfilesByKey();
- Map<String, QualityProfile> previousProfiles = parseJsonData(previousMeasure);
- detectNewOrUpdatedProfiles(projectComponent, previousProfiles, currentProfiles);
- detectNoMoreUsedProfiles(projectComponent, previousProfiles, currentProfiles);
+ Map<String, QualityProfile> baseProfiles = parseJsonData(baseMeasure);
+ detectNewOrUpdatedProfiles(projectComponent, baseProfiles, rawProfiles);
+ detectNoMoreUsedProfiles(projectComponent, baseProfiles, rawProfiles);
}
- private static Map<String, QualityProfile> parseJsonData(Optional<MeasureDto> previousMeasure) {
- String data = previousMeasure.get().getData();
+ private static Map<String, QualityProfile> parseJsonData(Optional<Measure> measure) {
+ String data = measure.get().getStringValue();
if (data == null) {
return Collections.emptyMap();
}
return QPMeasureData.fromJson(data).getProfilesByKey();
}
- private void detectNoMoreUsedProfiles(Component context, Map<String, QualityProfile> previousProfiles, Map<String, QualityProfile> currentProfiles) {
- for (QualityProfile previousProfile : previousProfiles.values()) {
- if (!currentProfiles.containsKey(previousProfile.getQpKey())) {
- markAsRemoved(context, previousProfile);
+ private void detectNoMoreUsedProfiles(Component context, Map<String, QualityProfile> baseProfiles, Map<String, QualityProfile> rawProfiles) {
+ for (QualityProfile baseProfile : baseProfiles.values()) {
+ if (!rawProfiles.containsKey(baseProfile.getQpKey())) {
+ markAsRemoved(context, baseProfile);
}
}
}
- private void detectNewOrUpdatedProfiles(Component component, Map<String, QualityProfile> previousProfiles, Map<String, QualityProfile> currentProfiles) {
- for (QualityProfile profile : currentProfiles.values()) {
- QualityProfile previousProfile = previousProfiles.get(profile.getQpKey());
- if (previousProfile == null) {
+ private void detectNewOrUpdatedProfiles(Component component, Map<String, QualityProfile> baseProfiles, Map<String, QualityProfile> rawProfiles) {
+ for (QualityProfile profile : rawProfiles.values()) {
+ QualityProfile baseProfile = baseProfiles.get(profile.getQpKey());
+ if (baseProfile == null) {
markAsAdded(component, profile);
- } else if (profile.getRulesUpdatedAt().after(previousProfile.getRulesUpdatedAt())) {
- markAsChanged(component, previousProfile, profile);
+ } else if (profile.getRulesUpdatedAt().after(baseProfile.getRulesUpdatedAt())) {
+ markAsChanged(component, baseProfile, profile);
}
}
}
- private void markAsChanged(Component component, QualityProfile previousProfile, QualityProfile profile) {
- Date from = previousProfile.getRulesUpdatedAt();
+ private void markAsChanged(Component component, QualityProfile baseProfile, QualityProfile profile) {
+ Date from = baseProfile.getRulesUpdatedAt();
String data = KeyValueFormat.format(ImmutableSortedMap.of(
"key", profile.getQpKey(),
--- /dev/null
+/*
+ * 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.Optional;
+import org.junit.Test;
+import org.sonar.batch.protocol.output.BatchReport;
+import org.sonar.server.computation.metric.Metric;
+import org.sonar.server.computation.metric.MetricImpl;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.guava.api.Assertions.assertThat;
+
+public class BatchMeasureToMeasureTest {
+ private static final Metric SOME_INT_METRIC = new MetricImpl("key", "name", Metric.MetricType.INT);
+ private static final Metric SOME_LONG_METRIC = new MetricImpl("key", "name", Metric.MetricType.WORK_DUR);
+ private static final Metric SOME_DOUBLE_METRIC = new MetricImpl("key", "name", Metric.MetricType.FLOAT);
+ private static final Metric SOME_STRING_METRIC = new MetricImpl("key", "name", Metric.MetricType.STRING);
+ private static final Metric SOME_BOOLEAN_METRIC = new MetricImpl("key", "name", Metric.MetricType.BOOL);
+ private static final Metric SOME_LEVEL_METRIC = new MetricImpl("key", "name", Metric.MetricType.LEVEL);
+
+ private static final String SOME_DATA = "some_data man!";
+ private static final String SOME_ALERT_TEXT = "some alert text_be_careFul!";
+ private static final BatchReport.Measure EMPTY_BATCH_MEASURE = BatchReport.Measure.newBuilder().build();
+
+ private BatchMeasureToMeasure underTest = new BatchMeasureToMeasure();
+
+ @Test
+ public void toMeasure_returns_absent_for_null_argument() {
+ assertThat(underTest.toMeasure(null, SOME_INT_METRIC)).isAbsent();
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void toMeasure_throws_NPE_if_metric_argument_is_null() {
+ underTest.toMeasure(EMPTY_BATCH_MEASURE, null);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void toMeasure_throws_NPE_if_both_arguments_are_null() {
+ underTest.toMeasure(null, null);
+ }
+
+ @Test
+ public void toMeasure_returns_no_value_if_dto_has_no_string_value_for_LEVEL_Metric() {
+ Optional<Measure> measure = underTest.toMeasure(EMPTY_BATCH_MEASURE, SOME_LEVEL_METRIC);
+
+ assertThat(measure).isPresent();
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.NO_VALUE);
+ }
+
+ @Test
+ public void toMeasure_returns_no_value_if_dto_has_invalid_string_value_for_LEVEL_Metric() {
+ Optional<Measure> measure = underTest.toMeasure(BatchReport.Measure.newBuilder().setStringValue("trololo").build(), SOME_LEVEL_METRIC);
+
+ assertThat(measure).isPresent();
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.NO_VALUE);
+ }
+
+ @Test
+ public void toMeasure_returns_no_value_if_dto_has_value_in_wrong_case_for_LEVEL_Metric() {
+ Optional<Measure> measure = underTest.toMeasure(BatchReport.Measure.newBuilder().setStringValue("waRn").build(), SOME_LEVEL_METRIC);
+
+ assertThat(measure).isPresent();
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.NO_VALUE);
+ }
+
+ @Test
+ public void toMeasure_returns_value_for_LEVEL_Metric() {
+ for (Measure.Level alertStatus : Measure.Level.values()) {
+ verify_toMeasure_returns_value_for_LEVEL_Metric(alertStatus);
+ }
+ }
+
+ private void verify_toMeasure_returns_value_for_LEVEL_Metric(Measure.Level expectedQualityGateStatus) {
+ Optional<Measure> measure = underTest.toMeasure(BatchReport.Measure.newBuilder().setStringValue(expectedQualityGateStatus.name()).build(), SOME_LEVEL_METRIC);
+ assertThat(measure).isPresent();
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.LEVEL);
+ assertThat(measure.get().getLevelValue()).isEqualTo(expectedQualityGateStatus);
+ }
+
+ @Test
+ public void toMeasure_for_LEVEL_Metric_maps_QualityGateStatus() {
+ BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder()
+ .setStringValue(Measure.Level.OK.name())
+ .setAlertStatus(Measure.Level.ERROR.name())
+ .setAlertText(SOME_ALERT_TEXT)
+ .build();
+
+ Optional<Measure> measure = underTest.toMeasure(batchMeasure, SOME_LEVEL_METRIC);
+
+ assertThat(measure).isPresent();
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.LEVEL);
+ assertThat(measure.get().getLevelValue()).isEqualTo(Measure.Level.OK);
+ assertThat(measure.get().getQualityGateStatus().getStatus()).isEqualTo(Measure.Level.ERROR);
+ assertThat(measure.get().getQualityGateStatus().getText()).isEqualTo(SOME_ALERT_TEXT);
+ }
+
+ @Test
+ public void toMeasure_for_LEVEL_Metric_parses_level_from_data() {
+ for (Measure.Level level : Measure.Level.values()) {
+ verify_toMeasure_for_LEVEL_Metric_parses_level_from_data(level);
+ }
+ }
+
+ private void verify_toMeasure_for_LEVEL_Metric_parses_level_from_data(Measure.Level expectedLevel) {
+ BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder()
+ .setStringValue(expectedLevel.name())
+ .build();
+
+ Optional<Measure> measure = underTest.toMeasure(batchMeasure, SOME_LEVEL_METRIC);
+
+ assertThat(measure).isPresent();
+ assertThat(measure.get().getLevelValue()).isEqualTo(expectedLevel);
+ }
+
+ @Test
+ public void toMeasure_returns_no_value_if_dto_has_no_value_for_Int_Metric() {
+ Optional<Measure> measure = underTest.toMeasure(EMPTY_BATCH_MEASURE, SOME_INT_METRIC);
+
+ assertThat(measure.isPresent());
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.NO_VALUE);
+ }
+
+ @Test
+ public void toMeasure_maps_data_and_alert_properties_in_dto_for_Int_Metric() {
+ BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder()
+ .setIntValue(10)
+ .setStringValue(SOME_DATA)
+ .setAlertStatus(Measure.Level.OK.name()).setAlertText(SOME_ALERT_TEXT)
+ .build();
+
+ Optional<Measure> measure = underTest.toMeasure(batchMeasure, SOME_INT_METRIC);
+
+ assertThat(measure.isPresent());
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.INT);
+ assertThat(measure.get().getIntValue()).isEqualTo(10);
+ assertThat(measure.get().getData()).isEqualTo(SOME_DATA);
+ assertThat(measure.get().getQualityGateStatus().getStatus()).isEqualTo(Measure.Level.OK);
+ assertThat(measure.get().getQualityGateStatus().getText()).isEqualTo(SOME_ALERT_TEXT);
+ }
+
+ @Test
+ public void toMeasure_returns_no_value_if_dto_has_no_value_for_Long_Metric() {
+ Optional<Measure> measure = underTest.toMeasure(EMPTY_BATCH_MEASURE, SOME_LONG_METRIC);
+
+ assertThat(measure.isPresent());
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.NO_VALUE);
+ }
+
+ @Test
+ public void toMeasure_returns_long_part_of_value_in_dto_for_Long_Metric() {
+ Optional<Measure> measure = underTest.toMeasure(BatchReport.Measure.newBuilder().setLongValue(15l).build(), SOME_LONG_METRIC);
+
+ assertThat(measure.isPresent());
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.LONG);
+ assertThat(measure.get().getLongValue()).isEqualTo(15);
+ }
+
+ @Test
+ public void toMeasure_maps_data_and_alert_properties_in_dto_for_Long_Metric() {
+ BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder()
+ .setLongValue(10l)
+ .setStringValue(SOME_DATA)
+ .setAlertStatus(Measure.Level.OK.name()).setAlertText(SOME_ALERT_TEXT)
+ .build();
+
+ Optional<Measure> measure = underTest.toMeasure(batchMeasure, SOME_LONG_METRIC);
+
+ assertThat(measure.isPresent());
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.LONG);
+ assertThat(measure.get().getLongValue()).isEqualTo(10);
+ assertThat(measure.get().getData()).isEqualTo(SOME_DATA);
+ assertThat(measure.get().getQualityGateStatus().getStatus()).isEqualTo(Measure.Level.OK);
+ assertThat(measure.get().getQualityGateStatus().getText()).isEqualTo(SOME_ALERT_TEXT);
+ }
+
+ @Test
+ public void toMeasure_returns_no_value_if_dto_has_no_value_for_Double_Metric() {
+ Optional<Measure> measure = underTest.toMeasure(EMPTY_BATCH_MEASURE, SOME_DOUBLE_METRIC);
+
+ assertThat(measure.isPresent());
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.NO_VALUE);
+ }
+
+ @Test
+ public void toMeasure_maps_data_and_alert_properties_in_dto_for_Double_Metric() {
+ BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder()
+ .setDoubleValue(10.6395d)
+ .setStringValue(SOME_DATA)
+ .setAlertStatus(Measure.Level.OK.name()).setAlertText(SOME_ALERT_TEXT)
+ .build();
+
+ Optional<Measure> measure = underTest.toMeasure(batchMeasure, SOME_DOUBLE_METRIC);
+
+ assertThat(measure.isPresent());
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.DOUBLE);
+ assertThat(measure.get().getDoubleValue()).isEqualTo(10.6395d);
+ assertThat(measure.get().getData()).isEqualTo(SOME_DATA);
+ assertThat(measure.get().getQualityGateStatus().getStatus()).isEqualTo(Measure.Level.OK);
+ assertThat(measure.get().getQualityGateStatus().getText()).isEqualTo(SOME_ALERT_TEXT);
+ }
+
+ @Test
+ public void toMeasure_returns_no_value_if_dto_has_no_value_for_Boolean_metric() {
+ Optional<Measure> measure = underTest.toMeasure(EMPTY_BATCH_MEASURE, SOME_BOOLEAN_METRIC);
+
+ assertThat(measure.isPresent());
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.NO_VALUE);
+ }
+
+ @Test
+ public void toMeasure_returns_false_value_if_dto_has_invalid_value_for_Boolean_metric() {
+ verify_toMeasure_returns_false_value_if_dto_has_invalid_value_for_Boolean_metric(true);
+ verify_toMeasure_returns_false_value_if_dto_has_invalid_value_for_Boolean_metric(false);
+ }
+
+ private void verify_toMeasure_returns_false_value_if_dto_has_invalid_value_for_Boolean_metric(boolean expected) {
+ Optional<Measure> measure = underTest.toMeasure(BatchReport.Measure.newBuilder().setBooleanValue(expected).build(), SOME_BOOLEAN_METRIC);
+
+ assertThat(measure.isPresent());
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.BOOLEAN);
+ assertThat(measure.get().getBooleanValue()).isEqualTo(expected);
+ }
+
+ @Test
+ public void toMeasure_maps_data_and_alert_properties_in_dto_for_Boolean_metric() {
+ BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder()
+ .setBooleanValue(true).setStringValue(SOME_DATA).setAlertStatus(Measure.Level.OK.name()).setAlertText(SOME_ALERT_TEXT).build();
+
+ Optional<Measure> measure = underTest.toMeasure(batchMeasure, SOME_BOOLEAN_METRIC);
+
+ assertThat(measure.isPresent());
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.BOOLEAN);
+ assertThat(measure.get().getBooleanValue()).isTrue();
+ assertThat(measure.get().getData()).isEqualTo(SOME_DATA);
+ assertThat(measure.get().getQualityGateStatus().getStatus()).isEqualTo(Measure.Level.OK);
+ assertThat(measure.get().getQualityGateStatus().getText()).isEqualTo(SOME_ALERT_TEXT);
+ }
+
+ @Test
+ public void toMeasure_returns_no_value_if_dto_has_no_value_for_String_Metric() {
+ Optional<Measure> measure = underTest.toMeasure(EMPTY_BATCH_MEASURE, SOME_STRING_METRIC);
+
+ assertThat(measure.isPresent());
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.NO_VALUE);
+ }
+
+ @Test
+ public void toMeasure_maps_alert_properties_in_dto_for_String_Metric() {
+ BatchReport.Measure batchMeasure = BatchReport.Measure.newBuilder()
+ .setStringValue(SOME_DATA)
+ .setAlertStatus(Measure.Level.OK.name()).setAlertText(SOME_ALERT_TEXT)
+ .build();
+
+ Optional<Measure> measure = underTest.toMeasure(batchMeasure, SOME_STRING_METRIC);
+
+ assertThat(measure.isPresent());
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.STRING);
+ assertThat(measure.get().getStringValue()).isEqualTo(SOME_DATA);
+ assertThat(measure.get().getData()).isEqualTo(SOME_DATA);
+ assertThat(measure.get().getQualityGateStatus().getStatus()).isEqualTo(Measure.Level.OK);
+ assertThat(measure.get().getQualityGateStatus().getText()).isEqualTo(SOME_ALERT_TEXT);
+ }
+
+}
--- /dev/null
+/*
+ * 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.Optional;
+import org.junit.Test;
+import org.sonar.core.measure.db.MeasureDto;
+import org.sonar.server.computation.measure.Measure.Level;
+import org.sonar.server.computation.metric.Metric;
+import org.sonar.server.computation.metric.MetricImpl;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.guava.api.Assertions.assertThat;
+
+public class MeasureDtoToMeasureTest {
+ private static final Metric SOME_INT_METRIC = new MetricImpl("key", "name", Metric.MetricType.INT);
+ private static final Metric SOME_LONG_METRIC = new MetricImpl("key", "name", Metric.MetricType.WORK_DUR);
+ private static final Metric SOME_DOUBLE_METRIC = new MetricImpl("key", "name", Metric.MetricType.FLOAT);
+ private static final Metric SOME_STRING_METRIC = new MetricImpl("key", "name", Metric.MetricType.STRING);
+ private static final Metric SOME_BOOLEAN_METRIC = new MetricImpl("key", "name", Metric.MetricType.BOOL);
+ private static final Metric SOME_LEVEL_METRIC = new MetricImpl("key", "name", Metric.MetricType.LEVEL);
+
+ private static final String SOME_DATA = "some_data man!";
+ private static final String SOME_ALERT_TEXT = "some alert text_be_careFul!";
+ private static final MeasureDto EMPTY_MEASURE_DTO = new MeasureDto();
+
+ private MeasureDtoToMeasure underTest = new MeasureDtoToMeasure();
+
+ @Test
+ public void toMeasure_returns_absent_for_null_argument() {
+ assertThat(underTest.toMeasure(null, SOME_INT_METRIC)).isAbsent();
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void toMeasure_throws_NPE_if_metric_argument_is_null() {
+ underTest.toMeasure(EMPTY_MEASURE_DTO, null);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void toMeasure_throws_NPE_if_both_arguments_are_null() {
+ underTest.toMeasure(null, null);
+ }
+
+ @Test
+ public void toMeasure_returns_no_value_if_dto_has_no_data_for_Level_Metric() {
+ Optional<Measure> measure = underTest.toMeasure(EMPTY_MEASURE_DTO, SOME_LEVEL_METRIC);
+ assertThat(measure).isPresent();
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.NO_VALUE);
+ }
+
+ @Test
+ public void toMeasure_returns_no_value_if_dto_has_invalid_data_for_Level_Metric() {
+ Optional<Measure> measure = underTest.toMeasure(new MeasureDto().setData("trololo"), SOME_LEVEL_METRIC);
+ assertThat(measure).isPresent();
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.NO_VALUE);
+ }
+
+ @Test
+ public void toMeasure_returns_no_value_if_dta_has_data_in_wrong_case_for_Level_Metric() {
+ Optional<Measure> measure = underTest.toMeasure(new MeasureDto().setData("waRn"), SOME_LEVEL_METRIC);
+ assertThat(measure).isPresent();
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.NO_VALUE);
+ }
+
+ @Test
+ public void toMeasure_returns_no_QualityGateStatus_if_dto_has_no_alertStatus_for_Level_Metric() {
+ Optional<Measure> measure = underTest.toMeasure(EMPTY_MEASURE_DTO, SOME_STRING_METRIC);
+ assertThat(measure).isPresent();
+ assertThat(measure.get().hasQualityGateStatus()).isFalse();
+ }
+
+ @Test
+ public void toMeasure_returns_no_QualityGateStatus_if_alertStatus_has_invalid_data_for_Level_Metric() {
+ Optional<Measure> measure = underTest.toMeasure(new MeasureDto().setData("trololo"), SOME_STRING_METRIC);
+ assertThat(measure).isPresent();
+ assertThat(measure.get().hasQualityGateStatus()).isFalse();
+ }
+
+ @Test
+ public void toMeasure_returns_no_QualityGateStatus_if_alertStatus_has_data_in_wrong_case_for_Level_Metric() {
+ Optional<Measure> measure = underTest.toMeasure(new MeasureDto().setData("waRn"), SOME_STRING_METRIC);
+ assertThat(measure).isPresent();
+ assertThat(measure.get().hasQualityGateStatus()).isFalse();
+ }
+
+ @Test
+ public void toMeasure_returns_value_for_LEVEL_Metric() {
+ for (Level level : Level.values()) {
+ verify_toMeasure_returns_value_for_LEVEL_Metric(level);
+ }
+ }
+
+ private void verify_toMeasure_returns_value_for_LEVEL_Metric(Level expectedLevel) {
+ Optional<Measure> measure = underTest.toMeasure(new MeasureDto().setData(expectedLevel.name()), SOME_LEVEL_METRIC);
+ assertThat(measure).isPresent();
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.LEVEL);
+ assertThat(measure.get().getLevelValue()).isEqualTo(expectedLevel);
+ }
+
+ @Test
+ public void toMeasure_for_LEVEL_Metric_can_have_an_qualityGateStatus() {
+ MeasureDto measureDto = new MeasureDto().setData(Level.OK.name()).setAlertStatus(Level.ERROR.name()).setAlertText(SOME_ALERT_TEXT);
+
+ Optional<Measure> measure = underTest.toMeasure(measureDto, SOME_LEVEL_METRIC);
+
+ assertThat(measure).isPresent();
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.LEVEL);
+ assertThat(measure.get().getLevelValue()).isEqualTo(Level.OK);
+ assertThat(measure.get().getQualityGateStatus().getStatus()).isEqualTo(Level.ERROR);
+ assertThat(measure.get().getQualityGateStatus().getText()).isEqualTo(SOME_ALERT_TEXT);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void toMeasure_for_LEVEL_Metric_ignores_data() {
+ MeasureDto measureDto = new MeasureDto().setAlertStatus(Level.ERROR.name()).setData(SOME_DATA);
+
+ Optional<Measure> measure = underTest.toMeasure(measureDto, SOME_LEVEL_METRIC);
+
+ assertThat(measure).isPresent();
+ measure.get().getStringValue();
+ }
+
+ @Test
+ public void toMeasure_returns_no_value_if_dto_has_no_value_for_Int_Metric() {
+ Optional<Measure> measure = underTest.toMeasure(EMPTY_MEASURE_DTO, SOME_INT_METRIC);
+
+ assertThat(measure.isPresent());
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.NO_VALUE);
+ }
+
+ @Test
+ public void toMeasure_returns_int_part_of_value_in_dto_for_Int_Metric() {
+ Optional<Measure> measure = underTest.toMeasure(new MeasureDto().setValue(1.5d), SOME_INT_METRIC);
+
+ assertThat(measure.isPresent());
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.INT);
+ assertThat(measure.get().getIntValue()).isEqualTo(1);
+ }
+
+ @Test
+ public void toMeasure_maps_data_and_alert_properties_in_dto_for_Int_Metric() {
+ MeasureDto measureDto = new MeasureDto().setValue(10d).setData(SOME_DATA).setAlertStatus(Level.OK.name()).setAlertText(SOME_ALERT_TEXT);
+
+ Optional<Measure> measure = underTest.toMeasure(measureDto, SOME_INT_METRIC);
+
+ assertThat(measure.isPresent());
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.INT);
+ assertThat(measure.get().getIntValue()).isEqualTo(10);
+ assertThat(measure.get().getData()).isEqualTo(SOME_DATA);
+ assertThat(measure.get().getQualityGateStatus().getStatus()).isEqualTo(Level.OK);
+ assertThat(measure.get().getQualityGateStatus().getText()).isEqualTo(SOME_ALERT_TEXT);
+ }
+
+ @Test
+ public void toMeasure_returns_no_value_if_dto_has_no_value_for_Long_Metric() {
+ Optional<Measure> measure = underTest.toMeasure(EMPTY_MEASURE_DTO, SOME_LONG_METRIC);
+
+ assertThat(measure.isPresent());
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.NO_VALUE);
+ }
+
+ @Test
+ public void toMeasure_returns_long_part_of_value_in_dto_for_Long_Metric() {
+ Optional<Measure> measure = underTest.toMeasure(new MeasureDto().setValue(1.5d), SOME_LONG_METRIC);
+
+ assertThat(measure.isPresent());
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.LONG);
+ assertThat(measure.get().getLongValue()).isEqualTo(1);
+ }
+
+ @Test
+ public void toMeasure_maps_data_and_alert_properties_in_dto_for_Long_Metric() {
+ MeasureDto measureDto = new MeasureDto().setValue(10d).setData(SOME_DATA).setAlertStatus(Level.OK.name()).setAlertText(SOME_ALERT_TEXT);
+
+ Optional<Measure> measure = underTest.toMeasure(measureDto, SOME_LONG_METRIC);
+
+ assertThat(measure.isPresent());
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.LONG);
+ assertThat(measure.get().getLongValue()).isEqualTo(10);
+ assertThat(measure.get().getData()).isEqualTo(SOME_DATA);
+ assertThat(measure.get().getQualityGateStatus().getStatus()).isEqualTo(Level.OK);
+ assertThat(measure.get().getQualityGateStatus().getText()).isEqualTo(SOME_ALERT_TEXT);
+ }
+
+ @Test
+ public void toMeasure_returns_no_value_if_dto_has_no_value_for_Double_Metric() {
+ Optional<Measure> measure = underTest.toMeasure(EMPTY_MEASURE_DTO, SOME_DOUBLE_METRIC);
+
+ assertThat(measure.isPresent());
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.NO_VALUE);
+ }
+
+ @Test
+ public void toMeasure_maps_data_and_alert_properties_in_dto_for_Double_Metric() {
+ MeasureDto measureDto = new MeasureDto().setValue(10.6395d).setData(SOME_DATA).setAlertStatus(Level.OK.name()).setAlertText(SOME_ALERT_TEXT);
+
+ Optional<Measure> measure = underTest.toMeasure(measureDto, SOME_DOUBLE_METRIC);
+
+ assertThat(measure.isPresent());
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.DOUBLE);
+ 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);
+ }
+
+ @Test
+ public void toMeasure_returns_no_value_if_dto_has_no_value_for_Boolean_metric() {
+ Optional<Measure> measure = underTest.toMeasure(EMPTY_MEASURE_DTO, SOME_BOOLEAN_METRIC);
+
+ assertThat(measure.isPresent());
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.NO_VALUE);
+ }
+
+ @Test
+ public void toMeasure_returns_false_value_if_dto_has_invalid_value_for_Boolean_metric() {
+ Optional<Measure> measure = underTest.toMeasure(new MeasureDto().setValue(1.987d), SOME_BOOLEAN_METRIC);
+
+ assertThat(measure.isPresent());
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.BOOLEAN);
+ assertThat(measure.get().getBooleanValue()).isFalse();
+ }
+
+ @Test
+ public void toMeasure_maps_data_and_alert_properties_in_dto_for_Boolean_metric() {
+ MeasureDto measureDto = new MeasureDto().setValue(1d).setData(SOME_DATA).setAlertStatus(Level.OK.name()).setAlertText(SOME_ALERT_TEXT);
+
+ Optional<Measure> measure = underTest.toMeasure(measureDto, SOME_BOOLEAN_METRIC);
+
+ assertThat(measure.isPresent());
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.BOOLEAN);
+ assertThat(measure.get().getBooleanValue()).isTrue();
+ assertThat(measure.get().getData()).isEqualTo(SOME_DATA);
+ assertThat(measure.get().getQualityGateStatus().getStatus()).isEqualTo(Level.OK);
+ assertThat(measure.get().getQualityGateStatus().getText()).isEqualTo(SOME_ALERT_TEXT);
+ }
+
+ @Test
+ public void toMeasure_returns_no_value_if_dto_has_no_value_for_String_Metric() {
+ Optional<Measure> measure = underTest.toMeasure(EMPTY_MEASURE_DTO, SOME_STRING_METRIC);
+
+ assertThat(measure.isPresent());
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.NO_VALUE);
+ }
+
+ @Test
+ public void toMeasure_maps_alert_properties_in_dto_for_String_Metric() {
+ MeasureDto measureDto = new MeasureDto().setData(SOME_DATA).setAlertStatus(Level.OK.name()).setAlertText(SOME_ALERT_TEXT);
+
+ Optional<Measure> measure = underTest.toMeasure(measureDto, SOME_STRING_METRIC);
+
+ assertThat(measure.isPresent());
+ assertThat(measure.get().getValueType()).isEqualTo(Measure.ValueType.STRING);
+ assertThat(measure.get().getStringValue()).isEqualTo(SOME_DATA);
+ assertThat(measure.get().getData()).isEqualTo(SOME_DATA);
+ assertThat(measure.get().getQualityGateStatus().getStatus()).isEqualTo(Level.OK);
+ assertThat(measure.get().getQualityGateStatus().getText()).isEqualTo(SOME_ALERT_TEXT);
+ }
+}
--- /dev/null
+/*
+ * 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.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.Test;
+import org.junit.runner.RunWith;
+import org.sonar.server.computation.measure.Measure.ValueType;
+
+import static com.google.common.collect.FluentIterable.from;
+import static org.assertj.core.api.Assertions.assertThat;
+
+@RunWith(DataProviderRunner.class)
+public class MeasureImplTest {
+
+ private static final MeasureImpl INT_MEASURE = MeasureImpl.create((int) 1, null);
+ private static final MeasureImpl LONG_MEASURE = MeasureImpl.create(1l, null);
+ private static final MeasureImpl DOUBLE_MEASURE = MeasureImpl.create(1d, null);
+ private static final MeasureImpl STRING_MEASURE = MeasureImpl.create("some_sT ring");
+ private static final MeasureImpl TRUE_MEASURE = MeasureImpl.create(true, null);
+ private static final MeasureImpl FALSE_MEASURE = MeasureImpl.create(false, null);
+ private static final MeasureImpl LEVEL_MEASURE = MeasureImpl.create(Measure.Level.OK);
+ private static final MeasureImpl NO_VALUE_MEASURE = MeasureImpl.createNoValue();
+
+ private static final List<MeasureImpl> MEASURES = ImmutableList.of(
+ INT_MEASURE, LONG_MEASURE, DOUBLE_MEASURE, STRING_MEASURE, TRUE_MEASURE, FALSE_MEASURE, NO_VALUE_MEASURE, LEVEL_MEASURE
+ );
+
+ @Test(expected = NullPointerException.class)
+ public void create_from_String_throws_NPE_if_arg_is_null() {
+ MeasureImpl.create((String) null);
+ }
+
+ @DataProvider
+ public static Object[][] all_but_INT_MEASURE() {
+ return getMeasuresExcept(ValueType.INT);
+ }
+
+ @DataProvider
+ public static Object[][] all_but_LONG_MEASURE() {
+ return getMeasuresExcept(ValueType.LONG);
+ }
+
+ @DataProvider
+ public static Object[][] all_but_DOUBLE_MEASURE() {
+ return getMeasuresExcept(ValueType.DOUBLE);
+ }
+
+ @DataProvider
+ public static Object[][] all_but_BOOLEAN_MEASURE() {
+ return getMeasuresExcept(ValueType.BOOLEAN);
+ }
+
+ @DataProvider
+ public static Object[][] all_but_STRING_MEASURE() {
+ return getMeasuresExcept(ValueType.STRING);
+ }
+
+ @DataProvider
+ public static Object[][] all_but_LEVEL_MEASURE() {
+ return getMeasuresExcept(ValueType.LEVEL);
+ }
+
+ @DataProvider
+ public static Object[][] all() {
+ return from(MEASURES).transform(WrapInArray.INSTANCE).toArray(MeasureImpl[].class);
+ }
+
+ private static MeasureImpl[][] getMeasuresExcept(final ValueType valueType) {
+ return from(MEASURES)
+ .filter(new Predicate<MeasureImpl>() {
+ @Override
+ public boolean apply(@Nonnull MeasureImpl input) {
+ return input.getValueType() != valueType;
+ }
+ }).transform(WrapInArray.INSTANCE)
+ .toArray(MeasureImpl[].class);
+ }
+
+ @Test
+ public void create_from_int_has_INT_value_type() {
+ assertThat(INT_MEASURE.getValueType()).isEqualTo(ValueType.INT);
+ }
+
+ @Test
+ public void create_from_long_has_LONG_value_type() {
+ assertThat(LONG_MEASURE.getValueType()).isEqualTo(ValueType.LONG);
+ }
+
+ @Test
+ public void create_from_double_has_DOUBLE_value_type() {
+ assertThat(DOUBLE_MEASURE.getValueType()).isEqualTo(ValueType.DOUBLE);
+ }
+
+ @Test
+ public void create_from_boolean_has_BOOLEAN_value_type() {
+ assertThat(TRUE_MEASURE.getValueType()).isEqualTo(ValueType.BOOLEAN);
+ assertThat(FALSE_MEASURE.getValueType()).isEqualTo(ValueType.BOOLEAN);
+ }
+
+ @Test
+ public void create_from_String_has_STRING_value_type() {
+ assertThat(STRING_MEASURE.getValueType()).isEqualTo(ValueType.STRING);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ @UseDataProvider("all_but_INT_MEASURE")
+ public void getIntValue_throws_ISE_for_all_value_types_except_INT(Measure measure) {
+ measure.getIntValue();
+ }
+
+ @Test
+ public void getIntValue_returns_value_for_INT_value_type() {
+ assertThat(INT_MEASURE.getIntValue()).isEqualTo(1);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ @UseDataProvider("all_but_LONG_MEASURE")
+ public void getLongValue_throws_ISE_for_all_value_types_except_LONG(Measure measure) {
+ measure.getLongValue();
+ }
+
+ @Test
+ public void getLongValue_returns_value_for_LONG_value_type() {
+ assertThat(LONG_MEASURE.getLongValue()).isEqualTo(1);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ @UseDataProvider("all_but_DOUBLE_MEASURE")
+ public void getDoubleValue_throws_ISE_for_all_value_types_except_DOUBLE(Measure measure) {
+ measure.getDoubleValue();
+ }
+
+ @Test
+ public void getDoubleValue_returns_value_for_DOUBLE_value_type() {
+ assertThat(DOUBLE_MEASURE.getDoubleValue()).isEqualTo(1d);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ @UseDataProvider("all_but_BOOLEAN_MEASURE")
+ public void getBooleanValue_throws_ISE_for_all_value_types_except_BOOLEAN(Measure measure) {
+ measure.getBooleanValue();
+ }
+
+ @Test
+ public void getBooleanValue_returns_value_for_BOOLEAN_value_type() {
+ assertThat(TRUE_MEASURE.getBooleanValue()).isTrue();
+ assertThat(FALSE_MEASURE.getBooleanValue()).isFalse();
+ }
+
+ @Test(expected = IllegalStateException.class)
+ @UseDataProvider("all_but_STRING_MEASURE")
+ public void getStringValue_throws_ISE_for_all_value_types_except_STRING(Measure measure) {
+ measure.getStringValue();
+ }
+
+ @Test(expected = IllegalStateException.class)
+ @UseDataProvider("all_but_LEVEL_MEASURE")
+ public void getLevelValue_throws_ISE_for_all_value_types_except_LEVEL(Measure measure) {
+ measure.getLevelValue();
+ }
+
+ @Test
+ public void getData_returns_null_for_NO_VALUE_value_type() {
+ assertThat(NO_VALUE_MEASURE.getData()).isNull();
+ }
+
+ @Test
+ @UseDataProvider("all_but_STRING_MEASURE")
+ public void getData_returns_null_for_all_value_types_but_STRING_when_not_set(Measure measure) {
+ assertThat(measure.getData()).isNull();
+ }
+
+ @Test
+ public void getData_returns_value_for_STRING_value_type() {
+ assertThat(STRING_MEASURE.getData()).isEqualTo(STRING_MEASURE.getStringValue());
+ }
+
+ @Test
+ @UseDataProvider("all")
+ public void hasAlertStatus_returns_false_for_all_value_types_when_not_set(Measure measure) {
+ assertThat(measure.hasQualityGateStatus()).isFalse();
+ }
+
+ @Test(expected = IllegalStateException.class)
+ @UseDataProvider("all")
+ public void getAlertStatus_throws_ISE_for_all_value_types_when_not_set(Measure measure) {
+ measure.getQualityGateStatus();
+ }
+
+ @Test
+ public void getAlertStatus_returns_argument_from_setAlertStatus() {
+ Measure.QualityGateStatus someStatus = new Measure.QualityGateStatus(Measure.Level.OK);
+
+ assertThat(MeasureImpl.create(true, null).setQualityGateStatus(someStatus).getQualityGateStatus()).isEqualTo(someStatus);
+ assertThat(MeasureImpl.create(false, null).setQualityGateStatus(someStatus).getQualityGateStatus()).isEqualTo(someStatus);
+ assertThat(MeasureImpl.create((int) 1, null).setQualityGateStatus(someStatus).getQualityGateStatus()).isEqualTo(someStatus);
+ assertThat(MeasureImpl.create((long) 1, null).setQualityGateStatus(someStatus).getQualityGateStatus()).isEqualTo(someStatus);
+ assertThat(MeasureImpl.create((double) 1, null).setQualityGateStatus(someStatus).getQualityGateStatus()).isEqualTo(someStatus);
+ assertThat(MeasureImpl.create("str").setQualityGateStatus(someStatus).getQualityGateStatus()).isEqualTo(someStatus);
+ assertThat(MeasureImpl.create(Measure.Level.OK).setQualityGateStatus(someStatus).getQualityGateStatus()).isEqualTo(someStatus);
+ }
+
+ @Test(expected = NullPointerException.class)
+ @UseDataProvider("all")
+ public void setAlertStatus_throws_NPE_if_arg_is_null(MeasureImpl measure) {
+ measure.setQualityGateStatus(null);
+ }
+
+ @Test
+ public void getData_returns_argument_from_factory_method() {
+ String someData = "lololool";
+
+ assertThat(MeasureImpl.create(true, someData).getData()).isEqualTo(someData);
+ assertThat(MeasureImpl.create(false, someData).getData()).isEqualTo(someData);
+ assertThat(MeasureImpl.create((int) 1, someData).getData()).isEqualTo(someData);
+ assertThat(MeasureImpl.create((long) 1, someData).getData()).isEqualTo(someData);
+ assertThat(MeasureImpl.create((double) 1, someData).getData()).isEqualTo(someData);
+ }
+
+ @Test
+ public void measure_of_value_type_LEVEL_has_no_data() {
+ assertThat(LEVEL_MEASURE.getData()).isNull();
+ }
+
+ private enum WrapInArray implements Function<MeasureImpl, MeasureImpl[]> {
+ INSTANCE;
+
+ @Nullable
+ @Override
+ public MeasureImpl[] apply(@Nonnull MeasureImpl input) {
+ return new MeasureImpl[] {input};
+ }
+ }
+}
--- /dev/null
+/*
+ * 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.Optional;
+import com.google.common.collect.ImmutableList;
+import javax.annotation.CheckForNull;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.batch.protocol.output.BatchReport;
+import org.sonar.core.measure.db.MeasureDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.server.component.db.ComponentDao;
+import org.sonar.server.component.db.SnapshotDao;
+import org.sonar.server.computation.batch.BatchReportReader;
+import org.sonar.server.computation.batch.BatchReportReaderRule;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.component.DumbComponent;
+import org.sonar.server.computation.metric.Metric;
+import org.sonar.server.computation.metric.MetricRepository;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.measure.persistence.MeasureDao;
+import org.sonar.server.metric.persistence.MetricDao;
+
+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.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+public class MeasureRepositoryImplTest {
+ @ClassRule
+ public static final DbTester dbTester = new DbTester();
+ public static final String SOME_DATA = "some data";
+ @Rule
+ public BatchReportReaderRule reportReader = new BatchReportReaderRule();
+
+ private static final String FILE_COMPONENT_KEY = "file cpt key";
+ private static final DumbComponent FILE_COMPONENT = DumbComponent.builder(Component.Type.FILE, 1).setKey(FILE_COMPONENT_KEY).build();
+ private static final DumbComponent OTHER_COMPONENT = DumbComponent.builder(Component.Type.FILE, 2).setKey("some other key").build();
+ private static final String METRIC_KEY_1 = "metric 1";
+ private static final int METRIC_ID_1 = 1;
+ private static final String METRIC_KEY_2 = "metric 2";
+ private static final int METRIC_ID_2 = 2;
+ private final Metric metric1 = mock(Metric.class);
+ private final Metric metric2 = mock(Metric.class);
+ private static final long LAST_SNAPSHOT_ID = 123;
+ private static final long OTHER_SNAPSHOT_ID = 369;
+ private static final long COMPONENT_ID = 567;
+ private static final Measure SOME_MEASURE = mock(Measure.class);
+
+ private DbClient dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new MeasureDao(), new SnapshotDao(), new MetricDao(), new ComponentDao());
+ private MetricRepository metricRepository = mock(MetricRepository.class);
+ private MeasureRepositoryImpl underTest = new MeasureRepositoryImpl(dbClient, reportReader, metricRepository);
+
+ private DbClient mockedDbClient = mock(DbClient.class);
+ private BatchReportReader mockBatchReportReader = mock(BatchReportReader.class);
+ private MeasureRepositoryImpl underTestWithMock = new MeasureRepositoryImpl(mockedDbClient, mockBatchReportReader, metricRepository);
+
+ @CheckForNull
+ private DbSession dbSession;
+
+ @Before
+ public void setUp() throws Exception {
+ when(metric1.getKey()).thenReturn(METRIC_KEY_1);
+ when(metric1.getMetricType()).thenReturn(Metric.MetricType.STRING);
+ when(metric2.getKey()).thenReturn(METRIC_KEY_2);
+ when(metric2.getMetricType()).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);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (dbSession != null) {
+ dbSession.close();
+ }
+ }
+
+ @Test
+ public void getBaseMeasure_throws_NPE_and_does_not_open_session_if_component_is_null() {
+ try {
+ underTestWithMock.getBaseMeasure(null, metric1);
+ fail("an NPE should have been raised");
+ } catch (NullPointerException e) {
+ verifyZeroInteractions(mockedDbClient);
+ }
+ }
+
+ @Test
+ public void getBaseMeasure_throws_NPE_and_does_not_open_session_if_metric_is_null() {
+ try {
+ underTestWithMock.getBaseMeasure(FILE_COMPONENT, null);
+ fail("an NPE should have been raised");
+ } catch (NullPointerException e) {
+ verifyZeroInteractions(mockedDbClient);
+ }
+ }
+
+ @Test
+ public void getBaseMeasure_returns_absent_if_measure_does_not_exist_in_DB() {
+ Optional<Measure> res = underTest.getBaseMeasure(FILE_COMPONENT, metric1);
+
+ assertThat(res).isAbsent();
+ }
+
+ @Test
+ public void getBaseMeasure_returns_Measure_if_measure_of_last_snapshot_only_in_DB() {
+ dbTester.prepareDbUnit(getClass(), "shared.xml");
+ dbSession = dbClient.openSession(false);
+ dbClient.measureDao().insert(dbSession, createMeasureDto(METRIC_ID_1, LAST_SNAPSHOT_ID));
+ dbClient.measureDao().insert(dbSession, createMeasureDto(METRIC_ID_2, OTHER_SNAPSHOT_ID));
+ dbSession.commit();
+
+ // metric 1 is associated to snapshot with "last=true"
+ Optional<Measure> res = underTest.getBaseMeasure(FILE_COMPONENT, metric1);
+
+ assertThat(res).isPresent();
+ assertThat(res.get().getStringValue()).isEqualTo(SOME_DATA);
+
+ // metric 2 is associated to snapshot with "last=false" => not retrieved
+ res = underTest.getBaseMeasure(FILE_COMPONENT, metric2);
+
+ assertThat(res).isAbsent();
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void add_throws_NPE_if_Component_argument_is_null() {
+ underTest.add(null, metric1, mock(Measure.class));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void add_throws_NPE_if_Component_metric_is_null() {
+ underTest.add(FILE_COMPONENT, null, mock(Measure.class));
+ }
+
+ @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, mock(Measure.class));
+ underTest.add(FILE_COMPONENT, metric1, mock(Measure.class));
+ }
+
+ @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
+ public void getRawMeasure_returns_measure_from_batch_if_not_added_through_add_method() {
+ String value = "trololo";
+
+ reportReader.putMeasures(FILE_COMPONENT.getRef(), ImmutableList.of(
+ BatchReport.Measure.newBuilder().setMetricKey(METRIC_KEY_1).setStringValue(value).build()
+ ));
+
+ Optional<Measure> res = underTest.getRawMeasure(FILE_COMPONENT, metric1);
+
+ assertThat(res).isPresent();
+ assertThat(res.get().getStringValue()).isEqualTo(value);
+
+ // make sure we really match on the specified component and metric
+ assertThat(underTest.getRawMeasure(FILE_COMPONENT, metric2)).isAbsent();
+ assertThat(underTest.getRawMeasure(OTHER_COMPONENT, metric1)).isAbsent();
+ }
+
+ @Test
+ public void getRawMeasure_retrieves_added_measure_over_batch_measure() {
+ reportReader.putMeasures(FILE_COMPONENT.getRef(), ImmutableList.of(
+ BatchReport.Measure.newBuilder().setMetricKey(METRIC_KEY_1).setStringValue("some value").build()
+ ));
+
+ Measure addedMeasure = mock(Measure.class);
+ underTest.add(FILE_COMPONENT, metric1, addedMeasure);
+
+ Optional<Measure> res = underTest.getRawMeasure(FILE_COMPONENT, metric1);
+
+ assertThat(res).isPresent();
+ assertThat(res.get()).isSameAs(addedMeasure);
+ }
+
+ private static MeasureDto createMeasureDto(int metricId, long snapshotId) {
+ return new MeasureDto()
+ .setComponentId(COMPONENT_ID)
+ .setSnapshotId(snapshotId)
+ .setData(SOME_DATA)
+ .setMetricId(metricId);
+ }
+}
--- /dev/null
+/*
+ * 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.metric;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class MetricImplTest {
+
+ private static final String SOME_KEY = "key";
+ private static final String SOME_NAME = "name";
+
+ @Test(expected = NullPointerException.class)
+ public void constructor_throws_NPE_if_key_arg_is_null() {
+ new MetricImpl(null, SOME_NAME, Metric.MetricType.BOOL);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void constructor_throws_NPE_if_name_arg_is_null() {
+ new MetricImpl(SOME_KEY, null, Metric.MetricType.BOOL);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void constructor_throws_NPE_if_valueType_arg_is_null() {
+ new MetricImpl(SOME_KEY, SOME_NAME, null);
+ }
+
+ @Test
+ public void verify_getters() {
+ MetricImpl metric = new MetricImpl(SOME_KEY, SOME_NAME, Metric.MetricType.FLOAT);
+
+ assertThat(metric.getKey()).isEqualTo(SOME_KEY);
+ assertThat(metric.getName()).isEqualTo(SOME_NAME);
+ assertThat(metric.getMetricType()).isEqualTo(Metric.MetricType.FLOAT);
+ }
+
+ @Test
+ public void equals_uses_key_and_name() {
+ MetricImpl expected = new MetricImpl(SOME_KEY, SOME_NAME, Metric.MetricType.FLOAT);
+
+ assertThat(new MetricImpl(SOME_KEY, SOME_NAME, Metric.MetricType.FLOAT)).isEqualTo(expected);
+ assertThat(new MetricImpl("some other key", SOME_NAME, Metric.MetricType.FLOAT)).isNotEqualTo(expected);
+ assertThat(new MetricImpl(SOME_KEY, SOME_NAME, Metric.MetricType.STRING)).isNotEqualTo(expected);
+ }
+
+ @Test
+ public void equals_ignores_valueType() {
+ assertThat(new MetricImpl(SOME_KEY, SOME_NAME, Metric.MetricType.FLOAT)).isEqualTo(new MetricImpl(SOME_KEY, "some other name", Metric.MetricType.FLOAT));
+ }
+
+ @Test
+ public void hashcode_uses_only_key_and_valueType() {
+ int expected = new MetricImpl(SOME_KEY, SOME_NAME, Metric.MetricType.FLOAT).hashCode();
+
+ assertThat(new MetricImpl(SOME_KEY, "some other name", Metric.MetricType.FLOAT).hashCode()).isEqualTo(expected);
+ }
+
+ @Test
+ public void all_fields_are_displayed_in_toString() {
+ assertThat(new MetricImpl(SOME_KEY, SOME_NAME, Metric.MetricType.FLOAT).toString())
+ .isEqualTo("MetricImpl{key=key, name=name, metricType=FLOAT}");
+
+ }
+}
--- /dev/null
+/*
+ * 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.metric;
+
+import javax.annotation.CheckForNull;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.sonar.core.metric.db.MetricDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.metric.persistence.MetricDao;
+import org.sonar.test.DbTests;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@Category(DbTests.class)
+public class MetricRepositoryImplTest {
+ private static final String SOME_KEY = "some key";
+ private static final String SOME_NAME = "the short name";
+
+ @ClassRule
+ public static final DbTester dbTester = new DbTester();
+
+ private DbClient dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new MetricDao());
+ private MetricRepository underTest = new MetricRepositoryImpl(dbClient);
+
+ @CheckForNull
+ private DbSession dbSession;
+
+ @Before
+ public void setUp() throws Exception {
+ dbTester.truncateTables();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (dbSession != null) {
+ dbSession.close();
+ }
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void findByKey_throws_NPE_if_arg_is_null() {
+ underTest.getByKey(null);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void findByKey_throws_ISE_of_Metric_does_not_exist() {
+ underTest.getByKey(SOME_KEY);
+ }
+
+ @Test
+ public void verify_mapping_and_valueType_conversion_from_DB() {
+ dbSession = dbClient.openSession(false);
+
+ for (Metric.MetricType metricType : Metric.MetricType.values()) {
+ verify_mapping_and_valueType_conversion_from_DB_impl(metricType.name(), metricType);
+ }
+ }
+
+ private void verify_mapping_and_valueType_conversion_from_DB_impl(String valueType, Metric.MetricType expected) {
+ MetricDto metricDto = new MetricDto().setKey(SOME_KEY + valueType).setShortName(SOME_NAME).setValueType(valueType);
+
+ dbClient.metricDao().insert(dbSession, metricDto);
+ dbSession.commit();
+
+ Metric metric = underTest.getByKey(metricDto.getKey());
+
+ assertThat(metric.getKey()).isEqualTo(metricDto.getKey());
+ assertThat(metric.getName()).isEqualTo(metricDto.getShortName());
+ assertThat(metric.getMetricType()).isEqualTo(expected);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void findByKey_throws_IAE_if_valueType_can_not_be_parsed() {
+ MetricDto metricDto = new MetricDto().setKey(SOME_KEY).setShortName(SOME_NAME).setValueType("trololo");
+
+ dbSession = dbClient.openSession(false);
+ dbClient.metricDao().insert(dbSession, metricDto);
+ dbSession.commit();
+
+ underTest.getByKey(SOME_KEY);
+ }
+}
package org.sonar.server.computation.step;
import com.google.common.base.Optional;
-import javax.annotation.Nullable;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.sonar.api.notifications.Notification;
-import org.sonar.batch.protocol.output.BatchReport;
-import org.sonar.core.measure.db.MeasureDto;
import org.sonar.server.computation.batch.TreeRootHolderRule;
+import org.sonar.server.computation.component.Component;
+import org.sonar.server.computation.component.DumbComponent;
import org.sonar.server.computation.event.Event;
import org.sonar.server.computation.event.EventRepository;
+import org.sonar.server.computation.measure.Measure;
+import org.sonar.server.computation.measure.MeasureImpl;
import org.sonar.server.computation.measure.MeasureRepository;
+import org.sonar.server.computation.metric.Metric;
+import org.sonar.server.computation.metric.MetricRepository;
import org.sonar.server.notification.NotificationManager;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
-import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS;
-import static org.sonar.server.computation.component.DumbComponent.DUMB_PROJECT;
+import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY;
+import static org.sonar.server.computation.measure.Measure.Level.ERROR;
+import static org.sonar.server.computation.measure.Measure.Level.OK;
+import static org.sonar.server.computation.measure.Measure.Level.WARN;
public class QualityGateEventsStepTest {
-
- static final String INVALID_STATUS = "trololo";
- static final String DESCRIPTION = "gate errors";
+ private static final DumbComponent PROJECT_COMPONENT = DumbComponent.builder(Component.Type.PROJECT, 1).setUuid("uuid 1").setKey("key 1")
+ .addChildren(DumbComponent.builder(Component.Type.MODULE, 2).build())
+ .build();
+ private static final String INVALID_ALERT_STATUS = "trololo";
+ private static final String ALERT_TEXT = "alert text";
+ private static final Measure.QualityGateStatus OK_QUALITY_GATE_STATUS = new Measure.QualityGateStatus(OK, ALERT_TEXT);
+ private static final Measure.QualityGateStatus WARN_QUALITY_GATE_STATUS = new Measure.QualityGateStatus(WARN, ALERT_TEXT);
+ private static final Measure.QualityGateStatus ERROR_QUALITY_GATE_STATUS = new Measure.QualityGateStatus(ERROR, ALERT_TEXT);
@Rule
public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
- ArgumentCaptor<Event> eventArgumentCaptor = ArgumentCaptor.forClass(Event.class);
- ArgumentCaptor<Notification> notificationArgumentCaptor = ArgumentCaptor.forClass(Notification.class);
+ private ArgumentCaptor<Event> eventArgumentCaptor = ArgumentCaptor.forClass(Event.class);
+ private ArgumentCaptor<Notification> notificationArgumentCaptor = ArgumentCaptor.forClass(Notification.class);
+
+ private Metric alertStatusMetric = mock(Metric.class);
- EventRepository eventRepository = mock(EventRepository.class);
- MeasureRepository measureRepository = mock(MeasureRepository.class);
- NotificationManager notificationManager = mock(NotificationManager.class);
- QualityGateEventsStep underTest = new QualityGateEventsStep(treeRootHolder, eventRepository, measureRepository, notificationManager);
+ private MetricRepository metricRepository = mock(MetricRepository.class);
+ private MeasureRepository measureRepository = mock(MeasureRepository.class);
+ private EventRepository eventRepository = mock(EventRepository.class);
+ private NotificationManager notificationManager = mock(NotificationManager.class);
+ private QualityGateEventsStep underTest = new QualityGateEventsStep(treeRootHolder, metricRepository, measureRepository, eventRepository, notificationManager);
@Before
public void setUp() throws Exception {
- treeRootHolder.setRoot(DUMB_PROJECT);
+ when(metricRepository.getByKey(ALERT_STATUS_KEY)).thenReturn(alertStatusMetric);
+ treeRootHolder.setRoot(PROJECT_COMPONENT);
}
@Test
- public void no_event_if_no_status_measure() {
- when(measureRepository.findCurrent(DUMB_PROJECT, ALERT_STATUS)).thenReturn(Optional.<BatchReport.Measure>absent());
+ public void no_event_if_no_raw_ALERT_STATUS_measure() {
+ when(measureRepository.getRawMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(Optional.<Measure>absent());
underTest.execute();
- verify(measureRepository).findCurrent(DUMB_PROJECT, ALERT_STATUS);
- verifyNoMoreInteractions(measureRepository, eventRepository, notificationManager);
+ verify(measureRepository).getRawMeasure(PROJECT_COMPONENT, alertStatusMetric);
+ verifyNoMoreInteractions(measureRepository, eventRepository);
}
@Test
- public void no_event_created_if_status_measure_is_null() {
- when(measureRepository.findCurrent(DUMB_PROJECT, ALERT_STATUS)).thenReturn(Optional.of(BatchReport.Measure.newBuilder().build()));
+ public void no_event_created_if_raw_ALERT_STATUS_measure_is_null() {
+ when(measureRepository.getRawMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(of(MeasureImpl.createNoValue()));
underTest.execute();
- verify(measureRepository).findCurrent(DUMB_PROJECT, ALERT_STATUS);
- verifyNoMoreInteractions(measureRepository, eventRepository, notificationManager);
+ verify(measureRepository).getRawMeasure(PROJECT_COMPONENT, alertStatusMetric);
+ verifyNoMoreInteractions(measureRepository, eventRepository);
+ }
+
+ private static Optional<Measure> of(MeasureImpl measure) {
+ return Optional.of((Measure) measure);
}
@Test
- public void no_event_created_if_status_measure_has_unsupported_value() {
- when(measureRepository.findCurrent(DUMB_PROJECT, ALERT_STATUS)).thenReturn(Optional.of(BatchReport.Measure.newBuilder().setAlertStatus(INVALID_STATUS).build()));
+ public void no_event_created_if_raw_ALERT_STATUS_measure_is_unsupported_value() {
+ when(measureRepository.getRawMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(of(MeasureImpl.create(INVALID_ALERT_STATUS)));
underTest.execute();
- verify(measureRepository).findCurrent(DUMB_PROJECT, ALERT_STATUS);
- verifyNoMoreInteractions(measureRepository, eventRepository, notificationManager);
+ verify(measureRepository).getRawMeasure(PROJECT_COMPONENT, alertStatusMetric);
+ verifyNoMoreInteractions(measureRepository, eventRepository);
}
@Test
- public void no_event_created_if_OK_and_no_base_status() {
- String alertStatus = "OK";
+ public void no_event_created_if_no_base_ALERT_STATUS_and_raw_is_OK() {
+ Measure.QualityGateStatus someQGStatus = new Measure.QualityGateStatus(Measure.Level.OK);
- when(measureRepository.findCurrent(DUMB_PROJECT, ALERT_STATUS)).thenReturn(createBatchReportMeasure(alertStatus, null));
- when(measureRepository.findPrevious(DUMB_PROJECT, ALERT_STATUS)).thenReturn(Optional.<MeasureDto>absent());
+ when(measureRepository.getRawMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(of(MeasureImpl.createNoValue().setQualityGateStatus(someQGStatus)));
+ when(measureRepository.getBaseMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(of(MeasureImpl.createNoValue()));
underTest.execute();
- verify(measureRepository).findCurrent(DUMB_PROJECT, ALERT_STATUS);
- verify(measureRepository).findPrevious(DUMB_PROJECT, ALERT_STATUS);
- verifyNoMoreInteractions(measureRepository, eventRepository, notificationManager);
+ verify(measureRepository).getRawMeasure(PROJECT_COMPONENT, alertStatusMetric);
+ verify(measureRepository).getBaseMeasure(PROJECT_COMPONENT, alertStatusMetric);
+ verifyNoMoreInteractions(measureRepository, eventRepository);
}
@Test
- public void event_created_if_WARN_and_no_base_status() {
- verify_event_created_if_no_base_status("WARN", "Orange", null);
+ public void event_created_if_no_base_ALERT_STATUS_and_raw_is_WARN() {
+ verify_event_created_if_no_base_ALERT_STATUS_measure(WARN, "Orange");
}
@Test
- public void event_created_if_ERROR_and_no_base_status() {
- verify_event_created_if_no_base_status("ERROR", "Red", null);
+ public void event_created_if_base_ALERT_STATUS_and_raw_is_ERROR() {
+ verify_event_created_if_no_base_ALERT_STATUS_measure(ERROR, "Red");
}
@Test
- public void event_created_if_ERROR_and_base_measure_has_no_status() {
- verify_event_created_if_no_base_status("ERROR", "Red", new MeasureDto());
+ public void event_created_if_base_ALERT_STATUS_has_no_alertStatus_and_raw_is_ERROR() {
+ verify_event_created_if_no_base_ALERT_STATUS_measure(ERROR, "Red");
}
@Test
- public void event_created_if_WARN_and_base_measure_has_no_status() {
- verify_event_created_if_no_base_status("WARN", "Orange", new MeasureDto());
+ public void event_created_if_base_ALERT_STATUS_has_no_alertStatus_and_raw_is_WARN() {
+ verify_event_created_if_no_base_ALERT_STATUS_measure(WARN, "Orange");
}
@Test
- public void event_created_if_ERROR_and_base_status_has_invalid_value() {
- verify_event_created_if_no_base_status("ERROR", "Red", new MeasureDto().setAlertStatus(INVALID_STATUS));
+ public void event_created_if_base_ALERT_STATUS_has_invalid_alertStatus_and_raw_is_ERROR() {
+ verify_event_created_if_no_base_ALERT_STATUS_measure(ERROR, "Red");
}
@Test
- public void event_created_if_WARN_and_base_status_has_invalid_value() {
- verify_event_created_if_no_base_status("WARN", "Orange", new MeasureDto().setAlertStatus(INVALID_STATUS));
+ public void event_created_if_base_ALERT_STATUS_has_invalid_alertStatus_and_raw_is_WARN() {
+ verify_event_created_if_no_base_ALERT_STATUS_measure(WARN, "Orange");
}
- private void verify_event_created_if_no_base_status(String status, String expectedLabel, @Nullable MeasureDto measureDto) {
- when(measureRepository.findCurrent(DUMB_PROJECT, ALERT_STATUS)).thenReturn(createBatchReportMeasure(status, DESCRIPTION));
- when(measureRepository.findPrevious(DUMB_PROJECT, ALERT_STATUS)).thenReturn(Optional.fromNullable(measureDto));
+ private void verify_event_created_if_no_base_ALERT_STATUS_measure(Measure.Level rawAlterStatus, String expectedEventName) {
+ Measure.QualityGateStatus someQGStatus = new Measure.QualityGateStatus(rawAlterStatus, ALERT_TEXT);
+
+ when(measureRepository.getRawMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(of(MeasureImpl.createNoValue().setQualityGateStatus(someQGStatus)));
+ when(measureRepository.getBaseMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(of(MeasureImpl.createNoValue()));
underTest.execute();
- verify(measureRepository).findCurrent(DUMB_PROJECT, ALERT_STATUS);
- verify(measureRepository).findPrevious(DUMB_PROJECT, ALERT_STATUS);
- verify(eventRepository).add(eq(DUMB_PROJECT), eventArgumentCaptor.capture());
+ verify(measureRepository).getRawMeasure(PROJECT_COMPONENT, alertStatusMetric);
+ verify(measureRepository).getBaseMeasure(PROJECT_COMPONENT, alertStatusMetric);
+ verify(eventRepository).add(eq(PROJECT_COMPONENT), eventArgumentCaptor.capture());
verifyNoMoreInteractions(measureRepository, eventRepository);
Event event = eventArgumentCaptor.getValue();
assertThat(event.getCategory()).isEqualTo(Event.Category.ALERT);
- assertThat(event.getName()).isEqualTo(expectedLabel);
- assertThat(event.getDescription()).isEqualTo(DESCRIPTION);
+ assertThat(event.getName()).isEqualTo(expectedEventName);
+ assertThat(event.getDescription()).isEqualTo(ALERT_TEXT);
assertThat(event.getData()).isNull();
-
- verify(notificationManager).scheduleForSending(notificationArgumentCaptor.capture());
- Notification notification = notificationArgumentCaptor.getValue();
- assertThat(notification.getType()).isEqualTo("alerts");
- assertThat(notification.getFieldValue("projectKey")).isEqualTo(DUMB_PROJECT.getKey());
- assertThat(notification.getFieldValue("projectUuid")).isEqualTo(DUMB_PROJECT.getUuid());
- assertThat(notification.getFieldValue("projectName")).isEqualTo(DUMB_PROJECT.getName());
- assertThat(notification.getFieldValue("alertLevel")).isEqualTo(status);
- assertThat(notification.getFieldValue("alertName")).isEqualTo(expectedLabel);
}
@Test
- public void no_event_created_if_status_same_as_base() {
- String alertStatus = "OK";
-
- when(measureRepository.findCurrent(DUMB_PROJECT, ALERT_STATUS)).thenReturn(createBatchReportMeasure(alertStatus, DESCRIPTION));
- when(measureRepository.findPrevious(DUMB_PROJECT, ALERT_STATUS)).thenReturn(Optional.of(new MeasureDto().setAlertStatus(alertStatus)));
+ public void no_event_created_if_base_ALERT_STATUS_measure_but_status_is_the_same() {
+ when(measureRepository.getRawMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(of(MeasureImpl.createNoValue().setQualityGateStatus(OK_QUALITY_GATE_STATUS)));
+ when(measureRepository.getBaseMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(of(MeasureImpl.createNoValue().setQualityGateStatus(OK_QUALITY_GATE_STATUS)));
underTest.execute();
- verify(measureRepository).findCurrent(DUMB_PROJECT, ALERT_STATUS);
- verify(measureRepository).findPrevious(DUMB_PROJECT, ALERT_STATUS);
- verifyNoMoreInteractions(measureRepository, eventRepository, notificationManager);
+ verify(measureRepository).getRawMeasure(PROJECT_COMPONENT, alertStatusMetric);
+ verify(measureRepository).getBaseMeasure(PROJECT_COMPONENT, alertStatusMetric);
+ verifyNoMoreInteractions(measureRepository, eventRepository);
}
@Test
- public void event_created_if_status_changed() {
- verify_event_created_if_status_changed("OK", "WARN", "Orange (was Green)");
- verify_event_created_if_status_changed("OK", "ERROR", "Red (was Green)");
- verify_event_created_if_status_changed("WARN", "OK", "Green (was Orange)");
- verify_event_created_if_status_changed("WARN", "ERROR", "Red (was Orange)");
- verify_event_created_if_status_changed("ERROR", "OK", "Green (was Red)");
- verify_event_created_if_status_changed("ERROR", "WARN", "Orange (was Red)");
+ public void event_created_if_base_ALERT_STATUS_measure_exists_and_status_has_changed() {
+ verify_event_created_if_base_ALERT_STATUS_measure_exists_and_status_has_changed(OK, WARN_QUALITY_GATE_STATUS, "Orange (was Green)");
+ verify_event_created_if_base_ALERT_STATUS_measure_exists_and_status_has_changed(OK, ERROR_QUALITY_GATE_STATUS, "Red (was Green)");
+ verify_event_created_if_base_ALERT_STATUS_measure_exists_and_status_has_changed(WARN, OK_QUALITY_GATE_STATUS, "Green (was Orange)");
+ verify_event_created_if_base_ALERT_STATUS_measure_exists_and_status_has_changed(WARN, ERROR_QUALITY_GATE_STATUS, "Red (was Orange)");
+ verify_event_created_if_base_ALERT_STATUS_measure_exists_and_status_has_changed(ERROR, OK_QUALITY_GATE_STATUS, "Green (was Red)");
+ verify_event_created_if_base_ALERT_STATUS_measure_exists_and_status_has_changed(ERROR, WARN_QUALITY_GATE_STATUS, "Orange (was Red)");
}
- private void verify_event_created_if_status_changed(String baseStatus, String status, String expectedLabel) {
- when(measureRepository.findCurrent(DUMB_PROJECT, ALERT_STATUS)).thenReturn(createBatchReportMeasure(status, DESCRIPTION));
- when(measureRepository.findPrevious(DUMB_PROJECT, ALERT_STATUS)).thenReturn(Optional.of(new MeasureDto().setAlertStatus(baseStatus)));
+ private void verify_event_created_if_base_ALERT_STATUS_measure_exists_and_status_has_changed(Measure.Level previousAlertStatus,
+ Measure.QualityGateStatus newQualityGateStatus, String expectedLabel) {
+ when(measureRepository.getRawMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(of(MeasureImpl.createNoValue().setQualityGateStatus(newQualityGateStatus)));
+ when(measureRepository.getBaseMeasure(PROJECT_COMPONENT, alertStatusMetric)).thenReturn(
+ of(MeasureImpl.createNoValue().setQualityGateStatus(new Measure.QualityGateStatus(previousAlertStatus))));
underTest.execute();
- verify(measureRepository).findCurrent(DUMB_PROJECT, ALERT_STATUS);
- verify(measureRepository).findPrevious(DUMB_PROJECT, ALERT_STATUS);
- verify(eventRepository).add(eq(DUMB_PROJECT), eventArgumentCaptor.capture());
+ verify(measureRepository).getRawMeasure(PROJECT_COMPONENT, alertStatusMetric);
+ verify(measureRepository).getBaseMeasure(PROJECT_COMPONENT, alertStatusMetric);
+ verify(eventRepository).add(eq(PROJECT_COMPONENT), eventArgumentCaptor.capture());
verifyNoMoreInteractions(measureRepository, eventRepository);
Event event = eventArgumentCaptor.getValue();
assertThat(event.getCategory()).isEqualTo(Event.Category.ALERT);
assertThat(event.getName()).isEqualTo(expectedLabel);
- assertThat(event.getDescription()).isEqualTo(DESCRIPTION);
+ assertThat(event.getDescription()).isEqualTo(ALERT_TEXT);
assertThat(event.getData()).isNull();
verify(notificationManager).scheduleForSending(notificationArgumentCaptor.capture());
Notification notification = notificationArgumentCaptor.getValue();
assertThat(notification.getType()).isEqualTo("alerts");
- assertThat(notification.getFieldValue("projectKey")).isEqualTo(DUMB_PROJECT.getKey());
- assertThat(notification.getFieldValue("projectUuid")).isEqualTo(DUMB_PROJECT.getUuid());
- assertThat(notification.getFieldValue("projectName")).isEqualTo(DUMB_PROJECT.getName());
- assertThat(notification.getFieldValue("alertLevel")).isEqualTo(status);
+ assertThat(notification.getFieldValue("projectKey")).isEqualTo(PROJECT_COMPONENT.getKey());
+ assertThat(notification.getFieldValue("projectUuid")).isEqualTo(PROJECT_COMPONENT.getUuid());
+ assertThat(notification.getFieldValue("projectName")).isEqualTo(PROJECT_COMPONENT.getName());
+ assertThat(notification.getFieldValue("alertLevel")).isEqualTo(newQualityGateStatus.getStatus().name());
assertThat(notification.getFieldValue("alertName")).isEqualTo(expectedLabel);
reset(measureRepository, eventRepository, notificationManager);
}
- private static Optional<BatchReport.Measure> createBatchReportMeasure(String status, @Nullable String description) {
- BatchReport.Measure.Builder builder = BatchReport.Measure.newBuilder().setAlertStatus(status);
- if (description != null) {
- builder.setAlertText(description);
- }
- return Optional.of(builder.build());
- }
}
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.resources.AbstractLanguage;
import org.sonar.api.resources.Language;
-import org.sonar.batch.protocol.output.BatchReport;
import org.sonar.core.UtcDateUtils;
-import org.sonar.core.measure.db.MeasureDto;
import org.sonar.server.computation.batch.TreeRootHolderRule;
import org.sonar.server.computation.component.Component;
import org.sonar.server.computation.component.DumbComponent;
import org.sonar.server.computation.event.Event;
import org.sonar.server.computation.event.EventRepository;
import org.sonar.server.computation.language.LanguageRepository;
+import org.sonar.server.computation.measure.Measure;
+import org.sonar.server.computation.measure.MeasureImpl;
import org.sonar.server.computation.measure.MeasureRepository;
+import org.sonar.server.computation.metric.Metric;
+import org.sonar.server.computation.metric.MetricRepository;
import org.sonar.server.computation.qualityprofile.QPMeasureData;
import org.sonar.server.computation.qualityprofile.QualityProfile;
private static final String LANGUAGE_KEY_2 = "language_key_2";
private static final String LANGUAGE_KEY_3 = "languageKey3";
+ private MetricRepository metricRepository = mock(MetricRepository.class);
private MeasureRepository measureRepository = mock(MeasureRepository.class);
private LanguageRepository languageRepository = mock(LanguageRepository.class);
private EventRepository eventRepository = mock(EventRepository.class);
private ArgumentCaptor<Event> eventArgumentCaptor = ArgumentCaptor.forClass(Event.class);
- private QualityProfileEventsStep underTest = new QualityProfileEventsStep(treeRootHolder, measureRepository, eventRepository, languageRepository);
+ private Metric qualityProfileMetric = mock(Metric.class);
+
+ private QualityProfileEventsStep underTest = new QualityProfileEventsStep(treeRootHolder, metricRepository, measureRepository, languageRepository, eventRepository);
@Before
public void setUp() throws Exception {
+ when(metricRepository.getByKey(CoreMetrics.QUALITY_PROFILES_KEY)).thenReturn(qualityProfileMetric);
treeRootHolder.setRoot(DumbComponent.builder(Component.Type.PROJECT, 1).setUuid("uuid").setKey("key").build());
}
@Test
- public void no_effect_if_no_previous_measure() {
- when(measureRepository.findPrevious(treeRootHolder.getRoot(), CoreMetrics.QUALITY_PROFILES)).thenReturn(Optional.<MeasureDto>absent());
+ public void no_effect_if_no_base_measure() {
+ when(measureRepository.getBaseMeasure(treeRootHolder.getRoot(), qualityProfileMetric)).thenReturn(Optional.<Measure>absent());
underTest.execute();
}
@Test(expected = IllegalStateException.class)
- public void ISE_if_no_current_measure() {
- when(measureRepository.findPrevious(treeRootHolder.getRoot(), CoreMetrics.QUALITY_PROFILES)).thenReturn(Optional.of(newMeasureDto()));
- when(measureRepository.findCurrent(treeRootHolder.getRoot(), CoreMetrics.QUALITY_PROFILES)).thenReturn(Optional.<BatchReport.Measure>absent());
+ public void ISE_if_no_raw_measure() {
+ when(measureRepository.getBaseMeasure(treeRootHolder.getRoot(), qualityProfileMetric)).thenReturn(Optional.of(newMeasure()));
+ when(measureRepository.getRawMeasure(treeRootHolder.getRoot(), qualityProfileMetric)).thenReturn(Optional.<Measure>absent());
underTest.execute();
}
@Test
- public void no_event_if_no_qp_now_nor_before() {
+ public void no_event_if_no_base_nor_row_QualityProfile_measure() {
mockMeasures(treeRootHolder.getRoot(), null, null);
underTest.execute();
}
private void mockMeasures(Component component, @Nullable QualityProfile[] previous, @Nullable QualityProfile[] current) {
- when(measureRepository.findPrevious(component, CoreMetrics.QUALITY_PROFILES)).thenReturn(Optional.of(newMeasureDto(previous)));
- when(measureRepository.findCurrent(component, CoreMetrics.QUALITY_PROFILES)).thenReturn(Optional.of(newQPBatchMeasure(current)));
+ when(measureRepository.getBaseMeasure(component, qualityProfileMetric)).thenReturn(Optional.of(newMeasure(previous)));
+ when(measureRepository.getRawMeasure(component, qualityProfileMetric)).thenReturn(Optional.of(newMeasure(current)));
}
private static void verifyEvent(Event event, String expectedName, @Nullable String expectedData) {
return qps;
}
- private static MeasureDto newMeasureDto(@Nullable QualityProfile... qps) {
- return new MeasureDto().setData(toJson(qps));
- }
-
- private static BatchReport.Measure newQPBatchMeasure(@Nullable QualityProfile... qps) {
- return BatchReport.Measure.newBuilder().setStringValue(toJson(qps)).build();
+ private static Measure newMeasure(@Nullable QualityProfile... qps) {
+ return MeasureImpl.create(toJson(qps));
}
private static String toJson(@Nullable QualityProfile... qps) {
--- /dev/null
+<dataset>
+ <projects id="567" kee="file cpt key" enabled="[true]"/>
+ <snapshots id="123" project_id="567" islast="[true]"/>
+ <snapshots id="369" project_id="567" islast="[false]"/>
+ <metrics id="1" name="metric 1" />
+ <metrics id="2" name="metric 2" />
+</dataset>