upthewaterspout closed pull request #2: Cleaning up benchmark output URL: https://github.com/apache/geode-benchmarks/pull/2
This is a PR merged from a forked repository. As GitHub hides the original diff on merge, it is displayed below for the sake of provenance: As this is a foreign pull request (from a fork), the diff is supplied below (as it won't show otherwise due to GitHub magic): diff --git a/README.md b/README.md index 06833b2..7c563ed 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,9 @@ To run all benchmarks, run the benchmark task and pass in a list of hosts. For example: ``` -./gradlew benchmark -Phosts=localhost,localhost,localhost +./gradlew benchmark -Phosts=localhost,localhost,localhost -PoutputDir=/tmp/results ``` -Performance results will be written to geode-benchmarks/output - ## Project structure The project is divided into two modules diff --git a/geode-benchmarks/build.gradle b/geode-benchmarks/build.gradle index 67b6a8c..9b90312 100644 --- a/geode-benchmarks/build.gradle +++ b/geode-benchmarks/build.gradle @@ -43,7 +43,10 @@ task benchmark(type: Test) { exceptionFormat = 'full' } + def outputDir = project.hasProperty('outputDir') ? project.findProperty('outputDir') : new File(project.buildDir, "benchmarks").getAbsolutePath(); + systemProperty 'TEST_HOSTS', project.findProperty('hosts'); + systemProperty 'OUTPUT_DIR', outputDir; doFirst { if(!project.hasProperty('hosts')) { diff --git a/geode-benchmarks/src/main/java/org/apache/geode/benchmark/tasks/GetTask.java b/geode-benchmarks/src/main/java/org/apache/geode/benchmark/tasks/GetTask.java new file mode 100644 index 0000000..0f94741 --- /dev/null +++ b/geode-benchmarks/src/main/java/org/apache/geode/benchmark/tasks/GetTask.java @@ -0,0 +1,46 @@ +/* + * 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.benchmark.tasks; + +import java.io.Serializable; +import java.util.Map; + +import org.yardstickframework.BenchmarkConfiguration; +import org.yardstickframework.BenchmarkDriverAdapter; + +import org.apache.geode.cache.Region; +import org.apache.geode.cache.client.ClientCache; +import org.apache.geode.cache.client.ClientCacheFactory; + +public class GetTask extends BenchmarkDriverAdapter implements Serializable { + + private Region<Object, Object> region; + + @Override + public void setUp(BenchmarkConfiguration cfg) throws Exception { + super.setUp(cfg); + ClientCache cache = ClientCacheFactory.getAnyInstance(); + region = cache.getRegion("region"); + } + + @Override + public boolean test(Map<Object, Object> ctx) throws Exception { + region.get(1); + return true; + } +} diff --git a/geode-benchmarks/src/main/java/org/apache/geode/benchmark/tasks/StartClient.java b/geode-benchmarks/src/main/java/org/apache/geode/benchmark/tasks/StartClient.java index dab4d8f..f69c284 100644 --- a/geode-benchmarks/src/main/java/org/apache/geode/benchmark/tasks/StartClient.java +++ b/geode-benchmarks/src/main/java/org/apache/geode/benchmark/tasks/StartClient.java @@ -17,6 +17,7 @@ package org.apache.geode.benchmark.tasks; +import java.io.File; import java.net.InetAddress; import org.apache.geode.cache.client.ClientCache; @@ -38,10 +39,12 @@ public void run(TestContext context) throws Exception { InetAddress locator = context.getHostsForRole("locator").iterator().next(); + String statsFile = new File(context.getOutputDir(), "stats.gfs").getAbsolutePath(); + ClientCache clientCache = new ClientCacheFactory() .addPoolLocator(locator.getHostAddress(), locatorPort) .set(ConfigurationProperties.STATISTIC_SAMPLING_ENABLED,"true") - .set(ConfigurationProperties.STATISTIC_ARCHIVE_FILE,"output/stats.gfs") + .set(ConfigurationProperties.STATISTIC_ARCHIVE_FILE, statsFile) .create(); clientCache.createClientRegionFactory(ClientRegionShortcut.PROXY) diff --git a/geode-benchmarks/src/main/java/org/apache/geode/benchmark/tasks/StartLocator.java b/geode-benchmarks/src/main/java/org/apache/geode/benchmark/tasks/StartLocator.java index f04b3e0..5bc6d39 100644 --- a/geode-benchmarks/src/main/java/org/apache/geode/benchmark/tasks/StartLocator.java +++ b/geode-benchmarks/src/main/java/org/apache/geode/benchmark/tasks/StartLocator.java @@ -17,6 +17,7 @@ package org.apache.geode.benchmark.tasks; +import java.io.File; import java.net.InetAddress; import java.util.Properties; @@ -35,9 +36,12 @@ public StartLocator(int locatorPort) { @Override public void run(TestContext context) throws Exception { Properties properties = new Properties(); - properties.setProperty(ConfigurationProperties.NAME,"locator-"+ InetAddress.getLocalHost()); + + String statsFile = new File(context.getOutputDir(), "stats.gfs").getAbsolutePath(); properties.setProperty(ConfigurationProperties.STATISTIC_SAMPLING_ENABLED,"true"); - properties.setProperty(ConfigurationProperties.STATISTIC_ARCHIVE_FILE,"output/stats.gfs"); + properties.setProperty(ConfigurationProperties.STATISTIC_ARCHIVE_FILE, statsFile); + + properties.setProperty(ConfigurationProperties.NAME,"locator-"+ InetAddress.getLocalHost()); Locator.startLocatorAndDS(locatorPort, null, properties); } } diff --git a/geode-benchmarks/src/main/java/org/apache/geode/benchmark/tasks/StartServer.java b/geode-benchmarks/src/main/java/org/apache/geode/benchmark/tasks/StartServer.java index d2bb8aa..46f9445 100644 --- a/geode-benchmarks/src/main/java/org/apache/geode/benchmark/tasks/StartServer.java +++ b/geode-benchmarks/src/main/java/org/apache/geode/benchmark/tasks/StartServer.java @@ -17,6 +17,7 @@ package org.apache.geode.benchmark.tasks; +import java.io.File; import java.net.InetAddress; import org.apache.geode.cache.Cache; @@ -39,12 +40,13 @@ public StartServer(int locatorPort) { public void run(TestContext context) throws Exception { String locatorString = LocatorUtil.getLocatorString(context, locatorPort); + String statsFile = new File(context.getOutputDir(), "stats.gfs").getAbsolutePath(); Cache cache = new CacheFactory() .set(ConfigurationProperties.LOCATORS,locatorString) .set(ConfigurationProperties.NAME,"server-"+ InetAddress.getLocalHost()) .set(ConfigurationProperties.STATISTIC_SAMPLING_ENABLED,"true") - .set(ConfigurationProperties.STATISTIC_ARCHIVE_FILE,"output/stats.gfs") + .set(ConfigurationProperties.STATISTIC_ARCHIVE_FILE, statsFile) .create(); CacheServer cacheServer = ((Cache) cache).addCacheServer(); diff --git a/geode-benchmarks/src/main/java/org/apache/geode/benchmark/tests/PartitionedGetBenchmark.java b/geode-benchmarks/src/main/java/org/apache/geode/benchmark/tests/PartitionedGetBenchmark.java new file mode 100644 index 0000000..a5ceeb7 --- /dev/null +++ b/geode-benchmarks/src/main/java/org/apache/geode/benchmark/tests/PartitionedGetBenchmark.java @@ -0,0 +1,57 @@ +/* + * 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.benchmark.tests; + +import org.junit.Test; + +import org.apache.geode.benchmark.tasks.GetTask; +import org.apache.geode.benchmark.tasks.StartClient; +import org.apache.geode.benchmark.tasks.StartLocator; +import org.apache.geode.benchmark.tasks.StartServer; +import org.apache.geode.perftest.TestConfig; +import org.apache.geode.perftest.TestRunners; + +/** + * Benchmark of gets on a partitioned region. + * + * TODO - this is not populating the region! + * TODO - this is only getting a single key! + */ +public class PartitionedGetBenchmark { + + @Test + public void run() throws Exception { + TestRunners.defaultRunner().runTest(this::configure); + } + + public void configure(TestConfig config) { + + int locatorPort = 10334; + + config.name(PartitionedGetBenchmark.class.getCanonicalName()); + config.warmupSeconds(2); + config.durationSeconds(5); + config.role("locator", 1); + config.role("server", 1); + config.role("client", 1); + config.before(new StartLocator(locatorPort), "locator"); + config.before(new StartServer(locatorPort), "server"); + config.before(new StartClient(locatorPort), "client"); + config.workload(new GetTask(),"client"); + } +} diff --git a/geode-benchmarks/src/main/java/org/apache/geode/benchmark/tests/PartitionedPutBenchmark.java b/geode-benchmarks/src/main/java/org/apache/geode/benchmark/tests/PartitionedPutBenchmark.java index cd13c33..6689911 100644 --- a/geode-benchmarks/src/main/java/org/apache/geode/benchmark/tests/PartitionedPutBenchmark.java +++ b/geode-benchmarks/src/main/java/org/apache/geode/benchmark/tests/PartitionedPutBenchmark.java @@ -37,8 +37,9 @@ public void configure(TestConfig config) { int locatorPort = 10334; - config.warmupSeconds(5); - config.durationSeconds(30); + config.name(PartitionedPutBenchmark.class.getCanonicalName()); + config.warmupSeconds(2); + config.durationSeconds(5); config.role("locator", 1); config.role("server", 1); config.role("client", 1); diff --git a/geode-benchmarks/src/test/java/org/apache/geode/benchmark/PartitionedPutBenchmarkTest.java b/geode-benchmarks/src/test/java/org/apache/geode/benchmark/PartitionedPutBenchmarkTest.java index 377c464..4822dab 100644 --- a/geode-benchmarks/src/test/java/org/apache/geode/benchmark/PartitionedPutBenchmarkTest.java +++ b/geode-benchmarks/src/test/java/org/apache/geode/benchmark/PartitionedPutBenchmarkTest.java @@ -17,20 +17,23 @@ package org.apache.geode.benchmark; +import java.io.File; + +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; -import org.apache.geode.benchmark.tasks.PutTask; -import org.apache.geode.benchmark.tasks.StartClient; -import org.apache.geode.benchmark.tasks.StartLocator; -import org.apache.geode.benchmark.tasks.StartServer; import org.apache.geode.benchmark.tests.PartitionedPutBenchmark; -import org.apache.geode.perftest.TestConfig; import org.apache.geode.perftest.TestRunners; public class PartitionedPutBenchmarkTest { + @Rule + public TemporaryFolder folder = new TemporaryFolder(); + @Test public void benchmarkRunsSuccessfully() throws Exception { - TestRunners.minimalRunner().runTest(new PartitionedPutBenchmark()::configure); + TestRunners.minimalRunner(folder.newFolder()) + .runTest(new PartitionedPutBenchmark()::configure); } } diff --git a/harness/src/main/java/org/apache/geode/perftest/TestConfig.java b/harness/src/main/java/org/apache/geode/perftest/TestConfig.java index 985ad1e..1d5a6f6 100644 --- a/harness/src/main/java/org/apache/geode/perftest/TestConfig.java +++ b/harness/src/main/java/org/apache/geode/perftest/TestConfig.java @@ -39,6 +39,7 @@ private List<TestStep> before = new ArrayList<>(); private List<TestStep> workload = new ArrayList<>(); private List<TestStep> after = new ArrayList<>(); + private String name; /** * Define a role for the test. @@ -108,6 +109,14 @@ public void warmupSeconds(long warmupSeconds) { workloadConfig.warmupSeconds(warmupSeconds); } + /** + * Set the name of this benchmark. This name must be unique within a benchmarking run. Comparisons + * between runs will use this name to identify the same benchmark in both runs. + */ + public void name(String name) { + this.name = name; + } + public long getDurationSeconds() { return workloadConfig.getDurationSeconds(); } @@ -132,6 +141,10 @@ public long getWarmupSeconds() { return after; } + public String getName() { + return name; + } + /** * Return the total number of JVMs required to run this test * @return diff --git a/harness/src/main/java/org/apache/geode/perftest/TestContext.java b/harness/src/main/java/org/apache/geode/perftest/TestContext.java index 9a4425c..589900f 100644 --- a/harness/src/main/java/org/apache/geode/perftest/TestContext.java +++ b/harness/src/main/java/org/apache/geode/perftest/TestContext.java @@ -17,10 +17,13 @@ package org.apache.geode.perftest; +import java.io.File; import java.io.Serializable; import java.net.InetAddress; import java.util.Set; public interface TestContext extends Serializable { Set<InetAddress> getHostsForRole(String role); + + File getOutputDir(); } diff --git a/harness/src/main/java/org/apache/geode/perftest/TestRunners.java b/harness/src/main/java/org/apache/geode/perftest/TestRunners.java index fc6282a..685aafb 100644 --- a/harness/src/main/java/org/apache/geode/perftest/TestRunners.java +++ b/harness/src/main/java/org/apache/geode/perftest/TestRunners.java @@ -17,7 +17,8 @@ package org.apache.geode.perftest; -import org.apache.geode.perftest.infrastructure.InfrastructureFactory; +import java.io.File; + import org.apache.geode.perftest.infrastructure.local.LocalInfrastructureFactory; import org.apache.geode.perftest.infrastructure.ssh.SshInfrastructureFactory; import org.apache.geode.perftest.jvms.RemoteJVMFactory; @@ -37,10 +38,12 @@ public class TestRunners { public static final String TEST_HOSTS = "TEST_HOSTS"; + public static final String OUTPUT_DIR = "OUTPUT_DIR"; - public static TestRunner defaultRunner(String username, String ... hosts) { - return new DefaultTestRunner(new SshInfrastructureFactory(username, hosts), new RemoteJVMFactory()); + public static TestRunner defaultRunner(String username, File outputDir, String ... hosts) { + return new DefaultTestRunner(new RemoteJVMFactory(new SshInfrastructureFactory(username, hosts)), + outputDir); } /** * The default runner, which gets a list of hosts to run on from the @@ -49,25 +52,27 @@ public static TestRunner defaultRunner(String username, String ... hosts) { */ public static TestRunner defaultRunner() { String testHosts = System.getProperty(TEST_HOSTS); + String outputDir = System.getProperty(OUTPUT_DIR, "output"); - return defaultRunner(testHosts); + return defaultRunner(testHosts, new File(outputDir)); } - static TestRunner defaultRunner(String testHosts) { + static TestRunner defaultRunner(String testHosts, File outputDir) { if(testHosts == null) { throw new IllegalStateException("You must set the TEST_HOSTS system property to a comma separated list of hosts to run the benchmarks on."); } String userName = System.getProperty("user.name"); - return defaultRunner(userName, testHosts.split(",\\s*")); + return defaultRunner(userName, outputDir, testHosts.split(",\\s*")); } /** * A test runner that runs the test with the minimal tuning - only * 1 second duration on local infrastructure. + * @param outputDir */ - public static TestRunner minimalRunner() { - return new DefaultTestRunner(new LocalInfrastructureFactory(), new RemoteJVMFactory()) { + public static TestRunner minimalRunner(final File outputDir) { + return new DefaultTestRunner(new RemoteJVMFactory(new LocalInfrastructureFactory()), outputDir) { @Override public void runTest(TestConfig config) throws Exception { config.warmupSeconds(0); diff --git a/harness/src/main/java/org/apache/geode/perftest/infrastructure/Infrastructure.java b/harness/src/main/java/org/apache/geode/perftest/infrastructure/Infrastructure.java index f779acb..cb66845 100644 --- a/harness/src/main/java/org/apache/geode/perftest/infrastructure/Infrastructure.java +++ b/harness/src/main/java/org/apache/geode/perftest/infrastructure/Infrastructure.java @@ -43,9 +43,14 @@ int onNode(Node node, String[] shellCommand) void close() throws InterruptedException, IOException; /** - * Copy a list of files to a directory on the node + * Copy a list of files to a directory on the node. + * + * @param files A list of files on the local system to copy + * @param destDir The directory on the remote machine to copy to + * @param removeExisting If true, remove all existing files in the directory on the remote + * machine */ - void copyToNodes(Iterable<File> files, String destDir) throws IOException; + void copyToNodes(Iterable<File> files, String destDir, boolean removeExisting) throws IOException; void copyFromNode(Node node, String directory, File destDir) throws IOException; diff --git a/harness/src/main/java/org/apache/geode/perftest/infrastructure/local/LocalInfrastructure.java b/harness/src/main/java/org/apache/geode/perftest/infrastructure/local/LocalInfrastructure.java index f902a72..5b90fa4 100644 --- a/harness/src/main/java/org/apache/geode/perftest/infrastructure/local/LocalInfrastructure.java +++ b/harness/src/main/java/org/apache/geode/perftest/infrastructure/local/LocalInfrastructure.java @@ -24,9 +24,9 @@ import java.net.UnknownHostException; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; -import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @@ -85,10 +85,10 @@ public void close() throws InterruptedException, IOException { } @Override - public void copyToNodes(Iterable<File> files, String destDirName) throws IOException { + public void copyToNodes(Iterable<File> files, String destDirName, boolean removeExisting) throws IOException { for(LocalNode node : nodes) { Path destDir = new File(node.getWorkingDir(), destDirName).toPath(); - destDir.toFile().mkdir(); + destDir.toFile().mkdirs(); for(File file : files) { Files.copy(file.toPath(), destDir.resolve(file.getName())); diff --git a/harness/src/main/java/org/apache/geode/perftest/infrastructure/ssh/SshInfrastructure.java b/harness/src/main/java/org/apache/geode/perftest/infrastructure/ssh/SshInfrastructure.java index 33f2ed3..4ff90e4 100644 --- a/harness/src/main/java/org/apache/geode/perftest/infrastructure/ssh/SshInfrastructure.java +++ b/harness/src/main/java/org/apache/geode/perftest/infrastructure/ssh/SshInfrastructure.java @@ -102,7 +102,7 @@ public void close() throws InterruptedException, IOException { } @Override - public void copyToNodes(Iterable<File> files, String destDir) throws IOException { + public void copyToNodes(Iterable<File> files, String destDir, boolean removeExisting) throws IOException { Set<InetAddress> uniqueNodes = getNodes().stream().map(Node::getAddress).collect(Collectors.toSet()); List<CompletableFuture<Void>> futures = new ArrayList<>(); @@ -112,9 +112,11 @@ public void copyToNodes(Iterable<File> files, String destDir) throws IOException try (Session session = client.startSession()) { client.useCompression(); - String script = "mkdir -p " + destDir; - final Session.Command cmd = session.exec(script); - cmd.join(); + if(removeExisting) { + session.exec(String.format("/bin/sh -c \"rm -rf '%s'; mkdir -p '%s'\"", destDir, destDir)).join(); + }else { + session.exec(String.format("mkdir -p '%s'", destDir)).join(); + } for (File file : files) { logger.info("Copying " + file + " to " + address); client.newSCPFileTransfer().upload(new FileSystemFile(file), destDir); diff --git a/harness/src/main/java/org/apache/geode/perftest/jdk/SystemInterface.java b/harness/src/main/java/org/apache/geode/perftest/jdk/SystemInterface.java index 91a18e8..7d25070 100644 --- a/harness/src/main/java/org/apache/geode/perftest/jdk/SystemInterface.java +++ b/harness/src/main/java/org/apache/geode/perftest/jdk/SystemInterface.java @@ -24,7 +24,7 @@ */ public class SystemInterface { - public static String getProperty(String property) { + public String getProperty(String property) { return System.getProperty(property); } diff --git a/harness/src/main/java/org/apache/geode/perftest/jvms/JVMLauncher.java b/harness/src/main/java/org/apache/geode/perftest/jvms/JVMLauncher.java index b6794ef..eb26879 100644 --- a/harness/src/main/java/org/apache/geode/perftest/jvms/JVMLauncher.java +++ b/harness/src/main/java/org/apache/geode/perftest/jvms/JVMLauncher.java @@ -32,20 +32,25 @@ class JVMLauncher { private static final Logger logger = LoggerFactory.getLogger(RemoteJVMFactory.class); + JVMLauncher() { + } + CompletableFuture<Void> launchProcesses(Infrastructure infra, int rmiPort, - List<JVMMapping> mapping) + List<JVMMapping> mapping, String libDir) throws UnknownHostException { List<CompletableFuture<Void>> futures = new ArrayList<CompletableFuture<Void>>(); for (JVMMapping entry : mapping) { - futures.add(launchWorker(infra, rmiPort, entry.getId(), entry.getNode())); + futures.add(launchWorker(infra, rmiPort, entry.getId(), entry.getNode(), libDir, entry.getOutputDir())); } return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])); } CompletableFuture<Void> launchWorker(Infrastructure infra, int rmiPort, - int id, final Infrastructure.Node node) + int id, final Infrastructure.Node node, String libDir, + String outputDir) throws UnknownHostException { - String[] shellCommand = buildCommand(InetAddress.getLocalHost().getHostAddress(), rmiPort, id); + String[] shellCommand = buildCommand(InetAddress.getLocalHost().getHostAddress(), rmiPort, id, + libDir, outputDir); CompletableFuture<Void> future = new CompletableFuture<Void>(); Thread thread = new Thread("Worker " + node.getAddress()) { public void run() { @@ -67,15 +72,17 @@ public void run() { return future; } - String[] buildCommand(String rmiHost, int rmiPort, int id) { + String[] buildCommand(String rmiHost, int rmiPort, int id, String libDir, + String outputDir) { List<String> command = new ArrayList<String>(); command.add("java"); command.add("-classpath"); - command.add("lib/*"); + command.add(libDir + "/*"); command.add("-D" + RemoteJVMFactory.RMI_HOST + "=" + rmiHost); command.add("-D" + RemoteJVMFactory.RMI_PORT_PROPERTY + "=" + rmiPort); command.add("-D" + RemoteJVMFactory.JVM_ID + "=" + id); + command.add("-D" + RemoteJVMFactory.OUTPUT_DIR + "=" + outputDir); command.add(ChildJVM.class.getName()); return command.toArray(new String[0]); diff --git a/harness/src/main/java/org/apache/geode/perftest/jvms/JVMMapping.java b/harness/src/main/java/org/apache/geode/perftest/jvms/JVMMapping.java index e01f1f9..0ae6236 100644 --- a/harness/src/main/java/org/apache/geode/perftest/jvms/JVMMapping.java +++ b/harness/src/main/java/org/apache/geode/perftest/jvms/JVMMapping.java @@ -44,4 +44,7 @@ public int getId() { return id; } + public String getOutputDir() { + return "output/" + role + "-" + id; + } } diff --git a/harness/src/main/java/org/apache/geode/perftest/jvms/RemoteJVMFactory.java b/harness/src/main/java/org/apache/geode/perftest/jvms/RemoteJVMFactory.java index d105339..af18ddc 100644 --- a/harness/src/main/java/org/apache/geode/perftest/jvms/RemoteJVMFactory.java +++ b/harness/src/main/java/org/apache/geode/perftest/jvms/RemoteJVMFactory.java @@ -17,7 +17,6 @@ package org.apache.geode.perftest.jvms; -import java.rmi.registry.Registry; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -30,10 +29,11 @@ import org.slf4j.LoggerFactory; import org.apache.geode.perftest.infrastructure.Infrastructure; -import org.apache.geode.perftest.jdk.RMI; +import org.apache.geode.perftest.infrastructure.InfrastructureFactory; import org.apache.geode.perftest.jvms.classpath.ClassPathCopier; import org.apache.geode.perftest.jvms.rmi.Controller; import org.apache.geode.perftest.jvms.rmi.ControllerFactory; +import org.apache.geode.perftest.runner.SharedContext; /** * Factory for launching JVMs and a given infrastructure and setting up RMI @@ -45,55 +45,66 @@ public static final String RMI_HOST = "RMI_HOST"; public static final String RMI_PORT_PROPERTY = "RMI_PORT"; public static final String CONTROLLER = "CONTROLLER"; + public static final String OUTPUT_DIR = "OUTPUT_DIR"; public static final String JVM_ID = "JVM_ID"; public static final int RMI_PORT = 33333; public static final String CLASSPATH = System.getProperty("java.class.path"); public static final String JAVA_HOME = System.getProperty("java.home"); + private static final String LIB_DIR = ".geode-performance/lib"; private final JVMLauncher jvmLauncher; private final ClassPathCopier classPathCopier; private final ControllerFactory controllerFactory; + private final InfrastructureFactory infrastructureFactory; - public RemoteJVMFactory(JVMLauncher jvmLauncher, RMI rmi, + public RemoteJVMFactory(InfrastructureFactory infrastructureFactory, + JVMLauncher jvmLauncher, ClassPathCopier classPathCopier, ControllerFactory controllerFactory) { + this.infrastructureFactory = infrastructureFactory; this.jvmLauncher = jvmLauncher; this.classPathCopier = classPathCopier; this.controllerFactory = controllerFactory; } - public RemoteJVMFactory() { - this(new JVMLauncher(), new RMI(), new ClassPathCopier(CLASSPATH, JAVA_HOME), new ControllerFactory()); + public RemoteJVMFactory(InfrastructureFactory infrastructureFactory) { + this(infrastructureFactory, new JVMLauncher(), new ClassPathCopier(CLASSPATH, JAVA_HOME), new ControllerFactory()); } /** * Start all requested JVMs on the infrastructure - * @param infra The infrastructure to use * @param roles The JVMs to start. Keys a roles and values are the number * of JVMs in that role. * * @return a {@link RemoteJVMs} object used to access the JVMs through RMI */ - public RemoteJVMs launch(Infrastructure infra, - Map<String, Integer> roles) throws Exception { + public RemoteJVMs launch(Map<String, Integer> roles) throws Exception { + int numWorkers = roles.values().stream().mapToInt(Integer::intValue).sum(); + + Infrastructure infra = infrastructureFactory.create(numWorkers); Set<Infrastructure.Node> nodes = infra.getNodes(); - int numWorkers = roles.values().stream().mapToInt(Integer::intValue).sum(); if(nodes.size() < numWorkers) { throw new IllegalStateException("Too few nodes for test. Need " + numWorkers + ", have " + nodes.size()); } - Controller controller = controllerFactory.createController(numWorkers); + List<JVMMapping> mapping = mapRolesToNodes(roles, nodes); - classPathCopier.copyToNodes(infra); + Controller controller = controllerFactory.createController(new SharedContext(mapping), numWorkers); - List<JVMMapping> mapping = mapRolesToNodes(roles, nodes); - CompletableFuture<Void> processesExited = jvmLauncher.launchProcesses(infra, RMI_PORT, mapping); + classPathCopier.copyToNodes(infra, LIB_DIR); + + CompletableFuture<Void> processesExited = jvmLauncher.launchProcesses(infra, RMI_PORT, mapping, + LIB_DIR); if(!controller.waitForWorkers(5, TimeUnit.MINUTES)) { throw new IllegalStateException("Workers failed to start in 1 minute"); } - return new RemoteJVMs(mapping, controller, processesExited); + return new RemoteJVMs(infra, mapping, controller, processesExited); + } + + public InfrastructureFactory getInfrastructureFactory() { + return infrastructureFactory; } private List<JVMMapping> mapRolesToNodes(Map<String, Integer> roles, @@ -113,5 +124,4 @@ public RemoteJVMs launch(Infrastructure infra, } return mapping; } - } diff --git a/harness/src/main/java/org/apache/geode/perftest/jvms/RemoteJVMs.java b/harness/src/main/java/org/apache/geode/perftest/jvms/RemoteJVMs.java index 5e30a3e..aa1e546 100644 --- a/harness/src/main/java/org/apache/geode/perftest/jvms/RemoteJVMs.java +++ b/harness/src/main/java/org/apache/geode/perftest/jvms/RemoteJVMs.java @@ -17,9 +17,8 @@ package org.apache.geode.perftest.jvms; -import java.rmi.NoSuchObjectException; -import java.rmi.registry.Registry; -import java.rmi.server.UnicastRemoteObject; +import java.io.File; +import java.io.IOException; import java.util.Arrays; import java.util.HashSet; import java.util.List; @@ -40,15 +39,16 @@ public class RemoteJVMs implements AutoCloseable { private final List<JVMMapping> jvmMappings; private final Controller controller; - private final TestContext context; private final CompletableFuture<Void> exited; + private final Infrastructure infra; - public RemoteJVMs(List<JVMMapping> mapping, Controller controller, + public RemoteJVMs(Infrastructure infra, + List<JVMMapping> mapping, Controller controller, CompletableFuture<Void> exited) { + this.infra = infra; this.jvmMappings = mapping; this.controller = controller; - this.context = new DefaultTestContext(jvmMappings); this.exited = exited; } @@ -61,21 +61,24 @@ public void execute(Task task, String ... roleArray) { Stream<CompletableFuture> futures = jvmMappings.stream() .filter(mapping -> roles.contains(mapping.getRole())) - .map(mapping -> controller.onWorker(mapping.getId(), task, context)); + .map(mapping -> controller.onWorker(mapping.getId(), task)); futures.forEach(CompletableFuture::join); } - public void close() throws NoSuchObjectException, ExecutionException, InterruptedException { + public void close() throws IOException, ExecutionException, InterruptedException { + infra.close(); controller.close(); exited.get(); } - public String getRole(Infrastructure.Node node) { - return jvmMappings.stream() - .filter(mapping -> mapping.getNode().equals(node)) - .map(JVMMapping::getRole) - .findFirst() - .orElse("no-role"); + /** + * Copy results to the provided output directory + */ + public void copyResults(File benchmarkOutput) throws IOException { + benchmarkOutput.mkdirs(); + for (JVMMapping jvm : jvmMappings) { + infra.copyFromNode(jvm.getNode(), jvm.getOutputDir(), new File(benchmarkOutput, jvm.getRole() + "-" + jvm.getId())); + } } } diff --git a/harness/src/main/java/org/apache/geode/perftest/jvms/classpath/ClassPathCopier.java b/harness/src/main/java/org/apache/geode/perftest/jvms/classpath/ClassPathCopier.java index af0f240..8d98b61 100644 --- a/harness/src/main/java/org/apache/geode/perftest/jvms/classpath/ClassPathCopier.java +++ b/harness/src/main/java/org/apache/geode/perftest/jvms/classpath/ClassPathCopier.java @@ -42,10 +42,9 @@ public ClassPathCopier(String classpath, String javaHome) { /** * Copy the current classpath to a lib directory on all of the nodes in the infrastructure */ - public void copyToNodes(Infrastructure infrastructure) throws IOException { + public void copyToNodes(Infrastructure infrastructure, String destDir) throws IOException { String[] fileArray = classpath.split(File.pathSeparator); - String destDir = "lib"; Iterable<File> files = Arrays.asList(fileArray) .stream() .filter(path -> !path.contains(javaHome)) @@ -54,7 +53,7 @@ public void copyToNodes(Infrastructure infrastructure) throws IOException { .filter(File::exists) .collect(Collectors.toSet()); - infrastructure.copyToNodes(files, destDir); + infrastructure.copyToNodes(files, destDir, true); } private File jarDir(File file) { diff --git a/harness/src/main/java/org/apache/geode/perftest/jvms/rmi/ChildJVM.java b/harness/src/main/java/org/apache/geode/perftest/jvms/rmi/ChildJVM.java index 478902b..45d4c6a 100644 --- a/harness/src/main/java/org/apache/geode/perftest/jvms/rmi/ChildJVM.java +++ b/harness/src/main/java/org/apache/geode/perftest/jvms/rmi/ChildJVM.java @@ -20,9 +20,14 @@ import java.io.File; import java.io.PrintStream; +import org.apache.commons.io.FileUtils; +import org.bouncycastle.jcajce.provider.drbg.DRBG; + import org.apache.geode.perftest.jdk.RMI; import org.apache.geode.perftest.jdk.SystemInterface; import org.apache.geode.perftest.jvms.RemoteJVMFactory; +import org.apache.geode.perftest.runner.DefaultTestContext; +import org.apache.geode.perftest.runner.SharedContext; /** * Main method for a JVM running on a remote node @@ -48,17 +53,29 @@ void run() { try { String RMI_HOST = system.getProperty(RemoteJVMFactory.RMI_HOST); String RMI_PORT = system.getProperty(RemoteJVMFactory.RMI_PORT_PROPERTY); + String OUTPUT_DIR = system.getProperty(RemoteJVMFactory.OUTPUT_DIR); int id = system.getInteger(RemoteJVMFactory.JVM_ID); - File outputDir = new File("output"); + + + if(RMI_HOST == null || RMI_PORT == null || OUTPUT_DIR == null) { + throw new IllegalStateException("ChildJVM must be launched with all required system properties set."); + } + + File outputDir = new File(OUTPUT_DIR); + //Clean up the output directory before the test runs + FileUtils.deleteQuietly(outputDir); outputDir.mkdirs(); - PrintStream out = new PrintStream(new File(outputDir, "ChildJVM-" + id + ".txt")); + PrintStream out = new PrintStream(new File(outputDir, "system.log")); system.setOut(out); system.setErr(out); ControllerRemote controller = (ControllerRemote) rmi .lookup("//" + RMI_HOST + ":" + RMI_PORT + "/" + RemoteJVMFactory.CONTROLLER); - Worker worker = new Worker(); + SharedContext sharedContext = controller.getsharedContext(); + DefaultTestContext context = new DefaultTestContext(sharedContext, outputDir); + + Worker worker = new Worker(context); controller.addWorker(id, worker); diff --git a/harness/src/main/java/org/apache/geode/perftest/jvms/rmi/Controller.java b/harness/src/main/java/org/apache/geode/perftest/jvms/rmi/Controller.java index 1e20a96..e40c2fd 100644 --- a/harness/src/main/java/org/apache/geode/perftest/jvms/rmi/Controller.java +++ b/harness/src/main/java/org/apache/geode/perftest/jvms/rmi/Controller.java @@ -28,21 +28,23 @@ import java.util.concurrent.TimeUnit; import org.apache.geode.perftest.Task; -import org.apache.geode.perftest.TestContext; +import org.apache.geode.perftest.runner.SharedContext; /** * RMI object that lives on the main controller JVM */ public class Controller extends UnicastRemoteObject implements ControllerRemote { private final Registry registry; - private Map<Integer, WorkerRemote> workers = new ConcurrentHashMap<>(); + private final SharedContext context; + private final Map<Integer, WorkerRemote> workers = new ConcurrentHashMap<>(); private final CountDownLatch workersStarted; private volatile boolean isClosed; - Controller(int numWorkers, Registry registry) throws RemoteException { + Controller(int numWorkers, Registry registry, SharedContext context) throws RemoteException { this.workersStarted = new CountDownLatch(numWorkers); this.registry = registry; + this.context = context; } public void close() throws NoSuchObjectException { @@ -66,7 +68,12 @@ public boolean ping() throws RemoteException { return !isClosed; } - public CompletableFuture<Void> onWorker(int id, Task task, TestContext context) { + @Override + public SharedContext getsharedContext() throws RemoteException { + return context; + } + + public CompletableFuture<Void> onWorker(int id, Task task) { WorkerRemote worker = workers.get(id); if(worker == null) { throw new IllegalStateException("Worker number " + id + " is not set"); @@ -74,7 +81,7 @@ public boolean ping() throws RemoteException { return CompletableFuture.runAsync(() -> { try { - worker.execute(task, context); + worker.execute(task); } catch (Exception e) { throw new RuntimeException(e); } diff --git a/harness/src/main/java/org/apache/geode/perftest/jvms/rmi/ControllerFactory.java b/harness/src/main/java/org/apache/geode/perftest/jvms/rmi/ControllerFactory.java index d580831..4aaa47f 100644 --- a/harness/src/main/java/org/apache/geode/perftest/jvms/rmi/ControllerFactory.java +++ b/harness/src/main/java/org/apache/geode/perftest/jvms/rmi/ControllerFactory.java @@ -25,14 +25,16 @@ import java.rmi.registry.Registry; import org.apache.geode.perftest.jdk.RMI; +import org.apache.geode.perftest.runner.SharedContext; public class ControllerFactory { private final RMI rmi = new RMI(); - public Controller createController(int numWorkers) throws RemoteException, AlreadyBoundException { + public Controller createController(SharedContext sharedContext, + int numWorkers) throws RemoteException, AlreadyBoundException { Registry registry = rmi.createRegistry(RMI_PORT); - Controller controller = new Controller(numWorkers, registry); + Controller controller = new Controller(numWorkers, registry, sharedContext); registry.bind(CONTROLLER, controller); return controller; } diff --git a/harness/src/main/java/org/apache/geode/perftest/jvms/rmi/ControllerRemote.java b/harness/src/main/java/org/apache/geode/perftest/jvms/rmi/ControllerRemote.java index 918d8d5..f29d361 100644 --- a/harness/src/main/java/org/apache/geode/perftest/jvms/rmi/ControllerRemote.java +++ b/harness/src/main/java/org/apache/geode/perftest/jvms/rmi/ControllerRemote.java @@ -20,9 +20,13 @@ import java.rmi.Remote; import java.rmi.RemoteException; +import org.apache.geode.perftest.runner.SharedContext; + public interface ControllerRemote extends Remote { void addWorker(int id, WorkerRemote remote) throws RemoteException; boolean ping() throws RemoteException; + + SharedContext getsharedContext() throws RemoteException; } diff --git a/harness/src/main/java/org/apache/geode/perftest/jvms/rmi/Worker.java b/harness/src/main/java/org/apache/geode/perftest/jvms/rmi/Worker.java index a452af1..0653c0e 100644 --- a/harness/src/main/java/org/apache/geode/perftest/jvms/rmi/Worker.java +++ b/harness/src/main/java/org/apache/geode/perftest/jvms/rmi/Worker.java @@ -21,15 +21,17 @@ import java.rmi.server.UnicastRemoteObject; import org.apache.geode.perftest.Task; -import org.apache.geode.perftest.TestContext; +import org.apache.geode.perftest.runner.DefaultTestContext; public class Worker extends UnicastRemoteObject implements WorkerRemote { - public Worker() throws RemoteException { - super(); + private DefaultTestContext context; + + public Worker(DefaultTestContext context) throws RemoteException { + this.context = context; } @Override - public void execute(Task task, TestContext context) throws Exception { + public void execute(Task task) throws Exception { task.run(context); } } diff --git a/harness/src/main/java/org/apache/geode/perftest/jvms/rmi/WorkerRemote.java b/harness/src/main/java/org/apache/geode/perftest/jvms/rmi/WorkerRemote.java index a4020b8..f5f2859 100644 --- a/harness/src/main/java/org/apache/geode/perftest/jvms/rmi/WorkerRemote.java +++ b/harness/src/main/java/org/apache/geode/perftest/jvms/rmi/WorkerRemote.java @@ -20,8 +20,7 @@ import java.rmi.Remote; import org.apache.geode.perftest.Task; -import org.apache.geode.perftest.TestContext; public interface WorkerRemote extends Remote { - void execute(Task task, TestContext context) throws Exception; + void execute(Task task) throws Exception; } diff --git a/harness/src/main/java/org/apache/geode/perftest/runner/DefaultTestContext.java b/harness/src/main/java/org/apache/geode/perftest/runner/DefaultTestContext.java index b649fa9..92a7182 100644 --- a/harness/src/main/java/org/apache/geode/perftest/runner/DefaultTestContext.java +++ b/harness/src/main/java/org/apache/geode/perftest/runner/DefaultTestContext.java @@ -17,27 +17,29 @@ package org.apache.geode.perftest.runner; +import java.io.File; import java.net.InetAddress; -import java.util.List; import java.util.Set; -import java.util.stream.Collectors; import org.apache.geode.perftest.TestContext; -import org.apache.geode.perftest.jvms.JVMMapping; public class DefaultTestContext implements TestContext { - private List<JVMMapping> jvmMappings; + private SharedContext sharedContext; + private File outputDir; - public DefaultTestContext(List<JVMMapping> jvmMappings) { + public DefaultTestContext(SharedContext sharedContext, File outputDir) { + this.sharedContext = sharedContext; + this.outputDir = outputDir; + } - this.jvmMappings = jvmMappings; + @Override + public Set<InetAddress> getHostsForRole(String role) { + return sharedContext.getHostsForRole(role); } - @Override public Set<InetAddress> getHostsForRole(String role) { - return jvmMappings.stream() - .filter(mapping -> mapping.getRole().equals(role)) - .map(mapping -> mapping.getNode().getAddress()) - .collect(Collectors.toSet()); + @Override + public File getOutputDir() { + return outputDir; } } diff --git a/harness/src/main/java/org/apache/geode/perftest/runner/DefaultTestRunner.java b/harness/src/main/java/org/apache/geode/perftest/runner/DefaultTestRunner.java index 54774f5..07ac6b5 100644 --- a/harness/src/main/java/org/apache/geode/perftest/runner/DefaultTestRunner.java +++ b/harness/src/main/java/org/apache/geode/perftest/runner/DefaultTestRunner.java @@ -18,10 +18,8 @@ package org.apache.geode.perftest.runner; import java.io.File; -import java.io.IOException; import java.util.List; import java.util.Map; -import java.util.concurrent.ExecutionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,12 +44,12 @@ private static final Logger logger = LoggerFactory.getLogger(DefaultTestRunner.class); - private final InfrastructureFactory infrastructureFactory; private final RemoteJVMFactory remoteJvmFactory; + private File outputDir; - public DefaultTestRunner(InfrastructureFactory infrastructureFactory, RemoteJVMFactory remoteJvmFactory) { - this.infrastructureFactory = infrastructureFactory; + public DefaultTestRunner(RemoteJVMFactory remoteJvmFactory, File outputDir) { this.remoteJvmFactory = remoteJvmFactory; + this.outputDir = outputDir; } @Override @@ -65,35 +63,34 @@ protected void runTest(TestConfig config) throws Exception { int nodes = config.getTotalJVMs(); - try (Infrastructure infra = infrastructureFactory.create(nodes)){ - Map<String, Integer> roles = config.getRoles(); + if(config.getName() == null) { + throw new IllegalStateException("Benchmark must have a name."); + } + File benchmarkOutput = new File(outputDir, config.getName()); + if(benchmarkOutput.exists()) { + throw new IllegalStateException("Benchmark output directory already exists: " + benchmarkOutput.getPath()); + } - logger.info("Lauching JVMs..."); - //launch JVMs in parallel, hook them up - try (RemoteJVMs remoteJVMs = remoteJvmFactory.launch(infra, roles)) { - logger.info("Starting before tasks..."); - runTasks(config.getBefore(), remoteJVMs); + Map<String, Integer> roles = config.getRoles(); - logger.info("Starting workload tasks..."); - runTasks(config.getWorkload(), remoteJVMs); + logger.info("Lauching JVMs..."); + //launch JVMs in parallel, hook them up + try (RemoteJVMs remoteJVMs = remoteJvmFactory.launch(roles)) { - logger.info("Starting after tasks..."); - runTasks(config.getAfter(), remoteJVMs); + logger.info("Starting before tasks..."); + runTasks(config.getBefore(), remoteJVMs); - logger.info("Copying results..."); - File outputDir = new File("output"); - int nodeId = 0; - for (Infrastructure.Node node : infra.getNodes()) { - String role = remoteJVMs.getRole(node); - infra.copyFromNode(node, "output", new File(outputDir, role + nodeId++)); - } - } - } - } + logger.info("Starting workload tasks..."); + runTasks(config.getWorkload(), remoteJVMs); + + logger.info("Starting after tasks..."); + runTasks(config.getAfter(), remoteJVMs); - public InfrastructureFactory getInfrastructureFactory() { - return infrastructureFactory; + logger.info("Copying results..."); + remoteJVMs.copyResults(benchmarkOutput); + + } } private void runTasks(List<TestConfig.TestStep> steps, @@ -102,4 +99,8 @@ private void runTasks(List<TestConfig.TestStep> steps, remoteJVMs.execute(testStep.getTask(), testStep.getRoles()); }); } + + public RemoteJVMFactory getRemoteJvmFactory() { + return remoteJvmFactory; + } } diff --git a/harness/src/main/java/org/apache/geode/perftest/runner/SharedContext.java b/harness/src/main/java/org/apache/geode/perftest/runner/SharedContext.java new file mode 100644 index 0000000..50aeadf --- /dev/null +++ b/harness/src/main/java/org/apache/geode/perftest/runner/SharedContext.java @@ -0,0 +1,48 @@ +/* + * 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.perftest.runner; + +import java.io.Serializable; +import java.net.InetAddress; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.geode.perftest.jvms.JVMMapping; + +/** + * Context for a running test that is the same for all JVMs + * running the test. This context is created at the beginning of the + * test run and passed to all JVMs. + */ +public class SharedContext implements Serializable { + + private List<JVMMapping> jvmMappings; + + public SharedContext(List<JVMMapping> jvmMappings) { + + this.jvmMappings = jvmMappings; + } + + public Set<InetAddress> getHostsForRole(String role) { + return jvmMappings.stream() + .filter(mapping -> mapping.getRole().equals(role)) + .map(mapping -> mapping.getNode().getAddress()) + .collect(Collectors.toSet()); + } +} diff --git a/harness/src/main/java/org/apache/geode/perftest/yardstick/YardstickTask.java b/harness/src/main/java/org/apache/geode/perftest/yardstick/YardstickTask.java index 1e25056..9046327 100644 --- a/harness/src/main/java/org/apache/geode/perftest/yardstick/YardstickTask.java +++ b/harness/src/main/java/org/apache/geode/perftest/yardstick/YardstickTask.java @@ -75,7 +75,7 @@ public int threads() { @Override public String outputFolder() { - return "output"; + return context.getOutputDir().getAbsolutePath(); } }; cfg.output(System.out); diff --git a/harness/src/test/java/org/apache/geode/perftest/TestRunnerIntegrationTest.java b/harness/src/test/java/org/apache/geode/perftest/TestRunnerIntegrationTest.java index c011da6..12bdbe0 100644 --- a/harness/src/test/java/org/apache/geode/perftest/TestRunnerIntegrationTest.java +++ b/harness/src/test/java/org/apache/geode/perftest/TestRunnerIntegrationTest.java @@ -17,23 +17,75 @@ package org.apache.geode.perftest; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.function.Predicate; +import java.util.stream.Stream; + +import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.apache.geode.perftest.benchmarks.EmptyBenchmark; import org.apache.geode.perftest.infrastructure.local.LocalInfrastructureFactory; import org.apache.geode.perftest.jvms.RemoteJVMFactory; import org.apache.geode.perftest.runner.DefaultTestRunner; +import org.apache.geode.perftest.yardstick.analysis.YardstickThroughputSensorParser; public class TestRunnerIntegrationTest { + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + private TestRunner runner; + private File outputDir; + public static final String SAMPLE_BENCHMARK = "SampleBenchmark"; + + @Before + public void setup() throws IOException { + outputDir = temporaryFolder.newFolder(); + runner = new DefaultTestRunner(new RemoteJVMFactory(new LocalInfrastructureFactory()), + outputDir); + } @Test public void runsBeforeWorkload() throws Exception { - TestRunner runner = new DefaultTestRunner(new LocalInfrastructureFactory(), new RemoteJVMFactory()); - runner.runTest(testConfig -> { + testConfig.name(SAMPLE_BENCHMARK); testConfig.role("all", 1); testConfig.before(context -> System.out.println("hello"), "all"); + }); + } + + @Test + public void generatesOutputDirectoryPerBenchmark() throws Exception { + runner.runTest(testConfig -> { + testConfig.name(SAMPLE_BENCHMARK); + testConfig.role("all", 1); + testConfig.workload(new EmptyBenchmark(), "all"); }); + File expectedBenchmarkDir = new File(outputDir, SAMPLE_BENCHMARK); + assertTrue(expectedBenchmarkDir.exists()); + + //Node directory name is the role + a number + File expectedNodeDir = new File(expectedBenchmarkDir, "all-0"); + assertTrue(expectedNodeDir.exists()); + + //We expect the node directory to have benchmark results + Stream<Path> + outputFiles = Files.walk(expectedNodeDir.toPath()) + .filter(nameMatches(YardstickThroughputSensorParser.sensorOutputFile)); + + assertEquals(1, outputFiles.count()); + } + + private Predicate<Path> nameMatches(String sensorOutputFile) { + return path -> path.toString().contains(sensorOutputFile); } } diff --git a/harness/src/test/java/org/apache/geode/perftest/TestRunnerJUnitTest.java b/harness/src/test/java/org/apache/geode/perftest/TestRunnerJUnitTest.java index 0ae3fee..2b1027b 100644 --- a/harness/src/test/java/org/apache/geode/perftest/TestRunnerJUnitTest.java +++ b/harness/src/test/java/org/apache/geode/perftest/TestRunnerJUnitTest.java @@ -25,7 +25,11 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.io.File; + +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.mockito.InOrder; import org.apache.geode.perftest.infrastructure.InfrastructureFactory; @@ -36,24 +40,25 @@ public class TestRunnerJUnitTest { + @Rule + public TemporaryFolder folder = new TemporaryFolder(); + @Test public void testRunnerRunsBeforeAndAfterTasks() throws Exception { - InfrastructureFactory infrastructureFactory = mock(InfrastructureFactory.class); - Infrastructure infrastructure = mock(Infrastructure.class); RemoteJVMFactory remoteJvmFactory = mock(RemoteJVMFactory.class); - when(infrastructureFactory.create(anyInt())).thenReturn(infrastructure); - RemoteJVMs remoteJVMs = mock(RemoteJVMs.class); - when(remoteJvmFactory.launch(eq(infrastructure), any())).thenReturn(remoteJVMs); + when(remoteJvmFactory.launch(any())).thenReturn(remoteJVMs); - TestRunner runner = new DefaultTestRunner(infrastructureFactory, remoteJvmFactory); + TestRunner runner = new DefaultTestRunner(remoteJvmFactory, + folder.newFolder()); Task before = mock(Task.class); Task after = mock(Task.class); PerformanceTest test = config -> { + config.name("SampleBenchmark"); config.role("before", 1); config.role("workload", 1); config.role("after", 1); diff --git a/harness/src/test/java/org/apache/geode/perftest/TestRunnersTest.java b/harness/src/test/java/org/apache/geode/perftest/TestRunnersTest.java index 05b21b8..99e33eb 100644 --- a/harness/src/test/java/org/apache/geode/perftest/TestRunnersTest.java +++ b/harness/src/test/java/org/apache/geode/perftest/TestRunnersTest.java @@ -17,18 +17,12 @@ package org.apache.geode.perftest; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; import java.util.Arrays; -import jdk.nashorn.internal.objects.NativeDebug; -import org.junit.Rule; import org.junit.Test; -import org.apache.geode.perftest.infrastructure.InfrastructureFactory; -import org.apache.geode.perftest.infrastructure.local.LocalInfrastructure; -import org.apache.geode.perftest.infrastructure.local.LocalInfrastructureFactory; -import org.apache.geode.perftest.infrastructure.ssh.SshInfrastructure; import org.apache.geode.perftest.infrastructure.ssh.SshInfrastructureFactory; import org.apache.geode.perftest.runner.DefaultTestRunner; @@ -36,16 +30,16 @@ @Test public void defaultRunnerShouldParseHosts() { - DefaultTestRunner runner = (DefaultTestRunner) TestRunners.defaultRunner("localhost,localhost"); + DefaultTestRunner runner = (DefaultTestRunner) TestRunners.defaultRunner("localhost,localhost", null); SshInfrastructureFactory infrastructureFactory = - (SshInfrastructureFactory) runner.getInfrastructureFactory(); + (SshInfrastructureFactory) runner.getRemoteJvmFactory().getInfrastructureFactory(); assertEquals(Arrays.asList("localhost", "localhost") , infrastructureFactory.getHosts()); } @Test(expected = IllegalStateException.class) public void defaultRunnerShouldFailWithNoHosts() { - TestRunners.defaultRunner(null); + TestRunners.defaultRunner(null, null); } } \ No newline at end of file diff --git a/harness/src/test/java/org/apache/geode/perftest/benchmarks/EmptyBenchmark.java b/harness/src/test/java/org/apache/geode/perftest/benchmarks/EmptyBenchmark.java new file mode 100644 index 0000000..02e0626 --- /dev/null +++ b/harness/src/test/java/org/apache/geode/perftest/benchmarks/EmptyBenchmark.java @@ -0,0 +1,43 @@ +/* + * 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.perftest.benchmarks; + +import java.io.Serializable; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; + +import org.yardstickframework.BenchmarkDriverAdapter; + +public class EmptyBenchmark extends BenchmarkDriverAdapter implements Serializable { + private AtomicInteger invocations = new AtomicInteger(); + + @Override + public boolean test(Map<Object, Object> ctx) throws Exception { + invocations.incrementAndGet(); + return true; + } + + public int getInvocations() { + return this.invocations.get(); + } + + @Override + public void onException(Throwable e) { + e.printStackTrace(); + } +} diff --git a/harness/src/test/java/org/apache/geode/perftest/infrastructure/local/LocalInfrastructureTest.java b/harness/src/test/java/org/apache/geode/perftest/infrastructure/local/LocalInfrastructureTest.java index 9205b51..9715b4e 100644 --- a/harness/src/test/java/org/apache/geode/perftest/infrastructure/local/LocalInfrastructureTest.java +++ b/harness/src/test/java/org/apache/geode/perftest/infrastructure/local/LocalInfrastructureTest.java @@ -57,7 +57,7 @@ public void copyToNodesPutsFileOnNode() throws IOException, InterruptedException File expectedDir = new File(nodedir, "lib"); assertFalse(expectedDir.exists()); - infra.copyToNodes(Arrays.asList(someFile), "lib"); + infra.copyToNodes(Arrays.asList(someFile), "lib", true); assertTrue(expectedDir.exists()); assertTrue(new File(expectedDir, someFile.getName()).exists()); diff --git a/harness/src/test/java/org/apache/geode/perftest/infrastructure/ssh/SshInfrastructureTest.java b/harness/src/test/java/org/apache/geode/perftest/infrastructure/ssh/SshInfrastructureTest.java index 94f6d71..2936e80 100644 --- a/harness/src/test/java/org/apache/geode/perftest/infrastructure/ssh/SshInfrastructureTest.java +++ b/harness/src/test/java/org/apache/geode/perftest/infrastructure/ssh/SshInfrastructureTest.java @@ -70,12 +70,31 @@ public void copyToNodesPutsFileOnNode() throws IOException, InterruptedException assertFalse(targetFolder.exists()); - infra.copyToNodes(Arrays.asList(someFile), targetFolder.getPath()); + infra.copyToNodes(Arrays.asList(someFile), targetFolder.getPath(), false); assertTrue(targetFolder.exists()); assertTrue(new File(targetFolder, someFile.getName()).exists()); } + @Test + public void copyToNodesCleansDirectory() throws IOException, InterruptedException { + SshInfrastructure infra = new SshInfrastructure(HOSTS, USER); + + File someFile = temporaryFolder.newFile(); + File targetFolder = new File(temporaryFolder.newFolder(), "dest"); + + targetFolder.mkdirs(); + File fileToRemove = new File(targetFolder, "removethis"); + fileToRemove.createNewFile(); + assertTrue(fileToRemove.exists()); + + infra.copyToNodes(Arrays.asList(someFile), targetFolder.getPath(), true); + + assertTrue(targetFolder.exists()); + assertTrue(new File(targetFolder, someFile.getName()).exists()); + assertFalse(fileToRemove.exists()); + } + @Test public void canCopyFilesFromANode() diff --git a/harness/src/test/java/org/apache/geode/perftest/jvms/RemoteJVMFactoryIntegrationTest.java b/harness/src/test/java/org/apache/geode/perftest/jvms/RemoteJVMFactoryIntegrationTest.java index 6528907..03e2931 100644 --- a/harness/src/test/java/org/apache/geode/perftest/jvms/RemoteJVMFactoryIntegrationTest.java +++ b/harness/src/test/java/org/apache/geode/perftest/jvms/RemoteJVMFactoryIntegrationTest.java @@ -28,6 +28,7 @@ import org.junit.rules.TemporaryFolder; import org.apache.geode.perftest.infrastructure.local.LocalInfrastructure; +import org.apache.geode.perftest.infrastructure.local.LocalInfrastructureFactory; public class RemoteJVMFactoryIntegrationTest { @Rule @@ -35,9 +36,9 @@ @Test public void canExecuteCodeOnWorker() throws Exception { - RemoteJVMFactory remoteJvmFactory = new RemoteJVMFactory(); + RemoteJVMFactory remoteJvmFactory = new RemoteJVMFactory(new LocalInfrastructureFactory()); Map<String, Integer> roles = Collections.singletonMap("worker", 1); - try (RemoteJVMs jvms = remoteJvmFactory.launch(new LocalInfrastructure(1), roles)) { + try (RemoteJVMs jvms = remoteJvmFactory.launch(roles)) { File tempFile = new File(temporaryFolder.newFolder(), "tmpfile").getAbsoluteFile(); jvms.execute(context -> { tempFile.createNewFile(); diff --git a/harness/src/test/java/org/apache/geode/perftest/jvms/RemoteJVMFactoryTest.java b/harness/src/test/java/org/apache/geode/perftest/jvms/RemoteJVMFactoryTest.java index 3433aeb..cb576f0 100644 --- a/harness/src/test/java/org/apache/geode/perftest/jvms/RemoteJVMFactoryTest.java +++ b/harness/src/test/java/org/apache/geode/perftest/jvms/RemoteJVMFactoryTest.java @@ -37,7 +37,7 @@ import org.mockito.InOrder; import org.apache.geode.perftest.infrastructure.Infrastructure; -import org.apache.geode.perftest.jdk.RMI; +import org.apache.geode.perftest.infrastructure.InfrastructureFactory; import org.apache.geode.perftest.jvms.classpath.ClassPathCopier; import org.apache.geode.perftest.jvms.rmi.Controller; import org.apache.geode.perftest.jvms.rmi.ControllerFactory; @@ -45,11 +45,11 @@ public class RemoteJVMFactoryTest { private JVMLauncher jvmLauncher; - private RMI rmi; private ClassPathCopier classPathCopier; private RemoteJVMFactory factory; private Controller controller; private ControllerFactory controllerFactory; + private Infrastructure infra; @Before public void setUp() throws AlreadyBoundException, RemoteException { @@ -57,14 +57,15 @@ public void setUp() throws AlreadyBoundException, RemoteException { jvmLauncher = mock(JVMLauncher.class); controller = mock(Controller.class); controllerFactory = mock(ControllerFactory.class); - when(controllerFactory.createController(anyInt())).thenReturn(controller); - factory = new RemoteJVMFactory(jvmLauncher, rmi, classPathCopier, controllerFactory); + when(controllerFactory.createController(any(), anyInt())).thenReturn(controller); + infra = mock(Infrastructure.class); + InfrastructureFactory infraFactory = nodes -> infra; + factory = new RemoteJVMFactory(infraFactory, jvmLauncher, classPathCopier, controllerFactory); } @Test public void launchMethodCreatesControllerAndLaunchesNodes() throws Exception { Map<String, Integer> roles = Collections.singletonMap("role", 2); - Infrastructure infra = mock(Infrastructure.class); Infrastructure.Node node1 = mock(Infrastructure.Node.class); Infrastructure.Node node2 = mock(Infrastructure.Node.class); @@ -73,12 +74,12 @@ public void launchMethodCreatesControllerAndLaunchesNodes() throws Exception { when(controller.waitForWorkers(anyInt(), any())).thenReturn(true); - factory.launch(infra, roles); + factory.launch(roles); InOrder inOrder = inOrder(controller, controllerFactory, jvmLauncher, classPathCopier, infra); - inOrder.verify(controllerFactory).createController(eq(2)); - inOrder.verify(jvmLauncher).launchProcesses(eq(infra), anyInt(), any()); + inOrder.verify(controllerFactory).createController(any(), eq(2)); + inOrder.verify(jvmLauncher).launchProcesses(eq(infra), anyInt(), any(), any()); inOrder.verify(controller).waitForWorkers(anyInt(), any()); diff --git a/harness/src/test/java/org/apache/geode/perftest/jvms/rmi/ChildJVMTest.java b/harness/src/test/java/org/apache/geode/perftest/jvms/rmi/ChildJVMTest.java index 146ab61..2d61883 100644 --- a/harness/src/test/java/org/apache/geode/perftest/jvms/rmi/ChildJVMTest.java +++ b/harness/src/test/java/org/apache/geode/perftest/jvms/rmi/ChildJVMTest.java @@ -17,6 +17,10 @@ package org.apache.geode.perftest.jvms.rmi; +import static org.apache.geode.perftest.jvms.RemoteJVMFactory.OUTPUT_DIR; +import static org.apache.geode.perftest.jvms.RemoteJVMFactory.RMI_HOST; +import static org.apache.geode.perftest.jvms.RemoteJVMFactory.RMI_PORT_PROPERTY; +import static org.junit.Assert.assertFalse; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; @@ -24,12 +28,16 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.io.File; +import java.io.IOException; import java.net.MalformedURLException; import java.rmi.NotBoundException; import java.rmi.RemoteException; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.apache.geode.perftest.jdk.RMI; import org.apache.geode.perftest.jdk.SystemInterface; @@ -37,14 +45,21 @@ public class ChildJVMTest { + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); private RMI rmi; private ChildJVM jvm; private SystemInterface system; private Controller controller; + private File folder; @Before - public void setUp() throws RemoteException, NotBoundException, MalformedURLException { + public void setUp() throws IOException, NotBoundException { system = mock(SystemInterface.class); + when(system.getProperty(RMI_HOST)).thenReturn("something"); + when(system.getProperty(RMI_PORT_PROPERTY)).thenReturn("0"); + folder = temporaryFolder.newFolder(); + when(system.getProperty(OUTPUT_DIR)).thenReturn(folder.getAbsolutePath()); rmi = mock(RMI.class); jvm = new ChildJVM(rmi, system, 1); @@ -69,4 +84,14 @@ public void childRetriesUntilControllerExits() throws RemoteException { verify(controller, times(3)).ping(); } + @Test + public void childCleansOutputDir() throws IOException { + File expectedFile = new File(folder, "somefile.txt"); + expectedFile.createNewFile(); + + jvm.run(); + + assertFalse(expectedFile.exists()); + } + } \ No newline at end of file diff --git a/harness/src/test/java/org/apache/geode/perftest/runner/DefaultTestContextTest.java b/harness/src/test/java/org/apache/geode/perftest/runner/SharedContextTest.java similarity index 93% rename from harness/src/test/java/org/apache/geode/perftest/runner/DefaultTestContextTest.java rename to harness/src/test/java/org/apache/geode/perftest/runner/SharedContextTest.java index 704374f..7784105 100644 --- a/harness/src/test/java/org/apache/geode/perftest/runner/DefaultTestContextTest.java +++ b/harness/src/test/java/org/apache/geode/perftest/runner/SharedContextTest.java @@ -33,7 +33,7 @@ import org.apache.geode.perftest.infrastructure.Infrastructure; import org.apache.geode.perftest.jvms.JVMMapping; -public class DefaultTestContextTest { +public class SharedContextTest { @Test public void getHostsForRoleShouldReturnCorrectList() throws UnknownHostException { @@ -47,7 +47,7 @@ public void getHostsForRoleShouldReturnCorrectList() throws UnknownHostException when(node2.getAddress()).thenReturn(host2); JVMMapping mapping2 = new JVMMapping(node2, "role", 2); - DefaultTestContext context = new DefaultTestContext(Arrays.asList(mapping1, mapping2)); + SharedContext context = new SharedContext(Arrays.asList(mapping1, mapping2)); Set<InetAddress> hosts = context.getHostsForRole("role"); diff --git a/harness/src/test/java/org/apache/geode/perftest/yardstick/YardstickTaskTest.java b/harness/src/test/java/org/apache/geode/perftest/yardstick/YardstickTaskTest.java index 7d60d9b..8a29d2e 100644 --- a/harness/src/test/java/org/apache/geode/perftest/yardstick/YardstickTaskTest.java +++ b/harness/src/test/java/org/apache/geode/perftest/yardstick/YardstickTaskTest.java @@ -17,50 +17,43 @@ package org.apache.geode.perftest.yardstick; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; +import static org.junit.Assert.assertTrue; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; +import java.io.File; +import java.nio.file.Files; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; -import org.yardstickframework.BenchmarkDriverAdapter; +import org.junit.rules.TemporaryFolder; import org.apache.geode.perftest.Task; +import org.apache.geode.perftest.TestContext; import org.apache.geode.perftest.WorkloadConfig; +import org.apache.geode.perftest.benchmarks.EmptyBenchmark; +import org.apache.geode.perftest.runner.DefaultTestContext; public class YardstickTaskTest { + @Rule + public final TemporaryFolder folder = new TemporaryFolder(); + @Test public void testExecuteBenchmark() throws Exception { EmptyBenchmark benchmark = new EmptyBenchmark(); WorkloadConfig workloadConfig = new WorkloadConfig(); workloadConfig.threads(1); Task task = new YardstickTask(benchmark, workloadConfig); - task.run(null); + File outputDir = folder.newFolder(); + TestContext context = new DefaultTestContext(null, outputDir); + task.run(context); + + assertTrue(1 <= benchmark.getInvocations()); - Assert.assertTrue(1 <= benchmark.invocations.get()); + assertTrue(Files.walk(outputDir.toPath()).findFirst().isPresent()); //TODO -verify probes are shutdown //TODO -verify benchmark is shutdown - //TODO - pass in probes to yardstick util, turn it into a real class - } - private static class EmptyBenchmark extends BenchmarkDriverAdapter { - private AtomicInteger invocations = new AtomicInteger(); - - @Override - public boolean test(Map<Object, Object> ctx) throws Exception { - invocations.incrementAndGet(); - return true; - } - - @Override - public void onException(Throwable e) { - e.printStackTrace(); - } - } } \ No newline at end of file ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: us...@infra.apache.org With regards, Apache Git Services