3 * Copyright (C) 2009-2020 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.server.qualitygate;
22 import java.util.ArrayList;
23 import java.util.Date;
24 import java.util.List;
25 import java.util.Random;
26 import org.junit.Rule;
27 import org.junit.Test;
28 import org.sonar.api.utils.System2;
29 import org.sonar.api.utils.log.LogTester;
30 import org.sonar.api.utils.log.LoggerLevel;
31 import org.sonar.core.util.UuidFactoryFast;
32 import org.sonar.core.util.Uuids;
33 import org.sonar.db.DbClient;
34 import org.sonar.db.DbSession;
35 import org.sonar.db.DbTester;
36 import org.sonar.db.metric.MetricDao;
37 import org.sonar.db.metric.MetricDto;
38 import org.sonar.db.qualitygate.QualityGateConditionDao;
39 import org.sonar.db.qualitygate.QualityGateConditionDto;
40 import org.sonar.db.qualitygate.QualityGateDao;
41 import org.sonar.db.qualitygate.QualityGateDto;
43 import static org.assertj.core.api.Assertions.assertThat;
44 import static org.assertj.core.api.Assertions.tuple;
45 import static org.sonar.api.measures.CoreMetrics.NEW_COVERAGE_KEY;
46 import static org.sonar.api.measures.CoreMetrics.NEW_DUPLICATED_LINES_DENSITY_KEY;
47 import static org.sonar.api.measures.CoreMetrics.NEW_MAINTAINABILITY_RATING_KEY;
48 import static org.sonar.api.measures.CoreMetrics.NEW_RELIABILITY_RATING_KEY;
49 import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_RATING_KEY;
50 import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_REMEDIATION_EFFORT_KEY;
51 import static org.sonar.api.measures.Metric.ValueType.INT;
52 import static org.sonar.api.measures.Metric.ValueType.PERCENT;
53 import static org.sonar.db.metric.MetricTesting.newMetricDto;
54 import static org.sonar.db.qualitygate.QualityGateConditionDto.OPERATOR_GREATER_THAN;
55 import static org.sonar.db.qualitygate.QualityGateConditionDto.OPERATOR_LESS_THAN;
57 public class RegisterQualityGatesTest {
60 public DbTester db = DbTester.create(System2.INSTANCE);
62 public LogTester logTester = new LogTester();
64 private static final String BUILT_IN_NAME = "Sonar way";
66 private DbClient dbClient = db.getDbClient();
67 private DbSession dbSession = db.getSession();
69 private QualityGateDao qualityGateDao = dbClient.qualityGateDao();
70 private QualityGateConditionDao gateConditionDao = dbClient.gateConditionDao();
71 private MetricDao metricDao = dbClient.metricDao();
72 private QualityGateConditionsUpdater qualityGateConditionsUpdater = new QualityGateConditionsUpdater(dbClient);
73 private QualityGateFinder qualityGateFinder = new QualityGateFinder(dbClient);
75 private RegisterQualityGates underTest = new RegisterQualityGates(dbClient, qualityGateConditionsUpdater,
76 UuidFactoryFast.getInstance(), System2.INSTANCE);
79 public void register_default_gate() {
84 verifyCorrectBuiltInQualityGate();
86 logTester.logs(LoggerLevel.INFO).contains("Built-in quality gate [Sonar way] has been created")).isTrue();
88 logTester.logs(LoggerLevel.INFO).contains("Built-in quality gate's conditions of [Sonar way] has been updated")).isTrue();
92 public void upgrade_empty_quality_gate() {
97 assertThat(db.countRowsOfTable("quality_gates")).isEqualTo(1);
98 verifyCorrectBuiltInQualityGate();
100 logTester.logs(LoggerLevel.INFO).contains("Built-in quality gate's conditions of [Sonar way] has been updated")).isTrue();
104 public void upgrade_should_remove_deleted_condition() {
106 QualityGateDto builtInQualityGate = db.qualityGates().insertBuiltInQualityGate();
107 createBuiltInConditions(builtInQualityGate);
108 // Add another condition
109 qualityGateConditionsUpdater.createCondition(dbSession, builtInQualityGate,
110 NEW_SECURITY_REMEDIATION_EFFORT_KEY, OPERATOR_GREATER_THAN, "5");
115 assertThat(db.countRowsOfTable("quality_gates")).isEqualTo(1);
116 verifyCorrectBuiltInQualityGate();
118 logTester.logs(LoggerLevel.INFO).contains("Built-in quality gate's conditions of [Sonar way] has been updated")).isTrue();
122 public void upgrade_should_add_missing_condition() {
124 QualityGateDto builtInQualityGate = db.qualityGates().insertBuiltInQualityGate();
125 List<QualityGateConditionDto> builtInConditions = createBuiltInConditions(builtInQualityGate);
126 // Remove a condition
127 QualityGateConditionDto conditionToBeDeleted = builtInConditions.get(new Random().nextInt(builtInConditions.size()));
128 gateConditionDao.delete(conditionToBeDeleted, dbSession);
133 assertThat(db.countRowsOfTable("quality_gates")).isEqualTo(1);
134 verifyCorrectBuiltInQualityGate();
136 logTester.logs(LoggerLevel.INFO).contains("Built-in quality gate's conditions of [Sonar way] has been updated")).isTrue();
140 public void should_set_SonarWay_as_builtin_when_not_set() {
142 QualityGateDto qualityGate = dbClient.qualityGateDao().insert(dbSession, new QualityGateDto()
143 .setName("Sonar way")
144 .setUuid(Uuids.createFast())
146 .setCreatedAt(new Date()));
148 createBuiltInConditions(qualityGate);
153 assertThat(db.countRowsOfTable("quality_gates")).isEqualTo(1);
154 verifyCorrectBuiltInQualityGate();
156 logTester.logs(LoggerLevel.INFO).contains("Quality gate [Sonar way] has been set as built-in")).isTrue();
160 public void should_not_update_builtin_quality_gate_if_already_uptodate() {
162 QualityGateDto builtInQualityGate = db.qualityGates().insertBuiltInQualityGate();
163 createBuiltInConditions(builtInQualityGate);
168 assertThat(db.countRowsOfTable("quality_gates")).isEqualTo(1);
169 verifyCorrectBuiltInQualityGate();
170 // Log must not be present
172 logTester.logs(LoggerLevel.INFO).contains("Quality gate [Sonar way] has been set as built-in")).isFalse();
174 logTester.logs(LoggerLevel.INFO).contains("Built-in quality gate [Sonar way] has been created")).isFalse();
176 logTester.logs(LoggerLevel.INFO).contains("Built-in quality gate's conditions of [Sonar way] has been updated")).isFalse();
180 public void ensure_only_one_built_in_quality_gate() {
182 String qualityGateName = "IncorrectQualityGate";
183 QualityGateDto builtin = new QualityGateDto().setName(qualityGateName).setBuiltIn(true).setUuid(Uuids.createFast());
184 qualityGateDao.insert(dbSession, builtin);
189 QualityGateDto oldQualityGate = qualityGateDao.selectByName(dbSession, qualityGateName);
190 assertThat(oldQualityGate).isNotNull();
191 assertThat(oldQualityGate.isBuiltIn()).isFalse();
192 assertThat(db.select("select name as \"name\" from quality_gates where is_built_in is true"))
193 .extracting(column -> column.get("name"))
194 .containsExactly(BUILT_IN_NAME);
196 logTester.logs(LoggerLevel.INFO).contains("Built-in quality gate [Sonar way] has been created")).isTrue();
198 logTester.logs(LoggerLevel.INFO).contains("Built-in quality gate's conditions of [Sonar way] has been updated")).isTrue();
202 public void ensure_only_that_builtin_is_set_as_default_when_no_default_quality_gate() {
204 QualityGateDto builtInQualityGate = db.qualityGates().insertBuiltInQualityGate();
208 assertThat(qualityGateFinder.getBuiltInQualityGate(dbSession)).isNotNull();
209 assertThat(qualityGateFinder.getBuiltInQualityGate(dbSession).getId()).isEqualTo(builtInQualityGate.getId());
213 public void builtin_quality_gate_with_incorrect_metricId_should_not_throw_an_exception() {
215 QualityGateConditionDto conditionDto = new QualityGateConditionDto()
216 .setMetricId(-1) // This Id does not exist
217 .setOperator(OPERATOR_GREATER_THAN)
218 .setErrorThreshold("1");
219 gateConditionDao.insert(conditionDto, dbSession);
224 // No exception thrown
225 verifyCorrectBuiltInQualityGate();
227 logTester.logs(LoggerLevel.INFO).contains("Built-in quality gate's conditions of [Sonar way] has been updated")).isTrue();
230 private void insertMetrics() {
231 dbClient.metricDao().insert(dbSession, newMetricDto().setKey(NEW_RELIABILITY_RATING_KEY).setValueType(INT.name()).setHidden(false).setDirection(0));
232 dbClient.metricDao().insert(dbSession, newMetricDto().setKey(NEW_SECURITY_RATING_KEY).setValueType(INT.name()).setHidden(false).setDirection(0));
233 dbClient.metricDao().insert(dbSession, newMetricDto().setKey(NEW_SECURITY_REMEDIATION_EFFORT_KEY).setValueType(INT.name()).setHidden(false).setDirection(0));
234 dbClient.metricDao().insert(dbSession, newMetricDto().setKey(NEW_MAINTAINABILITY_RATING_KEY).setValueType(PERCENT.name()).setHidden(false).setDirection(0));
235 dbClient.metricDao().insert(dbSession, newMetricDto().setKey(NEW_COVERAGE_KEY).setValueType(PERCENT.name()).setHidden(false).setDirection(0));
236 dbClient.metricDao().insert(dbSession, newMetricDto().setKey(NEW_DUPLICATED_LINES_DENSITY_KEY).setValueType(PERCENT.name()).setHidden(false).setDirection(0));
240 private void verifyCorrectBuiltInQualityGate() {
241 MetricDto newReliability = metricDao.selectByKey(dbSession, NEW_RELIABILITY_RATING_KEY);
242 MetricDto newSecurity = metricDao.selectByKey(dbSession, NEW_SECURITY_RATING_KEY);
243 MetricDto newMaintainability = metricDao.selectByKey(dbSession, NEW_MAINTAINABILITY_RATING_KEY);
244 MetricDto newCoverage = metricDao.selectByKey(dbSession, NEW_COVERAGE_KEY);
245 MetricDto newDuplication = metricDao.selectByKey(dbSession, NEW_DUPLICATED_LINES_DENSITY_KEY);
247 QualityGateDto qualityGateDto = qualityGateDao.selectByName(dbSession, BUILT_IN_NAME);
248 assertThat(qualityGateDto).isNotNull();
249 assertThat(qualityGateDto.getCreatedAt()).isNotNull();
250 assertThat(qualityGateDto.isBuiltIn()).isTrue();
251 assertThat(gateConditionDao.selectForQualityGate(dbSession, qualityGateDto.getId()))
252 .extracting(QualityGateConditionDto::getMetricId, QualityGateConditionDto::getOperator,
253 QualityGateConditionDto::getErrorThreshold)
255 tuple(newReliability.getId().longValue(), OPERATOR_GREATER_THAN, "1"),
256 tuple(newSecurity.getId().longValue(), OPERATOR_GREATER_THAN, "1"),
257 tuple(newMaintainability.getId().longValue(), OPERATOR_GREATER_THAN, "1"),
258 tuple(newCoverage.getId().longValue(), OPERATOR_LESS_THAN, "80"),
259 tuple(newDuplication.getId().longValue(), OPERATOR_GREATER_THAN, "3"));
262 private List<QualityGateConditionDto> createBuiltInConditions(QualityGateDto qg) {
263 List<QualityGateConditionDto> conditions = new ArrayList<>();
265 conditions.add(qualityGateConditionsUpdater.createCondition(dbSession, qg,
266 NEW_SECURITY_RATING_KEY, OPERATOR_GREATER_THAN, "1"));
267 conditions.add(qualityGateConditionsUpdater.createCondition(dbSession, qg,
268 NEW_RELIABILITY_RATING_KEY, OPERATOR_GREATER_THAN, "1"));
269 conditions.add(qualityGateConditionsUpdater.createCondition(dbSession, qg,
270 NEW_MAINTAINABILITY_RATING_KEY, OPERATOR_GREATER_THAN, "1"));
271 conditions.add(qualityGateConditionsUpdater.createCondition(dbSession, qg,
272 NEW_COVERAGE_KEY, OPERATOR_LESS_THAN, "80"));
273 conditions.add(qualityGateConditionsUpdater.createCondition(dbSession, qg,
274 NEW_DUPLICATED_LINES_DENSITY_KEY, OPERATOR_GREATER_THAN, "3"));