Skip to content

Commit

Permalink
GEODE-3071: Provide capability to parallelize distributedTests
Browse files Browse the repository at this point in the history
Herewith the ability to leverage Gradle's parallel test execution
capability to run dunits in parallel. This is combined with launching
tests in Docker containers to provide process, network and filesystem
isolation. Depending on the size of your system, this can speed up
running the distributedTest task 2-5 times.

The capability is enabled by launching gradle with '-PparallelDunit'

Tunables, enabled as gradle parametrs (-P option) are:

- dunitDockerImage: The docker image which will be used to launch
  tests. The image must have the JAVA_HOME environment variable set. The
  image must be pulled locally before starting the tests.
- dunitParallelForks: The number of parallel docker containers to be
  launched.
- dunitDockerUser: The docker user which will run the tests. Because of
  the way that the containers map the build directory into them, the
  test artifacts, will be written with this user id. By default this is
  'root'.
  • Loading branch information
jdeppe-pivotal committed Jun 14, 2017
1 parent a4d790c commit 588c3ed
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 0 deletions.
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ buildscript {
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.0.1'
classpath "com.diffplug.gradle.spotless:spotless:2.2.0"
classpath "me.champeau.gradle:jmh-gradle-plugin:0.3.1"
classpath "com.pedjak.gradle.plugins:dockerized-test:0.4.2"
}
}

Expand Down Expand Up @@ -82,6 +83,7 @@ apply from: "${scriptDir}/code-analysis.gradle"
apply from: "${scriptDir}/sonar.gradle"
apply from: "${scriptDir}/ide.gradle"
apply from: "${scriptDir}/rat.gradle"
apply from: "${scriptDir}/docker.gradle"

subprojects {
// Make sure clean task for rootProject runs last
Expand Down
7 changes: 7 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,10 @@ buildRoot=

# We want signing to be on by default. Signing requires GPG to be set up.
nexusSignArchives = true

# Control how many concurrent dunit (using docker) tests will be run
dunitParallelForks = 8
# This is the name of the Docker image for running parallel dunits
dunitDockerImage = openjdk:8
# Docker user for parallel dunit tests
dunitDockerUser = root
83 changes: 83 additions & 0 deletions gradle/docker.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Configuration for running (dunit) tests in parallel in Docker containers.
* The container used must hava JAVA_HOME set in it's environment and must
* have 'java' defined on the path. For example, the relevant Dockerfile
* content could be:
*
* ENV JAVA_HOME=/opt/jdk1.8.0_u101
* ENV PATH=$PATH:$JAVA_HOME/bin
*
* In addition, the container must have docker installed.
*
* The plugin can be activated with the Gradle property 'parallelDunit'.
* Additional properties that can be set are:
*
* dunitDockerImage - The docker image used for running parallel dunits. The
* default image is 'openjdk:8'. The image is required to
* have 'JAVA_HOME' set as an environment variable.
* dunitParallelForks - The number of parallel containers that will be
* launched. The default is 8.
* dunitDockerUser - The user used within the docker container to run tests.
* The default is 'root'.
*/

def dockerConfig = {
maxParallelForks = dunitParallelForks.toInteger()

docker {
// base image for creating docker containers that execute the tests
image = dunitDockerImage

// volumes mounted to the containers
// in a form: host_dir : container_dir
def pwd = System.getenv('PWD')
def gradleHome = System.getenv('GRADLE_USER_HOME') ?: "${System.getenv('HOME')}/.gradle"
volumes = ["${gradleHome}":gradleHome]

volumes << ["${pwd}":pwd]

// specify the user for starting Gradle test worker within the container.
user = dunitDockerUser

argsInspect = { List args ->
def javaHomeIdx = 0
def i = args.iterator()
def j = 0
while (i.hasNext()) {
if (i.next() == '-e') {
def x = i.next()
j++
if (x.startsWith('JAVA_HOME')) {
javaHomeIdx = j
}
}
j++
}

// Remove JAVA_HOME env variable - it might not be the same as the container needs
if (javaHomeIdx > 0) {
args.removeAt(javaHomeIdx-1)
args.removeAt(javaHomeIdx-1)
}

// Infer the index of this invocation
def matcher = (args[args.size - 1] =~ /.*Executor (\d*).*/)

args[3] = args[3] + matcher[0][1]
def workdir = new File(args[3])
println "dockerize: making ${workdir}"
workdir.mkdirs()
// println args

args
}
}
}

subprojects {
apply plugin: 'com.github.pedjak.dockerized-test'

if (project.hasProperty('parallelDunit')) {
distributedTest.configure(dockerConfig)
}
}

0 comments on commit 588c3ed

Please sign in to comment.