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.ImmutableSet;
23 import com.tngtech.java.junit.dataprovider.DataProvider;
24 import com.tngtech.java.junit.dataprovider.DataProviderRunner;
25 import com.tngtech.java.junit.dataprovider.UseDataProvider;
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.ce.task.projectanalysis.measure.Measure;
31 import org.sonar.ce.task.projectanalysis.metric.Metric;
32 import org.sonar.ce.task.projectanalysis.metric.MetricImpl;
34 import static com.google.common.base.Predicates.in;
35 import static com.google.common.base.Predicates.not;
36 import static com.google.common.collect.FluentIterable.from;
37 import static java.util.Arrays.asList;
38 import static org.junit.Assert.fail;
39 import static org.sonar.ce.task.projectanalysis.measure.Measure.newMeasureBuilder;
40 import static org.sonar.ce.task.projectanalysis.measure.Measure.Level.ERROR;
41 import static org.sonar.ce.task.projectanalysis.measure.Measure.Level.OK;
42 import static org.sonar.ce.task.projectanalysis.metric.Metric.MetricType;
43 import static org.sonar.ce.task.projectanalysis.metric.Metric.MetricType.BOOL;
44 import static org.sonar.ce.task.projectanalysis.metric.Metric.MetricType.DATA;
45 import static org.sonar.ce.task.projectanalysis.metric.Metric.MetricType.FLOAT;
46 import static org.sonar.ce.task.projectanalysis.metric.Metric.MetricType.INT;
47 import static org.sonar.ce.task.projectanalysis.metric.Metric.MetricType.LEVEL;
48 import static org.sonar.ce.task.projectanalysis.metric.Metric.MetricType.PERCENT;
49 import static org.sonar.ce.task.projectanalysis.metric.Metric.MetricType.RATING;
50 import static org.sonar.ce.task.projectanalysis.metric.Metric.MetricType.STRING;
51 import static org.sonar.ce.task.projectanalysis.metric.Metric.MetricType.WORK_DUR;
52 import static org.sonar.ce.task.projectanalysis.metric.Metric.MetricType.values;
53 import static org.sonar.ce.task.projectanalysis.qualitygate.Condition.Operator.EQUALS;
54 import static org.sonar.ce.task.projectanalysis.qualitygate.Condition.Operator.GREATER_THAN;
55 import static org.sonar.ce.task.projectanalysis.qualitygate.Condition.Operator.LESS_THAN;
56 import static org.sonar.ce.task.projectanalysis.qualitygate.Condition.Operator.NOT_EQUALS;
57 import static org.sonar.ce.task.projectanalysis.qualitygate.EvaluationResultAssert.assertThat;
59 @RunWith(DataProviderRunner.class)
60 public class ConditionEvaluatorTest {
62 public ExpectedException expectedException = ExpectedException.none();
64 private ConditionEvaluator underTest = new ConditionEvaluator();
67 public void test_input_numbers() {
69 Metric metric = createMetric(FLOAT);
70 Measure measure = newMeasureBuilder().create(10.2d, 1, null);
71 underTest.evaluate(createErrorCondition(metric, LESS_THAN, "20"), measure);
72 } catch (NumberFormatException ex) {
77 Metric metric = createMetric(INT);
78 Measure measure = newMeasureBuilder().create(5, null);
79 underTest.evaluate(createErrorCondition(metric, LESS_THAN, "20.1"), measure);
80 } catch (NumberFormatException ex) {
85 Metric metric = createMetric(PERCENT);
86 Measure measure = newMeasureBuilder().create(10.2d, 1, null);
87 underTest.evaluate(createErrorCondition(metric, LESS_THAN, "20.1"), measure);
88 } catch (NumberFormatException ex) {
94 public void testEquals_for_double() {
95 Metric metric = createMetric(FLOAT);
96 Measure measure = newMeasureBuilder().create(10.2d, 1, null);
98 assertThat(underTest.evaluate(createErrorCondition(metric, EQUALS, "10.2"), measure)).hasLevel(ERROR).hasValue(10.2d);
99 assertThat(underTest.evaluate(createErrorCondition(metric, EQUALS, "10.1"), measure)).hasLevel(OK).hasValue(10.2d);
103 public void testEquals_for_String() {
104 Metric metric = createMetric(STRING);
105 Measure measure = newMeasureBuilder().create("TEST");
107 assertThat(underTest.evaluate(createErrorCondition(metric, EQUALS, "TEST"), measure)).hasLevel(ERROR).hasValue("TEST");
108 assertThat(underTest.evaluate(createErrorCondition(metric, EQUALS, "TEST2"), measure)).hasLevel(OK).hasValue("TEST");
112 public void testNotEquals_for_double() {
113 Metric metric = createMetric(FLOAT);
114 Measure measure = newMeasureBuilder().create(10.2d, 1, null);
116 assertThat(underTest.evaluate(createErrorCondition(metric, NOT_EQUALS, "10.2"), measure)).hasLevel(OK).hasValue(10.2d);
117 assertThat(underTest.evaluate(createErrorCondition(metric, NOT_EQUALS, "10.1"), measure)).hasLevel(ERROR).hasValue(10.2d);
121 public void testNotEquals() {
122 Metric metric = createMetric(STRING);
123 Measure measure = newMeasureBuilder().create("TEST");
125 assertThat(underTest.evaluate(createErrorCondition(metric, NOT_EQUALS, "TEST"), measure)).hasLevel(OK).hasValue("TEST");
126 assertThat(underTest.evaluate(createErrorCondition(metric, NOT_EQUALS, "TEST2"), measure)).hasLevel(ERROR).hasValue("TEST");
130 public void testGreater() {
131 Metric metric = createMetric(FLOAT);
132 Measure measure = newMeasureBuilder().create(10.2d, 1, null);
134 assertThat(underTest.evaluate(createErrorCondition(metric, GREATER_THAN, "10.1"), measure)).hasLevel(ERROR).hasValue(10.2d);
135 assertThat(underTest.evaluate(createErrorCondition(metric, GREATER_THAN, "10.2"), measure)).hasLevel(OK).hasValue(10.2d);
136 assertThat(underTest.evaluate(createErrorCondition(metric, GREATER_THAN, "10.3"), measure)).hasLevel(OK).hasValue(10.2d);
140 public void testSmaller() {
141 Metric metric = createMetric(FLOAT);
142 Measure measure = newMeasureBuilder().create(10.2d, 1, null);
144 assertThat(underTest.evaluate(createErrorCondition(metric, LESS_THAN, "10.1"), measure)).hasLevel(OK).hasValue(10.2d);
145 assertThat(underTest.evaluate(createErrorCondition(metric, LESS_THAN, "10.2"), measure)).hasLevel(OK).hasValue(10.2d);
146 assertThat(underTest.evaluate(createErrorCondition(metric, LESS_THAN, "10.3"), measure)).hasLevel(ERROR).hasValue(10.2d);
150 public void testEquals_Percent() {
151 Metric metric = createMetric(PERCENT);
152 Measure measure = newMeasureBuilder().create(10.2d, 1, null);
154 assertThat(underTest.evaluate(createErrorCondition(metric, EQUALS, "10.2"), measure)).hasLevel(ERROR).hasValue(10.2d);
158 public void testEquals_Float() {
159 Metric metric = createMetric(PERCENT);
160 Measure measure = newMeasureBuilder().create(10.2d, 1, null);
162 assertThat(underTest.evaluate(createErrorCondition(metric, EQUALS, "10.2"), measure)).hasLevel(ERROR).hasValue(10.2d);
166 public void testEquals_Int() {
167 Metric metric = createMetric(INT);
168 Measure measure = newMeasureBuilder().create(10, null);
170 assertThat(underTest.evaluate(createErrorCondition(metric, EQUALS, "10"), measure)).hasLevel(ERROR).hasValue(10);
171 assertThat(underTest.evaluate(createErrorCondition(metric, EQUALS, "10.2"), measure)).hasLevel(ERROR).hasValue(10);
175 public void testEquals_Level() {
176 Metric metric = createMetric(LEVEL);
177 Measure measure = newMeasureBuilder().create(ERROR);
179 assertThat(underTest.evaluate(createErrorCondition(metric, EQUALS, ERROR.name()), measure)).hasLevel(ERROR).hasValue(ERROR.name());
181 assertThat(underTest.evaluate(createErrorCondition(metric, EQUALS, OK.name()), measure)).hasLevel(OK).hasValue(ERROR.name());
185 public void testNotEquals_Level() {
186 Metric metric = createMetric(LEVEL);
187 Measure measure = newMeasureBuilder().create(ERROR);
189 assertThat(underTest.evaluate(createErrorCondition(metric, NOT_EQUALS, OK.name()), measure)).hasLevel(ERROR).hasValue(ERROR.name());
193 public void testEquals_BOOL() {
194 Metric metric = createMetric(BOOL);
195 Measure measure = newMeasureBuilder().create(false, null);
197 assertThat(underTest.evaluate(createErrorCondition(metric, EQUALS, "1"), measure)).hasLevel(OK).hasValue(false);
198 assertThat(underTest.evaluate(createErrorCondition(metric, EQUALS, "0"), measure)).hasLevel(ERROR).hasValue(false);
202 public void testNotEquals_BOOL() {
203 Metric metric = createMetric(BOOL);
204 Measure measure = newMeasureBuilder().create(false, null);
206 assertThat(underTest.evaluate(createErrorCondition(metric, NOT_EQUALS, "1"), measure)).hasLevel(ERROR).hasValue(false);
207 assertThat(underTest.evaluate(createErrorCondition(metric, NOT_EQUALS, "0"), measure)).hasLevel(OK).hasValue(false);
211 public void getLevel_throws_IEA_if_error_threshold_is_not_parsable_boolean() {
212 Metric metric = createMetric(BOOL);
213 Measure measure = newMeasureBuilder().create(false, null);
215 expectedException.expect(IllegalArgumentException.class);
216 expectedException.expectMessage("Quality Gate: Unable to parse value 'polop' to compare against name");
218 underTest.evaluate(createErrorCondition(metric, EQUALS, "polop"), measure);
222 public void testEquals_work_duration() {
223 Metric metric = createMetric(WORK_DUR);
224 Measure measure = newMeasureBuilder().create(60l, null);
226 assertThat(underTest.evaluate(createErrorCondition(metric, EQUALS, "60"), measure)).hasLevel(ERROR);
230 public void getLevel_throws_IEA_if_error_threshold_is_not_parsable_long() {
231 Metric metric = createMetric(WORK_DUR);
232 Measure measure = newMeasureBuilder().create(60l, null);
234 expectedException.expect(IllegalArgumentException.class);
235 expectedException.expectMessage("Quality Gate: Unable to parse value 'polop' to compare against name");
237 underTest.evaluate(createErrorCondition(metric, EQUALS, "polop"), measure);
241 public void testErrorAndWarningLevel() {
242 Metric metric = createMetric(FLOAT);
243 Measure measure = newMeasureBuilder().create(10.2d, 1, null);
245 assertThat(underTest.evaluate(createErrorCondition(metric, EQUALS, "10.2"), measure)).hasLevel(ERROR);
246 assertThat(underTest.evaluate(createErrorCondition(metric, EQUALS, "10.1"), measure)).hasLevel(OK);
248 assertThat(underTest.evaluate(new Condition(metric, EQUALS.getDbValue(), "10.3", "10.2"), measure)).hasLevel(Measure.Level.WARN);
249 assertThat(underTest.evaluate(new Condition(metric, LESS_THAN.getDbValue(), "10.3", "10.2"), measure)).hasLevel(Measure.Level.ERROR);
253 public void condition_is_always_ok_when_measure_is_noValue() {
254 for (MetricType metricType : from(asList(values())).filter(not(in(ImmutableSet.of(DATA, LEVEL))))) {
255 Metric metric = createMetric(metricType);
256 Measure measure = newMeasureBuilder().createNoValue();
258 assertThat(underTest.evaluate(createErrorCondition(metric, EQUALS, "10.2"), measure)).hasLevel(OK);
263 public void testUnsupportedType() {
264 Metric metric = createMetric(DATA);
265 Measure measure = newMeasureBuilder().create("3.14159265358");
267 expectedException.expect(IllegalArgumentException.class);
268 expectedException.expectMessage("Conditions on MetricType DATA are not supported");
270 underTest.evaluate(createErrorCondition(metric, EQUALS, "1.60217657"), measure);
274 @UseDataProvider("numericNewMetricTypes")
275 public void test_condition_on_numeric_new_metric(MetricType metricType) {
276 Metric metric = createNewMetric(metricType);
277 Measure measure = newMeasureBuilder().setVariation(3d).createNoValue();
279 assertThat(underTest.evaluate(new Condition(metric, GREATER_THAN.getDbValue(), "3", null), measure)).hasLevel(OK);
280 assertThat(underTest.evaluate(new Condition(metric, GREATER_THAN.getDbValue(), "2", null), measure)).hasLevel(ERROR);
284 @UseDataProvider("numericNewMetricTypes")
285 public void condition_on_new_metric_without_value_is_OK(MetricType metricType) {
286 Metric metric = createNewMetric(metricType);
287 Measure measure = newMeasureBuilder().createNoValue();
289 assertThat(underTest.evaluate(new Condition(metric, GREATER_THAN.getDbValue(), "3", null), measure)).hasLevel(OK).hasValue(null);
293 public static Object[][] numericNewMetricTypes() {
294 return new Object[][] {
302 @UseDataProvider("unsupportedNewMetricTypes")
303 public void condition_on_new_metric_with_unsupported_type(MetricType metricType) {
304 Metric metric = createNewMetric(metricType);
305 Measure measure = newMeasureBuilder().setVariation(0d).createNoValue();
307 expectedException.expect(IllegalArgumentException.class);
308 expectedException.expectMessage("Unsupported metric type " + metricType);
310 underTest.evaluate(new Condition(metric, EQUALS.getDbValue(), "3", null), measure);
314 public static Object[][] unsupportedNewMetricTypes() {
315 return new Object[][] {
322 public void test_condition_on_rating() {
323 Metric metric = createMetric(RATING);
324 Measure measure = newMeasureBuilder().create(4, "D");
326 assertThat(underTest.evaluate(new Condition(metric, GREATER_THAN.getDbValue(), "4", null), measure)).hasLevel(OK).hasValue(4);
327 assertThat(underTest.evaluate(new Condition(metric, GREATER_THAN.getDbValue(), "2", null), measure)).hasLevel(ERROR).hasValue(4);
330 private static Condition createErrorCondition(Metric metric, Condition.Operator operator, String errorThreshold) {
331 return new Condition(metric, operator.getDbValue(), errorThreshold, null);
334 private static MetricImpl createMetric(MetricType metricType) {
335 return new MetricImpl(1, "key", "name", metricType);
338 private static MetricImpl createNewMetric(MetricType metricType) {
339 return new MetricImpl(1, "new_key", "name", metricType);