How can I debug Gradle Worker Daemons in IntelliJ? - debugging

I am using Gradle Worker Daemons in a custom task to enable parallel work.
The Worker API can accommodate this using the processIsolation() method that causes the work to execute in a separate "worker daemon". These worker daemon processes will persist across builds and can be reused during subsequent builds. If system resources get low, however, Gradle will stop any unused worker daemons.
Note that this not the same as the Gradle Daemon.
I am using Gradle 7.5.1 and IntelliJ IDEA 2022.3.2 (Ultimate Edition).
Basic example - GenerateMD5 WorkAction
I have recreated the basic example in the Worker Daemon docs that will generate MD5 files, based on the example in the Gradle docs.
The exception is that I am using an external library, Apache Commons Codec, to generate the MD5.
// build.gradle.kts
import org.apache.commons.codec.digest.DigestUtils
buildscript {
repositories {
gradlePluginPortal()
mavenCentral()
}
dependencies {
classpath("commons-codec:commons-codec:1.15")
}
}
plugins {
`java-library`
}
repositories {
gradlePluginPortal()
mavenCentral()
}
abstract class GenerateMD5 : WorkAction<GenerateMD5.Parameters> {
interface Parameters : WorkParameters {
val sourceFile: RegularFileProperty
val md5File: RegularFileProperty
}
override fun execute() {
val sourceFile = parameters.sourceFile.asFile.get()
val md5File = parameters.md5File.asFile.get()
val md5Hex = DigestUtils.md5Hex(sourceFile.inputStream())
println("Generated MD5 for ${sourceFile.name}: $md5Hex")
md5File.writeText(md5Hex)
}
}
dependencies {
implementation("commons-codec:commons-codec:1.15")
}
abstract class CreateMD5 : DefaultTask() {
#get:InputFiles
abstract val source: ConfigurableFileCollection
#get:Classpath
abstract val codecClasspath: ConfigurableFileCollection
#get:OutputDirectory
abstract val destinationDirectory: DirectoryProperty
#get:Inject
protected abstract val workerExecutor: WorkerExecutor
#TaskAction
fun createHashes() {
val workQueue: WorkQueue = workerExecutor.processIsolation {
classpath.from(codecClasspath)
forkOptions {
maxHeapSize = "64m"
//debug = true
}
}
source.files.forEach { file ->
workQueue.submit(GenerateMD5::class) {
sourceFile.set(file)
md5File.set(destinationDirectory.file("${file.name}.md5"))
}
}
}
}
val createMd5 by tasks.registering(CreateMD5::class) {
group = "md5"
codecClasspath.from(configurations.runtimeClasspath)
destinationDirectory.set(temporaryDir)
source.from(
resources.text.fromString(
"""
blah
blah
some
file
""".trimIndent()
)
)
}
Running without debug
When I run ./gradlew createMd5, the task executes successfully.
Executing 'createMd5'...
> Task :createMd5
Generated MD5 for string12197505505076104021.txt: 7a55d3ab41f37979cd7cccc92b7fc8fa
BUILD SUCCESSFUL in 866ms
1 actionable task: 1 executed
Execution finished 'createMd5'.
Running with debug
I then try and enable debug mode:
#TaskAction
fun createHashes() {
val workQueue: WorkQueue = workerExecutor.processIsolation {
classpath.from(codecClasspath)
forkOptions {
maxHeapSize = "64m"
debug = true // enable debug
}
}
// ...
I put a breakpoint in DigestUtils.java
And I then run the task with the debug options enabled in Intellij
However, I get an error.
Executing 'createMd5'...
Starting Gradle Daemon...
Connected to the target VM, address: '127.0.0.1:59032', transport: 'socket'
Gradle Daemon started in 1 s 460 ms
ERROR: transport error 202: bind failed: Address already in use
ERROR: JDWP Transport dt_socket failed to initialize, TRANSPORT_INIT(510)
JDWP exit error AGENT_ERROR_TRANSPORT_INIT(197): No transports initialized [./src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c:735]
Could not write standard input to Gradle Worker Daemon 1.
java.io.IOException: Broken pipe
at java.base/java.io.FileOutputStream.writeBytes(Native Method)
at java.base/java.io.FileOutputStream.write(FileOutputStream.java:354)
at java.base/java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:81)
at java.base/java.io.BufferedOutputStream.flush(BufferedOutputStream.java:142)
at org.gradle.process.internal.streams.ExecOutputHandleRunner.forwardContent(ExecOutputHandleRunner.java:68)
at org.gradle.process.internal.streams.ExecOutputHandleRunner.run(ExecOutputHandleRunner.java:53)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:829)
> Task :createMd5 FAILED
1 actionable task: 1 executed
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':createMd5'.
> A failure occurred while executing Build_gradle$GenerateMD5
> Failed to run Gradle Worker Daemon
> Process 'Gradle Worker Daemon 1' finished with non-zero exit value 2
* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 6s
Disconnected from the target VM, address: '127.0.0.1:59032', transport: 'socket'
Execution finished 'createMd5'.
Attempts
I have tried killing the Gradle Daemon,
./gradlew --stop
but to no effect.
I have also tried killing the Gradle Daemon
pkill -f '.*GradleDaemon.*';
but this also did not work.

