]> source.dussan.org Git - sonarqube.git/blob
22a71234a67c80bcda38cd97f1c2f14c8eba515b
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2022 SonarSource SA
4  * mailto:info AT sonarsource DOT com
5  *
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.
10  *
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.
15  *
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.
19  */
20 package org.sonar.server.qualitygate;
21
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;
42
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_HOTSPOTS_REVIEWED_KEY;
50 import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_RATING_KEY;
51 import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_REMEDIATION_EFFORT_KEY;
52 import static org.sonar.api.measures.Metric.ValueType.INT;
53 import static org.sonar.api.measures.Metric.ValueType.PERCENT;
54 import static org.sonar.db.metric.MetricTesting.newMetricDto;
55 import static org.sonar.db.qualitygate.QualityGateConditionDto.OPERATOR_GREATER_THAN;
56 import static org.sonar.db.qualitygate.QualityGateConditionDto.OPERATOR_LESS_THAN;
57
58 public class RegisterQualityGatesTest {
59
60   @Rule
61   public DbTester db = DbTester.create(System2.INSTANCE);
62   @Rule
63   public LogTester logTester = new LogTester();
64
65   private static final String BUILT_IN_NAME = "Sonar way";
66
67   private final DbClient dbClient = db.getDbClient();
68   private final DbSession dbSession = db.getSession();
69
70   private final QualityGateDao qualityGateDao = dbClient.qualityGateDao();
71   private final QualityGateConditionDao gateConditionDao = dbClient.gateConditionDao();
72   private final MetricDao metricDao = dbClient.metricDao();
73   private final QualityGateConditionsUpdater qualityGateConditionsUpdater = new QualityGateConditionsUpdater(dbClient);
74   private final QualityGateFinder qualityGateFinder = new QualityGateFinder(dbClient);
75
76   private final RegisterQualityGates underTest = new RegisterQualityGates(dbClient, qualityGateConditionsUpdater,
77     UuidFactoryFast.getInstance(), System2.INSTANCE);
78
79   @Test
80   public void register_default_gate() {
81     insertMetrics();
82
83     underTest.start();
84
85     verifyCorrectBuiltInQualityGate();
86     assertThat(
87       logTester.logs(LoggerLevel.INFO).contains("Built-in quality gate [Sonar way] has been created")).isTrue();
88     assertThat(
89       logTester.logs(LoggerLevel.INFO).contains("Built-in quality gate's conditions of [Sonar way] has been updated")).isTrue();
90   }
91
92   @Test
93   public void upgrade_empty_quality_gate() {
94     insertMetrics();
95
96     underTest.start();
97
98     assertThat(db.countRowsOfTable("quality_gates")).isOne();
99     verifyCorrectBuiltInQualityGate();
100     assertThat(
101       logTester.logs(LoggerLevel.INFO).contains("Built-in quality gate's conditions of [Sonar way] has been updated")).isTrue();
102   }
103
104   @Test
105   public void upgrade_should_remove_deleted_condition() {
106     insertMetrics();
107     QualityGateDto builtInQualityGate = db.qualityGates().insertBuiltInQualityGate();
108     createBuiltInConditions(builtInQualityGate);
109     // Add another condition
110     qualityGateConditionsUpdater.createCondition(dbSession, builtInQualityGate,
111       NEW_SECURITY_REMEDIATION_EFFORT_KEY, OPERATOR_GREATER_THAN, "5");
112     dbSession.commit();
113
114     underTest.start();
115
116     assertThat(db.countRowsOfTable("quality_gates")).isOne();
117     verifyCorrectBuiltInQualityGate();
118     assertThat(
119       logTester.logs(LoggerLevel.INFO).contains("Built-in quality gate's conditions of [Sonar way] has been updated")).isTrue();
120   }
121
122   @Test
123   public void upgrade_should_add_missing_condition() {
124     insertMetrics();
125     QualityGateDto builtInQualityGate = db.qualityGates().insertBuiltInQualityGate();
126     List<QualityGateConditionDto> builtInConditions = createBuiltInConditions(builtInQualityGate);
127     // Remove a condition
128     QualityGateConditionDto conditionToBeDeleted = builtInConditions.get(new Random().nextInt(builtInConditions.size()));
129     gateConditionDao.delete(conditionToBeDeleted, dbSession);
130     dbSession.commit();
131
132     underTest.start();
133
134     assertThat(db.countRowsOfTable("quality_gates")).isOne();
135     verifyCorrectBuiltInQualityGate();
136     assertThat(
137       logTester.logs(LoggerLevel.INFO).contains("Built-in quality gate's conditions of [Sonar way] has been updated")).isTrue();
138   }
139
140   @Test
141   public void should_set_SonarWay_as_builtin_when_not_set() {
142     insertMetrics();
143     QualityGateDto qualityGate = dbClient.qualityGateDao().insert(dbSession, new QualityGateDto()
144       .setName("Sonar way")
145       .setUuid(Uuids.createFast())
146       .setBuiltIn(false)
147       .setCreatedAt(new Date()));
148     dbSession.commit();
149     createBuiltInConditions(qualityGate);
150     dbSession.commit();
151
152     underTest.start();
153
154     assertThat(db.countRowsOfTable("quality_gates")).isOne();
155     verifyCorrectBuiltInQualityGate();
156     assertThat(
157       logTester.logs(LoggerLevel.INFO).contains("Quality gate [Sonar way] has been set as built-in")).isTrue();
158   }
159
160   @Test
161   public void should_not_update_builtin_quality_gate_if_already_uptodate() {
162     insertMetrics();
163     QualityGateDto builtInQualityGate = db.qualityGates().insertBuiltInQualityGate();
164     createBuiltInConditions(builtInQualityGate);
165     dbSession.commit();
166
167     underTest.start();
168
169     assertThat(db.countRowsOfTable("quality_gates")).isOne();
170     verifyCorrectBuiltInQualityGate();
171     // Log must not be present
172     assertThat(
173       logTester.logs(LoggerLevel.INFO).contains("Quality gate [Sonar way] has been set as built-in")).isFalse();
174     assertThat(
175       logTester.logs(LoggerLevel.INFO).contains("Built-in quality gate [Sonar way] has been created")).isFalse();
176     assertThat(
177       logTester.logs(LoggerLevel.INFO).contains("Built-in quality gate's conditions of [Sonar way] has been updated")).isFalse();
178   }
179
180   @Test
181   public void ensure_only_one_built_in_quality_gate() {
182     insertMetrics();
183     String qualityGateName = "IncorrectQualityGate";
184     QualityGateDto builtin = new QualityGateDto().setName(qualityGateName).setBuiltIn(true).setUuid(Uuids.createFast());
185     qualityGateDao.insert(dbSession, builtin);
186     dbSession.commit();
187
188     underTest.start();
189
190     QualityGateDto oldQualityGate = qualityGateDao.selectByName(dbSession, qualityGateName);
191     assertThat(oldQualityGate).isNotNull();
192     assertThat(oldQualityGate.isBuiltIn()).isFalse();
193     assertThat(db.select("select name as \"name\" from quality_gates where is_built_in is true"))
194       .extracting(column -> column.get("name"))
195       .containsExactly(BUILT_IN_NAME);
196     assertThat(
197       logTester.logs(LoggerLevel.INFO).contains("Built-in quality gate [Sonar way] has been created")).isTrue();
198     assertThat(
199       logTester.logs(LoggerLevel.INFO).contains("Built-in quality gate's conditions of [Sonar way] has been updated")).isTrue();
200   }
201
202   @Test
203   public void ensure_only_that_builtin_is_set_as_default_when_no_default_quality_gate() {
204     insertMetrics();
205     QualityGateDto builtInQualityGate = db.qualityGates().insertBuiltInQualityGate();
206
207     underTest.start();
208
209     assertThat(qualityGateFinder.getBuiltInQualityGate(dbSession)).isNotNull();
210     assertThat(qualityGateFinder.getBuiltInQualityGate(dbSession).getUuid()).isEqualTo(builtInQualityGate.getUuid());
211   }
212
213   @Test
214   public void builtin_quality_gate_with_incorrect_metricuuid_should_not_throw_an_exception() {
215     insertMetrics();
216     QualityGateConditionDto conditionDto = new QualityGateConditionDto()
217       .setUuid(Uuids.createFast())
218       .setQualityGateUuid("qgate_uuid")
219       .setMetricUuid("unknown") // This uuid does not exist
220       .setOperator(OPERATOR_GREATER_THAN)
221       .setErrorThreshold("1");
222     gateConditionDao.insert(conditionDto, dbSession);
223     dbSession.commit();
224
225     underTest.start();
226
227     // No exception thrown
228     verifyCorrectBuiltInQualityGate();
229     assertThat(
230       logTester.logs(LoggerLevel.INFO).contains("Built-in quality gate's conditions of [Sonar way] has been updated")).isTrue();
231   }
232
233   private void insertMetrics() {
234     dbClient.metricDao().insert(dbSession, newMetricDto().setKey(NEW_RELIABILITY_RATING_KEY).setValueType(INT.name()).setHidden(false).setDirection(0));
235     dbClient.metricDao().insert(dbSession, newMetricDto().setKey(NEW_SECURITY_RATING_KEY).setValueType(INT.name()).setHidden(false).setDirection(0));
236     dbClient.metricDao().insert(dbSession, newMetricDto().setKey(NEW_SECURITY_REMEDIATION_EFFORT_KEY).setValueType(INT.name()).setHidden(false).setDirection(0));
237     dbClient.metricDao().insert(dbSession, newMetricDto().setKey(NEW_MAINTAINABILITY_RATING_KEY).setValueType(PERCENT.name()).setHidden(false).setDirection(0));
238     dbClient.metricDao().insert(dbSession, newMetricDto().setKey(NEW_COVERAGE_KEY).setValueType(PERCENT.name()).setHidden(false).setDirection(0));
239     dbClient.metricDao().insert(dbSession, newMetricDto().setKey(NEW_DUPLICATED_LINES_DENSITY_KEY).setValueType(PERCENT.name()).setHidden(false).setDirection(0));
240     dbClient.metricDao().insert(dbSession, newMetricDto().setKey(NEW_SECURITY_HOTSPOTS_REVIEWED_KEY).setValueType(PERCENT.name()).setHidden(false).setDirection(0));
241     dbSession.commit();
242   }
243
244   private void verifyCorrectBuiltInQualityGate() {
245     MetricDto newReliability = metricDao.selectByKey(dbSession, NEW_RELIABILITY_RATING_KEY);
246     MetricDto newSecurity = metricDao.selectByKey(dbSession, NEW_SECURITY_RATING_KEY);
247     MetricDto newMaintainability = metricDao.selectByKey(dbSession, NEW_MAINTAINABILITY_RATING_KEY);
248     MetricDto newCoverage = metricDao.selectByKey(dbSession, NEW_COVERAGE_KEY);
249     MetricDto newDuplication = metricDao.selectByKey(dbSession, NEW_DUPLICATED_LINES_DENSITY_KEY);
250     MetricDto newSecurityHotspots = metricDao.selectByKey(dbSession, NEW_SECURITY_HOTSPOTS_REVIEWED_KEY);
251
252     QualityGateDto qualityGateDto = qualityGateDao.selectByName(dbSession, BUILT_IN_NAME);
253     assertThat(qualityGateDto).isNotNull();
254     assertThat(qualityGateDto.getCreatedAt()).isNotNull();
255     assertThat(qualityGateDto.isBuiltIn()).isTrue();
256     assertThat(gateConditionDao.selectForQualityGate(dbSession, qualityGateDto.getUuid()))
257       .extracting(QualityGateConditionDto::getMetricUuid, QualityGateConditionDto::getOperator,
258         QualityGateConditionDto::getErrorThreshold)
259       .containsExactlyInAnyOrder(
260         tuple(newReliability.getUuid(), OPERATOR_GREATER_THAN, "1"),
261         tuple(newSecurity.getUuid(), OPERATOR_GREATER_THAN, "1"),
262         tuple(newMaintainability.getUuid(), OPERATOR_GREATER_THAN, "1"),
263         tuple(newCoverage.getUuid(), OPERATOR_LESS_THAN, "80"),
264         tuple(newDuplication.getUuid(), OPERATOR_GREATER_THAN, "3"),
265         tuple(newSecurityHotspots.getUuid(), OPERATOR_LESS_THAN, "100"));
266   }
267
268   private List<QualityGateConditionDto> createBuiltInConditions(QualityGateDto qg) {
269     List<QualityGateConditionDto> conditions = new ArrayList<>();
270
271     conditions.add(qualityGateConditionsUpdater.createCondition(dbSession, qg,
272       NEW_SECURITY_RATING_KEY, OPERATOR_GREATER_THAN, "1"));
273     conditions.add(qualityGateConditionsUpdater.createCondition(dbSession, qg,
274       NEW_RELIABILITY_RATING_KEY, OPERATOR_GREATER_THAN, "1"));
275     conditions.add(qualityGateConditionsUpdater.createCondition(dbSession, qg,
276       NEW_MAINTAINABILITY_RATING_KEY, OPERATOR_GREATER_THAN, "1"));
277     conditions.add(qualityGateConditionsUpdater.createCondition(dbSession, qg,
278       NEW_COVERAGE_KEY, OPERATOR_LESS_THAN, "80"));
279     conditions.add(qualityGateConditionsUpdater.createCondition(dbSession, qg,
280       NEW_DUPLICATED_LINES_DENSITY_KEY, OPERATOR_GREATER_THAN, "3"));
281     conditions.add(qualityGateConditionsUpdater.createCondition(dbSession, qg,
282       NEW_SECURITY_HOTSPOTS_REVIEWED_KEY, OPERATOR_LESS_THAN, "100"));
283
284     return conditions;
285   }
286 }