You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by kl...@apache.org on 2015/08/21 22:29:31 UTC
[4/9] incubator-geode git commit: Dunit changes for JUnit 4 syntax.
Refactoring to modernize API.
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/ExpectedExceptionString.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/ExpectedExceptionString.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/ExpectedExceptionString.java
new file mode 100755
index 0000000..a1ef782
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/ExpectedExceptionString.java
@@ -0,0 +1,142 @@
+package com.gemstone.gemfire.test.dunit;
+
+import static com.gemstone.gemfire.test.dunit.Invoke.invokeInEveryVM;
+
+import java.io.Serializable;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+import org.apache.logging.log4j.Logger;
+
+import com.gemstone.gemfire.internal.logging.LogService;
+
+/**
+ * An expected exception string which is added or removed in the log to
+ * suppress it during greplogs (grep for error strings).
+ *
+ * Extracted from DistributedTestCase. Renamed from ExpectedException to
+ * prevent conflict with the JUnit rule. Note that the implementation
+ * is still writing <code><ExpectedException ...></code> statements to the
+ * log for the <code>batterytest.greplogs.LogConsumer</code>.
+ *
+ * @author Mitch Thomas
+ * @since 5.7bugfix
+ * @see batterytest.greplogs.LogConsumer
+ */
+public class ExpectedExceptionString implements Serializable {
+ private static final long serialVersionUID = 1L;
+ private static final Logger logger = LogService.getLogger();
+
+ // Note: if you change these prefixes and suffix then you must also change batterytest.greplogs.LogConsumer to match
+ private static final String LOG_MESSAGE_PREFIX_ADD = "<ExpectedException action=add>";
+ private static final String LOG_MESSAGE_PREFIX_REMOVE = "<ExpectedException action=remove>";
+ private static final String LOG_MESSAGE_SUFFIX = "</ExpectedException>";
+
+ private final String exceptionString;
+
+ private final transient VM vm;
+
+ // TODO: prevent memory leak here
+ private static final Queue<ExpectedExceptionString> expectedExceptionStrings = new ConcurrentLinkedQueue<ExpectedExceptionString>();
+
+ public ExpectedExceptionString(final String exceptionString) {
+ this(exceptionString, null);
+ }
+
+ public ExpectedExceptionString(final String exceptionString, final VM vm) {
+ this.exceptionString = exceptionString;
+ this.vm = vm;
+ }
+
+ public String getAddMessage() {
+ return LOG_MESSAGE_PREFIX_ADD + this.exceptionString + LOG_MESSAGE_SUFFIX;
+ }
+
+ public String getRemoveMessage() {
+ return LOG_MESSAGE_PREFIX_REMOVE + this.exceptionString + LOG_MESSAGE_SUFFIX;
+ }
+
+ public void remove() {
+ final SerializableRunnable removeRunnable = newRemoveSerializableRunnable(getRemoveMessage());
+
+ if (this.vm != null) {
+ this.vm.invoke(removeRunnable);
+ } else {
+ invokeInEveryVM(removeRunnable);
+ }
+
+ logger.info(getRemoveMessage());
+ }
+
+ /**
+ * Log in all VMs the expected exception string to prevent grep logs from
+ * complaining. The expected string is used by the GrepLogs utility and so
+ * can contain regular expression characters.
+ *
+ * If you do not remove the expected exception, it will be removed at the
+ * end of your test case automatically.
+ *
+ * @since 5.7bugfix
+ * @param exception the exception string to expect
+ * @return an instance that a test can use for removal
+ */
+ public static ExpectedExceptionString addExpectedExceptionString(final String exception) {
+ return addExpectedExceptionString(exception, null);
+ }
+
+ /**
+ * Log in all VMs, the
+ * expected exception string to prevent grep logs from complaining. The
+ * expected string is used by the GrepLogs utility and so can contain
+ * regular expression characters.
+ *
+ * @since 5.7bugfix
+ * @param exceptionString the exception string to expect
+ * @param vm the VM on which to log the expected exception or null for all VMs
+ * @return an instance that a test can use for removal
+ */
+ public static ExpectedExceptionString addExpectedExceptionString(final String exceptionString, final VM vm) {
+ final ExpectedExceptionString expectedOutput;
+ if (vm != null) {
+ expectedOutput = new ExpectedExceptionString(exceptionString, vm);
+ } else {
+ expectedOutput = new ExpectedExceptionString(exceptionString);
+ }
+
+ final String addMessage = expectedOutput.getAddMessage();
+
+ final SerializableRunnable addRunnable = newAddSerializableRunnable(addMessage);
+
+ if (vm != null) {
+ vm.invoke(addRunnable);
+ } else {
+ invokeInEveryVM(addRunnable);
+ }
+
+ logger.info(addMessage);
+ expectedExceptionStrings.add(expectedOutput);
+ return expectedOutput;
+ }
+
+ static ExpectedExceptionString poll() {
+ return expectedExceptionStrings.poll();
+ }
+
+ @SuppressWarnings("serial")
+ private static SerializableRunnable newAddSerializableRunnable(final String addMessage) {
+ return new SerializableRunnable("addExpectedExceptionString") {
+ public void run() {
+ logger.info(addMessage);
+ }
+ };
+ }
+
+ @SuppressWarnings("serial")
+ private static SerializableRunnable newRemoveSerializableRunnable(final String removeMessage) {
+ return new SerializableRunnable("removeExpectedExceptionString") {
+ public void run() {
+ logger.info(removeMessage);
+ }
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Host.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Host.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Host.java
new file mode 100644
index 0000000..6d69436
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Host.java
@@ -0,0 +1,201 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.test.dunit;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * <P>This class represents a host on which a remote method may be
+ * invoked. It provides access to the VMs and GemFire systems that
+ * run on that host.</P>
+ *
+ * <P>Additionally, it provides access to the Java RMI registry that
+ * runs on the host. By default, an RMI registry is only started on
+ * the host on which Hydra's Master VM runs. RMI registries may be
+ * started on other hosts via additional Hydra configuration.</P>
+ *
+ * @author David Whitlock
+ *
+ */
+public abstract class Host implements java.io.Serializable {
+
+ /** The available hosts */
+ protected static List hosts = new ArrayList();
+
+ private static VM locator;
+
+ /** Indicates an unstarted RMI registry */
+ protected static int NO_REGISTRY = -1;
+
+ //////////////////// Instance Fields ////////////////////
+
+ /** The name of this host machine */
+ private String hostName;
+
+ /** The VMs that run on this host */
+ private List vms;
+
+ /** The GemFire systems that are available on this host */
+ private List systems;
+
+ /** Key is system name, value is GemFireSystem instance */
+ private HashMap systemNames;
+
+ //////////////////// Static Methods /////////////////////
+
+ /**
+ * Returns the number of known hosts
+ */
+ public static int getHostCount() {
+ return hosts.size();
+ }
+
+ /**
+ * Makes note of a new <code>Host</code>
+ */
+ protected static void addHost(Host host) {
+ hosts.add(host);
+ }
+
+ /**
+ * Returns a given host
+ *
+ * @param n
+ * A zero-based identifier of the host
+ *
+ * @throws IllegalArgumentException
+ * <code>n</code> is more than the number of hosts
+ */
+ public static Host getHost(int n) {
+ int size = hosts.size();
+ if (n >= size) {
+ String s = "Cannot request host " + n + ". There are only " +
+ size + " hosts.";
+ throw new IllegalArgumentException(s);
+
+ } else {
+ return (Host) hosts.get(n);
+ }
+ }
+
+ ///////////////////// Constructors //////////////////////
+
+ /**
+ * Creates a new <code>Host</code> with the given name
+ */
+ protected Host(String hostName) {
+ if (hostName == null) {
+ String s = "Cannot create a Host with a null name";
+ throw new NullPointerException(s);
+ }
+
+ this.hostName = hostName;
+ this.vms = new ArrayList();
+ this.systems = new ArrayList();
+ this.systemNames = new HashMap();
+ }
+
+ //////////////////// Instance Methods ////////////////////
+
+ /**
+ * Returns the machine name of this host
+ */
+ public String getHostName() {
+ return this.hostName;
+ }
+
+ /**
+ * Returns the number of VMs that run on this host
+ */
+ public int getVMCount() {
+ return this.vms.size();
+ }
+
+ /**
+ * Returns a VM that runs on this host
+ *
+ * @param n
+ * A zero-based identifier of the VM
+ *
+ * @throws IllegalArgumentException
+ * <code>n</code> is more than the number of VMs
+ */
+ public VM getVM(int n) {
+ int size = vms.size();
+ if (n >= size) {
+ String s = "Cannot request VM " + n + ". There are only " +
+ size + " VMs on " + this;
+ throw new IllegalArgumentException(s);
+
+ } else {
+ return (VM) vms.get(n);
+ }
+ }
+
+ /**
+ * Adds a VM to this <code>Host</code> with the given process id and client record.
+ */
+ protected void addVM(int pid, RemoteDUnitVMIF client) {
+ VM vm = new VM(this, pid, client);
+ this.vms.add(vm);
+ }
+
+ public static VM getLocator() {
+ return locator;
+ }
+
+ private static void setLocator(VM l) {
+ locator = l;
+ }
+
+ protected void addLocator(int pid, RemoteDUnitVMIF client) {
+ setLocator(new VM(this, pid, client));
+ }
+
+ /**
+ * Returns the number of GemFire systems that run on this host
+ */
+ public int getSystemCount() {
+ return this.systems.size();
+ }
+
+ //////////////////// Utility Methods ////////////////////
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer("Host ");
+ sb.append(this.getHostName());
+ sb.append(" with ");
+ sb.append(getVMCount());
+ sb.append(" VMs");
+ return sb.toString();
+ }
+
+ /**
+ * Two <code>Host</code>s are considered equal if they have the same
+ * name.
+ */
+ public boolean equals(Object o) {
+ if (o instanceof Host) {
+ return ((Host) o).getHostName().equals(this.getHostName());
+
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * A <code>Host</code>'s hash code is based on the hash code of its
+ * name.
+ */
+ public int hashCode() {
+ return this.getHostName().hashCode();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Invoke.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Invoke.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Invoke.java
new file mode 100755
index 0000000..bd9eaf6
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Invoke.java
@@ -0,0 +1,146 @@
+package com.gemstone.gemfire.test.dunit;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A set of remote invocation methods useful for writing tests.
+ * <pr/>
+ * These methods can be used directly:
+ * <code>Invoke.invokeInEveryVM(...)</code>, however, they read better if they
+ * are referenced through static import:
+ *
+ * <pre>
+ * import static com.gemstone.gemfire.test.dunit.Invoke.*;
+ * ...
+ * invokeInEveryVM(...);
+ * </pre>
+ * <pr/>
+ * Extracted from DistributedTestCase
+ *
+ * @see VM
+ * @see SerializableCallable
+ * @see SerializableRunnable
+ * @see RepeatableRunnable
+ */
+public class Invoke {
+
+ protected Invoke() {
+ }
+
+ /**
+ * Invokes a <code>SerializableRunnable</code> in every VM that DUnit knows about.
+ *
+ * @see VM#invoke(Runnable)
+ */
+ public static void invokeInEveryVM(final SerializableRunnable work) {
+ for (int h = 0; h < Host.getHostCount(); h++) {
+ Host host = Host.getHost(h);
+
+ for (int v = 0; v < host.getVMCount(); v++) {
+ VM vm = host.getVM(v);
+ vm.invoke(work);
+ }
+ }
+ }
+
+ public static void invokeInLocator(final SerializableRunnable work) {
+ Host.getLocator().invoke(work);
+ }
+
+ /**
+ * Invokes a <code>SerializableCallable</code> in every VM that DUnit knows about.
+ *
+ * @return a Map of results, where the key is the VM and the value is the result for that VM
+ * @see VM#invoke(java.util.concurrent.Callable)
+ */
+ public static Map<VM, Object> invokeInEveryVM(final SerializableCallable<?> work) {
+ final Map<VM, Object> results = new HashMap<VM, Object>();
+ for (int h = 0; h < Host.getHostCount(); h++) {
+ Host host = Host.getHost(h);
+ for (int v = 0; v < host.getVMCount(); v++) {
+ VM vm = host.getVM(v);
+ results.put(vm, vm.invoke(work));
+ }
+ }
+ return results;
+ }
+
+ /**
+ * Invokes a method in every remote VM that DUnit knows about.
+ *
+ * @see VM#invoke(Class, String)
+ */
+ public static void invokeInEveryVM(final Class<?> theClass, final String methodName) {
+ for (int h = 0; h < Host.getHostCount(); h++) {
+ Host host = Host.getHost(h);
+ for (int v = 0; v < host.getVMCount(); v++) {
+ VM vm = host.getVM(v);
+ vm.invoke(theClass, methodName);
+ }
+ }
+ }
+
+ /**
+ * Invokes a method in every remote VM that DUnit knows about.
+ *
+ * @see VM#invoke(Class, String)
+ */
+ public static void invokeInEveryVM(final Class<?> theClass, final String methodName, final Object[] methodArgs) {
+ for (int h = 0; h < Host.getHostCount(); h++) {
+ Host host = Host.getHost(h);
+ for (int v = 0; v < host.getVMCount(); v++) {
+ VM vm = host.getVM(v);
+ vm.invoke(theClass, methodName, methodArgs);
+ }
+ }
+ }
+
+ public static void invokeRepeatingIfNecessary(final VM vm, final RepeatableRunnable task) {
+ vm.invokeRepeatingIfNecessary(task, 0);
+ }
+
+ /**
+ * For ACK scopes, no repeat should be necessary.
+ *
+ * @param vm
+ * @param task
+ * @param repeatTimeoutMs the number of milliseconds to try repeating validation code in the
+ * event that AssertionFailedError is thrown.
+ */
+ public static void invokeRepeatingIfNecessary(final VM vm, final RepeatableRunnable task, final long repeatTimeoutMs) {
+ vm.invokeRepeatingIfNecessary(task, repeatTimeoutMs);
+ }
+
+ /**
+ * Invokes a <code>SerializableRunnable</code> in every VM that
+ * DUnit knows about. If work.run() throws an assertion failure,
+ * its execution is repeated, until no assertion failure occurs or
+ * repeatTimeout milliseconds have passed.
+ *
+ * @see VM#invoke(Runnable)
+ */
+ public static void invokeInEveryVMRepeatingIfNecessary(final RepeatableRunnable work) {
+ invokeInEveryVMRepeatingIfNecessary(work, 0);
+ }
+
+ public static void invokeInEveryVMRepeatingIfNecessary(final RepeatableRunnable work, final long repeatTimeoutMs) {
+ for (int h = 0; h < Host.getHostCount(); h++) {
+ Host host = Host.getHost(h);
+ for (int v = 0; v < host.getVMCount(); v++) {
+ VM vm = host.getVM(v);
+ vm.invokeRepeatingIfNecessary(work, repeatTimeoutMs);
+ }
+ }
+ }
+
+ /** Return the total number of VMs on all hosts */
+ public static int getVMCount() {
+ int count = 0;
+ for (int h = 0; h < Host.getHostCount(); h++) {
+ Host host = Host.getHost(h);
+ count += host.getVMCount();
+ }
+ return count;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Jitter.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Jitter.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Jitter.java
new file mode 100755
index 0000000..446b4bf
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Jitter.java
@@ -0,0 +1,70 @@
+package com.gemstone.gemfire.test.dunit;
+
+import java.util.Random;
+
+/**
+ * Extracted from DistributedTestCase
+ */
+public class Jitter {
+
+ /**
+ * If true, we randomize the amount of time we wait
+ */
+ private static final boolean USE_JITTER = true;
+
+ private static final Random jitter = new Random();
+
+ protected Jitter() {
+ }
+
+ /**
+ * Returns an adjusted interval from <code>minimum()</code to
+ * <code>intervalMillis</code> milliseconds. If jittering is disabled then
+ * the value returned will be equal to intervalMillis.
+ *
+ * @param intervalMillis
+ * @return adjust milliseconds to use as interval for WaitCriteria polling
+ */
+ static long jitterInterval(final long intervalMillis) {
+ if (USE_JITTER) {
+ return adjustIntervalIfJitterIsEnabled(intervalMillis);
+ } else {
+ return intervalMillis;
+ }
+ }
+
+ static int minimum() {
+ return 10;
+ }
+
+ static int maximum() {
+ return 5000;
+ }
+
+ /**
+ * If jittering is enabled then returns a jittered interval up to a maximum
+ * of <code>intervalMillis</code> milliseconds, inclusive.
+ *
+ * If jittering is disabled then returns <code>intervalMillis</code>.
+ *
+ * The result is bounded by 50 ms as a minimum and 5000 ms as a maximum.
+ *
+ * @param ms total amount of time to wait
+ * @return randomized interval we should wait
+ */
+ private static int adjustIntervalIfJitterIsEnabled(final long intervalMillis) {
+ final int minLegal = minimum();
+ final int maxLegal = maximum();
+
+ if (intervalMillis <= minLegal) {
+ return (int)intervalMillis; // Don't ever jitter anything below this.
+ }
+
+ int maxValue = maxLegal;
+ if (intervalMillis < maxLegal) {
+ maxValue = (int)intervalMillis;
+ }
+
+ return minLegal + jitter.nextInt(maxValue - minLegal + 1);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/RMIException.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/RMIException.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/RMIException.java
new file mode 100644
index 0000000..d08ac25
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/RMIException.java
@@ -0,0 +1,161 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.test.dunit;
+
+import com.gemstone.gemfire.GemFireException;
+
+/**
+ * This exception is thrown when an exception occurs during a remote
+ * method invocation. This {@link RuntimeException} wraps the actual
+ * exception. It allows distributed unit tests to verify that an
+ * exception was thrown in a different VM.
+ *
+ * <PRE>
+ * VM vm0 = host0.getVM(0);
+ * try {
+ * vm.invoke(this.getClass(), "getUnknownObject");
+ *
+ * } catch (RMIException ex) {
+ * assertEquals(ex.getCause() instanceof ObjectException);
+ * }
+ * </PRE>
+ *
+ * Note that special steps are taken so that the stack trace of the
+ * cause exception reflects the call stack on the remote machine.
+ * The stack trace of the exception returned by {@link #getCause()}
+ * may not be available.
+ *
+ * @see hydra.RemoteTestModuleIF
+ *
+ * @author David Whitlock
+ *
+ */
+public class RMIException extends GemFireException {
+
+ /** SHADOWED FIELD that holds the cause exception (as opposed to the
+ * HokeyException */
+ private Throwable cause;
+
+ /** The name of the method being invoked */
+ private String methodName;
+
+ /** The name of the class (or class of the object type) whose method
+ * was being invoked */
+ private String className;
+
+ /** The type of exception that was thrown in the remote VM */
+ private String exceptionClassName;
+
+ /** Stack trace for the exception that was thrown in the remote VM */
+ private String stackTrace;
+
+ /** The VM in which the method was executing */
+ private VM vm;
+
+ //////////////////////// Constructors ////////////////////////
+
+ /**
+ * Creates a new <code>RMIException</code> that was caused by a
+ * given <code>Throwable</code> while invoking a given method.
+ */
+ public RMIException(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.
+ *
+ * @param vm
+ * The VM in which the method was executing
+ * @param className
+ * The name of the class whose method was being invoked
+ * remotely
+ * @param methodName
+ * The name of the method that was being invoked remotely
+ * @param cause
+ * The type of exception that was thrown in the remote VM
+ * @param stackTrace
+ * The stack trace of the exception from the remote VM
+ */
+ public RMIException(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.
+ */
+ public String getExceptionClassName() {
+ return this.exceptionClassName;
+ }
+
+// /**
+// * Returns the stack trace for the exception that was thrown in a
+// * remote method invocation.
+// */
+// public String getStackTrace() {
+// return this.stackTrace;
+// }
+
+ /**
+ * Returns the cause of this exception. Note that this is not
+ * necessarily the exception that gets printed out with the stack
+ * trace.
+ */
+ public Throwable getCause() {
+ return this.cause;
+ }
+
+ /**
+ * Returns the VM in which the remote method was invoked
+ */
+ public VM getVM() {
+ return this.vm;
+ }
+
+ ////////////////////// Inner Classes //////////////////////
+
+ /**
+ * A hokey exception class that makes it looks like we have a real
+ * cause exception.
+ */
+ private static class HokeyException extends Throwable {
+ private String stackTrace;
+ private String toString;
+
+ HokeyException(Throwable cause, String stackTrace) {
+ this.toString = cause.toString();
+ this.stackTrace = stackTrace;
+ }
+
+ public void printStackTrace(java.io.PrintWriter pw) {
+ pw.print(this.stackTrace);
+ pw.flush();
+ }
+
+ public String toString() {
+ return this.toString;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/RemoteDUnitVMIF.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/RemoteDUnitVMIF.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/RemoteDUnitVMIF.java
new file mode 100644
index 0000000..412aeac
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/RemoteDUnitVMIF.java
@@ -0,0 +1,18 @@
+package com.gemstone.gemfire.test.dunit;
+
+import hydra.MethExecutorResult;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+public interface RemoteDUnitVMIF extends Remote {
+
+ MethExecutorResult executeMethodOnObject(Object o, String methodName) throws RemoteException;
+
+ MethExecutorResult executeMethodOnObject(Object o, String methodName,
+ Object[] args) throws RemoteException;
+
+ MethExecutorResult executeMethodOnClass(String name, String methodName,
+ Object[] args) throws RemoteException;
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/RepeatableRunnable.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/RepeatableRunnable.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/RepeatableRunnable.java
new file mode 100644
index 0000000..c8952bb
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/RepeatableRunnable.java
@@ -0,0 +1,13 @@
+package com.gemstone.gemfire.test.dunit;
+
+/**
+ * A RepeatableRunnable is an object that implements a method that
+ * can be invoked repeatably without causing any side affects.
+ *
+ * @author dmonnie
+ */
+public interface RepeatableRunnable {
+
+ public void runRepeatingIfNecessary(long repeatTimeoutMs);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/SerializableCallable.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/SerializableCallable.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/SerializableCallable.java
new file mode 100644
index 0000000..2c21284
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/SerializableCallable.java
@@ -0,0 +1,61 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.test.dunit;
+
+import java.io.Serializable;
+import java.util.concurrent.Callable;
+
+/**
+ * This interface provides both {@link Serializable} and {@link
+ * Callable}. It is often used in conjunction with {@link
+ * VM#invoke(Callable)}.
+ *
+ * <PRE>
+ * public void testRepilcatedRegionPut() {
+ * final Host host = Host.getHost(0);
+ * VM vm0 = host.getVM(0);
+ * VM vm1 = host.getVM(1);
+ * final String name = this.getUniqueName();
+ * final Object value = new Integer(42);
+ *
+ * SerializableCallable putMethod = new SerializableCallable("Replicated put") {
+ * public Object call() throws Exception {
+ * ...// get replicated test region //...
+ * return region.put(name, value);
+ * }
+ * });
+ * assertNull(vm0.invoke(putMethod));
+ * assertEquals(value, vm1.invoke(putMethod));
+ * }
+ * </PRE>
+ *
+ * @author Mitch Thomas
+ */
+public abstract class SerializableCallable<T> implements Callable<T>, Serializable {
+
+ private static final long serialVersionUID = -5914706166172952484L;
+
+ private String name;
+
+ public SerializableCallable() {
+ this.name = null;
+ }
+
+ public SerializableCallable(String name) {
+ this.name = name;
+ }
+
+ public String toString() {
+ if (this.name != null) {
+ return "\"" + this.name + "\"";
+
+ } else {
+ return super.toString();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/SerializableRunnable.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/SerializableRunnable.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/SerializableRunnable.java
new file mode 100644
index 0000000..28eabc3
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/SerializableRunnable.java
@@ -0,0 +1,83 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.test.dunit;
+
+import java.io.Serializable;
+
+/**
+ * This interface provides both {@link Serializable} and {@link
+ * Runnable}. It is often used in conjunction with {@link
+ * VM#invoke(Runnable)}.
+ *
+ * <PRE>
+ * public void testRegionPutGet() {
+ * final Host host = Host.getHost(0);
+ * VM vm0 = host.getVM(0);
+ * VM vm1 = host.getVM(1);
+ * final String name = this.getUniqueName();
+ * final Object value = new Integer(42);
+ *
+ * vm0.invoke(new SerializableRunnable("Put value") {
+ * public void run() {
+ * ...// get the region //...
+ * region.put(name, value);
+ * }
+ * });
+ * vm1.invoke(new SerializableRunnable("Get value") {
+ * public void run() {
+ * ...// get the region //...
+ * assertEquals(value, region.get(name));
+ * }
+ * });
+ * }
+ * </PRE>
+ */
+public abstract class SerializableRunnable
+ implements Serializable, Runnable {
+
+ private static final long serialVersionUID = 7584289978241650456L;
+
+ private String name;
+
+ public SerializableRunnable() {
+ this.name = null;
+ }
+
+ /**
+ * This constructor lets you do the following:
+ *
+ * <PRE>
+ * vm.invoke(new SerializableRunnable("Do some work") {
+ * public void run() {
+ * // ...
+ * }
+ * });
+ * </PRE>
+ */
+ public SerializableRunnable(String name) {
+ this.name = name;
+ }
+
+ public void setName(String newName) {
+ this.name = newName;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public String toString() {
+ if (this.name != null) {
+ return "\"" + this.name + "\"";
+
+ } else {
+ return super.toString();
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/StoppableWaitCriterion.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/StoppableWaitCriterion.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/StoppableWaitCriterion.java
new file mode 100755
index 0000000..b1e0d88
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/StoppableWaitCriterion.java
@@ -0,0 +1,12 @@
+package com.gemstone.gemfire.test.dunit;
+
+/**
+ * Extracted from DistributedTestCase
+ */
+public interface StoppableWaitCriterion extends WaitCriterion {
+ /**
+ * If this method returns true then quit waiting even if we are not done.
+ * This allows a wait to fail early.
+ */
+ public boolean stopWaiting();
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/ThreadDump.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/ThreadDump.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/ThreadDump.java
new file mode 100755
index 0000000..acf43b9
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/ThreadDump.java
@@ -0,0 +1,157 @@
+package com.gemstone.gemfire.test.dunit;
+
+import static com.gemstone.gemfire.test.dunit.Jitter.*;
+import static org.junit.Assert.fail;
+
+import com.gemstone.gemfire.LogWriter;
+import com.gemstone.gemfire.internal.OSProcess;
+import com.gemstone.gemfire.internal.logging.LocalLogWriter;
+import com.gemstone.gemfire.internal.logging.LogWriterImpl;
+
+/**
+ * A set of thread dump methods useful for writing tests.
+ * <pr/>
+ * These methods can be used directly:
+ * <code>ThreadDump.dumpStack(...)</code>, however, they read better if they
+ * are referenced through static import:
+ *
+ * <pre>
+ * import static com.gemstone.gemfire.test.dunit.ThreadDump.*;
+ * ...
+ * dumpStack(...);
+ * </pre>
+ * <pr/>
+ * Extracted from DistributedTestCase
+ *
+ * @see VM
+ * @see Host
+ */
+@SuppressWarnings("serial")
+public class ThreadDump {
+
+ protected ThreadDump() {
+ }
+
+ /**
+ * Print a stack dump for this vm
+ *
+ * @author bruce
+ * @since 5.0
+ */
+ public static void dumpStack() {
+ com.gemstone.gemfire.internal.OSProcess.printStacks(0, false);
+ }
+
+ /**
+ * Print a stack dump for the given vm
+ *
+ * @author bruce
+ * @since 5.0
+ */
+ public static void dumpStack(final VM vm) {
+ vm.invoke(dumpStackSerializableRunnable());
+ }
+
+ /**
+ * Print stack dumps for all vms on the given host
+ *
+ * @author bruce
+ * @since 5.0
+ */
+ public static void dumpStack(final Host host) {
+ for (int v=0; v < host.getVMCount(); v++) {
+ host.getVM(v).invoke(dumpStackSerializableRunnable());
+ }
+ }
+
+ /**
+ * Print stack dumps for all vms on all hosts
+ *
+ * @author bruce
+ * @since 5.0
+ */
+ public static void dumpAllStacks() {
+ for (int h=0; h < Host.getHostCount(); h++) {
+ dumpStack(Host.getHost(h));
+ }
+ }
+
+ public static void dumpStackTrace(final Thread thread, final StackTraceElement[] stack, final LogWriter logWriter) { // TODO: remove LogWriter
+ StringBuilder msg = new StringBuilder();
+ msg.append("Thread=<")
+ .append(thread)
+ .append("> stackDump:\n");
+ for (int i=0; i < stack.length; i++) {
+ msg.append("\t")
+ .append(stack[i])
+ .append("\n");
+ }
+ logWriter.info(msg.toString());
+ }
+
+ /**
+ * Dump all thread stacks
+ */
+ public static void dumpMyThreads(final LogWriter logWriter) { // TODO: remove LogWriter
+ OSProcess.printStacks(0, false);
+ }
+
+ /**
+ * Wait for a thread to join
+ * @param t thread to wait on
+ * @param ms maximum time to wait
+ * @throws AssertionFailure if the thread does not terminate
+ */
+ static public void join(Thread t, long ms, LogWriter logger) {
+ final long tilt = System.currentTimeMillis() + ms;
+ final long incrementalWait = jitterInterval(ms);
+ final long start = System.currentTimeMillis();
+ for (;;) {
+ // I really do *not* understand why this check is necessary
+ // but it is, at least with JDK 1.6. According to the source code
+ // and the javadocs, one would think that join() would exit immediately
+ // if the thread is dead. However, I can tell you from experimentation
+ // that this is not the case. :-( djp 2008-12-08
+ if (!t.isAlive()) {
+ break;
+ }
+ try {
+ t.join(incrementalWait);
+ } catch (InterruptedException e) {
+ fail("interrupted");
+ }
+ if (System.currentTimeMillis() >= tilt) {
+ break;
+ }
+ } // for
+ if (logger == null) {
+ logger = new LocalLogWriter(LogWriterImpl.INFO_LEVEL, System.out);
+ }
+ if (t.isAlive()) {
+ logger.info("HUNG THREAD");
+ dumpStackTrace(t, t.getStackTrace(), logger);
+ dumpMyThreads(logger);
+ t.interrupt(); // We're in trouble!
+ fail("Thread did not terminate after " + ms + " ms: " + t);
+// getLogWriter().warning("Thread did not terminate"
+// /* , new Exception()*/
+// );
+ }
+ long elapsedMs = (System.currentTimeMillis() - start);
+ if (elapsedMs > 0) {
+ String msg = "Thread " + t + " took "
+ + elapsedMs
+ + " ms to exit.";
+ logger.info(msg);
+ }
+ }
+
+ private static SerializableRunnable dumpStackSerializableRunnable() {
+ return new SerializableRunnable() {
+ @Override
+ public void run() {
+ dumpStack();
+ }
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/VM.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/VM.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/VM.java
new file mode 100644
index 0000000..f850184
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/VM.java
@@ -0,0 +1,1333 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.test.dunit;
+
+import hydra.MethExecutorResult;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.rmi.RemoteException;
+import java.util.concurrent.Callable;
+
+/**
+ * This class represents a Java Virtual Machine that runs on a host.
+ *
+ * @author David Whitlock
+ *
+ */
+public class VM implements java.io.Serializable {
+
+ /** The host on which this VM runs */
+ private Host host;
+
+ /** The process id of this VM */
+ private int pid;
+
+ /** The hydra client for this VM */
+ private RemoteDUnitVMIF client;
+
+ /** The state of this VM */
+ private volatile boolean available;
+
+ //////////////////// Constructors ////////////////////
+
+ /**
+ * Creates a new <code>VM</code> that runs on a given host with a
+ * given process id.
+ */
+ public VM(Host host, int pid, RemoteDUnitVMIF client) {
+ this.host = host;
+ this.pid = pid;
+ this.client = client;
+ this.available = true;
+ }
+
+ ////////////////////// Accessors //////////////////////
+
+ /**
+ * Returns the host on which this <code>VM</code> runs
+ */
+ public Host getHost() {
+ return this.host;
+ }
+
+ /**
+ * Returns the process id of this <code>VM</code>
+ */
+ public int getPid() {
+ return this.pid;
+ }
+
+ ///////////////// Remote Method Invocation ///////////////
+
+ /**
+ * Invokes a static zero-arg method with an {@link Object} or
+ * <code>void</code> return type in this VM. If the return type of
+ * the method is <code>void</code>, <code>null</code> is returned.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public Object invoke(Class c, String methodName) {
+ return invoke(c, methodName, new Object[0]);
+ }
+
+ /**
+ * Asynchronously invokes a static zero-arg method with an {@link
+ * Object} or <code>void</code> return type in this VM. If the
+ * return type of the method is <code>void</code>, <code>null</code>
+ * is returned.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ */
+ public AsyncInvocation invokeAsync(Class c, String methodName) {
+ return invokeAsync(c, methodName, null);
+ }
+
+ /**
+ * Invokes a static method with an {@link Object} or
+ * <code>void</code> return type in this VM. If the return type of
+ * the method is <code>void</code>, <code>null</code> is returned.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public Object invoke(Class c, String methodName, Object[] args) {
+ if (!this.available) {
+ String s = "VM not available: " + this;
+ throw new RMIException(this, c.getName(), methodName,
+ new IllegalStateException(s));
+ }
+ MethExecutorResult result = null;
+ int retryCount = 120;
+ do {
+ try {
+ result = this.client.executeMethodOnClass(c.getName(), methodName, args);
+ break; // out of while loop
+ } catch( RemoteException e ) {
+ boolean isWindows = false;
+ String os = System.getProperty("os.name");
+ if (os != null) {
+ if (os.indexOf("Windows") != -1) {
+ isWindows = true;
+ }
+ }
+ if (isWindows && retryCount-- > 0) {
+ boolean interrupted = Thread.interrupted();
+ try { Thread.sleep(1000); } catch (InterruptedException ignore) {interrupted = true;}
+ finally {
+ if (interrupted) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ } else {
+ throw new RMIException(this, c.getName(), methodName, e );
+ }
+ }
+ } while (true);
+
+ if (!result.exceptionOccurred()) {
+ return result.getResult();
+
+ } else {
+ Throwable thr = result.getException();
+ throw new RMIException(this, c.getName(), methodName, thr,
+ result.getStackTrace());
+ }
+ }
+
+ /**
+ * Asynchronously invokes a static method with an {@link Object} or
+ * <code>void</code> return type in this VM. If the return type of
+ * the method is <code>void</code>, <code>null</code> is returned.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ */
+ public AsyncInvocation invokeAsync(final Class c,
+ final String methodName,
+ final Object[] args) {
+ AsyncInvocation ai =
+ new AsyncInvocation(c, methodName, new Runnable() {
+ public void run() {
+ final Object o = invoke(c, methodName, args);
+ AsyncInvocation.setReturnValue(o);
+ }
+ });
+ ai.start();
+ return ai;
+ }
+
+ /**
+ * Asynchronously invokes an instance method with an {@link Object} or
+ * <code>void</code> return type in this VM. If the return type of
+ * the method is <code>void</code>, <code>null</code> is returned.
+ *
+ * @param o
+ * The object on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ */
+ public AsyncInvocation invokeAsync(final Object o,
+ final String methodName,
+ final Object[] args) {
+ AsyncInvocation ai =
+ new AsyncInvocation(o, methodName, new Runnable() {
+ public void run() {
+ final Object ret = invoke(o, methodName, args);
+ AsyncInvocation.setReturnValue(ret);
+ }
+ });
+ ai.start();
+ return ai;
+ }
+
+ /**
+ * Invokes the <code>run</code> method of a {@link Runnable} in this
+ * VM. Recall that <code>run</code> takes no arguments and has no
+ * return value.
+ *
+ * @param r
+ * The <code>Runnable</code> to be run
+ *
+ * @see SerializableRunnable
+ */
+ public AsyncInvocation invokeAsync(Runnable r) {
+ return invokeAsync(r, "run", new Object[0]);
+ }
+
+ /**
+ * Invokes the <code>call</code> method of a {@link Runnable} in this
+ * VM.
+ *
+ * @param c
+ * The <code>Callable</code> to be run
+ *
+ * @see SerializableCallable
+ */
+ public AsyncInvocation invokeAsync(Callable c) {
+ return invokeAsync(c, "call", new Object[0]);
+ }
+
+ /**
+ * Invokes the <code>run</code> method of a {@link Runnable} in this
+ * VM. Recall that <code>run</code> takes no arguments and has no
+ * return value.
+ *
+ * @param r
+ * The <code>Runnable</code> to be run
+ *
+ * @see SerializableRunnable
+ */
+ public void invoke(Runnable r) {
+ invoke(r, "run");
+ }
+
+ /**
+ * Invokes the <code>run</code> method of a {@link Runnable} in this
+ * VM. Recall that <code>run</code> takes no arguments and has no
+ * return value.
+ *
+ * @param c
+ * The <code>Callable</code> to be run
+ *
+ * @see SerializableCallable
+ */
+ public Object invoke(Callable c) {
+ return invoke(c, "call");
+ }
+
+ /**
+ * Invokes the <code>run</code method of a {@link Runnable} in this
+ * VM. If the invocation throws AssertionFailedError, and repeatTimeoutMs
+ * is >0, the <code>run</code> method is invoked repeatedly until it
+ * either succeeds, or repeatTimeoutMs has passed. The AssertionFailedError
+ * is thrown back to the sender of this method if <code>run</code> has not
+ * completed successfully before repeatTimeoutMs has passed.
+ */
+ public void invokeRepeatingIfNecessary(RepeatableRunnable o, long repeatTimeoutMs) {
+ invoke(o, "runRepeatingIfNecessary", new Object[] {new Long(repeatTimeoutMs)});
+ }
+
+ /**
+ * Invokes an instance method with no arguments on an object that is
+ * serialized into this VM. The return type of the method can be
+ * either {@link Object} or <code>void</code>. If the return type
+ * of the method is <code>void</code>, <code>null</code> is
+ * returned.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public Object invoke(Object o, String methodName) {
+ return invoke(o, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method can be either {@link
+ * Object} or <code>void</code>. If the return type of the method
+ * is <code>void</code>, <code>null</code> is returned.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public Object invoke(Object o, String methodName, Object[] args) {
+ if (!this.available) {
+ String s = "VM not available: " + this;
+ throw new RMIException(this, o.getClass().getName(), methodName,
+ new IllegalStateException(s));
+ }
+ MethExecutorResult result = null;
+ int retryCount = 120;
+ do {
+ try {
+ if ( args == null )
+ result = this.client.executeMethodOnObject(o, methodName);
+ else
+ result = this.client.executeMethodOnObject(o, methodName, args);
+ break; // out of while loop
+ } catch( RemoteException e ) {
+ if (retryCount-- > 0) {
+ boolean interrupted = Thread.interrupted();
+ try { Thread.sleep(1000); } catch (InterruptedException ignore) {interrupted = true;}
+ finally {
+ if (interrupted) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ } else {
+ throw new RMIException(this, o.getClass().getName(), methodName, e );
+ }
+ }
+ } while (true);
+
+ if (!result.exceptionOccurred()) {
+ return result.getResult();
+
+ } else {
+ Throwable thr = result.getException();
+ throw new RMIException(this, o.getClass().getName(), methodName, thr,
+ result.getStackTrace());
+ }
+ }
+
+ /**
+ * Invokes the <code>main</code> method of a given class
+ *
+ * @param c
+ * The class on which to invoke the <code>main</code> method
+ * @param args
+ * The "command line" arguments to pass to the
+ * <code>main</code> method
+ */
+ public void invokeMain(Class c, String[] args) {
+ Object[] stupid = new Object[] { args };
+ invoke(c, "main", stupid);
+ }
+
+ /**
+ * Asynchronously invokes the <code>main</code> method of a given
+ * class
+ *
+ * @param c
+ * The class on which to invoke the <code>main</code> method
+ * @param args
+ * The "command line" arguments to pass to the
+ * <code>main</code> method
+ */
+ public AsyncInvocation invokeMainAsync(Class c, String[] args) {
+ Object[] stupid = new Object[] { args };
+ return invokeAsync(c, "main", stupid);
+ }
+
+ /**
+ * Invokes a static method with a <code>boolean</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>boolean</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public boolean invokeBoolean(Class c, String methodName) {
+ return invokeBoolean(c, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes a static method with a <code>boolean</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>boolean</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public boolean invokeBoolean(Class c, String methodName, Object[] args) {
+ Object result = invoke(c, methodName, args);
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a boolean";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Boolean) {
+ return ((Boolean) result).booleanValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a boolean";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>boolean</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>boolean</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public boolean invokeBoolean(Object o, String methodName) {
+ return invokeBoolean(o, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>boolean</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>boolean</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public boolean invokeBoolean(Object o, String methodName, Object[] args) {
+ Object result = invoke(o, methodName, args);
+ Class c = o.getClass();
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a boolean";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Boolean) {
+ return ((Boolean) result).booleanValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a boolean";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes a static method with a <code>char</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>char</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public char invokeChar(Class c, String methodName) {
+ return invokeChar(c, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes a static method with a <code>char</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>char</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public char invokeChar(Class c, String methodName, Object[] args) {
+ Object result = invoke(c, methodName, args);
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a char";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Character) {
+ return ((Character) result).charValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a char";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>char</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>char</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public char invokeChar(Object o, String methodName) {
+ return invokeChar(o, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>char</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>char</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public char invokeChar(Object o, String methodName, Object[] args) {
+ Object result = invoke(o, methodName, args);
+ Class c = o.getClass();
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a char";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Character) {
+ return ((Character) result).charValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a char";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes a static method with a <code>byte</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>byte</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public byte invokeByte(Class c, String methodName) {
+ return invokeByte(c, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes a static method with a <code>byte</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>byte</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public byte invokeByte(Class c, String methodName, Object[] args) {
+ Object result = invoke(c, methodName, args);
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a byte";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Byte) {
+ return ((Byte) result).byteValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a byte";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>byte</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>byte</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public byte invokeByte(Object o, String methodName) {
+ return invokeByte(o, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>byte</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>byte</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public byte invokeByte(Object o, String methodName, Object[] args) {
+ Object result = invoke(o, methodName, args);
+ Class c = o.getClass();
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a byte";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Byte) {
+ return ((Byte) result).byteValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a byte";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes a static method with a <code>short</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>short</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public short invokeShort(Class c, String methodName) {
+ return invokeShort(c, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes a static method with a <code>short</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>short</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public short invokeShort(Class c, String methodName, Object[] args) {
+ Object result = invoke(c, methodName, args);
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a short";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Short) {
+ return ((Short) result).shortValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a short";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>short</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>short</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public short invokeShort(Object o, String methodName) {
+ return invokeShort(o, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>short</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>short</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public short invokeShort(Object o, String methodName, Object[] args) {
+ Object result = invoke(o, methodName, args);
+ Class c = o.getClass();
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a short";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Short) {
+ return ((Short) result).shortValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a short";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes a static method with a <code>int</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>int</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public int invokeInt(Class c, String methodName) {
+ return invokeInt(c, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes a static method with a <code>int</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>int</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public int invokeInt(Class c, String methodName, Object[] args) {
+ Object result = invoke(c, methodName, args);
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a int";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Integer) {
+ return ((Integer) result).intValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a int";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>int</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>int</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public int invokeInt(Object o, String methodName) {
+ return invokeInt(o, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>int</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>int</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public int invokeInt(Object o, String methodName, Object[] args) {
+ Object result = invoke(o, methodName, args);
+ Class c = o.getClass();
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a int";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Integer) {
+ return ((Integer) result).intValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a int";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes a static method with a <code>long</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>long</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public long invokeLong(Class c, String methodName) {
+ return invokeLong(c, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes a static method with a <code>long</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>long</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public long invokeLong(Class c, String methodName, Object[] args) {
+ Object result = invoke(c, methodName, args);
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a long";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Long) {
+ return ((Long) result).longValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a long";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>long</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>long</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public long invokeLong(Object o, String methodName) {
+ return invokeLong(o, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>long</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>long</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public long invokeLong(Object o, String methodName, Object[] args) {
+ Object result = invoke(o, methodName, args);
+ Class c = o.getClass();
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a long";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Long) {
+ return ((Long) result).longValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a long";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes a static method with a <code>float</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>float</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public float invokeFloat(Class c, String methodName) {
+ return invokeFloat(c, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes a static method with a <code>float</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>float</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public float invokeFloat(Class c, String methodName, Object[] args) {
+ Object result = invoke(c, methodName, args);
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a float";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Float) {
+ return ((Float) result).floatValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a float";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>float</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>float</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public float invokeFloat(Object o, String methodName) {
+ return invokeFloat(o, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>float</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>float</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public float invokeFloat(Object o, String methodName, Object[] args) {
+ Object result = invoke(o, methodName, args);
+ Class c = o.getClass();
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a float";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Float) {
+ return ((Float) result).floatValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a float";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes a static method with a <code>double</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>double</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public double invokeDouble(Class c, String methodName) {
+ return invokeDouble(c, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes a static method with a <code>double</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>double</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public double invokeDouble(Class c, String methodName, Object[] args) {
+ Object result = invoke(c, methodName, args);
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a double";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Double) {
+ return ((Double) result).doubleValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a double";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>double</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>double</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public double invokeDouble(Object o, String methodName) {
+ return invokeDouble(o, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>double</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>double</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public double invokeDouble(Object o, String methodName, Object[] args) {
+ Object result = invoke(o, methodName, args);
+ Class c = o.getClass();
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a double";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Double) {
+ return ((Double) result).doubleValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a double";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Synchronously bounces (mean kills and restarts) this <code>VM</code>.
+ * Concurrent bounce attempts are synchronized but attempts to invoke
+ * methods on a bouncing VM will cause test failure. Tests using bounce
+ * should be placed at the end of the dunit test suite, since an exception
+ * here will cause all tests using the unsuccessfully bounced VM to fail.
+ *
+ * This method is currently not supported by the standalone dunit
+ * runner.
+ *
+ * @throws RMIException if an exception occurs while bouncing this VM, for
+ * example a HydraTimeoutException if the VM fails to stop within {@link
+ * hydra.Prms#maxClientShutdownWaitSec} or restart within {@link
+ * hydra.Prms#maxClientStartupWaitSec}.
+ */
+ public synchronized void bounce() {
+ if (!this.available) {
+ String s = "VM not available: " + this;
+ throw new RMIException(this, this.getClass().getName(), "bounceVM",
+ new IllegalStateException(s));
+ }
+ this.available = false;
+ try {
+ BounceResult result = DUnitEnv.get().bounce(this.pid);
+
+ this.pid = result.getNewPid();
+ this.client = result.getNewClient();
+ this.available = true;
+ } catch (UnsupportedOperationException e) {
+ this.available = true;
+ throw e;
+ } catch (RemoteException e) {
+ StringWriter sw = new StringWriter();
+ e.printStackTrace(new PrintWriter(sw, true));
+ RMIException rmie = new RMIException(this, this.getClass().getName(),
+ "bounceVM", e, sw.toString());
+ throw rmie;
+ }
+ }
+
+ ///////////////////// Utility Methods ////////////////////
+
+ public String toString() {
+ return "VM " + this.getPid() + " running on " + this.getHost();
+ }
+
+ public static int getCurrentVMNum() {
+ return DUnitEnv.get().getVMID();
+ }
+
+ public File getWorkingDirectory() {
+ return DUnitEnv.get().getWorkingDirectory(this.getPid());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Wait.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Wait.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Wait.java
new file mode 100755
index 0000000..9653a76
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Wait.java
@@ -0,0 +1,167 @@
+package com.gemstone.gemfire.test.dunit;
+
+import static com.gemstone.gemfire.test.dunit.Jitter.jitterInterval;
+import static org.junit.Assert.fail;
+
+import com.gemstone.gemfire.internal.cache.LocalRegion;
+
+/**
+ * Extracted from DistributedTestCase
+ */
+public class Wait {
+
+ /**
+ * Wait until given criterion is met
+ *
+ * @param ev criterion to wait on
+ * @param ms total time to wait, in milliseconds
+ * @param interval pause interval between waits
+ * @param throwOnTimeout if false, don't generate an error
+ */
+ public static void waitForCriterion(final WaitCriterion ev, final long ms, final long interval, final boolean throwOnTimeout) {
+ long waitThisTime = jitterInterval(interval);
+ final long tilt = System.currentTimeMillis() + ms;
+ for (;;) {
+ if (ev.done()) {
+ return; // success
+ }
+
+ if (ev instanceof StoppableWaitCriterion) {
+ StoppableWaitCriterion ev2 = (StoppableWaitCriterion)ev;
+ if (ev2.stopWaiting()) {
+ if (throwOnTimeout) {
+ fail("stopWaiting returned true: " + ev.description());
+ }
+ return;
+ }
+ }
+
+ // Calculate time left
+ long timeLeft = tilt - System.currentTimeMillis();
+ if (timeLeft <= 0) {
+ if (!throwOnTimeout) {
+ return; // not an error, but we're done
+ }
+ fail("Event never occurred after " + ms + " ms: " + ev.description());
+ }
+
+ if (waitThisTime > timeLeft) {
+ waitThisTime = timeLeft;
+ }
+
+ // Wait a little bit
+ Thread.yield();
+ try {
+ Thread.sleep(waitThisTime);
+ } catch (InterruptedException e) {
+ fail("interrupted");
+ }
+ }
+ }
+
+ /**
+ * Wait on a mutex. This is done in a loop in order to address the
+ * "spurious wakeup" "feature" in Java.
+ *
+ * @param ev condition to test
+ * @param mutex object to lock and wait on
+ * @param ms total amount of time to wait
+ * @param interval interval to pause for the wait
+ * @param throwOnTimeout if false, no error is thrown.
+ */
+ public static void waitOnMutex(final WaitCriterion ev, final Object mutex, final long ms, final long interval, final boolean throwOnTimeout) {
+ final long tilt = System.currentTimeMillis() + ms;
+ long waitThisTime = jitterInterval(interval);
+ synchronized (mutex) {
+ for (;;) {
+ if (ev.done()) {
+ break;
+ }
+
+ long timeLeft = tilt - System.currentTimeMillis();
+ if (timeLeft <= 0) {
+ if (!throwOnTimeout) {
+ return; // not an error, but we're done
+ }
+ fail("Event never occurred after " + ms + " ms: " + ev.description());
+ }
+
+ if (waitThisTime > timeLeft) {
+ waitThisTime = timeLeft;
+ }
+
+ try {
+ mutex.wait(waitThisTime);
+ } catch (InterruptedException e) {
+ fail("interrupted");
+ }
+ } // for
+ } // synchronized
+ }
+
+ /** pause for a default interval */
+ public static void pause() {
+ pause(250);
+ }
+
+ /**
+ * Use of this function indicates a place in the tests tree where t
+ * he use of Thread.sleep() is
+ * highly questionable.
+ * <p>
+ * Some places in the system, especially those that test expirations and other
+ * timeouts, have a very good reason to call {@link Thread#sleep(long)}. The
+ * <em>other</em> places are marked by the use of this method.
+ *
+ * @param ms
+ */
+ public static final void staticPause(int ms) {
+ final long target = System.currentTimeMillis() + ms;
+ try {
+ for (;;) {
+ long msLeft = target - System.currentTimeMillis();
+ if (msLeft <= 0) {
+ break;
+ }
+ Thread.sleep(msLeft);
+ }
+ }
+ catch (InterruptedException e) {
+ throw new AssertionError("interrupted", e);
+ }
+
+ }
+
+ /**
+ * Blocks until the clock used for expiration on the given region changes.
+ */
+ public static final void waitForExpiryClockToChange(LocalRegion lr) {
+ long startTime = lr.cacheTimeMillis();
+ do {
+ Thread.yield();
+ } while (startTime == lr.cacheTimeMillis());
+ }
+
+ /** pause for specified ms interval
+ * Make sure system clock has advanced by the specified number of millis before
+ * returning.
+ */
+ public static final void pause(int ms) {
+ if (ms > 50) {
+ //getLogWriter().info("Pausing for " + ms + " ms..."/*, new Exception()*/);
+ }
+ final long target = System.currentTimeMillis() + ms;
+ try {
+ for (;;) {
+ long msLeft = target - System.currentTimeMillis();
+ if (msLeft <= 0) {
+ break;
+ }
+ Thread.sleep(msLeft);
+ }
+ }
+ catch (InterruptedException e) {
+ throw new AssertionError("interrupted", e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/WaitCriterion.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/WaitCriterion.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/WaitCriterion.java
new file mode 100755
index 0000000..493038e
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/WaitCriterion.java
@@ -0,0 +1,11 @@
+package com.gemstone.gemfire.test.dunit;
+
+/**
+ * Extracted from DistributedTestCase
+ */
+public interface WaitCriterion {
+
+ public boolean done();
+
+ public String description();
+}