Execute task "jacocoTestReportMerged" failure on Gradle 5.0
canglongxiang opened this issue ยท 26 comments
Greate plugin for jacaco support!
Everything is ok when using with jacoco 0.8.2, gradle 4.10.2, jdk8 and this plugin 0.13.0.
After upgrade gradle to 5.0, execute task "jacocoTestReportMerged" has below error info:
FAILURE: Build failed with an exception.
What went wrong:
java.lang.StackOverflowError (no error message)
PS: Task "jacocoTestReport" is ok.
Can you send a proper stacktrace?
I'm closing this issue due to inactivity. If you have any further input on the issue, don't hesitate to reopen this issue or post a new one.
I'm getting this same exception with this recursion in the stack trace:
at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext.resolveAsFileCollections(DefaultFileCollectionResolveContext.java:92)
at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext$FileCollectionConverter.convertInto(DefaultFileCollectionResolveContext.java:164)
at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext.doResolve(DefaultFileCollectionResolveContext.java:109)
at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext.resolveAsFileCollections(DefaultFileCollectionResolveContext.java:92)
...
Can we reopen this?
Here's more of the stack trace (my terminal buffer was cutting it off):
* Exception is:
java.lang.StackOverflowError
at org.gradle.util.GUtil.addToCollection(GUtil.java:163)
at org.gradle.util.GUtil.addToCollection(GUtil.java:174)
at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext.doResolve(DefaultFileCollectionResolveContext.java:130)
at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext.resolveAsFileCollections(DefaultFileCollectionResolveContext.java:92)
at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext$FileCollectionConverter.convertInto(DefaultFileCollectionResolveContext.java:164)
at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext.doResolve(DefaultFileCollectionResolveContext.java:109)
at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext.resolveAsFileCollections(DefaultFileCollectionResolveContext.java:92)
...
I'm only seeing Gradle internals here and nothing from my plugin. Can you extract a proper stacktrace somehow?
I would assume this is related to this: gradle/gradle#7636
Is gradle/gradle#7636 not enough information to reopen this? Appending to the source directories in this way:
Is the source of the StackOverflowError
. Rather, the sources should be collected and set once using the additional sources methods or setFrom
on the FileCollection
s.
Sure, I can reopen this but it seems like this is something Gradle can/will fix? If you can come up with a solution, feel free to create a PR.
I'm not sure they're going to fix it on their end: gradle/gradle#7636 (comment)
I worked around it by doing:
def allFiles = task.fileCollection.files + newFiles
task.fileCollection.setFrom(allFiles)
Where have you done that?
I copied the lastest release's sources (master is broken) into buildSrc.
Mind creating a PR with a fix?
@pardom have you had time to look into this?
Closed by #151
Thanks :)
I'm still getting the StackOverFlow error with the 0.14.0-SNAPSHOT
version.
Ideas?
Gradle: 5.1.1
Gradle tools plugin: 3.4.0
Android Studio: 3.4
Still facing this issue on 0.16.0
This works:
./gradlew clean jacocoTestReportDebug mergeJacocoReports jacocoTestReportMerged
this doesn't
./gradlew clean jacocoTestReportDebug mergeJacocoReports && ./gradlew jacocoTestReportMerged
Mind submitting a PR?
I have not really played with source code of the plugin itself and I've tried to see if Gradle gives any useful error, but it gives nothing, so I have no idea whatsoever, why that would be the case. I have not really dug deep enough.
Ok, I'm not sure how deep I'll be able to dig into this, but my preliminary finding is, that it might have something to do with this line:
Commenting this line prevents crash of the build, running:
./gradlew clean jacocoTestReportDebug mergeJacocoReports && ./gradlew jacocoTestReportMerged
Also, I'm adding some prints to the start of jacocoTestReportMerged
task. It looks like this task is run at least twice, once during start(which is weird btw, that it runs during start of the build, since it's the very last task that should have been run), when mergeTask.destinationFile
doesn't exist yet and then when running the task jacocoTestReportMerged
after &&
, the mergedReport.exec
file already exists, but then it fails somewhere in gradle (I don't have any error message).
Disabling the line that I sent above makes the task succeed, but obviously nothing is happening.
I'm not sure if it's incorrect contents of the report file, because I don't know how to verify that.
ok bit more information and since I'm really not knowledgable about writing gradle plugins or using JaCoCo very much, I could probably also use some help. I've localised the problem to this line:
mergedReportTask.classDirectories.setFrom(classDirectories.getFrom() + mergedReportTask.classDirectories.getFrom())
now, if I change this line to this:
mergedReportTask.classDirectories.setFrom(classDirectories.getFrom())
the build doesn't fail, but obviously the generated report is not a combined report, rather its just
a report of the last variant (reason for that is understandable from the code).
So there must be some problem in this merging part of class directories.
At first I thought that the problem is, that actually getting mergedReportTask.classDirectories.getFrom()
returns collection of collections, while classDirectories.getFrom()
returns simple collection.
I've attempted to flatten it, that didn't help. I have also noticed, that despite flattening, same collection would appear there over and over again (despite classDirectories.setFrom
accepting a Set
). (Or at least it appears as the same collection, having the same displayName
)
I thought maybe the problem is in incorrect identification of unique collections, so I wrote this hacky code to see if it helps:
def merged = (classDirectories.getFrom() + mergedReportTask.classDirectories.getFrom().flatten())
.unique { m ->
if (m instanceof DefaultConfigurableFileCollection) {
println("PATH: ${(m as DefaultConfigurableFileCollection).displayName}")
return (m as DefaultConfigurableFileCollection).displayName
}
println("TREE: ${(m as DefaultConfigurableFileTree).displayName}")
(m as DefaultConfigurableFileTree).displayName
}
println("MERGED (${merged.size()}): $merged")
mergedReportTask.classDirectories.setFrom(merged)
The build itself doesn't fail now. Maybe that's good, maybe not. I don't know. Unfortunately the merged html report is actually empty. And here I'm at my wits' end.
Any pointer would be very helpful.
Also, if it helps, this is how the print of my merged
property looks like:
MERGED (4): [directory 'path/core/build', directory 'path/common/build', directory 'path/app/build', file collection]
But you can see this line: mergedReportTask.classDirectories.setFrom(merged)
. When printing println("${mergedReportTask.classDirectories.getFrom()}")
it looks like this, when printed:
[[directory 'path/core/build', directory 'path/common/build', directory 'path/app/build', file collection]]
The thing that looks funny to me in that second output is, that now it's a collection within collection. Which... maybe it's correct, I don't know, I don't understand internals of Jacoco that well.
Any ideas? :-)
No idea's no. Maybe this is a bug in the Jacoco API that we're using? In the end we're just delegating but not having an actual implementation.
ok, I'll see when I have time to work on this again and I'll try to bother some more people ;o)
Sorry that I could not help more. To be honest, I've also mostly stopped using this plugin myself. I have it in my open source projects but that's about it.
@vanniktech What are you using instead?
Stopped caring about code coverage mostly. My open source projects are still using this project but that's about it.