Skip to content

Commit 4c83d07

Browse files
marchofGodin
authored andcommitted
Report invalid coverage ratio configuration (bazel-contrib#931)
To avoid common misconfigurations where users forget to specify percent sign.
1 parent b71209a commit 4c83d07

File tree

7 files changed

+125
-29
lines changed

7 files changed

+125
-29
lines changed

jacoco-maven-plugin/src/org/jacoco/maven/CheckMojo.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,10 @@ public class CheckMojo extends AbstractJacocoMojo implements IViolationsOutput {
4848
* applies to a certain counter (INSTRUCTION, LINE, BRANCH, COMPLEXITY,
4949
* METHOD, CLASS) and defines a minimum or maximum for the corresponding
5050
* value (TOTALCOUNT, COVEREDCOUNT, MISSEDCOUNT, COVEREDRATIO, MISSEDRATIO).
51-
* If a limit refers to a ratio the range is from 0.0 to 1.0 where the
52-
* number of decimal places will also determine the precision in error
53-
* messages. A limit ratio may optionally be declared as a percentage
54-
* where 0.80 and 80% represent the same value, the value must end with %.
51+
* If a limit refers to a ratio it must be in the range from 0.0 to 1.0
52+
* where the number of decimal places will also determine the precision in
53+
* error messages. A limit ratio may optionally be declared as a percentage
54+
* where 0.80 and 80% represent the same value.
5555
* </p>
5656
*
5757
* <p>
@@ -150,8 +150,8 @@ private boolean canCheckCoverage() {
150150
getLog().info(MSG_SKIPPING + dataFile);
151151
return false;
152152
}
153-
final File classesDirectory = new File(getProject().getBuild()
154-
.getOutputDirectory());
153+
final File classesDirectory = new File(
154+
getProject().getBuild().getOutputDirectory());
155155
if (!classesDirectory.exists()) {
156156
getLog().info(
157157
"Skipping JaCoCo execution due to missing classes directory:"

org.jacoco.ant.test/src/org/jacoco/ant/ReportTaskTest.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,24 @@
464464
<au:assertLogContains level="error" text="instructions covered ratio is 0.00, but expected minimum is 0.90"/>
465465
</target>
466466

467+
<target name="testReportInvalidConfiguration">
468+
<au:expectfailure expectedMessage="Coverage check failed due to violated rules.">
469+
<jacoco:report>
470+
<structure name="Test">
471+
<classfiles>
472+
<fileset dir="${org.jacoco.ant.reportTaskTest.classes.dir}" includes="**/*.class"/>
473+
</classfiles>
474+
</structure>
475+
<check>
476+
<rule element="BUNDLE">
477+
<limit counter="INSTRUCTION" value="COVEREDRATIO" minimum="80"/>
478+
</rule>
479+
</check>
480+
</jacoco:report>
481+
</au:expectfailure>
482+
<au:assertLogContains level="error" text="given minimum ratio is 80, but must be between 0.0 and 1.0"/>
483+
</target>
484+
467485
<target name="testReportCheckSetPropertyOnly">
468486
<jacoco:report>
469487
<structure name="Test">

org.jacoco.doc/docroot/doc/ant.html

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -857,11 +857,11 @@ <h3>Element <code>check</code></h3>
857857
</tr>
858858
<tr>
859859
<td><code>minimum</code></td>
860-
<td>Expected minimum value. If the minimum refers to a ratio the range is
861-
from 0.0 to 1.0 where the number of decimal places will also determine
862-
the precision in error messages. A limit ratio may optionally be
863-
declared as a percentage where 0.80 and 80% represent the same value,
864-
the value must end with %.</td>
860+
<td>Expected minimum value. If the minimum refers to a ratio it must be
861+
in the range from 0.0 to 1.0 where the number of decimal places will
862+
also determine the precision in error messages. A limit ratio may
863+
optionally be declared as a percentage where 0.80 and 80% represent
864+
the same value.</td>
865865
<td><i>none</i></td>
866866
</tr>
867867
<tr>

org.jacoco.doc/docroot/doc/changes.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,14 @@ <h3>Non-functional Changes</h3>
6262
(GitHub <a href="https://github.com/jacoco/jacoco/issues/910">#910</a>).</li>
6363
</ul>
6464

65+
<h3>API Changes</h3>
66+
<ul>
67+
<li>The coverage check API and tools (Ant, Maven) now report an error, when
68+
a coverage ratio limit is configured outside the range [0,1] to avoid
69+
common configuration mistakes
70+
(GitHub <a href="https://github.com/jacoco/jacoco/issues/783">#783</a>).</li>
71+
</ul>
72+
6573
<h2>Release 0.8.4 (2019/05/08)</h2>
6674

6775
<h3>New Features</h3>

org.jacoco.report.test/src/org/jacoco/report/check/LimitTest.java

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,27 +79,27 @@ public void check_should_fail_on_value_coveredcount() {
7979
@Test
8080
public void check_should_fail_on_value_missedratio() {
8181
limit.setValue(CounterValue.MISSEDRATIO.name());
82-
limit.setMaximum("-1");
82+
limit.setMaximum("0.5");
8383
assertEquals(CounterValue.MISSEDRATIO, limit.getValue());
8484
assertEquals(
85-
"instructions missed ratio is 0, but expected maximum is -1",
85+
"instructions missed ratio is 1.0, but expected maximum is 0.5",
8686
limit.check(new TestNode() {
8787
{
88-
instructionCounter = CounterImpl.COUNTER_0_1;
88+
instructionCounter = CounterImpl.COUNTER_1_0;
8989
}
9090
}));
9191
}
9292

9393
@Test
9494
public void check_should_fail_on_value_coveredratio() {
9595
limit.setValue(CounterValue.COVEREDRATIO.name());
96-
limit.setMaximum("-1");
96+
limit.setMaximum("0.5");
9797
assertEquals(CounterValue.COVEREDRATIO, limit.getValue());
9898
assertEquals(
99-
"instructions covered ratio is 0, but expected maximum is -1",
99+
"instructions covered ratio is 1.0, but expected maximum is 0.5",
100100
limit.check(new TestNode() {
101101
{
102-
instructionCounter = CounterImpl.COUNTER_1_0;
102+
instructionCounter = CounterImpl.COUNTER_0_1;
103103
}
104104
}));
105105
}
@@ -242,6 +242,24 @@ public void check_should_report_counter_with_given_precision() {
242242
}));
243243
}
244244

245+
@Test
246+
public void check_should_fail_when_minimum_ratio_is_smaller_than_0() {
247+
limit.setMinimum("-3");
248+
assertEquals("-3", limit.getMinimum());
249+
assertEquals(
250+
"given minimum ratio is -3, but must be between 0.0 and 1.0",
251+
limit.check(new TestNode()));
252+
}
253+
254+
@Test
255+
public void check_should_fail_when_minimum_ratio_is_bigger_than_1() {
256+
limit.setMinimum("80");
257+
assertEquals("80", limit.getMinimum());
258+
assertEquals(
259+
"given minimum ratio is 80, but must be between 0.0 and 1.0",
260+
limit.check(new TestNode()));
261+
}
262+
245263
@Test
246264
public void setMinimum_should_accept_percentage_string() {
247265
limit.setMinimum("1.55%");
@@ -314,6 +332,24 @@ public void check_should_report_actual_ratio_rounded_up_when_maximum_is_not_met(
314332
}));
315333
}
316334

335+
@Test
336+
public void check_should_fail_when_maximum_ratio_is_smaller_than_0() {
337+
limit.setMaximum("-3");
338+
assertEquals("-3", limit.getMaximum());
339+
assertEquals(
340+
"given maximum ratio is -3, but must be between 0.0 and 1.0",
341+
limit.check(new TestNode()));
342+
}
343+
344+
@Test
345+
public void check_should_fail_when_maximum_ratio_is_bigger_than_1() {
346+
limit.setMaximum("80");
347+
assertEquals("80", limit.getMaximum());
348+
assertEquals(
349+
"given maximum ratio is 80, but must be between 0.0 and 1.0",
350+
limit.check(new TestNode()));
351+
}
352+
317353
@Test
318354
public void setMaximum_should_accept_percentage_string() {
319355
limit.setMaximum("1.55%");

org.jacoco.report/src/org/jacoco/report/check/BundleChecker.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,11 @@ private void checkRules(final ICoverageNode node,
139139
}
140140

141141
private void checkLimit(final ICoverageNode node, final String elementtype,
142-
final String typename, final Rule rule, final Limit limit) {
142+
final String elementname, final Rule rule, final Limit limit) {
143143
final String message = limit.check(node);
144144
if (message != null) {
145145
output.onViolation(node, rule, limit, String.format(
146-
"Rule violated for %s %s: %s", elementtype, typename,
146+
"Rule violated for %s %s: %s", elementtype, elementname,
147147
message));
148148
}
149149
}

org.jacoco.report/src/org/jacoco/report/check/Limit.java

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,8 @@ public CounterEntity getEntity() {
8383
*
8484
* @param entity
8585
* counter entity to check
86-
* TODO: use CounterEntity directly once Maven 3 is required.
8786
*/
87+
// TODO: use CounterEntity directly once Maven 3 is required.
8888
public void setCounter(final String entity) {
8989
this.entity = CounterEntity.valueOf(entity);
9090
}
@@ -101,8 +101,8 @@ public CounterValue getValue() {
101101
*
102102
* @param value
103103
* value to check
104-
* TODO: use CounterValue directly once Maven 3 is required.
105104
*/
105+
// TODO: use CounterValue directly once Maven 3 is required.
106106
public void setValue(final String value) {
107107
this.value = CounterValue.valueOf(value);
108108
}
@@ -116,9 +116,11 @@ public String getMinimum() {
116116
}
117117

118118
/**
119-
* Sets allowed maximum value as decimal string or percent representation.
120-
* The given precision is also considered in error messages. Coverage ratios
121-
* are given in the range from 0.0 to 1.0.
119+
* Sets the expected minimum value. If the minimum refers to a ratio it must
120+
* be in the range from 0.0 to 1.0 where the number of decimal places will
121+
* also determine the precision in error messages. A limit ratio may
122+
* optionally be declared as a percentage where 0.80 and 80% represent the
123+
* same value.
122124
*
123125
* @param minimum
124126
* allowed minimum or <code>null</code>, if no minimum should be
@@ -137,9 +139,11 @@ public String getMaximum() {
137139
}
138140

139141
/**
140-
* Sets allowed maximum value as decimal string or percent representation.
141-
* The given precision is also considered in error messages. Coverage ratios
142-
* are given in the range from 0.0 to 1.0.
142+
* Sets the expected maximum value. If the maximum refers to a ratio it must
143+
* be in the range from 0.0 to 1.0 where the number of decimal places will
144+
* also determine the precision in error messages. A limit ratio may
145+
* optionally be declared as a percentage where 0.80 and 80% represent the
146+
* same value.
143147
*
144148
* @param maximum
145149
* allowed maximum or <code>null</code>, if no maximum should be
@@ -153,17 +157,22 @@ private static BigDecimal parseValue(final String value) {
153157
if (value == null) {
154158
return null;
155159
}
156-
160+
157161
final String trimmedValue = value.trim();
158162
if (trimmedValue.endsWith("%")) {
159-
final String percent = trimmedValue.substring(0, trimmedValue.length() - 1);
163+
final String percent = trimmedValue.substring(0,
164+
trimmedValue.length() - 1);
160165
return new BigDecimal(percent).movePointLeft(2);
161166
}
162167

163168
return new BigDecimal(trimmedValue);
164169
}
165170

166171
String check(final ICoverageNode node) {
172+
final String msg = checkRatioLimit();
173+
if (msg != null) {
174+
return msg;
175+
}
167176
final double d = node.getCounter(entity).getValue(value);
168177
if (Double.isNaN(d)) {
169178
return null;
@@ -186,4 +195,29 @@ private String message(final String minmax, final BigDecimal v,
186195
rounded.toPlainString(), minmax, ref.toPlainString());
187196
}
188197

198+
private String checkRatioLimit() {
199+
if (CounterValue.MISSEDRATIO.equals(value)
200+
|| CounterValue.COVEREDRATIO.equals(value)) {
201+
final String minmsg = checkRatioLimit("minimum", minimum);
202+
if (minmsg != null) {
203+
return minmsg;
204+
}
205+
final String maxmsg = checkRatioLimit("maximum", maximum);
206+
if (maxmsg != null) {
207+
return maxmsg;
208+
}
209+
}
210+
return null;
211+
}
212+
213+
private String checkRatioLimit(final String minmax, final BigDecimal v) {
214+
if (v != null && (v.compareTo(BigDecimal.ZERO) < 0
215+
|| v.compareTo(BigDecimal.ONE) > 0)) {
216+
return String.format(
217+
"given %s ratio is %s, but must be between 0.0 and 1.0",
218+
minmax, v);
219+
}
220+
return null;
221+
}
222+
189223
}

0 commit comments

Comments
 (0)