Cobertura instrumentation fails in Gradle 1.2


(Dan Stine) #1

Possibly related to the ASM upgrade mentioned in the release notes?

Exception:

13:10:39.555 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument] java.lang.IncompatibleClassChangeError: Implementing class
13:10:39.559 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at java.lang.ClassLoader.defineClass1(Native Method)
13:10:39.562 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
13:10:39.566 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
13:10:39.570 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
13:10:39.573 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
13:10:39.577 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
13:10:39.581 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
13:10:39.584 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at java.security.AccessController.doPrivileged(Native Method)
13:10:39.588 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
13:10:39.592 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
13:10:39.595 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
13:10:39.599 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
13:10:39.602 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at java.lang.ClassLoader.defineClass1(Native Method)
13:10:39.606 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
13:10:39.609 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
13:10:39.613 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
13:10:39.617 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
13:10:39.621 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
13:10:39.624 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
13:10:39.628 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at java.security.AccessController.doPrivileged(Native Method)
13:10:39.631 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
13:10:39.635 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
13:10:39.639 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
13:10:39.642 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
13:10:39.645 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at java.lang.Class.getDeclaredMethods0(Native Method)
13:10:39.649 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at java.lang.Class.privateGetDeclaredMethods(Class.java:2442)
13:10:39.653 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at java.lang.Class.getMethod0(Class.java:2685)
13:10:39.656 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at java.lang.Class.getMethod(Class.java:1620)
13:10:39.660 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at sun.launcher.LauncherHelper.getMainMethod(LauncherHelper.java:492)
13:10:39.664 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument]
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:484)
13:10:39.903 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:cobertura-instrument] Exception in thread "main"

Cobertura dependencies:

testRuntime - Classpath for running the compiled test classes.
...
\--- net.sourceforge.cobertura:cobertura:1.9.4.1
     +--- oro:oro:2.0.8
     +--- asm:asm:3.0 -> 3.2 (*)
     +--- asm:asm-tree:3.0 -> 3.2 (*)
     +--- log4j:log4j:1.2.9
     \--- org.apache.ant:ant:1.7.0
          \--- org.apache.ant:ant-launcher:1.7.0

Simply excluding the ASM group from the Cobertura dependencies didn’t work. Nor did defining a client module dependency on Cobertura in which I forced the version to 4.0. But if ASM 4 breaks binary compatibility, I guess those options are doomed to failure.

I am using Gradle 1.2, Oracle JDK 1.7.0_05.


(Justin Ryan) #2

Which cobertura plugin are you using? There are two open source ones, and they have different levels of support and ways in which they setup cobertura.


(Dan Stine) #3

We are using home-brewed support created last year, which mostly follows the Gradle Cookbook: http://docs.codehaus.org/display/GRADLE/Cookbook#Cookbook-usingCobertura

This is the snippet for building our custom plugins, which is where I had the problem. In the custom plugins themselves, we cleaned this up a bit (e.g. no more copy/backup/replace): https://gist.github.com/3713721

I just tried ‘com.mapvine:gradle-cobertura-plugin:0.3.1’ but got a similar error:

org.gradle.api.GradleException: Could not generate a proxy class for class org.gradle.api.internal.project.DefaultProject.
        at org.gradle.api.internal.AbstractClassGenerator.generate(AbstractClassGenerator.java:187)
        at org.gradle.api.internal.ClassGeneratorBackedInstantiator.newInstance(ClassGeneratorBackedInstantiator.java:36)
        at org.gradle.api.internal.project.ProjectFactory.createProject(ProjectFactory.java:47)
        at org.gradle.api.internal.project.ProjectFactory.createProject(ProjectFactory.java:31)
        at org.gradle.testfixtures.internal.ProjectBuilderImpl.createProject(ProjectBuilderImpl.java:72)
        at org.gradle.testfixtures.ProjectBuilder.build(ProjectBuilder.java:99)
        at org.gradle.testfixtures.ProjectBuilder$build.call(Unknown Source)
        at com.copyright.rup.scm.gradle.plugins.PluginTestUtils.getTestProject(PluginTestUtils.groovy:14)
        at com.copyright.rup.scm.gradle.plugins.PluginTestUtils$getTestProject.call(Unknown Source)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:112)
        at com.copyright.rup.scm.gradle.plugins.RupJavaPluginTest.applyPlugin(RupJavaPluginTest.groovy:17)
          Caused by:
        java.lang.IncompatibleClassChangeError: Found interface org.objectweb.asm.MethodVisitor, but class was expected
            at org.gradle.api.internal.AsmBackedClassGenerator$ClassBuilderImpl.addGetter(AsmBackedClassGenerator.java:470)
            at org.gradle.api.internal.AsmBackedClassGenerator$ClassBuilderImpl.addGetter(AsmBackedClassGenerator.java:464)
            at org.gradle.api.internal.AsmBackedClassGenerator$ClassBuilderImpl.mixInGroovyObject(AsmBackedClassGenerator.java:430)

(Luke Daley) #4

It’s because of the ASM upgrade: http://gradle.org/docs/current/release-notes#upgrade-to-asm-4.0

