trautonen / coveralls-maven-plugin

Maven plugin for submitting Java code coverage reports to Coveralls web service.
MIT License
312 stars 123 forks source link

ArrayIndexOutOfBoundsException on multi module build #56

Open hazendaz opened 9 years ago

hazendaz commented 9 years ago

I have a project https://github.com/hazendaz/waffle. On this project, we have builds for various versions of tomcat from 5 through 8. If I run the current 3.0.1 coveralls, it will work if I exclude tomcat 7 and 8. I've tried a few variations and it seems if I run only tomcat 7 or only tomcat 8, it also works. I don't really understand what the issue might be here. We also have multiple builds like this for spring 2 through 4 and those work without issue. Any ideas?

Here is the stack trace. [ERROR] Failed to execute goal org.eluder.coveralls:coveralls-maven-plugin:3.0.1:report (default-cli) on project waffle-parent: Build error: 247 -> [Help 1] org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.eluder.coveralls:coveralls-maven-plugin:3.0.1:report (default-cli) on project waffle-parent: Build error at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:216) at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153) at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145) at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:116) at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:80) at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51) at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:120) at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:347) at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:154) at org.apache.maven.cli.MavenCli.execute(MavenCli.java:582) at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:214) at org.apache.maven.cli.MavenCli.main(MavenCli.java:158) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289) at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229) at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415) at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356) Caused by: org.apache.maven.plugin.MojoExecutionException: Build error at org.eluder.coveralls.maven.plugin.CoverallsReportMojo.execute(CoverallsReportMojo.java:216) at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:132) at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:208) ... 19 more Caused by: java.lang.ArrayIndexOutOfBoundsException: 247 at org.eluder.coveralls.maven.plugin.domain.Source.addCoverage(Source.java:92) at org.eluder.coveralls.maven.plugin.parser.JaCoCoParser.onEvent(JaCoCoParser.java:61) at org.eluder.coveralls.maven.plugin.parser.AbstractXmlEventParser.parse(AbstractXmlEventParser.java:64) at org.eluder.coveralls.maven.plugin.CoverallsReportMojo.writeCoveralls(CoverallsReportMojo.java:325) at org.eluder.coveralls.maven.plugin.CoverallsReportMojo.execute(CoverallsReportMojo.java:205) ... 21 more

trautonen commented 9 years ago

I guess that you have equally named source files in different modules. The problem is that when running a multi-module project, the plugin gathers all modules as potential source directories and when a source file is found in a coverage report the plugin just tries whichever source loader can grab the sources. This will result a failure because in the JaCoCo report there's different source file than the plugin's source loader sees.

I think it's good practice to uniquely name the source files anyway. Duplicate file/package names might lead to issues with other tools too. If you can name the packages for example along with the tomcat version like waffle.apache.tomcat7 etc. this should solve your problem. If you cannot change the package names, then we might be out of luck. It would be really hard to track in the plugin in which module the source should be loaded and at the moment I don't have time to investigate this feature. I'll keep this issue in the backlog and see if it can be implemented at some point with reasonable effort.

hazendaz commented 9 years ago

Thanks for detailed response. I sort of was thinking that may be the issue. Although the spring modules do not have the issue and package naming matches. I will look at renaming the packages tonight and will report back.

--- Original Message ---