Please try attaching a remote debugger to the running gradlew command.
https://docs.gradle.org/current/userguide/troubleshooting.html#sec:troubleshooting_build_logic

Related

Could not find org.apache.jmeter:bom:5.4.1

I have a Jenkinsfile pipeline and in one of its stages I run some jmeter tests and generate the respective report.
This is my stage
stage('Run Non-Functional tests - Windows'){
when { expression { env.OS == 'BAT' }}
steps {
dir('') {
bat 'gradlew.bat jmReport'
}
}
}
and this is my build gradle
import de.qualersoft.jmeter.gradleplugin.task.*
dependencies {
jmeterPlugin("kg.apc:jmeter-plugins-casutg:2.10")
}
plugins {
id "de.qualersoft.jmeter" version "2.1.0"
}
tasks.register('jmRun',JMeterRunTask) {
jmxFile.set("TestPlan.jmx")
}
tasks.register("jmReport",JMeterReportTask) {
jmxFile.set("TestPlan.jmx")
dependsOn("jmRun")
deleteResults=true
}
When I try to run my pipeline it fails with the following error
Execution failed for task ':jmRun'.
> Could not resolve all dependencies for configuration ':jmeterPlugin'.
> Could not find org.apache.jmeter:bom:5.4.1.
Required by:
project :
> Could not find org.apache.jmeter:bom:5.4.1.
Required by:
project : > org.apache.jmeter:ApacheJMeter_core:5.4.1
project : > org.apache.jmeter:ApacheJMeter_core:5.4.1 > org.apache.jmeter:jorphan:5.4.1
Why does this happen? Is it some kind of bug with JMeter?
Take a look at JMeter BugĀ 64465 which contains the workaround.
Or just consider switching to JMeter Maven Plugin

How is it possible that Gradle task's `outputFiles` differ when run for the first time and when it has run once already?

When I run the below build.gradle.kts script, invoking target downloadAndUnzipFile for the first time, when I run with clean build directory, I get an error.
> Task :downloadZipFile
Download https://github.com/michel-kraemer/gradle-download-task/archive/1.0.zip
[...]
Execution failed for task ':downloadAndUnzipFile'.
> Cannot expand ZIP '/home/jdanek/repos/testing/gradle-infer-deps/build/downloads' as it is not a file.
If I rerun the same task immediately, I get success now
> Task :downloadZipFile
Download https://github.com/michel-kraemer/gradle-download-task/archive/1.0.zip
> Task :downloadAndUnzipFile
BUILD SUCCESSFUL in 1s
2 actionable tasks: 2 executed
1:16:14 PM: Task execution finished 'downloadAndUnzipFile'.
Is this expected, or is it a bug? If it is a bug, then where? In my script?
My build.gradle.kts looks like this
import de.undercouch.gradle.tasks.download.Download
group = "org.example"
version = "1.0-SNAPSHOT"
plugins {
id("de.undercouch.download").version("4.0.4")
}
tasks {
val downloadZipFile by registering(Download::class) {
val destDir = buildDir.resolve("downloads")
doFirst {
destDir.mkdirs()
}
src("https://github.com/michel-kraemer/gradle-download-task/archive/1.0.zip")
dest(destDir)
}
val downloadAndUnzipFile by registering(Copy::class) {
dependsOn(downloadZipFile)
from(downloadZipFile.get().outputFiles.map { zipTree(it) })
into(buildDir)
}
}

