]> source.dussan.org Git - sonarqube.git/blob
2269165109d65e2329d83e64b733701ba88e0ca5
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2019 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.Rule;
27 import org.junit.Test;
28 import org.junit.rules.ExpectedException;
29 import org.junit.runner.RunWith;
30 import org.sonar.api.measures.Metric;
31 import org.sonar.api.utils.System2;
32 import org.sonar.db.DbTester;
33 import org.sonar.db.metric.MetricDto;
34 import org.sonar.db.qualitygate.QualityGateConditionDto;
35 import org.sonar.db.qualitygate.QualityGateDto;
36 import org.sonar.server.exceptions.BadRequestException;
37 import org.sonar.server.exceptions.NotFoundException;
38
39 import static java.lang.String.format;
40 import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
41 import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY;
42 import static org.sonar.api.measures.CoreMetrics.SQALE_RATING_KEY;
43 import static org.sonar.api.measures.Metric.ValueType.BOOL;
44 import static org.sonar.api.measures.Metric.ValueType.DATA;
45 import static org.sonar.api.measures.Metric.ValueType.FLOAT;
46 import static org.sonar.api.measures.Metric.ValueType.INT;
47 import static org.sonar.api.measures.Metric.ValueType.MILLISEC;
48 import static org.sonar.api.measures.Metric.ValueType.PERCENT;
49 import static org.sonar.api.measures.Metric.ValueType.RATING;
50 import static org.sonar.api.measures.Metric.ValueType.WORK_DUR;
51
52 @RunWith(DataProviderRunner.class)
53 public class QualityGateConditionsUpdaterTest {
54
55   @Rule
56   public ExpectedException expectedException = ExpectedException.none();
57
58   @Rule
59   public DbTester db = DbTester.create(System2.INSTANCE);
60
61   private QualityGateConditionsUpdater underTest = new QualityGateConditionsUpdater(db.getDbClient());
62
63   @Test
64   public void create_error_condition() {
65     MetricDto metric = db.measures().insertMetric(m -> m.setKey("new_coverage").setValueType(INT.name()).setHidden(false));
66     QualityGateDto qualityGate = db.qualityGates().insertQualityGate(db.getDefaultOrganization());
67
68     QualityGateConditionDto result = underTest.createCondition(db.getSession(), qualityGate, metric.getKey(), "LT", "80");
69
70     verifyCondition(result, qualityGate, metric, "LT", "80");
71   }
72
73   @Test
74   public void create_condition_throws_NPE_if_errorThreshold_is_null() {
75     MetricDto metric = db.measures().insertMetric(m -> m.setKey(SQALE_RATING_KEY).setValueType(RATING.name()).setHidden(false));
76     QualityGateDto qualityGate = db.qualityGates().insertQualityGate(db.getDefaultOrganization());
77
78     expectedException.expect(NullPointerException.class);
79     expectedException.expectMessage("errorThreshold can not be null");
80
81     underTest.createCondition(db.getSession(), qualityGate, metric.getKey(), "GT", null);
82   }
83
84   @Test
85   public void fail_to_create_condition_when_condition_on_same_metric_already_exist() {
86     MetricDto metric = db.measures().insertMetric(m -> m.setValueType(PERCENT.name()).setHidden(false));
87     QualityGateDto qualityGate = db.qualityGates().insertQualityGate(db.getDefaultOrganization());
88     db.qualityGates().addCondition(qualityGate, metric);
89
90     expectedException.expect(BadRequestException.class);
91     expectedException.expectMessage(format("Condition on metric '%s' already exists.", metric.getShortName()));
92
93     underTest.createCondition(db.getSession(), qualityGate, metric.getKey(), "LT", "90");
94   }
95
96   @Test
97   public void fail_to_create_condition_on_missing_metric() {
98     QualityGateDto qualityGate = db.qualityGates().insertQualityGate(db.getDefaultOrganization());
99
100     expectedException.expect(NotFoundException.class);
101     expectedException.expectMessage("There is no metric with key=new_coverage");
102
103     underTest.createCondition(db.getSession(), qualityGate, "new_coverage", "LT", "80");
104   }
105
106   @Test
107   @UseDataProvider("invalid_metrics")
108   public void fail_to_create_condition_on_invalid_metric(String metricKey, Metric.ValueType valueType, boolean hidden) {
109     MetricDto metric = db.measures().insertMetric(m -> m.setKey(metricKey).setValueType(valueType.name()).setHidden(hidden));
110     QualityGateDto qualityGate = db.qualityGates().insertQualityGate(db.getDefaultOrganization());
111
112     expectedException.expect(BadRequestException.class);
113     expectedException.expectMessage(format("Metric '%s' cannot be used to define a condition.", metric.getKey()));
114
115     underTest.createCondition(db.getSession(), qualityGate, metric.getKey(), "EQ", "80");
116   }
117
118   @Test
119   public void fail_to_create_condition_on_not_allowed_operator() {
120     MetricDto metric = db.measures().insertMetric(m -> m.setValueType(PERCENT.name()).setHidden(false));
121     QualityGateDto qualityGate = db.qualityGates().insertQualityGate(db.getDefaultOrganization());
122
123     expectedException.expect(BadRequestException.class);
124     expectedException.expectMessage("Operator UNKNOWN is not allowed for metric type PERCENT.");
125
126     underTest.createCondition(db.getSession(), qualityGate, metric.getKey(), "UNKNOWN", "90");
127   }
128
129   @Test
130   public void create_condition_on_rating_metric() {
131     MetricDto metric = db.measures().insertMetric(m -> m.setKey(SQALE_RATING_KEY).setValueType(RATING.name()).setHidden(false));
132     QualityGateDto qualityGate = db.qualityGates().insertQualityGate(db.getDefaultOrganization());
133
134     QualityGateConditionDto result = underTest.createCondition(db.getSession(), qualityGate, metric.getKey(), "GT", "3");
135
136     verifyCondition(result, qualityGate, metric, "GT", "3");
137   }
138
139   @Test
140   public void fail_to_create_error_condition_on_invalid_rating_metric() {
141     MetricDto metric = db.measures().insertMetric(m -> m.setKey(SQALE_RATING_KEY).setValueType(RATING.name()).setHidden(false));
142     QualityGateDto qualityGate = db.qualityGates().insertQualityGate(db.getDefaultOrganization());
143
144     expectedException.expect(BadRequestException.class);
145     expectedException.expectMessage("'80' is not a valid rating");
146
147     underTest.createCondition(db.getSession(), qualityGate, metric.getKey(), "GT", "80");
148   }
149
150   @Test
151   public void fail_to_create_condition_on_greater_than_E() {
152     MetricDto metric = db.measures().insertMetric(m -> m.setKey(SQALE_RATING_KEY).setValueType(RATING.name()).setHidden(false));
153     QualityGateDto qualityGate = db.qualityGates().insertQualityGate(db.getDefaultOrganization());
154
155     expectedException.expect(BadRequestException.class);
156     expectedException.expectMessage("There's no worse rating than E (5)");
157
158     underTest.createCondition(db.getSession(), qualityGate, metric.getKey(), "GT", "5");
159   }
160
161   @Test
162   @UseDataProvider("valid_values")
163   public void create_error_condition(Metric.ValueType valueType, String value) {
164     MetricDto metric = db.measures().insertMetric(m -> m.setValueType(valueType.name()).setHidden(false));
165     QualityGateDto qualityGate = db.qualityGates().insertQualityGate(db.getDefaultOrganization());
166
167     QualityGateConditionDto result = underTest.createCondition(db.getSession(), qualityGate, metric.getKey(), "EQ", value);
168
169     verifyCondition(result, qualityGate, metric, "EQ", value);
170   }
171
172   @Test
173   @UseDataProvider("invalid_values")
174   public void fail_to_create_error_INT_condition_when_value_is_not_an_integer(Metric.ValueType valueType, String value) {
175     MetricDto metric = db.measures().insertMetric(m -> m.setValueType(valueType.name()).setHidden(false));
176     QualityGateDto qualityGate = db.qualityGates().insertQualityGate(db.getDefaultOrganization());
177
178     expectedException.expect(BadRequestException.class);
179     expectedException.expectMessage(format("Invalid value '%s' for metric '%s'", value, metric.getShortName()));
180
181     underTest.createCondition(db.getSession(), qualityGate, metric.getKey(), "EQ", value);
182   }
183
184   @Test
185   public void update_condition() {
186     MetricDto metric = db.measures().insertMetric(m -> m.setValueType(PERCENT.name()).setHidden(false));
187     QualityGateDto qualityGate = db.qualityGates().insertQualityGate(db.getDefaultOrganization());
188     QualityGateConditionDto condition = db.qualityGates().addCondition(qualityGate, metric,
189       c -> c.setOperator("LT").setErrorThreshold("80"));
190
191     QualityGateConditionDto result = underTest.updateCondition(db.getSession(), condition, metric.getKey(), "LT", "80");
192
193     verifyCondition(result, qualityGate, metric, "LT", "80");
194   }
195
196   @Test
197   public void update_condition_throws_NPE_if_errorThreshold_is_null() {
198     MetricDto metric = db.measures().insertMetric(m -> m.setValueType(PERCENT.name()).setHidden(false));
199     QualityGateDto qualityGate = db.qualityGates().insertQualityGate(db.getDefaultOrganization());
200     QualityGateConditionDto condition = db.qualityGates().addCondition(qualityGate, metric,
201       c -> c.setOperator("LT").setErrorThreshold("80"));
202
203     expectedException.expect(NullPointerException.class);
204     expectedException.expectMessage("errorThreshold can not be null");
205
206     underTest.updateCondition(db.getSession(), condition, metric.getKey(), "GT", null);
207   }
208
209   @Test
210   public void update_condition_on_rating_metric() {
211     MetricDto metric = db.measures().insertMetric(m -> m.setKey(SQALE_RATING_KEY).setValueType(RATING.name()).setHidden(false));
212     QualityGateDto qualityGate = db.qualityGates().insertQualityGate(db.getDefaultOrganization());
213     QualityGateConditionDto condition = db.qualityGates().addCondition(qualityGate, metric,
214       c -> c.setOperator("LT").setErrorThreshold("80"));
215
216     QualityGateConditionDto result = underTest.updateCondition(db.getSession(), condition, metric.getKey(), "GT", "4");
217
218     verifyCondition(result, qualityGate, metric, "GT", "4");
219   }
220
221   @Test
222   public void fail_to_update_condition_on_rating_metric_on_not_core_rating_metric() {
223     MetricDto metric = db.measures().insertMetric(m -> m.setKey("not_core_rating_metric").setValueType(RATING.name()).setHidden(false));
224     QualityGateDto qualityGate = db.qualityGates().insertQualityGate(db.getDefaultOrganization());
225     QualityGateConditionDto condition = db.qualityGates().addCondition(qualityGate, metric,
226       c -> c.setOperator("LT").setErrorThreshold("3"));
227
228     expectedException.expect(BadRequestException.class);
229     expectedException.expectMessage(format("The metric '%s' cannot be used", metric.getShortName()));
230
231     underTest.updateCondition(db.getSession(), condition, metric.getKey(), "GT", "4");
232   }
233
234   @Test
235   @UseDataProvider("invalid_metrics")
236   public void fail_to_update_condition_on_invalid_metric(String metricKey, Metric.ValueType valueType, boolean hidden) {
237     MetricDto metric = db.measures().insertMetric(m -> m.setKey(metricKey).setValueType(valueType.name()).setHidden(hidden));
238     QualityGateDto qualityGate = db.qualityGates().insertQualityGate(db.getDefaultOrganization());
239     QualityGateConditionDto condition = db.qualityGates().addCondition(qualityGate, metric,
240       c -> c.setOperator("LT").setErrorThreshold("80"));
241
242     expectedException.expect(BadRequestException.class);
243     expectedException.expectMessage(format("Metric '%s' cannot be used to define a condition.", metric.getKey()));
244
245     underTest.updateCondition(db.getSession(), condition, metric.getKey(), "GT", "60");
246   }
247
248   @Test
249   @UseDataProvider("valid_values")
250   public void update_error_condition(Metric.ValueType valueType, String value) {
251     MetricDto metric = db.measures().insertMetric(m -> m.setValueType(valueType.name()).setHidden(false));
252     QualityGateDto qualityGate = db.qualityGates().insertQualityGate(db.getDefaultOrganization());
253     QualityGateConditionDto condition = db.qualityGates().addCondition(qualityGate, metric,
254       c -> c.setOperator("LT").setErrorThreshold("80"));
255
256     QualityGateConditionDto result = underTest.updateCondition(db.getSession(), condition, metric.getKey(), "EQ", value);
257
258     verifyCondition(result, qualityGate, metric, "EQ", value);
259   }
260
261   @Test
262   @UseDataProvider("invalid_values")
263   public void fail_to_update_error_INT_condition_when_value_is_not_an_integer(Metric.ValueType valueType, String value) {
264     MetricDto metric = db.measures().insertMetric(m -> m.setValueType(valueType.name()).setHidden(false));
265     QualityGateDto qualityGate = db.qualityGates().insertQualityGate(db.getDefaultOrganization());
266     QualityGateConditionDto condition = db.qualityGates().addCondition(qualityGate, metric,
267       c -> c.setOperator("LT").setErrorThreshold("80"));
268
269     expectedException.expect(BadRequestException.class);
270     expectedException.expectMessage(format("Invalid value '%s' for metric '%s'", value, metric.getShortName()));
271
272     underTest.updateCondition(db.getSession(), condition, metric.getKey(), "EQ", value);
273   }
274
275   @DataProvider
276   public static Object[][] invalid_metrics() {
277     return new Object[][] {
278       {ALERT_STATUS_KEY, INT, false},
279       {"data_metric", DATA, false},
280       {"hidden", INT, true}
281     };
282   }
283
284   @DataProvider
285   public static Object[][] valid_values() {
286     return new Object[][] {
287       {INT, "10"},
288       {BOOL, "1"},
289       {MILLISEC, "1000"},
290       {WORK_DUR, "1000"},
291       {FLOAT, "5.12"},
292       {PERCENT, "10.30"},
293     };
294   }
295
296   @DataProvider
297   public static Object[][] invalid_values() {
298     return new Object[][] {
299       {INT, "ABCD"},
300       {BOOL, "ABCD"},
301       {MILLISEC, "ABCD"},
302       {WORK_DUR, "ABCD"},
303       {FLOAT, "ABCD"},
304       {PERCENT, "ABCD"},
305     };
306   }
307
308   private void verifyCondition(QualityGateConditionDto dto, QualityGateDto qualityGate, MetricDto metric, String operator, String error) {
309     QualityGateConditionDto reloaded = db.getDbClient().gateConditionDao().selectById(dto.getId(), db.getSession());
310     assertThat(reloaded.getQualityGateId()).isEqualTo(qualityGate.getId());
311     assertThat(reloaded.getMetricId()).isEqualTo(metric.getId().longValue());
312     assertThat(reloaded.getOperator()).isEqualTo(operator);
313     assertThat(reloaded.getErrorThreshold()).isEqualTo(error);
314
315     assertThat(dto.getQualityGateId()).isEqualTo(qualityGate.getId());
316     assertThat(dto.getMetricId()).isEqualTo(metric.getId().longValue());
317     assertThat(dto.getOperator()).isEqualTo(operator);
318     assertThat(dto.getErrorThreshold()).isEqualTo(error);
319   }
320
321 }