Any chance you can upgrade the version of ASM you are using?


(Dan Stine) #5

I tried, but maybe I am not doing it correctly; please let me know!

ASM is a dependency of my project via two paths. One is Cobertura, one is tberglund’s gradle-liquibase-plugin.

I declared this to upgrade ASM for Cobertura:

testRuntime module('net.sourceforge.cobertura:cobertura:1.9.4.1') {
        dependency 'oro:oro:2.0.8'
        dependency 'org.ow2.asm:asm:4.0'
        dependency 'org.ow2.asm:asm-tree:4.0'
        dependency 'log4j:log4j:1.2.9'
        dependency 'org.apache.ant:ant:1.7.0'
    }

And I commented out the gradle-liquibase-plugin dependency for the moment.

But then Cobertura has an error, I think because it wants the old ASM (see below). Unless I’m missing something, Cobertura itself would have to be re-released for ASM 4.

[ant:cobertura-instrument] java.lang.NoClassDefFoundError: org/objectweb/asm/ClassAdapter
[ant:cobertura-instrument]
    at java.lang.ClassLoader.defineClass1(Native Method)
[ant:cobertura-instrument]
    at java.lang.ClassLoader.defineClass(ClassLoader.java:791)
[ant:cobertura-instrument]
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
[ant:cobertura-instrument]
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
[ant:cobertura-instrument]
    at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
[ant:cobertura-instrument]
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
[ant:cobertura-instrument]
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
[ant:cobertura-instrument]
    at java.security.AccessController.doPrivileged(Native Method)
[ant:cobertura-instrument]
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
[ant:cobertura-instrument]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
[ant:cobertura-instrument]
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
[ant:cobertura-instrument]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
[ant:cobertura-instrument]
    at java.lang.Class.getDeclaredMethods0(Native Method)
[ant:cobertura-instrument]
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2442)
[ant:cobertura-instrument]
    at java.lang.Class.getMethod0(Class.java:2685)
[ant:cobertura-instrument]
    at java.lang.Class.getMethod(Class.java:1620)
[ant:cobertura-instrument]
    at sun.launcher.LauncherHelper.getMainMethod(LauncherHelper.java:492)
[ant:cobertura-instrument]
    at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:484)
[ant:cobertura-instrument] Caused by: java.lang.ClassNotFoundException: org.objectweb.asm.ClassAdapter
[ant:cobertura-instrument]
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
[ant:cobertura-instrument]
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
[ant:cobertura-instrument]
    at java.security.AccessController.doPrivileged(Native Method)
[ant:cobertura-instrument]
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
[ant:cobertura-instrument]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
[ant:cobertura-instrument]
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
[ant:cobertura-instrument]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
[ant:cobertura-instrument]
    ... 18 more
[ant:cobertura-instrument] Exception in thread "main"

(Luke Daley) #6

The question is whether the classpaths need to mix.

  1. Does cobertura introduce runtime dependencies to test execution? 2. Does cobertura instrumentation require runtime dependencies on the classpath?

(Dan Stine) #7

Good point. My implementation uses the ‘testRuntime’ configuration, and it probably shouldn’t. I’ve learned more about Gradle since writing this.

But as noted above, I tried using ‘com.mapvine:gradle-cobertura-plugin:0.3.1’. This plugin creates a separate ‘cobertura’ configuraion, yet I still see the ‘IncompatibleClassChangeError’ quoted above. I followed the instructions here and thus added

buildscript {
    dependencies {
        classpath 'com.mapvine:gradle-cobertura-plugin:0.3.1'
    }
}

Per the stacktrace, the failure is in calling Gradle’s ‘ProjectBuilder’. If that depends on ASM 4 and we’ve already put ASM 3 on the buildscript classpath for Cobertura …


(Dan Stine) #8

Here’s a stripped-down sample project that recreates the error: https://github.com/dstine/gradle-asm


(Luke Daley) #9

I’ve submitted a pull request for that plugin that fixes the issue.

Luckily, cobertura is compatible with asm 4. Which means you should put cobertura and it’s dependencies last on the test runtime classpath. If you do that, it all works.


(Eric Wendelin) #10

I’m checking out the pull request and verifying the fix.

I’ll let you all know when there’s a new version published, probably in a few hours.


(Dan Stine) #11

Thanks, Luke and Eric.


(Eric Wendelin) #12

With Luke’s help, I have pushed version 1.0 of our cobertura plugin to Maven Central. It will take a couple hours to become available. Please update your buildScript to:

buildscript {

dependencies {

classpath ‘com.mapvine:gradle-cobertura-plugin:1.0’

}

}

This release slightly changes how you declare your sources for code coverage. Configure cobertura like so:

cobertura {

format = ‘xml’ // Optional

includes = [’/*.java’, '/*.groovy’]

}

Thanks again to Luke for his huge help.


(Dan Stine) #13

The new version of the plugin works for my build. Thanks again.


(Luke Daley) #14

Great news :slight_smile: Open source at its finest. Thanks for the prompt response Eric.


(Eric Wendelin) #15

Thanks for letting me know about the problem right away and all of the helpful code, Luke :slight_smile: