diff --git a/buildSrc/src/main/groovy/net/corda/testing/DistributedTesting.groovy b/buildSrc/src/main/groovy/net/corda/testing/DistributedTesting.groovy index c6dfc2d5a2..4bff02cf2d 100644 --- a/buildSrc/src/main/groovy/net/corda/testing/DistributedTesting.groovy +++ b/buildSrc/src/main/groovy/net/corda/testing/DistributedTesting.groovy @@ -10,7 +10,6 @@ import org.gradle.api.tasks.testing.Test */ class DistributedTesting implements Plugin { - static def getPropertyAsInt(Project proj, String property, Integer defaultValue) { return proj.hasProperty(property) ? Integer.parseInt(proj.property(property).toString()) : defaultValue } @@ -33,6 +32,7 @@ class DistributedTesting implements Plugin { //1. add the task to determine all tests within the module //2. modify the underlying testing task to use the output of the listing task to include a subset of tests for each fork //3. KubesTest will invoke these test tasks in a parallel fashion on a remote k8s cluster + //4. after each completed test write its name to a file to keep track of what finished for restart purposes project.subprojects { Project subProject -> subProject.tasks.withType(Test) { Test task -> println "Evaluating ${task.getPath()}" @@ -47,7 +47,6 @@ class DistributedTesting implements Plugin { if (!task.hasProperty("ignoreForDistribution")) { KubesTest parallelTestTask = generateParallelTestingTask(subProject, task, imageBuildingTask, providedTag) } - } } @@ -129,6 +128,20 @@ class DistributedTesting implements Plugin { maxHeapSize = "6g" doFirst { filter { + List executedTests = [] + File executedTestsFile = new File(KubesTest.TEST_RUN_DIR + "/executedTests.txt") + try { + executedTests = executedTestsFile.readLines() + } catch (FileNotFoundException e) { + executedTestsFile.createNewFile() + } + + task.afterTest { desc, result -> + executedTestsFile.withWriterAppend { writer -> + writer.writeLine(desc.getClassName() + "." + desc.getName()) + } + } + def fork = getPropertyAsInt(subProject, "dockerFork", 0) subProject.logger.info("requesting tests to include in testing task ${task.getPath()} (idx: ${fork})") List includes = globalAllocator.getTestIncludesForForkAndTestTask( @@ -141,10 +154,18 @@ class DistributedTesting implements Plugin { excludeTestsMatching "*" } + includes.removeAll(executedTests) + + executedTests.forEach { exclude -> + subProject.logger.info "excluding: $exclude for testing task ${task.getPath()}" + excludeTestsMatching exclude + } + includes.forEach { include -> subProject.logger.info "including: $include for testing task ${task.getPath()}" includeTestsMatching include } + failOnNoMatchingTests false } } diff --git a/buildSrc/src/main/groovy/net/corda/testing/KubesTest.java b/buildSrc/src/main/groovy/net/corda/testing/KubesTest.java index a041b38ccc..60f2aa353f 100644 --- a/buildSrc/src/main/groovy/net/corda/testing/KubesTest.java +++ b/buildSrc/src/main/groovy/net/corda/testing/KubesTest.java @@ -22,6 +22,7 @@ import java.util.stream.IntStream; public class KubesTest extends DefaultTask { + static final String TEST_RUN_DIR = "/test-runs"; private static final ExecutorService executorService = Executors.newCachedThreadPool(); /** * Name of the k8s Secret object that holds the credentials to access the docker image registry @@ -247,7 +248,7 @@ public class KubesTest extends DefaultTask { .addToRequests("memory", new Quantity(memoryGbPerFork.toString() + "Gi")) .endResources() .addNewVolumeMount().withName("gradlecache").withMountPath("/tmp/gradle").endVolumeMount() - .addNewVolumeMount().withName("testruns").withMountPath("/test-runs").endVolumeMount() + .addNewVolumeMount().withName("testruns").withMountPath(TEST_RUN_DIR).endVolumeMount() .endContainer() .addNewImagePullSecret(REGISTRY_CREDENTIALS_SECRET_NAME)