Custom plugin test cases failing with MS-5

I have some test cases written against a custom plugin that I wrote. They passed with MS-3, but are now failing (I’m guessing because of a classpath issue) with MS-5. The plugin is used for code generation via XJC.

My test case starts with

Project project = ProjectBuilder.builder().build()
          when: 'xjc is applied without java plugin, and an XJC configuration is added'
        project.apply plugin: 'xjc'

In src/main/resources/META-INF/gradle-plugins, I have xjc.properties which contains the line

implementation-class=my.package.XJCPlugin

On the

project.apply plugin: 'xjc'

line though, the test case fails with

org.gradle.api.plugins.PluginInstantiationException: Could not find implementation class ‘null’ for plugin ‘xjc’ specified in file:/my/project/directory/GradlePlugins/subprojects/xjc/build/classes/main/META-INF/gradle-plugins/xjc.properties.

at org.gradle.api.internal.plugins.DefaultPluginRegistry.getTypeForId(DefaultPluginRegistry.java:102)

at org.gradle.api.internal.plugins.DefaultPluginRegistry.getTypeForId(DefaultPluginRegistry.java:76)

at org.gradle.api.internal.plugins.DefaultProjectsPluginContainer.getTypeForId(DefaultProjectsPluginContainer.java:102)

at org.gradle.api.internal.plugins.DefaultProjectsPluginContainer.apply(DefaultProjectsPluginContainer.java:37)

at org.gradle.api.internal.plugins.DefaultObjectConfigurationAction.applyPlugin(DefaultObjectConfigurationAction.java:101)

at org.gradle.api.internal.plugins.DefaultObjectConfigurationAction.execute(DefaultObjectConfigurationAction.java:114)

at org.gradle.api.internal.project.AbstractProject.apply(AbstractProject.java:841)

at my.package.XJCPluginTest.default source directory is defined when java plugin is added(XJCPluginTest.groovy:41) Caused by: java.lang.ClassNotFoundException: my.package.XJCPlugin not found.

at org.gradle.util.MultiParentClassLoader.loadClass(MultiParentClassLoader.java:51)

at java.lang.ClassLoader.loadClass(ClassLoader.java:247)

at org.gradle.api.internal.plugins.DefaultPluginRegistry.getTypeForId(DefaultPluginRegistry.java:100)

… 7 more

Are you sure it works fine for M3? I cannot figure out what the problem is from looking at the stack trace. How does it behave in M4? Do you run it from command line (e.g. gradle test) VS in IDE?

Hmmm, it might be regression with ProjectBuilder. As a workaround, if you have an instance of your plugin, you can do:

myPlugin.apply(someProject)

Might this be related to the gradleApi() issue i reported on these forums a few days ago?

That issue also has to do with invalid classpaths on custom plugin projects in M5. For the gradleApi issue I know it works in M3 and not in M5. The issue has a JIRA attached to it. Jira is closed, but I suspect it is still zombying around.

It’ll be due to this: http://wiki.gradle.org/display/GRADLE/Gradle+1.0-milestone-5+Migration+Guide#Gradle1.0-milestone-5MigrationGuide-Buildscriptclasspath

ProjectBuilder should make the test classes visible via the shared script classloader.

Do we already have a ticket for it?

Don’t know if this helps at all, but I did some digging and found that the Plugin class was discovered just fine, but the FilteringClassLoader’s classAllowed() method refused my custom package.

I changed my test case from

project.apply plugin: 'xjc'

to

project.plugins.apply(XJCPlugin)

and it worked fine.

Also, in response to Szcezepan’s questions, I’m running everything via the CLI. Everything passes with MS3, but MS4 gives me the same problem as MS5.

I had exactly the same problem! Thanks for the temporary fix with project.plugins.apply… It works flawlessly… I think this is a problem with “allowPackage” not passed up the MultiParentClassLoaders and URLClassloaders. I looked at the source code and debugged it a bit, but I have not enough code knowledge. It seems that when the classloader hierarchy is build the “allowedPackages” are either not yet set or not traversing up the hierarchy. In my debug session in all the classloaders in hierarchy “packages” were empty - only in the one at the very bottom, the packages contained a lot of packages including my packages where Plugins were located…

For reference, the gradleApi() issue went away in a later M5 snapshot.

Jarek, glad my fix helped you out.

I think the build script classpath uses the allowPackage mechanism to limit which packages are visible to the script (http://wiki.gradle.org/display/GRADLE/Gradle+1.0-milestone-5+Migration+Guide#Gradle1.0-milestone-5MigrationGuide-Buildscriptclasspath). I think that when you declare a dependency via ‘dependencies {…}’, a new classloader is added to the classloader hierarchy which gives you access to the artifacts.

With a test case though, you don’t use the ‘dependencies {…}’ notation and so the default classloaders (the ones that limit which packages are allowed to be loaded) end up trying to load the custom plugin class specified in gradle-plugins/plugin.properties file. It doesn’t work because of the build script classpath change.