]> source.dussan.org Git - sonarqube.git/blob
6bb3284df74197ca1045d46254b9eb0d5844321a
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2017 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 com.tngtech.java.junit.dataprovider.DataProvider;
23 import com.tngtech.java.junit.dataprovider.DataProviderRunner;
24 import com.tngtech.java.junit.dataprovider.UseDataProvider;
25 import javax.annotation.Nullable;
26 import org.junit.Before;
27 import org.junit.Rule;
28 import org.junit.Test;
29 import org.junit.rules.ExpectedException;
30 import org.junit.runner.RunWith;
31 import org.sonar.api.measures.Metric;
32 import org.sonar.api.utils.System2;
33 import org.sonar.db.DbClient;
34 import org.sonar.db.DbSession;
35 import org.sonar.db.DbTester;
36 import org.sonar.db.metric.MetricDto;
37 import org.sonar.db.qualitygate.QualityGateConditionDto;
38 import org.sonar.db.qualitygate.QualityGateDbTester;
39 import org.sonar.db.qualitygate.QualityGateDto;
40 import org.sonar.server.exceptions.BadRequestException;
41 import org.sonar.server.exceptions.NotFoundException;
42
43 import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
44 import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY;
45 import static org.sonar.api.measures.Metric.ValueType.DATA;
46 import static org.sonar.api.measures.Metric.ValueType.INT;
47 import static org.sonar.api.measures.Metric.ValueType.RATING;
48 import static org.sonar.db.metric.MetricTesting.newMetricDto;
49 import static org.sonar.server.computation.task.projectanalysis.metric.Metric.MetricType.PERCENT;
50
51 @RunWith(DataProviderRunner.class)
52 public class QualityGateConditionsUpdaterTest {
53
54   @Rule
55   public ExpectedException expectedException = ExpectedException.none();
56
57   @Rule
58   public DbTester db = DbTester.create(System2.INSTANCE);
59
60   DbClient dbClient = db.getDbClient();
61   DbSession dbSession = db.getSession();
62   QualityGateDbTester qualityGateDbTester = new QualityGateDbTester(db);
63
64   QualityGateDto qualityGateDto;
65   MetricDto coverageMetricDto = newMetricDto()
66     .setKey("coverage")
67     .setShortName("Coverage")
68     .setValueType(PERCENT.name())
69     .setHidden(false);
70
71   MetricDto ratingMetricDto = newMetricDto()
72     .setKey("reliability_rating")
73     .setShortName("Reliability Rating")
74     .setValueType(RATING.name())
75     .setHidden(false);
76
77   QualityGateConditionsUpdater underTest = new QualityGateConditionsUpdater(dbClient);
78
79   @Before
80   public void setUp() throws Exception {
81     qualityGateDto = qualityGateDbTester.insertQualityGate();
82     dbClient.metricDao().insert(dbSession, coverageMetricDto, ratingMetricDto);
83     dbSession.commit();
84   }
85
86   @Test
87   public void create_warning_condition_without_period() {
88     QualityGateConditionDto result = underTest.createCondition(dbSession, qualityGateDto, "coverage", "LT", "90", null, null);
89
90     verifyCondition(result, coverageMetricDto.getId(), "LT", "90", null, null);
91   }
92
93   @Test
94   public void create_error_condition_with_period() {
95     MetricDto metricDto = dbClient.metricDao().insert(dbSession, newMetricDto()
96       .setKey("new_coverage")
97       .setValueType(INT.name())
98       .setHidden(false));
99     dbSession.commit();
100
101     QualityGateConditionDto result = underTest.createCondition(dbSession, qualityGateDto, "new_coverage", "LT", null, "80", 1);
102
103     verifyCondition(result, metricDto.getId(), "LT", null, "80", 1);
104   }
105
106   @Test
107   public void fail_to_create_condition_when_condition_on_same_metric_already_exist() throws Exception {
108     dbClient.gateConditionDao().insert(new QualityGateConditionDto()
109       .setQualityGateId(qualityGateDto.getId())
110       .setMetricId(coverageMetricDto.getId())
111       .setPeriod(null),
112       dbSession);
113
114     expectedException.expect(BadRequestException.class);
115     expectedException.expectMessage("Condition on metric 'Coverage' already exists.");
116     underTest.createCondition(dbSession, qualityGateDto, coverageMetricDto.getKey(), "LT", "90", null, null);
117   }
118
119   @Test
120   public void fail_to_create_condition_when_condition_on_same_metric_and_on_leak_period_already_exist() throws Exception {
121     dbClient.gateConditionDao().insert(new QualityGateConditionDto()
122       .setQualityGateId(qualityGateDto.getId())
123       .setMetricId(coverageMetricDto.getId())
124       .setPeriod(1),
125       dbSession);
126
127     expectedException.expect(BadRequestException.class);
128     expectedException.expectMessage("Condition on metric 'Coverage' over leak period already exists.");
129     underTest.createCondition(dbSession, qualityGateDto, coverageMetricDto.getKey(), "LT", "90", null, 1);
130   }
131
132   @Test
133   public void fail_to_create_condition_on_missing_metric() {
134     expectedException.expect(NotFoundException.class);
135     expectedException.expectMessage("There is no metric with key=new_coverage");
136     underTest.createCondition(dbSession, qualityGateDto, "new_coverage", "LT", null, "80", 2);
137   }
138
139   @Test
140   @UseDataProvider("invalid_metrics")
141   public void fail_to_create_condition_on_invalid_metric(String metricKey, Metric.ValueType valueType, boolean hidden) {
142     dbClient.metricDao().insert(dbSession, newMetricDto()
143       .setKey(metricKey)
144       .setValueType(valueType.name())
145       .setHidden(hidden));
146     dbSession.commit();
147
148     expectedException.expect(BadRequestException.class);
149     expectedException.expectMessage("Metric '" + metricKey + "' cannot be used to define a condition.");
150     underTest.createCondition(dbSession, qualityGateDto, metricKey, "EQ", null, "80", null);
151   }
152
153   @Test
154   public void fail_to_create_condition_on_not_allowed_operator() {
155     expectedException.expect(BadRequestException.class);
156     expectedException.expectMessage("Operator UNKNOWN is not allowed for metric type PERCENT.");
157     underTest.createCondition(dbSession, qualityGateDto, "coverage", "UNKNOWN", null, "80", 2);
158   }
159
160   @Test
161   public void fail_to_create_condition_on_missing_period() {
162     dbClient.metricDao().insert(dbSession, newMetricDto()
163       .setKey("new_coverage")
164       .setValueType(INT.name())
165       .setHidden(false));
166     dbSession.commit();
167
168     expectedException.expect(BadRequestException.class);
169     expectedException.expectMessage("A period must be selected for differential metrics.");
170     underTest.createCondition(dbSession, qualityGateDto, "new_coverage", "EQ", null, "90", null);
171   }
172
173   @Test
174   public void fail_to_create_condition_on_invalid_period() {
175     expectedException.expect(BadRequestException.class);
176     expectedException.expectMessage("The only valid quality gate period is 1, the leak period.");
177     underTest.createCondition(dbSession, qualityGateDto, "coverage", "EQ", null, "90", 6);
178   }
179
180   @Test
181   public void create_condition_on_rating_metric() {
182     QualityGateConditionDto result = underTest.createCondition(dbSession, qualityGateDto, ratingMetricDto.getKey(), "GT", null, "3", null);
183
184     verifyCondition(result, ratingMetricDto.getId(), "GT", null, "3", null);
185   }
186
187   @Test
188   public void fail_to_create_condition_on_rating_metric_on_leak_period() {
189     expectedException.expect(BadRequestException.class);
190     expectedException.expectMessage("The metric 'Reliability Rating' cannot be used on the leak period");
191     underTest.createCondition(dbSession, qualityGateDto, ratingMetricDto.getKey(), "GT", null, "3", 1);
192   }
193
194   @Test
195   public void fail_to_create_warning_condition_on_invalid_rating_metric() {
196     expectedException.expect(BadRequestException.class);
197     expectedException.expectMessage("'6' is not a valid rating");
198     underTest.createCondition(dbSession, qualityGateDto, ratingMetricDto.getKey(), "GT", "6", null, null);
199   }
200
201   @Test
202   public void fail_to_create_error_condition_on_invalid_rating_metric() {
203     expectedException.expect(BadRequestException.class);
204     expectedException.expectMessage("'80' is not a valid rating");
205     underTest.createCondition(dbSession, qualityGateDto, ratingMetricDto.getKey(), "GT", null, "80", null);
206   }
207
208   @Test
209   public void fail_to_create_condition_on_greater_than_E() {
210     expectedException.expect(BadRequestException.class);
211     expectedException.expectMessage("There's no worse rating than E (5)");
212     underTest.createCondition(dbSession, qualityGateDto, ratingMetricDto.getKey(), "GT", "5", null, null);
213   }
214
215   @Test
216   public void update_condition() {
217     QualityGateConditionDto condition = insertCondition(coverageMetricDto.getId(), "LT", null, "80", null);
218
219     QualityGateConditionDto result = underTest.updateCondition(dbSession, condition, "coverage", "GT", "60", null, 1);
220
221     verifyCondition(result, coverageMetricDto.getId(), "GT", "60", null, 1);
222   }
223
224   @Test
225   public void update_condition_over_leak_period() {
226     QualityGateConditionDto condition = insertCondition(coverageMetricDto.getId(), "GT", "80", null, 1);
227
228     QualityGateConditionDto result = underTest.updateCondition(dbSession, condition, "coverage", "LT", null, "80", null);
229
230     verifyCondition(result, coverageMetricDto.getId(), "LT", null, "80", null);
231   }
232
233   @Test
234   public void update_condition_on_rating_metric() {
235     QualityGateConditionDto condition = insertCondition(ratingMetricDto.getId(), "LT", null, "3", null);
236
237     QualityGateConditionDto result = underTest.updateCondition(dbSession, condition, ratingMetricDto.getKey(), "GT", "4", null, null);
238
239     verifyCondition(result, ratingMetricDto.getId(), "GT", "4", null, null);
240   }
241
242   @Test
243   public void fail_to_update_condition_on_rating_metric_on_leak_period() {
244     QualityGateConditionDto condition = insertCondition(ratingMetricDto.getId(), "LT", null, "3", null);
245
246     expectedException.expect(BadRequestException.class);
247     expectedException.expectMessage("The metric 'Reliability Rating' cannot be used on the leak period");
248     underTest.updateCondition(dbSession, condition, ratingMetricDto.getKey(), "GT", "4", null, 1);
249   }
250
251   @Test
252   public void fail_to_update_condition_on_rating_metric_on_not_core_rating_metric() {
253     MetricDto metricDto = dbClient.metricDao().insert(dbSession, newMetricDto().setKey("rating_metric")
254       .setShortName("Not core rating")
255       .setValueType(RATING.name()).setHidden(false));
256     QualityGateConditionDto condition = insertCondition(metricDto.getId(), "LT", null, "3", null);
257     dbSession.commit();
258
259     expectedException.expect(BadRequestException.class);
260     expectedException.expectMessage("The metric 'Not core rating' cannot be used");
261     underTest.updateCondition(dbSession, condition, metricDto.getKey(), "GT", "4", null, 1);
262   }
263
264   @Test
265   @UseDataProvider("invalid_metrics")
266   public void fail_to_update_condition_on_invalid_metric(String metricKey, Metric.ValueType valueType, boolean hidden) {
267     MetricDto metricDto = dbClient.metricDao().insert(dbSession, newMetricDto()
268       .setKey(metricKey)
269       .setValueType(valueType.name())
270       .setHidden(hidden));
271     QualityGateConditionDto condition = insertCondition(metricDto.getId(), "LT", null, "80", null);
272     dbSession.commit();
273
274     expectedException.expect(BadRequestException.class);
275     expectedException.expectMessage("Metric '" + metricKey + "' cannot be used to define a condition.");
276     underTest.updateCondition(dbSession, condition, metricDto.getKey(), "GT", "60", null, 1);
277   }
278
279   @Test
280   public void fail_to_update_condition_when_condition_on_same_metric_already_exist() throws Exception {
281     QualityGateConditionDto conditionNotOnLeakPeriod = insertCondition(coverageMetricDto.getId(), "GT", "80", null, null);
282     QualityGateConditionDto conditionOnLeakPeriod = insertCondition(coverageMetricDto.getId(), "GT", "80", null, 1);
283
284     expectedException.expect(BadRequestException.class);
285     expectedException.expectMessage("Condition on metric 'Coverage' over leak period already exists.");
286     // Update condition not on leak period to be on leak period => will fail as this condition already exist
287     underTest.updateCondition(dbSession, conditionNotOnLeakPeriod, coverageMetricDto.getKey(), "GT", "80", null, 1);
288   }
289
290   @DataProvider
291   public static Object[][] invalid_metrics() {
292     return new Object[][] {
293       {ALERT_STATUS_KEY, INT, false},
294       {"data_metric", DATA, false},
295       {"hidden", INT, true}
296     };
297   }
298
299   private QualityGateConditionDto insertCondition(long metricId, String operator, @Nullable String warning, @Nullable String error,
300     @Nullable Integer period) {
301     QualityGateConditionDto qualityGateConditionDto = new QualityGateConditionDto().setQualityGateId(qualityGateDto.getId())
302       .setMetricId(metricId)
303       .setOperator(operator)
304       .setWarningThreshold(warning)
305       .setErrorThreshold(error)
306       .setPeriod(period);
307     dbClient.gateConditionDao().insert(qualityGateConditionDto, dbSession);
308     dbSession.commit();
309     return qualityGateConditionDto;
310   }
311
312   private void verifyCondition(QualityGateConditionDto dto, int metricId, String operator, @Nullable String warning, @Nullable String error, @Nullable Integer period) {
313     QualityGateConditionDto reloaded = dbClient.gateConditionDao().selectById(dto.getId(), dbSession);
314     assertThat(reloaded.getQualityGateId()).isEqualTo(qualityGateDto.getId());
315     assertThat(reloaded.getMetricId()).isEqualTo(metricId);
316     assertThat(reloaded.getOperator()).isEqualTo(operator);
317     assertThat(reloaded.getWarningThreshold()).isEqualTo(warning);
318     assertThat(reloaded.getErrorThreshold()).isEqualTo(error);
319     assertThat(reloaded.getPeriod()).isEqualTo(period);
320
321     assertThat(dto.getQualityGateId()).isEqualTo(qualityGateDto.getId());
322     assertThat(dto.getMetricId()).isEqualTo(metricId);
323     assertThat(dto.getOperator()).isEqualTo(operator);
324     assertThat(dto.getWarningThreshold()).isEqualTo(warning);
325     assertThat(dto.getErrorThreshold()).isEqualTo(error);
326     assertThat(dto.getPeriod()).isEqualTo(period);
327   }
328
329 }