/** * Evaluates the condition for the specified measure */ static EvaluatedCondition evaluate(Condition condition, QualityGateEvaluator.Measures measures) { Optional<QualityGateEvaluator.Measure> measure = measures.get(condition.getMetricKey()); if (!measure.isPresent()) { return new EvaluatedCondition(condition, EvaluationStatus.OK, null); } Optional<Comparable> value = getMeasureValue(condition, measure.get()); if (!value.isPresent()) { return new EvaluatedCondition(condition, EvaluationStatus.OK, null); } ValueType type = measure.get().getType(); return evaluateCondition(condition, type, value.get()) .orElseGet(() -> new EvaluatedCondition(condition, EvaluationStatus.OK, value.get().toString())); }
private static Optional<Comparable> getMeasureValue(Condition condition, QualityGateEvaluator.Measure measure) { if (condition.isOnLeakPeriod()) { return Optional.ofNullable(getLeakValue(measure)); } return Optional.ofNullable(getValue(measure)); }
@CheckForNull private static Comparable getLeakValue(QualityGateEvaluator.Measure measure) { if (NUMERICAL_TYPES.contains(measure.getType())) { return measure.getNewMetricValue().isPresent() ? getNumericValue(measure.getType(), measure.getNewMetricValue().getAsDouble()) : null; } throw new IllegalArgumentException("Condition on leak period is not allowed for type " + measure.getType()); }
/** * Evaluates the error condition. Returns empty if threshold or measure value is not defined. */ private static Optional<EvaluatedCondition> evaluateCondition(Condition condition, ValueType type, Comparable value) { Comparable threshold = getThreshold(condition, type); if (reachThreshold(value, threshold, condition)) { return of(new EvaluatedCondition(condition, EvaluationStatus.ERROR, value.toString())); } return Optional.empty(); }
private void test(@Nullable QualityGateEvaluator.Measure measure, Condition.Operator operator, String errorThreshold, EvaluatedCondition.EvaluationStatus expectedStatus, @Nullable String expectedValue) { Condition condition = new Condition("foo", operator, errorThreshold); EvaluatedCondition result = ConditionEvaluator.evaluate(condition, new FakeMeasures(measure)); assertThat(result.getStatus()).isEqualTo(expectedStatus); if (expectedValue == null) { assertThat(result.getValue()).isNotPresent(); } else { assertThat(result.getValue()).hasValue(expectedValue); } }
private static Comparable getThreshold(Condition condition, ValueType valueType) { String valString = condition.getErrorThreshold(); try { switch (valueType) { case INT: case RATING: return parseInteger(valString); case MILLISEC: case WORK_DUR: return Long.parseLong(valString); case FLOAT: case PERCENT: return Double.parseDouble(valString); case LEVEL: return valueType; default: throw new IllegalArgumentException(format("Unsupported value type %s. Cannot convert condition value", valueType)); } } catch (NumberFormatException badValueFormat) { throw new IllegalArgumentException(format( "Quality Gate: unable to parse threshold '%s' to compare against %s", valString, condition.getMetricKey())); } }
private void testOnLeak(QualityGateEvaluator.Measure measure, Condition.Operator operator, String errorThreshold, EvaluatedCondition.EvaluationStatus expectedStatus, @Nullable String expectedValue) { Condition condition = new Condition("new_foo", operator, errorThreshold); EvaluatedCondition result = ConditionEvaluator.evaluate(condition, new FakeMeasures(measure)); assertThat(result.getStatus()).isEqualTo(expectedStatus); if (expectedValue == null) { assertThat(result.getValue()).isNotPresent(); } else { assertThat(result.getValue()).hasValue(expectedValue); } }
/** * Evaluates the error or warning condition. Returns empty if threshold or measure value is not defined. */ private static Optional<EvaluatedCondition> evaluateCondition(Condition condition, ValueType type, Comparable value, boolean error) { Optional<Comparable> threshold = getThreshold(condition, type, error); if (!threshold.isPresent()) { return Optional.empty(); } if (reachThreshold(value, threshold.get(), condition)) { EvaluationStatus status = error ? EvaluationStatus.ERROR : EvaluationStatus.WARN; return of(new EvaluatedCondition(condition, status, value.toString())); } return Optional.empty(); }
private static Optional<Comparable> getThreshold(Condition condition, ValueType valueType, boolean error) { Optional<String> valString = error ? condition.getErrorThreshold() : condition.getWarningThreshold(); return valString.map(s -> { try { switch (valueType) { case BOOL: return parseInteger(s) == 1; case INT: case RATING: return parseInteger(s); case MILLISEC: case WORK_DUR: return Long.parseLong(s); case FLOAT: case PERCENT: return Double.parseDouble(s); case STRING: case LEVEL: return s; default: throw new IllegalArgumentException(String.format("Unsupported value type %s. Cannot convert condition value", valueType)); } } catch (NumberFormatException badValueFormat) { throw new IllegalArgumentException(String.format( "Quality Gate: unable to parse threshold '%s' to compare against %s", s, condition.getMetricKey())); } }); }
@Override public EvaluatedQualityGate evaluate(QualityGate gate, Measures measures) { EvaluatedQualityGate.Builder result = EvaluatedQualityGate.newBuilder() .setQualityGate(gate); boolean isSmallChangeset = isSmallChangeset(measures); gate.getConditions().forEach(condition -> { String metricKey = condition.getMetricKey(); EvaluatedCondition evaluation = ConditionEvaluator.evaluate(condition, measures); if (isSmallChangeset && evaluation.getStatus() != EvaluationStatus.OK && METRICS_TO_IGNORE_ON_SMALL_CHANGESETS.contains(metricKey)) { result.addCondition(new EvaluatedCondition(evaluation.getCondition(), EvaluationStatus.OK, evaluation.getValue().orElse(null))); result.setIgnoredConditionsOnSmallChangeset(true); } else { result.addCondition(evaluation); } }); result.setStatus(overallStatusOf(result.getEvaluatedConditions())); return result.build(); }
private static Optional<Comparable> getMeasureValue(Condition condition, QualityGateEvaluator.Measure measure) { if (condition.isOnLeakPeriod()) { return Optional.ofNullable(getLeakValue(measure)); } return Optional.ofNullable(getValue(measure)); }
/** * Evaluates the condition for the specified measure */ static EvaluatedCondition evaluate(Condition condition, QualityGateEvaluator.Measures measures) { Optional<QualityGateEvaluator.Measure> measure = measures.get(condition.getMetricKey()); if (!measure.isPresent()) { return new EvaluatedCondition(condition, EvaluationStatus.OK, null); } Optional<Comparable> value = getMeasureValue(condition, measure.get()); if (!value.isPresent()) { return new EvaluatedCondition(condition, EvaluationStatus.OK, null); } ValueType type = measure.get().getType(); return evaluateCondition(condition, type, value.get(), true) .orElseGet(() -> evaluateCondition(condition, type, value.get(), false) .orElseGet(() -> new EvaluatedCondition(condition, EvaluationStatus.OK, value.get().toString()))); }
@CheckForNull private static Comparable getValue(QualityGateEvaluator.Measure measure) { if (NUMERICAL_TYPES.contains(measure.getType())) { return measure.getValue().isPresent() ? getNumericValue(measure.getType(), measure.getValue().getAsDouble()) : null; } checkArgument(ValueType.LEVEL.equals(measure.getType()), "Condition is not allowed for type %s" , measure.getType()); return measure.getStringValue().orElse(null); }
private static EvaluatedCondition evaluateConditionsOnMetric(Collection<Condition> conditionsOnSameMetric, Measures measures) { EvaluatedCondition leakEvaluation = null; EvaluatedCondition absoluteEvaluation = null; for (Condition condition : conditionsOnSameMetric) { if (condition.isOnLeakPeriod()) { leakEvaluation = ConditionEvaluator.evaluate(condition, measures); } else { absoluteEvaluation = ConditionEvaluator.evaluate(condition, measures); } } if (leakEvaluation == null) { return requireNonNull(absoluteEvaluation, "Evaluation of absolute value can't be null on conditions " + conditionsOnSameMetric); } if (absoluteEvaluation == null) { return requireNonNull(leakEvaluation, "Evaluation of leak value can't be null on conditions " + conditionsOnSameMetric); } // both conditions are present. Take the worse one. In case of equality, take // the one on the leak period if (absoluteEvaluation.getStatus().compareTo(leakEvaluation.getStatus()) > 0) { return absoluteEvaluation; } return leakEvaluation; }
@CheckForNull private static Comparable getLeakValue(QualityGateEvaluator.Measure measure) { if (NUMERICAL_TYPES.contains(measure.getType())) { return measure.getLeakValue().isPresent() ? getNumericValue(measure.getType(), measure.getLeakValue().getAsDouble()) : null; } throw new IllegalArgumentException("Condition on leak period is not allowed for type " + measure.getType()); }
@CheckForNull private static Comparable getValue(QualityGateEvaluator.Measure measure) { if (NUMERICAL_TYPES.contains(measure.getType())) { return measure.getValue().isPresent() ? getNumericValue(measure.getType(), measure.getValue().getAsDouble()) : null; } switch (measure.getType()) { case LEVEL: case STRING: case DISTRIB: return measure.getStringValue().orElse(null); default: throw new IllegalArgumentException("Condition on leak period is not allowed for type " + measure.getType()); } }