3 * Copyright (C) 2009-2019 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.ce.task.projectanalysis.qualitygate;
22 import com.google.common.collect.ImmutableList;
23 import java.util.Collections;
24 import java.util.Optional;
25 import java.util.Random;
26 import org.apache.commons.lang.RandomStringUtils;
27 import org.junit.Before;
28 import org.junit.Test;
29 import org.sonar.api.measures.CoreMetrics;
30 import org.sonar.ce.task.projectanalysis.metric.Metric;
31 import org.sonar.ce.task.projectanalysis.metric.MetricImpl;
32 import org.sonar.ce.task.projectanalysis.metric.MetricRepository;
33 import org.sonar.db.DbClient;
34 import org.sonar.db.qualitygate.QualityGateConditionDao;
35 import org.sonar.db.qualitygate.QualityGateConditionDto;
36 import org.sonar.db.qualitygate.QualityGateDao;
37 import org.sonar.db.qualitygate.QualityGateDto;
38 import org.sonar.server.qualitygate.ShortLivingBranchQualityGate;
40 import static org.assertj.core.api.Assertions.assertThat;
41 import static org.assertj.core.api.Assertions.tuple;
42 import static org.mockito.ArgumentMatchers.any;
43 import static org.mockito.ArgumentMatchers.eq;
44 import static org.mockito.Mockito.mock;
45 import static org.mockito.Mockito.when;
46 import static org.sonar.ce.task.projectanalysis.qualitygate.Condition.Operator.GREATER_THAN;
48 public class QualityGateServiceImplTest {
49 private static final long SOME_ID = 123;
50 private static final String SOME_NAME = "some name";
51 private static final QualityGateDto QUALITY_GATE_DTO = new QualityGateDto().setId(SOME_ID).setName(SOME_NAME);
52 private static final long METRIC_ID_1 = 951;
53 private static final long METRIC_ID_2 = 753;
54 private static final Metric METRIC_1 = mock(Metric.class);
55 private static final Metric METRIC_2 = mock(Metric.class);
56 private static final QualityGateConditionDto CONDITION_1 = new QualityGateConditionDto().setId(321).setMetricId(METRIC_ID_1).setOperator("EQ")
57 .setWarningThreshold("warnin_th").setErrorThreshold("error_th");
58 private static final QualityGateConditionDto CONDITION_2 = new QualityGateConditionDto().setId(456).setMetricId(METRIC_ID_2).setOperator("NE");
60 private QualityGateDao qualityGateDao = mock(QualityGateDao.class);
61 private QualityGateConditionDao qualityGateConditionDao = mock(QualityGateConditionDao.class);
62 private MetricRepository metricRepository = mock(MetricRepository.class);
63 private DbClient dbClient = mock(DbClient.class);
64 private QualityGateServiceImpl underTest = new QualityGateServiceImpl(dbClient, metricRepository);
67 public void setUp() throws Exception {
68 when(dbClient.qualityGateDao()).thenReturn(qualityGateDao);
69 when(dbClient.gateConditionDao()).thenReturn(qualityGateConditionDao);
71 when(METRIC_1.getKey()).thenReturn("metric");
72 when(METRIC_2.getKey()).thenReturn("new_metric");
76 public void findById_returns_absent_when_QualityGateDto_does_not_exist() {
77 assertThat(underTest.findById(SOME_ID)).isNotPresent();
81 public void findById_returns_QualityGate_with_empty_set_of_conditions_when_there_is_none_in_DB() {
82 when(qualityGateDao.selectById(any(), eq(SOME_ID))).thenReturn(QUALITY_GATE_DTO);
83 when(qualityGateConditionDao.selectForQualityGate(any(), eq(SOME_ID))).thenReturn(Collections.emptyList());
85 Optional<QualityGate> res = underTest.findById(SOME_ID);
87 assertThat(res).isPresent();
88 assertThat(res.get().getId()).isEqualTo(SOME_ID);
89 assertThat(res.get().getName()).isEqualTo(SOME_NAME);
90 assertThat(res.get().getConditions()).isEmpty();
94 public void findById_returns_conditions_when_there_is_some_in_DB() {
95 when(qualityGateDao.selectById(any(), eq(SOME_ID))).thenReturn(QUALITY_GATE_DTO);
96 when(qualityGateConditionDao.selectForQualityGate(any(), eq(SOME_ID))).thenReturn(ImmutableList.of(CONDITION_1, CONDITION_2));
97 // metrics are always supposed to be there
98 when(metricRepository.getOptionalById(METRIC_ID_1)).thenReturn(Optional.of(METRIC_1));
99 when(metricRepository.getOptionalById(METRIC_ID_2)).thenReturn(Optional.of(METRIC_2));
101 Optional<QualityGate> res = underTest.findById(SOME_ID);
103 assertThat(res).isPresent();
104 assertThat(res.get().getId()).isEqualTo(SOME_ID);
105 assertThat(res.get().getName()).isEqualTo(SOME_NAME);
106 assertThat(res.get().getConditions()).containsOnly(
107 new Condition(METRIC_1, CONDITION_1.getOperator(), CONDITION_1.getErrorThreshold(), CONDITION_1.getWarningThreshold()),
108 new Condition(METRIC_2, CONDITION_2.getOperator(), CONDITION_2.getErrorThreshold(), CONDITION_2.getWarningThreshold()));
112 public void findById_ignores_conditions_on_missing_metrics() {
113 when(qualityGateDao.selectById(any(), eq(SOME_ID))).thenReturn(QUALITY_GATE_DTO);
114 when(qualityGateConditionDao.selectForQualityGate(any(), eq(SOME_ID))).thenReturn(ImmutableList.of(CONDITION_1, CONDITION_2));
115 // metrics are always supposed to be there
116 when(metricRepository.getOptionalById(METRIC_ID_1)).thenReturn(Optional.empty());
117 when(metricRepository.getOptionalById(METRIC_ID_2)).thenReturn(Optional.of(METRIC_2));
119 Optional<QualityGate> res = underTest.findById(SOME_ID);
121 assertThat(res).isPresent();
122 assertThat(res.get().getId()).isEqualTo(SOME_ID);
123 assertThat(res.get().getName()).isEqualTo(SOME_NAME);
124 assertThat(res.get().getConditions()).containsOnly(
125 new Condition(METRIC_2, CONDITION_2.getOperator(), CONDITION_2.getErrorThreshold(), CONDITION_2.getWarningThreshold()));
129 public void findById_of_hardcoded_short_living_branch_returns_hardcoded_qg() {
130 MetricImpl bugsMetric = mockMetricInRepository(CoreMetrics.BUGS_KEY);
131 MetricImpl vulnerabilitiesMetric = mockMetricInRepository(CoreMetrics.VULNERABILITIES_KEY);
132 MetricImpl codeSmellsMetric = mockMetricInRepository(CoreMetrics.CODE_SMELLS_KEY);
133 MetricImpl openedIssueMetric = mockMetricInRepository(CoreMetrics.OPEN_ISSUES_KEY);
134 MetricImpl reOpenedIssueMetric = mockMetricInRepository(CoreMetrics.REOPENED_ISSUES_KEY);
136 Optional<QualityGate> res = underTest.findById(ShortLivingBranchQualityGate.ID);
138 assertThat(res).isPresent();
139 QualityGate qualityGate = res.get();
140 assertThat(qualityGate.getId()).isEqualTo(ShortLivingBranchQualityGate.ID);
141 assertThat(qualityGate.getName()).isEqualTo("Hardcoded short living branch quality gate");
142 assertThat(qualityGate.getConditions())
143 .extracting(Condition::getMetric, Condition::getOperator, Condition::getErrorThreshold, Condition::getWarningThreshold)
145 tuple(openedIssueMetric, GREATER_THAN, "0", null),
146 tuple(reOpenedIssueMetric, GREATER_THAN, "0", null));
149 private MetricImpl mockMetricInRepository(String metricKey) {
150 MetricImpl metric = new MetricImpl(new Random().nextInt(999), metricKey, RandomStringUtils.randomAlphanumeric(20), Metric.MetricType.INT);
151 when(metricRepository.getByKey(metricKey))