This is an automated email from the ASF dual-hosted git repository.

jensdeppe pushed a commit to branch feature/GEODE-5787-refactor-dunit
in repository https://gitbox.apache.org/repos/asf/geode.git

commit 3a2082e31f433b127f15fe3a3a17e927dfee863b
Author: Sai Boorlagadda <sboorlaga...@pivotal.io>
AuthorDate: Mon Oct 1 15:55:46 2018 -0700

    wip
    
    Signed-off-by: Jens Deppe <jde...@pivotal.io>
---
 .../org/apache/geode/test/dunit/RMIException.java  |  20 +++
 .../test/dunit/standalone/ProcessManager.java      |   1 +
 .../apache/geode/test/dunit2/ChildVMLauncher.java  | 192 +++++++++++++++++++++
 .../apache/geode/test/dunit2/DUnitEnvConfig.java   |  27 +++
 .../apache/geode/test/dunit2/DUnitEnvironment.java |   7 +
 .../main/java/org/apache/geode/test/dunit2/VM.java | 127 ++++++++++++++
 .../geode/test/dunit2/DUnitEnvironmentTest.java    |  21 +++
 .../java/org/apache/geode/test/dunit2/VMTest.java  |  41 +++++
 8 files changed, 436 insertions(+)

diff --git 
a/geode-dunit/src/main/java/org/apache/geode/test/dunit/RMIException.java 
b/geode-dunit/src/main/java/org/apache/geode/test/dunit/RMIException.java
index 1d59bcc..72005eb 100644
--- a/geode-dunit/src/main/java/org/apache/geode/test/dunit/RMIException.java
+++ b/geode-dunit/src/main/java/org/apache/geode/test/dunit/RMIException.java
@@ -77,6 +77,14 @@ public class RMIException extends GemFireException {
     this.vm = vm;
   }
 
+  public RMIException(org.apache.geode.test.dunit2.VM vm, String className, 
String methodName, Throwable cause) {
+    super("While invoking " + className + "." + methodName + " in " + vm, 
cause);
+    this.cause = cause;
+    this.className = className;
+    this.methodName = methodName;
+    //this.vm = vm;
+  }
+
   /**
    * Creates a new <code>RMIException</code> to indicate that an exception of 
a given type was
    * thrown while invoking a given method.
@@ -99,6 +107,18 @@ public class RMIException extends GemFireException {
     this.stackTrace = stackTrace;
   }
 
+  public RMIException(org.apache.geode.test.dunit2.VM vm, String className, 
String methodName, Throwable cause,
+                      String stackTrace) {
+    super("While invoking " + className + "." + methodName + " in " + vm,
+        new HokeyException(cause, stackTrace));
+//    this.vm = vm;
+    this.cause = cause;
+    this.className = className;
+    this.methodName = methodName;
+    // this.exceptionClassName = exceptionClassName; assignment has no effect
+    this.stackTrace = stackTrace;
+  }
+
   /**
    * Returns the class name of the exception that was thrown in a remote 
method invocation.
    */
diff --git 
a/geode-dunit/src/main/java/org/apache/geode/test/dunit/standalone/ProcessManager.java
 
