@@ -0,0 +1,123 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 SonarSource SA | |||
* mailto:info 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.qualitygate; | |||
import java.util.Objects; | |||
import java.util.Optional; | |||
import javax.annotation.CheckForNull; | |||
import javax.annotation.Nullable; | |||
import javax.annotation.concurrent.Immutable; | |||
import static java.util.Objects.requireNonNull; | |||
@Immutable | |||
public class Condition { | |||
private final String metricKey; | |||
private final Operator operator; | |||
@CheckForNull | |||
private final String warningThreshold; | |||
@CheckForNull | |||
private final String errorThreshold; | |||
private final boolean onLeakPeriod; | |||
public Condition(String metricKey, Operator operator, | |||
@Nullable String errorThreshold, @Nullable String warningThreshold, | |||
boolean onLeakPeriod) { | |||
this.metricKey = requireNonNull(metricKey, "metricKey can't be null"); | |||
this.operator = requireNonNull(operator, "operator can't be null"); | |||
this.onLeakPeriod = onLeakPeriod; | |||
this.errorThreshold = errorThreshold; | |||
this.warningThreshold = warningThreshold; | |||
} | |||
public String getMetricKey() { | |||
return metricKey; | |||
} | |||
public boolean isOnLeakPeriod() { | |||
return onLeakPeriod; | |||
} | |||
public Operator getOperator() { | |||
return operator; | |||
} | |||
public Optional<String> getWarningThreshold() { | |||
return Optional.ofNullable(warningThreshold); | |||
} | |||
public Optional<String> getErrorThreshold() { | |||
return Optional.ofNullable(errorThreshold); | |||
} | |||
@Override | |||
public boolean equals(Object o) { | |||
if (this == o) { | |||
return true; | |||
} | |||
if (o == null || getClass() != o.getClass()) { | |||
return false; | |||
} | |||
Condition condition = (Condition) o; | |||
return onLeakPeriod == condition.onLeakPeriod && | |||
Objects.equals(metricKey, condition.metricKey) && | |||
operator == condition.operator && | |||
Objects.equals(warningThreshold, condition.warningThreshold) && | |||
Objects.equals(errorThreshold, condition.errorThreshold); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return Objects.hash(metricKey, operator, warningThreshold, errorThreshold, onLeakPeriod); | |||
} | |||
@Override | |||
public String toString() { | |||
return "Condition{" + | |||
"metricKey='" + metricKey + '\'' + | |||
", operator=" + operator + | |||
", warningThreshold=" + toString(warningThreshold) + | |||
", errorThreshold=" + toString(errorThreshold) + | |||
", onLeakPeriod=" + onLeakPeriod + | |||
'}'; | |||
} | |||
private static String toString(@Nullable String errorThreshold) { | |||
if (errorThreshold == null) { | |||
return null; | |||
} | |||
return '\'' + errorThreshold + '\''; | |||
} | |||
public enum Operator { | |||
EQUALS("EQ"), NOT_EQUALS("NE"), GREATER_THAN("GT"), LESS_THAN("LT"); | |||
private final String dbValue; | |||
Operator(String dbValue) { | |||
this.dbValue = dbValue; | |||
} | |||
public String getDbValue() { | |||
return dbValue; | |||
} | |||
} | |||
} |
@@ -0,0 +1,103 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 SonarSource SA | |||
* mailto:info 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.qualitygate; | |||
import java.util.Objects; | |||
import java.util.Optional; | |||
import javax.annotation.Nullable; | |||
import javax.annotation.concurrent.Immutable; | |||
import static java.util.Objects.requireNonNull; | |||
@Immutable | |||
public class EvaluatedCondition { | |||
private final Condition condition; | |||
private final EvaluationStatus status; | |||
private final String value; | |||
public EvaluatedCondition(Condition condition, EvaluationStatus status, @Nullable String value) { | |||
this.condition = requireNonNull(condition, "condition can't be null"); | |||
this.status = requireNonNull(status, "status can't be null"); | |||
this.value = value; | |||
} | |||
public Condition getCondition() { | |||
return condition; | |||
} | |||
public EvaluationStatus getStatus() { | |||
return status; | |||
} | |||
public Optional<String> getValue() { | |||
return Optional.ofNullable(value); | |||
} | |||
@Override | |||
public boolean equals(Object o) { | |||
if (this == o) { | |||
return true; | |||
} | |||
if (o == null || getClass() != o.getClass()) { | |||
return false; | |||
} | |||
EvaluatedCondition that = (EvaluatedCondition) o; | |||
return Objects.equals(condition, that.condition) && | |||
status == that.status && | |||
Objects.equals(value, that.value); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return Objects.hash(condition, status, value); | |||
} | |||
@Override | |||
public String toString() { | |||
return "EvaluatedCondition{" + | |||
"condition=" + condition + | |||
", status=" + status + | |||
", value=" + (value == null ? null : '\'' + value + '\'') + | |||
'}'; | |||
} | |||
/** | |||
* Quality gate condition evaluation status. | |||
*/ | |||
public enum EvaluationStatus { | |||
/** | |||
* No measure found or measure had no value. The condition has not been evaluated and therefor ignored in | |||
* the computation of the Quality Gate status. | |||
*/ | |||
NO_VALUE, | |||
/** | |||
* Condition evaluated as OK, neither error nor warning thresholds have been reached. | |||
*/ | |||
OK, | |||
/** | |||
* Condition evaluated as WARN, only warning thresholds has been reached. | |||
*/ | |||
WARN, | |||
/** | |||
* Condition evaluated as ERROR, error thresholds has been reached (and most likely warning thresholds too). | |||
*/ | |||
ERROR | |||
} | |||
} |
@@ -0,0 +1,159 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 SonarSource SA | |||
* mailto:info 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.qualitygate; | |||
import com.google.common.collect.ImmutableSet; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
import java.util.Objects; | |||
import java.util.Set; | |||
import java.util.stream.Collectors; | |||
import javax.annotation.Nullable; | |||
import javax.annotation.concurrent.Immutable; | |||
import org.sonar.server.qualitygate.EvaluatedCondition.EvaluationStatus; | |||
import static com.google.common.base.Preconditions.checkArgument; | |||
import static java.util.Objects.requireNonNull; | |||
@Immutable | |||
public class EvaluatedQualityGate { | |||
private final QualityGate qualityGate; | |||
private final Status status; | |||
private final Set<EvaluatedCondition> evaluatedConditions; | |||
private EvaluatedQualityGate(QualityGate qualityGate, Status status, Set<EvaluatedCondition> evaluatedConditions) { | |||
this.qualityGate = qualityGate; | |||
this.status = status; | |||
this.evaluatedConditions = evaluatedConditions; | |||
} | |||
public QualityGate getQualityGate() { | |||
return qualityGate; | |||
} | |||
public Status getStatus() { | |||
return status; | |||
} | |||
public Set<EvaluatedCondition> getEvaluatedConditions() { | |||
return evaluatedConditions; | |||
} | |||
public static Builder newBuilder() { | |||
return new Builder(); | |||
} | |||
@Override | |||
public boolean equals(Object o) { | |||
if (this == o) { | |||
return true; | |||
} | |||
if (o == null || getClass() != o.getClass()) { | |||
return false; | |||
} | |||
EvaluatedQualityGate that = (EvaluatedQualityGate) o; | |||
return Objects.equals(qualityGate, that.qualityGate) && | |||
status == that.status && | |||
Objects.equals(evaluatedConditions, that.evaluatedConditions); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return Objects.hash(qualityGate, status, evaluatedConditions); | |||
} | |||
@Override | |||
public String toString() { | |||
return "EvaluatedQualityGate{" + | |||
"qualityGate=" + qualityGate + | |||
", status=" + status + | |||
", evaluatedConditions=" + evaluatedConditions + | |||
'}'; | |||
} | |||
public static final class Builder { | |||
private QualityGate qualityGate; | |||
private Status status; | |||
private final Map<Condition, EvaluatedCondition> evaluatedConditions = new HashMap<>(); | |||
private Builder() { | |||
// use static factory method | |||
} | |||
public Builder setQualityGate(QualityGate qualityGate) { | |||
this.qualityGate = checkQualityGate(qualityGate); | |||
return this; | |||
} | |||
public Builder setStatus(Status status) { | |||
this.status = checkStatus(status); | |||
return this; | |||
} | |||
public Builder addCondition(Condition condition, EvaluationStatus status, @Nullable String value) { | |||
evaluatedConditions.put(condition, new EvaluatedCondition(condition, status, value)); | |||
return this; | |||
} | |||
public Set<EvaluatedCondition> getEvaluatedConditions() { | |||
return ImmutableSet.copyOf(evaluatedConditions.values()); | |||
} | |||
public EvaluatedQualityGate build() { | |||
checkQualityGate(this.qualityGate); | |||
checkStatus(this.status); | |||
return new EvaluatedQualityGate( | |||
this.qualityGate, | |||
this.status, | |||
checkEvaluatedConditions(qualityGate, evaluatedConditions)); | |||
} | |||
private static Set<EvaluatedCondition> checkEvaluatedConditions(QualityGate qualityGate, Map<Condition, EvaluatedCondition> evaluatedConditions) { | |||
Set<Condition> conditions = qualityGate.getConditions(); | |||
Set<Condition> conditionsNotEvaluated = conditions.stream() | |||
.filter(c -> !evaluatedConditions.containsKey(c)) | |||
.collect(Collectors.toSet()); | |||
checkArgument(conditionsNotEvaluated.isEmpty(), "Evaluation missing for the following conditions: %s", conditionsNotEvaluated); | |||
Set<Condition> unknownConditions = evaluatedConditions.keySet().stream() | |||
.filter(c -> !conditions.contains(c)) | |||
.collect(Collectors.toSet()); | |||
checkArgument(unknownConditions.isEmpty(), "Evaluation provided for unknown conditions: %s", unknownConditions); | |||
return ImmutableSet.copyOf(evaluatedConditions.values()); | |||
} | |||
private static QualityGate checkQualityGate(@Nullable QualityGate qualityGate) { | |||
return requireNonNull(qualityGate, "qualityGate can't be null"); | |||
} | |||
private static Status checkStatus(@Nullable Status status) { | |||
return requireNonNull(status, "status can't be null"); | |||
} | |||
} | |||
public enum Status { | |||
OK, | |||
WARN, | |||
ERROR | |||
} | |||
} |
@@ -0,0 +1,83 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 SonarSource SA | |||
* mailto:info 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.qualitygate; | |||
import java.util.Objects; | |||
import java.util.Set; | |||
import javax.annotation.concurrent.Immutable; | |||
import static java.util.Objects.requireNonNull; | |||
import static org.sonar.core.util.stream.MoreCollectors.toSet; | |||
@Immutable | |||
public class QualityGate { | |||
private final String id; | |||
private final String name; | |||
private final Set<Condition> conditions; | |||
public QualityGate(String id, String name, Set<Condition> conditions) { | |||
this.id = requireNonNull(id, "id can't be null"); | |||
this.name = requireNonNull(name, "name can't be null"); | |||
this.conditions = requireNonNull(conditions, "conditions can't be null") | |||
.stream() | |||
.map(c -> requireNonNull(c, "condition can't be null")) | |||
.collect(toSet(conditions.size())); | |||
} | |||
public String getId() { | |||
return id; | |||
} | |||
public String getName() { | |||
return name; | |||
} | |||
public Set<Condition> getConditions() { | |||
return conditions; | |||
} | |||
@Override | |||
public boolean equals(Object o) { | |||
if (this == o) { | |||
return true; | |||
} | |||
if (o == null || getClass() != o.getClass()) { | |||
return false; | |||
} | |||
QualityGate that = (QualityGate) o; | |||
return Objects.equals(id, that.id) && | |||
Objects.equals(name, that.name) && | |||
Objects.equals(conditions, that.conditions); | |||
} | |||
@Override | |||
public int hashCode() { | |||
return Objects.hash(id, name, conditions); | |||
} | |||
@Override | |||
public String toString() { | |||
return "QualityGate{" + | |||
"id=" + id + | |||
", name='" + name + '\'' + | |||
", conditions=" + conditions + | |||
'}'; | |||
} | |||
} |
@@ -0,0 +1,128 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 SonarSource SA | |||
* mailto:info 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.qualitygate; | |||
import java.util.Arrays; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class ConditionTest { | |||
private static final String METRIC_KEY = "metric_key"; | |||
private static final Condition.Operator OPERATOR = Condition.Operator.EQUALS; | |||
private static final String ERROR_THRESHOLD = "2"; | |||
private static final String WARN_THRESHOLD = "4"; | |||
private static final boolean ON_LEAK_PERIOD = true; | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
private Condition underTest = new Condition(METRIC_KEY, OPERATOR, ERROR_THRESHOLD, WARN_THRESHOLD, ON_LEAK_PERIOD); | |||
@Test | |||
public void constructor_throws_NPE_if_metricKey_is_null() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("metricKey can't be null"); | |||
new Condition(null, OPERATOR, ERROR_THRESHOLD, WARN_THRESHOLD, ON_LEAK_PERIOD); | |||
} | |||
@Test | |||
public void constructor_throws_NPE_if_operator_is_null() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("operator can't be null"); | |||
new Condition(METRIC_KEY, null, ERROR_THRESHOLD, WARN_THRESHOLD, ON_LEAK_PERIOD); | |||
} | |||
@Test | |||
public void errorThreshold_can_be_null() { | |||
Condition underTest = new Condition(METRIC_KEY, OPERATOR, null, WARN_THRESHOLD, ON_LEAK_PERIOD); | |||
assertThat(underTest.getErrorThreshold()).isEmpty(); | |||
} | |||
@Test | |||
public void warnThreshold_can_be_null() { | |||
Condition underTest = new Condition(METRIC_KEY, OPERATOR, ERROR_THRESHOLD, null, ON_LEAK_PERIOD); | |||
assertThat(underTest.getWarningThreshold()).isEmpty(); | |||
} | |||
@Test | |||
public void verify_getters() { | |||
assertThat(underTest.getMetricKey()).isEqualTo(METRIC_KEY); | |||
assertThat(underTest.getOperator()).isEqualTo(OPERATOR); | |||
assertThat(underTest.getErrorThreshold()).contains(ERROR_THRESHOLD); | |||
assertThat(underTest.getWarningThreshold()).contains(WARN_THRESHOLD); | |||
assertThat(underTest.isOnLeakPeriod()).isEqualTo(ON_LEAK_PERIOD); | |||
} | |||
@Test | |||
public void toString_is_override() { | |||
assertThat(underTest.toString()) | |||
.isEqualTo("Condition{metricKey='metric_key', operator=EQUALS, warningThreshold='4', errorThreshold='2', onLeakPeriod=true}"); | |||
} | |||
@Test | |||
public void toString_does_not_quote_nulls() { | |||
Condition withNulls = new Condition("metric_key", Condition.Operator.LESS_THAN, null, null, false); | |||
assertThat(withNulls.toString()) | |||
.isEqualTo("Condition{metricKey='metric_key', operator=LESS_THAN, warningThreshold=null, errorThreshold=null, onLeakPeriod=false}"); | |||
} | |||
@Test | |||
public void equals_is_based_on_all_fields() { | |||
assertThat(underTest).isEqualTo(underTest); | |||
assertThat(underTest).isNotEqualTo(null); | |||
assertThat(underTest).isNotEqualTo(new Object()); | |||
assertThat(underTest).isEqualTo(new Condition(METRIC_KEY, OPERATOR, ERROR_THRESHOLD, WARN_THRESHOLD, ON_LEAK_PERIOD)); | |||
assertThat(underTest).isNotEqualTo(new Condition("other_metric_key", OPERATOR, ERROR_THRESHOLD, WARN_THRESHOLD, ON_LEAK_PERIOD)); | |||
Arrays.stream(Condition.Operator.values()) | |||
.filter(s -> !OPERATOR.equals(s)) | |||
.forEach(otherOperator -> assertThat(underTest) | |||
.isNotEqualTo(new Condition(METRIC_KEY, otherOperator, ERROR_THRESHOLD, WARN_THRESHOLD, ON_LEAK_PERIOD))); | |||
assertThat(underTest).isNotEqualTo(new Condition(METRIC_KEY, OPERATOR, null, WARN_THRESHOLD, ON_LEAK_PERIOD)); | |||
assertThat(underTest).isNotEqualTo(new Condition(METRIC_KEY, OPERATOR, "other_error_threshold", WARN_THRESHOLD, ON_LEAK_PERIOD)); | |||
assertThat(underTest).isNotEqualTo(new Condition(METRIC_KEY, OPERATOR, ERROR_THRESHOLD, null, ON_LEAK_PERIOD)); | |||
assertThat(underTest).isNotEqualTo(new Condition(METRIC_KEY, OPERATOR, ERROR_THRESHOLD, "other_warn_threshold", ON_LEAK_PERIOD)); | |||
assertThat(underTest).isNotEqualTo(new Condition(METRIC_KEY, OPERATOR, ERROR_THRESHOLD, WARN_THRESHOLD, !ON_LEAK_PERIOD)); | |||
} | |||
@Test | |||
public void hashcode_is_based_on_all_fields() { | |||
assertThat(underTest.hashCode()).isEqualTo(underTest.hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(null); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new Object().hashCode()); | |||
assertThat(underTest.hashCode()).isEqualTo(new Condition(METRIC_KEY, OPERATOR, ERROR_THRESHOLD, WARN_THRESHOLD, ON_LEAK_PERIOD).hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new Condition("other_metric_key", OPERATOR, ERROR_THRESHOLD, WARN_THRESHOLD, ON_LEAK_PERIOD).hashCode()); | |||
Arrays.stream(Condition.Operator.values()) | |||
.filter(s -> !OPERATOR.equals(s)) | |||
.forEach(otherOperator -> assertThat(underTest.hashCode()) | |||
.isNotEqualTo(new Condition(METRIC_KEY, otherOperator, ERROR_THRESHOLD, WARN_THRESHOLD, ON_LEAK_PERIOD).hashCode())); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new Condition(METRIC_KEY, OPERATOR, null, WARN_THRESHOLD, ON_LEAK_PERIOD).hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new Condition(METRIC_KEY, OPERATOR, "other_error_threshold", WARN_THRESHOLD, ON_LEAK_PERIOD).hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new Condition(METRIC_KEY, OPERATOR, ERROR_THRESHOLD, null, ON_LEAK_PERIOD).hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new Condition(METRIC_KEY, OPERATOR, ERROR_THRESHOLD, "other_warn_threshold", ON_LEAK_PERIOD).hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new Condition(METRIC_KEY, OPERATOR, ERROR_THRESHOLD, WARN_THRESHOLD, !ON_LEAK_PERIOD).hashCode()); | |||
} | |||
} |
@@ -0,0 +1,110 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 SonarSource SA | |||
* mailto:info 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.qualitygate; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.sonar.server.qualitygate.Condition.Operator.EQUALS; | |||
import static org.sonar.server.qualitygate.EvaluatedCondition.EvaluationStatus.OK; | |||
import static org.sonar.server.qualitygate.EvaluatedCondition.EvaluationStatus.WARN; | |||
public class EvaluatedConditionTest { | |||
private static final Condition CONDITION_1 = new Condition("metricKey", EQUALS, "2", "4", false); | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
private EvaluatedCondition underTest = new EvaluatedCondition(CONDITION_1, WARN, "value"); | |||
@Test | |||
public void constructor_throws_NPE_if_condition_is_null() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("condition can't be null"); | |||
new EvaluatedCondition(null, WARN, "value"); | |||
} | |||
@Test | |||
public void constructor_throws_NPE_if_EvaluationStatus_is_null() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("status can't be null"); | |||
new EvaluatedCondition(CONDITION_1, null, "value"); | |||
} | |||
@Test | |||
public void constructor_accepts_null_value() { | |||
EvaluatedCondition underTest = new EvaluatedCondition(CONDITION_1, WARN, null); | |||
assertThat(underTest.getValue()).isEmpty(); | |||
} | |||
@Test | |||
public void verify_getters() { | |||
EvaluatedCondition underTest = new EvaluatedCondition(CONDITION_1, WARN, "value"); | |||
assertThat(underTest.getCondition()).isEqualTo(CONDITION_1); | |||
assertThat(underTest.getStatus()).isEqualTo(WARN); | |||
assertThat(underTest.getValue()).contains("value"); | |||
} | |||
@Test | |||
public void override_toString() { | |||
assertThat(underTest.toString()).isEqualTo("EvaluatedCondition{condition=" + | |||
"Condition{metricKey='metricKey', operator=EQUALS, warningThreshold='4', errorThreshold='2', onLeakPeriod=false}, " + | |||
"status=WARN, value='value'}"); | |||
} | |||
@Test | |||
public void toString_does_not_quote_null_value() { | |||
EvaluatedCondition underTest = new EvaluatedCondition(CONDITION_1, WARN, null); | |||
assertThat(underTest.toString()).isEqualTo("EvaluatedCondition{condition=" + | |||
"Condition{metricKey='metricKey', operator=EQUALS, warningThreshold='4', errorThreshold='2', onLeakPeriod=false}, " + | |||
"status=WARN, value=null}"); | |||
} | |||
@Test | |||
public void equals_is_based_on_all_fields() { | |||
assertThat(underTest).isEqualTo(underTest); | |||
assertThat(underTest).isEqualTo(new EvaluatedCondition(CONDITION_1, WARN, "value")); | |||
assertThat(underTest).isNotEqualTo(null); | |||
assertThat(underTest).isNotEqualTo(new Object()); | |||
assertThat(underTest).isNotEqualTo(new EvaluatedCondition(new Condition("other_metric", EQUALS, "a", "b", true), WARN, "value")); | |||
assertThat(underTest).isNotEqualTo(new EvaluatedCondition(CONDITION_1, OK, "value")); | |||
assertThat(underTest).isNotEqualTo(new EvaluatedCondition(CONDITION_1, WARN, null)); | |||
assertThat(underTest).isNotEqualTo(new EvaluatedCondition(CONDITION_1, WARN, "other_value")); | |||
} | |||
@Test | |||
public void hashcode_is_based_on_all_fields() { | |||
assertThat(underTest.hashCode()).isEqualTo(underTest.hashCode()); | |||
assertThat(underTest.hashCode()).isEqualTo(new EvaluatedCondition(CONDITION_1, WARN, "value").hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(null); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new Object().hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new EvaluatedCondition(new Condition("other_metric", EQUALS, "a", "b", true), WARN, "value").hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new EvaluatedCondition(CONDITION_1, OK, "value").hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new EvaluatedCondition(CONDITION_1, WARN, null).hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new EvaluatedCondition(CONDITION_1, WARN, "other_value").hashCode()); | |||
} | |||
} |
@@ -0,0 +1,225 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 SonarSource SA | |||
* mailto:info 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.qualitygate; | |||
import com.google.common.collect.ImmutableSet; | |||
import java.util.Random; | |||
import org.apache.commons.lang.RandomStringUtils; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import static java.util.Collections.emptySet; | |||
import static java.util.Collections.singleton; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.sonar.server.qualitygate.EvaluatedQualityGate.newBuilder; | |||
import static org.sonar.server.qualitygate.EvaluatedQualityGate.Status.OK; | |||
import static org.sonar.server.qualitygate.EvaluatedQualityGate.Status.WARN; | |||
public class EvaluatedQualityGateTest { | |||
private static final String QUALITY_GATE_ID = "qg_id"; | |||
private static final String QUALITY_GATE_NAME = "qg_name"; | |||
private static final QualityGate NO_CONDITION_QUALITY_GATE = new QualityGate(QUALITY_GATE_ID, QUALITY_GATE_NAME, emptySet()); | |||
private static final Condition CONDITION_1 = new Condition("metric_key", Condition.Operator.LESS_THAN, "2", "4", true); | |||
private static final Condition CONDITION_2 = new Condition("metric_key_2", Condition.Operator.GREATER_THAN, "6", "12", false); | |||
private static final QualityGate ONE_CONDITION_QUALITY_GATE = new QualityGate(QUALITY_GATE_ID, QUALITY_GATE_NAME, singleton(CONDITION_1)); | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
private final Random random = new Random(); | |||
private final EvaluatedQualityGate.Status randomStatus = EvaluatedQualityGate.Status.values()[random.nextInt(EvaluatedQualityGate.Status.values().length)]; | |||
private final EvaluatedCondition.EvaluationStatus randomEvaluationStatus = EvaluatedCondition.EvaluationStatus.values()[random | |||
.nextInt(EvaluatedCondition.EvaluationStatus.values().length)]; | |||
private final String randomValue = random.nextBoolean() ? null : RandomStringUtils.randomAlphanumeric(3); | |||
private EvaluatedQualityGate.Builder builder = newBuilder(); | |||
@Test | |||
public void setQualityGate_fails_with_NPE_if_argument_is_null() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("qualityGate can't be null"); | |||
builder.setQualityGate(null); | |||
} | |||
@Test | |||
public void setStatus_fails_with_NPE_if_argument_is_null() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("status can't be null"); | |||
builder.setStatus(null); | |||
} | |||
@Test | |||
public void build_fails_with_NPE_if_qualityGate_not_set() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("qualityGate can't be null"); | |||
builder.build(); | |||
} | |||
@Test | |||
public void build_fails_with_NPE_if_status_not_set() { | |||
builder.setQualityGate(NO_CONDITION_QUALITY_GATE); | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("status can't be null"); | |||
builder.build(); | |||
} | |||
@Test | |||
public void addCondition_fails_with_NPE_if_condition_is_null() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("condition can't be null"); | |||
builder.addCondition(null, EvaluatedCondition.EvaluationStatus.WARN, "a_value"); | |||
} | |||
@Test | |||
public void addCondition_fails_with_NPE_if_status_is_null() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("status can't be null"); | |||
builder.addCondition(new Condition("metric_key", Condition.Operator.LESS_THAN, "2", "4", true), null, "a_value"); | |||
} | |||
@Test | |||
public void addCondition_accepts_null_value() { | |||
builder.addCondition(CONDITION_1, EvaluatedCondition.EvaluationStatus.NO_VALUE, null); | |||
assertThat(builder.getEvaluatedConditions()) | |||
.containsOnly(new EvaluatedCondition(CONDITION_1, EvaluatedCondition.EvaluationStatus.NO_VALUE, null)); | |||
} | |||
@Test | |||
public void getEvaluatedConditions_returns_empty_with_no_condition_added_to_builder() { | |||
assertThat(builder.getEvaluatedConditions()).isEmpty(); | |||
} | |||
@Test | |||
public void build_fails_with_IAE_if_condition_added_and_no_on_QualityGate() { | |||
builder.setQualityGate(NO_CONDITION_QUALITY_GATE) | |||
.setStatus(randomStatus) | |||
.addCondition(CONDITION_1, randomEvaluationStatus, randomValue); | |||
expectedException.expect(IllegalArgumentException.class); | |||
expectedException.expectMessage("Evaluation provided for unknown conditions: [" + CONDITION_1 + "]"); | |||
builder.build(); | |||
} | |||
@Test | |||
public void build_fails_with_IAE_if_condition_is_missing_for_one_defined_in_QualityGate() { | |||
builder.setQualityGate(ONE_CONDITION_QUALITY_GATE) | |||
.setStatus(randomStatus); | |||
expectedException.expect(IllegalArgumentException.class); | |||
expectedException.expectMessage("Evaluation missing for the following conditions: [" + CONDITION_1 + "]"); | |||
builder.build(); | |||
} | |||
@Test | |||
public void verify_getters() { | |||
EvaluatedQualityGate underTest = builder | |||
.setQualityGate(ONE_CONDITION_QUALITY_GATE) | |||
.setStatus(randomStatus) | |||
.addCondition(CONDITION_1, randomEvaluationStatus, randomValue) | |||
.build(); | |||
assertThat(underTest.getQualityGate()).isEqualTo(ONE_CONDITION_QUALITY_GATE); | |||
assertThat(underTest.getStatus()).isEqualTo(randomStatus); | |||
assertThat(underTest.getEvaluatedConditions()) | |||
.containsOnly(new EvaluatedCondition(CONDITION_1, randomEvaluationStatus, randomValue)); | |||
} | |||
@Test | |||
public void verify_getters_when_no_condition() { | |||
EvaluatedQualityGate underTest = builder | |||
.setQualityGate(NO_CONDITION_QUALITY_GATE) | |||
.setStatus(randomStatus) | |||
.build(); | |||
assertThat(underTest.getQualityGate()).isEqualTo(NO_CONDITION_QUALITY_GATE); | |||
assertThat(underTest.getStatus()).isEqualTo(randomStatus); | |||
assertThat(underTest.getEvaluatedConditions()).isEmpty(); | |||
} | |||
@Test | |||
public void verify_getters_when_multiple_conditions() { | |||
QualityGate qualityGate = new QualityGate(QUALITY_GATE_ID, QUALITY_GATE_NAME, ImmutableSet.of(CONDITION_1, CONDITION_2)); | |||
EvaluatedQualityGate underTest = builder | |||
.setQualityGate(qualityGate) | |||
.setStatus(randomStatus) | |||
.addCondition(CONDITION_1, randomEvaluationStatus, randomValue) | |||
.addCondition(CONDITION_2, EvaluatedCondition.EvaluationStatus.WARN, "bad") | |||
.build(); | |||
assertThat(underTest.getQualityGate()).isEqualTo(qualityGate); | |||
assertThat(underTest.getStatus()).isEqualTo(randomStatus); | |||
assertThat(underTest.getEvaluatedConditions()).containsOnly( | |||
new EvaluatedCondition(CONDITION_1, randomEvaluationStatus, randomValue), | |||
new EvaluatedCondition(CONDITION_2, EvaluatedCondition.EvaluationStatus.WARN, "bad")); | |||
} | |||
@Test | |||
public void equals_is_based_on_all_fields() { | |||
EvaluatedQualityGate.Builder builder = this.builder | |||
.setQualityGate(ONE_CONDITION_QUALITY_GATE) | |||
.setStatus(WARN) | |||
.addCondition(CONDITION_1, EvaluatedCondition.EvaluationStatus.WARN, "foo"); | |||
EvaluatedQualityGate underTest = builder.build(); | |||
assertThat(underTest).isEqualTo(builder.build()); | |||
assertThat(underTest).isNotSameAs(builder.build()); | |||
assertThat(underTest).isNotEqualTo(null); | |||
assertThat(underTest).isNotEqualTo(new Object()); | |||
assertThat(underTest).isNotEqualTo(builder.setQualityGate(new QualityGate("other_id", QUALITY_GATE_NAME, singleton(CONDITION_1))).build()); | |||
assertThat(underTest).isNotEqualTo(builder.setQualityGate(ONE_CONDITION_QUALITY_GATE).setStatus(OK).build()); | |||
assertThat(underTest).isNotEqualTo(newBuilder() | |||
.setQualityGate(ONE_CONDITION_QUALITY_GATE) | |||
.setStatus(WARN) | |||
.addCondition(CONDITION_1, EvaluatedCondition.EvaluationStatus.OK, "foo") | |||
.build()); | |||
} | |||
@Test | |||
public void hashcode_is_based_on_all_fields() { | |||
EvaluatedQualityGate.Builder builder = this.builder | |||
.setQualityGate(ONE_CONDITION_QUALITY_GATE) | |||
.setStatus(WARN) | |||
.addCondition(CONDITION_1, EvaluatedCondition.EvaluationStatus.WARN, "foo"); | |||
EvaluatedQualityGate underTest = builder.build(); | |||
assertThat(underTest.hashCode()).isEqualTo(builder.build().hashCode()); | |||
assertThat(underTest.hashCode()).isNotSameAs(builder.build().hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(null); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new Object().hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(builder.setQualityGate(new QualityGate("other_id", QUALITY_GATE_NAME, singleton(CONDITION_1))).build().hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(builder.setQualityGate(ONE_CONDITION_QUALITY_GATE).setStatus(OK).build().hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(newBuilder() | |||
.setQualityGate(ONE_CONDITION_QUALITY_GATE) | |||
.setStatus(WARN) | |||
.addCondition(CONDITION_1, EvaluatedCondition.EvaluationStatus.OK, "foo") | |||
.build().hashCode()); | |||
} | |||
} |
@@ -0,0 +1,135 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 SonarSource SA | |||
* mailto:info 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.qualitygate; | |||
import com.google.common.collect.ImmutableSet; | |||
import java.util.Random; | |||
import java.util.Set; | |||
import java.util.stream.Collectors; | |||
import java.util.stream.IntStream; | |||
import java.util.stream.Stream; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import static java.util.Collections.emptySet; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class QualityGateTest { | |||
private static final String QUALIGATE_ID = "qg_id"; | |||
private static final String QUALIGATE_NAME = "qg_name"; | |||
private static final Condition CONDITION_1 = new Condition("m1", Condition.Operator.EQUALS, "1", "2", false); | |||
private static final Condition CONDITION_2 = new Condition("m2", Condition.Operator.LESS_THAN, "2", "4", true); | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
private QualityGate underTest = new QualityGate(QUALIGATE_ID, QUALIGATE_NAME, ImmutableSet.of(CONDITION_1, CONDITION_2)); | |||
@Test | |||
public void constructor_fails_with_NPE_if_id_is_null() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("id can't be null"); | |||
new QualityGate(null, "name", emptySet()); | |||
} | |||
@Test | |||
public void constructor_fails_with_NPE_if_name_is_null() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("name can't be null"); | |||
new QualityGate("id", null, emptySet()); | |||
} | |||
@Test | |||
public void constructor_fails_with_NPE_if_conditions_is_null() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("conditions can't be null"); | |||
new QualityGate("id", "name", null); | |||
} | |||
@Test | |||
public void constructor_fails_with_NPE_if_conditions_contains_null() { | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("condition can't be null"); | |||
Random random = new Random(); | |||
Set<Condition> conditions = Stream.of( | |||
IntStream.range(0, random.nextInt(5)) | |||
.mapToObj(i -> new Condition("m_before_" + i, Condition.Operator.EQUALS, null, null, false)), | |||
Stream.of((Condition) null), | |||
IntStream.range(0, random.nextInt(5)) | |||
.mapToObj(i -> new Condition("m_after_" + i, Condition.Operator.EQUALS, null, null, false))) | |||
.flatMap(s -> s) | |||
.collect(Collectors.toSet()); | |||
expectedException.expect(NullPointerException.class); | |||
expectedException.expectMessage("condition can't be null"); | |||
new QualityGate("id", "name", conditions); | |||
} | |||
@Test | |||
public void verify_getters() { | |||
assertThat(underTest.getId()).isEqualTo(QUALIGATE_ID); | |||
assertThat(underTest.getName()).isEqualTo(QUALIGATE_NAME); | |||
assertThat(underTest.getConditions()).containsOnly(CONDITION_1, CONDITION_2); | |||
} | |||
@Test | |||
public void toString_is_override() { | |||
QualityGate underTest = new QualityGate(QUALIGATE_ID, QUALIGATE_NAME, ImmutableSet.of(CONDITION_2)); | |||
assertThat(underTest.toString()).isEqualTo("QualityGate{id=qg_id, name='qg_name', conditions=[" + | |||
"Condition{metricKey='m2', operator=LESS_THAN, warningThreshold='4', errorThreshold='2', onLeakPeriod=true}" + | |||
"]}"); | |||
} | |||
@Test | |||
public void equals_is_based_on_all_fields() { | |||
assertThat(underTest).isEqualTo(underTest); | |||
assertThat(underTest).isEqualTo(new QualityGate(QUALIGATE_ID, QUALIGATE_NAME, ImmutableSet.of(CONDITION_2, CONDITION_1))); | |||
assertThat(underTest).isNotEqualTo(null); | |||
assertThat(underTest).isNotEqualTo(new Object()); | |||
assertThat(underTest).isNotEqualTo(new QualityGate("other_id", QUALIGATE_NAME, ImmutableSet.of(CONDITION_2, CONDITION_1))); | |||
assertThat(underTest).isNotEqualTo(new QualityGate(QUALIGATE_ID, "other_name", ImmutableSet.of(CONDITION_2, CONDITION_1))); | |||
assertThat(underTest).isNotEqualTo(new QualityGate(QUALIGATE_ID, QUALIGATE_NAME, emptySet())); | |||
assertThat(underTest).isNotEqualTo(new QualityGate(QUALIGATE_ID, QUALIGATE_NAME, ImmutableSet.of(CONDITION_1))); | |||
assertThat(underTest).isNotEqualTo(new QualityGate(QUALIGATE_ID, QUALIGATE_NAME, ImmutableSet.of(CONDITION_2))); | |||
assertThat(underTest).isNotEqualTo( | |||
new QualityGate(QUALIGATE_ID, QUALIGATE_NAME, ImmutableSet.of(CONDITION_1, CONDITION_2, new Condition("new", Condition.Operator.GREATER_THAN, "a", "b", false)))); | |||
} | |||
@Test | |||
public void hashcode_is_based_on_all_fields() { | |||
assertThat(underTest.hashCode()).isEqualTo(underTest.hashCode()); | |||
assertThat(underTest.hashCode()).isEqualTo(new QualityGate(QUALIGATE_ID, QUALIGATE_NAME, ImmutableSet.of(CONDITION_2, CONDITION_1)).hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(null); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new Object().hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new QualityGate("other_id", QUALIGATE_NAME, ImmutableSet.of(CONDITION_2, CONDITION_1)).hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new QualityGate(QUALIGATE_ID, "other_name", ImmutableSet.of(CONDITION_2, CONDITION_1)).hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new QualityGate(QUALIGATE_ID, QUALIGATE_NAME, emptySet()).hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new QualityGate(QUALIGATE_ID, QUALIGATE_NAME, ImmutableSet.of(CONDITION_1)).hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo(new QualityGate(QUALIGATE_ID, QUALIGATE_NAME, ImmutableSet.of(CONDITION_2)).hashCode()); | |||
assertThat(underTest.hashCode()).isNotEqualTo( | |||
new QualityGate(QUALIGATE_ID, QUALIGATE_NAME, ImmutableSet.of(CONDITION_1, CONDITION_2, new Condition("new", Condition.Operator.GREATER_THAN, "a", "b", false))).hashCode()); | |||
} | |||
} |