Gradle build for kotlin failing

I have a kotlin package for which I'm trying to write a gradle setup to automate building. The related repository can be found on github -> https://github.com/ishankhare07/kotlin-web-server/tree/feature/dynamic-routing
Currently running gradle build or gradle compileLKotlin fails with the following error:
e: java.lang.ArrayIndexOutOfBoundsException: 450
at org.jetbrains.org.objectweb.asm.ClassReader.readUnsignedShort(ClassReader.java:2464)
at org.jetbrains.org.objectweb.asm.ClassReader.readUTF8(ClassReader.java:2525)
at org.jetbrains.org.objectweb.asm.ClassReader.readModule(ClassReader.java:761)
at org.jetbrains.org.objectweb.asm.ClassReader.accept(ClassReader.java:646)
at org.jetbrains.org.objectweb.asm.ClassReader.accept(ClassReader.java:507)
at org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleInfo$Companion.read(JavaModuleInfo.kt:67)
at org.jetbrains.kotlin.cli.jvm.modules.CliJavaModuleFinder.findSystemModule(CliJavaModuleFinder.kt:44)
at org.jetbrains.kotlin.cli.jvm.modules.CliJavaModuleFinder.access$findSystemModule(CliJavaModuleFinder.kt:25)
at org.jetbrains.kotlin.cli.jvm.modules.CliJavaModuleFinder$systemModules$1.invoke(CliJavaModuleFinder.kt:37)
at org.jetbrains.kotlin.cli.jvm.modules.CliJavaModuleFinder$systemModules$1.invoke(CliJavaModuleFinder.kt:25)
at kotlin.sequences.TransformingSequence$iterator$1.next(Sequences.kt:149)
at kotlin.sequences.FilteringSequence$iterator$1.calcNext(Sequences.kt:109)
at kotlin.sequences.FilteringSequence$iterator$1.hasNext(Sequences.kt:133)
at kotlin.sequences.FlatteningSequence$iterator$1.ensureItemIterator(Sequences.kt:254)
at kotlin.sequences.FlatteningSequence$iterator$1.hasNext(Sequences.kt:241)
at kotlin.sequences.SequencesKt___SequencesKt.none(_Sequences.kt:1239)
at org.jetbrains.kotlin.cli.jvm.compiler.ClasspathRootsResolver.addModularRoots(ClasspathRootsResolver.kt:227)
at org.jetbrains.kotlin.cli.jvm.compiler.ClasspathRootsResolver.computeRoots(ClasspathRootsResolver.kt:124)
at org.jetbrains.kotlin.cli.jvm.compiler.ClasspathRootsResolver.convertClasspathRoots(ClasspathRootsResolver.kt:79)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment.<init>(KotlinCoreEnvironment.kt:230)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment.<init>(KotlinCoreEnvironment.kt:114)
at org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment$Companion.createForProduction(KotlinCoreEnvironment.kt:409)
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.createCoreEnvironment(K2JVMCompiler.kt:286)
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.createEnvironmentWithScriptingSupport(K2JVMCompiler.kt:276)
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:155)
at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:63)
at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.java:109)
at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.java:53)
at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:92)
at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:451)
at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:97)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileIncrementally(IncrementalCompilerRunner.kt:218)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.access$compileIncrementally(IncrementalCompilerRunner.kt:37)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner$compile$2.invoke(IncrementalCompilerRunner.kt:80)
at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:92)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.execIncrementalCompiler(CompileServiceImpl.kt:518)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.access$execIncrementalCompiler(CompileServiceImpl.kt:97)
at org.jetbrains.kotlin.daemon.CompileServiceImpl$compile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:400)
at org.jetbrains.kotlin.daemon.CompileServiceImpl$compile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:97)
at org.jetbrains.kotlin.daemon.CompileServiceImpl$doCompile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:895)
at org.jetbrains.kotlin.daemon.CompileServiceImpl$doCompile$$inlined$ifAlive$lambda$2.invoke(CompileServiceImpl.kt:97)
at org.jetbrains.kotlin.daemon.common.DummyProfiler.withMeasure(PerfUtils.kt:137)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.checkedCompile(CompileServiceImpl.kt:925)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.doCompile(CompileServiceImpl.kt:894)
at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:399)
at jdk.internal.reflect.GeneratedMethodAccessor23.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:359)
at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200)
at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196)
at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:562)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:796)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:677)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:676)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1135)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at java.base/java.lang.Thread.run(Thread.java:844)
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':compileKotlin'.
> Internal compiler error. See log for more details
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 1s
Below is my build.gradle file:
buildscript {
ext.kotlin_version = '1.2.21'
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
plugins {
id "org.jetbrains.kotlin.jvm" version "1.2.21"
id "com.jfrog.bintray" version "1.7.3"
id 'maven-publish'
}
repositories {
jcenter()
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib"
}
jar {
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
task sourcesJar(type: Jar, dependsOn: project.classes) {
from sourceSets.main.allSource
}
publishing {
publications {
publishToBintray(MavenPublication) {
artifact sourcesJar
groupId 'com.ishankhare.kotlin-server'
}
}
}
bintray {
user = 'ishankhare07'
key = '9b693a0c46f7021021a2422f3ea837f0ad8e3ea6'
publications = ['publishToBintray']
pkg {
version {
name = 'v0.0.1'
}
repo = 'server'
name = 'server'
licenses = ['MIT']
vcsUrl = 'https://github.com/ishankhare07/kotlin-web-server'
}
}
sourceSets {
main.kotlin.srcDirs += "./"
}
On running the build with --info flag I get the following output:
Initialized native services in: /Users/ishankhare/.gradle/native
The client will now receive all logging from the daemon (pid: 11054). The daemon log file: /Users/ishankhare/.gradle/daemon/4.10/daemon-11054.out.log
Starting 42nd build in daemon [uptime: 43 mins 31.646 secs, performance: 100%, no major garbage collections]
Using 4 worker leases.
Starting Build
Settings evaluated using settings file '/Users/ishankhare/code/ishan/kotlin-web-server/server/settings.gradle'.
Projects loaded. Root project using build file '/Users/ishankhare/code/ishan/kotlin-web-server/server/build.gradle'.
Included projects: [root project 'server']
> Configure project :
Evaluating root project 'server' using build file '/Users/ishankhare/code/ishan/kotlin-web-server/server/build.gradle'.
All projects evaluated.
Selected primary task 'compileKotlin' from project :
Tasks to be executed: [task ':compileKotlin']
:compileKotlin (Thread[Task worker for ':',5,main]) started.
e: java.lang.ArrayIndexOutOfBoundsException
> Task :compileKotlin FAILED
file or directory '/Users/ishankhare/code/ishan/kotlin-web-server/server/src/main/kotlin', not found
file or directory '/Users/ishankhare/code/ishan/kotlin-web-server/server/src/main/java', not found
Task ':compileKotlin' is not up-to-date because:
Task has failed previously.
All input files are considered out-of-date for incremental task ':compileKotlin'.
file or directory '/Users/ishankhare/code/ishan/kotlin-web-server/server/src/main/kotlin', not found
file or directory '/Users/ishankhare/code/ishan/kotlin-web-server/server/src/main/java', not found
file or directory '/Users/ishankhare/code/ishan/kotlin-web-server/server/src/main/kotlin', not found
file or directory '/Users/ishankhare/code/ishan/kotlin-web-server/server/src/main/java', not found
Using Kotlin incremental compilation
Options for KOTLIN DAEMON: IncrementalCompilationOptions(super=CompilationOptions(compilerMode=INCREMENTAL_COMPILER, targetPlatform=JVM, reportCategories=[0], reportSeverity=2, requestedCompilationResults=[0]), areFileChangesKnown=false, modifiedFiles=null, deletedFiles=null, workingDir=/Users/ishankhare/code/ishan/kotlin-web-server/server/build/kotlin/compileKotlin, customCacheVersionFileName='gradle-format-version.txt', customCacheVersion=4, resultDifferenceFile=/Users/ishankhare/code/ishan/kotlin-web-server/server/build/kotlin/compileKotlin/build-history.bin, friendDifferenceFile=null, usePreciseJavaTracking=false)
[KOTLIN] deleting /Users/ishankhare/code/ishan/kotlin-web-server/server/build/classes/kotlin/main on error
[KOTLIN] deleting /Users/ishankhare/code/ishan/kotlin-web-server/server/build/classes/kotlin/main on error
:compileKotlin (Thread[Task worker for ':',5,main]) completed. Took 0.087 secs.
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':compileKotlin'.
> Internal compiler error. See log for more details
* Try:
Run with --stacktrace option to get the stack trace. Run with --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
Deprecated Gradle features were used in this build, making it incompatible with Gradle 5.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/4.10/userguide/command_line_interface.html#sec:command_line_warnings
BUILD FAILED in 0s
1 actionable task: 1 executed
with arrayindexoutofboundsexception at: it basically seems like its looking for stuff and not finding it therefore it is failing my suggestion would be to update and switch the buildscript ext.kotlin_version = '1.2.21' to 1.2.61 this will most likely solve the issues for the stuff that its looking for and not finding

How to re-run failed TestNG tests using Gradle

I know what TestNG generates testng-failed.xml with information about failed test.
I'd like to use it in Gradle to created new task for running failed tests:
task secondTry(type: Test) {
onlyIf {
file("build/reports/tests/test/testng-failed.xml").exists()
}
println file("build/reports/tests/test/testng-failed.xml").exists()
testClassesDir = sourceSets.test.output.classesDir
classpath = sourceSets.test.runtimeClasspath
useTestNG() {
suites("build/reports/tests/test/testng-failed.xml")
}
}
Aftrer running task secondTry I got true for println file("build/reports/tests/test/testng-failed.xml").exists(), but failed tests are not run and task is skipped: secondTry SKIPPED
Does anyone experience in such cases, how to make tests run?
UPDATE:
I've tried to modify task a bit, so just run testng-failed.xml:
task secondTry(type: Test) {
useTestNG() {
useDefaultListeners = true
reports.html.enabled = false
options.suites("build/reports/tests/test/testng-failed.xml")
}
}
As result, build is successfully executed, including secondTry task, but failed tests still are not run.
This can be achieved by a TestNG's feature called RetryAnalyzer. With few little tweaks, we can tell TestNG that how many times a test should get retried until it gets passed and what kind of exceptions/errors would trigger the retrying of the failed test methods.
The idiomatic way of doing this in TestNG is to implement the retry method in IRetryAnalyzer interface and then annotate the required test methods or class that you expect flaky tests to be in. TestNG will automatically run them again as part of your test suite. You can refer to the TestNG docs for this.
Here is a working example of this in Kotlin language, Here the failed test methods would be run again until they meet the specified criteria.
RerunTests.kt
import framework.core.retry.FailureRunner
import org.testng.Assert
import org.testng.annotations.Test
#Test(groups = ["rerun"], retryAnalyzer = FailureRunner::class)
class RerunTests {
fun foobar() {
Assert.assertFalse(true)
}
fun foo() {
Assert.assertEquals(2, 2)
}
}
And here is a sample implementation of a class that implements the required interface
FailureRunner.kt
import org.testng.IRetryAnalyzer
import org.testng.ITestResult
import org.testng.Reporter
class FailureRunner : IRetryAnalyzer {
private var retryCounter = 0
private var maxRetryCount = System.getProperty("maxFailureRetries").toInt()
override fun retry(result: ITestResult?): Boolean {
val testName = result?.testName
return if (retryCounter < maxRetryCount) {
Reporter.log("Current retry count <$retryCounter> is less than the max no of failure retries <$maxRetryCount>")
Reporter.log("Retrying $testName")
++retryCounter
true
} else {
Reporter.log("Retry count exceeded max limit for $testName.")
false
}
}
}
The Test Retry Gradle plugin is designed to retry failed tests, and works with TestNG, JUnit 4 & 5, and Spock. It will rerun each failed test a certain number of times, with the option of failing the build if too many failures have occurred overall.
plugins {
id 'org.gradle.test-retry' version '1.2.1'
}
test {
retry {
maxRetries = 3
maxFailures = 20 // Optional attribute
}
}

Gradle: cannot execute sql, driver not found

I have got the following gradle script. It results in No suitable driver found error which I found strange.
buildscript {
repositories{
maven {
url = 'http://localhost:8090/nexus/content/groups/public/'
}
}
dependencies {
classpath 'com.oracle:ojdbc6:11.2.0.4.0'
}
}
task sql << {
def url = 'jdbc:oracle:thin:#' + project.properties['db_hostname'] + ':' + project.properties['db_port'] + ':' + project.properties['db_sid']
println 'sql, db url:' + url
def driverName = 'oracle.jdbc.OracleDriver'
Class.forName(driverName).newInstance();
groovy.sql.Sql sql = groovy.sql.Sql.newInstance(
url,
project.properties['db_username'],
project.properties['db_password'],
driverName
)
}
The error is:
Tasks to be executed: [task ':sql']
:sql (Thread[main,5,main]) started.
:sql
Executing task ':sql' (up-to-date check took 0.0 secs) due to:
Task has not declared any outputs.
truncating, db url:jdbc:oracle:thin:#LOCALHOST:1521:orcl
:sql FAILED
:sql (Thread[main,5,main]) completed. Took 0.105 secs.
FAILURE: Build failed with an exception.
* Where:
Build file '/home/fran/projects/jua/build.gradle' line: 49
* What went wrong:
Execution failed for task ':sql'.
> No suitable driver found for jdbc:oracle:thin:#LOCALHOST:1521:orcl
* Try:
Run with --debug option to get more log output.
The driver jar is being loaded in a different classloader context than the Sql class. To fix it, try adding this:
// Add jars resolved by buildscript classpath configuration to the classloader which Sql will use
URLClassLoader loader = groovy.sql.Sql.class.classLoader
project.buildscript.configurations.classpath.each { File file ->
loader.addURL(file.toURL())
}
prior to the call to Sql.newInstance(). It will make all your classpath dependencies available to the Groovy classloader which loads the Sql class. The Class.forName() should not be neccesary.
See the discussion here for more information:
http://gradle.1045684.n5.nabble.com/using-jdbc-driver-in-a-task-fails-td1435189.html
For me that didn't work (Gradle 2.12).
But instead of performing:
Class.forName("org.h2.Driver")
I did:
groovy.sql.loadDriver("org.h2.Driver")
The Groovy Sql.loadDriver method does some nifty classloader stuff.
You should use something like this:
configurations {
db2database
}
buildscript {
dependencies {
classpath('com.ibm.db2:db2jcc4:10.5.5')//db2 driver for gradle task
}
}
dependencies {
db2database "com.ibm.db2:db2jcc4:10.5.5" //db2 driver for configuration
}
//load drivers for gradle tasks
configurations.db2database.each {
GroovyObject.class.classLoader.addURL(it.toURI().toURL())
}
....
Sql sql = Sql.newInstance(
envProps.getProperty('dbUri'),
envProps.getProperty('dbUsername'),
envProps.getProperty('dbPassword'),
envProps.getProperty('dbDriverClassName')
)
println sql.rows("SELECT * FROM TEST.TEST")

Resources