Skip to content

Commit

Permalink
GEODE-8637: Give each test worker a unique working dir (apache#5649)
Browse files Browse the repository at this point in the history
* Give each test worker a unique working dir

Before running a test task, wrap its TestFramework in a wrapper that
creates a unique working dir for each new test worker.
  • Loading branch information
demery-pivotal authored Oct 27, 2020
1 parent 5312335 commit e65f579
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License. You may obtain a
* copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/

package org.apache.geode.gradle;

import static java.nio.file.StandardCopyOption.COPY_ATTRIBUTES;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.atomic.AtomicLong;

import org.gradle.api.Action;
import org.gradle.api.internal.tasks.testing.TestFramework;
import org.gradle.api.internal.tasks.testing.WorkerTestClassProcessorFactory;
import org.gradle.api.internal.tasks.testing.detection.TestFrameworkDetector;
import org.gradle.api.tasks.testing.TestFrameworkOptions;
import org.gradle.process.internal.JavaExecHandleBuilder;
import org.gradle.process.internal.worker.WorkerProcessBuilder;

/**
* Wraps a test framework to run each test worker in a separate working directory.
*/
public class RunInSubdirectoryTestFramework implements TestFramework {
private static final String GEMFIRE_PROPERTIES = "gemfire.properties";
private final AtomicLong workerId = new AtomicLong();
private final TestFramework delegate;

public RunInSubdirectoryTestFramework(TestFramework delegate) {
this.delegate = delegate;
}

@Override
public TestFrameworkDetector getDetector() {
return delegate.getDetector();
}

@Override
public TestFrameworkOptions getOptions() {
return delegate.getOptions();
}

@Override
public WorkerTestClassProcessorFactory getProcessorFactory() {
return delegate.getProcessorFactory();
}

/**
* Return an action that configures the test worker builder to run the test worker in a unique
* subdirectory of the task's working directory.
*/
@Override
public Action<WorkerProcessBuilder> getWorkerConfigurationAction() {
return workerProcessBuilder -> {
delegate.getWorkerConfigurationAction().execute(workerProcessBuilder);
JavaExecHandleBuilder javaCommand = workerProcessBuilder.getJavaCommand();

Path taskWorkingDir = javaCommand.getWorkingDir().toPath();
String workerWorkingDirName = String.format("test-worker-%06d", workerId.incrementAndGet());
Path workerWorkingDir = taskWorkingDir.resolve(workerWorkingDirName);

createWorkingDir(workerWorkingDir);
copyGemFirePropertiesFile(taskWorkingDir, workerWorkingDir);

javaCommand.setWorkingDir(workerWorkingDir);
};
}

private void copyGemFirePropertiesFile(Path taskWorkingDir, Path workerWorkingDir) {
Path taskPropertiesFile = taskWorkingDir.resolve(GEMFIRE_PROPERTIES);
if (!Files.exists(taskPropertiesFile)) {
return;
}
Path workerPropertiesFile = workerWorkingDir.resolve(taskPropertiesFile.getFileName());
try {
Files.copy(taskPropertiesFile, workerPropertiesFile, COPY_ATTRIBUTES);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}

private void createWorkingDir(Path workerWorkingDir) {
try {
Files.createDirectories(workerWorkingDir);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ public abstract class AbstractSessionsTest {

// Set up the servers we need
protected static void setupServer(final DeltaSessionManager manager) throws Exception {
FileUtils.copyDirectory(Paths.get("..", "resources", "integrationTest", "tomcat").toFile(),
FileUtils.copyDirectory(
Paths.get("..", "..", "resources", "integrationTest", "tomcat").toFile(),
new File("./tomcat"));
port = SocketUtils.findAvailableTcpPort();
server = new EmbeddedTomcat(port, "JVM-1");
Expand Down
12 changes: 12 additions & 0 deletions gradle/test.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import org.apache.geode.gradle.TestPropertiesWriter
import org.apache.geode.gradle.RepeatTest
import org.apache.geode.gradle.plugins.DependencyConstraints
import org.apache.geode.gradle.RunInSubdirectoryTestFramework

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
Expand Down Expand Up @@ -161,6 +162,17 @@ configure([integrationTest, distributedTest, performanceTest, acceptanceTest, ui
}
}

configure([acceptanceTest, distributedTest, integrationTest, uiTest, upgradeTest, repeatAcceptanceTest, repeatDistributedTest, repeatIntegrationTest, repeatUnitTest, repeatUpgradeTest]) {
doFirst {
// Wrap the task's test framework in a wrapper that runs each test worker JVM in a unique
// subdirectory.
def subdirFramework = new RunInSubdirectoryTestFramework(testFramework)
// This call works for now, but the Test class declares useTestFramework() as protected, so
// this could become troublesome in a future version of Gradle/Groovy.
useTestFramework subdirFramework
}
}

configure([repeatDistributedTest, repeatIntegrationTest, repeatUpgradeTest, repeatUnitTest, repeatAcceptanceTest]) {
times = Integer.parseInt(repeat)
useJUnit {}
Expand Down

0 comments on commit e65f579

Please sign in to comment.