From: "Tapio Rautonen" notifications@github.com Sent: November 3, 2014 2:27 AM To: "trautonen/coveralls-maven-plugin" coveralls-maven-plugin@noreply.github.com Cc: "Jeremy Landis" jeremylandis@hotmail.com Subject: Re: [coveralls-maven-plugin] ArrayIndexOutOfBoundsException on multi module build (#56)

I guess that you have equally named source files in different modules. The problem is that when running a multi-module project, the plugin gathers are modules as potential source directories and when a source file is found in a coverage report the plugin just tries whichever source loader can grab the sources. This will result a failure because in the JaCoCo report there's different source file than the plugin's source loader sees.

I think it's good practice to uniquely name the source files anyway. Duplicate file/package names might lead to issues with other tools too. If you can name the packages for example along with the tomcat version like waffle.apache.tomcat7 etc. this should solve your problem. If you cannot change the package names, then we might be out of luck. It would be really hard to track in the plugin in which module the source should be loaded and at the moment I don't have time to investigate this feature. I'll keep this issue in the backlog and see if it can be implemented at some point with reasonable effort.


Reply to this email directly or view it on GitHub: https://github.com/trautonen/coveralls-maven-plugin/issues/56#issuecomment-61446349

hazendaz commented 9 years ago

OK - verified changing the package naming fixed the issue. Still doesn't fully explain why it occurs only on some of the duplicated packages but clearly not a problem with this plugin and indicates possibly larger undiscovered issue in my project. Therefore, again thanking you for assistance and closing this ticket out.

trautonen commented 9 years ago

The reason why it only occurs on some packages is how the source loading is implemented in the plugin. Let me enlighten some internals here.

The plugin creates multiple source loaders, which are responsible for loading the source files in the project. By default all reactor maven modules are attached and also explicit user defined source directories.

Source loaders are asked one by one if they can load the file requested in the coverage report. If some source loader returns a valid source, it will be used. After the source is found, the coverage report is parsed further and the coverage details are attached.

Now the exception you see is only thrown if the actual source file has less actual lines of code than the coverage report expects for coverage data. If the source file has same number or more lines of code, then the coverage is added without any exceptions. If you have same logic to show the coverage in a source file that Coveralls used, you'd just see misplaced lines of coverage.

hazendaz commented 9 years ago

Thanks for the information. I think I have a clearer understanding now and see really why I had issue. I think keeping this open for now is probably the best idea especially if anyone else runs into this. If I get time, maybe I'll look into this and contribute!

ceki commented 9 years ago

I have a similar issue with the slf4j project, which is a multi-module maven project. I get the following exception when executing the command

mvn cobertura:cobertura coveralls:report

Here is the exception.

Caused by: java.lang.ArrayIndexOutOfBoundsException: 74
        at org.eluder.coveralls.maven.plugin.domain.Source.addCoverage(Source.java:92)
        at org.eluder.coveralls.maven.plugin.parser.CoberturaParser.onEvent(CoberturaParser.java:68)
        at org.eluder.coveralls.maven.plugin.parser.AbstractXmlEventParser.parse(AbstractXmlEventParser.java
        at org.eluder.coveralls.maven.plugin.CoverallsReportMojo.writeCoveralls(CoverallsReportMojo.java:348
        at org.eluder.coveralls.maven.plugin.CoverallsReportMojo.execute(CoverallsReportMojo.java:225)

I have several classes which are named exactly the same with the same package name etc. However, that is part of the slf4j architecture which cannot be changed.

I'll try with the logback project if it fairs any better.

hazendaz commented 9 years ago

On possibly solution to this would be to create a coveralls branch and on that branch rework the packaging to avoid the issue then have only that branch used to get the coverage scores. For the project I was working on, I just did it in my local branch, got the scans, then reverted the logic. I too ultimately decided it was something I couldn't change without greatly affecting those using the product and it wasn't worth fixing just to satisfy usage.

trautonen commented 9 years ago

Hacks to get the coverage calculated just doesn't seem right. This issue is quite hard to solve and is now even more harder due to due to scanning source loaders (#63) that allow less strict control where the sources are loaded.

I guess it would be possible to lock the source loading under the reactor module that contains the sources. This would require source loaders to store the module's base directory and when loading the sources the source file's fully qualified path can be compared against the module's base dir. Only source loaders that match the file with their base dir will be applied.

I can give that approach a try at some point. But can't promise any estimates because I'm really busy at the moment.

trautonen commented 9 years ago

And just realized that Cobertura does not store the fully qualified file name anywhere. In the aggregate mode it just tells which source roots are scanned and then uses relative file names...

liushuainudt commented 6 years ago

try to upgrade to version 3.53. this works for me.