@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")))); }
@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 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"))).hashCode()); } }
@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, errorThreshold='2'}" + "]}"); }
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()); } }
@Test public void loadQualityGate_on_long_branch_returns_organization_default_gate() { OrganizationDto organization = db.organizations().insert(); ComponentDto project = db.components().insertPublicProject(organization); BranchDto branch = newBranchDto(project).setBranchType(BranchType.LONG); db.components().insertProjectBranch(project, branch); MetricDto metric = db.measures().insertMetric(); QGateWithOrgDto gate = db.qualityGates().insertQualityGate(organization); db.qualityGates().setDefaultQualityGate(organization, gate); QualityGateConditionDto condition = db.qualityGates().addCondition(gate, metric); QualityGate result = underTest.loadQualityGate(db.getSession(), organization, project, branch); assertThat(result.getId()).isEqualTo("" + gate.getId()); assertThat(result.getConditions()) .extracting(Condition::getMetricKey, Condition::getOperator, Condition::getErrorThreshold) .containsExactlyInAnyOrder( tuple(metric.getKey(), Condition.Operator.fromDbValue(condition.getOperator()), condition.getErrorThreshold())); }
private static void writeQualityGate(JsonWriter writer, EvaluatedQualityGate gate) { writer .name("qualityGate") .beginObject() .prop("name", gate.getQualityGate().getName()) .prop(PROPERTY_STATUS, gate.getStatus().toString()) .name("conditions") .beginArray(); for (EvaluatedCondition evaluatedCondition : gate.getEvaluatedConditions()) { Condition condition = evaluatedCondition.getCondition(); writer .beginObject() .prop("metric", condition.getMetricKey()) .prop("operator", condition.getOperator().name()); evaluatedCondition.getValue().ifPresent(t -> writer.prop("value", t)); writer .prop(PROPERTY_STATUS, evaluatedCondition.getStatus().name()) .prop("errorThreshold", condition.getErrorThreshold()) .endObject(); } writer .endArray() .endObject(); }
@Override public Set<String> getMetricKeys(QualityGate gate) { Set<String> metricKeys = new HashSet<>(); metricKeys.add(CoreMetrics.NEW_LINES_KEY); for (Condition condition : gate.getConditions()) { metricKeys.add(condition.getMetricKey()); } return metricKeys; }
private static void writeQualityGate(JsonWriter writer, EvaluatedQualityGate gate) { writer .name("qualityGate") .beginObject() .prop("name", gate.getQualityGate().getName()) .prop(PROPERTY_STATUS, gate.getStatus().toString()) .name("conditions") .beginArray(); for (EvaluatedCondition evaluatedCondition : gate.getEvaluatedConditions()) { Condition condition = evaluatedCondition.getCondition(); writer .beginObject() .prop("metric", condition.getMetricKey()) .prop("operator", condition.getOperator().name()); evaluatedCondition.getValue().ifPresent(t -> writer.prop("value", t)); writer .prop(PROPERTY_STATUS, evaluatedCondition.getStatus().name()) .prop("onLeakPeriod", condition.isOnLeakPeriod()) .prop("errorThreshold", condition.getErrorThreshold().orElse(null)) .prop("warningThreshold", condition.getWarningThreshold().orElse(null)) .endObject(); } writer .endArray() .endObject(); }
@Override public QualityGate loadQualityGate(DbSession dbSession, OrganizationDto organization, ComponentDto project, BranchDto branch) { if (branch.getBranchType() == BranchType.SHORT || branch.getBranchType() == BranchType.PULL_REQUEST) { return ShortLivingBranchQualityGate.GATE; } ComponentDto mainProject = project.getMainBranchProjectUuid() == null ? project : dbClient.componentDao().selectOrFailByKey(dbSession, project.getKey()); QualityGateDto gateDto = qGateFinder.getQualityGate(dbSession, organization, mainProject) .orElseThrow(() -> new IllegalStateException(format("Quality Gate not found for project %s", mainProject.getKey()))) .getQualityGate(); Collection<QualityGateConditionDto> conditionDtos = dbClient.gateConditionDao().selectForQualityGate(dbSession, gateDto.getId()); Set<Integer> metricIds = conditionDtos.stream().map(c -> (int) c.getMetricId()) .collect(toHashSet(conditionDtos.size())); Map<Integer, MetricDto> metricsById = dbClient.metricDao().selectByIds(dbSession, metricIds).stream() .collect(uniqueIndex(MetricDto::getId)); Set<Condition> conditions = conditionDtos.stream().map(conditionDto -> { String metricKey = metricsById.get((int) conditionDto.getMetricId()).getKey(); Condition.Operator operator = Condition.Operator.fromDbValue(conditionDto.getOperator()); return new Condition(metricKey, operator, conditionDto.getErrorThreshold()); }).collect(toHashSet(conditionDtos.size())); return new QualityGate(String.valueOf(gateDto.getId()), gateDto.getName(), conditions); }
@Override public Set<String> getMetricKeys(QualityGate gate) { return gate.getConditions().stream().map(Condition::getMetricKey).collect(Collectors.toSet()); } }
@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 getMetricKeys_includes_metrics_from_qgate() { Set<String> metricKeys = ImmutableSet.of("foo", "bar", "baz"); Set<Condition> conditions = metricKeys.stream().map(key -> { Condition condition = mock(Condition.class); when(condition.getMetricKey()).thenReturn(key); return condition; }).collect(Collectors.toSet()); QualityGate gate = mock(QualityGate.class); when(gate.getConditions()).thenReturn(conditions); assertThat(underTest.getMetricKeys(gate)).containsAll(metricKeys); }
@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()); }
@Override public EvaluatedQualityGate evaluate(QualityGate gate, Measures measures) { checkState(this.measures == null); this.measures = measures; EvaluatedQualityGate.Builder builder = EvaluatedQualityGate.newBuilder().setQualityGate(gate).setStatus(Metric.Level.OK); for (Condition condition : gate.getConditions()) { builder.addCondition(condition, EvaluatedCondition.EvaluationStatus.OK, "bar"); } return builder.build(); }
@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.GREATER_THAN, "10")), Stream.of((Condition) null), IntStream.range(0, random.nextInt(5)) .mapToObj(i -> new Condition("m_after_" + i, Condition.Operator.GREATER_THAN, "10"))) .flatMap(s -> s) .collect(Collectors.toSet()); expectedException.expect(NullPointerException.class); expectedException.expectMessage("condition can't be null"); new QualityGate("id", "name", conditions); }
@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(); }
@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); }
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()); } }
@Test public void getMetricsRelatedTo() { Condition condition = new Condition("metric1", Condition.Operator.GREATER_THAN, "10"); QualityGate gate = new QualityGate("1", "foo", ImmutableSet.of(condition)); Set<String> result = underTest.getMetricsRelatedTo(gate); assertThat(result).containsExactlyInAnyOrder( // the metrics needed to compute the status of gate condition.getMetricKey(), // generated metrics CoreMetrics.ALERT_STATUS_KEY, CoreMetrics.QUALITY_GATE_DETAILS_KEY); }