import org.sonar.server.computation.measure.MeasureToMeasureDto;
import org.sonar.server.computation.metric.MetricModule;
import org.sonar.server.computation.period.PeriodsHolderImpl;
+import org.sonar.server.computation.posttask.PostProjectAnalysisTasksExecutor;
import org.sonar.server.computation.qualitygate.EvaluationResultTextConverterImpl;
import org.sonar.server.computation.qualitygate.QualityGateHolderImpl;
import org.sonar.server.computation.qualitygate.QualityGateServiceImpl;
+import org.sonar.server.computation.qualitygate.QualityGateStatusHolderImpl;
import org.sonar.server.computation.qualitymodel.NewQualityModelMeasuresVisitor;
import org.sonar.server.computation.qualitymodel.QualityModelMeasuresVisitor;
import org.sonar.server.computation.qualitymodel.RatingSettings;
*/
private static List componentClasses() {
return Arrays.asList(
+ PostProjectAnalysisTasksExecutor.class,
ComputationStepExecutor.class,
// File System
TreeRootHolderImpl.class,
PeriodsHolderImpl.class,
QualityGateHolderImpl.class,
+ QualityGateStatusHolderImpl.class,
RatingSettings.class,
ActiveRulesHolderImpl.class,
MeasureComputersHolderImpl.class,
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.posttask;
+
+import javax.annotation.concurrent.Immutable;
+import org.sonar.api.ce.posttask.CeTask;
+
+import static java.util.Objects.requireNonNull;
+
+@Immutable
+class CeTaskImpl implements CeTask {
+ private final String id;
+ private final Status status;
+
+ CeTaskImpl(String id, Status status) {
+ this.id = requireNonNull(id, "uuid can not be null");
+ this.status = requireNonNull(status, "status can not be null");
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public Status getStatus() {
+ return status;
+ }
+
+ @Override
+ public String toString() {
+ return "CeTaskImpl{" +
+ "id='" + id + '\'' +
+ ", status=" + status +
+ '}';
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.posttask;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.concurrent.Immutable;
+import org.sonar.api.ce.posttask.QualityGate;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+import static java.util.Objects.requireNonNull;
+import static org.sonar.api.ce.posttask.QualityGate.EvaluationStatus.NO_VALUE;
+
+@Immutable
+class ConditionImpl implements QualityGate.Condition {
+ private final QualityGate.EvaluationStatus status;
+ private final String metricKey;
+ private final QualityGate.Operator operator;
+ @CheckForNull
+ private final String errorThreshold;
+ @CheckForNull
+ private final String warningThreshold;
+ private final boolean onLeakPeriod;
+ @CheckForNull
+ private final String value;
+
+ private ConditionImpl(Builder builder) {
+ requireNonNull(builder.status, "status can not be null");
+ requireNonNull(builder.metricKey, "metricKey can not be null");
+ requireNonNull(builder.operator, "operator can not be null");
+ verifyThresholds(builder);
+ verifyValue(builder);
+
+ this.status = builder.status;
+ this.metricKey = builder.metricKey;
+ this.operator = builder.operator;
+ this.errorThreshold = builder.errorThreshold;
+ this.warningThreshold = builder.warningThreshold;
+ this.onLeakPeriod = builder.onLeakPeriod;
+ this.value = builder.value;
+ }
+
+ private static void verifyThresholds(Builder builder) {
+ checkArgument(
+ builder.errorThreshold != null || builder.warningThreshold != null,
+ "At least one of errorThreshold and warningThreshold must be non null");
+ }
+
+ private static void verifyValue(Builder builder) {
+ if (builder.status == NO_VALUE) {
+ checkArgument(builder.value == null, "value must be null when status is %s", NO_VALUE);
+ } else {
+ checkArgument(builder.value != null, "value can not be null when status is not %s", NO_VALUE);
+ }
+ }
+
+ public static Builder newBuilder() {
+ return new Builder();
+ }
+
+ public static class Builder {
+ private String metricKey;
+ private QualityGate.Operator operator;
+ @CheckForNull
+ private String errorThreshold;
+ @CheckForNull
+ private String warningThreshold;
+ private boolean onLeakPeriod;
+ @CheckForNull
+ private String value;
+ private QualityGate.EvaluationStatus status;
+
+ private Builder() {
+ // enforce use of static method
+ }
+
+ public Builder setMetricKey(String metricKey) {
+ this.metricKey = metricKey;
+ return this;
+ }
+
+ public Builder setOperator(QualityGate.Operator operator) {
+ this.operator = operator;
+ return this;
+ }
+
+ public Builder setErrorThreshold(String errorThreshold) {
+ this.errorThreshold = errorThreshold;
+ return this;
+ }
+
+ public Builder setWarningThreshold(String warningThreshold) {
+ this.warningThreshold = warningThreshold;
+ return this;
+ }
+
+ public Builder setOnLeakPeriod(boolean onLeakPeriod) {
+ this.onLeakPeriod = onLeakPeriod;
+ return this;
+ }
+
+ public Builder setValue(String value) {
+ this.value = value;
+ return this;
+ }
+
+ public Builder setStatus(QualityGate.EvaluationStatus status) {
+ this.status = status;
+ return this;
+ }
+
+ public ConditionImpl build() {
+ return new ConditionImpl(this);
+ }
+ }
+
+ @Override
+ public QualityGate.EvaluationStatus getStatus() {
+ return status;
+ }
+
+ @Override
+ public String getMetricKey() {
+ return metricKey;
+ }
+
+ @Override
+ public QualityGate.Operator getOperator() {
+ return operator;
+ }
+
+ @Override
+ public String getErrorThreshold() {
+ return errorThreshold;
+ }
+
+ @Override
+ public String getWarningThreshold() {
+ return warningThreshold;
+ }
+
+ @Override
+ public boolean isOnLeakPeriod() {
+ return onLeakPeriod;
+ }
+
+ @Override
+ public String getValue() {
+ checkState(status != NO_VALUE, "There is no value when status is " + NO_VALUE);
+
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ return "ConditionImpl{" +
+ "status=" + status +
+ ", metricKey='" + metricKey + '\'' +
+ ", operator=" + operator +
+ ", errorThreshold='" + errorThreshold + '\'' +
+ ", warningThreshold='" + warningThreshold + '\'' +
+ ", onLeakPeriod=" + onLeakPeriod +
+ ", value='" + value + '\'' +
+ '}';
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.posttask;
+
+import com.google.common.base.Function;
+import java.util.Map;
+import javax.annotation.Nonnull;
+import org.sonar.api.ce.posttask.QualityGate;
+import org.sonar.server.computation.qualitygate.Condition;
+import org.sonar.server.computation.qualitygate.ConditionStatus;
+
+import static com.google.common.base.Preconditions.checkState;
+import static java.lang.String.format;
+
+/**
+ * Converts a {@link Condition} from the Compute Engine internal API to a {@link org.sonar.api.ce.posttask.QualityGate.Condition}
+ * of the public API.
+ */
+class ConditionToCondition implements Function<Condition, QualityGate.Condition> {
+ private final ConditionImpl.Builder builder = ConditionImpl.newBuilder();
+ private final Map<Condition, ConditionStatus> statusPerConditions;
+
+ public ConditionToCondition(Map<Condition, ConditionStatus> statusPerConditions) {
+ this.statusPerConditions = statusPerConditions;
+ }
+
+ @Override
+ @Nonnull
+ public QualityGate.Condition apply(@Nonnull Condition input) {
+ String metricKey = input.getMetric().getKey();
+ ConditionStatus conditionStatus = statusPerConditions.get(input);
+ checkState(conditionStatus != null, "Missing ConditionStatus for condition on metric key %s", metricKey);
+ return builder
+ .setStatus(convert(conditionStatus.getStatus()))
+ .setMetricKey(metricKey)
+ .setOperator(convert(input.getOperator()))
+ .setErrorThreshold(input.getErrorThreshold())
+ .setWarningThreshold(input.getWarningThreshold())
+ .setOnLeakPeriod(input.getPeriod() != null)
+ .setValue(conditionStatus.getValue())
+ .build();
+ }
+
+ private static QualityGate.EvaluationStatus convert(ConditionStatus.EvaluationStatus status) {
+ switch (status) {
+ case NO_VALUE:
+ return QualityGate.EvaluationStatus.NO_VALUE;
+ case OK:
+ return QualityGate.EvaluationStatus.OK;
+ case WARN:
+ return QualityGate.EvaluationStatus.WARN;
+ case ERROR:
+ return QualityGate.EvaluationStatus.ERROR;
+ default:
+ throw new IllegalArgumentException(format(
+ "Unsupported value '%s' of ConditionStatus.EvaluationStatus can not be converted to QualityGate.EvaluationStatus",
+ status));
+ }
+ }
+
+ private static QualityGate.Operator convert(Condition.Operator operator) {
+ switch (operator) {
+ case EQUALS:
+ return QualityGate.Operator.EQUALS;
+ case NOT_EQUALS:
+ return QualityGate.Operator.NOT_EQUALS;
+ case GREATER_THAN:
+ return QualityGate.Operator.GREATER_THAN;
+ case LESS_THAN:
+ return QualityGate.Operator.LESS_THAN;
+ default:
+ throw new IllegalArgumentException(format(
+ "Unsupported value '%s' of Condition.Operation can not be converted to QualityGate.Operator",
+ operator));
+ }
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.posttask;
+
+import com.google.common.base.Optional;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Map;
+import java.util.Set;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.sonar.api.ce.posttask.CeTask;
+import org.sonar.api.ce.posttask.PostProjectAnalysisTask;
+import org.sonar.api.ce.posttask.Project;
+import org.sonar.api.ce.posttask.QualityGate;
+import org.sonar.server.computation.analysis.AnalysisMetadataHolder;
+import org.sonar.server.computation.qualitygate.Condition;
+import org.sonar.server.computation.qualitygate.ConditionStatus;
+import org.sonar.server.computation.qualitygate.QualityGateHolder;
+import org.sonar.server.computation.qualitygate.QualityGateStatus;
+import org.sonar.server.computation.qualitygate.QualityGateStatusHolder;
+import org.sonar.server.computation.step.ComputationStepExecutor;
+
+import static com.google.common.collect.FluentIterable.from;
+import static java.lang.String.format;
+import static java.util.Objects.requireNonNull;
+import static org.sonar.api.ce.posttask.CeTask.Status.FAILED;
+import static org.sonar.api.ce.posttask.CeTask.Status.SUCCESS;
+
+/**
+ * Responsible for calling {@link PostProjectAnalysisTask} implementations (if any).
+ */
+public class PostProjectAnalysisTasksExecutor implements ComputationStepExecutor.Listener {
+ private static final PostProjectAnalysisTask[] NO_POST_PROJECT_ANALYSIS_TASKS = new PostProjectAnalysisTask[0];
+
+ private final org.sonar.ce.queue.CeTask ceTask;
+ private final AnalysisMetadataHolder analysisMetadataHolder;
+ private final QualityGateHolder qualityGateHolder;
+ private final QualityGateStatusHolder qualityGateStatusHolder;
+ private final PostProjectAnalysisTask[] postProjectAnalysisTasks;
+
+ /**
+ * Constructor used by Pico when there is no {@link PostProjectAnalysisTask} in the container.
+ */
+ public PostProjectAnalysisTasksExecutor(org.sonar.ce.queue.CeTask ceTask,
+ AnalysisMetadataHolder analysisMetadataHolder,
+ QualityGateHolder qualityGateHolder, QualityGateStatusHolder qualityGateStatusHolder) {
+ this(ceTask, analysisMetadataHolder, qualityGateHolder, qualityGateStatusHolder, null);
+ }
+
+ public PostProjectAnalysisTasksExecutor(org.sonar.ce.queue.CeTask ceTask,
+ AnalysisMetadataHolder analysisMetadataHolder,
+ QualityGateHolder qualityGateHolder, QualityGateStatusHolder qualityGateStatusHolder,
+ @Nullable PostProjectAnalysisTask[] postProjectAnalysisTasks) {
+ this.analysisMetadataHolder = analysisMetadataHolder;
+ this.qualityGateHolder = qualityGateHolder;
+ this.qualityGateStatusHolder = qualityGateStatusHolder;
+ this.ceTask = ceTask;
+ this.postProjectAnalysisTasks = postProjectAnalysisTasks == null ? NO_POST_PROJECT_ANALYSIS_TASKS : postProjectAnalysisTasks;
+ }
+
+ @Override
+ public void finished(boolean allStepsExecuted) {
+ if (postProjectAnalysisTasks.length == 0) {
+ return;
+ }
+
+ ProjectAnalysis projectAnalysis = createProjectAnalysis(allStepsExecuted ? SUCCESS : FAILED);
+ for (PostProjectAnalysisTask postProjectAnalysisTask : postProjectAnalysisTasks) {
+ postProjectAnalysisTask.finished(projectAnalysis);
+ }
+ }
+
+ private ProjectAnalysis createProjectAnalysis(CeTask.Status status) {
+ return new ProjectAnalysis(
+ new CeTaskImpl(this.ceTask.getUuid(), status),
+ createProject(this.ceTask),
+ getAnalysisDate(),
+ status == SUCCESS ? createQualityGate(this.qualityGateHolder) : null);
+ }
+
+ private static Project createProject(org.sonar.ce.queue.CeTask ceTask) {
+ return new ProjectImpl(
+ ceTask.getComponentUuid(),
+ ceTask.getComponentKey(),
+ ceTask.getComponentName());
+ }
+
+ private Date getAnalysisDate() {
+ return new Date(this.analysisMetadataHolder.getAnalysisDate());
+ }
+
+ @CheckForNull
+ private QualityGateImpl createQualityGate(QualityGateHolder qualityGateHolder) {
+ Optional<org.sonar.server.computation.qualitygate.QualityGate> qualityGateOptional = qualityGateHolder.getQualityGate();
+ if (qualityGateOptional.isPresent()) {
+ org.sonar.server.computation.qualitygate.QualityGate qualityGate = qualityGateOptional.get();
+
+ return new QualityGateImpl(
+ String.valueOf(qualityGate.getId()),
+ qualityGate.getName(),
+ convert(qualityGateStatusHolder.getStatus()),
+ convert(qualityGate.getConditions(), qualityGateStatusHolder.getStatusPerConditions()));
+ }
+ return null;
+ }
+
+ private static QualityGate.Status convert(QualityGateStatus status) {
+ switch (status) {
+ case OK:
+ return QualityGate.Status.OK;
+ case WARN:
+ return QualityGate.Status.WARN;
+ case ERROR:
+ return QualityGate.Status.ERROR;
+ default:
+ throw new IllegalArgumentException(format(
+ "Unsupported value '%s' of QualityGateStatus can not be converted to QualityGate.Status",
+ status));
+ }
+ }
+
+ private static Collection<QualityGate.Condition> convert(Set<Condition> conditions, Map<Condition, ConditionStatus> statusPerConditions) {
+ return from(conditions)
+ .transform(new ConditionToCondition(statusPerConditions))
+ .toList();
+ }
+
+ private static class ProjectAnalysis implements PostProjectAnalysisTask.ProjectAnalysis {
+ private final CeTask ceTask;
+ private final Project project;
+ private final Date date;
+ @CheckForNull
+ private final QualityGate qualityGate;
+
+ private ProjectAnalysis(CeTask ceTask, Project project, Date date, @Nullable QualityGate qualityGate) {
+ this.ceTask = requireNonNull(ceTask, "ceTask can not be null");
+ this.project = requireNonNull(project, "project can not be null");
+ this.date = requireNonNull(date, "date can not be null");
+ this.qualityGate = qualityGate;
+ }
+
+ @Override
+ public CeTask getCeTask() {
+ return ceTask;
+ }
+
+ @Override
+ public Project getProject() {
+ return project;
+ }
+
+ @Override
+ @CheckForNull
+ public QualityGate getQualityGate() {
+ return qualityGate;
+ }
+
+ @Override
+ public Date getDate() {
+ return date;
+ }
+
+ @Override
+ public String toString() {
+ return "ProjectAnalysis{" +
+ "ceTask=" + ceTask +
+ ", project=" + project +
+ ", date=" + date +
+ ", qualityGate=" + qualityGate +
+ '}';
+ }
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.posttask;
+
+import javax.annotation.concurrent.Immutable;
+import org.sonar.api.ce.posttask.Project;
+
+import static java.util.Objects.requireNonNull;
+
+@Immutable
+class ProjectImpl implements Project {
+ private final String uuid;
+ private final String key;
+ private final String name;
+
+ ProjectImpl(String uuid, String key, String name) {
+ this.uuid = requireNonNull(uuid, "uuid can not be null");
+ this.key = requireNonNull(key, "key can not be null");
+ this.name = requireNonNull(name, "name can not be null");
+ }
+
+ @Override
+ public String getUuid() {
+ return uuid;
+ }
+
+ @Override
+ public String getKey() {
+ return key;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String toString() {
+ return "ProjectImpl{" +
+ "uuid='" + uuid + '\'' +
+ ", key='" + key + '\'' +
+ ", name='" + name + '\'' +
+ '}';
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.posttask;
+
+import com.google.common.collect.ImmutableList;
+import java.util.Collection;
+import javax.annotation.concurrent.Immutable;
+import org.sonar.api.ce.posttask.QualityGate;
+
+import static java.util.Objects.requireNonNull;
+
+@Immutable
+class QualityGateImpl implements QualityGate {
+ private final String id;
+ private final String name;
+ private final Status status;
+ private final Collection<Condition> conditions;
+
+ public QualityGateImpl(String id, String name, Status status, Collection<Condition> conditions) {
+ this.id = requireNonNull(id, "id can not be null");
+ this.name = requireNonNull(name, "name can not be null");
+ this.status = requireNonNull(status, "status can not be null");
+ this.conditions = ImmutableList.copyOf(requireNonNull(conditions, "conditions can not be null"));
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public Status getStatus() {
+ return status;
+ }
+
+ @Override
+ public Collection<Condition> getConditions() {
+ return conditions;
+ }
+
+ @Override
+ public String toString() {
+ return "QualityGateImpl{" +
+ "id='" + id + '\'' +
+ ", name='" + name + '\'' +
+ ", status=" + status +
+ ", conditions=" + conditions +
+ '}';
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.posttask;
+
+import javax.annotation.ParametersAreNonnullByDefault;
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.qualitygate;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
+@Immutable
+public class ConditionStatus {
+ public static final ConditionStatus NO_VALUE_STATUS = new ConditionStatus(EvaluationStatus.NO_VALUE, null);
+
+ private final EvaluationStatus status;
+ @CheckForNull
+ private final String value;
+
+ private ConditionStatus(EvaluationStatus status, @Nullable String value) {
+ this.status = requireNonNull(status, "status can not be null");
+ this.value = value;
+ }
+
+ public static ConditionStatus create(EvaluationStatus status, String value) {
+ requireNonNull(status, "status can not be null");
+ checkArgument(status != EvaluationStatus.NO_VALUE, "EvaluationStatus 'NO_VALUE' can not be used with this method, use constant ConditionStatus.NO_VALUE_STATUS instead.");
+ requireNonNull(value, "value can not be null");
+ return new ConditionStatus(status, value);
+ }
+
+ public EvaluationStatus getStatus() {
+ return status;
+ }
+
+ /**
+ * @return {@code null} when {@link #getStatus()} is {@link EvaluationStatus#NO_VALUE}, otherwise non {@code null}
+ */
+ @CheckForNull
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ return "ConditionStatus{" +
+ "status=" + status +
+ ", value='" + value + '\'' +
+ '}';
+ }
+
+ public enum EvaluationStatus {
+ NO_VALUE, OK, WARN, ERROR
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.qualitygate;
+
+import java.util.Map;
+
+public interface MutableQualityGateStatusHolder extends QualityGateStatusHolder {
+ /**
+ * Sets the status of the quality gate and its conditions in the holder.
+ *
+ * @throws NullPointerException if either {@code globalStatus} or {@code statusPerCondition} is {@code null}
+ * @throws IllegalArgumentException if {@code statusPerCondition} is empty
+ * @throws IllegalStateException if the status has already been set in the holder
+ */
+ void setStatus(QualityGateStatus globalStatus, Map<Condition, ConditionStatus> statusPerCondition);
+}
@Immutable
public class QualityGate {
+ private final long id;
private final String name;
private final Set<Condition> conditions;
- public QualityGate(String name, Iterable<Condition> conditions) {
+ public QualityGate(long id, String name, Iterable<Condition> conditions) {
+ this.id = id;
this.name = Objects.requireNonNull(name);
this.conditions = from(conditions).filter(notNull()).toSet();
}
+ public long getId() {
+ return id;
+ }
+
public String getName() {
return name;
}
private QualityGate toQualityGate(QualityGateDto qualityGateDto) {
Iterable<Condition> conditions = from(conditionDao.selectForQualityGate(qualityGateDto.getId())).transform(conditionDtoToBean);
- return new QualityGate(qualityGateDto.getName(), conditions);
+ return new QualityGate(qualityGateDto.getId(), qualityGateDto.getName(), conditions);
}
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.qualitygate;
+
+public enum QualityGateStatus {
+ OK, WARN, ERROR
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.qualitygate;
+
+import java.util.Map;
+
+public interface QualityGateStatusHolder {
+
+ /**
+ * The global status of the quality gate (if there is a quality gate on the project).
+ *
+ * @throws IllegalStateException if status has not yet been set in the holder
+ * @see QualityGateHolder#getQualityGate()
+ */
+ QualityGateStatus getStatus();
+
+ /**
+ * The status per condition of the quality gate (if there is a quality gate on the project).
+ *
+ * @throws IllegalStateException if status has not yet been set in the holder
+ * @see QualityGateHolder#getQualityGate()
+ */
+ Map<Condition, ConditionStatus> getStatusPerConditions();
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.qualitygate;
+
+import com.google.common.collect.ImmutableMap;
+import java.util.Map;
+import javax.annotation.CheckForNull;
+
+import static com.google.common.base.Preconditions.checkState;
+import static java.util.Objects.requireNonNull;
+
+public class QualityGateStatusHolderImpl implements MutableQualityGateStatusHolder {
+ @CheckForNull
+ private QualityGateStatus status;
+ @CheckForNull
+ private Map<Condition, ConditionStatus> statusPerCondition;
+
+ @Override
+ public QualityGateStatus getStatus() {
+ checkInitialized();
+
+ return status;
+ }
+
+ @Override
+ public Map<Condition, ConditionStatus> getStatusPerConditions() {
+ checkInitialized();
+
+ return statusPerCondition;
+ }
+
+ private void checkInitialized() {
+ checkState(status != null, "Quality gate status has not been set yet");
+ }
+
+ @Override
+ public void setStatus(QualityGateStatus globalStatus, Map<Condition, ConditionStatus> statusPerCondition) {
+ checkState(status == null, "Quality gate status has already been set in the holder");
+ requireNonNull(globalStatus, "global status can not be null");
+ requireNonNull(statusPerCondition, "status per condition can not be null");
+
+ this.status = globalStatus;
+ this.statusPerCondition = ImmutableMap.copyOf(statusPerCondition);
+ }
+}
*/
package org.sonar.server.computation.step;
+import com.google.common.base.Function;
import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableMap;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
import java.util.Set;
+import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.server.computation.metric.MetricRepository;
import org.sonar.server.computation.qualitygate.Condition;
import org.sonar.server.computation.qualitygate.ConditionEvaluator;
+import org.sonar.server.computation.qualitygate.ConditionStatus;
import org.sonar.server.computation.qualitygate.EvaluationResult;
import org.sonar.server.computation.qualitygate.EvaluationResultTextConverter;
+import org.sonar.server.computation.qualitygate.MutableQualityGateStatusHolder;
import org.sonar.server.computation.qualitygate.QualityGate;
import org.sonar.server.computation.qualitygate.QualityGateHolder;
+import static com.google.common.collect.FluentIterable.from;
+import static java.lang.String.format;
import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;
+import static org.sonar.server.computation.qualitygate.ConditionStatus.NO_VALUE_STATUS;
+import static org.sonar.server.computation.qualitygate.ConditionStatus.create;
/**
* This step:
private final TreeRootHolder treeRootHolder;
private final QualityGateHolder qualityGateHolder;
+ private final MutableQualityGateStatusHolder qualityGateStatusHolder;
private final MeasureRepository measureRepository;
private final MetricRepository metricRepository;
private final EvaluationResultTextConverter evaluationResultTextConverter;
- public QualityGateMeasuresStep(TreeRootHolder treeRootHolder, QualityGateHolder qualityGateHolder,
+ public QualityGateMeasuresStep(TreeRootHolder treeRootHolder,
+ QualityGateHolder qualityGateHolder, MutableQualityGateStatusHolder qualityGateStatusHolder,
MeasureRepository measureRepository, MetricRepository metricRepository,
EvaluationResultTextConverter evaluationResultTextConverter) {
this.treeRootHolder = treeRootHolder;
this.qualityGateHolder = qualityGateHolder;
+ this.qualityGateStatusHolder = qualityGateStatusHolder;
this.evaluationResultTextConverter = evaluationResultTextConverter;
this.measureRepository = measureRepository;
this.metricRepository = metricRepository;
}
private void executeForProject(Component project) {
- QualityGateDetailsDataBuilder builder = new QualityGateDetailsDataBuilder();
-
Optional<QualityGate> qualityGate = qualityGateHolder.getQualityGate();
if (qualityGate.isPresent()) {
+ QualityGateDetailsDataBuilder builder = new QualityGateDetailsDataBuilder();
updateMeasures(project, qualityGate.get().getConditions(), builder);
addProjectMeasure(project, builder);
+
+ updateQualityGateStatusHolder(qualityGate.get(), builder);
}
}
+ private void updateQualityGateStatusHolder(QualityGate qualityGate, QualityGateDetailsDataBuilder builder) {
+ qualityGateStatusHolder.setStatus(convert(builder.getGlobalLevel()), createStatusPerCondition(qualityGate.getConditions(), builder.getEvaluatedConditions()));
+ }
+
+ private static ConditionStatus.EvaluationStatus toEvaluationStatus(Measure.Level globalLevel) {
+ switch (globalLevel) {
+ case OK:
+ return ConditionStatus.EvaluationStatus.OK;
+ case WARN:
+ return ConditionStatus.EvaluationStatus.WARN;
+ case ERROR:
+ return ConditionStatus.EvaluationStatus.ERROR;
+ default:
+ throw new IllegalArgumentException(format(
+ "Unsupported value '%s' of Measure.Level can not be converted to EvaluationStatus",
+ globalLevel));
+ }
+ }
+
+ private static org.sonar.server.computation.qualitygate.QualityGateStatus convert(Measure.Level globalLevel) {
+ switch (globalLevel) {
+ case OK:
+ return org.sonar.server.computation.qualitygate.QualityGateStatus.OK;
+ case WARN:
+ return org.sonar.server.computation.qualitygate.QualityGateStatus.WARN;
+ case ERROR:
+ return org.sonar.server.computation.qualitygate.QualityGateStatus.ERROR;
+ default:
+ throw new IllegalArgumentException(format(
+ "Unsupported value '%s' of Measure.Level can not be converted to QualityGateStatus",
+ globalLevel));
+ }
+ }
+
+ private static Map<Condition, ConditionStatus> createStatusPerCondition(Iterable<Condition> conditions, Iterable<EvaluatedCondition> evaluatedConditions) {
+ Map<Condition, EvaluatedCondition> evaluatedConditionPerCondition = from(evaluatedConditions)
+ .uniqueIndex(EvaluatedConditionToCondition.INSTANCE);
+
+ ImmutableMap.Builder<Condition, ConditionStatus> builder = ImmutableMap.builder();
+ for (Condition condition : conditions) {
+ EvaluatedCondition evaluatedCondition = evaluatedConditionPerCondition.get(condition);
+
+ if (evaluatedCondition == null) {
+ builder.put(condition, NO_VALUE_STATUS);
+ } else {
+ builder.put(condition, create(toEvaluationStatus(evaluatedCondition.getLevel()), evaluatedCondition.getActualValue()));
+ }
+ }
+ return builder.build();
+ }
+
private void updateMeasures(Component project, Set<Condition> conditions, QualityGateDetailsDataBuilder builder) {
for (Condition condition : conditions) {
Optional<Measure> measure = measureRepository.getRawMeasure(project, condition.getMetric());
return evaluatedConditions;
}
}
+
+ private enum EvaluatedConditionToCondition implements Function<EvaluatedCondition, Condition> {
+ INSTANCE;
+
+ @Override
+ @Nonnull
+ public Condition apply(@Nonnull EvaluatedCondition input) {
+ return input.getCondition();
+ }
+ }
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.posttask;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.ce.posttask.CeTask;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class CeTaskImplTest {
+ private static final String SOME_ID = "some id";
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ @Test
+ public void constructor_throws_NPE_if_id_is_null() {
+ expectedException.expect(NullPointerException.class);
+ expectedException.expectMessage("id can not be null");
+
+ new CeTaskImpl(null, CeTask.Status.SUCCESS);
+ }
+
+ @Test
+ public void constructor_throws_NPE_if_status_is_null() {
+ expectedException.expect(NullPointerException.class);
+ expectedException.expectMessage("status can not be null");
+
+ new CeTaskImpl(SOME_ID, null);
+ }
+
+ @Test
+ public void verify_getters() {
+ CeTaskImpl underTest = new CeTaskImpl(SOME_ID, CeTask.Status.FAILED);
+
+ assertThat(underTest.getId()).isEqualTo(SOME_ID);
+ assertThat(underTest.getStatus()).isEqualTo(CeTask.Status.FAILED);
+ }
+
+ @Test
+ public void verify_toString() {
+ assertThat(new CeTaskImpl(SOME_ID, CeTask.Status.SUCCESS).toString()).isEqualTo("CeTaskImpl{id='some id', status=SUCCESS}");
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.posttask;
+
+import com.tngtech.java.junit.dataprovider.DataProvider;
+import com.tngtech.java.junit.dataprovider.DataProviderRunner;
+import com.tngtech.java.junit.dataprovider.UseDataProvider;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.sonar.api.ce.posttask.QualityGate;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@RunWith(DataProviderRunner.class)
+public class ConditionImplTest {
+ private static final String METRIC_KEY = "metricKey";
+ private static final String ERROR_THRESHOLD = "error threshold";
+ private static final String WARN_THRESHOLD = "warn threshold";
+ private static final String VALUE = "value";
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ private ConditionImpl.Builder builder = ConditionImpl.newBuilder()
+ .setStatus(QualityGate.EvaluationStatus.OK)
+ .setMetricKey(METRIC_KEY)
+ .setOperator(QualityGate.Operator.GREATER_THAN)
+ .setErrorThreshold(ERROR_THRESHOLD)
+ .setWarningThreshold(WARN_THRESHOLD)
+ .setOnLeakPeriod(true)
+ .setValue(VALUE);
+
+ @Test
+ public void build_throws_NPE_if_status_is_null() {
+ builder.setStatus(null);
+
+ expectedException.expect(NullPointerException.class);
+ expectedException.expectMessage("status can not be null");
+
+ builder.build();
+ }
+
+ @Test
+ public void build_throws_NPE_if_metricKey_is_null() {
+ builder.setMetricKey(null);
+
+ expectedException.expect(NullPointerException.class);
+ expectedException.expectMessage("metricKey can not be null");
+
+ builder.build();
+ }
+
+ @Test
+ public void build_throws_NPE_if_operator_is_null() {
+ builder.setOperator(null);
+
+ expectedException.expect(NullPointerException.class);
+ expectedException.expectMessage("operator can not be null");
+
+ builder.build();
+ }
+
+ @Test
+ public void build_throws_IAE_if_both_thresholds_are_null() {
+ builder.setWarningThreshold(null)
+ .setErrorThreshold(null);
+
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("At least one of errorThreshold and warningThreshold must be non null");
+
+ builder.build();
+ }
+
+ @Test
+ public void getValue_throws_ISE_when_condition_type_is_NO_VALUE() {
+ builder.setStatus(QualityGate.EvaluationStatus.NO_VALUE).setValue(null);
+ ConditionImpl condition = builder.build();
+
+ expectedException.expect(IllegalStateException.class);
+ expectedException.expectMessage("There is no value when status is NO_VALUE");
+
+ condition.getValue();
+ }
+
+ @DataProvider
+ public static Object[][] allStatusesButNO_VALUE() {
+ Object[][] res = new Object[QualityGate.EvaluationStatus.values().length - 1][1];
+ int i = 0;
+ for (QualityGate.EvaluationStatus status : QualityGate.EvaluationStatus.values()) {
+ if (status != QualityGate.EvaluationStatus.NO_VALUE) {
+ res[i][0] = status;
+ i++;
+ }
+ }
+ return res;
+ }
+
+ @Test
+ @UseDataProvider("allStatusesButNO_VALUE")
+ public void build_throws_IAE_if_value_is_null_but_status_is_not_NO_VALUE(QualityGate.EvaluationStatus status) {
+ builder.setStatus(status)
+ .setValue(null);
+
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("value can not be null when status is not NO_VALUE");
+
+ builder.build();
+ }
+
+ @Test
+ public void build_throws_IAE_if_value_is_not_null_but_status_is_NO_VALUE() {
+ builder.setStatus(QualityGate.EvaluationStatus.NO_VALUE);
+
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("value must be null when status is NO_VALUE");
+
+ builder.build();
+ }
+
+ @Test
+ public void toString_ConditionImpl_of_type_different_from_NO_VALUE() {
+ assertThat(builder.build().toString())
+ .isEqualTo(
+ "ConditionImpl{status=OK, metricKey='metricKey', operator=GREATER_THAN, errorThreshold='error threshold', warningThreshold='warn threshold', onLeakPeriod=true, value='value'}");
+ }
+
+ @Test
+ public void toString_ConditionImpl_of_type_NO_VALUE() {
+ builder.setStatus(QualityGate.EvaluationStatus.NO_VALUE)
+ .setValue(null);
+
+ assertThat(builder.build().toString())
+ .isEqualTo(
+ "ConditionImpl{status=NO_VALUE, metricKey='metricKey', operator=GREATER_THAN, errorThreshold='error threshold', warningThreshold='warn threshold', onLeakPeriod=true, value='null'}");
+ }
+
+ @Test
+ public void verify_getters() {
+ ConditionImpl underTest = builder.build();
+
+ assertThat(underTest.getStatus()).isEqualTo(QualityGate.EvaluationStatus.OK);
+ assertThat(underTest.getMetricKey()).isEqualTo(METRIC_KEY);
+ assertThat(underTest.getOperator()).isEqualTo(QualityGate.Operator.GREATER_THAN);
+ assertThat(underTest.getErrorThreshold()).isEqualTo(ERROR_THRESHOLD);
+ assertThat(underTest.getWarningThreshold()).isEqualTo(WARN_THRESHOLD);
+ assertThat(underTest.isOnLeakPeriod()).isEqualTo(true);
+ assertThat(underTest.getValue()).isEqualTo(VALUE);
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.posttask;
+
+import com.tngtech.java.junit.dataprovider.DataProvider;
+import com.tngtech.java.junit.dataprovider.DataProviderRunner;
+import com.tngtech.java.junit.dataprovider.UseDataProvider;
+import java.util.Collections;
+import java.util.Map;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.sonar.api.ce.posttask.QualityGate;
+import org.sonar.server.computation.metric.Metric;
+import org.sonar.server.computation.qualitygate.Condition;
+import org.sonar.server.computation.qualitygate.ConditionStatus;
+
+import static com.google.common.collect.ImmutableMap.of;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@RunWith(DataProviderRunner.class)
+public class ConditionToConditionTest {
+ private static final String METRIC_KEY = "metricKey";
+ private static final String ERROR_THRESHOLD = "error threshold";
+ private static final String WARN_THRESHOLD = "warn threshold";
+ private static final Map<Condition, ConditionStatus> NO_STATUS_PER_CONDITIONS = Collections.emptyMap();
+ private static final String SOME_VALUE = "some value";
+ private static final ConditionStatus SOME_CONDITION_STATUS = ConditionStatus.create(ConditionStatus.EvaluationStatus.OK, SOME_VALUE);
+ private static final Condition SOME_CONDITION = new Condition(newMetric(METRIC_KEY), Condition.Operator.EQUALS.getDbValue(), ERROR_THRESHOLD, WARN_THRESHOLD, 1);
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ @Test
+ public void apply_throws_NPE_if_Condition_argument_is_null() {
+ ConditionToCondition underTest = new ConditionToCondition(NO_STATUS_PER_CONDITIONS);
+
+ expectedException.expect(NullPointerException.class);
+
+ underTest.apply(null);
+ }
+
+ @Test
+ public void apply_throws_ISE_if_there_is_no_ConditionStatus_for_Condition_argument() {
+ ConditionToCondition underTest = new ConditionToCondition(NO_STATUS_PER_CONDITIONS);
+
+ expectedException.expect(IllegalStateException.class);
+ expectedException.expectMessage("Missing ConditionStatus for condition on metric key " + METRIC_KEY);
+
+ underTest.apply(SOME_CONDITION);
+ }
+
+ @Test
+ @UseDataProvider("allEvaluationStatuses")
+ public void apply_converts_all_values_of_status(ConditionStatus.EvaluationStatus status) {
+ ConditionToCondition underTest = new ConditionToCondition(of(
+ SOME_CONDITION,
+ status == ConditionStatus.EvaluationStatus.NO_VALUE ? ConditionStatus.NO_VALUE_STATUS : ConditionStatus.create(status, SOME_VALUE)));
+
+ assertThat(underTest.apply(SOME_CONDITION).getStatus().name()).isEqualTo(status.name());
+ }
+
+ @Test
+ public void apply_converts_key_from_metric() {
+ ConditionToCondition underTest = new ConditionToCondition(of(SOME_CONDITION, SOME_CONDITION_STATUS));
+
+ assertThat(underTest.apply(SOME_CONDITION).getMetricKey()).isEqualTo(METRIC_KEY);
+ }
+
+ @Test
+ public void apply_copies_thresholds() {
+ ConditionToCondition underTest = new ConditionToCondition(of(SOME_CONDITION, SOME_CONDITION_STATUS));
+
+ assertThat(underTest.apply(SOME_CONDITION).getErrorThreshold()).isEqualTo(ERROR_THRESHOLD);
+ assertThat(underTest.apply(SOME_CONDITION).getWarningThreshold()).isEqualTo(WARN_THRESHOLD);
+ }
+
+ @Test
+ @UseDataProvider("allOperatorValues")
+ public void apply_converts_all_values_of_operator(Condition.Operator operator) {
+ Condition condition = new Condition(newMetric(METRIC_KEY), operator.getDbValue(), ERROR_THRESHOLD, WARN_THRESHOLD, 1);
+ ConditionToCondition underTest = new ConditionToCondition(of(condition, SOME_CONDITION_STATUS));
+
+ assertThat(underTest.apply(condition).getOperator().name()).isEqualTo(operator.name());
+ }
+
+ @Test
+ public void apply_sets_onLeakPeriod_flag_when_Condition_has_non_null_Period() {
+ Condition noPeriodCondition = new Condition(newMetric(METRIC_KEY), Condition.Operator.NOT_EQUALS.getDbValue(), ERROR_THRESHOLD, WARN_THRESHOLD, null);
+ ConditionToCondition underTest = new ConditionToCondition(of(
+ SOME_CONDITION, SOME_CONDITION_STATUS,
+ noPeriodCondition, SOME_CONDITION_STATUS));
+
+ assertThat(underTest.apply(SOME_CONDITION).isOnLeakPeriod()).isTrue();
+ assertThat(underTest.apply(noPeriodCondition).isOnLeakPeriod()).isFalse();
+ }
+
+ @Test
+ public void apply_copies_value() {
+ Condition otherCondition = new Condition(newMetric(METRIC_KEY), Condition.Operator.NOT_EQUALS.getDbValue(), ERROR_THRESHOLD, WARN_THRESHOLD, null);
+ ConditionToCondition underTest = new ConditionToCondition(of(
+ SOME_CONDITION, SOME_CONDITION_STATUS,
+ otherCondition, ConditionStatus.NO_VALUE_STATUS
+ ));
+
+ assertThat(underTest.apply(SOME_CONDITION).getValue()).isEqualTo(SOME_VALUE);
+
+ QualityGate.Condition res = underTest.apply(otherCondition);
+
+ expectedException.expect(IllegalStateException.class);
+ expectedException.expectMessage("There is no value when status is NO_VALUE");
+
+ res.getValue();
+ }
+
+ @DataProvider
+ public static Object[][] allEvaluationStatuses() {
+ Object[][] res = new Object[ConditionStatus.EvaluationStatus.values().length][1];
+ int i = 0;
+ for (ConditionStatus.EvaluationStatus status : ConditionStatus.EvaluationStatus.values()) {
+ res[i][0] = status;
+ i++;
+ }
+ return res;
+ }
+
+ @DataProvider
+ public static Object[][] allOperatorValues() {
+ Object[][] res = new Object[Condition.Operator.values().length][1];
+ int i = 0;
+ for (Condition.Operator operator : Condition.Operator.values()) {
+ res[i][0] = operator;
+ i++;
+ }
+ return res;
+ }
+
+ private static Metric newMetric(String metricKey) {
+ Metric metric = mock(Metric.class);
+ when(metric.getKey()).thenReturn(metricKey);
+ return metric;
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.posttask;
+
+import com.google.common.collect.ImmutableMap;
+import com.tngtech.java.junit.dataprovider.DataProvider;
+import com.tngtech.java.junit.dataprovider.DataProviderRunner;
+import com.tngtech.java.junit.dataprovider.UseDataProvider;
+import java.util.Date;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
+import org.sonar.api.ce.posttask.PostProjectAnalysisTask;
+import org.sonar.api.ce.posttask.Project;
+import org.sonar.ce.queue.CeTask;
+import org.sonar.server.computation.analysis.AnalysisMetadataHolderRule;
+import org.sonar.server.computation.metric.Metric;
+import org.sonar.server.computation.qualitygate.Condition;
+import org.sonar.server.computation.qualitygate.ConditionStatus;
+import org.sonar.server.computation.qualitygate.MutableQualityGateHolderRule;
+import org.sonar.server.computation.qualitygate.MutableQualityGateStatusHolderRule;
+import org.sonar.server.computation.qualitygate.QualityGate;
+import org.sonar.server.computation.qualitygate.QualityGateStatus;
+
+import static com.google.common.collect.ImmutableList.of;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(DataProviderRunner.class)
+public class PostProjectAnalysisTasksExecutorTest {
+ private static final long QUALITY_GATE_ID = 98451;
+ private static final String QUALITY_GATE_NAME = "qualityGate name";
+ private static final Condition CONDITION_1 = createCondition("metric key 1");
+ private static final Condition CONDITION_2 = createCondition("metric key 2");
+
+ @Rule
+ public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule()
+ .setAnalysisDate(8465132498L);
+ @Rule
+ public MutableQualityGateHolderRule qualityGateHolder = new MutableQualityGateHolderRule();
+ @Rule
+ public MutableQualityGateStatusHolderRule qualityGateStatusHolder = new MutableQualityGateStatusHolderRule();
+
+ private ArgumentCaptor<PostProjectAnalysisTask.ProjectAnalysis> projectAnalysisArgumentCaptor = ArgumentCaptor.forClass(PostProjectAnalysisTask.ProjectAnalysis.class);
+ private CeTask ceTask = new CeTask.Builder()
+ .setType("type")
+ .setUuid("uuid")
+ .setComponentKey("component key")
+ .setComponentName("component name")
+ .setComponentUuid("component uuid")
+ .build();
+ private PostProjectAnalysisTask postProjectAnalysisTask = mock(PostProjectAnalysisTask.class);
+ private PostProjectAnalysisTasksExecutor underTest = new PostProjectAnalysisTasksExecutor(
+ ceTask, analysisMetadataHolder, qualityGateHolder, qualityGateStatusHolder,
+ new PostProjectAnalysisTask[] {postProjectAnalysisTask});
+
+ @Before
+ public void setUp() throws Exception {
+ qualityGateHolder.setQualityGate(new QualityGate(QUALITY_GATE_ID, QUALITY_GATE_NAME, of(CONDITION_1, CONDITION_2)));
+ qualityGateStatusHolder.setStatus(QualityGateStatus.OK, ImmutableMap.of(
+ CONDITION_1, ConditionStatus.create(ConditionStatus.EvaluationStatus.OK, "value"),
+ CONDITION_2, ConditionStatus.NO_VALUE_STATUS));
+ }
+
+ @Test
+ @UseDataProvider("booleanValues")
+ public void does_not_fail_when_there_is_no_PostProjectAnalysisTasksExecutor(boolean allStepsExecuted) {
+ new PostProjectAnalysisTasksExecutor(ceTask, analysisMetadataHolder, qualityGateHolder, qualityGateStatusHolder)
+ .finished(allStepsExecuted);
+ }
+
+ @Test
+ @UseDataProvider("booleanValues")
+ public void finished_calls_all_PostProjectAnalysisTask_in_order_of_the_array_and_passes_the_same_object_to_all(boolean allStepsExecuted) {
+ PostProjectAnalysisTask postProjectAnalysisTask1 = mock(PostProjectAnalysisTask.class);
+ PostProjectAnalysisTask postProjectAnalysisTask2 = mock(PostProjectAnalysisTask.class);
+ InOrder inOrder = inOrder(postProjectAnalysisTask1, postProjectAnalysisTask2);
+
+ new PostProjectAnalysisTasksExecutor(
+ ceTask, analysisMetadataHolder, qualityGateHolder, qualityGateStatusHolder,
+ new PostProjectAnalysisTask[] {postProjectAnalysisTask1, postProjectAnalysisTask2})
+ .finished(allStepsExecuted);
+
+ inOrder.verify(postProjectAnalysisTask1).finished(projectAnalysisArgumentCaptor.capture());
+ inOrder.verify(postProjectAnalysisTask2).finished(projectAnalysisArgumentCaptor.capture());
+ inOrder.verifyNoMoreInteractions();
+
+ List<PostProjectAnalysisTask.ProjectAnalysis> allValues = projectAnalysisArgumentCaptor.getAllValues();
+ assertThat(allValues).hasSize(2);
+ assertThat(allValues.get(0)).isSameAs(allValues.get(1));
+ }
+
+ @Test
+ @UseDataProvider("booleanValues")
+ public void CeTask_status_depends_on_finished_method_argument_is_true_or_false(boolean allStepsExecuted) {
+ underTest.finished(allStepsExecuted);
+
+ verify(postProjectAnalysisTask).finished(projectAnalysisArgumentCaptor.capture());
+
+ assertThat(projectAnalysisArgumentCaptor.getValue().getCeTask().getStatus())
+ .isEqualTo(
+ allStepsExecuted ? org.sonar.api.ce.posttask.CeTask.Status.SUCCESS : org.sonar.api.ce.posttask.CeTask.Status.FAILED);
+ }
+
+ @Test
+ public void ceTask_uuid_is_UUID_of_CeTask() {
+ underTest.finished(true);
+
+ verify(postProjectAnalysisTask).finished(projectAnalysisArgumentCaptor.capture());
+
+ assertThat(projectAnalysisArgumentCaptor.getValue().getCeTask().getId())
+ .isEqualTo(ceTask.getUuid());
+ }
+
+ @Test
+ public void project_uuid_key_and_name_come_from_CeTask() {
+ underTest.finished(true);
+
+ verify(postProjectAnalysisTask).finished(projectAnalysisArgumentCaptor.capture());
+
+ Project project = projectAnalysisArgumentCaptor.getValue().getProject();
+ assertThat(project.getUuid()).isEqualTo(ceTask.getComponentUuid());
+ assertThat(project.getKey()).isEqualTo(ceTask.getComponentKey());
+ assertThat(project.getName()).isEqualTo(ceTask.getComponentName());
+ }
+
+ @Test
+ public void analysisDate_comes_from_AnalysisMetadataHolder() {
+ underTest.finished(true);
+
+ verify(postProjectAnalysisTask).finished(projectAnalysisArgumentCaptor.capture());
+
+ assertThat(projectAnalysisArgumentCaptor.getValue().getDate())
+ .isEqualTo(new Date(analysisMetadataHolder.getAnalysisDate()));
+ }
+
+ @Test
+ public void qualityGate_is_null_when_finished_method_argument_is_false() {
+ underTest.finished(false);
+
+ verify(postProjectAnalysisTask).finished(projectAnalysisArgumentCaptor.capture());
+
+ assertThat(projectAnalysisArgumentCaptor.getValue().getQualityGate()).isNull();
+ }
+
+ @Test
+ public void qualityGate_is_populated_when_finished_method_argument_is_true() {
+ underTest.finished(true);
+
+ verify(postProjectAnalysisTask).finished(projectAnalysisArgumentCaptor.capture());
+
+ org.sonar.api.ce.posttask.QualityGate qualityGate = projectAnalysisArgumentCaptor.getValue().getQualityGate();
+ assertThat(qualityGate.getStatus()).isEqualTo(org.sonar.api.ce.posttask.QualityGate.Status.OK);
+ assertThat(qualityGate.getId()).isEqualTo(String.valueOf(QUALITY_GATE_ID));
+ assertThat(qualityGate.getName()).isEqualTo(QUALITY_GATE_NAME);
+ assertThat(qualityGate.getConditions()).hasSize(2);
+ }
+
+ @DataProvider
+ public static Object[][] booleanValues() {
+ return new Object[][] {
+ {true},
+ {false}
+ };
+ }
+
+ private static Condition createCondition(String metricKey) {
+ Metric metric = mock(Metric.class);
+ when(metric.getKey()).thenReturn(metricKey);
+ return new Condition(metric, Condition.Operator.EQUALS.getDbValue(), "error threshold", "warn threshold", null);
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.posttask;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class ProjectImplTest {
+ private static final String SOME_UUID = "some uuid";
+ private static final String SOME_KEY = "some key";
+ private static final String SOME_NAME = "some name";
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ @Test
+ public void constructor_throws_NPE_if_uuid_is_null() {
+ expectedException.expect(NullPointerException.class);
+ expectedException.expectMessage("uuid can not be null");
+
+ new ProjectImpl(null, SOME_KEY, SOME_NAME);
+ }
+
+ @Test
+ public void constructor_throws_NPE_if_key_is_null() {
+ expectedException.expect(NullPointerException.class);
+ expectedException.expectMessage("key can not be null");
+
+ new ProjectImpl(SOME_UUID, null, SOME_NAME);
+ }
+
+ @Test
+ public void constructor_throws_NPE_if_name_is_null() {
+ expectedException.expect(NullPointerException.class);
+ expectedException.expectMessage("name can not be null");
+
+ new ProjectImpl(SOME_UUID, SOME_KEY, null);
+ }
+
+ @Test
+ public void verify_getters() {
+ ProjectImpl underTest = new ProjectImpl(SOME_UUID, SOME_KEY, SOME_NAME);
+
+ assertThat(underTest.getUuid()).isEqualTo(SOME_UUID);
+ assertThat(underTest.getKey()).isEqualTo(SOME_KEY);
+ assertThat(underTest.getName()).isEqualTo(SOME_NAME);
+ }
+
+ @Test
+ public void verify_toString() {
+ assertThat(new ProjectImpl(SOME_UUID, SOME_KEY, SOME_NAME).toString())
+ .isEqualTo("ProjectImpl{uuid='some uuid', key='some key', name='some name'}");
+
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.posttask;
+
+import com.google.common.collect.ImmutableList;
+import java.util.Collections;
+import java.util.List;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.ce.posttask.QualityGate;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class QualityGateImplTest {
+ private static final String SOME_ID = "some id";
+ private static final String SOME_NAME = "some name";
+ private static final QualityGate.Status SOME_STATUS = QualityGate.Status.OK;
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ private QualityGate.Condition condition = mock(QualityGate.Condition.class);
+ private QualityGateImpl underTest = new QualityGateImpl(SOME_ID, SOME_NAME, SOME_STATUS, ImmutableList.of(condition));
+
+ @Test
+ public void constructor_throws_NPE_if_id_argument_is_null() {
+ expectedException.expect(NullPointerException.class);
+ expectedException.expectMessage("id can not be null");
+
+ new QualityGateImpl(null, SOME_NAME, SOME_STATUS, Collections.<QualityGate.Condition>emptyList());
+ }
+
+ @Test
+ public void constructor_throws_NPE_if_name_argument_is_null() {
+ expectedException.expect(NullPointerException.class);
+ expectedException.expectMessage("name can not be null");
+
+ new QualityGateImpl(SOME_ID, null, SOME_STATUS, Collections.<QualityGate.Condition>emptyList());
+ }
+
+ @Test
+ public void constructor_throws_NPE_if_status_argument_is_null() {
+ expectedException.expect(NullPointerException.class);
+ expectedException.expectMessage("status can not be null");
+
+ new QualityGateImpl(SOME_ID, SOME_NAME, null, Collections.<QualityGate.Condition>emptyList());
+ }
+
+ @Test
+ public void constructor_throws_NPE_if_conditions_argument_is_null() {
+ expectedException.expect(NullPointerException.class);
+ expectedException.expectMessage("conditions can not be null");
+
+ new QualityGateImpl(SOME_ID, SOME_NAME, SOME_STATUS, null);
+ }
+
+ @Test
+ public void verify_getters() {
+ List<QualityGate.Condition> conditions = ImmutableList.of(condition);
+
+ QualityGateImpl underTest = new QualityGateImpl(SOME_ID, SOME_NAME, SOME_STATUS, conditions);
+
+ assertThat(underTest.getId()).isEqualTo(SOME_ID);
+ assertThat(underTest.getName()).isEqualTo(SOME_NAME);
+ assertThat(underTest.getStatus()).isEqualTo(SOME_STATUS);
+ assertThat(underTest.getConditions()).isEqualTo(conditions);
+ }
+
+ @Test
+ public void verify_toString() {
+ when(condition.toString()).thenReturn("{Condition}");
+
+ assertThat(underTest.toString())
+ .isEqualTo("QualityGateImpl{id='some id', name='some name', status=OK, conditions=[{Condition}]}");
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.qualitygate;
+
+import com.tngtech.java.junit.dataprovider.DataProvider;
+import com.tngtech.java.junit.dataprovider.DataProviderRunner;
+import com.tngtech.java.junit.dataprovider.UseDataProvider;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.server.computation.qualitygate.ConditionStatus.EvaluationStatus.NO_VALUE;
+import static org.sonar.server.computation.qualitygate.ConditionStatus.EvaluationStatus.OK;
+import static org.sonar.server.computation.qualitygate.ConditionStatus.EvaluationStatus.values;
+
+@RunWith(DataProviderRunner.class)
+public class ConditionStatusTest {
+ private static final String SOME_VALUE = "value";
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ @Test
+ public void create_throws_NPE_if_status_argument_is_null() {
+ expectedException.expect(NullPointerException.class);
+ expectedException.expectMessage("status can not be null");
+
+ ConditionStatus.create(null, SOME_VALUE);
+ }
+
+ @Test
+ public void create_throws_IAE_if_status_argument_is_NO_VALUE() {
+ expectedException.expect(IllegalArgumentException.class);
+ expectedException.expectMessage("EvaluationStatus 'NO_VALUE' can not be used with this method, use constant ConditionStatus.NO_VALUE_STATUS instead.");
+
+ ConditionStatus.create(NO_VALUE, SOME_VALUE);
+ }
+
+ @Test
+ @UseDataProvider("allStatusesButNO_VALUE")
+ public void create_throws_NPE_if_value_is_null_and_status_argument_is_not_NO_VALUE(ConditionStatus.EvaluationStatus status) {
+ expectedException.expect(NullPointerException.class);
+ expectedException.expectMessage("value can not be null");
+
+ ConditionStatus.create(status, null);
+ }
+
+ @Test
+ public void verify_getters() {
+ ConditionStatus underTest = ConditionStatus.create(OK, SOME_VALUE);
+
+ assertThat(underTest.getStatus()).isEqualTo(OK);
+ assertThat(underTest.getValue()).isEqualTo(SOME_VALUE);
+ }
+
+ @Test
+ public void verify_toString() {
+ assertThat(ConditionStatus.create(OK, SOME_VALUE).toString()).isEqualTo("ConditionStatus{status=OK, value='value'}");
+ assertThat(ConditionStatus.NO_VALUE_STATUS.toString()).isEqualTo("ConditionStatus{status=NO_VALUE, value='null'}");
+ }
+
+ @Test
+ public void constant_NO_VALUE_STATUS_has_status_NO_VALUE_and_null_value() {
+ assertThat(ConditionStatus.NO_VALUE_STATUS.getStatus()).isEqualTo(NO_VALUE);
+ assertThat(ConditionStatus.NO_VALUE_STATUS.getValue()).isNull();
+ }
+
+ @DataProvider
+ public static Object[][] allStatusesButNO_VALUE() {
+ Object[][] res = new Object[values().length - 1][1];
+ int i = 0;
+ for (ConditionStatus.EvaluationStatus status : values()) {
+ if (status != NO_VALUE) {
+ res[i][0] = status;
+ i++;
+ }
+ }
+ return res;
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.qualitygate;
+
+import java.util.Map;
+import org.junit.rules.ExternalResource;
+
+public class MutableQualityGateStatusHolderRule extends ExternalResource implements MutableQualityGateStatusHolder {
+ private MutableQualityGateStatusHolder delegate = new QualityGateStatusHolderImpl();
+
+ @Override
+ public void setStatus(QualityGateStatus globalStatus, Map<Condition, ConditionStatus> statusPerCondition) {
+ delegate.setStatus(globalStatus, statusPerCondition);
+ }
+
+ @Override
+ public QualityGateStatus getStatus() {
+ return delegate.getStatus();
+ }
+
+ @Override
+ public Map<Condition, ConditionStatus> getStatusPerConditions() {
+ return delegate.getStatusPerConditions();
+ }
+
+ @Override
+ protected void after() {
+ reset();
+ }
+
+ public void reset() {
+ this.delegate = new QualityGateStatusHolderImpl();
+ }
+}
public class QualityGateHolderImplTest {
- public static final QualityGate QUALITY_GATE = new QualityGate("name", Collections.<Condition>emptyList());
+ public static final QualityGate QUALITY_GATE = new QualityGate(4612, "name", Collections.<Condition>emptyList());
@Test(expected = IllegalStateException.class)
public void getQualityGate_throws_ISE_if_QualityGate_not_set() {
Optional<QualityGate> res = underTest.findById(SOME_ID);
assertThat(res).isPresent();
+ assertThat(res.get().getId()).isEqualTo(SOME_ID);
assertThat(res.get().getName()).isEqualTo(SOME_NAME);
assertThat(res.get().getConditions()).isEmpty();
}
Optional<QualityGate> res = underTest.findById(SOME_ID);
assertThat(res).isPresent();
+ assertThat(res.get().getId()).isEqualTo(SOME_ID);
assertThat(res.get().getName()).isEqualTo(SOME_NAME);
assertThat(res.get().getConditions()).containsOnly(
new Condition(METRIC_1, CONDITION_1.getOperator(), CONDITION_1.getErrorThreshold(), CONDITION_1.getWarningThreshold(), CONDITION_1.getPeriod()),
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.qualitygate;
+
+import com.tngtech.java.junit.dataprovider.DataProvider;
+import com.tngtech.java.junit.dataprovider.DataProviderRunner;
+import com.tngtech.java.junit.dataprovider.UseDataProvider;
+import java.util.Collections;
+import java.util.Map;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+@RunWith(DataProviderRunner.class)
+public class QualityGateStatusHolderImplTest {
+ private static final Map<Condition, ConditionStatus> SOME_STATUS_PER_CONDITION = Collections.singletonMap(
+ mock(Condition.class), ConditionStatus.create(ConditionStatus.EvaluationStatus.OK, "val"));
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ private QualityGateStatusHolderImpl underTest = new QualityGateStatusHolderImpl();
+
+ @Test
+ public void setStatus_throws_NPE_if_globalStatus_is_null() {
+ expectedException.expect(NullPointerException.class);
+ expectedException.expectMessage("global status can not be null");
+
+ underTest.setStatus(null, SOME_STATUS_PER_CONDITION);
+ }
+
+ @Test
+ public void setStatus_throws_NPE_if_statusPerCondition_is_null() {
+ expectedException.expect(NullPointerException.class);
+ expectedException.expectMessage("status per condition can not be null");
+
+ underTest.setStatus(QualityGateStatus.OK, null);
+ }
+
+ @Test
+ public void setStatus_throws_ISE_if_called_twice() {
+ underTest.setStatus(QualityGateStatus.OK, SOME_STATUS_PER_CONDITION);
+
+ expectedException.expect(IllegalStateException.class);
+ expectedException.expectMessage("Quality gate status has already been set in the holder");
+
+ underTest.setStatus(null, null);
+ }
+
+ @Test
+ public void getStatus_throws_ISE_if_setStatus_not_called_yet() {
+ expectQGNotSetYetISE();
+
+ underTest.getStatus();
+ }
+
+ @Test
+ @UseDataProvider("qualityGateStatusValue")
+ public void getStatus_returns_status_argument_from_setStatus(QualityGateStatus status) {
+ underTest.setStatus(status, SOME_STATUS_PER_CONDITION);
+
+ assertThat(underTest.getStatus()).isEqualTo(status);
+ }
+
+ @Test
+ public void getStatusPerConditions_throws_ISE_if_setStatus_not_called_yet() {
+ expectQGNotSetYetISE();
+
+ underTest.getStatusPerConditions();
+ }
+
+ @Test
+ public void getStatusPerConditions_returns_statusPerCondition_argument_from_setStatus() {
+ underTest.setStatus(QualityGateStatus.ERROR, SOME_STATUS_PER_CONDITION);
+
+ assertThat(underTest.getStatusPerConditions()).isEqualTo(SOME_STATUS_PER_CONDITION);
+ // a copy is made to be immutable
+ assertThat(underTest.getStatusPerConditions()).isNotSameAs(SOME_STATUS_PER_CONDITION);
+ }
+
+ private void expectQGNotSetYetISE() {
+ expectedException.expect(IllegalStateException.class);
+ expectedException.expectMessage("Quality gate status has not been set yet");
+ }
+
+ @DataProvider
+ public static Object[][] qualityGateStatusValue() {
+ Object[][] res = new Object[QualityGateStatus.values().length][1];
+ int i = 0;
+ for (QualityGateStatus status : QualityGateStatus.values()) {
+ res[i][0] = status;
+ i++;
+ }
+ return res;
+ }
+}
@Test
public void execute_sets_QualityGate_if_it_can_be_found_by_service() {
- QualityGate qualityGate = new QualityGate("name", Collections.<Condition>emptyList());
+ QualityGate qualityGate = new QualityGate(465, "name", Collections.<Condition>emptyList());
treeRootHolder.setRoot(PROJECT_ALONE);
when(settingsRepository.getSettings(PROJECT_ALONE)).thenReturn(new Settings().setProperty("sonar.qualitygate", 10));
import com.google.common.base.Optional;
import java.util.Collections;
+import java.util.Map;
+import java.util.Objects;
import javax.annotation.Nullable;
+import org.assertj.core.api.AbstractAssert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.mockito.ArgumentCaptor;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.sonar.server.computation.metric.MetricImpl;
import org.sonar.server.computation.metric.MetricRepository;
import org.sonar.server.computation.qualitygate.Condition;
+import org.sonar.server.computation.qualitygate.ConditionStatus;
import org.sonar.server.computation.qualitygate.EvaluationResult;
import org.sonar.server.computation.qualitygate.EvaluationResultTextConverter;
+import org.sonar.server.computation.qualitygate.MutableQualityGateStatusHolderRule;
import org.sonar.server.computation.qualitygate.QualityGate;
import org.sonar.server.computation.qualitygate.QualityGateHolderRule;
+import org.sonar.server.computation.qualitygate.QualityGateStatus;
+import org.sonar.server.computation.qualitygate.QualityGateStatusHolder;
import static com.google.common.collect.ImmutableList.of;
import static org.mockito.Matchers.any;
private static final MetricImpl INT_METRIC_2 = createIntMetric(2);
private static final ReportComponent PROJECT_COMPONENT = ReportComponent.builder(Component.Type.PROJECT, 1).build();
+ private static final long SOME_QG_ID = 7521551;
+ private static final String SOME_QG_NAME = "name";
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
@Rule
public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
@Rule
public QualityGateHolderRule qualityGateHolder = new QualityGateHolderRule();
+ @Rule
+ public MutableQualityGateStatusHolderRule qualityGateStatusHolder = new MutableQualityGateStatusHolderRule();
private static final Metric ALERT_STATUS_METRIC = mock(Metric.class);
private static final Metric QUALITY_GATE_DETAILS_METRIC = mock(Metric.class);
private MeasureRepository measureRepository = mock(MeasureRepository.class);
private MetricRepository metricRepository = mock(MetricRepository.class);
private EvaluationResultTextConverter resultTextConverter = mock(EvaluationResultTextConverter.class);
- private QualityGateMeasuresStep underTest = new QualityGateMeasuresStep(treeRootHolder, qualityGateHolder, measureRepository, metricRepository, resultTextConverter);
+ private QualityGateMeasuresStep underTest = new QualityGateMeasuresStep(treeRootHolder, qualityGateHolder, qualityGateStatusHolder, measureRepository, metricRepository,
+ resultTextConverter);
@Before
public void setUp() {
verifyNoMoreInteractions(measureRepository);
}
+ @Test
+ public void mutableQualityGateStatusHolder_is_not_populated_if_there_is_no_qualitygate() {
+ qualityGateHolder.setQualityGate(null);
+
+ underTest.execute();
+
+ expectedException.expect(IllegalStateException.class);
+ expectedException.expectMessage("Quality gate status has not been set yet");
+
+ qualityGateStatusHolder.getStatus();
+ }
+
@Test
public void new_measures_are_created_even_if_there_is_no_rawMeasure_for_metric_of_condition() {
Condition equals2Condition = createEqualsCondition(INT_METRIC_1, "2", null);
- qualityGateHolder.setQualityGate(new QualityGate("name", of(equals2Condition)));
+ qualityGateHolder.setQualityGate(new QualityGate(SOME_QG_ID, SOME_QG_NAME, of(equals2Condition)));
when(measureRepository.getRawMeasure(PROJECT_COMPONENT, INT_METRIC_1)).thenReturn(Optional.<Measure>absent());
underTest.execute();
.hasQualityGateText("");
assertThat(qgDetailsMeasureCaptor.getValue())
.hasValue(new QualityGateDetailsData(OK, Collections.<EvaluatedCondition>emptyList()).toJson());
+
+ QualityGateStatusHolderAssertions.assertThat(qualityGateStatusHolder)
+ .hasStatus(QualityGateStatus.OK)
+ .hasConditionCount(1)
+ .hasCondition(equals2Condition, ConditionStatus.EvaluationStatus.NO_VALUE, null);
}
@Test
Condition equals2Condition = createEqualsCondition(INT_METRIC_1, "2", null);
Measure rawMeasure = Measure.newMeasureBuilder().create(rawValue, null);
- qualityGateHolder.setQualityGate(new QualityGate("name", of(equals2Condition)));
+ qualityGateHolder.setQualityGate(new QualityGate(SOME_QG_ID, SOME_QG_NAME, of(equals2Condition)));
when(measureRepository.getRawMeasure(PROJECT_COMPONENT, INT_METRIC_1)).thenReturn(Optional.of(rawMeasure));
underTest.execute();
.hasQualityGateText(dumbResultTextAnswer(equals2Condition, OK, rawValue));
assertThat(qgDetailsMeasureCaptor.getValue())
.hasValue(new QualityGateDetailsData(OK, of(new EvaluatedCondition(equals2Condition, OK, rawValue))).toJson());
+
+ QualityGateStatusHolderAssertions.assertThat(qualityGateStatusHolder)
+ .hasStatus(QualityGateStatus.OK)
+ .hasConditionCount(1)
+ .hasCondition(equals2Condition, ConditionStatus.EvaluationStatus.OK, String.valueOf(rawValue));
}
@Test
Condition equals1WarningCondition = createEqualsCondition(INT_METRIC_2, null, "1");
Measure rawMeasure = Measure.newMeasureBuilder().create(rawValue, null);
- qualityGateHolder.setQualityGate(new QualityGate("name", of(equals1ErrorCondition, equals1WarningCondition)));
+ qualityGateHolder.setQualityGate(new QualityGate(SOME_QG_ID, SOME_QG_NAME, of(equals1ErrorCondition, equals1WarningCondition)));
when(measureRepository.getRawMeasure(PROJECT_COMPONENT, INT_METRIC_1)).thenReturn(Optional.of(rawMeasure));
when(measureRepository.getRawMeasure(PROJECT_COMPONENT, INT_METRIC_2)).thenReturn(Optional.of(rawMeasure));
verifyNoMoreInteractions(measureRepository);
assertThat(equals1ErrorConditionMeasureCaptor.getValue())
- .hasQualityGateLevel(ERROR)
- .hasQualityGateText(dumbResultTextAnswer(equals1ErrorCondition, ERROR, rawValue));
+ .hasQualityGateLevel(ERROR)
+ .hasQualityGateText(dumbResultTextAnswer(equals1ErrorCondition, ERROR, rawValue));
assertThat(equals1WarningConditionMeasureCaptor.getValue())
- .hasQualityGateLevel(WARN)
- .hasQualityGateText(dumbResultTextAnswer(equals1WarningCondition, WARN, rawValue));
+ .hasQualityGateLevel(WARN)
+ .hasQualityGateText(dumbResultTextAnswer(equals1WarningCondition, WARN, rawValue));
assertThat(alertStatusMeasureCaptor.getValue())
- .hasQualityGateLevel(ERROR)
- .hasQualityGateText(dumbResultTextAnswer(equals1ErrorCondition, ERROR, rawValue) + ", "
- + dumbResultTextAnswer(equals1WarningCondition, WARN, rawValue));
+ .hasQualityGateLevel(ERROR)
+ .hasQualityGateText(dumbResultTextAnswer(equals1ErrorCondition, ERROR, rawValue) + ", "
+ + dumbResultTextAnswer(equals1WarningCondition, WARN, rawValue));
assertThat(qgDetailsMeasureCaptor.getValue())
- .hasValue(new QualityGateDetailsData(ERROR, of(
- new EvaluatedCondition(equals1ErrorCondition, ERROR, rawValue),
- new EvaluatedCondition(equals1WarningCondition, WARN, rawValue)
- )).toJson());
+ .hasValue(new QualityGateDetailsData(ERROR, of(
+ new EvaluatedCondition(equals1ErrorCondition, ERROR, rawValue),
+ new EvaluatedCondition(equals1WarningCondition, WARN, rawValue))).toJson());
+
+ QualityGateStatusHolderAssertions.assertThat(qualityGateStatusHolder)
+ .hasStatus(QualityGateStatus.ERROR)
+ .hasConditionCount(2)
+ .hasCondition(equals1ErrorCondition, ConditionStatus.EvaluationStatus.ERROR, String.valueOf(rawValue))
+ .hasCondition(equals1WarningCondition, ConditionStatus.EvaluationStatus.WARN, String.valueOf(rawValue));
}
@Test
Condition equals1WarningCondition = createEqualsCondition(INT_METRIC_2, null, "1");
Measure rawMeasure = Measure.newMeasureBuilder().create(rawValue, null);
- qualityGateHolder.setQualityGate(new QualityGate("name", of(equals2Condition, equals1WarningCondition)));
+ qualityGateHolder.setQualityGate(new QualityGate(SOME_QG_ID, SOME_QG_NAME, of(equals2Condition, equals1WarningCondition)));
when(measureRepository.getRawMeasure(PROJECT_COMPONENT, INT_METRIC_1)).thenReturn(Optional.of(rawMeasure));
when(measureRepository.getRawMeasure(PROJECT_COMPONENT, INT_METRIC_2)).thenReturn(Optional.of(rawMeasure));
verifyNoMoreInteractions(measureRepository);
assertThat(equals2ConditionMeasureCaptor.getValue())
- .hasQualityGateLevel(OK)
- .hasQualityGateText(dumbResultTextAnswer(equals2Condition, OK, rawValue));
+ .hasQualityGateLevel(OK)
+ .hasQualityGateText(dumbResultTextAnswer(equals2Condition, OK, rawValue));
assertThat(equals1WarningConditionMeasureCaptor.getValue())
- .hasQualityGateLevel(WARN)
- .hasQualityGateText(dumbResultTextAnswer(equals1WarningCondition, WARN, rawValue));
+ .hasQualityGateLevel(WARN)
+ .hasQualityGateText(dumbResultTextAnswer(equals1WarningCondition, WARN, rawValue));
assertThat(alertStatusMeasureCaptor.getValue())
- .hasQualityGateLevel(WARN)
- .hasQualityGateText(dumbResultTextAnswer(equals2Condition, OK, rawValue) + ", "
- + dumbResultTextAnswer(equals1WarningCondition, WARN, rawValue));
+ .hasQualityGateLevel(WARN)
+ .hasQualityGateText(dumbResultTextAnswer(equals2Condition, OK, rawValue) + ", "
+ + dumbResultTextAnswer(equals1WarningCondition, WARN, rawValue));
assertThat(qgDetailsMeasureCaptor.getValue())
- .hasValue(new QualityGateDetailsData(WARN, of(
- new EvaluatedCondition(equals2Condition, OK, rawValue),
- new EvaluatedCondition(equals1WarningCondition, WARN, rawValue)
- )).toJson());
+ .hasValue(new QualityGateDetailsData(WARN, of(
+ new EvaluatedCondition(equals2Condition, OK, rawValue),
+ new EvaluatedCondition(equals1WarningCondition, WARN, rawValue))).toJson());
+
+ QualityGateStatusHolderAssertions.assertThat(qualityGateStatusHolder)
+ .hasStatus(QualityGateStatus.WARN)
+ .hasConditionCount(2)
+ .hasCondition(equals2Condition, ConditionStatus.EvaluationStatus.OK, String.valueOf(rawValue))
+ .hasCondition(equals1WarningCondition, ConditionStatus.EvaluationStatus.WARN, String.valueOf(rawValue));
}
private static Condition createEqualsCondition(Metric metric, @Nullable String errorThreshold, @Nullable String warningThreshold) {
return new MetricImpl(index, "metricKey" + index, "metricName" + index, Metric.MetricType.INT);
}
+ private static class QualityGateStatusHolderAssertions extends AbstractAssert<QualityGateStatusHolderAssertions, QualityGateStatusHolder> {
+
+ private QualityGateStatusHolderAssertions(QualityGateStatusHolder actual) {
+ super(actual, QualityGateStatusHolderAssertions.class);
+ }
+
+ public static QualityGateStatusHolderAssertions assertThat(QualityGateStatusHolder holder) {
+ return new QualityGateStatusHolderAssertions(holder);
+ }
+
+ public QualityGateStatusHolderAssertions hasStatus(QualityGateStatus status) {
+ if (actual.getStatus() != status) {
+ failWithMessage(
+ "Expected QualityGateStatusHolder to have global status <%s> but was <%s>",
+ status, actual.getStatus());
+ }
+
+ return this;
+ }
+
+ public QualityGateStatusHolderAssertions hasConditionCount(int count) {
+ int conditionCount = actual.getStatusPerConditions().size();
+ if (conditionCount != count) {
+ failWithMessage(
+ "Expected QualityGateStatusHolder to have <%s> conditions but it has <%s>",
+ count, conditionCount);
+ }
+
+ return this;
+ }
+
+ public QualityGateStatusHolderAssertions hasCondition(Condition condition, ConditionStatus.EvaluationStatus evaluationStatus, @Nullable String expectedValue) {
+ for (Map.Entry<Condition, ConditionStatus> entry : actual.getStatusPerConditions().entrySet()) {
+ if (entry.getKey() == condition) {
+ ConditionStatus.EvaluationStatus actualStatus = entry.getValue().getStatus();
+ if (actualStatus != evaluationStatus) {
+ failWithMessage(
+ "Expected Status of condition <%s> in QualityGateStatusHolder to be <%s> but it was <%s>",
+ condition, evaluationStatus, actualStatus);
+ }
+ String actualValue = entry.getValue().getValue();
+ if (!Objects.equals(expectedValue, actualValue)) {
+ failWithMessage(
+ "Expected Value of condition <%s> in QualityGateStatusHolder to be <%s> but it was <%s>",
+ condition, expectedValue, actualValue);
+ }
+ return this;
+ }
+ }
+
+ failWithMessage(
+ "Expected QualityGateStatusHolder to have an entry for <%s> but none was found",
+ condition);
+
+ return this;
+ }
+ }
+
}