Hello there,
we’ve been writing Gralde Plugins for our projects configurations for quiet a while now and did some functional testing allmost exactly how it is described here: https://docs.gradle.org/nightly/userguide/testing_gradle_plugins.html#setting_up_automated_tests
Using a dedicated source set and testing with spok works pretty nice for us.
We recently discovered, that we are missing the testcoverage from jacoco for these kind of tests, so we applied the https://github.com/koral--/jacoco-gradle-testkit-plugin plugin.
At first everything was ok, starting functional tests from Intellij workes like it should and we could also produce a html report afterwards to see that the coverage was recorded successfully.
But then we found out that on a windows (developer) system we can no longer execute those tests from the command line, and this is how it fails:
Failed to load cache entry for task ':resource-validator-plugin:functionalTest', cleaning outputs and falling back to (non-incremental) execution
org.gradle.api.UncheckedIOException: Failed to create MD5 hash for file content.
at org.gradle.internal.hash.DefaultStreamHasher.hash(DefaultStreamHasher.java:37)
at org.gradle.internal.hash.DefaultFileHasher.hash(DefaultFileHasher.java:40)
at org.gradle.api.internal.changedetection.state.CachingFileHasher.snapshot(CachingFileHasher.java:93)
at org.gradle.api.internal.changedetection.state.CachingFileHasher.hash(CachingFileHasher.java:71)
at org.gradle.api.internal.changedetection.state.SplitFileHasher.hash(SplitFileHasher.java:65)
at org.gradle.internal.snapshot.impl.DefaultFileSystemSnapshotter.snapshot(DefaultFileSystemSnapshotter.java:163)
at org.gradle.internal.snapshot.impl.DefaultFileSystemSnapshotter.snapshotAndCache(DefaultFileSystemSnapshotter.java:149)
at org.gradle.internal.snapshot.impl.DefaultFileSystemSnapshotter.snapshotAndCache(DefaultFileSystemSnapshotter.java:133)
at org.gradle.internal.snapshot.impl.DefaultFileSystemSnapshotter.access$200(DefaultFileSystemSnapshotter.java:62)
at org.gradle.internal.snapshot.impl.DefaultFileSystemSnapshotter$2.create(DefaultFileSystemSnapshotter.java:116)
at org.gradle.internal.snapshot.impl.DefaultFileSystemSnapshotter$2.create(DefaultFileSystemSnapshotter.java:113)
at org.gradle.cache.internal.ProducerGuard$StripedProducerGuard.guardByKey(ProducerGuard.java:115)
at org.gradle.internal.snapshot.impl.DefaultFileSystemSnapshotter.snapshot(DefaultFileSystemSnapshotter.java:113)
at org.gradle.internal.snapshot.impl.DefaultFileSystemSnapshotter$FileCollectionLeafVisitorImpl.visitCollection(DefaultFileSystemSnapshotter.java:241)
at org.gradle.api.internal.file.AbstractFileCollection.visitLeafCollections(AbstractFileCollection.java:233)
at org.gradle.api.internal.file.CompositeFileCollection.visitLeafCollections(CompositeFileCollection.java:205)
at org.gradle.internal.snapshot.impl.DefaultFileSystemSnapshotter.snapshot(DefaultFileSystemSnapshotter.java:126)
at org.gradle.internal.fingerprint.impl.AbstractFileCollectionFingerprinter.fingerprint(AbstractFileCollectionFingerprinter.java:48)
at org.gradle.api.internal.tasks.execution.DefaultTaskFingerprinter.fingerprintTaskFiles(DefaultTaskFingerprinter.java:45)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$TaskExecution.snapshotAfterOutputsGenerated(ExecuteActionsTaskExecuter.java:328)
at org.gradle.internal.execution.steps.SnapshotOutputsStep.execute(SnapshotOutputsStep.java:48)
at org.gradle.internal.execution.steps.SnapshotOutputsStep.execute(SnapshotOutputsStep.java:31)
at org.gradle.internal.execution.steps.CacheStep.executeWithoutCache(CacheStep.java:201)
at org.gradle.internal.execution.steps.CacheStep.executeAndStoreInCache(CacheStep.java:183)
at org.gradle.internal.execution.steps.CacheStep.lambda$executeWithCache$2(CacheStep.java:106)
at java.util.Optional.orElseGet(Optional.java:267)
at org.gradle.internal.execution.steps.CacheStep.lambda$executeWithCache$3(CacheStep.java:106)
at org.gradle.internal.Try$1.apply(Try.java:59)
at org.gradle.internal.Try$1.apply(Try.java:56)
at org.gradle.internal.Try$Success.flatMap(Try.java:102)
at org.gradle.internal.Try.map(Try.java:56)
at org.gradle.internal.execution.steps.CacheStep.executeWithCache(CacheStep.java:79)
at org.gradle.internal.execution.steps.CacheStep.execute(CacheStep.java:69)
at org.gradle.internal.execution.steps.CacheStep.execute(CacheStep.java:45)
at org.gradle.internal.execution.steps.BroadcastChangingOutputsStep.execute(BroadcastChangingOutputsStep.java:49)
at org.gradle.internal.execution.steps.StoreSnapshotsStep.execute(StoreSnapshotsStep.java:43)
at org.gradle.internal.execution.steps.StoreSnapshotsStep.execute(StoreSnapshotsStep.java:32)
at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:38)
at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:24)
at org.gradle.internal.execution.steps.SkipUpToDateStep.executeBecause(SkipUpToDateStep.java:96)
at org.gradle.internal.execution.steps.SkipUpToDateStep.lambda$execute$0(SkipUpToDateStep.java:89)
at java.util.Optional.map(Optional.java:215)
at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:54)
at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:38)
at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:77)
at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:37)
at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:36)
at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:26)
at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:90)
at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:48)
at org.gradle.internal.execution.impl.DefaultWorkExecutor.execute(DefaultWorkExecutor.java:33)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:117)
at org.gradle.api.internal.tasks.execution.ResolveBeforeExecutionStateTaskExecuter.execute(ResolveBeforeExecutionStateTaskExecuter.java:75)
at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:62)
at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:108)
at org.gradle.api.internal.tasks.execution.ResolveBeforeExecutionOutputsTaskExecuter.execute(ResolveBeforeExecutionOutputsTaskExecuter.java:67)
at org.gradle.api.internal.tasks.execution.StartSnapshotTaskInputsBuildOperationTaskExecuter.execute(StartSnapshotTaskInputsBuildOperationTaskExecuter.java:62)
at org.gradle.api.internal.tasks.execution.ResolveAfterPreviousExecutionStateTaskExecuter.execute(ResolveAfterPreviousExecutionStateTaskExecuter.java:46)
at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:94)
at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:95)
at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:56)
at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:73)
at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:49)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:416)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:406)
at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:102)
at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36)
at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:49)
at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:43)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:355)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:343)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:336)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:322)
at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker$1.execute(DefaultPlanExecutor.java:134)
at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker$1.execute(DefaultPlanExecutor.java:129)
at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:202)
at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:193)
at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:129)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.io.IOException: The process cannot access the file because another process has locked a portion of the file
at java.io.FileInputStream.readBytes(Native Method)
at java.io.FileInputStream.read(FileInputStream.java:233)
at org.gradle.internal.hash.DefaultStreamHasher.doHash(DefaultStreamHasher.java:52)
at org.gradle.internal.hash.DefaultStreamHasher.hash(DefaultStreamHasher.java:35)
... 90 more
We already tried to force sequential execution of tests with
functionalTest {
maxParallelForks = 1
}
but had no success.
We also tried gradlew functionalTest --no-daemon --no-build-cache
without success.
On our Linux based build environment, this is not a problem, only on the developers windows machines.
We are using Gradle 5.5.1 (a update is scheduled, but will take some time) and Java 1.8.0_202.
Any ideas are appreciated.
Update:
Tested with amazon-corretto-8.275.01.1-windows-x64-jdk (1.8.0_275) and still failing.
another possibly relevant output:
Custom actions are attached to task ':resource-validator-plugin:functionalTest'.
Caching disabled for task ':resource-validator-plugin:functionalTest' because:
Gradle does not know how file 'build\jacoco\functionalTest.exec' was created (output property 'jvmArgumentProviders.jacocoAgent$0.jacoco.destinationFile'). Task output caching requires exclusive access to output paths to guarantee correctness.
maybe the binary jacoco.exec file is beeing written to twice - from the jacocoAgent of the calling gradle instance and from the jacocoAgent of the forked test build? Not sure how to suppress that and why it is only failing on windows?