Open fadookie opened 1 year ago
Not sure what it can be. The only place I see report.dtd is in the jacoco report. In my jacoco report xml I see something like:
<!DOCTYPE report PUBLIC "-//JACOCO//DTD Report 1.1//EN" "report.dtd">
but is not something I really care about... maybe the xml parser lib but I did nothing to change or don't know how it's modified.
are you using jacoco 0.8.8
? any special jacoco xml report configuration?
Thanks for the reply. I was using the configuration from https://blog.canopas.com/android-code-coverage-using-jacoco-6639a1fc4293
I was using jacoco 0.8.7. I was blocked by this so I decided to deintegrate this gradle plugin and use cover2cover instead. So if you want I can close the issue, but I'm happy to keep it open and continue to troubleshoot to help others who might run into the same issue in the future.
OK, so this is pretty hacky but I am trying out this plugin again (cover2cover is generating invalid XML) and I figured out a workaround... I just downloaded https://github.com/jacoco/jacoco/blob/master/org.jacoco.report/src/org/jacoco/report/xml/report.dtd into ~/.gradle/daemon/7.2/report.dtd
🤷♂️
It looks like it also works to save this file next to the jacoco XML file.
I suppose it might also work to edit the JaCoCo XML to have the fully qualified URL of https://raw.githubusercontent.com/jacoco/jacoco/master/org.jacoco.report/src/org/jacoco/report/xml/report.dtd
I don't see why it really looks for the dtd...
I tried with jacoco 0.8.7 but no matter how hard I try to screw up the DOCTYPE tag
<!DOCTYPE report PUBLIC "-//JACOCO//DTD Report 1.1//EN" "report.dtd">
(using a bad path, bad version, wrong file name, without the tag) I get no error.
That's bizarre. I can reproduce it 100% of the time even on JaCoCo 0.8.8. I tried changing the dtd to that raw URL to see if that would fix it but it didn't seem to work. What is your JDK version? Maybe something changed in the underlying XML parsing lib, if you're using one from the java standard library?
Hello, I tried on macOS & Linux jdk 11 &. 17. The xml library I use is SimpleXML I can't see where or why it cares about the dtd, I couldn't manage to make it care.
I may try to switch to another one when I'll have some time as this one is quite old, but wanted something easy and fast to implement.
had the same problem in a simply spring-kotlin-multimodule project with open-jdk-17, gradle 8.0.2 and the default used jacoco plugin. I also use macOS. I switched back to kover and with that it works fine.
So this is the solution I eventually landed at that's compatible with running in CI. In the gradle task, I download the DTD to the working directory:
jacocoToCobertura {
def inputDir = "$buildDir/reports/jacoco/testDevelopEnvironmentDebugUnitTestCoverage"
def inputFilePath = "$inputDir/testDevelopEnvironmentDebugUnitTestCoverage.xml"
// Workaround for parse error: Download JaCoCo DTD to working directory
def workingDir = new File(".").getAbsoluteFile().getParent()
def f = new File("$workingDir/report.dtd")
if (!f.exists()) {
new URL('https://raw.githubusercontent.com/jacoco/jacoco/master/org.jacoco.report/src/org/jacoco/report/xml/report.dtd')
.withInputStream{ i -> f.withOutputStream{ it << i }}
}
def outDir = "${buildDir}/reports/cobertura"
file(outDir).mkdirs()
inputFile.set(file(inputFilePath))
outputFile.set(file("$outDir/cobertura.xml"))
}
This vexing issue has been annoying me also for the past year, but FWIW, the solution above (thanks @fadookie!) led me to adopt this workaround:
tasks.named('jacocoToCobertura').configure {
dependsOn jacocoTestReport
doFirst {
def jacocoClasspathUrls = jacocoTestReport.jacocoClasspath.collect { it.toURI().toURL() }
def classloader = new URLClassLoader(jacocoClasspathUrls as URL[])
def jacocoReportsDir = jacocoTestReport.reports.xml.outputLocation.get().asFile.parent
new File(jacocoReportsDir, 'report.dtd').withWriter {
it << classloader.getResourceAsStream('org/jacoco/report/xml/report.dtd')
}
}
}
The key difference to the previous solution is that I'm unpacking the report.dtd
directly from Gradle's JaCoCo classpath instead of downloading it from the internet, and dropping it into build/reports/jacoco
instead of the Gradle daemon's global working directory.
P.S. For some reason, in CI/CD, the local build dir destination for the "missing" report.dtd
isn't working after all, but using
// [...]
def workingDir = new File('').absolutePath
new File(workingDir, 'report.dtd').withWriter {
// [...]
like in @fadookie's solution works fine.
My workaround is just to remove the doctype:
jacocoToCobertura {
// Remove the DOCTYPE otherwise the conversion fails with
// Error while running JacocoToCobertura conversion: `Loading Jacoco report error: `(was java.io.FileNotFoundException) .gradle/daemon/8.0.2/report.dtd (No such file or directory)
// See https://github.com/razvn/jacoco-to-cobertura-gradle-plugin/issues/11
val reportFile = file("$buildDir/reports/kover/report.xml")
val inputWithoutDoctypeFile = file("$buildDir/reports/kover/report-without-doctype.xml")
val docTypeToRemove = "<!DOCTYPE report PUBLIC \"-//JACOCO//DTD Report 1.1//EN\" \"report.dtd\">"
inputWithoutDoctypeFile.writeText(
reportFile.readText().replace(docTypeToRemove, "")
)
inputFile.set(inputWithoutDoctypeFile)
outputFile.set(file("$buildDir/reports/kover/cobertura.xml"))
}
Similar to the above ^
tasks.jacocoToCobertura {
val jacocoReport = file("$buildDir/reports/jacoco/test/jacocoTestReport.xml")
onlyIf { jacocoReport.exists() }
doFirst {
// This is a hack to remove the DOCTYPE from the jacoco report.
// Resolves https://github.com/razvn/jacoco-to-cobertura-gradle-plugin/issues/11
jacocoReport.readText().replace("<!DOCTYPE[^>]*>".toRegex(), "").let {
jacocoReport.writeText(it)
}
}
}
Thanks, everyone. I now am getting this all of a sudden as well. It must the due to a new dependency I've added recently, but I did neither touch Gradle nor this plugin 🤷
Anyway, if you adapt the above solutions a little bit, you reach this one that is generic and works by just utilizing the plugin's task's input:
// https://github.com/razvn/jacoco-to-cobertura-gradle-plugin/issues/11
tasks.named<JacocoToCoberturaTask>(JacocoToCoberturaPlugin.TASK_NAME) {
doFirst {
val inputFile = inputFile.asFile.get()
inputFile.writeText(
inputFile.readText().replace("<!DOCTYPE[^>]*>".toRegex(), "")
)
}
}
I have integrated the plugin following the instructions in the README and set an input and output path. I have confirmed that the input file exists, but when I try to run the
jacocoToCobertura
task I get aFileNotFoundException
. It seems the plugin is looking for a file called~/.gradle/daemon/7.2/report.dtd
but this file does not exist on my system.(This is occurring in a work project under NDA so I have redacted some of the build details). I added a println statement to log the input path.