b/geode-dunit/src/main/java/org/apache/geode/test/dunit/standalone/ProcessManager.java
index a200f14..ee0a3c5 100755
--- 
a/geode-dunit/src/main/java/org/apache/geode/test/dunit/standalone/ProcessManager.java
+++ 
b/geode-dunit/src/main/java/org/apache/geode/test/dunit/standalone/ProcessManager.java
@@ -63,6 +63,7 @@ public class ProcessManager {
 
   public synchronized void launchVM(String version, int vmNum, boolean 
bouncedVM)
       throws IOException {
+    //TODO: why do we need this gaurd? May be vm.launch should handle it
     if (processes.containsKey(vmNum)) {
       throw new IllegalStateException("VM " + vmNum + " is already running.");
     }
diff --git 
a/geode-dunit/src/main/java/org/apache/geode/test/dunit2/ChildVMLauncher.java 
b/geode-dunit/src/main/java/org/apache/geode/test/dunit2/ChildVMLauncher.java
new file mode 100644
index 0000000..6a19cab
--- /dev/null
+++ 
b/geode-dunit/src/main/java/org/apache/geode/test/dunit2/ChildVMLauncher.java
@@ -0,0 +1,192 @@
+package org.apache.geode.test.dunit2;
+
+import static 
org.apache.geode.distributed.ConfigurationProperties.ENABLE_NETWORK_PARTITION_DETECTION;
+import static org.apache.geode.distributed.ConfigurationProperties.LOG_LEVEL;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import org.apache.geode.distributed.ConfigurationProperties;
+import org.apache.geode.distributed.internal.DistributionConfig;
+import org.apache.geode.distributed.internal.InternalLocator;
+import org.apache.geode.test.dunit.VM;
+import org.apache.geode.test.dunit.standalone.ChildVM;
+import org.apache.geode.test.dunit.standalone.DUnitLauncher;
+import org.apache.geode.test.dunit.standalone.VersionManager;
+
+public class ChildVMLauncher {
+
+  private VersionManager versionManager;
+
+  private int debugPort = Integer.getInteger("dunit.debug.basePort", 0);
+  private int suspendVM = Integer.getInteger("dunit.debug.suspendVM", -100);
+
+  public ChildVMLauncher(VersionManager versionManager) {
+    this.versionManager = versionManager;
+  }
+
+  public Process launch(int vmId, String workingDirPath, String geodeVersion, 
String registryHost, int registryPort)
+    throws IOException {
+    File workingDir = new File(workingDirPath);
+
+    if (!workingDir.exists()) {
+      workingDir.mkdirs();
+    }
+
+    String[] cmd = buildJavaCommand(vmId, geodeVersion, registryHost, 
registryPort);
+    System.out.println("Executing " + Arrays.toString(cmd));
+
+//    if (log4jConfig != null) {
+//      FileUtils.copyFileToDirectory(log4jConfig, workingDir);
+//    }
+
+    // TODO - delete directory contents, preferably with commons io FileUtils
+    Process process = Runtime.getRuntime().exec(cmd, null, workingDir);
+    linkStreams(geodeVersion, vmId, process, process.getErrorStream(), 
System.err);
+    linkStreams(geodeVersion, vmId, process, process.getInputStream(), 
System.out);
+    return process;
+  }
+
+  private String[] buildJavaCommand(int vmId, String geodeVersion, String 
registryHost, int registryPort) {
+
+    String cmd = Paths.get(System.getProperty("java.home"), "bin", 
"java").toString();
+
+    String dunitClasspath = System.getProperty("java.class.path");
+    String separator = File.separator;
+    String classPath;
+    if (VersionManager.isCurrentVersion(geodeVersion)) {
+      classPath = dunitClasspath;
+    } else {
+      // remove current-version product classes and resources from the 
classpath
+      String buildDir = separator + "geode-core" + separator + "build" + 
separator;
+
+      String mainClasses = buildDir + "classes" + separator + "main";
+      dunitClasspath = removeFromPath(dunitClasspath, mainClasses);
+
+      dunitClasspath = removeFromPath(dunitClasspath, 
"geode-core/out/production");
+
+      String mainResources = buildDir + "resources" + separator + "main";
+      dunitClasspath = removeFromPath(dunitClasspath, mainResources);
+
+      String generatedResources = buildDir + "generated-resources" + separator 
+ "main";
+      dunitClasspath = removeFromPath(dunitClasspath, generatedResources);
+
+      buildDir = separator + "geode-common" + separator + "build" + separator 
+ "classes"
+          + separator + "main";
+      dunitClasspath = removeFromPath(dunitClasspath, buildDir);
+
+      buildDir = separator + "geode-json" + separator + "build" + separator + 
"classes" + separator
+          + "main";
+      dunitClasspath = removeFromPath(dunitClasspath, buildDir);
+
+      classPath = versionManager.getClasspath(geodeVersion) + 
File.pathSeparator + dunitClasspath;
+    }
+
+    String jdkDebug = "";
+    if (debugPort > 0) {
+      jdkDebug += ",address=" + debugPort;
+      debugPort++;
+    }
+
+    String jdkSuspend = vmId == suspendVM ? "y" : "n"; // ignore version
+    ArrayList<String> cmds = new ArrayList<String>();
+    cmds.add(cmd);
+    cmds.add("-classpath");
+    String jreLib = separator + "jre" + separator + "lib" + separator;
+    classPath = removeFromPath(classPath, jreLib);
+    cmds.add(classPath);
+    cmds.add("-D" + DUnitLauncher.RMI_HOST_PARAM + "=" + registryHost);
+    cmds.add("-D" + DUnitLauncher.RMI_PORT_PARAM + "=" + registryPort);
+    cmds.add("-D" + DUnitLauncher.VM_NUM_PARAM + "=" + vmId);
+    cmds.add("-D" + DUnitLauncher.VM_VERSION_PARAM + "=" + geodeVersion);
+    cmds.add("-D" + DUnitLauncher.WORKSPACE_DIR_PARAM + "=" + new 
File(".").getAbsolutePath());
+    if (vmId >= 0) { // let the locator print a banner
+      if (geodeVersion.equals(VersionManager.CURRENT_VERSION)) { // enable the 
banner for older versions
+        cmds.add("-D" + InternalLocator.INHIBIT_DM_BANNER + "=true");
+      }
+    } else {
+      // most distributed unit tests were written under the assumption that 
network partition
+      // detection is disabled, so we turn it off in the locator. Tests for 
network partition
+      // detection should create a separate locator that has it enabled
+      cmds.add(
+          "-D" + DistributionConfig.GEMFIRE_PREFIX + 
ENABLE_NETWORK_PARTITION_DETECTION + "=false");
+      cmds.add(
+          "-D" + DistributionConfig.GEMFIRE_PREFIX + 
"allow_old_members_to_join_for_testing=true");
+    }
+    cmds.add("-D" + LOG_LEVEL + "=" + DUnitLauncher.logLevel);
+    if (DUnitLauncher.LOG4J != null) {
+      cmds.add("-Dlog4j.configurationFile=" + DUnitLauncher.LOG4J);
+    }
+    cmds.add("-Djava.library.path=" + System.getProperty("java.library.path"));
+    cmds.add("-Xrunjdwp:transport=dt_socket,server=y,suspend=" + jdkSuspend + 
jdkDebug);
+    cmds.add("-XX:+HeapDumpOnOutOfMemoryError");
+    cmds.add("-Xmx512m");
+    cmds.add("-D" + DistributionConfig.GEMFIRE_PREFIX + 
"DEFAULT_MAX_OPLOG_SIZE=10");
+    cmds.add("-D" + DistributionConfig.GEMFIRE_PREFIX + 
"disallowMcastDefaults=true");
+    cmds.add("-D" + DistributionConfig.RESTRICT_MEMBERSHIP_PORT_RANGE + 
"=true");
+    cmds.add("-D" + DistributionConfig.GEMFIRE_PREFIX
+        + ConfigurationProperties.VALIDATE_SERIALIZABLE_OBJECTS + "=true");
+    cmds.add("-ea");
+    cmds.add("-XX:MetaspaceSize=512m");
+    cmds.add("-XX:SoftRefLRUPolicyMSPerMB=1");
+    cmds.add(ChildVM.class.getName());
+    String[] rst = new String[cmds.size()];
+    cmds.toArray(rst);
+
+    return rst;
+  }
+
+  private String removeFromPath(String classpath, String partialPath) {
+    String[] jars = classpath.split(File.pathSeparator);
+    StringBuilder sb = new StringBuilder(classpath.length());
+    Boolean firstjar = true;
+    for (String jar : jars) {
+      if (!jar.contains(partialPath)) {
+        if (!firstjar) {
+          sb.append(File.pathSeparator);
+        }
+        sb.append(jar);
+        firstjar = false;
+      }
+    }
+    return sb.toString();
+  }
+
+  private void linkStreams(final String version, final int vmId, final Process 
process,
+                           final InputStream in, final PrintStream out) {
+    final String vmName = "[" + VM.getVMName(version, vmId) + "] ";
+    System.out.println("linking IO streams for " + vmName);
+    Thread ioTransport = new Thread() {
+      public void run() {
+        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+        try {
+          String line = reader.readLine();
+          while (line != null) {
+            if (line.length() == 0) {
+              out.println();
+            } else {
+              out.print(vmName);
+              out.println(line);
+            }
+            line = reader.readLine();
+          }
+        } catch (Exception e) {
+          if (!process.isAlive()) {
+            out.println("Error transporting IO from child process");
+            e.printStackTrace(out);
+          }
+        }
+      }
+    };
+
+    ioTransport.setDaemon(true);
+    ioTransport.start();
+  }
+}
diff --git 
a/geode-dunit/src/main/java/org/apache/geode/test/dunit2/DUnitEnvConfig.java 
b/geode-dunit/src/main/java/org/apache/geode/test/dunit2/DUnitEnvConfig.java
new file mode 100644
index 0000000..1a1465e
--- /dev/null
+++ b/geode-dunit/src/main/java/org/apache/geode/test/dunit2/DUnitEnvConfig.java
@@ -0,0 +1,27 @@
+package org.apache.geode.test.dunit2;
+
+public class DUnitEnvConfig {
+  private String registryHost;
+  private int registryPort;
+
+  public DUnitEnvConfig(String registryHost, int registryPort) {
+    this.registryHost = registryHost;
+    this.registryPort = registryPort;
+  }
+
+  public String getRegistryHost() {
+    return registryHost;
+  }
+
+  public void setRegistryHost(String registryHost) {
+    this.registryHost = registryHost;
+  }
+
+  public int getRegistryPort() {
+    return registryPort;
+  }
+
+  public void setRegistryPort(int registryPort) {
+    this.registryPort = registryPort;
+  }
+}
diff --git 
a/geode-dunit/src/main/java/org/apache/geode/test/dunit2/DUnitEnvironment.java 
b/geode-dunit/src/main/java/org/apache/geode/test/dunit2/DUnitEnvironment.java
new file mode 100644
index 0000000..62a3e72
--- /dev/null
+++ 
b/geode-dunit/src/main/java/org/apache/geode/test/dunit2/DUnitEnvironment.java
@@ -0,0 +1,7 @@
+package org.apache.geode.test.dunit2;
+
+public class DUnitEnvironment {
+  public VM getVM(int i) {
+    return new VM();
+  }
+}
diff --git a/geode-dunit/src/main/java/org/apache/geode/test/dunit2/VM.java 
b/geode-dunit/src/main/java/org/apache/geode/test/dunit2/VM.java
new file mode 100644
index 0000000..85ffcc5
--- /dev/null
+++ b/geode-dunit/src/main/java/org/apache/geode/test/dunit2/VM.java
@@ -0,0 +1,127 @@
+package org.apache.geode.test.dunit2;
+
+import java.io.IOException;
+import java.rmi.RemoteException;
+import java.util.concurrent.Callable;
+
+import hydra.MethExecutorResult;
+
+import org.apache.geode.test.dunit.NamedCallable;
+import org.apache.geode.test.dunit.NamedRunnable;
+import org.apache.geode.test.dunit.RMIException;
+import org.apache.geode.test.dunit.SerializableCallable;
+import org.apache.geode.test.dunit.SerializableCallableIF;
+import org.apache.geode.test.dunit.SerializableRunnable;
+import org.apache.geode.test.dunit.SerializableRunnableIF;
+import org.apache.geode.test.dunit.standalone.RemoteDUnitVMIF;
+
+public class VM {
+  private ChildVMLauncher launcher;
+  private int id = 1;
+  private boolean alive = false;
+
+  private Process process;
+  private RemoteDUnitVMIF stub;
+
+  public VM() {
+
+  }
+  public VM(DUnitEnvConfig config, ChildVMLauncher launcher) {
+    this.launcher = launcher;
+  }
+
+  public int getId() {
+    return id;
+  }
+
+  public VM launch() throws IOException {
+    alive = true;
+    process = launcher.launch(1, "0", "0", "", 0);
+    return this;
+  }
+
+  public void stop() {
+    alive = false;
+  }
+
+  public boolean isAlive() {
+    return alive;
+  }
+
+  /**
+   * Invokes the {@code run} method of a {@link Runnable} in this {@code VM}. 
Recall that
+   * {@code run} takes no arguments and has no return value.
+   *
+   * @param runnable The {@code Runnable} to be run
+   * @param name The name of the {@code Runnable}, which will be logged in 
DUnit output
+   *
+   * @see SerializableRunnable
+   */
+  public void invoke(final String name, final SerializableRunnableIF runnable) 
{
+    invoke(new NamedRunnable(name, runnable), "run");
+  }
+
+  /**
+   * Invokes the {@code run} method of a {@link Runnable} in this {@code VM}. 
Recall that
+   * {@code run} takes no arguments and has no return value.
+   *
+   * @param runnable The {@code Runnable} to be run
+   *
+   * @see SerializableRunnable
+   */
+  public void invoke(final SerializableRunnableIF runnable) {
+    invoke(runnable, "run");
+  }
+
+  /**
+   * Invokes the {@code call} method of a {@link Callable} in this {@code VM}.
+   *
+   * @param callable The {@code Callable} to be run
+   * @param name The name of the {@code Callable}, which will be logged in 
DUnit output
+   *
+   * @see SerializableCallable
+   */
+  public <V> V invoke(final String name, final SerializableCallableIF<V> 
callable) {
+    return invoke(new NamedCallable<>(name, callable), "call");
+  }
+
+  /**
+   * Invokes the {@code call} method of a {@link Callable} in this {@code VM}.
+   *
+   * @param callable The {@code Callable} to be run
+   *
+   * @see SerializableCallable
+   */
+  public <V> V invoke(final SerializableCallableIF<V> callable) {
+    return invoke(callable, "call");
+  }
+
+  private <V> V invoke(final Object targetObject, final String methodName) {
+    return invoke(targetObject, methodName, new Object[0]);
+  }
+
+  private <V> V invoke(final Object targetObject, final String methodName, 
final Object[] args) {
+    if (!alive) {
+      throw new RMIException(this, targetObject.getClass().getName(), 
methodName,
+          new IllegalStateException("VM not available: " + this));
+    }
+
+    try {
+      MethExecutorResult result;
+      if (args == null) {
+        result = stub.executeMethodOnObject(targetObject, methodName);
+      } else {
+        result = stub.executeMethodOnObject(targetObject, methodName, args);
+      }
+      if (!result.exceptionOccurred()) {
+        return (V) result.getResult();
+
+      } else {
+        throw new RMIException(this, targetObject.getClass().getName(), 
methodName,
+            result.getException(), result.getStackTrace());
+      }
+    } catch (RemoteException exception) {
+      throw new RMIException(this, targetObject.getClass().getName(), 
methodName, exception);
+    }
+  }
+}
diff --git 
a/geode-dunit/src/test/java/org/apache/geode/test/dunit2/DUnitEnvironmentTest.java
 
b/geode-dunit/src/test/java/org/apache/geode/test/dunit2/DUnitEnvironmentTest.java
new file mode 100644
index 0000000..a5ee344
--- /dev/null
+++ 
b/geode-dunit/src/test/java/org/apache/geode/test/dunit2/DUnitEnvironmentTest.java
@@ -0,0 +1,21 @@
+package org.apache.geode.test.dunit2;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class DUnitEnvironmentTest {
+
+  @Test
+  public void getVMGetsRequestedVM() {
+    DUnitEnvironment environment = new DUnitEnvironment();
+    assertThat(environment.getVM(1)).isNotNull();
+    assertThat(environment.getVM(1).getId()).isEqualTo(1);
+  }
+
+  @Test
+  public void launchVMRunsJavaProcess() {
+
+  }
+
+}
\ No newline at end of file
diff --git a/geode-dunit/src/test/java/org/apache/geode/test/dunit2/VMTest.java 
b/geode-dunit/src/test/java/org/apache/geode/test/dunit2/VMTest.java
new file mode 100644
index 0000000..47e8fac
--- /dev/null
+++ b/geode-dunit/src/test/java/org/apache/geode/test/dunit2/VMTest.java
@@ -0,0 +1,41 @@
+package org.apache.geode.test.dunit2;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.IOException;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.contrib.java.lang.system.SystemOutRule;
+
+public class VMTest {
+
+  @Rule
+  public SystemOutRule systemOutRule = new SystemOutRule();
+  @Test
+  public void testLaunchVM() throws IOException {
+    VM newVM = new VM();
+    VM launchedVM = new VM().launch();
+
+    assertThat(launchedVM.isAlive()).isTrue();
+    assertThat(newVM.isAlive()).isFalse();
+  }
+
+  @Test
+  public void testStopVMStopsIt() throws IOException {
+    VM runningVM = new VM().launch();
+    runningVM.stop();
+    assertThat(runningVM.isAlive()).isFalse();
+  }
+
+  @Test
+  public void  testInvokeReturnsValueFromCallable() throws IOException {
+    final String message = "Hello! World";
+
+    VM vm = new VM().launch();
+    String result = vm.invoke(() -> message);
+
+    assertThat(result).isEqualTo(message);
+  }
+
+}
\ No newline at end of file

Reply via email to