From 313367a36e78dd1269c93adce81e969036ec82a2 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Thu, 1 Dec 2016 18:15:48 -0700 Subject: [PATCH 01/42] Basic support for enforcing Jacoco metrics --- .../JacocoCachingIntegrationTest.groovy | 18 +- ...oPluginCheckCoverageIntegrationTest.groovy | 212 ++++++++++++++++++ .../JacocoPluginIntegrationTest.groovy | 22 +- ...cocoReportRelocationIntegrationTest.groovy | 19 +- ...JacocoTestRelocationIntegrationTest.groovy | 21 +- .../plugins/JacocoVersionIntegTest.groovy | 32 +-- .../fixtures/JavaProjectUnderTest.groovy | 71 ++++++ .../internal/jacoco/AntJacocoReport.java | 59 ++++- .../jacoco/rules/JacocoThresholdImpl.java | 69 ++++++ .../rules/JacocoValidationRuleImpl.java | 83 +++++++ .../JacocoValidationRulesContainerImpl.java | 60 +++++ .../testing/jacoco/tasks/JacocoReport.java | 35 ++- .../jacoco/tasks/rules/JacocoRuleScope.java | 29 +++ .../jacoco/tasks/rules/JacocoThreshold.java | 56 +++++ .../tasks/rules/JacocoThresholdMetric.java | 29 +++ .../tasks/rules/JacocoThresholdValue.java | 29 +++ .../tasks/rules/JacocoValidationRule.java | 66 ++++++ .../rules/JacocoValidationRulesContainer.java | 54 +++++ .../jacoco/tasks/rules/package-info.java | 21 ++ 19 files changed, 896 insertions(+), 89 deletions(-) create mode 100644 subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy create mode 100644 subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/fixtures/JavaProjectUnderTest.groovy create mode 100644 subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoThresholdImpl.java create mode 100644 subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRuleImpl.java create mode 100644 subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRulesContainerImpl.java create mode 100644 subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoRuleScope.java create mode 100644 subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThreshold.java create mode 100644 subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdMetric.java create mode 100644 subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdValue.java create mode 100644 subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoValidationRule.java create mode 100644 subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoValidationRulesContainer.java create mode 100644 subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/package-info.java diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoCachingIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoCachingIntegrationTest.groovy index 3ec917fc84ac..d1c4044aecc6 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoCachingIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoCachingIntegrationTest.groovy @@ -18,6 +18,7 @@ package org.gradle.testing.jacoco.plugins import org.gradle.integtests.fixtures.AbstractIntegrationSpec import org.gradle.integtests.fixtures.LocalBuildCacheFixture +import org.gradle.testing.jacoco.plugins.fixtures.JavaProjectUnderTest import org.gradle.util.Requires import static org.gradle.util.TestPrecondition.FIX_TO_WORK_ON_JAVA9 @@ -25,24 +26,13 @@ import static org.gradle.util.TestPrecondition.FIX_TO_WORK_ON_JAVA9 @Requires(FIX_TO_WORK_ON_JAVA9) class JacocoCachingIntegrationTest extends AbstractIntegrationSpec implements LocalBuildCacheFixture { + private final JavaProjectUnderTest javaProjectUnderTest = new JavaProjectUnderTest(testDirectory) + def "jacoco file results are cached"() { - file("src/main/java/org/gradle/Class1.java") << - "package org.gradle; public class Class1 { public boolean isFoo(Object arg) { return true; } }" - file("src/test/java/org/gradle/Class1Test.java") << - "package org.gradle; import org.junit.Test; public class Class1Test { @Test public void someTest() { new Class1().isFoo(\"test\"); } }" + javaProjectUnderTest.writeBuildScript().writeSourceFiles() def reportFile = file("build/reports/jacoco/test/html/index.html") buildFile << """ - apply plugin: "java" - apply plugin: "jacoco" - - repositories { - mavenCentral() - } - dependencies { - testCompile 'junit:junit:4.12' - } - jacocoTestReport.dependsOn test sourceSets.test.output.classesDir = file("build/classes/test") diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy new file mode 100644 index 000000000000..55fa43408a17 --- /dev/null +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy @@ -0,0 +1,212 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.testing.jacoco.plugins + +import org.gradle.integtests.fixtures.AbstractIntegrationSpec +import org.gradle.testing.jacoco.plugins.fixtures.JavaProjectUnderTest +import spock.lang.Unroll + +class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { + + private final JavaProjectUnderTest javaProjectUnderTest = new JavaProjectUnderTest(testDirectory) + + def setup() { + javaProjectUnderTest.writeBuildScript().writeSourceFiles() + } + + def "no rules provided"() { + buildFile << """ + jacocoTestReport { + validationRules {} + } + """ + + when: + succeeds 'test', 'jacocoTestReport' + + then: + executedAndNotSkipped(':test', ':jacocoTestReport') + } + + def "single rule without thresholds"() { + buildFile << """ + jacocoTestReport { + validationRules { + rule {} + } + } + """ + + when: + succeeds 'test', 'jacocoTestReport' + + then: + executedAndNotSkipped(':test', ':jacocoTestReport') + } + + def "can define includes for single rule"() { + buildFile << """ + jacocoTestReport { + validationRules { + rule { + scope = org.gradle.testing.jacoco.tasks.rules.JacocoRuleScope.CLASS + includes = ['org.gradle.*'] + $Thresholds.Insufficient.LINE_METRIC_COVERED_RATIO + } + } + } + """ + + when: + fails 'test', 'jacocoTestReport' + + then: + executedAndNotSkipped(':test', ':jacocoTestReport') + errorOutput.contains("Rule violated for class org.gradle.Class1: lines covered ratio is 1.0, but expected maximum is 0.5") + } + + def "can define excludes for single rule"() { + buildFile << """ + jacocoTestReport { + validationRules { + rule { + excludes = ['*'] + $Thresholds.Insufficient.LINE_METRIC_COVERED_RATIO + } + } + } + """ + + when: + succeeds 'test', 'jacocoTestReport' + + then: + executedAndNotSkipped(':test', ':jacocoTestReport') + } + + @Unroll + def "rule with sufficient coverage for #description"() { + given: + buildFile << """ + jacocoTestReport { + validationRules { + rule { + ${thresholds.join('\n')} + } + } + } + """ + + when: + succeeds 'test', 'jacocoTestReport' + + then: + executedAndNotSkipped(':test', ':jacocoTestReport') + + where: + thresholds | description + [Thresholds.Sufficient.LINE_METRIC_COVERED_RATIO] | 'line metric with covered ratio' + [Thresholds.Sufficient.CLASS_METRIC_MISSED_COUNT] | 'class metric with missed count' + [Thresholds.Sufficient.LINE_METRIC_COVERED_RATIO, + Thresholds.Sufficient.CLASS_METRIC_MISSED_COUNT] | 'line and class metric' + + } + + @Unroll + def "rule with insufficient coverage for #description"() { + buildFile << """ + jacocoTestReport { + validationRules { + rule { + ${thresholds.join('\n')} + } + } + } + """ + + when: + fails 'test', 'jacocoTestReport' + + then: + executedAndNotSkipped(':test', ':jacocoTestReport') + errorOutput.contains("Rule violated for bundle $testDirectory.name: $errorMessage") + + where: + thresholds | description | errorMessage + [Thresholds.Insufficient.LINE_METRIC_COVERED_RATIO] | 'line metric with covered ratio' | 'lines covered ratio is 1.0, but expected maximum is 0.5' + [Thresholds.Insufficient.CLASS_METRIC_MISSED_COUNT] | 'class metric with missed count' | 'classes missed count is 0.0, but expected minimum is 0.5' + [Thresholds.Insufficient.LINE_METRIC_COVERED_RATIO, + Thresholds.Insufficient.CLASS_METRIC_MISSED_COUNT] | 'first of multiple insufficient thresholds fails' | 'lines covered ratio is 1.0, but expected maximum is 0.5' + [Thresholds.Sufficient.LINE_METRIC_COVERED_RATIO, + Thresholds.Insufficient.CLASS_METRIC_MISSED_COUNT, + Thresholds.Sufficient.CLASS_METRIC_MISSED_COUNT] | 'first insufficient threshold fails' | 'classes missed count is 0.0, but expected minimum is 0.5' + } + + def "can ignore failures"() { + buildFile << """ + jacocoTestReport { + validationRules { + ignoreFailures = true + + rule { + $Thresholds.Insufficient.LINE_METRIC_COVERED_RATIO + } + } + } + """ + + when: + succeeds 'test', 'jacocoTestReport' + + then: + executedAndNotSkipped(':test', ':jacocoTestReport') + errorOutput.contains("Rule violated for bundle $testDirectory.name: lines covered ratio is 1.0, but expected maximum is 0.5") + } + + static class Thresholds { + static class Sufficient { + static final String LINE_METRIC_COVERED_RATIO = Thresholds.threshold('org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric.LINE', 'org.gradle.testing.jacoco.tasks.rules.JacocoThresholdValue.COVEREDRATIO', '0.0', '1.0') + static final String CLASS_METRIC_MISSED_COUNT = Thresholds.threshold('org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric.CLASS', 'org.gradle.testing.jacoco.tasks.rules.JacocoThresholdValue.MISSEDCOUNT', null, '0') + } + + static class Insufficient { + static final String LINE_METRIC_COVERED_RATIO = Thresholds.threshold('org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric.LINE', 'org.gradle.testing.jacoco.tasks.rules.JacocoThresholdValue.COVEREDRATIO', '0.0', '0.5') + static final String CLASS_METRIC_MISSED_COUNT = Thresholds.threshold('org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric.CLASS', 'org.gradle.testing.jacoco.tasks.rules.JacocoThresholdValue.MISSEDCOUNT', '0.5', null) + } + + static String threshold(String metric, String value, String minimum, String maximum) { + StringBuilder threshold = new StringBuilder() + threshold <<= 'threshold {\n' + + if (metric) { + threshold <<= " metric = $metric\n" + } + if (value) { + threshold <<= " value = $value\n" + } + if (minimum) { + threshold <<= " minimum = $minimum\n" + } + if (maximum) { + threshold <<= " maximum = $maximum\n" + } + + threshold <<= '}' + threshold.toString() + } + } +} diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginIntegrationTest.groovy index 6d20df7c9a29..fd3161090e4d 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginIntegrationTest.groovy @@ -20,6 +20,7 @@ import org.gradle.api.Project import org.gradle.api.reporting.ReportingExtension import org.gradle.integtests.fixtures.AbstractIntegrationSpec import org.gradle.integtests.fixtures.executer.GradleContextualExecuter +import org.gradle.testing.jacoco.plugins.fixtures.JavaProjectUnderTest import org.gradle.util.Requires import spock.lang.IgnoreIf import spock.lang.Issue @@ -28,24 +29,14 @@ import static org.gradle.util.TestPrecondition.FIX_TO_WORK_ON_JAVA9 class JacocoPluginIntegrationTest extends AbstractIntegrationSpec { + private final JavaProjectUnderTest javaProjectUnderTest = new JavaProjectUnderTest(testDirectory) private static final String REPORTING_BASE = "${Project.DEFAULT_BUILD_DIR_NAME}/${ReportingExtension.DEFAULT_REPORTS_DIR_NAME}" private static final String REPORT_HTML_DEFAULT_PATH = "${REPORTING_BASE}/jacoco/test/html/index.html" private static final String REPORT_XML_DEFAULT_PATH = "${REPORTING_BASE}/jacoco/test/jacocoTestReport.xml" private static final String REPORT_CSV_DEFAULT_REPORT = "${REPORTING_BASE}/jacoco/test/jacocoTestReport.csv" def setup() { - buildFile << """ - apply plugin: "java" - apply plugin: "jacoco" - - repositories { - mavenCentral() - } - dependencies { - testCompile 'junit:junit:4.12' - } - """ - createTestFiles() + javaProjectUnderTest.writeBuildScript().writeSourceFiles() } def "jacoco plugin adds coverage report for test task when java plugin applied"() { @@ -320,12 +311,5 @@ public class ThingTest { private JacocoReportFixture htmlReport(String basedir = "${REPORTING_BASE}/jacoco/test/html") { return new JacocoReportFixture(file(basedir)) } - - private void createTestFiles() { - file("src/main/java/org/gradle/Class1.java") << - "package org.gradle; public class Class1 { public boolean isFoo(Object arg) { return true; } }" - file("src/test/java/org/gradle/Class1Test.java") << - "package org.gradle; import org.junit.Test; public class Class1Test { @Test public void someTest() { new Class1().isFoo(\"test\"); } }" - } } diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoReportRelocationIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoReportRelocationIntegrationTest.groovy index 60a84f645640..061c5ab1438a 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoReportRelocationIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoReportRelocationIntegrationTest.groovy @@ -17,12 +17,16 @@ package org.gradle.testing.jacoco.plugins import org.gradle.integtests.fixtures.AbstractTaskRelocationIntegrationTest +import org.gradle.testing.jacoco.plugins.fixtures.JavaProjectUnderTest import org.gradle.util.Requires import static org.gradle.util.TestPrecondition.FIX_TO_WORK_ON_JAVA9 @Requires(FIX_TO_WORK_ON_JAVA9) class JacocoReportRelocationIntegrationTest extends AbstractTaskRelocationIntegrationTest { + + private final JavaProjectUnderTest javaProjectUnderTest = new JavaProjectUnderTest(testDirectory) + @Override protected String getTaskName() { return ":jacocoTestReport" @@ -30,22 +34,9 @@ class JacocoReportRelocationIntegrationTest extends AbstractTaskRelocationIntegr @Override protected void setupProjectInOriginalLocation() { - file("src/main/java/org/gradle/Class1.java") << - "package org.gradle; public class Class1 { public boolean isFoo(Object arg) { return true; } }" - file("src/test/java/org/gradle/Class1Test.java") << - "package org.gradle; import org.junit.Test; public class Class1Test { @Test public void someTest() { new Class1().isFoo(\"test\"); } }" + javaProjectUnderTest.writeBuildScript().writeSourceFiles() buildFile << """ - apply plugin: "java" - apply plugin: "jacoco" - - repositories { - mavenCentral() - } - dependencies { - testCompile 'junit:junit:4.12' - } - sourceSets.test.output.classesDir = file("build/classes/test") """ diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoTestRelocationIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoTestRelocationIntegrationTest.groovy index 0962fb7a2347..545e76da1291 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoTestRelocationIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoTestRelocationIntegrationTest.groovy @@ -17,6 +17,7 @@ package org.gradle.testing.jacoco.plugins import org.gradle.integtests.fixtures.AbstractTaskRelocationIntegrationTest +import org.gradle.testing.jacoco.plugins.fixtures.JavaProjectUnderTest import org.gradle.util.Requires import static org.gradle.util.BinaryDiffUtils.levenshteinDistance @@ -25,6 +26,9 @@ import static org.gradle.util.TestPrecondition.FIX_TO_WORK_ON_JAVA9 @Requires(FIX_TO_WORK_ON_JAVA9) class JacocoTestRelocationIntegrationTest extends AbstractTaskRelocationIntegrationTest { + + private final JavaProjectUnderTest javaProjectUnderTest = new JavaProjectUnderTest(testDirectory) + @Override protected String getTaskName() { return ":test" @@ -32,22 +36,7 @@ class JacocoTestRelocationIntegrationTest extends AbstractTaskRelocationIntegrat @Override protected void setupProjectInOriginalLocation() { - file("src/main/java/org/gradle/Class1.java") << - "package org.gradle; public class Class1 { public boolean isFoo(Object arg) { return true; } }" - file("src/test/java/org/gradle/Class1Test.java") << - "package org.gradle; import org.junit.Test; public class Class1Test { @Test public void someTest() { new Class1().isFoo(\"test\"); } }" - - buildFile << """ - apply plugin: "java" - apply plugin: "jacoco" - - repositories { - mavenCentral() - } - dependencies { - testCompile 'junit:junit:4.12' - } - """ + javaProjectUnderTest.writeBuildScript().writeSourceFiles() } @Override diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoVersionIntegTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoVersionIntegTest.groovy index aea9bbab79fd..e4ef17b047da 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoVersionIntegTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoVersionIntegTest.groovy @@ -17,33 +17,24 @@ package org.gradle.testing.jacoco.plugins import org.gradle.integtests.fixtures.MultiVersionIntegrationSpec import org.gradle.integtests.fixtures.TargetVersions +import org.gradle.testing.jacoco.plugins.fixtures.JavaProjectUnderTest import org.gradle.util.Requires import org.gradle.util.TestPrecondition -import org.junit.Test @Requires(TestPrecondition.JDK7_OR_EARLIER) @TargetVersions(['0.6.0.201210061924', '0.6.2.201302030002', '0.7.1.201405082137', '0.7.6.201602180812']) class JacocoVersionIntegTest extends MultiVersionIntegrationSpec { - @Test - public void canRunVersions() { + private final JavaProjectUnderTest javaProjectUnderTest = new JavaProjectUnderTest(testDirectory) + + def "can run versions"() { given: + javaProjectUnderTest.writeBuildScript().writeSourceFiles() buildFile << """ - apply plugin: "java" - apply plugin: "jacoco" - - repositories { - mavenCentral() - } - - dependencies { - testCompile 'junit:junit:4.12' - } - jacoco { - toolVersion = '$version' - } + jacoco { + toolVersion = '$version' + } """ - createTestFiles(); when: succeeds('test', 'jacocoTestReport') @@ -57,11 +48,4 @@ class JacocoVersionIntegTest extends MultiVersionIntegrationSpec { private JacocoReportFixture htmlReport(String basedir = "build/reports/jacoco/test/html") { return new JacocoReportFixture(file(basedir)) } - - private void createTestFiles() { - file("src/main/java/org/gradle/Class1.java") << - "package org.gradle; public class Class1 { public boolean isFoo(Object arg) { return true; } }" - file("src/test/java/org/gradle/Class1Test.java") << - "package org.gradle; import org.junit.Test; public class Class1Test { @Test public void someTest() { new Class1().isFoo(\"test\"); } }" - } } diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/fixtures/JavaProjectUnderTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/fixtures/JavaProjectUnderTest.groovy new file mode 100644 index 000000000000..fee016518418 --- /dev/null +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/fixtures/JavaProjectUnderTest.groovy @@ -0,0 +1,71 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.testing.jacoco.plugins.fixtures + +import org.gradle.test.fixtures.file.TestFile + +class JavaProjectUnderTest { + private final TestFile projectDir + + JavaProjectUnderTest(TestFile projectDir) { + this.projectDir = projectDir + } + + JavaProjectUnderTest writeBuildScript() { + projectDir.file('build.gradle') << """ + apply plugin: 'java' + apply plugin: 'jacoco' + + repositories { + mavenCentral() + } + + dependencies { + testCompile 'junit:junit:4.12' + } + """ + + this + } + + JavaProjectUnderTest writeSourceFiles() { + projectDir.file('src/main/java/org/gradle/Class1.java') << """ + package org.gradle; + + public class Class1 { + public boolean isFoo(Object arg) { + return true; + } + } + """ + + projectDir.file('src/test/java/org/gradle/Class1Test.java') << """ + package org.gradle; + + import org.junit.Test; + + public class Class1Test { + @Test + public void someTest() { + new Class1().isFoo("test"); + } + } + """ + + this + } +} diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java index 5c9d53ec4672..5f8bdee4927f 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java @@ -16,14 +16,19 @@ package org.gradle.internal.jacoco; +import com.google.common.base.Joiner; import com.google.common.collect.ImmutableMap; import groovy.lang.Closure; import groovy.lang.GroovyObjectSupport; import org.gradle.api.file.FileCollection; import org.gradle.api.internal.project.IsolatedAntBuilder; import org.gradle.testing.jacoco.tasks.JacocoReportsContainer; +import org.gradle.testing.jacoco.tasks.rules.JacocoThreshold; +import org.gradle.testing.jacoco.tasks.rules.JacocoValidationRule; +import org.gradle.testing.jacoco.tasks.rules.JacocoValidationRulesContainer; import java.util.Collections; +import java.util.HashMap; import java.util.Map; public class AntJacocoReport { @@ -37,7 +42,8 @@ public AntJacocoReport(IsolatedAntBuilder ant) { public void execute(FileCollection classpath, final String projectName, final FileCollection allClassesDirs, final FileCollection allSourcesDirs, final FileCollection executionData, - final JacocoReportsContainer reports) { + final JacocoReportsContainer reports, + final JacocoValidationRulesContainer validationRules) { ant.withClasspath(classpath).execute(new Closure(this, this) { @SuppressWarnings("UnusedDeclaration") public Object doCall(Object it) { @@ -88,6 +94,7 @@ public Object doCall(Object ignore) { ImmutableMap.of("destfile", reports.getCsv().getDestination()) }); } + configureCheck(antBuilder, validationRules); return null; } }}); @@ -95,4 +102,54 @@ public Object doCall(Object ignore) { } }); } + + private void configureCheck(final GroovyObjectSupport antBuilder, final JacocoValidationRulesContainer validationRules) { + if (!validationRules.getRules().isEmpty()) { + Map checkArgs = ImmutableMap.of("failonviolation", !validationRules.isIgnoreFailures()); + antBuilder.invokeMethod("check", new Object[] {checkArgs, new Closure(this, this) { + @SuppressWarnings("UnusedDeclaration") + public Object doCall(Object ignore) { + for (final JacocoValidationRule rule : validationRules.getRules()) { + Map ruleArgs = new HashMap(); + + if (rule.getScope() != null) { + ruleArgs.put("element", rule.getScope()); + } + if (rule.getIncludes() != null && !rule.getIncludes().isEmpty()) { + ruleArgs.put("includes", Joiner.on(':').join(rule.getIncludes())); + } + if (rule.getExcludes() != null && !rule.getExcludes().isEmpty()) { + ruleArgs.put("excludes", Joiner.on(':').join(rule.getExcludes())); + } + + antBuilder.invokeMethod("rule", new Object[] {ImmutableMap.copyOf(ruleArgs), new Closure(this, this) { + @SuppressWarnings("UnusedDeclaration") + public Object doCall(Object ignore) { + for (JacocoThreshold threshold : rule.getThresholds()) { + Map ruleArgs = new HashMap(); + + if (threshold.getMetric() != null) { + ruleArgs.put("counter", threshold.getMetric().name()); + } + if (threshold.getValue() != null) { + ruleArgs.put("value", threshold.getValue().name()); + } + if (threshold.getMinimum() != null) { + ruleArgs.put("minimum", threshold.getMinimum()); + } + if (threshold.getMaximum() != null) { + ruleArgs.put("maximum", threshold.getMaximum()); + } + + antBuilder.invokeMethod("limit", new Object[] {ImmutableMap.copyOf(ruleArgs) }); + } + return null; + } + }}); + } + return null; + } + }}); + } + } } diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoThresholdImpl.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoThresholdImpl.java new file mode 100644 index 000000000000..cc2d6751a03e --- /dev/null +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoThresholdImpl.java @@ -0,0 +1,69 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.jacoco.rules; + +import org.gradle.testing.jacoco.tasks.rules.JacocoThreshold; +import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric; +import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdValue; + +public class JacocoThresholdImpl implements JacocoThreshold { + + private JacocoThresholdMetric metric; + private JacocoThresholdValue value; + private Double minimum; + private Double maximum; + + @Override + public JacocoThresholdMetric getMetric() { + return metric; + } + + @Override + public void setMetric(JacocoThresholdMetric metric) { + this.metric = metric; + } + + @Override + public JacocoThresholdValue getValue() { + return value; + } + + @Override + public void setValue(JacocoThresholdValue value) { + this.value = value; + } + + @Override + public Double getMinimum() { + return minimum; + } + + @Override + public void setMinimum(Double minimum) { + this.minimum = minimum; + } + + @Override + public Double getMaximum() { + return maximum; + } + + @Override + public void setMaximum(Double maximum) { + this.maximum = maximum; + } +} diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRuleImpl.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRuleImpl.java new file mode 100644 index 000000000000..963dc39c61cb --- /dev/null +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRuleImpl.java @@ -0,0 +1,83 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.jacoco.rules; + +import groovy.lang.Closure; +import org.gradle.api.Action; +import org.gradle.api.internal.ClosureBackedAction; +import org.gradle.testing.jacoco.tasks.rules.JacocoRuleScope; +import org.gradle.testing.jacoco.tasks.rules.JacocoThreshold; +import org.gradle.testing.jacoco.tasks.rules.JacocoValidationRule; + +import java.util.ArrayList; +import java.util.List; + +public class JacocoValidationRuleImpl implements JacocoValidationRule { + + private JacocoRuleScope scope; + private List includes = new ArrayList(); + private List excludes = new ArrayList(); + private final List thresholds = new ArrayList(); + + @Override + public void setScope(JacocoRuleScope scope) { + this.scope = scope; + } + + @Override + public JacocoRuleScope getScope() { + return scope; + } + + @Override + public void setIncludes(List includes) { + this.includes = includes; + } + + @Override + public List getIncludes() { + return includes; + } + + @Override + public void setExcludes(List excludes) { + this.excludes = excludes; + } + + @Override + public List getExcludes() { + return excludes; + } + + @Override + public List getThresholds() { + return thresholds; + } + + @Override + public JacocoThreshold threshold(Closure configureClosure) { + return threshold(ClosureBackedAction.of(configureClosure)); + } + + @Override + public JacocoThreshold threshold(Action configureAction) { + JacocoThreshold threshold = new JacocoThresholdImpl(); + configureAction.execute(threshold); + thresholds.add(threshold); + return threshold; + } +} diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRulesContainerImpl.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRulesContainerImpl.java new file mode 100644 index 000000000000..2a601f81258b --- /dev/null +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRulesContainerImpl.java @@ -0,0 +1,60 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.jacoco.rules; + +import groovy.lang.Closure; +import org.gradle.api.Action; +import org.gradle.api.internal.ClosureBackedAction; +import org.gradle.testing.jacoco.tasks.rules.JacocoValidationRule; +import org.gradle.testing.jacoco.tasks.rules.JacocoValidationRulesContainer; + +import java.util.ArrayList; +import java.util.List; + +public class JacocoValidationRulesContainerImpl implements JacocoValidationRulesContainer { + + private boolean ignoreFailures; + private final List rules = new ArrayList(); + + @Override + public void setIgnoreFailures(boolean ignoreFailures) { + this.ignoreFailures = ignoreFailures; + } + + @Override + public boolean isIgnoreFailures() { + return ignoreFailures; + } + + @Override + public List getRules() { + return rules; + } + + @Override + public JacocoValidationRule rule(Closure configureClosure) { + return rule(ClosureBackedAction.of(configureClosure)); + } + + @Override + public JacocoValidationRule rule(Action configureAction) { + JacocoValidationRule validationRule = new JacocoValidationRuleImpl(); + configureAction.execute(validationRule); + rules.add(validationRule); + return validationRule; + } +} diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java index 3818b9923766..9f7749e428a0 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java @@ -39,8 +39,10 @@ import org.gradle.api.tasks.TaskCollection; import org.gradle.internal.jacoco.AntJacocoReport; import org.gradle.internal.jacoco.JacocoReportsContainerImpl; +import org.gradle.internal.jacoco.rules.JacocoValidationRulesContainerImpl; import org.gradle.internal.reflect.Instantiator; import org.gradle.testing.jacoco.plugins.JacocoTaskExtension; +import org.gradle.testing.jacoco.tasks.rules.JacocoValidationRulesContainer; import javax.inject.Inject; import java.io.File; @@ -55,6 +57,7 @@ public class JacocoReport extends JacocoBase implements Reporting { private final JacocoReportsContainer reports; + private final JacocoValidationRulesContainer validationRules; private FileCollection executionData; private FileCollection sourceDirectories; @@ -64,6 +67,7 @@ public class JacocoReport extends JacocoBase implements Reporting() { @Override public boolean isSatisfiedBy(Task element) { @@ -99,6 +103,18 @@ public JacocoReportsContainer getReports() { return reports; } + /** + * Return the validation rules set for this task. + * + * @return Validation rules container + * @since 3.3 + */ + @Nested + @Incubating + public JacocoValidationRulesContainer getValidationRules() { + return validationRules; + } + /** * Configures the reports to be generated by this task. */ @@ -113,6 +129,22 @@ public JacocoReportsContainer reports(Action con return reports; } + /** + * Configures the validation rules for this task. + * + * @since 3.3 + */ + @Incubating + public JacocoValidationRulesContainer validationRules(Closure closure) { + return validationRules(new ClosureBackedAction(closure)); + } + + @Incubating + public JacocoValidationRulesContainer validationRules(Action configureAction) { + configureAction.execute(validationRules); + return validationRules; + } + /** * Collection of execution data files to analyze. */ @@ -194,7 +226,8 @@ public boolean isSatisfiedBy(File file) { getAllClassDirs().filter(fileExistsSpec), getAllSourceDirs().filter(fileExistsSpec), getExecutionData(), - getReports() + getReports(), + getValidationRules() ); } diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoRuleScope.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoRuleScope.java new file mode 100644 index 000000000000..91a4da7c1bd2 --- /dev/null +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoRuleScope.java @@ -0,0 +1,29 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.testing.jacoco.tasks.rules; + +import org.gradle.api.Incubating; + +/** + * Jacoco rule scopes. + * + * @since 3.3 + */ +@Incubating +public enum JacocoRuleScope { + BUNDLE, PACKAGE, CLASS, SOURCEFILE, METHOD; +} diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThreshold.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThreshold.java new file mode 100644 index 000000000000..d923443f4a8f --- /dev/null +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThreshold.java @@ -0,0 +1,56 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.testing.jacoco.tasks.rules; + +import org.gradle.api.Incubating; + +/** + * A Jacoco threshold. + * + * @since 3.3 + */ +@Incubating +public interface JacocoThreshold { + + /** + * The metric that applies to the threshold defined by {@link JacocoThresholdMetric}. + */ + JacocoThresholdMetric getMetric(); + + void setMetric(JacocoThresholdMetric metric); + + /** + * The value that applies to the threshold defined by {@link JacocoThresholdValue}. + */ + JacocoThresholdValue getValue(); + + void setValue(JacocoThresholdValue value); + + /** + * Gets the minimum expected value for threshold. Default to null. + */ + Double getMinimum(); + + void setMinimum(Double minimum); + + /** + * Gets the maximum expected value for threshold. Default to null. + */ + Double getMaximum(); + + void setMaximum(Double maximum); +} diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdMetric.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdMetric.java new file mode 100644 index 000000000000..a02e93eb5db0 --- /dev/null +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdMetric.java @@ -0,0 +1,29 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.testing.jacoco.tasks.rules; + +import org.gradle.api.Incubating; + +/** + * Jacoco threshold metrics. + * + * @since 3.3 + */ +@Incubating +public enum JacocoThresholdMetric { + INSTRUCTION, LINE, BRANCH, COMPLEXITY, METHOD, CLASS; +} diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdValue.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdValue.java new file mode 100644 index 000000000000..fc34876078fe --- /dev/null +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdValue.java @@ -0,0 +1,29 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.testing.jacoco.tasks.rules; + +import org.gradle.api.Incubating; + +/** + * Jacoco threshold values. + * + * @since 3.3 + */ +@Incubating +public enum JacocoThresholdValue { + TOTALCOUNT, MISSEDCOUNT, COVERED_COUNT, MISSEDRATIO, COVEREDRATIO; +} diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoValidationRule.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoValidationRule.java new file mode 100644 index 000000000000..e3a0f639dfe5 --- /dev/null +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoValidationRule.java @@ -0,0 +1,66 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.testing.jacoco.tasks.rules; + +import groovy.lang.Closure; +import org.gradle.api.Action; +import org.gradle.api.Incubating; + +import java.util.List; + +/** + * A validation rule. + * + * @since 3.3 + */ +@Incubating +public interface JacocoValidationRule { + void setScope(JacocoRuleScope scope); + + /** + * Gets the scope for this rule defined by {@link JacocoRuleScope}. + */ + JacocoRuleScope getScope(); + + void setIncludes(List includes); + + /** + * List of elements that should be included in check. Names can use wildcards (* and ?). + * If left empty, all elements will be included. Defaults to an empty list. + */ + List getIncludes(); + + void setExcludes(List excludes); + + /** + * List of elements that should be excluded from check. Names can use wildcards (* and ?). + * If left empty, no elements will be excluded. Defaults to an empty list. + */ + List getExcludes(); + + /** + * Gets all thresholds defined for this rule. Defaults to an empty list. + */ + List getThresholds(); + + /** + * Adds a threshold for this rule. There's no limitation to the number of thresholds that can be added. + */ + JacocoThreshold threshold(Closure configureClosure); + + JacocoThreshold threshold(Action configureAction); +} diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoValidationRulesContainer.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoValidationRulesContainer.java new file mode 100644 index 000000000000..7a2138179d9e --- /dev/null +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoValidationRulesContainer.java @@ -0,0 +1,54 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.testing.jacoco.tasks.rules; + +import groovy.lang.Closure; +import org.gradle.api.Action; +import org.gradle.api.Incubating; +import org.gradle.api.tasks.Internal; + +import java.util.List; + +/** + * The validation rules configuration for the {@link org.gradle.testing.jacoco.tasks.JacocoReport} task. + * + * @since 3.3 + */ +@Incubating +public interface JacocoValidationRulesContainer { + + void setIgnoreFailures(boolean ignore); + + /** + * Specifies whether build should fail in case of rule violations. + */ + @Internal + boolean isIgnoreFailures(); + + /** + * Gets all validation rules. Defaults to an empty list. + */ + @Internal + List getRules(); + + /** + * Adds a validation rule. There's no limitation to the number of rules that can be added. + */ + JacocoValidationRule rule(Closure configureClosure); + + JacocoValidationRule rule(Action configureAction); +} diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/package-info.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/package-info.java new file mode 100644 index 000000000000..6fe859185bc4 --- /dev/null +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/package-info.java @@ -0,0 +1,21 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Implementations for Jacoco metrics rules. + */ +@org.gradle.api.Incubating +package org.gradle.testing.jacoco.tasks.rules; \ No newline at end of file From d7f3b7d182dee4cb53eaf693d7b5e5a421f8c691 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Thu, 1 Dec 2016 20:50:20 -0700 Subject: [PATCH 02/42] Add test cases for multiple report tasks --- ...oPluginCheckCoverageIntegrationTest.groovy | 102 ++++++++++++++---- .../fixtures/JavaProjectUnderTest.groovy | 45 +++++++- 2 files changed, 122 insertions(+), 25 deletions(-) diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy index 55fa43408a17..7dc87539b91b 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy @@ -23,12 +23,15 @@ import spock.lang.Unroll class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { private final JavaProjectUnderTest javaProjectUnderTest = new JavaProjectUnderTest(testDirectory) + private final static String[] TEST_AND_JACOCO_REPORT_TASK_PATHS = [':test', ':jacocoTestReport'] as String[] + private final static String[] INTEG_TEST_AND_JACOCO_REPORT_TASK_PATHS = [':integrationTest', ':jacocoIntegrationTestReport'] as String[] def setup() { javaProjectUnderTest.writeBuildScript().writeSourceFiles() } - def "no rules provided"() { + def "can define no rules"() { + given: buildFile << """ jacocoTestReport { validationRules {} @@ -36,13 +39,14 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { """ when: - succeeds 'test', 'jacocoTestReport' + succeeds TEST_AND_JACOCO_REPORT_TASK_PATHS then: - executedAndNotSkipped(':test', ':jacocoTestReport') + executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) } - def "single rule without thresholds"() { + def "can define single rule without thresholds"() { + given: buildFile << """ jacocoTestReport { validationRules { @@ -52,19 +56,20 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { """ when: - succeeds 'test', 'jacocoTestReport' + succeeds TEST_AND_JACOCO_REPORT_TASK_PATHS then: - executedAndNotSkipped(':test', ':jacocoTestReport') + executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) } def "can define includes for single rule"() { + given: buildFile << """ jacocoTestReport { validationRules { rule { scope = org.gradle.testing.jacoco.tasks.rules.JacocoRuleScope.CLASS - includes = ['org.gradle.*'] + includes = ['com.company.*', 'org.gradle.*'] $Thresholds.Insufficient.LINE_METRIC_COVERED_RATIO } } @@ -72,19 +77,20 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { """ when: - fails 'test', 'jacocoTestReport' + fails TEST_AND_JACOCO_REPORT_TASK_PATHS then: - executedAndNotSkipped(':test', ':jacocoTestReport') + executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) errorOutput.contains("Rule violated for class org.gradle.Class1: lines covered ratio is 1.0, but expected maximum is 0.5") } def "can define excludes for single rule"() { + given: buildFile << """ jacocoTestReport { validationRules { rule { - excludes = ['*'] + excludes = ['company', '$testDirectory.name'] $Thresholds.Insufficient.LINE_METRIC_COVERED_RATIO } } @@ -92,14 +98,14 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { """ when: - succeeds 'test', 'jacocoTestReport' + succeeds TEST_AND_JACOCO_REPORT_TASK_PATHS then: - executedAndNotSkipped(':test', ':jacocoTestReport') + executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) } @Unroll - def "rule with sufficient coverage for #description"() { + def "can define rule with sufficient coverage for #description"() { given: buildFile << """ jacocoTestReport { @@ -112,10 +118,10 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { """ when: - succeeds 'test', 'jacocoTestReport' + succeeds TEST_AND_JACOCO_REPORT_TASK_PATHS then: - executedAndNotSkipped(':test', ':jacocoTestReport') + executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) where: thresholds | description @@ -127,7 +133,8 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { } @Unroll - def "rule with insufficient coverage for #description"() { + def "can define rule with insufficient coverage for #description"() { + given: buildFile << """ jacocoTestReport { validationRules { @@ -139,10 +146,10 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { """ when: - fails 'test', 'jacocoTestReport' + fails TEST_AND_JACOCO_REPORT_TASK_PATHS then: - executedAndNotSkipped(':test', ':jacocoTestReport') + executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) errorOutput.contains("Rule violated for bundle $testDirectory.name: $errorMessage") where: @@ -157,6 +164,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { } def "can ignore failures"() { + given: buildFile << """ jacocoTestReport { validationRules { @@ -170,13 +178,67 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { """ when: - succeeds 'test', 'jacocoTestReport' + succeeds TEST_AND_JACOCO_REPORT_TASK_PATHS then: - executedAndNotSkipped(':test', ':jacocoTestReport') + executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) errorOutput.contains("Rule violated for bundle $testDirectory.name: lines covered ratio is 1.0, but expected maximum is 0.5") } + @Unroll + def "can define same rules for multiple report tasks #tasksPaths"() { + given: + javaProjectUnderTest.writeIntegrationTestSourceFiles() + + buildFile << """ + tasks.withType(JacocoReport) { + validationRules { + rule { + $Thresholds.Insufficient.LINE_METRIC_COVERED_RATIO + } + } + } + """ + + when: + fails tasksPaths + + then: + executedAndNotSkipped(tasksPaths) + errorOutput.contains("Rule violated for bundle $testDirectory.name: lines covered ratio is 1.0, but expected maximum is 0.5") + + where: + tasksPaths << [TEST_AND_JACOCO_REPORT_TASK_PATHS, INTEG_TEST_AND_JACOCO_REPORT_TASK_PATHS] + } + + @Unroll + def "can define different rules for multiple report tasks #tasksPaths"() { + given: + javaProjectUnderTest.writeIntegrationTestSourceFiles() + + buildFile << """ + $reportTaskName { + validationRules { + rule { + $threshold + } + } + } + """ + + when: + fails tasksPaths + + then: + executedAndNotSkipped(tasksPaths) + errorOutput.contains("Rule violated for bundle $testDirectory.name: $errorMessage") + + where: + tasksPaths | reportTaskName | threshold | errorMessage + TEST_AND_JACOCO_REPORT_TASK_PATHS | 'jacocoTestReport' | Thresholds.Insufficient.LINE_METRIC_COVERED_RATIO | 'lines covered ratio is 1.0, but expected maximum is 0.5' + INTEG_TEST_AND_JACOCO_REPORT_TASK_PATHS | 'jacocoIntegrationTestReport' | Thresholds.Insufficient.CLASS_METRIC_MISSED_COUNT | 'classes missed count is 0.0, but expected minimum is 0.5' + } + static class Thresholds { static class Sufficient { static final String LINE_METRIC_COVERED_RATIO = Thresholds.threshold('org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric.LINE', 'org.gradle.testing.jacoco.tasks.rules.JacocoThresholdValue.COVEREDRATIO', '0.0', '1.0') diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/fixtures/JavaProjectUnderTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/fixtures/JavaProjectUnderTest.groovy index fee016518418..7304ad701910 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/fixtures/JavaProjectUnderTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/fixtures/JavaProjectUnderTest.groovy @@ -20,13 +20,15 @@ import org.gradle.test.fixtures.file.TestFile class JavaProjectUnderTest { private final TestFile projectDir + private final TestFile buildFile JavaProjectUnderTest(TestFile projectDir) { this.projectDir = projectDir + buildFile = projectDir.file('build.gradle') } JavaProjectUnderTest writeBuildScript() { - projectDir.file('build.gradle') << """ + buildFile << """ apply plugin: 'java' apply plugin: 'jacoco' @@ -38,11 +40,44 @@ class JavaProjectUnderTest { testCompile 'junit:junit:4.12' } """ - this } JavaProjectUnderTest writeSourceFiles() { + writeProductionSourceFile() + writeTestSourceFile('src/test/java') + this + } + + JavaProjectUnderTest writeIntegrationTestSourceFiles() { + String testSrcDir = 'src/integTest/java' + buildFile << """ + sourceSets { + integrationTest { + java { + srcDir file('$testSrcDir') + } + compileClasspath += sourceSets.main.output + configurations.testRuntime + runtimeClasspath += output + compileClasspath + } + } + + task integrationTest(type: Test) { + testClassesDir = sourceSets.integrationTest.output.classesDir + classpath = sourceSets.integrationTest.runtimeClasspath + } + + task jacocoIntegrationTestReport(type: JacocoReport) { + executionData integrationTest + sourceSets sourceSets.main + } + """ + + writeTestSourceFile(testSrcDir) + this + } + + private void writeProductionSourceFile() { projectDir.file('src/main/java/org/gradle/Class1.java') << """ package org.gradle; @@ -52,8 +87,10 @@ class JavaProjectUnderTest { } } """ + } - projectDir.file('src/test/java/org/gradle/Class1Test.java') << """ + private void writeTestSourceFile(String baseDir) { + projectDir.file("$baseDir/org/gradle/Class1Test.java") << """ package org.gradle; import org.junit.Test; @@ -65,7 +102,5 @@ class JavaProjectUnderTest { } } """ - - this } } From 3f50fcd39e034e8452f75818da56022ea1697636 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Fri, 2 Dec 2016 08:04:39 -0700 Subject: [PATCH 03/42] Add test case for multiple rules --- ...oPluginCheckCoverageIntegrationTest.groovy | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy index 7dc87539b91b..a9b5d051e8b8 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy @@ -163,6 +163,29 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { Thresholds.Sufficient.CLASS_METRIC_MISSED_COUNT] | 'first insufficient threshold fails' | 'classes missed count is 0.0, but expected minimum is 0.5' } + def "can define multiple rules"() { + given: + buildFile << """ + jacocoTestReport { + validationRules { + rule { + $Thresholds.Sufficient.LINE_METRIC_COVERED_RATIO + } + rule { + $Thresholds.Insufficient.CLASS_METRIC_MISSED_COUNT + } + } + } + """ + + when: + fails TEST_AND_JACOCO_REPORT_TASK_PATHS + + then: + executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) + errorOutput.contains("Rule violated for bundle $testDirectory.name: classes missed count is 0.0, but expected minimum is 0.5") + } + def "can ignore failures"() { given: buildFile << """ From 5c3a8adf95463a82bccc0fe12fc5f075be1a922b Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Fri, 2 Dec 2016 08:07:27 -0700 Subject: [PATCH 04/42] Break out method --- .../jacoco/plugins/fixtures/JavaProjectUnderTest.groovy | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/fixtures/JavaProjectUnderTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/fixtures/JavaProjectUnderTest.groovy index 7304ad701910..9e3c6da6370f 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/fixtures/JavaProjectUnderTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/fixtures/JavaProjectUnderTest.groovy @@ -27,6 +27,10 @@ class JavaProjectUnderTest { buildFile = projectDir.file('build.gradle') } + private TestFile file(Object... path) { + projectDir.file(path) + } + JavaProjectUnderTest writeBuildScript() { buildFile << """ apply plugin: 'java' @@ -78,7 +82,7 @@ class JavaProjectUnderTest { } private void writeProductionSourceFile() { - projectDir.file('src/main/java/org/gradle/Class1.java') << """ + file('src/main/java/org/gradle/Class1.java') << """ package org.gradle; public class Class1 { @@ -90,7 +94,7 @@ class JavaProjectUnderTest { } private void writeTestSourceFile(String baseDir) { - projectDir.file("$baseDir/org/gradle/Class1Test.java") << """ + file("$baseDir/org/gradle/Class1Test.java") << """ package org.gradle; import org.junit.Test; From c27a0b2414523eede226b00fbf7d4a43625044c3 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Fri, 2 Dec 2016 09:50:55 -0700 Subject: [PATCH 05/42] Expose configuration option for disabling rules --- ...oPluginCheckCoverageIntegrationTest.groovy | 23 +++++++++++++++++++ .../internal/jacoco/AntJacocoReport.java | 12 +++++++++- .../rules/JacocoValidationRuleImpl.java | 11 +++++++++ .../tasks/rules/JacocoValidationRule.java | 10 +++++++- 4 files changed, 54 insertions(+), 2 deletions(-) diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy index a9b5d051e8b8..88a527eee54d 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy @@ -186,6 +186,29 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { errorOutput.contains("Rule violated for bundle $testDirectory.name: classes missed count is 0.0, but expected minimum is 0.5") } + def "can disable rules"() { + given: + buildFile << """ + jacocoTestReport { + validationRules { + rule { + $Thresholds.Sufficient.LINE_METRIC_COVERED_RATIO + } + rule { + enabled = false + $Thresholds.Insufficient.CLASS_METRIC_MISSED_COUNT + } + } + } + """ + + when: + succeeds TEST_AND_JACOCO_REPORT_TASK_PATHS + + then: + executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) + } + def "can ignore failures"() { given: buildFile << """ diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java index 5f8bdee4927f..f5216f259d77 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java @@ -17,6 +17,7 @@ package org.gradle.internal.jacoco; import com.google.common.base.Joiner; +import com.google.common.base.Predicate; import com.google.common.collect.ImmutableMap; import groovy.lang.Closure; import groovy.lang.GroovyObjectSupport; @@ -31,8 +32,17 @@ import java.util.HashMap; import java.util.Map; +import static com.google.common.collect.Iterables.filter; + public class AntJacocoReport { + private static final Predicate RULE_ENABLED_PREDICATE = new Predicate() { + @Override + public boolean apply(JacocoValidationRule rule) { + return rule.isEnabled(); + } + }; + private final IsolatedAntBuilder ant; public AntJacocoReport(IsolatedAntBuilder ant) { @@ -109,7 +119,7 @@ private void configureCheck(final GroovyObjectSupport antBuilder, final JacocoVa antBuilder.invokeMethod("check", new Object[] {checkArgs, new Closure(this, this) { @SuppressWarnings("UnusedDeclaration") public Object doCall(Object ignore) { - for (final JacocoValidationRule rule : validationRules.getRules()) { + for (final JacocoValidationRule rule : filter(validationRules.getRules(), RULE_ENABLED_PREDICATE)) { Map ruleArgs = new HashMap(); if (rule.getScope() != null) { diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRuleImpl.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRuleImpl.java index 963dc39c61cb..23223bbe76e3 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRuleImpl.java +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRuleImpl.java @@ -28,11 +28,22 @@ public class JacocoValidationRuleImpl implements JacocoValidationRule { + private boolean enabled = true; private JacocoRuleScope scope; private List includes = new ArrayList(); private List excludes = new ArrayList(); private final List thresholds = new ArrayList(); + @Override + public boolean isEnabled() { + return enabled; + } + + @Override + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + @Override public void setScope(JacocoRuleScope scope) { this.scope = scope; diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoValidationRule.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoValidationRule.java index e3a0f639dfe5..94ea6979bdc8 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoValidationRule.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoValidationRule.java @@ -29,10 +29,18 @@ */ @Incubating public interface JacocoValidationRule { + + void setEnabled(boolean enabled); + + /** + * Indicates if the rule should be used when checking generated coverage metrics. + */ + boolean isEnabled(); + void setScope(JacocoRuleScope scope); /** - * Gets the scope for this rule defined by {@link JacocoRuleScope}. + * Gets the scope for the rule defined by {@link JacocoRuleScope}. */ JacocoRuleScope getScope(); From 3f971f7a9db5049d8f67e0862243c2587421fdc6 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Fri, 2 Dec 2016 10:42:38 -0700 Subject: [PATCH 06/42] Rules can be checked even if all report formats are disabled --- ...oPluginCheckCoverageIntegrationTest.groovy | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy index 88a527eee54d..17d60a06c5fe 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy @@ -104,6 +104,31 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) } + def "can check rules even all report formats are disabled"() { + given: + buildFile << """ + jacocoTestReport { + reports { + xml.enabled false + csv.enabled false + html.enabled false + } + validationRules { + rule { + $Thresholds.Insufficient.LINE_METRIC_COVERED_RATIO + } + } + } + """ + + when: + fails TEST_AND_JACOCO_REPORT_TASK_PATHS + + then: + executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) + errorOutput.contains("Rule violated for bundle $testDirectory.name: lines covered ratio is 1.0, but expected maximum is 0.5") + } + @Unroll def "can define rule with sufficient coverage for #description"() { given: From 2c7be9fb073b697b2304c1ffbab3980fba7926fe Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Fri, 2 Dec 2016 10:51:57 -0700 Subject: [PATCH 07/42] Use strong typing for enums --- ...oPluginCheckCoverageIntegrationTest.groovy | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy index 17d60a06c5fe..0a9f506ec30b 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy @@ -18,8 +18,15 @@ package org.gradle.testing.jacoco.plugins import org.gradle.integtests.fixtures.AbstractIntegrationSpec import org.gradle.testing.jacoco.plugins.fixtures.JavaProjectUnderTest +import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric +import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdValue import spock.lang.Unroll +import static org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric.CLASS +import static org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric.LINE +import static org.gradle.testing.jacoco.tasks.rules.JacocoThresholdValue.COVEREDRATIO +import static org.gradle.testing.jacoco.tasks.rules.JacocoThresholdValue.MISSEDCOUNT + class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { private final JavaProjectUnderTest javaProjectUnderTest = new JavaProjectUnderTest(testDirectory) @@ -64,11 +71,12 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { def "can define includes for single rule"() { given: + String scope = "${org.gradle.testing.jacoco.tasks.rules.JacocoRuleScope.CLASS.getClass().getName()}.${org.gradle.testing.jacoco.tasks.rules.JacocoRuleScope.CLASS.name()}" buildFile << """ jacocoTestReport { validationRules { rule { - scope = org.gradle.testing.jacoco.tasks.rules.JacocoRuleScope.CLASS + scope = $scope includes = ['com.company.*', 'org.gradle.*'] $Thresholds.Insufficient.LINE_METRIC_COVERED_RATIO } @@ -312,24 +320,24 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { static class Thresholds { static class Sufficient { - static final String LINE_METRIC_COVERED_RATIO = Thresholds.threshold('org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric.LINE', 'org.gradle.testing.jacoco.tasks.rules.JacocoThresholdValue.COVEREDRATIO', '0.0', '1.0') - static final String CLASS_METRIC_MISSED_COUNT = Thresholds.threshold('org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric.CLASS', 'org.gradle.testing.jacoco.tasks.rules.JacocoThresholdValue.MISSEDCOUNT', null, '0') + static final String LINE_METRIC_COVERED_RATIO = Thresholds.threshold(LINE, COVEREDRATIO, '0.0', '1.0') + static final String CLASS_METRIC_MISSED_COUNT = Thresholds.threshold(CLASS, MISSEDCOUNT, null, '0') } static class Insufficient { - static final String LINE_METRIC_COVERED_RATIO = Thresholds.threshold('org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric.LINE', 'org.gradle.testing.jacoco.tasks.rules.JacocoThresholdValue.COVEREDRATIO', '0.0', '0.5') - static final String CLASS_METRIC_MISSED_COUNT = Thresholds.threshold('org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric.CLASS', 'org.gradle.testing.jacoco.tasks.rules.JacocoThresholdValue.MISSEDCOUNT', '0.5', null) + static final String LINE_METRIC_COVERED_RATIO = Thresholds.threshold(LINE, COVEREDRATIO, '0.0', '0.5') + static final String CLASS_METRIC_MISSED_COUNT = Thresholds.threshold(CLASS, MISSEDCOUNT, '0.5', null) } - static String threshold(String metric, String value, String minimum, String maximum) { + static String threshold(JacocoThresholdMetric metric, JacocoThresholdValue value, String minimum, String maximum) { StringBuilder threshold = new StringBuilder() threshold <<= 'threshold {\n' if (metric) { - threshold <<= " metric = $metric\n" + threshold <<= " metric = ${metric.getClass().getName()}.${metric.name()}\n" } if (value) { - threshold <<= " value = $value\n" + threshold <<= " value = ${value.getClass().getName()}.${value.name()}\n" } if (minimum) { threshold <<= " minimum = $minimum\n" From 530828fd5c0bde436c90e615b7ea7a89118bb88b Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Fri, 2 Dec 2016 11:38:32 -0700 Subject: [PATCH 08/42] Rename of method --- .../JacocoPluginCheckCoverageIntegrationTest.groovy | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy index 0a9f506ec30b..b7b8e999f897 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy @@ -320,16 +320,16 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { static class Thresholds { static class Sufficient { - static final String LINE_METRIC_COVERED_RATIO = Thresholds.threshold(LINE, COVEREDRATIO, '0.0', '1.0') - static final String CLASS_METRIC_MISSED_COUNT = Thresholds.threshold(CLASS, MISSEDCOUNT, null, '0') + static final String LINE_METRIC_COVERED_RATIO = Thresholds.create(LINE, COVEREDRATIO, '0.0', '1.0') + static final String CLASS_METRIC_MISSED_COUNT = Thresholds.create(CLASS, MISSEDCOUNT, null, '0') } static class Insufficient { - static final String LINE_METRIC_COVERED_RATIO = Thresholds.threshold(LINE, COVEREDRATIO, '0.0', '0.5') - static final String CLASS_METRIC_MISSED_COUNT = Thresholds.threshold(CLASS, MISSEDCOUNT, '0.5', null) + static final String LINE_METRIC_COVERED_RATIO = Thresholds.create(LINE, COVEREDRATIO, '0.0', '0.5') + static final String CLASS_METRIC_MISSED_COUNT = Thresholds.create(CLASS, MISSEDCOUNT, '0.5', null) } - static String threshold(JacocoThresholdMetric metric, JacocoThresholdValue value, String minimum, String maximum) { + private static String create(JacocoThresholdMetric metric, JacocoThresholdValue value, String minimum, String maximum) { StringBuilder threshold = new StringBuilder() threshold <<= 'threshold {\n' From 493e2827e466c3598e89147e2822cdb2000e7287 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Fri, 2 Dec 2016 12:05:33 -0700 Subject: [PATCH 09/42] Add some unit tests --- .../jacoco/rules/JacocoThresholdImpl.java | 32 +++++++ .../rules/JacocoValidationRuleImpl.java | 43 ++++++++- .../JacocoValidationRulesContainerImpl.java | 3 +- .../rules/JacocoThresholdImplTest.groovy | 32 +++++++ .../rules/JacocoValidationRuleImplTest.groovy | 87 +++++++++++++++++++ ...ocoValidationRulesContainerImplTest.groovy | 72 +++++++++++++++ 6 files changed, 265 insertions(+), 4 deletions(-) create mode 100644 subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoThresholdImplTest.groovy create mode 100644 subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoValidationRuleImplTest.groovy create mode 100644 subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoValidationRulesContainerImplTest.groovy diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoThresholdImpl.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoThresholdImpl.java index cc2d6751a03e..789728328d89 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoThresholdImpl.java +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoThresholdImpl.java @@ -66,4 +66,36 @@ public Double getMaximum() { public void setMaximum(Double maximum) { this.maximum = maximum; } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + JacocoThresholdImpl that = (JacocoThresholdImpl) o; + + if (metric != that.metric) { + return false; + } + if (value != that.value) { + return false; + } + if (minimum != null ? !minimum.equals(that.minimum) : that.minimum != null) { + return false; + } + return maximum != null ? maximum.equals(that.maximum) : that.maximum == null; + } + + @Override + public int hashCode() { + int result = metric != null ? metric.hashCode() : 0; + result = 31 * result + (value != null ? value.hashCode() : 0); + result = 31 * result + (minimum != null ? minimum.hashCode() : 0); + result = 31 * result + (maximum != null ? maximum.hashCode() : 0); + return result; + } } diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRuleImpl.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRuleImpl.java index 23223bbe76e3..05d2ee95f269 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRuleImpl.java +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRuleImpl.java @@ -24,6 +24,7 @@ import org.gradle.testing.jacoco.tasks.rules.JacocoValidationRule; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class JacocoValidationRuleImpl implements JacocoValidationRule { @@ -61,7 +62,7 @@ public void setIncludes(List includes) { @Override public List getIncludes() { - return includes; + return Collections.unmodifiableList(includes); } @Override @@ -71,12 +72,12 @@ public void setExcludes(List excludes) { @Override public List getExcludes() { - return excludes; + return Collections.unmodifiableList(excludes); } @Override public List getThresholds() { - return thresholds; + return Collections.unmodifiableList(thresholds); } @Override @@ -91,4 +92,40 @@ public JacocoThreshold threshold(Action configureAction thresholds.add(threshold); return threshold; } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + JacocoValidationRuleImpl that = (JacocoValidationRuleImpl) o; + + if (enabled != that.enabled) { + return false; + } + if (scope != that.scope) { + return false; + } + if (includes != null ? !includes.equals(that.includes) : that.includes != null) { + return false; + } + if (excludes != null ? !excludes.equals(that.excludes) : that.excludes != null) { + return false; + } + return thresholds != null ? thresholds.equals(that.thresholds) : that.thresholds == null; + } + + @Override + public int hashCode() { + int result = enabled ? 1 : 0; + result = 31 * result + (scope != null ? scope.hashCode() : 0); + result = 31 * result + (includes != null ? includes.hashCode() : 0); + result = 31 * result + (excludes != null ? excludes.hashCode() : 0); + result = 31 * result + (thresholds != null ? thresholds.hashCode() : 0); + return result; + } } diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRulesContainerImpl.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRulesContainerImpl.java index 2a601f81258b..c07c17b3d702 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRulesContainerImpl.java +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRulesContainerImpl.java @@ -23,6 +23,7 @@ import org.gradle.testing.jacoco.tasks.rules.JacocoValidationRulesContainer; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class JacocoValidationRulesContainerImpl implements JacocoValidationRulesContainer { @@ -42,7 +43,7 @@ public boolean isIgnoreFailures() { @Override public List getRules() { - return rules; + return Collections.unmodifiableList(rules); } @Override diff --git a/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoThresholdImplTest.groovy b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoThresholdImplTest.groovy new file mode 100644 index 000000000000..a95b0d0497ef --- /dev/null +++ b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoThresholdImplTest.groovy @@ -0,0 +1,32 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.jacoco.rules + +import spock.lang.Specification + +class JacocoThresholdImplTest extends Specification { + + JacocoThresholdImpl threshold = new JacocoThresholdImpl() + + def "provides expected default field values"() { + expect: + !threshold.metric + !threshold.value + !threshold.minimum + !threshold.maximum + } +} diff --git a/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoValidationRuleImplTest.groovy b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoValidationRuleImplTest.groovy new file mode 100644 index 000000000000..a9f692664c54 --- /dev/null +++ b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoValidationRuleImplTest.groovy @@ -0,0 +1,87 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.jacoco.rules + +import org.gradle.api.Action +import org.gradle.testing.jacoco.tasks.rules.JacocoThreshold +import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric +import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdValue +import spock.lang.Specification + +class JacocoValidationRuleImplTest extends Specification { + + JacocoValidationRuleImpl rule = new JacocoValidationRuleImpl() + + def "provides expected default field values"() { + expect: + rule.enabled + !rule.scope + rule.includes == [] + rule.excludes == [] + } + + def "can add thresholds"() { + when: + def threshold = rule.threshold { + metric = JacocoThresholdMetric.CLASS + value = JacocoThresholdValue.TOTALCOUNT + minimum = 0.0 + maximum = 1.0 + } + + then: + rule.thresholds.size() == 1 + rule.thresholds[0] == threshold + + when: + threshold = rule.threshold(new Action() { + @Override + void execute(JacocoThreshold jacocoThreshold) { + jacocoThreshold.with { + metric = JacocoThresholdMetric.COMPLEXITY + value = JacocoThresholdValue.MISSEDCOUNT + minimum = 0.2 + maximum = 0.6 + } + } + }) + + then: + rule.thresholds.size() == 2 + rule.thresholds[1] == threshold + } + + def "returned includes, excludes and thresholds are unmodifiable"() { + when: + rule.includes << ['*'] + + then: + thrown(UnsupportedOperationException) + + when: + rule.excludes << ['*'] + + then: + thrown(UnsupportedOperationException) + + when: + rule.thresholds << new JacocoThresholdImpl() + + then: + thrown(UnsupportedOperationException) + } +} diff --git a/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoValidationRulesContainerImplTest.groovy b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoValidationRulesContainerImplTest.groovy new file mode 100644 index 000000000000..bd770128819f --- /dev/null +++ b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoValidationRulesContainerImplTest.groovy @@ -0,0 +1,72 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.jacoco.rules + +import org.gradle.api.Action +import org.gradle.testing.jacoco.tasks.rules.JacocoRuleScope +import org.gradle.testing.jacoco.tasks.rules.JacocoValidationRule +import spock.lang.Specification + +class JacocoValidationRulesContainerImplTest extends Specification { + + JacocoValidationRulesContainerImpl validationRulesContainer = new JacocoValidationRulesContainerImpl() + + def "provides expected default field values"() { + expect: + !validationRulesContainer.ignoreFailures + validationRulesContainer.rules.empty + } + + def "can add rules"() { + when: + def rule = validationRulesContainer.rule { + enabled = false + scope = JacocoRuleScope.CLASS + includes = ['**/*.class'] + excludes = ['*Special*.class'] + } + + then: + validationRulesContainer.rules.size() == 1 + validationRulesContainer.rules[0] == rule + + when: + rule = validationRulesContainer.rule(new Action() { + @Override + void execute(JacocoValidationRule jacocoValidationRule) { + jacocoValidationRule.with { + enabled = true + scope = JacocoRuleScope.PACKAGE + includes = ['**/*'] + excludes = ['**/special/*'] + } + } + }) + + then: + validationRulesContainer.rules.size() == 2 + validationRulesContainer.rules[1] == rule + } + + def "returned rules are unmodifiable"() { + when: + validationRulesContainer.rules << new JacocoValidationRuleImpl() + + then: + thrown(UnsupportedOperationException) + } +} From 317ec14582edafa2dab847e09b8a75825a70b285 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Fri, 2 Dec 2016 14:04:22 -0700 Subject: [PATCH 10/42] Renamed property --- .../JacocoPluginCheckCoverageIntegrationTest.groovy | 2 +- .../org/gradle/internal/jacoco/AntJacocoReport.java | 2 +- .../rules/JacocoValidationRulesContainerImpl.java | 12 +++++------- .../tasks/rules/JacocoValidationRulesContainer.java | 4 ++-- .../JacocoValidationRulesContainerImplTest.groovy | 2 +- 5 files changed, 10 insertions(+), 12 deletions(-) diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy index b7b8e999f897..31ede92a1968 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy @@ -247,7 +247,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { buildFile << """ jacocoTestReport { validationRules { - ignoreFailures = true + failOnViolation = true rule { $Thresholds.Insufficient.LINE_METRIC_COVERED_RATIO diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java index f5216f259d77..30f3c53870bb 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java @@ -115,7 +115,7 @@ public Object doCall(Object ignore) { private void configureCheck(final GroovyObjectSupport antBuilder, final JacocoValidationRulesContainer validationRules) { if (!validationRules.getRules().isEmpty()) { - Map checkArgs = ImmutableMap.of("failonviolation", !validationRules.isIgnoreFailures()); + Map checkArgs = ImmutableMap.of("failonviolation", !validationRules.isFailOnViolation()); antBuilder.invokeMethod("check", new Object[] {checkArgs, new Closure(this, this) { @SuppressWarnings("UnusedDeclaration") public Object doCall(Object ignore) { diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRulesContainerImpl.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRulesContainerImpl.java index c07c17b3d702..a9ac96e719df 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRulesContainerImpl.java +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRulesContainerImpl.java @@ -28,17 +28,15 @@ public class JacocoValidationRulesContainerImpl implements JacocoValidationRulesContainer { - private boolean ignoreFailures; + private boolean failOnViolation; private final List rules = new ArrayList(); - @Override - public void setIgnoreFailures(boolean ignoreFailures) { - this.ignoreFailures = ignoreFailures; + public void setFailOnViolation(boolean failOnViolation) { + this.failOnViolation = failOnViolation; } - @Override - public boolean isIgnoreFailures() { - return ignoreFailures; + public boolean isFailOnViolation() { + return failOnViolation; } @Override diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoValidationRulesContainer.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoValidationRulesContainer.java index 7a2138179d9e..75c1f440ccaf 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoValidationRulesContainer.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoValidationRulesContainer.java @@ -31,13 +31,13 @@ @Incubating public interface JacocoValidationRulesContainer { - void setIgnoreFailures(boolean ignore); + void setFailOnViolation(boolean ignore); /** * Specifies whether build should fail in case of rule violations. */ @Internal - boolean isIgnoreFailures(); + boolean isFailOnViolation(); /** * Gets all validation rules. Defaults to an empty list. diff --git a/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoValidationRulesContainerImplTest.groovy b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoValidationRulesContainerImplTest.groovy index bd770128819f..ecb08360bd6e 100644 --- a/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoValidationRulesContainerImplTest.groovy +++ b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoValidationRulesContainerImplTest.groovy @@ -27,7 +27,7 @@ class JacocoValidationRulesContainerImplTest extends Specification { def "provides expected default field values"() { expect: - !validationRulesContainer.ignoreFailures + !validationRulesContainer.failOnViolation validationRulesContainer.rules.empty } From 5b0f08527e6f8a5f9453d68f1698662530ac51e5 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Fri, 2 Dec 2016 14:14:54 -0700 Subject: [PATCH 11/42] Set default values for fields as described in Jacoco docs --- .../gradle/internal/jacoco/rules/JacocoThresholdImpl.java | 4 ++-- .../internal/jacoco/rules/JacocoValidationRuleImpl.java | 7 ++++--- .../testing/jacoco/tasks/rules/JacocoThresholdValue.java | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoThresholdImpl.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoThresholdImpl.java index 789728328d89..ae7f38584485 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoThresholdImpl.java +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoThresholdImpl.java @@ -22,8 +22,8 @@ public class JacocoThresholdImpl implements JacocoThreshold { - private JacocoThresholdMetric metric; - private JacocoThresholdValue value; + private JacocoThresholdMetric metric = JacocoThresholdMetric.INSTRUCTION; + private JacocoThresholdValue value = JacocoThresholdValue.COVEREDRATIO; private Double minimum; private Double maximum; diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRuleImpl.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRuleImpl.java index 05d2ee95f269..f36849099741 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRuleImpl.java +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRuleImpl.java @@ -16,6 +16,7 @@ package org.gradle.internal.jacoco.rules; +import com.google.common.collect.ImmutableList; import groovy.lang.Closure; import org.gradle.api.Action; import org.gradle.api.internal.ClosureBackedAction; @@ -30,9 +31,9 @@ public class JacocoValidationRuleImpl implements JacocoValidationRule { private boolean enabled = true; - private JacocoRuleScope scope; - private List includes = new ArrayList(); - private List excludes = new ArrayList(); + private JacocoRuleScope scope = JacocoRuleScope.BUNDLE; + private List includes = ImmutableList.of("*"); + private List excludes = ImmutableList.of(); private final List thresholds = new ArrayList(); @Override diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdValue.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdValue.java index fc34876078fe..809eb106dc61 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdValue.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdValue.java @@ -25,5 +25,5 @@ */ @Incubating public enum JacocoThresholdValue { - TOTALCOUNT, MISSEDCOUNT, COVERED_COUNT, MISSEDRATIO, COVEREDRATIO; + TOTALCOUNT, MISSEDCOUNT, COVEREDCOUNT, MISSEDRATIO, COVEREDRATIO; } From f8f3070def21fa8c45ff732f9cdd4e7dbc338b06 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Fri, 2 Dec 2016 14:34:29 -0700 Subject: [PATCH 12/42] Renamed fields to better express intention --- ...oPluginCheckCoverageIntegrationTest.groovy | 24 +++++++------- .../internal/jacoco/AntJacocoReport.java | 20 +++++------ ...Impl.java => JacocoViolationRuleImpl.java} | 6 ++-- ...=> JacocoViolationRulesContainerImpl.java} | 16 ++++----- .../testing/jacoco/tasks/JacocoReport.java | 33 ++++++++++--------- ...tionRule.java => JacocoViolationRule.java} | 4 +-- ...ava => JacocoViolationRulesContainer.java} | 14 ++++---- .../rules/JacocoThresholdImplTest.groovy | 6 ++-- ...ovy => JacocoViolationRuleImplTest.groovy} | 9 ++--- ...ocoViolationRulesContainerImplTest.groovy} | 26 +++++++-------- 10 files changed, 82 insertions(+), 76 deletions(-) rename subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/{JacocoValidationRuleImpl.java => JacocoViolationRuleImpl.java} (94%) rename subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/{JacocoValidationRulesContainerImpl.java => JacocoViolationRulesContainerImpl.java} (69%) rename subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/{JacocoValidationRule.java => JacocoViolationRule.java} (96%) rename subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/{JacocoValidationRulesContainer.java => JacocoViolationRulesContainer.java} (68%) rename subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/{JacocoValidationRuleImplTest.groovy => JacocoViolationRuleImplTest.groovy} (90%) rename subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/{JacocoValidationRulesContainerImplTest.groovy => JacocoViolationRulesContainerImplTest.groovy} (65%) diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy index 31ede92a1968..3d96c00412ba 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy @@ -41,7 +41,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { given: buildFile << """ jacocoTestReport { - validationRules {} + violationRules {} } """ @@ -56,7 +56,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { given: buildFile << """ jacocoTestReport { - validationRules { + violationRules { rule {} } } @@ -74,7 +74,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { String scope = "${org.gradle.testing.jacoco.tasks.rules.JacocoRuleScope.CLASS.getClass().getName()}.${org.gradle.testing.jacoco.tasks.rules.JacocoRuleScope.CLASS.name()}" buildFile << """ jacocoTestReport { - validationRules { + violationRules { rule { scope = $scope includes = ['com.company.*', 'org.gradle.*'] @@ -96,7 +96,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { given: buildFile << """ jacocoTestReport { - validationRules { + violationRules { rule { excludes = ['company', '$testDirectory.name'] $Thresholds.Insufficient.LINE_METRIC_COVERED_RATIO @@ -121,7 +121,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { csv.enabled false html.enabled false } - validationRules { + violationRules { rule { $Thresholds.Insufficient.LINE_METRIC_COVERED_RATIO } @@ -142,7 +142,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { given: buildFile << """ jacocoTestReport { - validationRules { + violationRules { rule { ${thresholds.join('\n')} } @@ -170,7 +170,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { given: buildFile << """ jacocoTestReport { - validationRules { + violationRules { rule { ${thresholds.join('\n')} } @@ -200,7 +200,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { given: buildFile << """ jacocoTestReport { - validationRules { + violationRules { rule { $Thresholds.Sufficient.LINE_METRIC_COVERED_RATIO } @@ -223,7 +223,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { given: buildFile << """ jacocoTestReport { - validationRules { + violationRules { rule { $Thresholds.Sufficient.LINE_METRIC_COVERED_RATIO } @@ -246,7 +246,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { given: buildFile << """ jacocoTestReport { - validationRules { + violationRules { failOnViolation = true rule { @@ -271,7 +271,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { buildFile << """ tasks.withType(JacocoReport) { - validationRules { + violationRules { rule { $Thresholds.Insufficient.LINE_METRIC_COVERED_RATIO } @@ -297,7 +297,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { buildFile << """ $reportTaskName { - validationRules { + violationRules { rule { $threshold } diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java index 30f3c53870bb..74b19358e7b5 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java @@ -25,8 +25,8 @@ import org.gradle.api.internal.project.IsolatedAntBuilder; import org.gradle.testing.jacoco.tasks.JacocoReportsContainer; import org.gradle.testing.jacoco.tasks.rules.JacocoThreshold; -import org.gradle.testing.jacoco.tasks.rules.JacocoValidationRule; -import org.gradle.testing.jacoco.tasks.rules.JacocoValidationRulesContainer; +import org.gradle.testing.jacoco.tasks.rules.JacocoViolationRule; +import org.gradle.testing.jacoco.tasks.rules.JacocoViolationRulesContainer; import java.util.Collections; import java.util.HashMap; @@ -36,9 +36,9 @@ public class AntJacocoReport { - private static final Predicate RULE_ENABLED_PREDICATE = new Predicate() { + private static final Predicate RULE_ENABLED_PREDICATE = new Predicate() { @Override - public boolean apply(JacocoValidationRule rule) { + public boolean apply(JacocoViolationRule rule) { return rule.isEnabled(); } }; @@ -53,7 +53,7 @@ public void execute(FileCollection classpath, final String projectName, final FileCollection allClassesDirs, final FileCollection allSourcesDirs, final FileCollection executionData, final JacocoReportsContainer reports, - final JacocoValidationRulesContainer validationRules) { + final JacocoViolationRulesContainer violationRules) { ant.withClasspath(classpath).execute(new Closure(this, this) { @SuppressWarnings("UnusedDeclaration") public Object doCall(Object it) { @@ -104,7 +104,7 @@ public Object doCall(Object ignore) { ImmutableMap.of("destfile", reports.getCsv().getDestination()) }); } - configureCheck(antBuilder, validationRules); + configureCheck(antBuilder, violationRules); return null; } }}); @@ -113,13 +113,13 @@ public Object doCall(Object ignore) { }); } - private void configureCheck(final GroovyObjectSupport antBuilder, final JacocoValidationRulesContainer validationRules) { - if (!validationRules.getRules().isEmpty()) { - Map checkArgs = ImmutableMap.of("failonviolation", !validationRules.isFailOnViolation()); + private void configureCheck(final GroovyObjectSupport antBuilder, final JacocoViolationRulesContainer violationRules) { + if (!violationRules.getRules().isEmpty()) { + Map checkArgs = ImmutableMap.of("failonviolation", !violationRules.isFailOnViolation()); antBuilder.invokeMethod("check", new Object[] {checkArgs, new Closure(this, this) { @SuppressWarnings("UnusedDeclaration") public Object doCall(Object ignore) { - for (final JacocoValidationRule rule : filter(validationRules.getRules(), RULE_ENABLED_PREDICATE)) { + for (final JacocoViolationRule rule : filter(violationRules.getRules(), RULE_ENABLED_PREDICATE)) { Map ruleArgs = new HashMap(); if (rule.getScope() != null) { diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRuleImpl.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoViolationRuleImpl.java similarity index 94% rename from subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRuleImpl.java rename to subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoViolationRuleImpl.java index f36849099741..7abc51414fcb 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRuleImpl.java +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoViolationRuleImpl.java @@ -22,13 +22,13 @@ import org.gradle.api.internal.ClosureBackedAction; import org.gradle.testing.jacoco.tasks.rules.JacocoRuleScope; import org.gradle.testing.jacoco.tasks.rules.JacocoThreshold; -import org.gradle.testing.jacoco.tasks.rules.JacocoValidationRule; +import org.gradle.testing.jacoco.tasks.rules.JacocoViolationRule; import java.util.ArrayList; import java.util.Collections; import java.util.List; -public class JacocoValidationRuleImpl implements JacocoValidationRule { +public class JacocoViolationRuleImpl implements JacocoViolationRule { private boolean enabled = true; private JacocoRuleScope scope = JacocoRuleScope.BUNDLE; @@ -103,7 +103,7 @@ public boolean equals(Object o) { return false; } - JacocoValidationRuleImpl that = (JacocoValidationRuleImpl) o; + JacocoViolationRuleImpl that = (JacocoViolationRuleImpl) o; if (enabled != that.enabled) { return false; diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRulesContainerImpl.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoViolationRulesContainerImpl.java similarity index 69% rename from subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRulesContainerImpl.java rename to subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoViolationRulesContainerImpl.java index a9ac96e719df..86c3f74432de 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoValidationRulesContainerImpl.java +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoViolationRulesContainerImpl.java @@ -19,17 +19,17 @@ import groovy.lang.Closure; import org.gradle.api.Action; import org.gradle.api.internal.ClosureBackedAction; -import org.gradle.testing.jacoco.tasks.rules.JacocoValidationRule; -import org.gradle.testing.jacoco.tasks.rules.JacocoValidationRulesContainer; +import org.gradle.testing.jacoco.tasks.rules.JacocoViolationRule; +import org.gradle.testing.jacoco.tasks.rules.JacocoViolationRulesContainer; import java.util.ArrayList; import java.util.Collections; import java.util.List; -public class JacocoValidationRulesContainerImpl implements JacocoValidationRulesContainer { +public class JacocoViolationRulesContainerImpl implements JacocoViolationRulesContainer { private boolean failOnViolation; - private final List rules = new ArrayList(); + private final List rules = new ArrayList(); public void setFailOnViolation(boolean failOnViolation) { this.failOnViolation = failOnViolation; @@ -40,18 +40,18 @@ public boolean isFailOnViolation() { } @Override - public List getRules() { + public List getRules() { return Collections.unmodifiableList(rules); } @Override - public JacocoValidationRule rule(Closure configureClosure) { + public JacocoViolationRule rule(Closure configureClosure) { return rule(ClosureBackedAction.of(configureClosure)); } @Override - public JacocoValidationRule rule(Action configureAction) { - JacocoValidationRule validationRule = new JacocoValidationRuleImpl(); + public JacocoViolationRule rule(Action configureAction) { + JacocoViolationRule validationRule = new JacocoViolationRuleImpl(); configureAction.execute(validationRule); rules.add(validationRule); return validationRule; diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java index 9f7749e428a0..358ea8e7d7d4 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java @@ -39,10 +39,10 @@ import org.gradle.api.tasks.TaskCollection; import org.gradle.internal.jacoco.AntJacocoReport; import org.gradle.internal.jacoco.JacocoReportsContainerImpl; -import org.gradle.internal.jacoco.rules.JacocoValidationRulesContainerImpl; +import org.gradle.internal.jacoco.rules.JacocoViolationRulesContainerImpl; import org.gradle.internal.reflect.Instantiator; import org.gradle.testing.jacoco.plugins.JacocoTaskExtension; -import org.gradle.testing.jacoco.tasks.rules.JacocoValidationRulesContainer; +import org.gradle.testing.jacoco.tasks.rules.JacocoViolationRulesContainer; import javax.inject.Inject; import java.io.File; @@ -57,7 +57,7 @@ public class JacocoReport extends JacocoBase implements Reporting { private final JacocoReportsContainer reports; - private final JacocoValidationRulesContainer validationRules; + private final JacocoViolationRulesContainer violationRules; private FileCollection executionData; private FileCollection sourceDirectories; @@ -67,7 +67,7 @@ public class JacocoReport extends JacocoBase implements Reporting() { @Override public boolean isSatisfiedBy(Task element) { @@ -104,15 +104,15 @@ public JacocoReportsContainer getReports() { } /** - * Return the validation rules set for this task. + * Return the violation rules set for this task. * - * @return Validation rules container + * @return Violation rules container * @since 3.3 */ @Nested @Incubating - public JacocoValidationRulesContainer getValidationRules() { - return validationRules; + public JacocoViolationRulesContainer getViolationRules() { + return violationRules; } /** @@ -130,19 +130,22 @@ public JacocoReportsContainer reports(Action con } /** - * Configures the validation rules for this task. + * Configures the violation rules for this task. Requires JaCoCo version >= 0.6.3. * * @since 3.3 */ @Incubating - public JacocoValidationRulesContainer validationRules(Closure closure) { - return validationRules(new ClosureBackedAction(closure)); + public JacocoViolationRulesContainer violationRules(Closure closure) { + return violationRules(new ClosureBackedAction(closure)); } + /** + * @since 3.3 + */ @Incubating - public JacocoValidationRulesContainer validationRules(Action configureAction) { - configureAction.execute(validationRules); - return validationRules; + public JacocoViolationRulesContainer violationRules(Action configureAction) { + configureAction.execute(violationRules); + return violationRules; } /** @@ -227,7 +230,7 @@ public boolean isSatisfiedBy(File file) { getAllSourceDirs().filter(fileExistsSpec), getExecutionData(), getReports(), - getValidationRules() + getViolationRules() ); } diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoValidationRule.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java similarity index 96% rename from subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoValidationRule.java rename to subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java index 94ea6979bdc8..c8ec89abc54c 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoValidationRule.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java @@ -23,12 +23,12 @@ import java.util.List; /** - * A validation rule. + * Jacoco violation rule. * * @since 3.3 */ @Incubating -public interface JacocoValidationRule { +public interface JacocoViolationRule { void setEnabled(boolean enabled); diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoValidationRulesContainer.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRulesContainer.java similarity index 68% rename from subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoValidationRulesContainer.java rename to subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRulesContainer.java index 75c1f440ccaf..ecac8f17eef4 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoValidationRulesContainer.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRulesContainer.java @@ -24,12 +24,12 @@ import java.util.List; /** - * The validation rules configuration for the {@link org.gradle.testing.jacoco.tasks.JacocoReport} task. + * The violation rules configuration for the {@link org.gradle.testing.jacoco.tasks.JacocoReport} task. * * @since 3.3 */ @Incubating -public interface JacocoValidationRulesContainer { +public interface JacocoViolationRulesContainer { void setFailOnViolation(boolean ignore); @@ -40,15 +40,15 @@ public interface JacocoValidationRulesContainer { boolean isFailOnViolation(); /** - * Gets all validation rules. Defaults to an empty list. + * Gets all violation rules. Defaults to an empty list. */ @Internal - List getRules(); + List getRules(); /** - * Adds a validation rule. There's no limitation to the number of rules that can be added. + * Adds a violation rule. There's no limitation to the number of rules that can be added. */ - JacocoValidationRule rule(Closure configureClosure); + JacocoViolationRule rule(Closure configureClosure); - JacocoValidationRule rule(Action configureAction); + JacocoViolationRule rule(Action configureAction); } diff --git a/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoThresholdImplTest.groovy b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoThresholdImplTest.groovy index a95b0d0497ef..c8d6c87d17eb 100644 --- a/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoThresholdImplTest.groovy +++ b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoThresholdImplTest.groovy @@ -16,6 +16,8 @@ package org.gradle.internal.jacoco.rules +import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric +import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdValue import spock.lang.Specification class JacocoThresholdImplTest extends Specification { @@ -24,8 +26,8 @@ class JacocoThresholdImplTest extends Specification { def "provides expected default field values"() { expect: - !threshold.metric - !threshold.value + threshold.metric == JacocoThresholdMetric.INSTRUCTION + threshold.value == JacocoThresholdValue.COVEREDRATIO !threshold.minimum !threshold.maximum } diff --git a/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoValidationRuleImplTest.groovy b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoViolationRuleImplTest.groovy similarity index 90% rename from subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoValidationRuleImplTest.groovy rename to subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoViolationRuleImplTest.groovy index a9f692664c54..bbef0ac7ff6c 100644 --- a/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoValidationRuleImplTest.groovy +++ b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoViolationRuleImplTest.groovy @@ -17,20 +17,21 @@ package org.gradle.internal.jacoco.rules import org.gradle.api.Action +import org.gradle.testing.jacoco.tasks.rules.JacocoRuleScope import org.gradle.testing.jacoco.tasks.rules.JacocoThreshold import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdValue import spock.lang.Specification -class JacocoValidationRuleImplTest extends Specification { +class JacocoViolationRuleImplTest extends Specification { - JacocoValidationRuleImpl rule = new JacocoValidationRuleImpl() + JacocoViolationRuleImpl rule = new JacocoViolationRuleImpl() def "provides expected default field values"() { expect: rule.enabled - !rule.scope - rule.includes == [] + rule.scope == JacocoRuleScope.BUNDLE + rule.includes == ['*'] rule.excludes == [] } diff --git a/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoValidationRulesContainerImplTest.groovy b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoViolationRulesContainerImplTest.groovy similarity index 65% rename from subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoValidationRulesContainerImplTest.groovy rename to subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoViolationRulesContainerImplTest.groovy index ecb08360bd6e..610dbd217057 100644 --- a/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoValidationRulesContainerImplTest.groovy +++ b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoViolationRulesContainerImplTest.groovy @@ -18,22 +18,22 @@ package org.gradle.internal.jacoco.rules import org.gradle.api.Action import org.gradle.testing.jacoco.tasks.rules.JacocoRuleScope -import org.gradle.testing.jacoco.tasks.rules.JacocoValidationRule +import org.gradle.testing.jacoco.tasks.rules.JacocoViolationRule import spock.lang.Specification -class JacocoValidationRulesContainerImplTest extends Specification { +class JacocoViolationRulesContainerImplTest extends Specification { - JacocoValidationRulesContainerImpl validationRulesContainer = new JacocoValidationRulesContainerImpl() + JacocoViolationRulesContainerImpl violationRulesContainer = new JacocoViolationRulesContainerImpl() def "provides expected default field values"() { expect: - !validationRulesContainer.failOnViolation - validationRulesContainer.rules.empty + !violationRulesContainer.failOnViolation + violationRulesContainer.rules.empty } def "can add rules"() { when: - def rule = validationRulesContainer.rule { + def rule = violationRulesContainer.rule { enabled = false scope = JacocoRuleScope.CLASS includes = ['**/*.class'] @@ -41,13 +41,13 @@ class JacocoValidationRulesContainerImplTest extends Specification { } then: - validationRulesContainer.rules.size() == 1 - validationRulesContainer.rules[0] == rule + violationRulesContainer.rules.size() == 1 + violationRulesContainer.rules[0] == rule when: - rule = validationRulesContainer.rule(new Action() { + rule = violationRulesContainer.rule(new Action() { @Override - void execute(JacocoValidationRule jacocoValidationRule) { + void execute(JacocoViolationRule jacocoValidationRule) { jacocoValidationRule.with { enabled = true scope = JacocoRuleScope.PACKAGE @@ -58,13 +58,13 @@ class JacocoValidationRulesContainerImplTest extends Specification { }) then: - validationRulesContainer.rules.size() == 2 - validationRulesContainer.rules[1] == rule + violationRulesContainer.rules.size() == 2 + violationRulesContainer.rules[1] == rule } def "returned rules are unmodifiable"() { when: - validationRulesContainer.rules << new JacocoValidationRuleImpl() + violationRulesContainer.rules << new JacocoViolationRuleImpl() then: thrown(UnsupportedOperationException) From 9b5ed0a2bc3dfebfaea77a76220804f509e408a6 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Fri, 2 Dec 2016 14:48:38 -0700 Subject: [PATCH 13/42] Rename field --- ...cocoPluginCheckCoverageIntegrationTest.groovy | 12 ++++++------ .../gradle/internal/jacoco/AntJacocoReport.java | 4 ++-- .../jacoco/rules/JacocoThresholdImpl.java | 16 ++++++++-------- .../testing/jacoco/tasks/JacocoReport.java | 2 ++ .../jacoco/tasks/rules/JacocoThreshold.java | 10 +++++----- ...esholdValue.java => JacocoThresholdType.java} | 4 ++-- .../jacoco/tasks/rules/JacocoViolationRule.java | 4 ++-- .../rules/JacocoViolationRulesContainer.java | 2 +- .../jacoco/rules/JacocoThresholdImplTest.groovy | 4 ++-- .../rules/JacocoViolationRuleImplTest.groovy | 6 +++--- 10 files changed, 33 insertions(+), 31 deletions(-) rename subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/{JacocoThresholdValue.java => JacocoThresholdType.java} (92%) diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy index 3d96c00412ba..338262046be9 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy @@ -19,13 +19,13 @@ package org.gradle.testing.jacoco.plugins import org.gradle.integtests.fixtures.AbstractIntegrationSpec import org.gradle.testing.jacoco.plugins.fixtures.JavaProjectUnderTest import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric -import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdValue +import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdType import spock.lang.Unroll import static org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric.CLASS import static org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric.LINE -import static org.gradle.testing.jacoco.tasks.rules.JacocoThresholdValue.COVEREDRATIO -import static org.gradle.testing.jacoco.tasks.rules.JacocoThresholdValue.MISSEDCOUNT +import static JacocoThresholdType.COVEREDRATIO +import static JacocoThresholdType.MISSEDCOUNT class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { @@ -329,15 +329,15 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { static final String CLASS_METRIC_MISSED_COUNT = Thresholds.create(CLASS, MISSEDCOUNT, '0.5', null) } - private static String create(JacocoThresholdMetric metric, JacocoThresholdValue value, String minimum, String maximum) { + private static String create(JacocoThresholdMetric metric, JacocoThresholdType type, String minimum, String maximum) { StringBuilder threshold = new StringBuilder() threshold <<= 'threshold {\n' if (metric) { threshold <<= " metric = ${metric.getClass().getName()}.${metric.name()}\n" } - if (value) { - threshold <<= " value = ${value.getClass().getName()}.${value.name()}\n" + if (type) { + threshold <<= " type = ${type.getClass().getName()}.${type.name()}\n" } if (minimum) { threshold <<= " minimum = $minimum\n" diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java index 74b19358e7b5..b4d303bab5b1 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java @@ -141,8 +141,8 @@ public Object doCall(Object ignore) { if (threshold.getMetric() != null) { ruleArgs.put("counter", threshold.getMetric().name()); } - if (threshold.getValue() != null) { - ruleArgs.put("value", threshold.getValue().name()); + if (threshold.getType() != null) { + ruleArgs.put("value", threshold.getType().name()); } if (threshold.getMinimum() != null) { ruleArgs.put("minimum", threshold.getMinimum()); diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoThresholdImpl.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoThresholdImpl.java index ae7f38584485..5bef7d1c9dac 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoThresholdImpl.java +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoThresholdImpl.java @@ -18,12 +18,12 @@ import org.gradle.testing.jacoco.tasks.rules.JacocoThreshold; import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric; -import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdValue; +import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdType; public class JacocoThresholdImpl implements JacocoThreshold { private JacocoThresholdMetric metric = JacocoThresholdMetric.INSTRUCTION; - private JacocoThresholdValue value = JacocoThresholdValue.COVEREDRATIO; + private JacocoThresholdType type = JacocoThresholdType.COVEREDRATIO; private Double minimum; private Double maximum; @@ -38,13 +38,13 @@ public void setMetric(JacocoThresholdMetric metric) { } @Override - public JacocoThresholdValue getValue() { - return value; + public JacocoThresholdType getType() { + return type; } @Override - public void setValue(JacocoThresholdValue value) { - this.value = value; + public void setType(JacocoThresholdType type) { + this.type = type; } @Override @@ -81,7 +81,7 @@ public boolean equals(Object o) { if (metric != that.metric) { return false; } - if (value != that.value) { + if (type != that.type) { return false; } if (minimum != null ? !minimum.equals(that.minimum) : that.minimum != null) { @@ -93,7 +93,7 @@ public boolean equals(Object o) { @Override public int hashCode() { int result = metric != null ? metric.hashCode() : 0; - result = 31 * result + (value != null ? value.hashCode() : 0); + result = 31 * result + (type != null ? type.hashCode() : 0); result = 31 * result + (minimum != null ? minimum.hashCode() : 0); result = 31 * result + (maximum != null ? maximum.hashCode() : 0); return result; diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java index 358ea8e7d7d4..1840a8ccc109 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java @@ -140,6 +140,8 @@ public JacocoViolationRulesContainer violationRules(Closure closure) { } /** + * Configures the violation rules for this task. Requires JaCoCo version >= 0.6.3. + * * @since 3.3 */ @Incubating diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThreshold.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThreshold.java index d923443f4a8f..6aeb27fa81df 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThreshold.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThreshold.java @@ -19,7 +19,7 @@ import org.gradle.api.Incubating; /** - * A Jacoco threshold. + * Jacoco threshold. * * @since 3.3 */ @@ -27,18 +27,18 @@ public interface JacocoThreshold { /** - * The metric that applies to the threshold defined by {@link JacocoThresholdMetric}. + * The metric that applies to the threshold defined by {@link JacocoThresholdMetric}. Defaults to INSTRUCTION. */ JacocoThresholdMetric getMetric(); void setMetric(JacocoThresholdMetric metric); /** - * The value that applies to the threshold defined by {@link JacocoThresholdValue}. + * The value that applies to the threshold defined by {@link JacocoThresholdType}. Defaults to COVEREDRATIO. */ - JacocoThresholdValue getValue(); + JacocoThresholdType getType(); - void setValue(JacocoThresholdValue value); + void setType(JacocoThresholdType type); /** * Gets the minimum expected value for threshold. Default to null. diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdValue.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdType.java similarity index 92% rename from subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdValue.java rename to subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdType.java index 809eb106dc61..e4297dde72e7 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdValue.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdType.java @@ -19,11 +19,11 @@ import org.gradle.api.Incubating; /** - * Jacoco threshold values. + * Jacoco threshold types. * * @since 3.3 */ @Incubating -public enum JacocoThresholdValue { +public enum JacocoThresholdType { TOTALCOUNT, MISSEDCOUNT, COVEREDCOUNT, MISSEDRATIO, COVEREDRATIO; } diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java index c8ec89abc54c..a26761d718e3 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java @@ -40,7 +40,7 @@ public interface JacocoViolationRule { void setScope(JacocoRuleScope scope); /** - * Gets the scope for the rule defined by {@link JacocoRuleScope}. + * Gets the scope for the rule defined by {@link JacocoRuleScope}. Defaults to BUNDLE. */ JacocoRuleScope getScope(); @@ -48,7 +48,7 @@ public interface JacocoViolationRule { /** * List of elements that should be included in check. Names can use wildcards (* and ?). - * If left empty, all elements will be included. Defaults to an empty list. + * If left empty, all elements will be included. Defaults to [*]. */ List getIncludes(); diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRulesContainer.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRulesContainer.java index ecac8f17eef4..856b6ad991c4 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRulesContainer.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRulesContainer.java @@ -34,7 +34,7 @@ public interface JacocoViolationRulesContainer { void setFailOnViolation(boolean ignore); /** - * Specifies whether build should fail in case of rule violations. + * Specifies whether build should fail in case of rule violations. Defaults to true. */ @Internal boolean isFailOnViolation(); diff --git a/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoThresholdImplTest.groovy b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoThresholdImplTest.groovy index c8d6c87d17eb..f5f5fabe4f90 100644 --- a/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoThresholdImplTest.groovy +++ b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoThresholdImplTest.groovy @@ -17,7 +17,7 @@ package org.gradle.internal.jacoco.rules import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric -import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdValue +import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdType import spock.lang.Specification class JacocoThresholdImplTest extends Specification { @@ -27,7 +27,7 @@ class JacocoThresholdImplTest extends Specification { def "provides expected default field values"() { expect: threshold.metric == JacocoThresholdMetric.INSTRUCTION - threshold.value == JacocoThresholdValue.COVEREDRATIO + threshold.type == JacocoThresholdType.COVEREDRATIO !threshold.minimum !threshold.maximum } diff --git a/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoViolationRuleImplTest.groovy b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoViolationRuleImplTest.groovy index bbef0ac7ff6c..eb622996d5e4 100644 --- a/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoViolationRuleImplTest.groovy +++ b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoViolationRuleImplTest.groovy @@ -20,7 +20,7 @@ import org.gradle.api.Action import org.gradle.testing.jacoco.tasks.rules.JacocoRuleScope import org.gradle.testing.jacoco.tasks.rules.JacocoThreshold import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric -import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdValue +import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdType import spock.lang.Specification class JacocoViolationRuleImplTest extends Specification { @@ -39,7 +39,7 @@ class JacocoViolationRuleImplTest extends Specification { when: def threshold = rule.threshold { metric = JacocoThresholdMetric.CLASS - value = JacocoThresholdValue.TOTALCOUNT + type = JacocoThresholdType.TOTALCOUNT minimum = 0.0 maximum = 1.0 } @@ -54,7 +54,7 @@ class JacocoViolationRuleImplTest extends Specification { void execute(JacocoThreshold jacocoThreshold) { jacocoThreshold.with { metric = JacocoThresholdMetric.COMPLEXITY - value = JacocoThresholdValue.MISSEDCOUNT + type = JacocoThresholdType.MISSEDCOUNT minimum = 0.2 maximum = 0.6 } From 358a6f9e012a4db7e83e3dd9a50b5714f56ccc7b Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Mon, 5 Dec 2016 16:11:36 -0500 Subject: [PATCH 14/42] Enhance samples and documentation --- .../docs/src/docs/userguide/jacocoPlugin.xml | 21 ++++++++++++++ .../testing/jacoco/quickstart/build.gradle | 28 +++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/subprojects/docs/src/docs/userguide/jacocoPlugin.xml b/subprojects/docs/src/docs/userguide/jacocoPlugin.xml index 8b1fd38fabae..ba9e78e0645b 100644 --- a/subprojects/docs/src/docs/userguide/jacocoPlugin.xml +++ b/subprojects/docs/src/docs/userguide/jacocoPlugin.xml @@ -81,6 +81,27 @@ +
+ Enforcing code coverage metrics + + Every task of type can be configured to verify if code coverage + metrics are met based on configured rules. The methods + and + + are the main entry point of configuring rules. + It returns an instance of which provides + extensive configuration options. The build fails if any of the configured rules is not met. JaCoCo only reports the first violated rule. + + + Code coverage requirements can be specified for a project as a whole, for individual files, and for + particular JaCoCo-specific types of coverage, e.g., lines covered or branches covered. The following example + describes the syntax. + + + + +
+
JaCoCo specific task configuration The JaCoCo plugin adds a diff --git a/subprojects/docs/src/samples/testing/jacoco/quickstart/build.gradle b/subprojects/docs/src/samples/testing/jacoco/quickstart/build.gradle index 29919b774be7..6d916d1dd3ea 100644 --- a/subprojects/docs/src/samples/testing/jacoco/quickstart/build.gradle +++ b/subprojects/docs/src/samples/testing/jacoco/quickstart/build.gradle @@ -56,3 +56,31 @@ jacocoTestReport { } } // END SNIPPET report-configuration + +// START SNIPPET violation-rules-configuration +import org.gradle.testing.jacoco.tasks.rules.JacocoRuleScope +import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric +import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdType + +jacocoTestReport { + violationRules { + rule { + threshold { + minimum = 0.5 + } + } + + rule { + enabled = false + scope = JacocoRuleScope.CLASS + includes = ['org.gradle.*'] + + threshold { + metric = JacocoThresholdMetric.LINE + type = JacocoThresholdType.TOTALCOUNT + maximum = 0.3 + } + } + } +} +// END SNIPPET violation-rules-configuration From a73a1930bf96e44d1f5c31dbee68448b42db9c58 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Mon, 5 Dec 2016 16:20:08 -0500 Subject: [PATCH 15/42] Better IDE support for Closure parameters --- .../java/org/gradle/testing/jacoco/tasks/JacocoReport.java | 5 ++++- .../testing/jacoco/tasks/rules/JacocoViolationRule.java | 5 ++++- .../jacoco/tasks/rules/JacocoViolationRulesContainer.java | 5 ++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java index 1840a8ccc109..9b249913ddf3 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java @@ -18,6 +18,7 @@ import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import groovy.lang.Closure; +import groovy.lang.DelegatesTo; import org.gradle.api.Action; import org.gradle.api.Incubating; import org.gradle.api.Project; @@ -49,6 +50,8 @@ import java.util.Arrays; import java.util.concurrent.Callable; +import static groovy.lang.Closure.DELEGATE_FIRST; + /** * Task to generate HTML, Xml and CSV reports of Jacoco coverage data. */ @@ -135,7 +138,7 @@ public JacocoReportsContainer reports(Action con * @since 3.3 */ @Incubating - public JacocoViolationRulesContainer violationRules(Closure closure) { + public JacocoViolationRulesContainer violationRules(@DelegatesTo(value = JacocoViolationRulesContainer.class, strategy = DELEGATE_FIRST) Closure closure) { return violationRules(new ClosureBackedAction(closure)); } diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java index a26761d718e3..0a968367f4f4 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java @@ -17,11 +17,14 @@ package org.gradle.testing.jacoco.tasks.rules; import groovy.lang.Closure; +import groovy.lang.DelegatesTo; import org.gradle.api.Action; import org.gradle.api.Incubating; import java.util.List; +import static groovy.lang.Closure.DELEGATE_FIRST; + /** * Jacoco violation rule. * @@ -68,7 +71,7 @@ public interface JacocoViolationRule { /** * Adds a threshold for this rule. There's no limitation to the number of thresholds that can be added. */ - JacocoThreshold threshold(Closure configureClosure); + JacocoThreshold threshold(@DelegatesTo(value = JacocoThreshold.class, strategy = DELEGATE_FIRST) Closure configureClosure); JacocoThreshold threshold(Action configureAction); } diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRulesContainer.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRulesContainer.java index 856b6ad991c4..b141cd73f351 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRulesContainer.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRulesContainer.java @@ -17,12 +17,15 @@ package org.gradle.testing.jacoco.tasks.rules; import groovy.lang.Closure; +import groovy.lang.DelegatesTo; import org.gradle.api.Action; import org.gradle.api.Incubating; import org.gradle.api.tasks.Internal; import java.util.List; +import static groovy.lang.Closure.DELEGATE_FIRST; + /** * The violation rules configuration for the {@link org.gradle.testing.jacoco.tasks.JacocoReport} task. * @@ -48,7 +51,7 @@ public interface JacocoViolationRulesContainer { /** * Adds a violation rule. There's no limitation to the number of rules that can be added. */ - JacocoViolationRule rule(Closure configureClosure); + JacocoViolationRule rule(@DelegatesTo(value = JacocoViolationRule.class, strategy = DELEGATE_FIRST) Closure configureClosure); JacocoViolationRule rule(Action configureAction); } From 6627b4942eafdb97321fc2c64a31d4aa44d73704 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Mon, 5 Dec 2016 16:22:18 -0500 Subject: [PATCH 16/42] Bump up version number --- .../java/org/gradle/testing/jacoco/tasks/JacocoReport.java | 6 +++--- .../gradle/testing/jacoco/tasks/rules/JacocoRuleScope.java | 2 +- .../gradle/testing/jacoco/tasks/rules/JacocoThreshold.java | 2 +- .../testing/jacoco/tasks/rules/JacocoThresholdMetric.java | 2 +- .../testing/jacoco/tasks/rules/JacocoThresholdType.java | 2 +- .../testing/jacoco/tasks/rules/JacocoViolationRule.java | 2 +- .../jacoco/tasks/rules/JacocoViolationRulesContainer.java | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java index 9b249913ddf3..897c8bd2cacb 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java @@ -110,7 +110,7 @@ public JacocoReportsContainer getReports() { * Return the violation rules set for this task. * * @return Violation rules container - * @since 3.3 + * @since 4.0 */ @Nested @Incubating @@ -135,7 +135,7 @@ public JacocoReportsContainer reports(Action con /** * Configures the violation rules for this task. Requires JaCoCo version >= 0.6.3. * - * @since 3.3 + * @since 4.0 */ @Incubating public JacocoViolationRulesContainer violationRules(@DelegatesTo(value = JacocoViolationRulesContainer.class, strategy = DELEGATE_FIRST) Closure closure) { @@ -145,7 +145,7 @@ public JacocoViolationRulesContainer violationRules(@DelegatesTo(value = JacocoV /** * Configures the violation rules for this task. Requires JaCoCo version >= 0.6.3. * - * @since 3.3 + * @since 4.0 */ @Incubating public JacocoViolationRulesContainer violationRules(Action configureAction) { diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoRuleScope.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoRuleScope.java index 91a4da7c1bd2..e67dee2ca9cf 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoRuleScope.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoRuleScope.java @@ -21,7 +21,7 @@ /** * Jacoco rule scopes. * - * @since 3.3 + * @since 4.0 */ @Incubating public enum JacocoRuleScope { diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThreshold.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThreshold.java index 6aeb27fa81df..999d4b89a48a 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThreshold.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThreshold.java @@ -21,7 +21,7 @@ /** * Jacoco threshold. * - * @since 3.3 + * @since 4.0 */ @Incubating public interface JacocoThreshold { diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdMetric.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdMetric.java index a02e93eb5db0..7b018c9f5a76 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdMetric.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdMetric.java @@ -21,7 +21,7 @@ /** * Jacoco threshold metrics. * - * @since 3.3 + * @since 4.0 */ @Incubating public enum JacocoThresholdMetric { diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdType.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdType.java index e4297dde72e7..6dff78b5957a 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdType.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdType.java @@ -21,7 +21,7 @@ /** * Jacoco threshold types. * - * @since 3.3 + * @since 4.0 */ @Incubating public enum JacocoThresholdType { diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java index 0a968367f4f4..72d8c4bf69bb 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java @@ -28,7 +28,7 @@ /** * Jacoco violation rule. * - * @since 3.3 + * @since 4.0 */ @Incubating public interface JacocoViolationRule { diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRulesContainer.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRulesContainer.java index b141cd73f351..7d3a2bc1edf5 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRulesContainer.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRulesContainer.java @@ -29,7 +29,7 @@ /** * The violation rules configuration for the {@link org.gradle.testing.jacoco.tasks.JacocoReport} task. * - * @since 3.3 + * @since 4.0 */ @Incubating public interface JacocoViolationRulesContainer { From 8e6d20c945767d29bdcaa7ec211b4531da42340f Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Mon, 5 Dec 2016 16:57:48 -0500 Subject: [PATCH 17/42] Use String data type instead of enum Allows for better forward and backward capability in case JaCoCo decides to introduce new values or change existing ones. --- .../testing/jacoco/quickstart/build.gradle | 10 ++----- ...oPluginCheckCoverageIntegrationTest.groovy | 24 +++++---------- .../internal/jacoco/AntJacocoReport.java | 4 +-- .../jacoco/rules/JacocoThresholdImpl.java | 14 ++++----- .../jacoco/rules/JacocoViolationRuleImpl.java | 7 ++--- .../jacoco/tasks/rules/JacocoRuleScope.java | 29 ------------------- .../jacoco/tasks/rules/JacocoThreshold.java | 16 ++++++---- .../tasks/rules/JacocoThresholdMetric.java | 29 ------------------- .../tasks/rules/JacocoThresholdType.java | 29 ------------------- .../tasks/rules/JacocoViolationRule.java | 8 +++-- .../rules/JacocoThresholdImplTest.groovy | 6 ++-- .../rules/JacocoViolationRuleImplTest.groovy | 13 ++++----- ...cocoViolationRulesContainerImplTest.groovy | 5 ++-- 13 files changed, 46 insertions(+), 148 deletions(-) delete mode 100644 subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoRuleScope.java delete mode 100644 subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdMetric.java delete mode 100644 subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdType.java diff --git a/subprojects/docs/src/samples/testing/jacoco/quickstart/build.gradle b/subprojects/docs/src/samples/testing/jacoco/quickstart/build.gradle index 6d916d1dd3ea..32dc7d1fdd8b 100644 --- a/subprojects/docs/src/samples/testing/jacoco/quickstart/build.gradle +++ b/subprojects/docs/src/samples/testing/jacoco/quickstart/build.gradle @@ -58,10 +58,6 @@ jacocoTestReport { // END SNIPPET report-configuration // START SNIPPET violation-rules-configuration -import org.gradle.testing.jacoco.tasks.rules.JacocoRuleScope -import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric -import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdType - jacocoTestReport { violationRules { rule { @@ -72,12 +68,12 @@ jacocoTestReport { rule { enabled = false - scope = JacocoRuleScope.CLASS + scope = 'CLASS' includes = ['org.gradle.*'] threshold { - metric = JacocoThresholdMetric.LINE - type = JacocoThresholdType.TOTALCOUNT + metric = 'LINE' + type = 'TOTALCOUNT' maximum = 0.3 } } diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy index 338262046be9..7b2cb624ca7e 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy @@ -18,15 +18,8 @@ package org.gradle.testing.jacoco.plugins import org.gradle.integtests.fixtures.AbstractIntegrationSpec import org.gradle.testing.jacoco.plugins.fixtures.JavaProjectUnderTest -import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric -import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdType import spock.lang.Unroll -import static org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric.CLASS -import static org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric.LINE -import static JacocoThresholdType.COVEREDRATIO -import static JacocoThresholdType.MISSEDCOUNT - class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { private final JavaProjectUnderTest javaProjectUnderTest = new JavaProjectUnderTest(testDirectory) @@ -71,12 +64,11 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { def "can define includes for single rule"() { given: - String scope = "${org.gradle.testing.jacoco.tasks.rules.JacocoRuleScope.CLASS.getClass().getName()}.${org.gradle.testing.jacoco.tasks.rules.JacocoRuleScope.CLASS.name()}" buildFile << """ jacocoTestReport { violationRules { rule { - scope = $scope + scope = 'CLASS' includes = ['com.company.*', 'org.gradle.*'] $Thresholds.Insufficient.LINE_METRIC_COVERED_RATIO } @@ -320,24 +312,24 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { static class Thresholds { static class Sufficient { - static final String LINE_METRIC_COVERED_RATIO = Thresholds.create(LINE, COVEREDRATIO, '0.0', '1.0') - static final String CLASS_METRIC_MISSED_COUNT = Thresholds.create(CLASS, MISSEDCOUNT, null, '0') + static final String LINE_METRIC_COVERED_RATIO = Thresholds.create('LINE', 'COVEREDRATIO', '0.0', '1.0') + static final String CLASS_METRIC_MISSED_COUNT = Thresholds.create('CLASS', 'MISSEDCOUNT', null, '0') } static class Insufficient { - static final String LINE_METRIC_COVERED_RATIO = Thresholds.create(LINE, COVEREDRATIO, '0.0', '0.5') - static final String CLASS_METRIC_MISSED_COUNT = Thresholds.create(CLASS, MISSEDCOUNT, '0.5', null) + static final String LINE_METRIC_COVERED_RATIO = Thresholds.create('LINE', 'COVEREDRATIO', '0.0', '0.5') + static final String CLASS_METRIC_MISSED_COUNT = Thresholds.create('CLASS', 'MISSEDCOUNT', '0.5', null) } - private static String create(JacocoThresholdMetric metric, JacocoThresholdType type, String minimum, String maximum) { + private static String create(String metric, String type, String minimum, String maximum) { StringBuilder threshold = new StringBuilder() threshold <<= 'threshold {\n' if (metric) { - threshold <<= " metric = ${metric.getClass().getName()}.${metric.name()}\n" + threshold <<= " metric = '${metric}'\n" } if (type) { - threshold <<= " type = ${type.getClass().getName()}.${type.name()}\n" + threshold <<= " type = '${type}'\n" } if (minimum) { threshold <<= " minimum = $minimum\n" diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java index b4d303bab5b1..5d1c92401f39 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java @@ -139,10 +139,10 @@ public Object doCall(Object ignore) { Map ruleArgs = new HashMap(); if (threshold.getMetric() != null) { - ruleArgs.put("counter", threshold.getMetric().name()); + ruleArgs.put("counter", threshold.getMetric()); } if (threshold.getType() != null) { - ruleArgs.put("value", threshold.getType().name()); + ruleArgs.put("value", threshold.getType()); } if (threshold.getMinimum() != null) { ruleArgs.put("minimum", threshold.getMinimum()); diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoThresholdImpl.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoThresholdImpl.java index 5bef7d1c9dac..568ba6c1642e 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoThresholdImpl.java +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoThresholdImpl.java @@ -17,33 +17,31 @@ package org.gradle.internal.jacoco.rules; import org.gradle.testing.jacoco.tasks.rules.JacocoThreshold; -import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric; -import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdType; public class JacocoThresholdImpl implements JacocoThreshold { - private JacocoThresholdMetric metric = JacocoThresholdMetric.INSTRUCTION; - private JacocoThresholdType type = JacocoThresholdType.COVEREDRATIO; + private String metric = "INSTRUCTION"; + private String type = "COVEREDRATIO"; private Double minimum; private Double maximum; @Override - public JacocoThresholdMetric getMetric() { + public String getMetric() { return metric; } @Override - public void setMetric(JacocoThresholdMetric metric) { + public void setMetric(String metric) { this.metric = metric; } @Override - public JacocoThresholdType getType() { + public String getType() { return type; } @Override - public void setType(JacocoThresholdType type) { + public void setType(String type) { this.type = type; } diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoViolationRuleImpl.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoViolationRuleImpl.java index 7abc51414fcb..c298e4556537 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoViolationRuleImpl.java +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoViolationRuleImpl.java @@ -20,7 +20,6 @@ import groovy.lang.Closure; import org.gradle.api.Action; import org.gradle.api.internal.ClosureBackedAction; -import org.gradle.testing.jacoco.tasks.rules.JacocoRuleScope; import org.gradle.testing.jacoco.tasks.rules.JacocoThreshold; import org.gradle.testing.jacoco.tasks.rules.JacocoViolationRule; @@ -31,7 +30,7 @@ public class JacocoViolationRuleImpl implements JacocoViolationRule { private boolean enabled = true; - private JacocoRuleScope scope = JacocoRuleScope.BUNDLE; + private String scope = "BUNDLE"; private List includes = ImmutableList.of("*"); private List excludes = ImmutableList.of(); private final List thresholds = new ArrayList(); @@ -47,12 +46,12 @@ public void setEnabled(boolean enabled) { } @Override - public void setScope(JacocoRuleScope scope) { + public void setScope(String scope) { this.scope = scope; } @Override - public JacocoRuleScope getScope() { + public String getScope() { return scope; } diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoRuleScope.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoRuleScope.java deleted file mode 100644 index e67dee2ca9cf..000000000000 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoRuleScope.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.testing.jacoco.tasks.rules; - -import org.gradle.api.Incubating; - -/** - * Jacoco rule scopes. - * - * @since 4.0 - */ -@Incubating -public enum JacocoRuleScope { - BUNDLE, PACKAGE, CLASS, SOURCEFILE, METHOD; -} diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThreshold.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThreshold.java index 999d4b89a48a..13796f8494a1 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThreshold.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThreshold.java @@ -27,18 +27,22 @@ public interface JacocoThreshold { /** - * The metric that applies to the threshold defined by {@link JacocoThresholdMetric}. Defaults to INSTRUCTION. + * The metric that applies to the threshold as defined by + * org.jacoco.core.analysis.ICoverageNode.CounterEntity. + * Valid values are INSTRUCTION, LINE, BRANCH, COMPLEXITY, METHOD and CLASS. Defaults to INSTRUCTION. */ - JacocoThresholdMetric getMetric(); + String getMetric(); - void setMetric(JacocoThresholdMetric metric); + void setMetric(String metric); /** - * The value that applies to the threshold defined by {@link JacocoThresholdType}. Defaults to COVEREDRATIO. + * The value that applies to the threshold as defined by + * org.jacoco.core.analysis.ICounter.CounterValue. + * Valid values are TOTALCOUNT, MISSEDCOUNT, COVEREDCOUNT, MISSEDRATIO and COVEREDRATIO. Defaults to COVEREDRATIO. */ - JacocoThresholdType getType(); + String getType(); - void setType(JacocoThresholdType type); + void setType(String type); /** * Gets the minimum expected value for threshold. Default to null. diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdMetric.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdMetric.java deleted file mode 100644 index 7b018c9f5a76..000000000000 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdMetric.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.testing.jacoco.tasks.rules; - -import org.gradle.api.Incubating; - -/** - * Jacoco threshold metrics. - * - * @since 4.0 - */ -@Incubating -public enum JacocoThresholdMetric { - INSTRUCTION, LINE, BRANCH, COMPLEXITY, METHOD, CLASS; -} diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdType.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdType.java deleted file mode 100644 index 6dff78b5957a..000000000000 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThresholdType.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.gradle.testing.jacoco.tasks.rules; - -import org.gradle.api.Incubating; - -/** - * Jacoco threshold types. - * - * @since 4.0 - */ -@Incubating -public enum JacocoThresholdType { - TOTALCOUNT, MISSEDCOUNT, COVEREDCOUNT, MISSEDRATIO, COVEREDRATIO; -} diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java index 72d8c4bf69bb..59a3d48d3d83 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java @@ -40,12 +40,14 @@ public interface JacocoViolationRule { */ boolean isEnabled(); - void setScope(JacocoRuleScope scope); + void setScope(String scope); /** - * Gets the scope for the rule defined by {@link JacocoRuleScope}. Defaults to BUNDLE. + * Gets the scope for the rule as defined by + * org.jacoco.core.analysis.ICoverageNode.ElementType. + * Valid scope values are BUNDLE, PACKAGE, CLASS, SOURCEFILE and METHOD. Defaults to BUNDLE. */ - JacocoRuleScope getScope(); + String getScope(); void setIncludes(List includes); diff --git a/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoThresholdImplTest.groovy b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoThresholdImplTest.groovy index f5f5fabe4f90..28a29e243322 100644 --- a/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoThresholdImplTest.groovy +++ b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoThresholdImplTest.groovy @@ -16,8 +16,6 @@ package org.gradle.internal.jacoco.rules -import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric -import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdType import spock.lang.Specification class JacocoThresholdImplTest extends Specification { @@ -26,8 +24,8 @@ class JacocoThresholdImplTest extends Specification { def "provides expected default field values"() { expect: - threshold.metric == JacocoThresholdMetric.INSTRUCTION - threshold.type == JacocoThresholdType.COVEREDRATIO + threshold.metric == 'INSTRUCTION' + threshold.type == 'COVEREDRATIO' !threshold.minimum !threshold.maximum } diff --git a/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoViolationRuleImplTest.groovy b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoViolationRuleImplTest.groovy index eb622996d5e4..549a971d86b7 100644 --- a/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoViolationRuleImplTest.groovy +++ b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoViolationRuleImplTest.groovy @@ -17,10 +17,7 @@ package org.gradle.internal.jacoco.rules import org.gradle.api.Action -import org.gradle.testing.jacoco.tasks.rules.JacocoRuleScope import org.gradle.testing.jacoco.tasks.rules.JacocoThreshold -import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdMetric -import org.gradle.testing.jacoco.tasks.rules.JacocoThresholdType import spock.lang.Specification class JacocoViolationRuleImplTest extends Specification { @@ -30,7 +27,7 @@ class JacocoViolationRuleImplTest extends Specification { def "provides expected default field values"() { expect: rule.enabled - rule.scope == JacocoRuleScope.BUNDLE + rule.scope == 'BUNDLE' rule.includes == ['*'] rule.excludes == [] } @@ -38,8 +35,8 @@ class JacocoViolationRuleImplTest extends Specification { def "can add thresholds"() { when: def threshold = rule.threshold { - metric = JacocoThresholdMetric.CLASS - type = JacocoThresholdType.TOTALCOUNT + metric = 'CLASS' + type = 'TOTALCOUNT' minimum = 0.0 maximum = 1.0 } @@ -53,8 +50,8 @@ class JacocoViolationRuleImplTest extends Specification { @Override void execute(JacocoThreshold jacocoThreshold) { jacocoThreshold.with { - metric = JacocoThresholdMetric.COMPLEXITY - type = JacocoThresholdType.MISSEDCOUNT + metric = 'COMPLEXITY' + type = 'MISSEDCOUNT' minimum = 0.2 maximum = 0.6 } diff --git a/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoViolationRulesContainerImplTest.groovy b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoViolationRulesContainerImplTest.groovy index 610dbd217057..8758f3da966d 100644 --- a/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoViolationRulesContainerImplTest.groovy +++ b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoViolationRulesContainerImplTest.groovy @@ -17,7 +17,6 @@ package org.gradle.internal.jacoco.rules import org.gradle.api.Action -import org.gradle.testing.jacoco.tasks.rules.JacocoRuleScope import org.gradle.testing.jacoco.tasks.rules.JacocoViolationRule import spock.lang.Specification @@ -35,7 +34,7 @@ class JacocoViolationRulesContainerImplTest extends Specification { when: def rule = violationRulesContainer.rule { enabled = false - scope = JacocoRuleScope.CLASS + scope = 'CLASS' includes = ['**/*.class'] excludes = ['*Special*.class'] } @@ -50,7 +49,7 @@ class JacocoViolationRulesContainerImplTest extends Specification { void execute(JacocoViolationRule jacocoValidationRule) { jacocoValidationRule.with { enabled = true - scope = JacocoRuleScope.PACKAGE + scope = 'PACKAGE' includes = ['**/*'] excludes = ['**/special/*'] } From 70b0f0af840d41c79f64497cfc25448d6152b1f6 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Mon, 5 Dec 2016 17:25:45 -0500 Subject: [PATCH 18/42] Align terminology with Jacoco configuration options Makes it easier for users to map configuration options to Jacoco documentation. Aligns the configuration options with Maven plugin and Ant tasks. --- .../testing/jacoco/quickstart/build.gradle | 10 +- ...oPluginCheckCoverageIntegrationTest.groovy | 92 +++++++++---------- .../internal/jacoco/AntJacocoReport.java | 24 ++--- ...hresholdImpl.java => JacocoLimitImpl.java} | 34 +++---- .../jacoco/rules/JacocoViolationRuleImpl.java | 32 +++---- ...{JacocoThreshold.java => JacocoLimit.java} | 20 ++-- .../tasks/rules/JacocoViolationRule.java | 18 ++-- .../rules/JacocoViolationRulesContainer.java | 2 +- .../jacoco/tasks/rules/package-info.java | 2 +- ...Test.groovy => JacocoLimitImplTest.groovy} | 12 +-- .../rules/JacocoViolationRuleImplTest.groovy | 34 +++---- ...cocoViolationRulesContainerImplTest.groovy | 4 +- 12 files changed, 142 insertions(+), 142 deletions(-) rename subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/{JacocoThresholdImpl.java => JacocoLimitImpl.java} (72%) rename subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/{JacocoThreshold.java => JacocoLimit.java} (77%) rename subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/{JacocoThresholdImplTest.groovy => JacocoLimitImplTest.groovy} (75%) diff --git a/subprojects/docs/src/samples/testing/jacoco/quickstart/build.gradle b/subprojects/docs/src/samples/testing/jacoco/quickstart/build.gradle index 32dc7d1fdd8b..401566904800 100644 --- a/subprojects/docs/src/samples/testing/jacoco/quickstart/build.gradle +++ b/subprojects/docs/src/samples/testing/jacoco/quickstart/build.gradle @@ -61,19 +61,19 @@ jacocoTestReport { jacocoTestReport { violationRules { rule { - threshold { + limit { minimum = 0.5 } } rule { enabled = false - scope = 'CLASS' + element = 'CLASS' includes = ['org.gradle.*'] - threshold { - metric = 'LINE' - type = 'TOTALCOUNT' + limit { + counter = 'LINE' + value = 'TOTALCOUNT' maximum = 0.3 } } diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy index 7b2cb624ca7e..8f6c3412d165 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy @@ -45,7 +45,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) } - def "can define single rule without thresholds"() { + def "can define single rule without limits"() { given: buildFile << """ jacocoTestReport { @@ -68,9 +68,9 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { jacocoTestReport { violationRules { rule { - scope = 'CLASS' + element = 'CLASS' includes = ['com.company.*', 'org.gradle.*'] - $Thresholds.Insufficient.LINE_METRIC_COVERED_RATIO + $Limits.Insufficient.LINE_METRIC_COVERED_RATIO } } } @@ -91,7 +91,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { violationRules { rule { excludes = ['company', '$testDirectory.name'] - $Thresholds.Insufficient.LINE_METRIC_COVERED_RATIO + $Limits.Insufficient.LINE_METRIC_COVERED_RATIO } } } @@ -115,7 +115,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { } violationRules { rule { - $Thresholds.Insufficient.LINE_METRIC_COVERED_RATIO + $Limits.Insufficient.LINE_METRIC_COVERED_RATIO } } } @@ -136,7 +136,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { jacocoTestReport { violationRules { rule { - ${thresholds.join('\n')} + ${limits.join('\n')} } } } @@ -149,11 +149,11 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) where: - thresholds | description - [Thresholds.Sufficient.LINE_METRIC_COVERED_RATIO] | 'line metric with covered ratio' - [Thresholds.Sufficient.CLASS_METRIC_MISSED_COUNT] | 'class metric with missed count' - [Thresholds.Sufficient.LINE_METRIC_COVERED_RATIO, - Thresholds.Sufficient.CLASS_METRIC_MISSED_COUNT] | 'line and class metric' + limits | description + [Limits.Sufficient.LINE_METRIC_COVERED_RATIO] | 'line metric with covered ratio' + [Limits.Sufficient.CLASS_METRIC_MISSED_COUNT] | 'class metric with missed count' + [Limits.Sufficient.LINE_METRIC_COVERED_RATIO, + Limits.Sufficient.CLASS_METRIC_MISSED_COUNT] | 'line and class metric' } @@ -164,7 +164,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { jacocoTestReport { violationRules { rule { - ${thresholds.join('\n')} + ${limits.join('\n')} } } } @@ -178,14 +178,14 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { errorOutput.contains("Rule violated for bundle $testDirectory.name: $errorMessage") where: - thresholds | description | errorMessage - [Thresholds.Insufficient.LINE_METRIC_COVERED_RATIO] | 'line metric with covered ratio' | 'lines covered ratio is 1.0, but expected maximum is 0.5' - [Thresholds.Insufficient.CLASS_METRIC_MISSED_COUNT] | 'class metric with missed count' | 'classes missed count is 0.0, but expected minimum is 0.5' - [Thresholds.Insufficient.LINE_METRIC_COVERED_RATIO, - Thresholds.Insufficient.CLASS_METRIC_MISSED_COUNT] | 'first of multiple insufficient thresholds fails' | 'lines covered ratio is 1.0, but expected maximum is 0.5' - [Thresholds.Sufficient.LINE_METRIC_COVERED_RATIO, - Thresholds.Insufficient.CLASS_METRIC_MISSED_COUNT, - Thresholds.Sufficient.CLASS_METRIC_MISSED_COUNT] | 'first insufficient threshold fails' | 'classes missed count is 0.0, but expected minimum is 0.5' + limits | description | errorMessage + [Limits.Insufficient.LINE_METRIC_COVERED_RATIO] | 'line metric with covered ratio' | 'lines covered ratio is 1.0, but expected maximum is 0.5' + [Limits.Insufficient.CLASS_METRIC_MISSED_COUNT] | 'class metric with missed count' | 'classes missed count is 0.0, but expected minimum is 0.5' + [Limits.Insufficient.LINE_METRIC_COVERED_RATIO, + Limits.Insufficient.CLASS_METRIC_MISSED_COUNT] | 'first of multiple insufficient limits fails' | 'lines covered ratio is 1.0, but expected maximum is 0.5' + [Limits.Sufficient.LINE_METRIC_COVERED_RATIO, + Limits.Insufficient.CLASS_METRIC_MISSED_COUNT, + Limits.Sufficient.CLASS_METRIC_MISSED_COUNT] | 'first insufficient limits fails' | 'classes missed count is 0.0, but expected minimum is 0.5' } def "can define multiple rules"() { @@ -194,10 +194,10 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { jacocoTestReport { violationRules { rule { - $Thresholds.Sufficient.LINE_METRIC_COVERED_RATIO + $Limits.Sufficient.LINE_METRIC_COVERED_RATIO } rule { - $Thresholds.Insufficient.CLASS_METRIC_MISSED_COUNT + $Limits.Insufficient.CLASS_METRIC_MISSED_COUNT } } } @@ -217,11 +217,11 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { jacocoTestReport { violationRules { rule { - $Thresholds.Sufficient.LINE_METRIC_COVERED_RATIO + $Limits.Sufficient.LINE_METRIC_COVERED_RATIO } rule { enabled = false - $Thresholds.Insufficient.CLASS_METRIC_MISSED_COUNT + $Limits.Insufficient.CLASS_METRIC_MISSED_COUNT } } } @@ -242,7 +242,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { failOnViolation = true rule { - $Thresholds.Insufficient.LINE_METRIC_COVERED_RATIO + $Limits.Insufficient.LINE_METRIC_COVERED_RATIO } } } @@ -265,7 +265,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { tasks.withType(JacocoReport) { violationRules { rule { - $Thresholds.Insufficient.LINE_METRIC_COVERED_RATIO + $Limits.Insufficient.LINE_METRIC_COVERED_RATIO } } } @@ -291,7 +291,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { $reportTaskName { violationRules { rule { - $threshold + $limit } } } @@ -305,41 +305,41 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { errorOutput.contains("Rule violated for bundle $testDirectory.name: $errorMessage") where: - tasksPaths | reportTaskName | threshold | errorMessage - TEST_AND_JACOCO_REPORT_TASK_PATHS | 'jacocoTestReport' | Thresholds.Insufficient.LINE_METRIC_COVERED_RATIO | 'lines covered ratio is 1.0, but expected maximum is 0.5' - INTEG_TEST_AND_JACOCO_REPORT_TASK_PATHS | 'jacocoIntegrationTestReport' | Thresholds.Insufficient.CLASS_METRIC_MISSED_COUNT | 'classes missed count is 0.0, but expected minimum is 0.5' + tasksPaths | reportTaskName | limit | errorMessage + TEST_AND_JACOCO_REPORT_TASK_PATHS | 'jacocoTestReport' | Limits.Insufficient.LINE_METRIC_COVERED_RATIO | 'lines covered ratio is 1.0, but expected maximum is 0.5' + INTEG_TEST_AND_JACOCO_REPORT_TASK_PATHS | 'jacocoIntegrationTestReport' | Limits.Insufficient.CLASS_METRIC_MISSED_COUNT | 'classes missed count is 0.0, but expected minimum is 0.5' } - static class Thresholds { + static class Limits { static class Sufficient { - static final String LINE_METRIC_COVERED_RATIO = Thresholds.create('LINE', 'COVEREDRATIO', '0.0', '1.0') - static final String CLASS_METRIC_MISSED_COUNT = Thresholds.create('CLASS', 'MISSEDCOUNT', null, '0') + static final String LINE_METRIC_COVERED_RATIO = Limits.create('LINE', 'COVEREDRATIO', '0.0', '1.0') + static final String CLASS_METRIC_MISSED_COUNT = Limits.create('CLASS', 'MISSEDCOUNT', null, '0') } static class Insufficient { - static final String LINE_METRIC_COVERED_RATIO = Thresholds.create('LINE', 'COVEREDRATIO', '0.0', '0.5') - static final String CLASS_METRIC_MISSED_COUNT = Thresholds.create('CLASS', 'MISSEDCOUNT', '0.5', null) + static final String LINE_METRIC_COVERED_RATIO = Limits.create('LINE', 'COVEREDRATIO', '0.0', '0.5') + static final String CLASS_METRIC_MISSED_COUNT = Limits.create('CLASS', 'MISSEDCOUNT', '0.5', null) } - private static String create(String metric, String type, String minimum, String maximum) { - StringBuilder threshold = new StringBuilder() - threshold <<= 'threshold {\n' + private static String create(String counter, String value, String minimum, String maximum) { + StringBuilder limit = new StringBuilder() + limit <<= 'limit {\n' - if (metric) { - threshold <<= " metric = '${metric}'\n" + if (counter) { + limit <<= " counter = '${counter}'\n" } - if (type) { - threshold <<= " type = '${type}'\n" + if (value) { + limit <<= " value = '${value}'\n" } if (minimum) { - threshold <<= " minimum = $minimum\n" + limit <<= " minimum = $minimum\n" } if (maximum) { - threshold <<= " maximum = $maximum\n" + limit <<= " maximum = $maximum\n" } - threshold <<= '}' - threshold.toString() + limit <<= '}' + limit.toString() } } } diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java index 5d1c92401f39..7493576de1f3 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java @@ -24,7 +24,7 @@ import org.gradle.api.file.FileCollection; import org.gradle.api.internal.project.IsolatedAntBuilder; import org.gradle.testing.jacoco.tasks.JacocoReportsContainer; -import org.gradle.testing.jacoco.tasks.rules.JacocoThreshold; +import org.gradle.testing.jacoco.tasks.rules.JacocoLimit; import org.gradle.testing.jacoco.tasks.rules.JacocoViolationRule; import org.gradle.testing.jacoco.tasks.rules.JacocoViolationRulesContainer; @@ -122,8 +122,8 @@ public Object doCall(Object ignore) { for (final JacocoViolationRule rule : filter(violationRules.getRules(), RULE_ENABLED_PREDICATE)) { Map ruleArgs = new HashMap(); - if (rule.getScope() != null) { - ruleArgs.put("element", rule.getScope()); + if (rule.getElement() != null) { + ruleArgs.put("element", rule.getElement()); } if (rule.getIncludes() != null && !rule.getIncludes().isEmpty()) { ruleArgs.put("includes", Joiner.on(':').join(rule.getIncludes())); @@ -135,20 +135,20 @@ public Object doCall(Object ignore) { antBuilder.invokeMethod("rule", new Object[] {ImmutableMap.copyOf(ruleArgs), new Closure(this, this) { @SuppressWarnings("UnusedDeclaration") public Object doCall(Object ignore) { - for (JacocoThreshold threshold : rule.getThresholds()) { + for (JacocoLimit limit : rule.getLimits()) { Map ruleArgs = new HashMap(); - if (threshold.getMetric() != null) { - ruleArgs.put("counter", threshold.getMetric()); + if (limit.getCounter() != null) { + ruleArgs.put("counter", limit.getCounter()); } - if (threshold.getType() != null) { - ruleArgs.put("value", threshold.getType()); + if (limit.getValue() != null) { + ruleArgs.put("value", limit.getValue()); } - if (threshold.getMinimum() != null) { - ruleArgs.put("minimum", threshold.getMinimum()); + if (limit.getMinimum() != null) { + ruleArgs.put("minimum", limit.getMinimum()); } - if (threshold.getMaximum() != null) { - ruleArgs.put("maximum", threshold.getMaximum()); + if (limit.getMaximum() != null) { + ruleArgs.put("maximum", limit.getMaximum()); } antBuilder.invokeMethod("limit", new Object[] {ImmutableMap.copyOf(ruleArgs) }); diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoThresholdImpl.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoLimitImpl.java similarity index 72% rename from subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoThresholdImpl.java rename to subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoLimitImpl.java index 568ba6c1642e..1a8fa5e6b844 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoThresholdImpl.java +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoLimitImpl.java @@ -16,33 +16,33 @@ package org.gradle.internal.jacoco.rules; -import org.gradle.testing.jacoco.tasks.rules.JacocoThreshold; +import org.gradle.testing.jacoco.tasks.rules.JacocoLimit; -public class JacocoThresholdImpl implements JacocoThreshold { +public class JacocoLimitImpl implements JacocoLimit { - private String metric = "INSTRUCTION"; - private String type = "COVEREDRATIO"; + private String counter = "INSTRUCTION"; + private String value = "COVEREDRATIO"; private Double minimum; private Double maximum; @Override - public String getMetric() { - return metric; + public String getCounter() { + return counter; } @Override - public void setMetric(String metric) { - this.metric = metric; + public void setCounter(String counter) { + this.counter = counter; } @Override - public String getType() { - return type; + public String getValue() { + return value; } @Override - public void setType(String type) { - this.type = type; + public void setValue(String value) { + this.value = value; } @Override @@ -74,12 +74,12 @@ public boolean equals(Object o) { return false; } - JacocoThresholdImpl that = (JacocoThresholdImpl) o; + JacocoLimitImpl that = (JacocoLimitImpl) o; - if (metric != that.metric) { + if (counter != that.counter) { return false; } - if (type != that.type) { + if (value != that.value) { return false; } if (minimum != null ? !minimum.equals(that.minimum) : that.minimum != null) { @@ -90,8 +90,8 @@ public boolean equals(Object o) { @Override public int hashCode() { - int result = metric != null ? metric.hashCode() : 0; - result = 31 * result + (type != null ? type.hashCode() : 0); + int result = counter != null ? counter.hashCode() : 0; + result = 31 * result + (value != null ? value.hashCode() : 0); result = 31 * result + (minimum != null ? minimum.hashCode() : 0); result = 31 * result + (maximum != null ? maximum.hashCode() : 0); return result; diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoViolationRuleImpl.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoViolationRuleImpl.java index c298e4556537..80bc725f0b3c 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoViolationRuleImpl.java +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/rules/JacocoViolationRuleImpl.java @@ -20,7 +20,7 @@ import groovy.lang.Closure; import org.gradle.api.Action; import org.gradle.api.internal.ClosureBackedAction; -import org.gradle.testing.jacoco.tasks.rules.JacocoThreshold; +import org.gradle.testing.jacoco.tasks.rules.JacocoLimit; import org.gradle.testing.jacoco.tasks.rules.JacocoViolationRule; import java.util.ArrayList; @@ -33,7 +33,7 @@ public class JacocoViolationRuleImpl implements JacocoViolationRule { private String scope = "BUNDLE"; private List includes = ImmutableList.of("*"); private List excludes = ImmutableList.of(); - private final List thresholds = new ArrayList(); + private final List limits = new ArrayList(); @Override public boolean isEnabled() { @@ -46,12 +46,12 @@ public void setEnabled(boolean enabled) { } @Override - public void setScope(String scope) { - this.scope = scope; + public void setElement(String element) { + this.scope = element; } @Override - public String getScope() { + public String getElement() { return scope; } @@ -76,21 +76,21 @@ public List getExcludes() { } @Override - public List getThresholds() { - return Collections.unmodifiableList(thresholds); + public List getLimits() { + return Collections.unmodifiableList(limits); } @Override - public JacocoThreshold threshold(Closure configureClosure) { - return threshold(ClosureBackedAction.of(configureClosure)); + public JacocoLimit limit(Closure configureClosure) { + return limit(ClosureBackedAction.of(configureClosure)); } @Override - public JacocoThreshold threshold(Action configureAction) { - JacocoThreshold threshold = new JacocoThresholdImpl(); - configureAction.execute(threshold); - thresholds.add(threshold); - return threshold; + public JacocoLimit limit(Action configureAction) { + JacocoLimit limit = new JacocoLimitImpl(); + configureAction.execute(limit); + limits.add(limit); + return limit; } @Override @@ -116,7 +116,7 @@ public boolean equals(Object o) { if (excludes != null ? !excludes.equals(that.excludes) : that.excludes != null) { return false; } - return thresholds != null ? thresholds.equals(that.thresholds) : that.thresholds == null; + return limits != null ? limits.equals(that.limits) : that.limits == null; } @Override @@ -125,7 +125,7 @@ public int hashCode() { result = 31 * result + (scope != null ? scope.hashCode() : 0); result = 31 * result + (includes != null ? includes.hashCode() : 0); result = 31 * result + (excludes != null ? excludes.hashCode() : 0); - result = 31 * result + (thresholds != null ? thresholds.hashCode() : 0); + result = 31 * result + (limits != null ? limits.hashCode() : 0); return result; } } diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThreshold.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoLimit.java similarity index 77% rename from subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThreshold.java rename to subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoLimit.java index 13796f8494a1..6a13c077097d 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoThreshold.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoLimit.java @@ -19,40 +19,40 @@ import org.gradle.api.Incubating; /** - * Jacoco threshold. + * Defines a Jacoco rule limit. * * @since 4.0 */ @Incubating -public interface JacocoThreshold { +public interface JacocoLimit { /** - * The metric that applies to the threshold as defined by + * The counter that applies to the limit as defined by * org.jacoco.core.analysis.ICoverageNode.CounterEntity. * Valid values are INSTRUCTION, LINE, BRANCH, COMPLEXITY, METHOD and CLASS. Defaults to INSTRUCTION. */ - String getMetric(); + String getCounter(); - void setMetric(String metric); + void setCounter(String counter); /** - * The value that applies to the threshold as defined by + * The value that applies to the limit as defined by * org.jacoco.core.analysis.ICounter.CounterValue. * Valid values are TOTALCOUNT, MISSEDCOUNT, COVEREDCOUNT, MISSEDRATIO and COVEREDRATIO. Defaults to COVEREDRATIO. */ - String getType(); + String getValue(); - void setType(String type); + void setValue(String value); /** - * Gets the minimum expected value for threshold. Default to null. + * Gets the minimum expected value for limit. Default to null. */ Double getMinimum(); void setMinimum(Double minimum); /** - * Gets the maximum expected value for threshold. Default to null. + * Gets the maximum expected value for limit. Default to null. */ Double getMaximum(); diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java index 59a3d48d3d83..66c545cf3a94 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java @@ -26,7 +26,7 @@ import static groovy.lang.Closure.DELEGATE_FIRST; /** - * Jacoco violation rule. + * Defines a Jacoco violation rule. * * @since 4.0 */ @@ -40,14 +40,14 @@ public interface JacocoViolationRule { */ boolean isEnabled(); - void setScope(String scope); + void setElement(String element); /** - * Gets the scope for the rule as defined by + * Gets the element for the rule as defined by * org.jacoco.core.analysis.ICoverageNode.ElementType. * Valid scope values are BUNDLE, PACKAGE, CLASS, SOURCEFILE and METHOD. Defaults to BUNDLE. */ - String getScope(); + String getElement(); void setIncludes(List includes); @@ -66,14 +66,14 @@ public interface JacocoViolationRule { List getExcludes(); /** - * Gets all thresholds defined for this rule. Defaults to an empty list. + * Gets all limits defined for this rule. Defaults to an empty list. */ - List getThresholds(); + List getLimits(); /** - * Adds a threshold for this rule. There's no limitation to the number of thresholds that can be added. + * Adds a limit for this rule. Any number of limits can be added. */ - JacocoThreshold threshold(@DelegatesTo(value = JacocoThreshold.class, strategy = DELEGATE_FIRST) Closure configureClosure); + JacocoLimit limit(@DelegatesTo(value = JacocoLimit.class, strategy = DELEGATE_FIRST) Closure configureClosure); - JacocoThreshold threshold(Action configureAction); + JacocoLimit limit(Action configureAction); } diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRulesContainer.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRulesContainer.java index 7d3a2bc1edf5..1e62f2d9dcd6 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRulesContainer.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRulesContainer.java @@ -49,7 +49,7 @@ public interface JacocoViolationRulesContainer { List getRules(); /** - * Adds a violation rule. There's no limitation to the number of rules that can be added. + * Adds a violation rule. Any number of rules can be added. */ JacocoViolationRule rule(@DelegatesTo(value = JacocoViolationRule.class, strategy = DELEGATE_FIRST) Closure configureClosure); diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/package-info.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/package-info.java index 6fe859185bc4..983b97986fff 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/package-info.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/package-info.java @@ -15,7 +15,7 @@ */ /** - * Implementations for Jacoco metrics rules. + * Implementations for Jacoco code coverage rules. */ @org.gradle.api.Incubating package org.gradle.testing.jacoco.tasks.rules; \ No newline at end of file diff --git a/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoThresholdImplTest.groovy b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoLimitImplTest.groovy similarity index 75% rename from subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoThresholdImplTest.groovy rename to subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoLimitImplTest.groovy index 28a29e243322..5d431c6079c7 100644 --- a/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoThresholdImplTest.groovy +++ b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoLimitImplTest.groovy @@ -18,15 +18,15 @@ package org.gradle.internal.jacoco.rules import spock.lang.Specification -class JacocoThresholdImplTest extends Specification { +class JacocoLimitImplTest extends Specification { - JacocoThresholdImpl threshold = new JacocoThresholdImpl() + JacocoLimitImpl limit = new JacocoLimitImpl() def "provides expected default field values"() { expect: - threshold.metric == 'INSTRUCTION' - threshold.type == 'COVEREDRATIO' - !threshold.minimum - !threshold.maximum + limit.counter == 'INSTRUCTION' + limit.value == 'COVEREDRATIO' + !limit.minimum + !limit.maximum } } diff --git a/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoViolationRuleImplTest.groovy b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoViolationRuleImplTest.groovy index 549a971d86b7..d15aa0aace4d 100644 --- a/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoViolationRuleImplTest.groovy +++ b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoViolationRuleImplTest.groovy @@ -17,7 +17,7 @@ package org.gradle.internal.jacoco.rules import org.gradle.api.Action -import org.gradle.testing.jacoco.tasks.rules.JacocoThreshold +import org.gradle.testing.jacoco.tasks.rules.JacocoLimit import spock.lang.Specification class JacocoViolationRuleImplTest extends Specification { @@ -27,31 +27,31 @@ class JacocoViolationRuleImplTest extends Specification { def "provides expected default field values"() { expect: rule.enabled - rule.scope == 'BUNDLE' + rule.element == 'BUNDLE' rule.includes == ['*'] rule.excludes == [] } - def "can add thresholds"() { + def "can add limits"() { when: - def threshold = rule.threshold { - metric = 'CLASS' - type = 'TOTALCOUNT' + def limit = rule.limit { + counter = 'CLASS' + value = 'TOTALCOUNT' minimum = 0.0 maximum = 1.0 } then: - rule.thresholds.size() == 1 - rule.thresholds[0] == threshold + rule.limits.size() == 1 + rule.limits[0] == limit when: - threshold = rule.threshold(new Action() { + limit = rule.limit(new Action() { @Override - void execute(JacocoThreshold jacocoThreshold) { - jacocoThreshold.with { - metric = 'COMPLEXITY' - type = 'MISSEDCOUNT' + void execute(JacocoLimit jacocoLimit) { + jacocoLimit.with { + counter = 'COMPLEXITY' + value = 'MISSEDCOUNT' minimum = 0.2 maximum = 0.6 } @@ -59,11 +59,11 @@ class JacocoViolationRuleImplTest extends Specification { }) then: - rule.thresholds.size() == 2 - rule.thresholds[1] == threshold + rule.limits.size() == 2 + rule.limits[1] == limit } - def "returned includes, excludes and thresholds are unmodifiable"() { + def "returned includes, excludes and limits are unmodifiable"() { when: rule.includes << ['*'] @@ -77,7 +77,7 @@ class JacocoViolationRuleImplTest extends Specification { thrown(UnsupportedOperationException) when: - rule.thresholds << new JacocoThresholdImpl() + rule.limits << new JacocoLimitImpl() then: thrown(UnsupportedOperationException) diff --git a/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoViolationRulesContainerImplTest.groovy b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoViolationRulesContainerImplTest.groovy index 8758f3da966d..11933cb83a64 100644 --- a/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoViolationRulesContainerImplTest.groovy +++ b/subprojects/jacoco/src/test/groovy/org/gradle/internal/jacoco/rules/JacocoViolationRulesContainerImplTest.groovy @@ -34,7 +34,7 @@ class JacocoViolationRulesContainerImplTest extends Specification { when: def rule = violationRulesContainer.rule { enabled = false - scope = 'CLASS' + element = 'CLASS' includes = ['**/*.class'] excludes = ['*Special*.class'] } @@ -49,7 +49,7 @@ class JacocoViolationRulesContainerImplTest extends Specification { void execute(JacocoViolationRule jacocoValidationRule) { jacocoValidationRule.with { enabled = true - scope = 'PACKAGE' + element = 'PACKAGE' includes = ['**/*'] excludes = ['**/special/*'] } From aed27f6667e308abcf2f79cd7b052ca55a7a3ca6 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Tue, 6 Dec 2016 10:07:32 -0500 Subject: [PATCH 19/42] Apply input/output annotations --- ...oPluginCheckCoverageIntegrationTest.groovy | 41 ++++++++++++++++++- .../jacoco/tasks/rules/JacocoLimit.java | 12 +++++- .../tasks/rules/JacocoViolationRule.java | 10 ++++- .../rules/JacocoViolationRulesContainer.java | 6 +-- 4 files changed, 63 insertions(+), 6 deletions(-) diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy index 8f6c3412d165..15e4944bee41 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy @@ -23,7 +23,9 @@ import spock.lang.Unroll class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { private final JavaProjectUnderTest javaProjectUnderTest = new JavaProjectUnderTest(testDirectory) - private final static String[] TEST_AND_JACOCO_REPORT_TASK_PATHS = [':test', ':jacocoTestReport'] as String[] + private final static String[] TEST_TASK_PATH = [':test'] as String[] + private final static String[] JACOCO_REPORT_TASK_PATH = [':jacocoTestReport'] as String[] + private final static String[] TEST_AND_JACOCO_REPORT_TASK_PATHS = TEST_TASK_PATH + JACOCO_REPORT_TASK_PATH private final static String[] INTEG_TEST_AND_JACOCO_REPORT_TASK_PATHS = [':integrationTest', ':jacocoIntegrationTestReport'] as String[] def setup() { @@ -310,6 +312,43 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { INTEG_TEST_AND_JACOCO_REPORT_TASK_PATHS | 'jacocoIntegrationTestReport' | Limits.Insufficient.CLASS_METRIC_MISSED_COUNT | 'classes missed count is 0.0, but expected minimum is 0.5' } + def "changes to violation rules re-run task"() { + buildFile << """ + jacocoTestReport { + violationRules { + rule { + $Limits.Sufficient.LINE_METRIC_COVERED_RATIO + } + } + } + """ + + when: + succeeds TEST_AND_JACOCO_REPORT_TASK_PATHS + + then: + executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) + + when: + succeeds TEST_AND_JACOCO_REPORT_TASK_PATHS + + then: + executed(TEST_AND_JACOCO_REPORT_TASK_PATHS) + skipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) + + when: + buildFile << """ + jacocoTestReport.violationRules.rules[0].limits[0].maximum = 0.5 + """ + + fails TEST_AND_JACOCO_REPORT_TASK_PATHS + + then: + executed(JACOCO_REPORT_TASK_PATH) + skipped(TEST_TASK_PATH) + errorOutput.contains("Rule violated for bundle $testDirectory.name: lines covered ratio is 1.0, but expected maximum is 0.5") + } + static class Limits { static class Sufficient { static final String LINE_METRIC_COVERED_RATIO = Limits.create('LINE', 'COVEREDRATIO', '0.0', '1.0') diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoLimit.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoLimit.java index 6a13c077097d..2fd378a688d6 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoLimit.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoLimit.java @@ -17,6 +17,10 @@ package org.gradle.testing.jacoco.tasks.rules; import org.gradle.api.Incubating; +import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.Optional; + +import java.io.Serializable; /** * Defines a Jacoco rule limit. @@ -24,13 +28,14 @@ * @since 4.0 */ @Incubating -public interface JacocoLimit { +public interface JacocoLimit extends Serializable { /** * The counter that applies to the limit as defined by * org.jacoco.core.analysis.ICoverageNode.CounterEntity. * Valid values are INSTRUCTION, LINE, BRANCH, COMPLEXITY, METHOD and CLASS. Defaults to INSTRUCTION. */ + @Input String getCounter(); void setCounter(String counter); @@ -40,6 +45,7 @@ public interface JacocoLimit { * org.jacoco.core.analysis.ICounter.CounterValue. * Valid values are TOTALCOUNT, MISSEDCOUNT, COVEREDCOUNT, MISSEDRATIO and COVEREDRATIO. Defaults to COVEREDRATIO. */ + @Input String getValue(); void setValue(String value); @@ -47,6 +53,8 @@ public interface JacocoLimit { /** * Gets the minimum expected value for limit. Default to null. */ + @Input + @Optional Double getMinimum(); void setMinimum(Double minimum); @@ -54,6 +62,8 @@ public interface JacocoLimit { /** * Gets the maximum expected value for limit. Default to null. */ + @Input + @Optional Double getMaximum(); void setMaximum(Double maximum); diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java index 66c545cf3a94..d9adb1901241 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java @@ -20,7 +20,10 @@ import groovy.lang.DelegatesTo; import org.gradle.api.Action; import org.gradle.api.Incubating; +import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.Nested; +import java.io.Serializable; import java.util.List; import static groovy.lang.Closure.DELEGATE_FIRST; @@ -31,13 +34,14 @@ * @since 4.0 */ @Incubating -public interface JacocoViolationRule { +public interface JacocoViolationRule extends Serializable { void setEnabled(boolean enabled); /** * Indicates if the rule should be used when checking generated coverage metrics. */ + @Input boolean isEnabled(); void setElement(String element); @@ -47,6 +51,7 @@ public interface JacocoViolationRule { * org.jacoco.core.analysis.ICoverageNode.ElementType. * Valid scope values are BUNDLE, PACKAGE, CLASS, SOURCEFILE and METHOD. Defaults to BUNDLE. */ + @Input String getElement(); void setIncludes(List includes); @@ -55,6 +60,7 @@ public interface JacocoViolationRule { * List of elements that should be included in check. Names can use wildcards (* and ?). * If left empty, all elements will be included. Defaults to [*]. */ + @Input List getIncludes(); void setExcludes(List excludes); @@ -63,11 +69,13 @@ public interface JacocoViolationRule { * List of elements that should be excluded from check. Names can use wildcards (* and ?). * If left empty, no elements will be excluded. Defaults to an empty list. */ + @Input List getExcludes(); /** * Gets all limits defined for this rule. Defaults to an empty list. */ + @Nested List getLimits(); /** diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRulesContainer.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRulesContainer.java index 1e62f2d9dcd6..f6488fab6ed4 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRulesContainer.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRulesContainer.java @@ -20,7 +20,7 @@ import groovy.lang.DelegatesTo; import org.gradle.api.Action; import org.gradle.api.Incubating; -import org.gradle.api.tasks.Internal; +import org.gradle.api.tasks.Input; import java.util.List; @@ -39,13 +39,13 @@ public interface JacocoViolationRulesContainer { /** * Specifies whether build should fail in case of rule violations. Defaults to true. */ - @Internal + @Input boolean isFailOnViolation(); /** * Gets all violation rules. Defaults to an empty list. */ - @Internal + @Input List getRules(); /** From 00b2cb32ad7c367059e8fb6e502e42e1ff5dc419 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Tue, 6 Dec 2016 10:09:30 -0500 Subject: [PATCH 20/42] Document default value for property --- .../gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java index d9adb1901241..cf88f14ef500 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java @@ -39,7 +39,7 @@ public interface JacocoViolationRule extends Serializable { void setEnabled(boolean enabled); /** - * Indicates if the rule should be used when checking generated coverage metrics. + * Indicates if the rule should be used when checking generated coverage metrics. Defaults to true. */ @Input boolean isEnabled(); From 0dc8b31860cab4beec8769d8932d0fc2441e0bb2 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Tue, 6 Dec 2016 10:17:28 -0500 Subject: [PATCH 21/42] Verify proper behavior of Ant task for unknown values --- ...oPluginCheckCoverageIntegrationTest.groovy | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy index 15e4944bee41..eb5d98b71935 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy @@ -64,6 +64,26 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) } + def "Ant task reports error for unknown field value"() { + given: + buildFile << """ + jacocoTestReport { + violationRules { + rule { + element = 'UNKNOWN' + } + } + } + """ + + when: + fails TEST_AND_JACOCO_REPORT_TASK_PATHS + + then: + executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) + errorOutput.contains("'UNKNOWN' is not a permitted value for org.jacoco.core.analysis.ICoverageNode\$ElementType") + } + def "can define includes for single rule"() { given: buildFile << """ From 45674bdd70a177db1464d7463672114e3bf2b142 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Tue, 6 Dec 2016 11:20:22 -0500 Subject: [PATCH 22/42] Remove spaces --- .../plugins/JacocoPluginCheckCoverageIntegrationTest.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy index eb5d98b71935..e1770ea4af3c 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy @@ -358,7 +358,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { when: buildFile << """ - jacocoTestReport.violationRules.rules[0].limits[0].maximum = 0.5 + jacocoTestReport.violationRules.rules[0].limits[0].maximum = 0.5 """ fails TEST_AND_JACOCO_REPORT_TASK_PATHS From ebb4d115dca047d8d1bb9edb5612fa33322ed7ae Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Tue, 6 Dec 2016 12:04:35 -0500 Subject: [PATCH 23/42] Add multi-version coverage for check support --- ...CheckCoverageVersionIntegrationTest.groovy | 48 ++++++++++ ...ageCompatibleVersionIntegrationTest.groovy | 31 +++++++ ...eIncompatibleVersionIntegrationTest.groovy | 32 +++++++ ...oPluginCheckCoverageIntegrationTest.groovy | 90 +++++++------------ .../rules/JacocoViolationRulesLimit.groovy | 53 +++++++++++ 5 files changed, 194 insertions(+), 60 deletions(-) create mode 100644 subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/AbstractJacocoPluginCheckCoverageVersionIntegrationTest.groovy create mode 100644 subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageCompatibleVersionIntegrationTest.groovy create mode 100644 subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIncompatibleVersionIntegrationTest.groovy rename subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/{ => rules}/JacocoPluginCheckCoverageIntegrationTest.groovy (72%) create mode 100644 subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoViolationRulesLimit.groovy diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/AbstractJacocoPluginCheckCoverageVersionIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/AbstractJacocoPluginCheckCoverageVersionIntegrationTest.groovy new file mode 100644 index 000000000000..f7330ae9f373 --- /dev/null +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/AbstractJacocoPluginCheckCoverageVersionIntegrationTest.groovy @@ -0,0 +1,48 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.testing.jacoco.plugins.rules + +import org.gradle.integtests.fixtures.MultiVersionIntegrationSpec +import org.gradle.testing.jacoco.plugins.fixtures.JavaProjectUnderTest +import org.gradle.util.Requires +import org.gradle.util.TestPrecondition + +import static JacocoViolationRulesLimit.Sufficient + +@Requires(TestPrecondition.JDK7_OR_EARLIER) +abstract class AbstractJacocoPluginCheckCoverageVersionIntegrationTest extends MultiVersionIntegrationSpec { + + private final JavaProjectUnderTest javaProjectUnderTest = new JavaProjectUnderTest(testDirectory) + + def setup() { + javaProjectUnderTest.writeBuildScript().writeSourceFiles() + + buildFile << """ + jacoco { + toolVersion = '$version' + } + + jacocoTestReport { + violationRules { + rule { + $Sufficient.LINE_METRIC_COVERED_RATIO + } + } + } + """ + } +} diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageCompatibleVersionIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageCompatibleVersionIntegrationTest.groovy new file mode 100644 index 000000000000..5c6bb91fda45 --- /dev/null +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageCompatibleVersionIntegrationTest.groovy @@ -0,0 +1,31 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.testing.jacoco.plugins.rules + +import org.gradle.integtests.fixtures.TargetVersions + +@TargetVersions(['0.6.3.201306030806', '0.7.1.201405082137', '0.7.6.201602180812']) +class JacocoPluginCheckCoverageCompatibleVersionIntegrationTest extends AbstractJacocoPluginCheckCoverageVersionIntegrationTest { + + def "can check code coverage for compatible versions"() { + when: + succeeds 'test', 'jacocoTestReport' + + then: + executedAndNotSkipped(':test', ':jacocoTestReport') + } +} diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIncompatibleVersionIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIncompatibleVersionIntegrationTest.groovy new file mode 100644 index 000000000000..5928823cde83 --- /dev/null +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIncompatibleVersionIntegrationTest.groovy @@ -0,0 +1,32 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.testing.jacoco.plugins.rules + +import org.gradle.integtests.fixtures.TargetVersions + +@TargetVersions(['0.6.2.201302030002']) +class JacocoPluginCheckCoverageIncompatibleVersionIntegrationTest extends AbstractJacocoPluginCheckCoverageVersionIntegrationTest { + + def "fails to check code coverage"() { + when: + fails 'test', 'jacocoTestReport' + + then: + executedAndNotSkipped(':test', ':jacocoTestReport') + errorOutput.contains("jacocoReport doesn't support the nested \"check\" element.") + } +} \ No newline at end of file diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIntegrationTest.groovy similarity index 72% rename from subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy rename to subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIntegrationTest.groovy index e1770ea4af3c..05cad202d75f 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginCheckCoverageIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIntegrationTest.groovy @@ -14,12 +14,15 @@ * limitations under the License. */ -package org.gradle.testing.jacoco.plugins +package org.gradle.testing.jacoco.plugins.rules import org.gradle.integtests.fixtures.AbstractIntegrationSpec import org.gradle.testing.jacoco.plugins.fixtures.JavaProjectUnderTest import spock.lang.Unroll +import static JacocoViolationRulesLimit.Insufficient +import static JacocoViolationRulesLimit.Sufficient + class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { private final JavaProjectUnderTest javaProjectUnderTest = new JavaProjectUnderTest(testDirectory) @@ -92,7 +95,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { rule { element = 'CLASS' includes = ['com.company.*', 'org.gradle.*'] - $Limits.Insufficient.LINE_METRIC_COVERED_RATIO + $Insufficient.LINE_METRIC_COVERED_RATIO } } } @@ -113,7 +116,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { violationRules { rule { excludes = ['company', '$testDirectory.name'] - $Limits.Insufficient.LINE_METRIC_COVERED_RATIO + $Insufficient.LINE_METRIC_COVERED_RATIO } } } @@ -137,7 +140,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { } violationRules { rule { - $Limits.Insufficient.LINE_METRIC_COVERED_RATIO + $Insufficient.LINE_METRIC_COVERED_RATIO } } } @@ -171,11 +174,11 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) where: - limits | description - [Limits.Sufficient.LINE_METRIC_COVERED_RATIO] | 'line metric with covered ratio' - [Limits.Sufficient.CLASS_METRIC_MISSED_COUNT] | 'class metric with missed count' - [Limits.Sufficient.LINE_METRIC_COVERED_RATIO, - Limits.Sufficient.CLASS_METRIC_MISSED_COUNT] | 'line and class metric' + limits | description + [Sufficient.LINE_METRIC_COVERED_RATIO] | 'line metric with covered ratio' + [Sufficient.CLASS_METRIC_MISSED_COUNT] | 'class metric with missed count' + [Sufficient.LINE_METRIC_COVERED_RATIO, + Sufficient.CLASS_METRIC_MISSED_COUNT] | 'line and class metric' } @@ -200,14 +203,14 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { errorOutput.contains("Rule violated for bundle $testDirectory.name: $errorMessage") where: - limits | description | errorMessage - [Limits.Insufficient.LINE_METRIC_COVERED_RATIO] | 'line metric with covered ratio' | 'lines covered ratio is 1.0, but expected maximum is 0.5' - [Limits.Insufficient.CLASS_METRIC_MISSED_COUNT] | 'class metric with missed count' | 'classes missed count is 0.0, but expected minimum is 0.5' - [Limits.Insufficient.LINE_METRIC_COVERED_RATIO, - Limits.Insufficient.CLASS_METRIC_MISSED_COUNT] | 'first of multiple insufficient limits fails' | 'lines covered ratio is 1.0, but expected maximum is 0.5' - [Limits.Sufficient.LINE_METRIC_COVERED_RATIO, - Limits.Insufficient.CLASS_METRIC_MISSED_COUNT, - Limits.Sufficient.CLASS_METRIC_MISSED_COUNT] | 'first insufficient limits fails' | 'classes missed count is 0.0, but expected minimum is 0.5' + limits | description | errorMessage + [Insufficient.LINE_METRIC_COVERED_RATIO] | 'line metric with covered ratio' | 'lines covered ratio is 1.0, but expected maximum is 0.5' + [Insufficient.CLASS_METRIC_MISSED_COUNT] | 'class metric with missed count' | 'classes missed count is 0.0, but expected minimum is 0.5' + [Insufficient.LINE_METRIC_COVERED_RATIO, + Insufficient.CLASS_METRIC_MISSED_COUNT] | 'first of multiple insufficient limits fails' | 'lines covered ratio is 1.0, but expected maximum is 0.5' + [Sufficient.LINE_METRIC_COVERED_RATIO, + Insufficient.CLASS_METRIC_MISSED_COUNT, + Sufficient.CLASS_METRIC_MISSED_COUNT] | 'first insufficient limits fails' | 'classes missed count is 0.0, but expected minimum is 0.5' } def "can define multiple rules"() { @@ -216,10 +219,10 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { jacocoTestReport { violationRules { rule { - $Limits.Sufficient.LINE_METRIC_COVERED_RATIO + $Sufficient.LINE_METRIC_COVERED_RATIO } rule { - $Limits.Insufficient.CLASS_METRIC_MISSED_COUNT + $Insufficient.CLASS_METRIC_MISSED_COUNT } } } @@ -239,11 +242,11 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { jacocoTestReport { violationRules { rule { - $Limits.Sufficient.LINE_METRIC_COVERED_RATIO + $Sufficient.LINE_METRIC_COVERED_RATIO } rule { enabled = false - $Limits.Insufficient.CLASS_METRIC_MISSED_COUNT + $Insufficient.CLASS_METRIC_MISSED_COUNT } } } @@ -264,7 +267,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { failOnViolation = true rule { - $Limits.Insufficient.LINE_METRIC_COVERED_RATIO + $Insufficient.LINE_METRIC_COVERED_RATIO } } } @@ -287,7 +290,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { tasks.withType(JacocoReport) { violationRules { rule { - $Limits.Insufficient.LINE_METRIC_COVERED_RATIO + $Insufficient.LINE_METRIC_COVERED_RATIO } } } @@ -327,9 +330,9 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { errorOutput.contains("Rule violated for bundle $testDirectory.name: $errorMessage") where: - tasksPaths | reportTaskName | limit | errorMessage - TEST_AND_JACOCO_REPORT_TASK_PATHS | 'jacocoTestReport' | Limits.Insufficient.LINE_METRIC_COVERED_RATIO | 'lines covered ratio is 1.0, but expected maximum is 0.5' - INTEG_TEST_AND_JACOCO_REPORT_TASK_PATHS | 'jacocoIntegrationTestReport' | Limits.Insufficient.CLASS_METRIC_MISSED_COUNT | 'classes missed count is 0.0, but expected minimum is 0.5' + tasksPaths | reportTaskName | limit | errorMessage + TEST_AND_JACOCO_REPORT_TASK_PATHS | 'jacocoTestReport' | Insufficient.LINE_METRIC_COVERED_RATIO | 'lines covered ratio is 1.0, but expected maximum is 0.5' + INTEG_TEST_AND_JACOCO_REPORT_TASK_PATHS | 'jacocoIntegrationTestReport' | Insufficient.CLASS_METRIC_MISSED_COUNT | 'classes missed count is 0.0, but expected minimum is 0.5' } def "changes to violation rules re-run task"() { @@ -337,7 +340,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { jacocoTestReport { violationRules { rule { - $Limits.Sufficient.LINE_METRIC_COVERED_RATIO + $Sufficient.LINE_METRIC_COVERED_RATIO } } } @@ -368,37 +371,4 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { skipped(TEST_TASK_PATH) errorOutput.contains("Rule violated for bundle $testDirectory.name: lines covered ratio is 1.0, but expected maximum is 0.5") } - - static class Limits { - static class Sufficient { - static final String LINE_METRIC_COVERED_RATIO = Limits.create('LINE', 'COVEREDRATIO', '0.0', '1.0') - static final String CLASS_METRIC_MISSED_COUNT = Limits.create('CLASS', 'MISSEDCOUNT', null, '0') - } - - static class Insufficient { - static final String LINE_METRIC_COVERED_RATIO = Limits.create('LINE', 'COVEREDRATIO', '0.0', '0.5') - static final String CLASS_METRIC_MISSED_COUNT = Limits.create('CLASS', 'MISSEDCOUNT', '0.5', null) - } - - private static String create(String counter, String value, String minimum, String maximum) { - StringBuilder limit = new StringBuilder() - limit <<= 'limit {\n' - - if (counter) { - limit <<= " counter = '${counter}'\n" - } - if (value) { - limit <<= " value = '${value}'\n" - } - if (minimum) { - limit <<= " minimum = $minimum\n" - } - if (maximum) { - limit <<= " maximum = $maximum\n" - } - - limit <<= '}' - limit.toString() - } - } } diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoViolationRulesLimit.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoViolationRulesLimit.groovy new file mode 100644 index 000000000000..eda00266a378 --- /dev/null +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoViolationRulesLimit.groovy @@ -0,0 +1,53 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.testing.jacoco.plugins.rules + +final class JacocoViolationRulesLimit { + + private JacocoViolationRulesLimit() {} + + static class Sufficient { + static final String LINE_METRIC_COVERED_RATIO = JacocoViolationRulesLimit.create('LINE', 'COVEREDRATIO', '0.0', '1.0') + static final String CLASS_METRIC_MISSED_COUNT = JacocoViolationRulesLimit.create('CLASS', 'MISSEDCOUNT', null, '0') + } + + static class Insufficient { + static final String LINE_METRIC_COVERED_RATIO = JacocoViolationRulesLimit.create('LINE', 'COVEREDRATIO', '0.0', '0.5') + static final String CLASS_METRIC_MISSED_COUNT = JacocoViolationRulesLimit.create('CLASS', 'MISSEDCOUNT', '0.5', null) + } + + private static String create(String counter, String value, String minimum, String maximum) { + StringBuilder limit = new StringBuilder() + limit <<= 'limit {\n' + + if (counter) { + limit <<= " counter = '${counter}'\n" + } + if (value) { + limit <<= " value = '${value}'\n" + } + if (minimum) { + limit <<= " minimum = $minimum\n" + } + if (maximum) { + limit <<= " maximum = $maximum\n" + } + + limit <<= '}' + limit.toString() + } +} From 41dcf72225dbfba1ba6bb884f22784d29b67cd04 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Tue, 6 Dec 2016 13:01:18 -0500 Subject: [PATCH 24/42] Reuse version number across all multi-version tests --- .../plugins/JacocoVersionIntegTest.groovy | 5 +- .../plugins/fixtures/JacocoCoverage.groovy | 82 +++++++++++++++++++ ...ageCompatibleVersionIntegrationTest.groovy | 5 +- ...eIncompatibleVersionIntegrationTest.groovy | 5 +- 4 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/fixtures/JacocoCoverage.groovy diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoVersionIntegTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoVersionIntegTest.groovy index e4ef17b047da..3d9f54c9d54d 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoVersionIntegTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoVersionIntegTest.groovy @@ -16,13 +16,14 @@ package org.gradle.testing.jacoco.plugins import org.gradle.integtests.fixtures.MultiVersionIntegrationSpec -import org.gradle.integtests.fixtures.TargetVersions +import org.gradle.integtests.fixtures.TargetCoverage +import org.gradle.testing.jacoco.plugins.fixtures.JacocoCoverage import org.gradle.testing.jacoco.plugins.fixtures.JavaProjectUnderTest import org.gradle.util.Requires import org.gradle.util.TestPrecondition @Requires(TestPrecondition.JDK7_OR_EARLIER) -@TargetVersions(['0.6.0.201210061924', '0.6.2.201302030002', '0.7.1.201405082137', '0.7.6.201602180812']) +@TargetCoverage({ JacocoCoverage.ALL }) class JacocoVersionIntegTest extends MultiVersionIntegrationSpec { private final JavaProjectUnderTest javaProjectUnderTest = new JavaProjectUnderTest(testDirectory) diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/fixtures/JacocoCoverage.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/fixtures/JacocoCoverage.groovy new file mode 100644 index 000000000000..2c6973053c1d --- /dev/null +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/fixtures/JacocoCoverage.groovy @@ -0,0 +1,82 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.testing.jacoco.plugins.fixtures + +final class JacocoCoverage { + + JacocoCoverage() {} + + final static String[] ALL = ['0.6.0.201210061924', '0.6.2.201302030002', '0.6.3.201306030806', '0.7.1.201405082137', '0.7.6.201602180812'].asImmutable() + + final static List COVERAGE_CHECK_SUPPORTED = ALL.findAll { + def jacocoVersion = new JacocoVersion(it) + def supportedJacocoVersion = JacocoVersion.CHECK_INTRODUCED + jacocoVersion.compareTo(supportedJacocoVersion) >= 0 + }.asImmutable() + + final static List COVERAGE_CHECK_UNSUPPORTED = ALL.findAll { + def jacocoVersion = new JacocoVersion(it) + def supportedJacocoVersion = JacocoVersion.CHECK_INTRODUCED + jacocoVersion.compareTo(supportedJacocoVersion) == -1 + }.asImmutable() + + private static class JacocoVersion implements Comparable { + final static CHECK_INTRODUCED = new JacocoVersion(0, 6, 3) + private final Integer major + private final Integer minor + private final Integer patch + + JacocoVersion(String version) { + def versionParts = version.split('\\.') + major = versionParts[0].toInteger() + minor = versionParts[1].toInteger() + patch = versionParts[2].toInteger() + } + + JacocoVersion(Integer major, Integer minor, Integer patch) { + this.major = major + this.minor = minor + this.patch = patch + } + + @Override + int compareTo(JacocoVersion o) { + if (major > o.major) { + return 1 + } + if (major < o.major) { + return -1 + } + + if (minor > o.minor) { + return 1 + } + if (minor < o.minor) { + return -1 + } + + if (patch > o.patch) { + return 1 + } + if (patch < o.patch) { + return -1 + } + + 0 + } + } +} diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageCompatibleVersionIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageCompatibleVersionIntegrationTest.groovy index 5c6bb91fda45..bcbfb8f80045 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageCompatibleVersionIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageCompatibleVersionIntegrationTest.groovy @@ -16,9 +16,10 @@ package org.gradle.testing.jacoco.plugins.rules -import org.gradle.integtests.fixtures.TargetVersions +import org.gradle.integtests.fixtures.TargetCoverage +import org.gradle.testing.jacoco.plugins.fixtures.JacocoCoverage -@TargetVersions(['0.6.3.201306030806', '0.7.1.201405082137', '0.7.6.201602180812']) +@TargetCoverage({ JacocoCoverage.COVERAGE_CHECK_SUPPORTED }) class JacocoPluginCheckCoverageCompatibleVersionIntegrationTest extends AbstractJacocoPluginCheckCoverageVersionIntegrationTest { def "can check code coverage for compatible versions"() { diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIncompatibleVersionIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIncompatibleVersionIntegrationTest.groovy index 5928823cde83..8700f4b64738 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIncompatibleVersionIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIncompatibleVersionIntegrationTest.groovy @@ -16,9 +16,10 @@ package org.gradle.testing.jacoco.plugins.rules -import org.gradle.integtests.fixtures.TargetVersions +import org.gradle.integtests.fixtures.TargetCoverage +import org.gradle.testing.jacoco.plugins.fixtures.JacocoCoverage -@TargetVersions(['0.6.2.201302030002']) +@TargetCoverage({ JacocoCoverage.COVERAGE_CHECK_UNSUPPORTED }) class JacocoPluginCheckCoverageIncompatibleVersionIntegrationTest extends AbstractJacocoPluginCheckCoverageVersionIntegrationTest { def "fails to check code coverage"() { From 0521afba096d49db92405ca9f4bd3d48c968cf6c Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Tue, 6 Dec 2016 13:03:16 -0500 Subject: [PATCH 25/42] Add missing word --- .../rules/JacocoPluginCheckCoverageIntegrationTest.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIntegrationTest.groovy index 05cad202d75f..4aa90c44ab7c 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIntegrationTest.groovy @@ -129,7 +129,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) } - def "can check rules even all report formats are disabled"() { + def "can check rules even if all report formats are disabled"() { given: buildFile << """ jacocoTestReport { From 6c63ff9cf2f344c6a7e00c23fbe2e9fe9f8f8ee4 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Tue, 6 Dec 2016 13:20:22 -0500 Subject: [PATCH 26/42] Use constant for task paths --- ...ractJacocoPluginCheckCoverageVersionIntegrationTest.groovy | 1 + ...PluginCheckCoverageCompatibleVersionIntegrationTest.groovy | 4 ++-- ...uginCheckCoverageIncompatibleVersionIntegrationTest.groovy | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/AbstractJacocoPluginCheckCoverageVersionIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/AbstractJacocoPluginCheckCoverageVersionIntegrationTest.groovy index f7330ae9f373..0acc0c5f435f 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/AbstractJacocoPluginCheckCoverageVersionIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/AbstractJacocoPluginCheckCoverageVersionIntegrationTest.groovy @@ -27,6 +27,7 @@ import static JacocoViolationRulesLimit.Sufficient abstract class AbstractJacocoPluginCheckCoverageVersionIntegrationTest extends MultiVersionIntegrationSpec { private final JavaProjectUnderTest javaProjectUnderTest = new JavaProjectUnderTest(testDirectory) + protected final static String[] TEST_AND_JACOCO_REPORT_TASK_PATHS = [':test', ':jacocoTestReport'] as String[] def setup() { javaProjectUnderTest.writeBuildScript().writeSourceFiles() diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageCompatibleVersionIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageCompatibleVersionIntegrationTest.groovy index bcbfb8f80045..242e2bc049db 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageCompatibleVersionIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageCompatibleVersionIntegrationTest.groovy @@ -24,9 +24,9 @@ class JacocoPluginCheckCoverageCompatibleVersionIntegrationTest extends Abstract def "can check code coverage for compatible versions"() { when: - succeeds 'test', 'jacocoTestReport' + succeeds TEST_AND_JACOCO_REPORT_TASK_PATHS then: - executedAndNotSkipped(':test', ':jacocoTestReport') + executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) } } diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIncompatibleVersionIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIncompatibleVersionIntegrationTest.groovy index 8700f4b64738..113cefaddbe1 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIncompatibleVersionIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIncompatibleVersionIntegrationTest.groovy @@ -24,10 +24,10 @@ class JacocoPluginCheckCoverageIncompatibleVersionIntegrationTest extends Abstra def "fails to check code coverage"() { when: - fails 'test', 'jacocoTestReport' + fails TEST_AND_JACOCO_REPORT_TASK_PATHS then: - executedAndNotSkipped(':test', ':jacocoTestReport') + executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) errorOutput.contains("jacocoReport doesn't support the nested \"check\" element.") } } \ No newline at end of file From db9494879999ae9b9c7ec6b4bb0cf20d65b93486 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Tue, 6 Dec 2016 18:38:37 -0500 Subject: [PATCH 27/42] Extract dedicated task for verifying if coverage metrics are met Results in better configurability for end user and decouples report generation from coverage verification. --- .../fixtures/JavaProjectUnderTest.groovy | 5 + ...CheckCoverageVersionIntegrationTest.groovy | 4 +- ...ageCompatibleVersionIntegrationTest.groovy | 4 +- ...eIncompatibleVersionIntegrationTest.groovy | 4 +- ...oPluginCheckCoverageIntegrationTest.groovy | 121 +++---- .../internal/jacoco/AntJacocoCheck.java | 148 ++++++++ .../internal/jacoco/AntJacocoReport.java | 97 +---- .../testing/jacoco/plugins/JacocoPlugin.java | 14 +- .../testing/jacoco/tasks/JacocoCheck.java | 333 ++++++++++++++++++ .../testing/jacoco/tasks/JacocoReport.java | 43 +-- 10 files changed, 569 insertions(+), 204 deletions(-) create mode 100644 subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoCheck.java create mode 100644 subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCheck.java diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/fixtures/JavaProjectUnderTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/fixtures/JavaProjectUnderTest.groovy index 9e3c6da6370f..9221fe357421 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/fixtures/JavaProjectUnderTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/fixtures/JavaProjectUnderTest.groovy @@ -75,6 +75,11 @@ class JavaProjectUnderTest { executionData integrationTest sourceSets sourceSets.main } + + task jacocoIntegrationTestCheck(type: JacocoCheck) { + executionData integrationTest + sourceSets sourceSets.main + } """ writeTestSourceFile(testSrcDir) diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/AbstractJacocoPluginCheckCoverageVersionIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/AbstractJacocoPluginCheckCoverageVersionIntegrationTest.groovy index 0acc0c5f435f..64f9f8eb36fe 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/AbstractJacocoPluginCheckCoverageVersionIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/AbstractJacocoPluginCheckCoverageVersionIntegrationTest.groovy @@ -27,7 +27,7 @@ import static JacocoViolationRulesLimit.Sufficient abstract class AbstractJacocoPluginCheckCoverageVersionIntegrationTest extends MultiVersionIntegrationSpec { private final JavaProjectUnderTest javaProjectUnderTest = new JavaProjectUnderTest(testDirectory) - protected final static String[] TEST_AND_JACOCO_REPORT_TASK_PATHS = [':test', ':jacocoTestReport'] as String[] + protected final static String[] TEST_AND_JACOCO_CHECK_TASK_PATHS = [':test', ':jacocoTestCheck'] as String[] def setup() { javaProjectUnderTest.writeBuildScript().writeSourceFiles() @@ -37,7 +37,7 @@ abstract class AbstractJacocoPluginCheckCoverageVersionIntegrationTest extends M toolVersion = '$version' } - jacocoTestReport { + jacocoTestCheck { violationRules { rule { $Sufficient.LINE_METRIC_COVERED_RATIO diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageCompatibleVersionIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageCompatibleVersionIntegrationTest.groovy index 242e2bc049db..897ebd952f90 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageCompatibleVersionIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageCompatibleVersionIntegrationTest.groovy @@ -24,9 +24,9 @@ class JacocoPluginCheckCoverageCompatibleVersionIntegrationTest extends Abstract def "can check code coverage for compatible versions"() { when: - succeeds TEST_AND_JACOCO_REPORT_TASK_PATHS + succeeds TEST_AND_JACOCO_CHECK_TASK_PATHS then: - executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) + executedAndNotSkipped(TEST_AND_JACOCO_CHECK_TASK_PATHS) } } diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIncompatibleVersionIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIncompatibleVersionIntegrationTest.groovy index 113cefaddbe1..629d31ea784c 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIncompatibleVersionIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIncompatibleVersionIntegrationTest.groovy @@ -24,10 +24,10 @@ class JacocoPluginCheckCoverageIncompatibleVersionIntegrationTest extends Abstra def "fails to check code coverage"() { when: - fails TEST_AND_JACOCO_REPORT_TASK_PATHS + fails TEST_AND_JACOCO_CHECK_TASK_PATHS then: - executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) + executedAndNotSkipped(TEST_AND_JACOCO_CHECK_TASK_PATHS) errorOutput.contains("jacocoReport doesn't support the nested \"check\" element.") } } \ No newline at end of file diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIntegrationTest.groovy index 4aa90c44ab7c..d33e341c84bc 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIntegrationTest.groovy @@ -27,9 +27,9 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { private final JavaProjectUnderTest javaProjectUnderTest = new JavaProjectUnderTest(testDirectory) private final static String[] TEST_TASK_PATH = [':test'] as String[] - private final static String[] JACOCO_REPORT_TASK_PATH = [':jacocoTestReport'] as String[] - private final static String[] TEST_AND_JACOCO_REPORT_TASK_PATHS = TEST_TASK_PATH + JACOCO_REPORT_TASK_PATH - private final static String[] INTEG_TEST_AND_JACOCO_REPORT_TASK_PATHS = [':integrationTest', ':jacocoIntegrationTestReport'] as String[] + private final static String[] JACOCO_CHECK_TASK_PATH = [':jacocoTestCheck'] as String[] + private final static String[] TEST_AND_JACOCO_CHECK_TASK_PATHS = TEST_TASK_PATH + JACOCO_CHECK_TASK_PATH + private final static String[] INTEG_TEST_AND_JACOCO_CHECK_TASK_PATHS = [':integrationTest', ':jacocoIntegrationTestCheck'] as String[] def setup() { javaProjectUnderTest.writeBuildScript().writeSourceFiles() @@ -38,22 +38,22 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { def "can define no rules"() { given: buildFile << """ - jacocoTestReport { + jacocoTestCheck { violationRules {} } """ when: - succeeds TEST_AND_JACOCO_REPORT_TASK_PATHS + succeeds TEST_AND_JACOCO_CHECK_TASK_PATHS then: - executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) + executedAndNotSkipped(TEST_AND_JACOCO_CHECK_TASK_PATHS) } def "can define single rule without limits"() { given: buildFile << """ - jacocoTestReport { + jacocoTestCheck { violationRules { rule {} } @@ -61,16 +61,16 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { """ when: - succeeds TEST_AND_JACOCO_REPORT_TASK_PATHS + succeeds TEST_AND_JACOCO_CHECK_TASK_PATHS then: - executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) + executedAndNotSkipped(TEST_AND_JACOCO_CHECK_TASK_PATHS) } def "Ant task reports error for unknown field value"() { given: buildFile << """ - jacocoTestReport { + jacocoTestCheck { violationRules { rule { element = 'UNKNOWN' @@ -80,17 +80,17 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { """ when: - fails TEST_AND_JACOCO_REPORT_TASK_PATHS + fails TEST_AND_JACOCO_CHECK_TASK_PATHS then: - executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) + executedAndNotSkipped(TEST_AND_JACOCO_CHECK_TASK_PATHS) errorOutput.contains("'UNKNOWN' is not a permitted value for org.jacoco.core.analysis.ICoverageNode\$ElementType") } def "can define includes for single rule"() { given: buildFile << """ - jacocoTestReport { + jacocoTestCheck { violationRules { rule { element = 'CLASS' @@ -102,17 +102,17 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { """ when: - fails TEST_AND_JACOCO_REPORT_TASK_PATHS + fails TEST_AND_JACOCO_CHECK_TASK_PATHS then: - executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) + executedAndNotSkipped(TEST_AND_JACOCO_CHECK_TASK_PATHS) errorOutput.contains("Rule violated for class org.gradle.Class1: lines covered ratio is 1.0, but expected maximum is 0.5") } def "can define excludes for single rule"() { given: buildFile << """ - jacocoTestReport { + jacocoTestCheck { violationRules { rule { excludes = ['company', '$testDirectory.name'] @@ -123,42 +123,17 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { """ when: - succeeds TEST_AND_JACOCO_REPORT_TASK_PATHS + succeeds TEST_AND_JACOCO_CHECK_TASK_PATHS then: - executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) - } - - def "can check rules even if all report formats are disabled"() { - given: - buildFile << """ - jacocoTestReport { - reports { - xml.enabled false - csv.enabled false - html.enabled false - } - violationRules { - rule { - $Insufficient.LINE_METRIC_COVERED_RATIO - } - } - } - """ - - when: - fails TEST_AND_JACOCO_REPORT_TASK_PATHS - - then: - executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) - errorOutput.contains("Rule violated for bundle $testDirectory.name: lines covered ratio is 1.0, but expected maximum is 0.5") + executedAndNotSkipped(TEST_AND_JACOCO_CHECK_TASK_PATHS) } @Unroll def "can define rule with sufficient coverage for #description"() { given: buildFile << """ - jacocoTestReport { + jacocoTestCheck { violationRules { rule { ${limits.join('\n')} @@ -168,10 +143,10 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { """ when: - succeeds TEST_AND_JACOCO_REPORT_TASK_PATHS + succeeds TEST_AND_JACOCO_CHECK_TASK_PATHS then: - executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) + executedAndNotSkipped(TEST_AND_JACOCO_CHECK_TASK_PATHS) where: limits | description @@ -186,7 +161,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { def "can define rule with insufficient coverage for #description"() { given: buildFile << """ - jacocoTestReport { + jacocoTestCheck { violationRules { rule { ${limits.join('\n')} @@ -196,10 +171,10 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { """ when: - fails TEST_AND_JACOCO_REPORT_TASK_PATHS + fails TEST_AND_JACOCO_CHECK_TASK_PATHS then: - executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) + executedAndNotSkipped(TEST_AND_JACOCO_CHECK_TASK_PATHS) errorOutput.contains("Rule violated for bundle $testDirectory.name: $errorMessage") where: @@ -216,7 +191,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { def "can define multiple rules"() { given: buildFile << """ - jacocoTestReport { + jacocoTestCheck { violationRules { rule { $Sufficient.LINE_METRIC_COVERED_RATIO @@ -229,17 +204,17 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { """ when: - fails TEST_AND_JACOCO_REPORT_TASK_PATHS + fails TEST_AND_JACOCO_CHECK_TASK_PATHS then: - executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) + executedAndNotSkipped(TEST_AND_JACOCO_CHECK_TASK_PATHS) errorOutput.contains("Rule violated for bundle $testDirectory.name: classes missed count is 0.0, but expected minimum is 0.5") } def "can disable rules"() { given: buildFile << """ - jacocoTestReport { + jacocoTestCheck { violationRules { rule { $Sufficient.LINE_METRIC_COVERED_RATIO @@ -253,16 +228,16 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { """ when: - succeeds TEST_AND_JACOCO_REPORT_TASK_PATHS + succeeds TEST_AND_JACOCO_CHECK_TASK_PATHS then: - executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) + executedAndNotSkipped(TEST_AND_JACOCO_CHECK_TASK_PATHS) } def "can ignore failures"() { given: buildFile << """ - jacocoTestReport { + jacocoTestCheck { violationRules { failOnViolation = true @@ -274,10 +249,10 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { """ when: - succeeds TEST_AND_JACOCO_REPORT_TASK_PATHS + succeeds TEST_AND_JACOCO_CHECK_TASK_PATHS then: - executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) + executedAndNotSkipped(TEST_AND_JACOCO_CHECK_TASK_PATHS) errorOutput.contains("Rule violated for bundle $testDirectory.name: lines covered ratio is 1.0, but expected maximum is 0.5") } @@ -287,7 +262,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { javaProjectUnderTest.writeIntegrationTestSourceFiles() buildFile << """ - tasks.withType(JacocoReport) { + tasks.withType(JacocoCheck) { violationRules { rule { $Insufficient.LINE_METRIC_COVERED_RATIO @@ -304,7 +279,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { errorOutput.contains("Rule violated for bundle $testDirectory.name: lines covered ratio is 1.0, but expected maximum is 0.5") where: - tasksPaths << [TEST_AND_JACOCO_REPORT_TASK_PATHS, INTEG_TEST_AND_JACOCO_REPORT_TASK_PATHS] + tasksPaths << [TEST_AND_JACOCO_CHECK_TASK_PATHS, INTEG_TEST_AND_JACOCO_CHECK_TASK_PATHS] } @Unroll @@ -330,14 +305,14 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { errorOutput.contains("Rule violated for bundle $testDirectory.name: $errorMessage") where: - tasksPaths | reportTaskName | limit | errorMessage - TEST_AND_JACOCO_REPORT_TASK_PATHS | 'jacocoTestReport' | Insufficient.LINE_METRIC_COVERED_RATIO | 'lines covered ratio is 1.0, but expected maximum is 0.5' - INTEG_TEST_AND_JACOCO_REPORT_TASK_PATHS | 'jacocoIntegrationTestReport' | Insufficient.CLASS_METRIC_MISSED_COUNT | 'classes missed count is 0.0, but expected minimum is 0.5' + tasksPaths | reportTaskName | limit | errorMessage + TEST_AND_JACOCO_CHECK_TASK_PATHS | 'jacocoTestCheck' | Insufficient.LINE_METRIC_COVERED_RATIO | 'lines covered ratio is 1.0, but expected maximum is 0.5' + INTEG_TEST_AND_JACOCO_CHECK_TASK_PATHS | 'jacocoIntegrationTestCheck' | Insufficient.CLASS_METRIC_MISSED_COUNT | 'classes missed count is 0.0, but expected minimum is 0.5' } - def "changes to violation rules re-run task"() { + def "task is never UP-TO-DATE as it does not define any outputs"() { buildFile << """ - jacocoTestReport { + jacocoTestCheck { violationRules { rule { $Sufficient.LINE_METRIC_COVERED_RATIO @@ -347,27 +322,27 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { """ when: - succeeds TEST_AND_JACOCO_REPORT_TASK_PATHS + succeeds TEST_AND_JACOCO_CHECK_TASK_PATHS then: - executedAndNotSkipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) + executedAndNotSkipped(TEST_AND_JACOCO_CHECK_TASK_PATHS) when: - succeeds TEST_AND_JACOCO_REPORT_TASK_PATHS + succeeds TEST_AND_JACOCO_CHECK_TASK_PATHS then: - executed(TEST_AND_JACOCO_REPORT_TASK_PATHS) - skipped(TEST_AND_JACOCO_REPORT_TASK_PATHS) + executed(JACOCO_CHECK_TASK_PATH) + skipped(TEST_TASK_PATH) when: buildFile << """ - jacocoTestReport.violationRules.rules[0].limits[0].maximum = 0.5 + jacocoTestCheck.violationRules.rules[0].limits[0].maximum = 0.5 """ - fails TEST_AND_JACOCO_REPORT_TASK_PATHS + fails TEST_AND_JACOCO_CHECK_TASK_PATHS then: - executed(JACOCO_REPORT_TASK_PATH) + executed(JACOCO_CHECK_TASK_PATH) skipped(TEST_TASK_PATH) errorOutput.contains("Rule violated for bundle $testDirectory.name: lines covered ratio is 1.0, but expected maximum is 0.5") } diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoCheck.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoCheck.java new file mode 100644 index 000000000000..20e3d5e08a86 --- /dev/null +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoCheck.java @@ -0,0 +1,148 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.jacoco; + +import com.google.common.base.Joiner; +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableMap; +import groovy.lang.Closure; +import groovy.lang.GroovyObjectSupport; +import org.gradle.api.file.FileCollection; +import org.gradle.api.internal.project.IsolatedAntBuilder; +import org.gradle.testing.jacoco.tasks.rules.JacocoLimit; +import org.gradle.testing.jacoco.tasks.rules.JacocoViolationRule; +import org.gradle.testing.jacoco.tasks.rules.JacocoViolationRulesContainer; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import static com.google.common.collect.Iterables.filter; + +public class AntJacocoCheck { + + private static final Predicate RULE_ENABLED_PREDICATE = new Predicate() { + @Override + public boolean apply(JacocoViolationRule rule) { + return rule.isEnabled(); + } + }; + + private final IsolatedAntBuilder ant; + + public AntJacocoCheck(IsolatedAntBuilder ant) { + this.ant = ant; + } + + public void execute(FileCollection classpath, final String projectName, + final FileCollection allClassesDirs, final FileCollection allSourcesDirs, + final FileCollection executionData, + final JacocoViolationRulesContainer violationRules) { + ant.withClasspath(classpath).execute(new Closure(this, this) { + @SuppressWarnings("UnusedDeclaration") + public Object doCall(Object it) { + final GroovyObjectSupport antBuilder = (GroovyObjectSupport) it; + antBuilder.invokeMethod("taskdef", ImmutableMap.of( + "name", "jacocoReport", + "classname", "org.jacoco.ant.ReportTask" + )); + final Map emptyArgs = Collections.emptyMap(); + antBuilder.invokeMethod("jacocoReport", new Object[]{emptyArgs, new Closure(this, this) { + public Object doCall(Object ignore) { + antBuilder.invokeMethod("executiondata", new Object[]{emptyArgs, new Closure(this, this) { + public Object doCall(Object ignore) { + executionData.addToAntBuilder(antBuilder, "resources"); + return null; + } + }}); + Map structureArgs = ImmutableMap.of("name", projectName); + antBuilder.invokeMethod("structure", new Object[]{structureArgs, new Closure(this, this) { + public Object doCall(Object ignore) { + antBuilder.invokeMethod("classfiles", new Object[]{emptyArgs, new Closure(this, this) { + public Object doCall(Object ignore) { + allClassesDirs.addToAntBuilder(antBuilder, "resources"); + return null; + } + }}); + antBuilder.invokeMethod("sourcefiles", new Object[]{emptyArgs, new Closure(this, this) { + public Object doCall(Object ignore) { + allSourcesDirs.addToAntBuilder(antBuilder, "resources"); + return null; + } + }}); + return null; + } + }}); + configureCheck(antBuilder, violationRules); + return null; + } + }}); + return null; + } + }); + } + + private void configureCheck(final GroovyObjectSupport antBuilder, final JacocoViolationRulesContainer violationRules) { + if (!violationRules.getRules().isEmpty()) { + Map checkArgs = ImmutableMap.of("failonviolation", !violationRules.isFailOnViolation()); + antBuilder.invokeMethod("check", new Object[] {checkArgs, new Closure(this, this) { + @SuppressWarnings("UnusedDeclaration") + public Object doCall(Object ignore) { + for (final JacocoViolationRule rule : filter(violationRules.getRules(), RULE_ENABLED_PREDICATE)) { + Map ruleArgs = new HashMap(); + + if (rule.getElement() != null) { + ruleArgs.put("element", rule.getElement()); + } + if (rule.getIncludes() != null && !rule.getIncludes().isEmpty()) { + ruleArgs.put("includes", Joiner.on(':').join(rule.getIncludes())); + } + if (rule.getExcludes() != null && !rule.getExcludes().isEmpty()) { + ruleArgs.put("excludes", Joiner.on(':').join(rule.getExcludes())); + } + + antBuilder.invokeMethod("rule", new Object[] {ImmutableMap.copyOf(ruleArgs), new Closure(this, this) { + @SuppressWarnings("UnusedDeclaration") + public Object doCall(Object ignore) { + for (JacocoLimit limit : rule.getLimits()) { + Map ruleArgs = new HashMap(); + + if (limit.getCounter() != null) { + ruleArgs.put("counter", limit.getCounter()); + } + if (limit.getValue() != null) { + ruleArgs.put("value", limit.getValue()); + } + if (limit.getMinimum() != null) { + ruleArgs.put("minimum", limit.getMinimum()); + } + if (limit.getMaximum() != null) { + ruleArgs.put("maximum", limit.getMaximum()); + } + + antBuilder.invokeMethod("limit", new Object[] {ImmutableMap.copyOf(ruleArgs) }); + } + return null; + } + }}); + } + return null; + } + }}); + } + } +} diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java index 7493576de1f3..061702e1888f 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java @@ -16,33 +16,18 @@ package org.gradle.internal.jacoco; -import com.google.common.base.Joiner; -import com.google.common.base.Predicate; import com.google.common.collect.ImmutableMap; import groovy.lang.Closure; import groovy.lang.GroovyObjectSupport; import org.gradle.api.file.FileCollection; import org.gradle.api.internal.project.IsolatedAntBuilder; import org.gradle.testing.jacoco.tasks.JacocoReportsContainer; -import org.gradle.testing.jacoco.tasks.rules.JacocoLimit; -import org.gradle.testing.jacoco.tasks.rules.JacocoViolationRule; -import org.gradle.testing.jacoco.tasks.rules.JacocoViolationRulesContainer; import java.util.Collections; -import java.util.HashMap; import java.util.Map; -import static com.google.common.collect.Iterables.filter; - public class AntJacocoReport { - private static final Predicate RULE_ENABLED_PREDICATE = new Predicate() { - @Override - public boolean apply(JacocoViolationRule rule) { - return rule.isEnabled(); - } - }; - private final IsolatedAntBuilder ant; public AntJacocoReport(IsolatedAntBuilder ant) { @@ -52,8 +37,7 @@ public AntJacocoReport(IsolatedAntBuilder ant) { public void execute(FileCollection classpath, final String projectName, final FileCollection allClassesDirs, final FileCollection allSourcesDirs, final FileCollection executionData, - final JacocoReportsContainer reports, - final JacocoViolationRulesContainer violationRules) { + final JacocoReportsContainer reports) { ant.withClasspath(classpath).execute(new Closure(this, this) { @SuppressWarnings("UnusedDeclaration") public Object doCall(Object it) { @@ -89,22 +73,7 @@ public Object doCall(Object ignore) { return null; } }}); - if (reports.getHtml().isEnabled()) { - antBuilder.invokeMethod("html", new Object[]{ - ImmutableMap.of("destdir", reports.getHtml().getDestination()) - }); - } - if (reports.getXml().isEnabled()) { - antBuilder.invokeMethod("xml", new Object[]{ - ImmutableMap.of("destfile", reports.getXml().getDestination()) - }); - } - if (reports.getCsv().isEnabled()) { - antBuilder.invokeMethod("csv", new Object[]{ - ImmutableMap.of("destfile", reports.getCsv().getDestination()) - }); - } - configureCheck(antBuilder, violationRules); + configureReportFormats(antBuilder, reports); return null; } }}); @@ -113,53 +82,21 @@ public Object doCall(Object ignore) { }); } - private void configureCheck(final GroovyObjectSupport antBuilder, final JacocoViolationRulesContainer violationRules) { - if (!violationRules.getRules().isEmpty()) { - Map checkArgs = ImmutableMap.of("failonviolation", !violationRules.isFailOnViolation()); - antBuilder.invokeMethod("check", new Object[] {checkArgs, new Closure(this, this) { - @SuppressWarnings("UnusedDeclaration") - public Object doCall(Object ignore) { - for (final JacocoViolationRule rule : filter(violationRules.getRules(), RULE_ENABLED_PREDICATE)) { - Map ruleArgs = new HashMap(); - - if (rule.getElement() != null) { - ruleArgs.put("element", rule.getElement()); - } - if (rule.getIncludes() != null && !rule.getIncludes().isEmpty()) { - ruleArgs.put("includes", Joiner.on(':').join(rule.getIncludes())); - } - if (rule.getExcludes() != null && !rule.getExcludes().isEmpty()) { - ruleArgs.put("excludes", Joiner.on(':').join(rule.getExcludes())); - } - - antBuilder.invokeMethod("rule", new Object[] {ImmutableMap.copyOf(ruleArgs), new Closure(this, this) { - @SuppressWarnings("UnusedDeclaration") - public Object doCall(Object ignore) { - for (JacocoLimit limit : rule.getLimits()) { - Map ruleArgs = new HashMap(); - - if (limit.getCounter() != null) { - ruleArgs.put("counter", limit.getCounter()); - } - if (limit.getValue() != null) { - ruleArgs.put("value", limit.getValue()); - } - if (limit.getMinimum() != null) { - ruleArgs.put("minimum", limit.getMinimum()); - } - if (limit.getMaximum() != null) { - ruleArgs.put("maximum", limit.getMaximum()); - } - - antBuilder.invokeMethod("limit", new Object[] {ImmutableMap.copyOf(ruleArgs) }); - } - return null; - } - }}); - } - return null; - } - }}); + private void configureReportFormats(GroovyObjectSupport antBuilder, JacocoReportsContainer reports) { + if (reports.getHtml().isEnabled()) { + antBuilder.invokeMethod("html", new Object[]{ + ImmutableMap.of("destdir", reports.getHtml().getDestination()) + }); + } + if (reports.getXml().isEnabled()) { + antBuilder.invokeMethod("xml", new Object[]{ + ImmutableMap.of("destfile", reports.getXml().getDestination()) + }); + } + if (reports.getCsv().isEnabled()) { + antBuilder.invokeMethod("csv", new Object[]{ + ImmutableMap.of("destfile", reports.getCsv().getDestination()) + }); } } } diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/plugins/JacocoPlugin.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/plugins/JacocoPlugin.java index 0a445c4998d7..a7a6b07fce4f 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/plugins/JacocoPlugin.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/plugins/JacocoPlugin.java @@ -35,6 +35,7 @@ import org.gradle.internal.jacoco.JacocoAgentJar; import org.gradle.internal.reflect.Instantiator; import org.gradle.testing.jacoco.tasks.JacocoBase; +import org.gradle.testing.jacoco.tasks.JacocoCheck; import org.gradle.testing.jacoco.tasks.JacocoMerge; import org.gradle.testing.jacoco.tasks.JacocoReport; @@ -78,7 +79,7 @@ public File call() { applyToDefaultTasks(extension); configureDefaultOutputPathForJacocoMerge(); configureJacocoReportsDefaults(extension); - addDefaultReportTasks(extension); + addDefaultReportAndCheckTasks(extension); } /** @@ -199,11 +200,11 @@ public File call() { } /** - * Adds report tasks for specific default test tasks. + * Adds report and check tasks for specific default test tasks. * * @param extension the extension describing the test task names */ - private void addDefaultReportTasks(final JacocoPluginExtension extension) { + private void addDefaultReportAndCheckTasks(final JacocoPluginExtension extension) { project.getPlugins().withType(JavaPlugin.class, new Action() { @Override public void execute(JavaPlugin javaPlugin) { @@ -212,6 +213,7 @@ public void execute(JavaPlugin javaPlugin) { public void execute(Test task) { if (task.getName().equals(JavaPlugin.TEST_TASK_NAME)) { addDefaultReportTask(extension, task); + addDefaultCheckTask(task); } } }); @@ -247,4 +249,10 @@ public File call() { } }); } + + private void addDefaultCheckTask(final Test task) { + final JacocoCheck checkTask = project.getTasks().create("jacoco" + StringUtils.capitalise(task.getName()) + "Check", JacocoCheck.class); + checkTask.executionData(task); + checkTask.sourceSets(project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets().getByName("main")); + } } diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCheck.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCheck.java new file mode 100644 index 000000000000..a31f7e237b18 --- /dev/null +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCheck.java @@ -0,0 +1,333 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.testing.jacoco.tasks; + +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; +import groovy.lang.Closure; +import groovy.lang.DelegatesTo; +import org.gradle.api.Action; +import org.gradle.api.Incubating; +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.file.FileCollection; +import org.gradle.api.internal.ClosureBackedAction; +import org.gradle.api.internal.project.IsolatedAntBuilder; +import org.gradle.api.specs.Spec; +import org.gradle.api.tasks.CacheableTask; +import org.gradle.api.tasks.InputFiles; +import org.gradle.api.tasks.Internal; +import org.gradle.api.tasks.Nested; +import org.gradle.api.tasks.Optional; +import org.gradle.api.tasks.PathSensitive; +import org.gradle.api.tasks.PathSensitivity; +import org.gradle.api.tasks.SourceSet; +import org.gradle.api.tasks.TaskAction; +import org.gradle.internal.jacoco.AntJacocoCheck; +import org.gradle.internal.jacoco.rules.JacocoViolationRulesContainerImpl; +import org.gradle.internal.reflect.Instantiator; +import org.gradle.testing.jacoco.plugins.JacocoTaskExtension; +import org.gradle.testing.jacoco.tasks.rules.JacocoViolationRulesContainer; + +import javax.inject.Inject; +import java.io.File; +import java.util.Arrays; +import java.util.concurrent.Callable; + +import static groovy.lang.Closure.DELEGATE_FIRST; + +/** + * Task for verifying code coverage metrics. Fails the task if violations are detected based on specified rules. + *

+ * Requires JaCoCo version >= 0.6.3. + * + * @since 4.0 + */ +@CacheableTask +@Incubating +public class JacocoCheck extends JacocoBase { + + private final JacocoViolationRulesContainer violationRules; + private FileCollection executionData; + private FileCollection sourceDirectories; + private FileCollection classDirectories; + private FileCollection additionalClassDirs; + private FileCollection additionalSourceDirs; + + public JacocoCheck() { + violationRules = getInstantiator().newInstance(JacocoViolationRulesContainerImpl.class); + onlyIf(new Spec() { + @Override + public boolean isSatisfiedBy(Task element) { + //TODO SF it should be 'any' instead of 'all' + return Iterables.all(getExecutionData(), new Predicate() { + @Override + public boolean apply(File file) { + return file.exists(); + } + + }); + } + + }); + } + + @Inject + protected Instantiator getInstantiator() { + throw new UnsupportedOperationException(); + } + + @Inject + protected IsolatedAntBuilder getAntBuilder() { + throw new UnsupportedOperationException(); + } + + /** + * Collection of execution data files to analyze. + */ + @PathSensitive(PathSensitivity.NONE) + @InputFiles + public FileCollection getExecutionData() { + return executionData; + } + + public void setExecutionData(FileCollection executionData) { + this.executionData = executionData; + } + + /** + * Adds execution data files to be used during coverage analysis. + * + * @param files one or more files to add + */ + public void executionData(Object... files) { + if (executionData == null) { + executionData = getProject().files(files); + } else { + executionData = executionData.plus(getProject().files(files)); + } + } + + /** + * Adds execution data generated by a task to the list of those used during coverage analysis. Only tasks with a {@link JacocoTaskExtension} will be included; all others will be ignored. + * + * @param tasks one or more tasks to add + */ + public void executionData(Task... tasks) { + for (Task task : tasks) { + final JacocoTaskExtension extension = task.getExtensions().findByType(JacocoTaskExtension.class); + if (extension != null) { + executionData(new Callable() { + @Override + public File call() { + return extension.getDestinationFile(); + } + }); + mustRunAfter(task); + } + } + } + + /** + * Source sets that coverage should be reported for. + */ + @PathSensitive(PathSensitivity.RELATIVE) + @InputFiles + public FileCollection getSourceDirectories() { + return sourceDirectories; + } + + public void setSourceDirectories(FileCollection sourceDirectories) { + this.sourceDirectories = sourceDirectories; + } + + /** + * Source sets that coverage should be reported for. + */ + @PathSensitive(PathSensitivity.RELATIVE) + @InputFiles + public FileCollection getClassDirectories() { + return classDirectories; + } + + public void setClassDirectories(FileCollection classDirectories) { + this.classDirectories = classDirectories; + } + + /** + * Gets the class directories that coverage will be reported for. All classes in these directories will be included in the report. + * + * @return class dirs to report coverage of + */ + @Internal + public FileCollection getAllClassDirs() { + FileCollection additionalDirs = getAdditionalClassDirs(); + if (additionalDirs == null) { + return classDirectories; + } + return classDirectories.plus(getAdditionalClassDirs()); + } + + /** + * Gets the source directories for the classes that will be reported on. Source will be obtained from these directories only for the classes included in the report. + * + * @return source directories for the classes reported on + * @see #getAllClassDirs() + */ + @Internal + public FileCollection getAllSourceDirs() { + FileCollection additionalDirs = getAdditionalSourceDirs(); + if (additionalDirs == null) { + return sourceDirectories; + } + return sourceDirectories.plus(getAdditionalSourceDirs()); + } + + /** + * Additional class dirs that coverage data should be reported for. + */ + @Optional + @PathSensitive(PathSensitivity.RELATIVE) + @InputFiles + public FileCollection getAdditionalClassDirs() { + return additionalClassDirs; + } + + public void setAdditionalClassDirs(FileCollection additionalClassDirs) { + this.additionalClassDirs = additionalClassDirs; + } + + /** + * Additional source dirs for the classes coverage data is being reported for. + */ + @Optional + @PathSensitive(PathSensitivity.RELATIVE) + @InputFiles + public FileCollection getAdditionalSourceDirs() { + return additionalSourceDirs; + } + + public void setAdditionalSourceDirs(FileCollection additionalSourceDirs) { + this.additionalSourceDirs = additionalSourceDirs; + } + + /** + * Adds additional class directories to those that will be included in the report. + * + * @param dirs a {@code FileCollection} of directories containing classes to report coverage of + */ + public void additionalClassDirs(FileCollection dirs) { + if (additionalClassDirs == null) { + additionalClassDirs = dirs; + } else { + additionalClassDirs = additionalClassDirs.plus(dirs); + } + } + + /** + * Adds additional source directories to be used for any classes included in the report. + * + * @param dirs one or more directories containing source files for the classes included in the report + */ + public void additionalSourceDirs(File... dirs) { + additionalSourceDirs(getProject().files(Arrays.asList(dirs))); + } + + /** + * Adds additional source directories to be used for any classes included in the report. + * + * @param dirs a {@code FileCollection} of directories containing source files for the classes included in the report + */ + public void additionalSourceDirs(FileCollection dirs) { + if (additionalSourceDirs == null) { + additionalSourceDirs = dirs; + } else { + additionalSourceDirs = additionalSourceDirs.plus(dirs); + } + } + + /** + * Adds a source set to the list to be reported on. The output of this source set will be used as classes to include in the report. The source for this source set will be used for any classes + * included in the report. + * + * @param sourceSets one or more source sets to report on + */ + public void sourceSets(final SourceSet... sourceSets) { + getProject().afterEvaluate(new Action() { + @Override + public void execute(Project project) { + for (SourceSet sourceSet : sourceSets) { + if (getSourceDirectories() == null) { + setSourceDirectories(getProject().files(sourceSet.getAllJava().getSrcDirs())); + } else { + setSourceDirectories(getSourceDirectories().plus(getProject().files(sourceSet.getAllJava().getSrcDirs()))); + } + if (getClassDirectories() == null) { + setClassDirectories(sourceSet.getOutput()); + } else { + setClassDirectories(getClassDirectories().plus(sourceSet.getOutput())); + } + } + } + }); + } + + /** + * Returns the violation rules set for this task. + * + * @return Violation rules container + */ + @Nested + public JacocoViolationRulesContainer getViolationRules() { + return violationRules; + } + + /** + * Configures the violation rules for this task. + */ + @Incubating + public JacocoViolationRulesContainer violationRules(@DelegatesTo(value = JacocoViolationRulesContainer.class, strategy = DELEGATE_FIRST) Closure closure) { + return violationRules(new ClosureBackedAction(closure)); + } + + /** + * Configures the violation rules for this task. + */ + @Incubating + public JacocoViolationRulesContainer violationRules(Action configureAction) { + configureAction.execute(violationRules); + return violationRules; + } + + @TaskAction + public void check() { + Spec fileExistsSpec = new Spec() { + @Override + public boolean isSatisfiedBy(File file) { + return file.exists(); + } + }; + new AntJacocoCheck(getAntBuilder()).execute( + getJacocoClasspath(), + getProject().getName(), + getAllClassDirs().filter(fileExistsSpec), + getAllSourceDirs().filter(fileExistsSpec), + getExecutionData(), + getViolationRules() + ); + } +} diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java index 897c8bd2cacb..3818b9923766 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java @@ -18,7 +18,6 @@ import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import groovy.lang.Closure; -import groovy.lang.DelegatesTo; import org.gradle.api.Action; import org.gradle.api.Incubating; import org.gradle.api.Project; @@ -40,18 +39,14 @@ import org.gradle.api.tasks.TaskCollection; import org.gradle.internal.jacoco.AntJacocoReport; import org.gradle.internal.jacoco.JacocoReportsContainerImpl; -import org.gradle.internal.jacoco.rules.JacocoViolationRulesContainerImpl; import org.gradle.internal.reflect.Instantiator; import org.gradle.testing.jacoco.plugins.JacocoTaskExtension; -import org.gradle.testing.jacoco.tasks.rules.JacocoViolationRulesContainer; import javax.inject.Inject; import java.io.File; import java.util.Arrays; import java.util.concurrent.Callable; -import static groovy.lang.Closure.DELEGATE_FIRST; - /** * Task to generate HTML, Xml and CSV reports of Jacoco coverage data. */ @@ -60,7 +55,6 @@ public class JacocoReport extends JacocoBase implements Reporting { private final JacocoReportsContainer reports; - private final JacocoViolationRulesContainer violationRules; private FileCollection executionData; private FileCollection sourceDirectories; @@ -70,7 +64,6 @@ public class JacocoReport extends JacocoBase implements Reporting() { @Override public boolean isSatisfiedBy(Task element) { @@ -106,18 +99,6 @@ public JacocoReportsContainer getReports() { return reports; } - /** - * Return the violation rules set for this task. - * - * @return Violation rules container - * @since 4.0 - */ - @Nested - @Incubating - public JacocoViolationRulesContainer getViolationRules() { - return violationRules; - } - /** * Configures the reports to be generated by this task. */ @@ -132,27 +113,6 @@ public JacocoReportsContainer reports(Action con return reports; } - /** - * Configures the violation rules for this task. Requires JaCoCo version >= 0.6.3. - * - * @since 4.0 - */ - @Incubating - public JacocoViolationRulesContainer violationRules(@DelegatesTo(value = JacocoViolationRulesContainer.class, strategy = DELEGATE_FIRST) Closure closure) { - return violationRules(new ClosureBackedAction(closure)); - } - - /** - * Configures the violation rules for this task. Requires JaCoCo version >= 0.6.3. - * - * @since 4.0 - */ - @Incubating - public JacocoViolationRulesContainer violationRules(Action configureAction) { - configureAction.execute(violationRules); - return violationRules; - } - /** * Collection of execution data files to analyze. */ @@ -234,8 +194,7 @@ public boolean isSatisfiedBy(File file) { getAllClassDirs().filter(fileExistsSpec), getAllSourceDirs().filter(fileExistsSpec), getExecutionData(), - getReports(), - getViolationRules() + getReports() ); } From f024a946445997203b0c38fc7fe3ce95b89982cd Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Tue, 6 Dec 2016 18:49:50 -0500 Subject: [PATCH 28/42] Input annotation make sure that requires properties are not null --- .../internal/jacoco/AntJacocoCheck.java | 31 +++++-------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoCheck.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoCheck.java index 20e3d5e08a86..770ec0bb79b7 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoCheck.java +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoCheck.java @@ -103,38 +103,23 @@ private void configureCheck(final GroovyObjectSupport antBuilder, final JacocoVi @SuppressWarnings("UnusedDeclaration") public Object doCall(Object ignore) { for (final JacocoViolationRule rule : filter(violationRules.getRules(), RULE_ENABLED_PREDICATE)) { - Map ruleArgs = new HashMap(); - - if (rule.getElement() != null) { - ruleArgs.put("element", rule.getElement()); - } - if (rule.getIncludes() != null && !rule.getIncludes().isEmpty()) { - ruleArgs.put("includes", Joiner.on(':').join(rule.getIncludes())); - } - if (rule.getExcludes() != null && !rule.getExcludes().isEmpty()) { - ruleArgs.put("excludes", Joiner.on(':').join(rule.getExcludes())); - } - - antBuilder.invokeMethod("rule", new Object[] {ImmutableMap.copyOf(ruleArgs), new Closure(this, this) { + Map ruleArgs = ImmutableMap.of("element", rule.getElement(), "includes", Joiner.on(':').join(rule.getIncludes()), "excludes", Joiner.on(':').join(rule.getExcludes())); + antBuilder.invokeMethod("rule", new Object[] {ruleArgs, new Closure(this, this) { @SuppressWarnings("UnusedDeclaration") public Object doCall(Object ignore) { for (JacocoLimit limit : rule.getLimits()) { - Map ruleArgs = new HashMap(); + Map limitArgs = new HashMap(); + limitArgs.put("counter", limit.getCounter()); + limitArgs.put("value", limit.getValue()); - if (limit.getCounter() != null) { - ruleArgs.put("counter", limit.getCounter()); - } - if (limit.getValue() != null) { - ruleArgs.put("value", limit.getValue()); - } if (limit.getMinimum() != null) { - ruleArgs.put("minimum", limit.getMinimum()); + limitArgs.put("minimum", limit.getMinimum()); } if (limit.getMaximum() != null) { - ruleArgs.put("maximum", limit.getMaximum()); + limitArgs.put("maximum", limit.getMaximum()); } - antBuilder.invokeMethod("limit", new Object[] {ImmutableMap.copyOf(ruleArgs) }); + antBuilder.invokeMethod("limit", new Object[] {ImmutableMap.copyOf(limitArgs) }); } return null; } From aa402c8022e785206780d7e30ec4eeac43a4eac4 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Tue, 6 Dec 2016 19:45:23 -0500 Subject: [PATCH 29/42] Reflect use of JacocoCheck task in documentation and sample --- .../testing/jacoco/quickstart/build.gradle | 2 +- .../testing/jacoco/tasks/JacocoCheck.java | 239 +----------------- 2 files changed, 3 insertions(+), 238 deletions(-) diff --git a/subprojects/docs/src/samples/testing/jacoco/quickstart/build.gradle b/subprojects/docs/src/samples/testing/jacoco/quickstart/build.gradle index 401566904800..0625c3656c53 100644 --- a/subprojects/docs/src/samples/testing/jacoco/quickstart/build.gradle +++ b/subprojects/docs/src/samples/testing/jacoco/quickstart/build.gradle @@ -58,7 +58,7 @@ jacocoTestReport { // END SNIPPET report-configuration // START SNIPPET violation-rules-configuration -jacocoTestReport { +jacocoTestCheck { violationRules { rule { limit { diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCheck.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCheck.java index a31f7e237b18..59cdcc3d6db7 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCheck.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCheck.java @@ -16,37 +16,20 @@ package org.gradle.testing.jacoco.tasks; -import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; import groovy.lang.Closure; import groovy.lang.DelegatesTo; import org.gradle.api.Action; import org.gradle.api.Incubating; -import org.gradle.api.Project; -import org.gradle.api.Task; -import org.gradle.api.file.FileCollection; import org.gradle.api.internal.ClosureBackedAction; -import org.gradle.api.internal.project.IsolatedAntBuilder; import org.gradle.api.specs.Spec; import org.gradle.api.tasks.CacheableTask; -import org.gradle.api.tasks.InputFiles; -import org.gradle.api.tasks.Internal; import org.gradle.api.tasks.Nested; -import org.gradle.api.tasks.Optional; -import org.gradle.api.tasks.PathSensitive; -import org.gradle.api.tasks.PathSensitivity; -import org.gradle.api.tasks.SourceSet; import org.gradle.api.tasks.TaskAction; import org.gradle.internal.jacoco.AntJacocoCheck; import org.gradle.internal.jacoco.rules.JacocoViolationRulesContainerImpl; -import org.gradle.internal.reflect.Instantiator; -import org.gradle.testing.jacoco.plugins.JacocoTaskExtension; import org.gradle.testing.jacoco.tasks.rules.JacocoViolationRulesContainer; -import javax.inject.Inject; import java.io.File; -import java.util.Arrays; -import java.util.concurrent.Callable; import static groovy.lang.Closure.DELEGATE_FIRST; @@ -59,231 +42,13 @@ */ @CacheableTask @Incubating -public class JacocoCheck extends JacocoBase { +public class JacocoCheck extends JacocoReportBase { private final JacocoViolationRulesContainer violationRules; - private FileCollection executionData; - private FileCollection sourceDirectories; - private FileCollection classDirectories; - private FileCollection additionalClassDirs; - private FileCollection additionalSourceDirs; public JacocoCheck() { + super(); violationRules = getInstantiator().newInstance(JacocoViolationRulesContainerImpl.class); - onlyIf(new Spec() { - @Override - public boolean isSatisfiedBy(Task element) { - //TODO SF it should be 'any' instead of 'all' - return Iterables.all(getExecutionData(), new Predicate() { - @Override - public boolean apply(File file) { - return file.exists(); - } - - }); - } - - }); - } - - @Inject - protected Instantiator getInstantiator() { - throw new UnsupportedOperationException(); - } - - @Inject - protected IsolatedAntBuilder getAntBuilder() { - throw new UnsupportedOperationException(); - } - - /** - * Collection of execution data files to analyze. - */ - @PathSensitive(PathSensitivity.NONE) - @InputFiles - public FileCollection getExecutionData() { - return executionData; - } - - public void setExecutionData(FileCollection executionData) { - this.executionData = executionData; - } - - /** - * Adds execution data files to be used during coverage analysis. - * - * @param files one or more files to add - */ - public void executionData(Object... files) { - if (executionData == null) { - executionData = getProject().files(files); - } else { - executionData = executionData.plus(getProject().files(files)); - } - } - - /** - * Adds execution data generated by a task to the list of those used during coverage analysis. Only tasks with a {@link JacocoTaskExtension} will be included; all others will be ignored. - * - * @param tasks one or more tasks to add - */ - public void executionData(Task... tasks) { - for (Task task : tasks) { - final JacocoTaskExtension extension = task.getExtensions().findByType(JacocoTaskExtension.class); - if (extension != null) { - executionData(new Callable() { - @Override - public File call() { - return extension.getDestinationFile(); - } - }); - mustRunAfter(task); - } - } - } - - /** - * Source sets that coverage should be reported for. - */ - @PathSensitive(PathSensitivity.RELATIVE) - @InputFiles - public FileCollection getSourceDirectories() { - return sourceDirectories; - } - - public void setSourceDirectories(FileCollection sourceDirectories) { - this.sourceDirectories = sourceDirectories; - } - - /** - * Source sets that coverage should be reported for. - */ - @PathSensitive(PathSensitivity.RELATIVE) - @InputFiles - public FileCollection getClassDirectories() { - return classDirectories; - } - - public void setClassDirectories(FileCollection classDirectories) { - this.classDirectories = classDirectories; - } - - /** - * Gets the class directories that coverage will be reported for. All classes in these directories will be included in the report. - * - * @return class dirs to report coverage of - */ - @Internal - public FileCollection getAllClassDirs() { - FileCollection additionalDirs = getAdditionalClassDirs(); - if (additionalDirs == null) { - return classDirectories; - } - return classDirectories.plus(getAdditionalClassDirs()); - } - - /** - * Gets the source directories for the classes that will be reported on. Source will be obtained from these directories only for the classes included in the report. - * - * @return source directories for the classes reported on - * @see #getAllClassDirs() - */ - @Internal - public FileCollection getAllSourceDirs() { - FileCollection additionalDirs = getAdditionalSourceDirs(); - if (additionalDirs == null) { - return sourceDirectories; - } - return sourceDirectories.plus(getAdditionalSourceDirs()); - } - - /** - * Additional class dirs that coverage data should be reported for. - */ - @Optional - @PathSensitive(PathSensitivity.RELATIVE) - @InputFiles - public FileCollection getAdditionalClassDirs() { - return additionalClassDirs; - } - - public void setAdditionalClassDirs(FileCollection additionalClassDirs) { - this.additionalClassDirs = additionalClassDirs; - } - - /** - * Additional source dirs for the classes coverage data is being reported for. - */ - @Optional - @PathSensitive(PathSensitivity.RELATIVE) - @InputFiles - public FileCollection getAdditionalSourceDirs() { - return additionalSourceDirs; - } - - public void setAdditionalSourceDirs(FileCollection additionalSourceDirs) { - this.additionalSourceDirs = additionalSourceDirs; - } - - /** - * Adds additional class directories to those that will be included in the report. - * - * @param dirs a {@code FileCollection} of directories containing classes to report coverage of - */ - public void additionalClassDirs(FileCollection dirs) { - if (additionalClassDirs == null) { - additionalClassDirs = dirs; - } else { - additionalClassDirs = additionalClassDirs.plus(dirs); - } - } - - /** - * Adds additional source directories to be used for any classes included in the report. - * - * @param dirs one or more directories containing source files for the classes included in the report - */ - public void additionalSourceDirs(File... dirs) { - additionalSourceDirs(getProject().files(Arrays.asList(dirs))); - } - - /** - * Adds additional source directories to be used for any classes included in the report. - * - * @param dirs a {@code FileCollection} of directories containing source files for the classes included in the report - */ - public void additionalSourceDirs(FileCollection dirs) { - if (additionalSourceDirs == null) { - additionalSourceDirs = dirs; - } else { - additionalSourceDirs = additionalSourceDirs.plus(dirs); - } - } - - /** - * Adds a source set to the list to be reported on. The output of this source set will be used as classes to include in the report. The source for this source set will be used for any classes - * included in the report. - * - * @param sourceSets one or more source sets to report on - */ - public void sourceSets(final SourceSet... sourceSets) { - getProject().afterEvaluate(new Action() { - @Override - public void execute(Project project) { - for (SourceSet sourceSet : sourceSets) { - if (getSourceDirectories() == null) { - setSourceDirectories(getProject().files(sourceSet.getAllJava().getSrcDirs())); - } else { - setSourceDirectories(getSourceDirectories().plus(getProject().files(sourceSet.getAllJava().getSrcDirs()))); - } - if (getClassDirectories() == null) { - setClassDirectories(sourceSet.getOutput()); - } else { - setClassDirectories(getClassDirectories().plus(sourceSet.getOutput())); - } - } - } - }); } /** From 08882e92605656e92edc8130b685c056ba03db34 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Tue, 6 Dec 2016 19:46:13 -0500 Subject: [PATCH 30/42] Revert change --- .../testing/jacoco/tasks/JacocoCheck.java | 239 +++++++++++++++++- 1 file changed, 237 insertions(+), 2 deletions(-) diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCheck.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCheck.java index 59cdcc3d6db7..a31f7e237b18 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCheck.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCheck.java @@ -16,20 +16,37 @@ package org.gradle.testing.jacoco.tasks; +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; import groovy.lang.Closure; import groovy.lang.DelegatesTo; import org.gradle.api.Action; import org.gradle.api.Incubating; +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.file.FileCollection; import org.gradle.api.internal.ClosureBackedAction; +import org.gradle.api.internal.project.IsolatedAntBuilder; import org.gradle.api.specs.Spec; import org.gradle.api.tasks.CacheableTask; +import org.gradle.api.tasks.InputFiles; +import org.gradle.api.tasks.Internal; import org.gradle.api.tasks.Nested; +import org.gradle.api.tasks.Optional; +import org.gradle.api.tasks.PathSensitive; +import org.gradle.api.tasks.PathSensitivity; +import org.gradle.api.tasks.SourceSet; import org.gradle.api.tasks.TaskAction; import org.gradle.internal.jacoco.AntJacocoCheck; import org.gradle.internal.jacoco.rules.JacocoViolationRulesContainerImpl; +import org.gradle.internal.reflect.Instantiator; +import org.gradle.testing.jacoco.plugins.JacocoTaskExtension; import org.gradle.testing.jacoco.tasks.rules.JacocoViolationRulesContainer; +import javax.inject.Inject; import java.io.File; +import java.util.Arrays; +import java.util.concurrent.Callable; import static groovy.lang.Closure.DELEGATE_FIRST; @@ -42,13 +59,231 @@ */ @CacheableTask @Incubating -public class JacocoCheck extends JacocoReportBase { +public class JacocoCheck extends JacocoBase { private final JacocoViolationRulesContainer violationRules; + private FileCollection executionData; + private FileCollection sourceDirectories; + private FileCollection classDirectories; + private FileCollection additionalClassDirs; + private FileCollection additionalSourceDirs; public JacocoCheck() { - super(); violationRules = getInstantiator().newInstance(JacocoViolationRulesContainerImpl.class); + onlyIf(new Spec() { + @Override + public boolean isSatisfiedBy(Task element) { + //TODO SF it should be 'any' instead of 'all' + return Iterables.all(getExecutionData(), new Predicate() { + @Override + public boolean apply(File file) { + return file.exists(); + } + + }); + } + + }); + } + + @Inject + protected Instantiator getInstantiator() { + throw new UnsupportedOperationException(); + } + + @Inject + protected IsolatedAntBuilder getAntBuilder() { + throw new UnsupportedOperationException(); + } + + /** + * Collection of execution data files to analyze. + */ + @PathSensitive(PathSensitivity.NONE) + @InputFiles + public FileCollection getExecutionData() { + return executionData; + } + + public void setExecutionData(FileCollection executionData) { + this.executionData = executionData; + } + + /** + * Adds execution data files to be used during coverage analysis. + * + * @param files one or more files to add + */ + public void executionData(Object... files) { + if (executionData == null) { + executionData = getProject().files(files); + } else { + executionData = executionData.plus(getProject().files(files)); + } + } + + /** + * Adds execution data generated by a task to the list of those used during coverage analysis. Only tasks with a {@link JacocoTaskExtension} will be included; all others will be ignored. + * + * @param tasks one or more tasks to add + */ + public void executionData(Task... tasks) { + for (Task task : tasks) { + final JacocoTaskExtension extension = task.getExtensions().findByType(JacocoTaskExtension.class); + if (extension != null) { + executionData(new Callable() { + @Override + public File call() { + return extension.getDestinationFile(); + } + }); + mustRunAfter(task); + } + } + } + + /** + * Source sets that coverage should be reported for. + */ + @PathSensitive(PathSensitivity.RELATIVE) + @InputFiles + public FileCollection getSourceDirectories() { + return sourceDirectories; + } + + public void setSourceDirectories(FileCollection sourceDirectories) { + this.sourceDirectories = sourceDirectories; + } + + /** + * Source sets that coverage should be reported for. + */ + @PathSensitive(PathSensitivity.RELATIVE) + @InputFiles + public FileCollection getClassDirectories() { + return classDirectories; + } + + public void setClassDirectories(FileCollection classDirectories) { + this.classDirectories = classDirectories; + } + + /** + * Gets the class directories that coverage will be reported for. All classes in these directories will be included in the report. + * + * @return class dirs to report coverage of + */ + @Internal + public FileCollection getAllClassDirs() { + FileCollection additionalDirs = getAdditionalClassDirs(); + if (additionalDirs == null) { + return classDirectories; + } + return classDirectories.plus(getAdditionalClassDirs()); + } + + /** + * Gets the source directories for the classes that will be reported on. Source will be obtained from these directories only for the classes included in the report. + * + * @return source directories for the classes reported on + * @see #getAllClassDirs() + */ + @Internal + public FileCollection getAllSourceDirs() { + FileCollection additionalDirs = getAdditionalSourceDirs(); + if (additionalDirs == null) { + return sourceDirectories; + } + return sourceDirectories.plus(getAdditionalSourceDirs()); + } + + /** + * Additional class dirs that coverage data should be reported for. + */ + @Optional + @PathSensitive(PathSensitivity.RELATIVE) + @InputFiles + public FileCollection getAdditionalClassDirs() { + return additionalClassDirs; + } + + public void setAdditionalClassDirs(FileCollection additionalClassDirs) { + this.additionalClassDirs = additionalClassDirs; + } + + /** + * Additional source dirs for the classes coverage data is being reported for. + */ + @Optional + @PathSensitive(PathSensitivity.RELATIVE) + @InputFiles + public FileCollection getAdditionalSourceDirs() { + return additionalSourceDirs; + } + + public void setAdditionalSourceDirs(FileCollection additionalSourceDirs) { + this.additionalSourceDirs = additionalSourceDirs; + } + + /** + * Adds additional class directories to those that will be included in the report. + * + * @param dirs a {@code FileCollection} of directories containing classes to report coverage of + */ + public void additionalClassDirs(FileCollection dirs) { + if (additionalClassDirs == null) { + additionalClassDirs = dirs; + } else { + additionalClassDirs = additionalClassDirs.plus(dirs); + } + } + + /** + * Adds additional source directories to be used for any classes included in the report. + * + * @param dirs one or more directories containing source files for the classes included in the report + */ + public void additionalSourceDirs(File... dirs) { + additionalSourceDirs(getProject().files(Arrays.asList(dirs))); + } + + /** + * Adds additional source directories to be used for any classes included in the report. + * + * @param dirs a {@code FileCollection} of directories containing source files for the classes included in the report + */ + public void additionalSourceDirs(FileCollection dirs) { + if (additionalSourceDirs == null) { + additionalSourceDirs = dirs; + } else { + additionalSourceDirs = additionalSourceDirs.plus(dirs); + } + } + + /** + * Adds a source set to the list to be reported on. The output of this source set will be used as classes to include in the report. The source for this source set will be used for any classes + * included in the report. + * + * @param sourceSets one or more source sets to report on + */ + public void sourceSets(final SourceSet... sourceSets) { + getProject().afterEvaluate(new Action() { + @Override + public void execute(Project project) { + for (SourceSet sourceSet : sourceSets) { + if (getSourceDirectories() == null) { + setSourceDirectories(getProject().files(sourceSet.getAllJava().getSrcDirs())); + } else { + setSourceDirectories(getSourceDirectories().plus(getProject().files(sourceSet.getAllJava().getSrcDirs()))); + } + if (getClassDirectories() == null) { + setClassDirectories(sourceSet.getOutput()); + } else { + setClassDirectories(getClassDirectories().plus(sourceSet.getOutput())); + } + } + } + }); } /** From 6b1f8d9e560089a4378e46d533b80937941dcf75 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Tue, 6 Dec 2016 19:46:30 -0500 Subject: [PATCH 31/42] Use JacocoCheck in documentation --- .../docs/src/docs/userguide/jacocoPlugin.xml | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/subprojects/docs/src/docs/userguide/jacocoPlugin.xml b/subprojects/docs/src/docs/userguide/jacocoPlugin.xml index ba9e78e0645b..13168c73b770 100644 --- a/subprojects/docs/src/docs/userguide/jacocoPlugin.xml +++ b/subprojects/docs/src/docs/userguide/jacocoPlugin.xml @@ -83,14 +83,19 @@
Enforcing code coverage metrics + + + This feature requires the use of JaCoCo version 0.6.3 or higher. + + - Every task of type can be configured to verify if code coverage - metrics are met based on configured rules. The methods - and - - are the main entry point of configuring rules. - It returns an instance of which provides - extensive configuration options. The build fails if any of the configured rules is not met. JaCoCo only reports the first violated rule. + The task can be used to verify if code coverage + metrics are met based on configured rules. Its API exposes two methods, + and + , + the main entry point for configuring rules. + Invoking any of those methods returns an instance of providing + extensive configuration options. The build fails if any of the configured rules are not met. JaCoCo only reports the first violated rule. Code coverage requirements can be specified for a project as a whole, for individual files, and for @@ -236,6 +241,16 @@ Generates code coverage report for the test task. + + + jacocoTestCheck + + - + + + + Verifies code coverage metrics based on specified rules for the test task. +
From 1eb517ce81ebb0266b2a1a8de88da29566130a2f Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Tue, 6 Dec 2016 20:00:01 -0500 Subject: [PATCH 32/42] Reuse task logic for JacocoReport and JacocoCheck --- ...radle.testing.jacoco.tasks.JacocoCheck.xml | 43 +++ ...adle.testing.jacoco.tasks.JacocoReport.xml | 28 +- ....testing.jacoco.tasks.JacocoReportBase.xml | 62 ++++ .../testing/jacoco/tasks/JacocoCheck.java | 239 +------------- .../testing/jacoco/tasks/JacocoReport.java | 264 +--------------- .../jacoco/tasks/JacocoReportBase.java | 294 ++++++++++++++++++ 6 files changed, 404 insertions(+), 526 deletions(-) create mode 100644 subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.tasks.JacocoCheck.xml create mode 100644 subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.tasks.JacocoReportBase.xml create mode 100644 subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReportBase.java diff --git a/subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.tasks.JacocoCheck.xml b/subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.tasks.JacocoCheck.xml new file mode 100644 index 000000000000..54cc660f3e4c --- /dev/null +++ b/subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.tasks.JacocoCheck.xml @@ -0,0 +1,43 @@ + + +
+
+ Properties + + + + + + + + + + +
NameDefault with jacoco plugin
violationRules +
+
+
+ Methods + + + + + + +
Name
+
+
\ No newline at end of file diff --git a/subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.tasks.JacocoReport.xml b/subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.tasks.JacocoReport.xml index 82e45484d7b8..d4caabc4c2dd 100644 --- a/subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.tasks.JacocoReport.xml +++ b/subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.tasks.JacocoReport.xml @@ -21,32 +21,9 @@ Name - Default with - jacoco - plugin - + Default with jacoco plugin - - executionData - - - - sourceDirectories - - - - classDirectories - - - - additionalClassDirs - - - - additionalSourceDirs - - reports @@ -61,9 +38,6 @@ Name - - executionData - \ No newline at end of file diff --git a/subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.tasks.JacocoReportBase.xml b/subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.tasks.JacocoReportBase.xml new file mode 100644 index 000000000000..9ff5b8f8eb00 --- /dev/null +++ b/subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.tasks.JacocoReportBase.xml @@ -0,0 +1,62 @@ + + +
+
+ Properties + + + + + + + + + + + + + + + + + + + + + + +
NameDefault with jacoco plugin
executionData +
sourceDirectories +
classDirectories +
additionalClassDirs +
additionalSourceDirs +
+
+
+ Methods + + + + + + + + + +
Name
executionData
+
+
\ No newline at end of file diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCheck.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCheck.java index a31f7e237b18..59cdcc3d6db7 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCheck.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCheck.java @@ -16,37 +16,20 @@ package org.gradle.testing.jacoco.tasks; -import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; import groovy.lang.Closure; import groovy.lang.DelegatesTo; import org.gradle.api.Action; import org.gradle.api.Incubating; -import org.gradle.api.Project; -import org.gradle.api.Task; -import org.gradle.api.file.FileCollection; import org.gradle.api.internal.ClosureBackedAction; -import org.gradle.api.internal.project.IsolatedAntBuilder; import org.gradle.api.specs.Spec; import org.gradle.api.tasks.CacheableTask; -import org.gradle.api.tasks.InputFiles; -import org.gradle.api.tasks.Internal; import org.gradle.api.tasks.Nested; -import org.gradle.api.tasks.Optional; -import org.gradle.api.tasks.PathSensitive; -import org.gradle.api.tasks.PathSensitivity; -import org.gradle.api.tasks.SourceSet; import org.gradle.api.tasks.TaskAction; import org.gradle.internal.jacoco.AntJacocoCheck; import org.gradle.internal.jacoco.rules.JacocoViolationRulesContainerImpl; -import org.gradle.internal.reflect.Instantiator; -import org.gradle.testing.jacoco.plugins.JacocoTaskExtension; import org.gradle.testing.jacoco.tasks.rules.JacocoViolationRulesContainer; -import javax.inject.Inject; import java.io.File; -import java.util.Arrays; -import java.util.concurrent.Callable; import static groovy.lang.Closure.DELEGATE_FIRST; @@ -59,231 +42,13 @@ */ @CacheableTask @Incubating -public class JacocoCheck extends JacocoBase { +public class JacocoCheck extends JacocoReportBase { private final JacocoViolationRulesContainer violationRules; - private FileCollection executionData; - private FileCollection sourceDirectories; - private FileCollection classDirectories; - private FileCollection additionalClassDirs; - private FileCollection additionalSourceDirs; public JacocoCheck() { + super(); violationRules = getInstantiator().newInstance(JacocoViolationRulesContainerImpl.class); - onlyIf(new Spec() { - @Override - public boolean isSatisfiedBy(Task element) { - //TODO SF it should be 'any' instead of 'all' - return Iterables.all(getExecutionData(), new Predicate() { - @Override - public boolean apply(File file) { - return file.exists(); - } - - }); - } - - }); - } - - @Inject - protected Instantiator getInstantiator() { - throw new UnsupportedOperationException(); - } - - @Inject - protected IsolatedAntBuilder getAntBuilder() { - throw new UnsupportedOperationException(); - } - - /** - * Collection of execution data files to analyze. - */ - @PathSensitive(PathSensitivity.NONE) - @InputFiles - public FileCollection getExecutionData() { - return executionData; - } - - public void setExecutionData(FileCollection executionData) { - this.executionData = executionData; - } - - /** - * Adds execution data files to be used during coverage analysis. - * - * @param files one or more files to add - */ - public void executionData(Object... files) { - if (executionData == null) { - executionData = getProject().files(files); - } else { - executionData = executionData.plus(getProject().files(files)); - } - } - - /** - * Adds execution data generated by a task to the list of those used during coverage analysis. Only tasks with a {@link JacocoTaskExtension} will be included; all others will be ignored. - * - * @param tasks one or more tasks to add - */ - public void executionData(Task... tasks) { - for (Task task : tasks) { - final JacocoTaskExtension extension = task.getExtensions().findByType(JacocoTaskExtension.class); - if (extension != null) { - executionData(new Callable() { - @Override - public File call() { - return extension.getDestinationFile(); - } - }); - mustRunAfter(task); - } - } - } - - /** - * Source sets that coverage should be reported for. - */ - @PathSensitive(PathSensitivity.RELATIVE) - @InputFiles - public FileCollection getSourceDirectories() { - return sourceDirectories; - } - - public void setSourceDirectories(FileCollection sourceDirectories) { - this.sourceDirectories = sourceDirectories; - } - - /** - * Source sets that coverage should be reported for. - */ - @PathSensitive(PathSensitivity.RELATIVE) - @InputFiles - public FileCollection getClassDirectories() { - return classDirectories; - } - - public void setClassDirectories(FileCollection classDirectories) { - this.classDirectories = classDirectories; - } - - /** - * Gets the class directories that coverage will be reported for. All classes in these directories will be included in the report. - * - * @return class dirs to report coverage of - */ - @Internal - public FileCollection getAllClassDirs() { - FileCollection additionalDirs = getAdditionalClassDirs(); - if (additionalDirs == null) { - return classDirectories; - } - return classDirectories.plus(getAdditionalClassDirs()); - } - - /** - * Gets the source directories for the classes that will be reported on. Source will be obtained from these directories only for the classes included in the report. - * - * @return source directories for the classes reported on - * @see #getAllClassDirs() - */ - @Internal - public FileCollection getAllSourceDirs() { - FileCollection additionalDirs = getAdditionalSourceDirs(); - if (additionalDirs == null) { - return sourceDirectories; - } - return sourceDirectories.plus(getAdditionalSourceDirs()); - } - - /** - * Additional class dirs that coverage data should be reported for. - */ - @Optional - @PathSensitive(PathSensitivity.RELATIVE) - @InputFiles - public FileCollection getAdditionalClassDirs() { - return additionalClassDirs; - } - - public void setAdditionalClassDirs(FileCollection additionalClassDirs) { - this.additionalClassDirs = additionalClassDirs; - } - - /** - * Additional source dirs for the classes coverage data is being reported for. - */ - @Optional - @PathSensitive(PathSensitivity.RELATIVE) - @InputFiles - public FileCollection getAdditionalSourceDirs() { - return additionalSourceDirs; - } - - public void setAdditionalSourceDirs(FileCollection additionalSourceDirs) { - this.additionalSourceDirs = additionalSourceDirs; - } - - /** - * Adds additional class directories to those that will be included in the report. - * - * @param dirs a {@code FileCollection} of directories containing classes to report coverage of - */ - public void additionalClassDirs(FileCollection dirs) { - if (additionalClassDirs == null) { - additionalClassDirs = dirs; - } else { - additionalClassDirs = additionalClassDirs.plus(dirs); - } - } - - /** - * Adds additional source directories to be used for any classes included in the report. - * - * @param dirs one or more directories containing source files for the classes included in the report - */ - public void additionalSourceDirs(File... dirs) { - additionalSourceDirs(getProject().files(Arrays.asList(dirs))); - } - - /** - * Adds additional source directories to be used for any classes included in the report. - * - * @param dirs a {@code FileCollection} of directories containing source files for the classes included in the report - */ - public void additionalSourceDirs(FileCollection dirs) { - if (additionalSourceDirs == null) { - additionalSourceDirs = dirs; - } else { - additionalSourceDirs = additionalSourceDirs.plus(dirs); - } - } - - /** - * Adds a source set to the list to be reported on. The output of this source set will be used as classes to include in the report. The source for this source set will be used for any classes - * included in the report. - * - * @param sourceSets one or more source sets to report on - */ - public void sourceSets(final SourceSet... sourceSets) { - getProject().afterEvaluate(new Action() { - @Override - public void execute(Project project) { - for (SourceSet sourceSet : sourceSets) { - if (getSourceDirectories() == null) { - setSourceDirectories(getProject().files(sourceSet.getAllJava().getSrcDirs())); - } else { - setSourceDirectories(getSourceDirectories().plus(getProject().files(sourceSet.getAllJava().getSrcDirs()))); - } - if (getClassDirectories() == null) { - setClassDirectories(sourceSet.getOutput()); - } else { - setClassDirectories(getClassDirectories().plus(sourceSet.getOutput())); - } - } - } - }); } /** diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java index 3818b9923766..d9eb449a099b 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java @@ -15,79 +15,32 @@ */ package org.gradle.testing.jacoco.tasks; -import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; import groovy.lang.Closure; import org.gradle.api.Action; import org.gradle.api.Incubating; -import org.gradle.api.Project; -import org.gradle.api.Task; -import org.gradle.api.file.FileCollection; import org.gradle.api.internal.ClosureBackedAction; -import org.gradle.api.internal.project.IsolatedAntBuilder; import org.gradle.api.reporting.Reporting; import org.gradle.api.specs.Spec; import org.gradle.api.tasks.CacheableTask; -import org.gradle.api.tasks.InputFiles; -import org.gradle.api.tasks.Internal; import org.gradle.api.tasks.Nested; -import org.gradle.api.tasks.Optional; -import org.gradle.api.tasks.PathSensitive; -import org.gradle.api.tasks.PathSensitivity; -import org.gradle.api.tasks.SourceSet; import org.gradle.api.tasks.TaskAction; -import org.gradle.api.tasks.TaskCollection; import org.gradle.internal.jacoco.AntJacocoReport; import org.gradle.internal.jacoco.JacocoReportsContainerImpl; -import org.gradle.internal.reflect.Instantiator; -import org.gradle.testing.jacoco.plugins.JacocoTaskExtension; -import javax.inject.Inject; import java.io.File; -import java.util.Arrays; -import java.util.concurrent.Callable; /** * Task to generate HTML, Xml and CSV reports of Jacoco coverage data. */ @CacheableTask @Incubating -public class JacocoReport extends JacocoBase implements Reporting { +public class JacocoReport extends JacocoReportBase implements Reporting { private final JacocoReportsContainer reports; - private FileCollection executionData; - private FileCollection sourceDirectories; - private FileCollection classDirectories; - private FileCollection additionalClassDirs; - private FileCollection additionalSourceDirs; - public JacocoReport() { + super(); reports = getInstantiator().newInstance(JacocoReportsContainerImpl.class, this); - onlyIf(new Spec() { - @Override - public boolean isSatisfiedBy(Task element) { - //TODO SF it should be 'any' instead of 'all' - return Iterables.all(getExecutionData(), new Predicate() { - @Override - public boolean apply(File file) { - return file.exists(); - } - - }); - } - - }); - } - - @Inject - protected Instantiator getInstantiator() { - throw new UnsupportedOperationException(); - } - - @Inject - protected IsolatedAntBuilder getAntBuilder() { - throw new UnsupportedOperationException(); } /** @@ -113,73 +66,6 @@ public JacocoReportsContainer reports(Action con return reports; } - /** - * Collection of execution data files to analyze. - */ - @PathSensitive(PathSensitivity.NONE) - @InputFiles - public FileCollection getExecutionData() { - return executionData; - } - - public void setExecutionData(FileCollection executionData) { - this.executionData = executionData; - } - - /** - * Source sets that coverage should be reported for. - */ - @PathSensitive(PathSensitivity.RELATIVE) - @InputFiles - public FileCollection getSourceDirectories() { - return sourceDirectories; - } - - public void setSourceDirectories(FileCollection sourceDirectories) { - this.sourceDirectories = sourceDirectories; - } - - /** - * Source sets that coverage should be reported for. - */ - @PathSensitive(PathSensitivity.RELATIVE) - @InputFiles - public FileCollection getClassDirectories() { - return classDirectories; - } - - public void setClassDirectories(FileCollection classDirectories) { - this.classDirectories = classDirectories; - } - - /** - * Additional class dirs that coverage data should be reported for. - */ - @Optional - @PathSensitive(PathSensitivity.RELATIVE) - @InputFiles - public FileCollection getAdditionalClassDirs() { - return additionalClassDirs; - } - - public void setAdditionalClassDirs(FileCollection additionalClassDirs) { - this.additionalClassDirs = additionalClassDirs; - } - - /** - * Additional source dirs for the classes coverage data is being reported for. - */ - @Optional - @PathSensitive(PathSensitivity.RELATIVE) - @InputFiles - public FileCollection getAdditionalSourceDirs() { - return additionalSourceDirs; - } - - public void setAdditionalSourceDirs(FileCollection additionalSourceDirs) { - this.additionalSourceDirs = additionalSourceDirs; - } - @TaskAction public void generate() { Spec fileExistsSpec = new Spec() { @@ -197,150 +83,4 @@ public boolean isSatisfiedBy(File file) { getReports() ); } - - /** - * Adds execution data files to be used during coverage analysis. - * - * @param files one or more files to add - */ - public void executionData(Object... files) { - if (executionData == null) { - executionData = getProject().files(files); - } else { - executionData = executionData.plus(getProject().files(files)); - } - } - - /** - * Adds execution data generated by a task to the list of those used during coverage analysis. Only tasks with a {@link JacocoTaskExtension} will be included; all others will be ignored. - * - * @param tasks one or more tasks to add - */ - public void executionData(Task... tasks) { - for (Task task : tasks) { - final JacocoTaskExtension extension = task.getExtensions().findByType(JacocoTaskExtension.class); - if (extension != null) { - executionData(new Callable() { - @Override - public File call() { - return extension.getDestinationFile(); - } - }); - mustRunAfter(task); - } - } - } - - /** - * Adds execution data generated by the given tasks to the list of those used during coverage analysis. Only tasks with a {@link JacocoTaskExtension} will be included; all others will be ignored. - * - * @param tasks one or more tasks to add - */ - public void executionData(TaskCollection tasks) { - tasks.all(new Action() { - @Override - public void execute(Task task) { - executionData(task); - } - }); - } - - /** - * Gets the class directories that coverage will be reported for. All classes in these directories will be included in the report. - * - * @return class dirs to report coverage of - */ - @Internal - public FileCollection getAllClassDirs() { - FileCollection additionalDirs = getAdditionalClassDirs(); - if (additionalDirs == null) { - return classDirectories; - } - return classDirectories.plus(getAdditionalClassDirs()); - } - - /** - * Gets the source directories for the classes that will be reported on. Source will be obtained from these directories only for the classes included in the report. - * - * @return source directories for the classes reported on - * @see #getAllClassDirs() - */ - @Internal - public FileCollection getAllSourceDirs() { - FileCollection additionalDirs = getAdditionalSourceDirs(); - if (additionalDirs == null) { - return sourceDirectories; - } - return sourceDirectories.plus(getAdditionalSourceDirs()); - } - - /** - * Adds a source set to the list to be reported on. The output of this source set will be used as classes to include in the report. The source for this source set will be used for any classes - * included in the report. - * - * @param sourceSets one or more source sets to report on - */ - public void sourceSets(final SourceSet... sourceSets) { - getProject().afterEvaluate(new Action() { - @Override - public void execute(Project project) { - for (SourceSet sourceSet : sourceSets) { - if (getSourceDirectories() == null) { - setSourceDirectories(getProject().files(sourceSet.getAllJava().getSrcDirs())); - } else { - setSourceDirectories(getSourceDirectories().plus(getProject().files(sourceSet.getAllJava().getSrcDirs()))); - } - if (getClassDirectories() == null) { - setClassDirectories(sourceSet.getOutput()); - } else { - setClassDirectories(getClassDirectories().plus(sourceSet.getOutput())); - } - } - } - }); - } - - /** - * Adds additional class directories to those that will be included in the report. - * - * @param dirs one or more directories containing classes to report coverage of - */ - public void additionalClassDirs(File... dirs) { - additionalClassDirs(getProject().files(Arrays.asList(dirs))); - } - - /** - * Adds additional class directories to those that will be included in the report. - * - * @param dirs a {@code FileCollection} of directories containing classes to report coverage of - */ - public void additionalClassDirs(FileCollection dirs) { - if (additionalClassDirs == null) { - additionalClassDirs = dirs; - } else { - additionalClassDirs = additionalClassDirs.plus(dirs); - } - } - - /** - * Adds additional source directories to be used for any classes included in the report. - * - * @param dirs one or more directories containing source files for the classes included in the report - */ - public void additionalSourceDirs(File... dirs) { - additionalSourceDirs(getProject().files(Arrays.asList(dirs))); - } - - /** - * Adds additional source directories to be used for any classes included in the report. - * - * @param dirs a {@code FileCollection} of directories containing source files for the classes included in the report - */ - public void additionalSourceDirs(FileCollection dirs) { - if (additionalSourceDirs == null) { - additionalSourceDirs = dirs; - } else { - additionalSourceDirs = additionalSourceDirs.plus(dirs); - } - } } diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReportBase.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReportBase.java new file mode 100644 index 000000000000..e53cb633b227 --- /dev/null +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReportBase.java @@ -0,0 +1,294 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.testing.jacoco.tasks; + +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; +import org.gradle.api.Action; +import org.gradle.api.Incubating; +import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.api.file.FileCollection; +import org.gradle.api.internal.project.IsolatedAntBuilder; +import org.gradle.api.specs.Spec; +import org.gradle.api.tasks.InputFiles; +import org.gradle.api.tasks.Internal; +import org.gradle.api.tasks.Optional; +import org.gradle.api.tasks.PathSensitive; +import org.gradle.api.tasks.PathSensitivity; +import org.gradle.api.tasks.SourceSet; +import org.gradle.api.tasks.TaskCollection; +import org.gradle.internal.reflect.Instantiator; +import org.gradle.testing.jacoco.plugins.JacocoTaskExtension; + +import javax.inject.Inject; +import java.io.File; +import java.util.Arrays; +import java.util.concurrent.Callable; + +/** + * Base class for Jacoco report tasks. + */ +@Incubating +public abstract class JacocoReportBase extends JacocoBase { + + private FileCollection executionData; + private FileCollection sourceDirectories; + private FileCollection classDirectories; + private FileCollection additionalClassDirs; + private FileCollection additionalSourceDirs; + + public JacocoReportBase() { + onlyIf(new Spec() { + @Override + public boolean isSatisfiedBy(Task element) { + //TODO SF it should be 'any' instead of 'all' + return Iterables.all(getExecutionData(), new Predicate() { + @Override + public boolean apply(File file) { + return file.exists(); + } + + }); + } + + }); + } + + @Inject + protected Instantiator getInstantiator() { + throw new UnsupportedOperationException(); + } + + @Inject + protected IsolatedAntBuilder getAntBuilder() { + throw new UnsupportedOperationException(); + } + + /** + * Collection of execution data files to analyze. + */ + @PathSensitive(PathSensitivity.NONE) + @InputFiles + public FileCollection getExecutionData() { + return executionData; + } + + public void setExecutionData(FileCollection executionData) { + this.executionData = executionData; + } + + /** + * Source sets that coverage should be reported for. + */ + @PathSensitive(PathSensitivity.RELATIVE) + @InputFiles + public FileCollection getSourceDirectories() { + return sourceDirectories; + } + + public void setSourceDirectories(FileCollection sourceDirectories) { + this.sourceDirectories = sourceDirectories; + } + + /** + * Source sets that coverage should be reported for. + */ + @PathSensitive(PathSensitivity.RELATIVE) + @InputFiles + public FileCollection getClassDirectories() { + return classDirectories; + } + + public void setClassDirectories(FileCollection classDirectories) { + this.classDirectories = classDirectories; + } + + /** + * Additional class dirs that coverage data should be reported for. + */ + @Optional + @PathSensitive(PathSensitivity.RELATIVE) + @InputFiles + public FileCollection getAdditionalClassDirs() { + return additionalClassDirs; + } + + public void setAdditionalClassDirs(FileCollection additionalClassDirs) { + this.additionalClassDirs = additionalClassDirs; + } + + /** + * Additional source dirs for the classes coverage data is being reported for. + */ + @Optional + @PathSensitive(PathSensitivity.RELATIVE) + @InputFiles + public FileCollection getAdditionalSourceDirs() { + return additionalSourceDirs; + } + + public void setAdditionalSourceDirs(FileCollection additionalSourceDirs) { + this.additionalSourceDirs = additionalSourceDirs; + } + + /** + * Adds execution data files to be used during coverage analysis. + * + * @param files one or more files to add + */ + public void executionData(Object... files) { + if (executionData == null) { + executionData = getProject().files(files); + } else { + executionData = executionData.plus(getProject().files(files)); + } + } + + /** + * Adds execution data generated by a task to the list of those used during coverage analysis. Only tasks with a {@link JacocoTaskExtension} will be included; all others will be ignored. + * + * @param tasks one or more tasks to add + */ + public void executionData(Task... tasks) { + for (Task task : tasks) { + final JacocoTaskExtension extension = task.getExtensions().findByType(JacocoTaskExtension.class); + if (extension != null) { + executionData(new Callable() { + @Override + public File call() { + return extension.getDestinationFile(); + } + }); + mustRunAfter(task); + } + } + } + + /** + * Adds execution data generated by the given tasks to the list of those used during coverage analysis. Only tasks with a {@link JacocoTaskExtension} will be included; all others will be ignored. + * + * @param tasks one or more tasks to add + */ + public void executionData(TaskCollection tasks) { + tasks.all(new Action() { + @Override + public void execute(Task task) { + executionData(task); + } + }); + } + + /** + * Gets the class directories that coverage will be reported for. All classes in these directories will be included in the report. + * + * @return class dirs to report coverage of + */ + @Internal + public FileCollection getAllClassDirs() { + FileCollection additionalDirs = getAdditionalClassDirs(); + if (additionalDirs == null) { + return classDirectories; + } + return classDirectories.plus(getAdditionalClassDirs()); + } + + /** + * Gets the source directories for the classes that will be reported on. Source will be obtained from these directories only for the classes included in the report. + * + * @return source directories for the classes reported on + * @see #getAllClassDirs() + */ + @Internal + public FileCollection getAllSourceDirs() { + FileCollection additionalDirs = getAdditionalSourceDirs(); + if (additionalDirs == null) { + return sourceDirectories; + } + return sourceDirectories.plus(getAdditionalSourceDirs()); + } + + /** + * Adds a source set to the list to be reported on. The output of this source set will be used as classes to include in the report. The source for this source set will be used for any classes + * included in the report. + * + * @param sourceSets one or more source sets to report on + */ + public void sourceSets(final SourceSet... sourceSets) { + getProject().afterEvaluate(new Action() { + @Override + public void execute(Project project) { + for (SourceSet sourceSet : sourceSets) { + if (getSourceDirectories() == null) { + setSourceDirectories(getProject().files(sourceSet.getAllJava().getSrcDirs())); + } else { + setSourceDirectories(getSourceDirectories().plus(getProject().files(sourceSet.getAllJava().getSrcDirs()))); + } + if (getClassDirectories() == null) { + setClassDirectories(sourceSet.getOutput()); + } else { + setClassDirectories(getClassDirectories().plus(sourceSet.getOutput())); + } + } + } + }); + } + + /** + * Adds additional class directories to those that will be included in the report. + * + * @param dirs one or more directories containing classes to report coverage of + */ + public void additionalClassDirs(File... dirs) { + additionalClassDirs(getProject().files(Arrays.asList(dirs))); + } + + /** + * Adds additional class directories to those that will be included in the report. + * + * @param dirs a {@code FileCollection} of directories containing classes to report coverage of + */ + public void additionalClassDirs(FileCollection dirs) { + if (additionalClassDirs == null) { + additionalClassDirs = dirs; + } else { + additionalClassDirs = additionalClassDirs.plus(dirs); + } + } + + /** + * Adds additional source directories to be used for any classes included in the report. + * + * @param dirs one or more directories containing source files for the classes included in the report + */ + public void additionalSourceDirs(File... dirs) { + additionalSourceDirs(getProject().files(Arrays.asList(dirs))); + } + + /** + * Adds additional source directories to be used for any classes included in the report. + * + * @param dirs a {@code FileCollection} of directories containing source files for the classes included in the report + */ + public void additionalSourceDirs(FileCollection dirs) { + if (additionalSourceDirs == null) { + additionalSourceDirs = dirs; + } else { + additionalSourceDirs = additionalSourceDirs.plus(dirs); + } + } +} From 8d06c8f46fc9ffc646e5e839ad516d33acab99d5 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Wed, 7 Dec 2016 11:52:06 -0500 Subject: [PATCH 33/42] Fix indentation --- .../java/org/gradle/internal/jacoco/AntJacocoReport.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java index 061702e1888f..f83ea1315c15 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java @@ -85,17 +85,17 @@ public Object doCall(Object ignore) { private void configureReportFormats(GroovyObjectSupport antBuilder, JacocoReportsContainer reports) { if (reports.getHtml().isEnabled()) { antBuilder.invokeMethod("html", new Object[]{ - ImmutableMap.of("destdir", reports.getHtml().getDestination()) + ImmutableMap.of("destdir", reports.getHtml().getDestination()) }); } if (reports.getXml().isEnabled()) { antBuilder.invokeMethod("xml", new Object[]{ - ImmutableMap.of("destfile", reports.getXml().getDestination()) + ImmutableMap.of("destfile", reports.getXml().getDestination()) }); } if (reports.getCsv().isEnabled()) { antBuilder.invokeMethod("csv", new Object[]{ - ImmutableMap.of("destfile", reports.getCsv().getDestination()) + ImmutableMap.of("destfile", reports.getCsv().getDestination()) }); } } From 699a622c28215bec027e8e79784965bffa8cf7e3 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Wed, 7 Dec 2016 12:13:08 -0500 Subject: [PATCH 34/42] Reuse logic --- .../jacoco/AbstractAntJacocoReport.java | 85 +++++++++++++++++++ .../internal/jacoco/AntJacocoCheck.java | 59 +------------ .../internal/jacoco/AntJacocoReport.java | 62 +------------- 3 files changed, 93 insertions(+), 113 deletions(-) create mode 100644 subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AbstractAntJacocoReport.java diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AbstractAntJacocoReport.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AbstractAntJacocoReport.java new file mode 100644 index 000000000000..35e52b4f3d64 --- /dev/null +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AbstractAntJacocoReport.java @@ -0,0 +1,85 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.internal.jacoco; + +import com.google.common.collect.ImmutableMap; +import groovy.lang.Closure; +import groovy.lang.GroovyObjectSupport; +import org.gradle.api.file.FileCollection; +import org.gradle.api.internal.project.IsolatedAntBuilder; + +import java.util.Collections; +import java.util.Map; + +public abstract class AbstractAntJacocoReport { + + private final IsolatedAntBuilder ant; + + public AbstractAntJacocoReport(IsolatedAntBuilder ant) { + this.ant = ant; + } + + public void execute(FileCollection classpath, final String projectName, + final FileCollection allClassesDirs, final FileCollection allSourcesDirs, + final FileCollection executionData, + final T t) { + ant.withClasspath(classpath).execute(new Closure(this, this) { + @SuppressWarnings("UnusedDeclaration") + public Object doCall(Object it) { + final GroovyObjectSupport antBuilder = (GroovyObjectSupport) it; + antBuilder.invokeMethod("taskdef", ImmutableMap.of( + "name", "jacocoReport", + "classname", "org.jacoco.ant.ReportTask" + )); + final Map emptyArgs = Collections.emptyMap(); + antBuilder.invokeMethod("jacocoReport", new Object[]{emptyArgs, new Closure(this, this) { + public Object doCall(Object ignore) { + antBuilder.invokeMethod("executiondata", new Object[]{emptyArgs, new Closure(this, this) { + public Object doCall(Object ignore) { + executionData.addToAntBuilder(antBuilder, "resources"); + return null; + } + }}); + Map structureArgs = ImmutableMap.of("name", projectName); + antBuilder.invokeMethod("structure", new Object[]{structureArgs, new Closure(this, this) { + public Object doCall(Object ignore) { + antBuilder.invokeMethod("classfiles", new Object[]{emptyArgs, new Closure(this, this) { + public Object doCall(Object ignore) { + allClassesDirs.addToAntBuilder(antBuilder, "resources"); + return null; + } + }}); + antBuilder.invokeMethod("sourcefiles", new Object[]{emptyArgs, new Closure(this, this) { + public Object doCall(Object ignore) { + allSourcesDirs.addToAntBuilder(antBuilder, "resources"); + return null; + } + }}); + return null; + } + }}); + configureReport(antBuilder, t); + return null; + } + }}); + return null; + } + }); + } + + protected abstract void configureReport(GroovyObjectSupport antBuilder, T t); +} diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoCheck.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoCheck.java index 770ec0bb79b7..d5690a954f63 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoCheck.java +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoCheck.java @@ -21,19 +21,17 @@ import com.google.common.collect.ImmutableMap; import groovy.lang.Closure; import groovy.lang.GroovyObjectSupport; -import org.gradle.api.file.FileCollection; import org.gradle.api.internal.project.IsolatedAntBuilder; import org.gradle.testing.jacoco.tasks.rules.JacocoLimit; import org.gradle.testing.jacoco.tasks.rules.JacocoViolationRule; import org.gradle.testing.jacoco.tasks.rules.JacocoViolationRulesContainer; -import java.util.Collections; import java.util.HashMap; import java.util.Map; import static com.google.common.collect.Iterables.filter; -public class AntJacocoCheck { +public class AntJacocoCheck extends AbstractAntJacocoReport { private static final Predicate RULE_ENABLED_PREDICATE = new Predicate() { @Override @@ -42,61 +40,12 @@ public boolean apply(JacocoViolationRule rule) { } }; - private final IsolatedAntBuilder ant; - public AntJacocoCheck(IsolatedAntBuilder ant) { - this.ant = ant; - } - - public void execute(FileCollection classpath, final String projectName, - final FileCollection allClassesDirs, final FileCollection allSourcesDirs, - final FileCollection executionData, - final JacocoViolationRulesContainer violationRules) { - ant.withClasspath(classpath).execute(new Closure(this, this) { - @SuppressWarnings("UnusedDeclaration") - public Object doCall(Object it) { - final GroovyObjectSupport antBuilder = (GroovyObjectSupport) it; - antBuilder.invokeMethod("taskdef", ImmutableMap.of( - "name", "jacocoReport", - "classname", "org.jacoco.ant.ReportTask" - )); - final Map emptyArgs = Collections.emptyMap(); - antBuilder.invokeMethod("jacocoReport", new Object[]{emptyArgs, new Closure(this, this) { - public Object doCall(Object ignore) { - antBuilder.invokeMethod("executiondata", new Object[]{emptyArgs, new Closure(this, this) { - public Object doCall(Object ignore) { - executionData.addToAntBuilder(antBuilder, "resources"); - return null; - } - }}); - Map structureArgs = ImmutableMap.of("name", projectName); - antBuilder.invokeMethod("structure", new Object[]{structureArgs, new Closure(this, this) { - public Object doCall(Object ignore) { - antBuilder.invokeMethod("classfiles", new Object[]{emptyArgs, new Closure(this, this) { - public Object doCall(Object ignore) { - allClassesDirs.addToAntBuilder(antBuilder, "resources"); - return null; - } - }}); - antBuilder.invokeMethod("sourcefiles", new Object[]{emptyArgs, new Closure(this, this) { - public Object doCall(Object ignore) { - allSourcesDirs.addToAntBuilder(antBuilder, "resources"); - return null; - } - }}); - return null; - } - }}); - configureCheck(antBuilder, violationRules); - return null; - } - }}); - return null; - } - }); + super(ant); } - private void configureCheck(final GroovyObjectSupport antBuilder, final JacocoViolationRulesContainer violationRules) { + @Override + protected void configureReport(final GroovyObjectSupport antBuilder, final JacocoViolationRulesContainer violationRules) { if (!violationRules.getRules().isEmpty()) { Map checkArgs = ImmutableMap.of("failonviolation", !violationRules.isFailOnViolation()); antBuilder.invokeMethod("check", new Object[] {checkArgs, new Closure(this, this) { diff --git a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java index f83ea1315c15..111db45599b4 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java +++ b/subprojects/jacoco/src/main/java/org/gradle/internal/jacoco/AntJacocoReport.java @@ -17,72 +17,18 @@ package org.gradle.internal.jacoco; import com.google.common.collect.ImmutableMap; -import groovy.lang.Closure; import groovy.lang.GroovyObjectSupport; -import org.gradle.api.file.FileCollection; import org.gradle.api.internal.project.IsolatedAntBuilder; import org.gradle.testing.jacoco.tasks.JacocoReportsContainer; -import java.util.Collections; -import java.util.Map; - -public class AntJacocoReport { - - private final IsolatedAntBuilder ant; +public class AntJacocoReport extends AbstractAntJacocoReport { public AntJacocoReport(IsolatedAntBuilder ant) { - this.ant = ant; - } - - public void execute(FileCollection classpath, final String projectName, - final FileCollection allClassesDirs, final FileCollection allSourcesDirs, - final FileCollection executionData, - final JacocoReportsContainer reports) { - ant.withClasspath(classpath).execute(new Closure(this, this) { - @SuppressWarnings("UnusedDeclaration") - public Object doCall(Object it) { - final GroovyObjectSupport antBuilder = (GroovyObjectSupport) it; - antBuilder.invokeMethod("taskdef", ImmutableMap.of( - "name", "jacocoReport", - "classname", "org.jacoco.ant.ReportTask" - )); - final Map emptyArgs = Collections.emptyMap(); - antBuilder.invokeMethod("jacocoReport", new Object[]{emptyArgs, new Closure(this, this) { - public Object doCall(Object ignore) { - antBuilder.invokeMethod("executiondata", new Object[]{emptyArgs, new Closure(this, this) { - public Object doCall(Object ignore) { - executionData.addToAntBuilder(antBuilder, "resources"); - return null; - } - }}); - Map structureArgs = ImmutableMap.of("name", projectName); - antBuilder.invokeMethod("structure", new Object[]{structureArgs, new Closure(this, this) { - public Object doCall(Object ignore) { - antBuilder.invokeMethod("classfiles", new Object[]{emptyArgs, new Closure(this, this) { - public Object doCall(Object ignore) { - allClassesDirs.addToAntBuilder(antBuilder, "resources"); - return null; - } - }}); - antBuilder.invokeMethod("sourcefiles", new Object[]{emptyArgs, new Closure(this, this) { - public Object doCall(Object ignore) { - allSourcesDirs.addToAntBuilder(antBuilder, "resources"); - return null; - } - }}); - return null; - } - }}); - configureReportFormats(antBuilder, reports); - return null; - } - }}); - return null; - } - }); + super(ant); } - private void configureReportFormats(GroovyObjectSupport antBuilder, JacocoReportsContainer reports) { + @Override + protected void configureReport(GroovyObjectSupport antBuilder, JacocoReportsContainer reports) { if (reports.getHtml().isEnabled()) { antBuilder.invokeMethod("html", new Object[]{ ImmutableMap.of("destdir", reports.getHtml().getDestination()) From 47feb94d1dec50232b6327a262204a74e88f978b Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Wed, 7 Dec 2016 14:02:11 -0500 Subject: [PATCH 35/42] Move logic into parent class --- .../org/gradle/testing/jacoco/tasks/JacocoCheck.java | 9 --------- .../org/gradle/testing/jacoco/tasks/JacocoReport.java | 9 --------- .../gradle/testing/jacoco/tasks/JacocoReportBase.java | 7 +++++++ 3 files changed, 7 insertions(+), 18 deletions(-) diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCheck.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCheck.java index 59cdcc3d6db7..4beab60e2f48 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCheck.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCheck.java @@ -21,7 +21,6 @@ import org.gradle.api.Action; import org.gradle.api.Incubating; import org.gradle.api.internal.ClosureBackedAction; -import org.gradle.api.specs.Spec; import org.gradle.api.tasks.CacheableTask; import org.gradle.api.tasks.Nested; import org.gradle.api.tasks.TaskAction; @@ -29,8 +28,6 @@ import org.gradle.internal.jacoco.rules.JacocoViolationRulesContainerImpl; import org.gradle.testing.jacoco.tasks.rules.JacocoViolationRulesContainer; -import java.io.File; - import static groovy.lang.Closure.DELEGATE_FIRST; /** @@ -80,12 +77,6 @@ public JacocoViolationRulesContainer violationRules(Action fileExistsSpec = new Spec() { - @Override - public boolean isSatisfiedBy(File file) { - return file.exists(); - } - }; new AntJacocoCheck(getAntBuilder()).execute( getJacocoClasspath(), getProject().getName(), diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java index d9eb449a099b..db2117e0f082 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReport.java @@ -20,15 +20,12 @@ import org.gradle.api.Incubating; import org.gradle.api.internal.ClosureBackedAction; import org.gradle.api.reporting.Reporting; -import org.gradle.api.specs.Spec; import org.gradle.api.tasks.CacheableTask; import org.gradle.api.tasks.Nested; import org.gradle.api.tasks.TaskAction; import org.gradle.internal.jacoco.AntJacocoReport; import org.gradle.internal.jacoco.JacocoReportsContainerImpl; -import java.io.File; - /** * Task to generate HTML, Xml and CSV reports of Jacoco coverage data. */ @@ -68,12 +65,6 @@ public JacocoReportsContainer reports(Action con @TaskAction public void generate() { - Spec fileExistsSpec = new Spec() { - @Override - public boolean isSatisfiedBy(File file) { - return file.exists(); - } - }; new AntJacocoReport(getAntBuilder()).execute( getJacocoClasspath(), getProject().getName(), diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReportBase.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReportBase.java index e53cb633b227..22921dd0b237 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReportBase.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReportBase.java @@ -46,6 +46,13 @@ @Incubating public abstract class JacocoReportBase extends JacocoBase { + protected final Spec fileExistsSpec = new Spec() { + @Override + public boolean isSatisfiedBy(File file) { + return file.exists(); + } + }; + private FileCollection executionData; private FileCollection sourceDirectories; private FileCollection classDirectories; From 8097fdd7c668441ceafeffe34adbcec0b6894e2c Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Wed, 7 Dec 2016 14:04:10 -0500 Subject: [PATCH 36/42] Task is not cacheable as it doesn't declare outputs --- .../main/java/org/gradle/testing/jacoco/tasks/JacocoCheck.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCheck.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCheck.java index 4beab60e2f48..690097b7648a 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCheck.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCheck.java @@ -21,7 +21,6 @@ import org.gradle.api.Action; import org.gradle.api.Incubating; import org.gradle.api.internal.ClosureBackedAction; -import org.gradle.api.tasks.CacheableTask; import org.gradle.api.tasks.Nested; import org.gradle.api.tasks.TaskAction; import org.gradle.internal.jacoco.AntJacocoCheck; @@ -37,7 +36,6 @@ * * @since 4.0 */ -@CacheableTask @Incubating public class JacocoCheck extends JacocoReportBase { From ff77afc326a486bb17a11f1c3b83cc3f7be05e07 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Tue, 20 Dec 2016 11:13:15 -0700 Subject: [PATCH 37/42] Ignore running tests on Java 9 --- .../rules/JacocoPluginCheckCoverageIntegrationTest.groovy | 3 +++ 1 file changed, 3 insertions(+) diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIntegrationTest.groovy index d33e341c84bc..fb24c960f4be 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIntegrationTest.groovy @@ -18,11 +18,14 @@ package org.gradle.testing.jacoco.plugins.rules import org.gradle.integtests.fixtures.AbstractIntegrationSpec import org.gradle.testing.jacoco.plugins.fixtures.JavaProjectUnderTest +import org.gradle.util.Requires import spock.lang.Unroll import static JacocoViolationRulesLimit.Insufficient import static JacocoViolationRulesLimit.Sufficient +import static org.gradle.util.TestPrecondition.FIX_TO_WORK_ON_JAVA9 +@Requires(FIX_TO_WORK_ON_JAVA9) class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { private final JavaProjectUnderTest javaProjectUnderTest = new JavaProjectUnderTest(testDirectory) From 1e317126f0aa11ceb9b54dfc5c4659211ef085c4 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Tue, 20 Dec 2016 12:11:25 -0700 Subject: [PATCH 38/42] Report task should fail if any of the input file does not exist --- .../JacocoPluginIntegrationTest.groovy | 34 +++++++++++++++++++ .../jacoco/tasks/JacocoReportBase.java | 5 +-- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginIntegrationTest.groovy index fd3161090e4d..c30198973951 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginIntegrationTest.groovy @@ -308,6 +308,40 @@ public class ThingTest { ':jacocoTestReport' in nonSkippedTasks } + def "skips report task if none of the execution data files does not exist"() { + given: + buildFile << """ + jacocoTestReport { + executionData = files('unknown.exec', 'data/test.exec') + } + """ + + when: + succeeds 'test', 'jacocoTestReport' + + then: + ':test' in nonSkippedTasks + ':jacocoTestReport' in skippedTasks + } + + def "fails report task if only some of the execution data files do not exist"() { + given: + def execFileName = 'unknown.exec' + buildFile << """ + jacocoTestReport { + executionData(files('$execFileName')) + } + """ + + when: + fails 'test', 'jacocoTestReport' + + then: + ':test' in nonSkippedTasks + ':jacocoTestReport' in executedTasks + errorOutput.contains("Unable to read execution data file ${new File(testDirectory, execFileName)}") + } + private JacocoReportFixture htmlReport(String basedir = "${REPORTING_BASE}/jacoco/test/html") { return new JacocoReportFixture(file(basedir)) } diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReportBase.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReportBase.java index 22921dd0b237..09f2eea09d80 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReportBase.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoReportBase.java @@ -63,16 +63,13 @@ public JacocoReportBase() { onlyIf(new Spec() { @Override public boolean isSatisfiedBy(Task element) { - //TODO SF it should be 'any' instead of 'all' - return Iterables.all(getExecutionData(), new Predicate() { + return Iterables.any(getExecutionData(), new Predicate() { @Override public boolean apply(File file) { return file.exists(); } - }); } - }); } From a7a4592ca9c9b64552f82512dce279edb59539e0 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Tue, 20 Dec 2016 14:04:42 -0700 Subject: [PATCH 39/42] Assign group and description for tasks --- .../testing/jacoco/plugins/JacocoPlugin.java | 5 +++++ .../testing/jacoco/plugins/JacocoPluginSpec.groovy | 14 ++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/plugins/JacocoPlugin.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/plugins/JacocoPlugin.java index a7a6b07fce4f..27071884191c 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/plugins/JacocoPlugin.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/plugins/JacocoPlugin.java @@ -34,6 +34,7 @@ import org.gradle.api.tasks.testing.Test; import org.gradle.internal.jacoco.JacocoAgentJar; import org.gradle.internal.reflect.Instantiator; +import org.gradle.language.base.plugins.LifecycleBasePlugin; import org.gradle.testing.jacoco.tasks.JacocoBase; import org.gradle.testing.jacoco.tasks.JacocoCheck; import org.gradle.testing.jacoco.tasks.JacocoMerge; @@ -223,6 +224,8 @@ public void execute(Test task) { private void addDefaultReportTask(final JacocoPluginExtension extension, final Test task) { final JacocoReport reportTask = project.getTasks().create("jacoco" + StringUtils.capitalise(task.getName()) + "Report", JacocoReport.class); + reportTask.setGroup(LifecycleBasePlugin.VERIFICATION_GROUP); + reportTask.setDescription(String.format("Generates code coverage report for the %s task.", task.getName())); reportTask.executionData(task); reportTask.sourceSets(project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets().getByName("main")); ConventionMapping taskMapping = ((IConventionAware) reportTask).getConventionMapping(); @@ -252,6 +255,8 @@ public File call() { private void addDefaultCheckTask(final Test task) { final JacocoCheck checkTask = project.getTasks().create("jacoco" + StringUtils.capitalise(task.getName()) + "Check", JacocoCheck.class); + checkTask.setGroup(LifecycleBasePlugin.VERIFICATION_GROUP); + checkTask.setDescription(String.format("Verifies code coverage metrics based on specified rules for the %s task.", task.getName())); checkTask.executionData(task); checkTask.sourceSets(project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets().getByName("main")); } diff --git a/subprojects/jacoco/src/test/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginSpec.groovy b/subprojects/jacoco/src/test/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginSpec.groovy index bfbd171f0a46..f4d9b270d52f 100644 --- a/subprojects/jacoco/src/test/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginSpec.groovy +++ b/subprojects/jacoco/src/test/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginSpec.groovy @@ -17,6 +17,7 @@ package org.gradle.testing.jacoco.plugins import org.gradle.api.tasks.JavaExec import org.gradle.api.tasks.testing.Test +import org.gradle.language.base.plugins.LifecycleBasePlugin import org.gradle.test.fixtures.AbstractProjectBuilderSpec import spock.lang.Issue import spock.lang.Unroll @@ -92,4 +93,17 @@ class JacocoPluginSpec extends AbstractProjectBuilderSpec { where: includeNoLocationClassesValue << [true, false] } + + def "declares task property values for group and description"() { + given: + project.apply plugin: 'java' + + expect: + def jacocoTestReportTask = project.tasks.getByName('jacocoTestReport') + def jacocoCheckTask = project.tasks.getByName('jacocoTestCheck') + jacocoTestReportTask.group == LifecycleBasePlugin.VERIFICATION_GROUP + jacocoCheckTask.group == LifecycleBasePlugin.VERIFICATION_GROUP + jacocoTestReportTask.description == 'Generates code coverage report for the test task.' + jacocoCheckTask.description == 'Verifies code coverage metrics based on specified rules for the test task.' + } } From d90079545f9894499f1836961e63d9ea6725d073 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Tue, 20 Dec 2016 14:53:18 -0700 Subject: [PATCH 40/42] Use task name that better expresses intent --- ...coco.tasks.JacocoCoverageVerification.xml} | 0 .../docs/src/docs/userguide/jacocoPlugin.xml | 10 +- .../fixtures/JavaProjectUnderTest.groovy | 2 +- ...VerificationVersionIntegrationTest.groovy} | 6 +- ...onCompatibleVersionIntegrationTest.groovy} | 8 +- ...IncompatibleVersionIntegrationTest.groovy} | 8 +- ...overageVerificationIntegrationTest.groovy} | 94 +++++++++---------- .../testing/jacoco/plugins/JacocoPlugin.java | 16 ++-- ...k.java => JacocoCoverageVerification.java} | 4 +- .../jacoco/plugins/JacocoPluginSpec.groovy | 6 +- 10 files changed, 77 insertions(+), 77 deletions(-) rename subprojects/docs/src/docs/dsl/{org.gradle.testing.jacoco.tasks.JacocoCheck.xml => org.gradle.testing.jacoco.tasks.JacocoCoverageVerification.xml} (100%) rename subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/{AbstractJacocoPluginCheckCoverageVersionIntegrationTest.groovy => AbstractJacocoPluginCoverageVerificationVersionIntegrationTest.groovy} (82%) rename subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/{JacocoPluginCheckCoverageCompatibleVersionIntegrationTest.groovy => JacocoPluginCoverageVerificationCompatibleVersionIntegrationTest.groovy} (71%) rename subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/{JacocoPluginCheckCoverageIncompatibleVersionIntegrationTest.groovy => JacocoPluginCoverageVerificationIncompatibleVersionIntegrationTest.groovy} (74%) rename subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/{JacocoPluginCheckCoverageIntegrationTest.groovy => JacocoPluginCoverageVerificationIntegrationTest.groovy} (69%) rename subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/{JacocoCheck.java => JacocoCoverageVerification.java} (96%) diff --git a/subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.tasks.JacocoCheck.xml b/subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.tasks.JacocoCoverageVerification.xml similarity index 100% rename from subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.tasks.JacocoCheck.xml rename to subprojects/docs/src/docs/dsl/org.gradle.testing.jacoco.tasks.JacocoCoverageVerification.xml diff --git a/subprojects/docs/src/docs/userguide/jacocoPlugin.xml b/subprojects/docs/src/docs/userguide/jacocoPlugin.xml index 13168c73b770..d1a24cc0173e 100644 --- a/subprojects/docs/src/docs/userguide/jacocoPlugin.xml +++ b/subprojects/docs/src/docs/userguide/jacocoPlugin.xml @@ -89,10 +89,10 @@ - The task can be used to verify if code coverage + The task can be used to verify if code coverage metrics are met based on configured rules. Its API exposes two methods, - and - , + and + , the main entry point for configuring rules. Invoking any of those methods returns an instance of providing extensive configuration options. The build fails if any of the configured rules are not met. JaCoCo only reports the first violated rule. @@ -243,11 +243,11 @@ - jacocoTestCheck + jacocoTestCoverageVerification - - + Verifies code coverage metrics based on specified rules for the test task. diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/fixtures/JavaProjectUnderTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/fixtures/JavaProjectUnderTest.groovy index 9221fe357421..ba18f67960ab 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/fixtures/JavaProjectUnderTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/fixtures/JavaProjectUnderTest.groovy @@ -76,7 +76,7 @@ class JavaProjectUnderTest { sourceSets sourceSets.main } - task jacocoIntegrationTestCheck(type: JacocoCheck) { + task jacocoIntegrationTestCoverageVerification(type: JacocoCoverageVerification) { executionData integrationTest sourceSets sourceSets.main } diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/AbstractJacocoPluginCheckCoverageVersionIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/AbstractJacocoPluginCoverageVerificationVersionIntegrationTest.groovy similarity index 82% rename from subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/AbstractJacocoPluginCheckCoverageVersionIntegrationTest.groovy rename to subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/AbstractJacocoPluginCoverageVerificationVersionIntegrationTest.groovy index 64f9f8eb36fe..35b783d60e4c 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/AbstractJacocoPluginCheckCoverageVersionIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/AbstractJacocoPluginCoverageVerificationVersionIntegrationTest.groovy @@ -24,10 +24,10 @@ import org.gradle.util.TestPrecondition import static JacocoViolationRulesLimit.Sufficient @Requires(TestPrecondition.JDK7_OR_EARLIER) -abstract class AbstractJacocoPluginCheckCoverageVersionIntegrationTest extends MultiVersionIntegrationSpec { +abstract class AbstractJacocoPluginCoverageVerificationVersionIntegrationTest extends MultiVersionIntegrationSpec { private final JavaProjectUnderTest javaProjectUnderTest = new JavaProjectUnderTest(testDirectory) - protected final static String[] TEST_AND_JACOCO_CHECK_TASK_PATHS = [':test', ':jacocoTestCheck'] as String[] + protected final static String[] TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS = [':test', ':jacocoTestCoverageVerification'] as String[] def setup() { javaProjectUnderTest.writeBuildScript().writeSourceFiles() @@ -37,7 +37,7 @@ abstract class AbstractJacocoPluginCheckCoverageVersionIntegrationTest extends M toolVersion = '$version' } - jacocoTestCheck { + jacocoTestCoverageVerification { violationRules { rule { $Sufficient.LINE_METRIC_COVERED_RATIO diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageCompatibleVersionIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCoverageVerificationCompatibleVersionIntegrationTest.groovy similarity index 71% rename from subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageCompatibleVersionIntegrationTest.groovy rename to subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCoverageVerificationCompatibleVersionIntegrationTest.groovy index 897ebd952f90..7388d564572d 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageCompatibleVersionIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCoverageVerificationCompatibleVersionIntegrationTest.groovy @@ -20,13 +20,13 @@ import org.gradle.integtests.fixtures.TargetCoverage import org.gradle.testing.jacoco.plugins.fixtures.JacocoCoverage @TargetCoverage({ JacocoCoverage.COVERAGE_CHECK_SUPPORTED }) -class JacocoPluginCheckCoverageCompatibleVersionIntegrationTest extends AbstractJacocoPluginCheckCoverageVersionIntegrationTest { +class JacocoPluginCoverageVerificationCompatibleVersionIntegrationTest extends AbstractJacocoPluginCoverageVerificationVersionIntegrationTest { - def "can check code coverage for compatible versions"() { + def "can verify code coverage metrics for compatible versions"() { when: - succeeds TEST_AND_JACOCO_CHECK_TASK_PATHS + succeeds TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS then: - executedAndNotSkipped(TEST_AND_JACOCO_CHECK_TASK_PATHS) + executedAndNotSkipped(TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS) } } diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIncompatibleVersionIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCoverageVerificationIncompatibleVersionIntegrationTest.groovy similarity index 74% rename from subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIncompatibleVersionIntegrationTest.groovy rename to subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCoverageVerificationIncompatibleVersionIntegrationTest.groovy index 629d31ea784c..789bc5f451e5 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIncompatibleVersionIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCoverageVerificationIncompatibleVersionIntegrationTest.groovy @@ -20,14 +20,14 @@ import org.gradle.integtests.fixtures.TargetCoverage import org.gradle.testing.jacoco.plugins.fixtures.JacocoCoverage @TargetCoverage({ JacocoCoverage.COVERAGE_CHECK_UNSUPPORTED }) -class JacocoPluginCheckCoverageIncompatibleVersionIntegrationTest extends AbstractJacocoPluginCheckCoverageVersionIntegrationTest { +class JacocoPluginCoverageVerificationIncompatibleVersionIntegrationTest extends AbstractJacocoPluginCoverageVerificationVersionIntegrationTest { - def "fails to check code coverage"() { + def "fails to verify code coverage metrics"() { when: - fails TEST_AND_JACOCO_CHECK_TASK_PATHS + fails TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS then: - executedAndNotSkipped(TEST_AND_JACOCO_CHECK_TASK_PATHS) + executedAndNotSkipped(TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS) errorOutput.contains("jacocoReport doesn't support the nested \"check\" element.") } } \ No newline at end of file diff --git a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIntegrationTest.groovy b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCoverageVerificationIntegrationTest.groovy similarity index 69% rename from subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIntegrationTest.groovy rename to subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCoverageVerificationIntegrationTest.groovy index fb24c960f4be..8b1aa4a889a6 100644 --- a/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCheckCoverageIntegrationTest.groovy +++ b/subprojects/jacoco/src/integTest/groovy/org/gradle/testing/jacoco/plugins/rules/JacocoPluginCoverageVerificationIntegrationTest.groovy @@ -26,13 +26,13 @@ import static JacocoViolationRulesLimit.Sufficient import static org.gradle.util.TestPrecondition.FIX_TO_WORK_ON_JAVA9 @Requires(FIX_TO_WORK_ON_JAVA9) -class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { +class JacocoPluginCoverageVerificationIntegrationTest extends AbstractIntegrationSpec { private final JavaProjectUnderTest javaProjectUnderTest = new JavaProjectUnderTest(testDirectory) private final static String[] TEST_TASK_PATH = [':test'] as String[] - private final static String[] JACOCO_CHECK_TASK_PATH = [':jacocoTestCheck'] as String[] - private final static String[] TEST_AND_JACOCO_CHECK_TASK_PATHS = TEST_TASK_PATH + JACOCO_CHECK_TASK_PATH - private final static String[] INTEG_TEST_AND_JACOCO_CHECK_TASK_PATHS = [':integrationTest', ':jacocoIntegrationTestCheck'] as String[] + private final static String[] JACOCO_COVERAGE_VERIFICATION_TASK_PATH = [':jacocoTestCoverageVerification'] as String[] + private final static String[] TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS = TEST_TASK_PATH + JACOCO_COVERAGE_VERIFICATION_TASK_PATH + private final static String[] INTEG_TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS = [':integrationTest', ':jacocoIntegrationTestCoverageVerification'] as String[] def setup() { javaProjectUnderTest.writeBuildScript().writeSourceFiles() @@ -41,22 +41,22 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { def "can define no rules"() { given: buildFile << """ - jacocoTestCheck { + jacocoTestCoverageVerification { violationRules {} } """ when: - succeeds TEST_AND_JACOCO_CHECK_TASK_PATHS + succeeds TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS then: - executedAndNotSkipped(TEST_AND_JACOCO_CHECK_TASK_PATHS) + executedAndNotSkipped(TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS) } def "can define single rule without limits"() { given: buildFile << """ - jacocoTestCheck { + jacocoTestCoverageVerification { violationRules { rule {} } @@ -64,16 +64,16 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { """ when: - succeeds TEST_AND_JACOCO_CHECK_TASK_PATHS + succeeds TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS then: - executedAndNotSkipped(TEST_AND_JACOCO_CHECK_TASK_PATHS) + executedAndNotSkipped(TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS) } def "Ant task reports error for unknown field value"() { given: buildFile << """ - jacocoTestCheck { + jacocoTestCoverageVerification { violationRules { rule { element = 'UNKNOWN' @@ -83,17 +83,17 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { """ when: - fails TEST_AND_JACOCO_CHECK_TASK_PATHS + fails TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS then: - executedAndNotSkipped(TEST_AND_JACOCO_CHECK_TASK_PATHS) + executedAndNotSkipped(TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS) errorOutput.contains("'UNKNOWN' is not a permitted value for org.jacoco.core.analysis.ICoverageNode\$ElementType") } def "can define includes for single rule"() { given: buildFile << """ - jacocoTestCheck { + jacocoTestCoverageVerification { violationRules { rule { element = 'CLASS' @@ -105,17 +105,17 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { """ when: - fails TEST_AND_JACOCO_CHECK_TASK_PATHS + fails TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS then: - executedAndNotSkipped(TEST_AND_JACOCO_CHECK_TASK_PATHS) + executedAndNotSkipped(TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS) errorOutput.contains("Rule violated for class org.gradle.Class1: lines covered ratio is 1.0, but expected maximum is 0.5") } def "can define excludes for single rule"() { given: buildFile << """ - jacocoTestCheck { + jacocoTestCoverageVerification { violationRules { rule { excludes = ['company', '$testDirectory.name'] @@ -126,17 +126,17 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { """ when: - succeeds TEST_AND_JACOCO_CHECK_TASK_PATHS + succeeds TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS then: - executedAndNotSkipped(TEST_AND_JACOCO_CHECK_TASK_PATHS) + executedAndNotSkipped(TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS) } @Unroll def "can define rule with sufficient coverage for #description"() { given: buildFile << """ - jacocoTestCheck { + jacocoTestCoverageVerification { violationRules { rule { ${limits.join('\n')} @@ -146,10 +146,10 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { """ when: - succeeds TEST_AND_JACOCO_CHECK_TASK_PATHS + succeeds TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS then: - executedAndNotSkipped(TEST_AND_JACOCO_CHECK_TASK_PATHS) + executedAndNotSkipped(TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS) where: limits | description @@ -164,7 +164,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { def "can define rule with insufficient coverage for #description"() { given: buildFile << """ - jacocoTestCheck { + jacocoTestCoverageVerification { violationRules { rule { ${limits.join('\n')} @@ -174,10 +174,10 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { """ when: - fails TEST_AND_JACOCO_CHECK_TASK_PATHS + fails TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS then: - executedAndNotSkipped(TEST_AND_JACOCO_CHECK_TASK_PATHS) + executedAndNotSkipped(TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS) errorOutput.contains("Rule violated for bundle $testDirectory.name: $errorMessage") where: @@ -194,7 +194,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { def "can define multiple rules"() { given: buildFile << """ - jacocoTestCheck { + jacocoTestCoverageVerification { violationRules { rule { $Sufficient.LINE_METRIC_COVERED_RATIO @@ -207,17 +207,17 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { """ when: - fails TEST_AND_JACOCO_CHECK_TASK_PATHS + fails TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS then: - executedAndNotSkipped(TEST_AND_JACOCO_CHECK_TASK_PATHS) + executedAndNotSkipped(TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS) errorOutput.contains("Rule violated for bundle $testDirectory.name: classes missed count is 0.0, but expected minimum is 0.5") } def "can disable rules"() { given: buildFile << """ - jacocoTestCheck { + jacocoTestCoverageVerification { violationRules { rule { $Sufficient.LINE_METRIC_COVERED_RATIO @@ -231,16 +231,16 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { """ when: - succeeds TEST_AND_JACOCO_CHECK_TASK_PATHS + succeeds TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS then: - executedAndNotSkipped(TEST_AND_JACOCO_CHECK_TASK_PATHS) + executedAndNotSkipped(TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS) } def "can ignore failures"() { given: buildFile << """ - jacocoTestCheck { + jacocoTestCoverageVerification { violationRules { failOnViolation = true @@ -252,10 +252,10 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { """ when: - succeeds TEST_AND_JACOCO_CHECK_TASK_PATHS + succeeds TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS then: - executedAndNotSkipped(TEST_AND_JACOCO_CHECK_TASK_PATHS) + executedAndNotSkipped(TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS) errorOutput.contains("Rule violated for bundle $testDirectory.name: lines covered ratio is 1.0, but expected maximum is 0.5") } @@ -265,7 +265,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { javaProjectUnderTest.writeIntegrationTestSourceFiles() buildFile << """ - tasks.withType(JacocoCheck) { + tasks.withType(JacocoCoverageVerification) { violationRules { rule { $Insufficient.LINE_METRIC_COVERED_RATIO @@ -282,7 +282,7 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { errorOutput.contains("Rule violated for bundle $testDirectory.name: lines covered ratio is 1.0, but expected maximum is 0.5") where: - tasksPaths << [TEST_AND_JACOCO_CHECK_TASK_PATHS, INTEG_TEST_AND_JACOCO_CHECK_TASK_PATHS] + tasksPaths << [TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS, INTEG_TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS] } @Unroll @@ -308,14 +308,14 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { errorOutput.contains("Rule violated for bundle $testDirectory.name: $errorMessage") where: - tasksPaths | reportTaskName | limit | errorMessage - TEST_AND_JACOCO_CHECK_TASK_PATHS | 'jacocoTestCheck' | Insufficient.LINE_METRIC_COVERED_RATIO | 'lines covered ratio is 1.0, but expected maximum is 0.5' - INTEG_TEST_AND_JACOCO_CHECK_TASK_PATHS | 'jacocoIntegrationTestCheck' | Insufficient.CLASS_METRIC_MISSED_COUNT | 'classes missed count is 0.0, but expected minimum is 0.5' + tasksPaths | reportTaskName | limit | errorMessage + TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS | 'jacocoTestCoverageVerification' | Insufficient.LINE_METRIC_COVERED_RATIO | 'lines covered ratio is 1.0, but expected maximum is 0.5' + INTEG_TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS | 'jacocoIntegrationTestCoverageVerification' | Insufficient.CLASS_METRIC_MISSED_COUNT | 'classes missed count is 0.0, but expected minimum is 0.5' } def "task is never UP-TO-DATE as it does not define any outputs"() { buildFile << """ - jacocoTestCheck { + jacocoTestCoverageVerification { violationRules { rule { $Sufficient.LINE_METRIC_COVERED_RATIO @@ -325,27 +325,27 @@ class JacocoPluginCheckCoverageIntegrationTest extends AbstractIntegrationSpec { """ when: - succeeds TEST_AND_JACOCO_CHECK_TASK_PATHS + succeeds TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS then: - executedAndNotSkipped(TEST_AND_JACOCO_CHECK_TASK_PATHS) + executedAndNotSkipped(TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS) when: - succeeds TEST_AND_JACOCO_CHECK_TASK_PATHS + succeeds TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS then: - executed(JACOCO_CHECK_TASK_PATH) + executed(JACOCO_COVERAGE_VERIFICATION_TASK_PATH) skipped(TEST_TASK_PATH) when: buildFile << """ - jacocoTestCheck.violationRules.rules[0].limits[0].maximum = 0.5 + jacocoTestCoverageVerification.violationRules.rules[0].limits[0].maximum = 0.5 """ - fails TEST_AND_JACOCO_CHECK_TASK_PATHS + fails TEST_AND_JACOCO_COVERAGE_VERIFICATION_TASK_PATHS then: - executed(JACOCO_CHECK_TASK_PATH) + executed(JACOCO_COVERAGE_VERIFICATION_TASK_PATH) skipped(TEST_TASK_PATH) errorOutput.contains("Rule violated for bundle $testDirectory.name: lines covered ratio is 1.0, but expected maximum is 0.5") } diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/plugins/JacocoPlugin.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/plugins/JacocoPlugin.java index 27071884191c..b0fe7ad10d89 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/plugins/JacocoPlugin.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/plugins/JacocoPlugin.java @@ -36,7 +36,7 @@ import org.gradle.internal.reflect.Instantiator; import org.gradle.language.base.plugins.LifecycleBasePlugin; import org.gradle.testing.jacoco.tasks.JacocoBase; -import org.gradle.testing.jacoco.tasks.JacocoCheck; +import org.gradle.testing.jacoco.tasks.JacocoCoverageVerification; import org.gradle.testing.jacoco.tasks.JacocoMerge; import org.gradle.testing.jacoco.tasks.JacocoReport; @@ -214,7 +214,7 @@ public void execute(JavaPlugin javaPlugin) { public void execute(Test task) { if (task.getName().equals(JavaPlugin.TEST_TASK_NAME)) { addDefaultReportTask(extension, task); - addDefaultCheckTask(task); + addDefaultCoverageVerificationTask(task); } } }); @@ -253,11 +253,11 @@ public File call() { }); } - private void addDefaultCheckTask(final Test task) { - final JacocoCheck checkTask = project.getTasks().create("jacoco" + StringUtils.capitalise(task.getName()) + "Check", JacocoCheck.class); - checkTask.setGroup(LifecycleBasePlugin.VERIFICATION_GROUP); - checkTask.setDescription(String.format("Verifies code coverage metrics based on specified rules for the %s task.", task.getName())); - checkTask.executionData(task); - checkTask.sourceSets(project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets().getByName("main")); + private void addDefaultCoverageVerificationTask(final Test task) { + final JacocoCoverageVerification coverageVerificationTask = project.getTasks().create("jacoco" + StringUtils.capitalise(task.getName()) + "CoverageVerification", JacocoCoverageVerification.class); + coverageVerificationTask.setGroup(LifecycleBasePlugin.VERIFICATION_GROUP); + coverageVerificationTask.setDescription(String.format("Verifies code coverage metrics based on specified rules for the %s task.", task.getName())); + coverageVerificationTask.executionData(task); + coverageVerificationTask.sourceSets(project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets().getByName("main")); } } diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCheck.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCoverageVerification.java similarity index 96% rename from subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCheck.java rename to subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCoverageVerification.java index 690097b7648a..83f6d3ef8b7e 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCheck.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCoverageVerification.java @@ -37,11 +37,11 @@ * @since 4.0 */ @Incubating -public class JacocoCheck extends JacocoReportBase { +public class JacocoCoverageVerification extends JacocoReportBase { private final JacocoViolationRulesContainer violationRules; - public JacocoCheck() { + public JacocoCoverageVerification() { super(); violationRules = getInstantiator().newInstance(JacocoViolationRulesContainerImpl.class); } diff --git a/subprojects/jacoco/src/test/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginSpec.groovy b/subprojects/jacoco/src/test/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginSpec.groovy index f4d9b270d52f..eb20dc8b5961 100644 --- a/subprojects/jacoco/src/test/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginSpec.groovy +++ b/subprojects/jacoco/src/test/groovy/org/gradle/testing/jacoco/plugins/JacocoPluginSpec.groovy @@ -100,10 +100,10 @@ class JacocoPluginSpec extends AbstractProjectBuilderSpec { expect: def jacocoTestReportTask = project.tasks.getByName('jacocoTestReport') - def jacocoCheckTask = project.tasks.getByName('jacocoTestCheck') + def jacocoTestCoverageVerificationTask = project.tasks.getByName('jacocoTestCoverageVerification') jacocoTestReportTask.group == LifecycleBasePlugin.VERIFICATION_GROUP - jacocoCheckTask.group == LifecycleBasePlugin.VERIFICATION_GROUP + jacocoTestCoverageVerificationTask.group == LifecycleBasePlugin.VERIFICATION_GROUP jacocoTestReportTask.description == 'Generates code coverage report for the test task.' - jacocoCheckTask.description == 'Verifies code coverage metrics based on specified rules for the test task.' + jacocoTestCoverageVerificationTask.description == 'Verifies code coverage metrics based on specified rules for the test task.' } } From d832d0dd9a601f34fe48b7232135c287dc6b589b Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Tue, 20 Dec 2016 15:10:08 -0700 Subject: [PATCH 41/42] Change targeted release version --- .../gradle/testing/jacoco/tasks/JacocoCoverageVerification.java | 2 +- .../java/org/gradle/testing/jacoco/tasks/rules/JacocoLimit.java | 2 +- .../gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java | 2 +- .../jacoco/tasks/rules/JacocoViolationRulesContainer.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCoverageVerification.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCoverageVerification.java index 83f6d3ef8b7e..e3dce19532ce 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCoverageVerification.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/JacocoCoverageVerification.java @@ -34,7 +34,7 @@ *

* Requires JaCoCo version >= 0.6.3. * - * @since 4.0 + * @since 3.4 */ @Incubating public class JacocoCoverageVerification extends JacocoReportBase { diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoLimit.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoLimit.java index 2fd378a688d6..035c33f68f47 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoLimit.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoLimit.java @@ -25,7 +25,7 @@ /** * Defines a Jacoco rule limit. * - * @since 4.0 + * @since 3.4 */ @Incubating public interface JacocoLimit extends Serializable { diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java index cf88f14ef500..5b6803907155 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRule.java @@ -31,7 +31,7 @@ /** * Defines a Jacoco violation rule. * - * @since 4.0 + * @since 3.4 */ @Incubating public interface JacocoViolationRule extends Serializable { diff --git a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRulesContainer.java b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRulesContainer.java index f6488fab6ed4..fe60db042e11 100644 --- a/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRulesContainer.java +++ b/subprojects/jacoco/src/main/java/org/gradle/testing/jacoco/tasks/rules/JacocoViolationRulesContainer.java @@ -29,7 +29,7 @@ /** * The violation rules configuration for the {@link org.gradle.testing.jacoco.tasks.JacocoReport} task. * - * @since 4.0 + * @since 3.4 */ @Incubating public interface JacocoViolationRulesContainer { From ec1b0036c134aada732d3bf73acf11d400df6268 Mon Sep 17 00:00:00 2001 From: Benjamin Muschko Date: Tue, 20 Dec 2016 15:35:17 -0700 Subject: [PATCH 42/42] Fix task name in sample project --- .../docs/src/samples/testing/jacoco/quickstart/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/docs/src/samples/testing/jacoco/quickstart/build.gradle b/subprojects/docs/src/samples/testing/jacoco/quickstart/build.gradle index 0625c3656c53..879ce3b74aa7 100644 --- a/subprojects/docs/src/samples/testing/jacoco/quickstart/build.gradle +++ b/subprojects/docs/src/samples/testing/jacoco/quickstart/build.gradle @@ -58,7 +58,7 @@ jacocoTestReport { // END SNIPPET report-configuration // START SNIPPET violation-rules-configuration -jacocoTestCheck { +jacocoTestCoverageVerification { violationRules { rule { limit {