You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ab...@apache.org on 2016/02/08 18:03:29 UTC
[14/50] [abbrv] incubator-geode git commit: Revert "GEODE-715: Move
dunit.standalone under com.gemstone.gemfire.test"
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/dfba327e/gemfire-core/src/test/java/dunit/standalone/ProcessManager.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/dunit/standalone/ProcessManager.java b/gemfire-core/src/test/java/dunit/standalone/ProcessManager.java
new file mode 100644
index 0000000..7fc762f
--- /dev/null
+++ b/gemfire-core/src/test/java/dunit/standalone/ProcessManager.java
@@ -0,0 +1,261 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package dunit.standalone;
+
+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.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
+import java.rmi.AccessException;
+import java.rmi.NotBoundException;
+import java.rmi.RemoteException;
+import java.rmi.registry.Registry;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.io.FileUtils;
+
+import com.gemstone.gemfire.internal.FileUtil;
+import com.gemstone.gemfire.internal.logging.LogService;
+
+import dunit.RemoteDUnitVMIF;
+
+/**
+ * @author dsmith
+ *
+ */
+public class ProcessManager {
+ private int namingPort;
+ private Map<Integer, ProcessHolder> processes = new HashMap<Integer, ProcessHolder>();
+ private File log4jConfig;
+ private int pendingVMs;
+ private Registry registry;
+ private int debugPort = Integer.getInteger("dunit.debug.basePort", 0);
+ private int suspendVM = Integer.getInteger("dunit.debug.suspendVM", -100);
+
+ public ProcessManager(int namingPort, Registry registry) {
+ this.namingPort = namingPort;
+ this.registry = registry;
+ }
+
+ public void launchVMs() throws IOException, NotBoundException {
+ log4jConfig = LogService.findLog4jConfigInCurrentDir();
+ }
+
+ public synchronized void launchVM(int vmNum) throws IOException {
+ if(processes.containsKey(vmNum)) {
+ throw new IllegalStateException("VM " + vmNum + " is already running.");
+ }
+
+ String[] cmd = buildJavaCommand(vmNum, namingPort);
+ System.out.println("Executing " + Arrays.asList(cmd));
+ File workingDir = getVMDir(vmNum);
+ try {
+ FileUtil.delete(workingDir);
+ } catch(IOException e) {
+ //This delete is occasionally failing on some platforms, maybe due to a lingering
+ //process. Allow the process to be launched anyway.
+ System.err.println("Unable to delete " + workingDir + ". Currently contains "
+ + Arrays.asList(workingDir.list()));
+ }
+ workingDir.mkdirs();
+ if (log4jConfig != null) {
+ FileUtils.copyFileToDirectory(log4jConfig, workingDir);
+ }
+
+ //TODO - delete directory contents, preferably with commons io FileUtils
+ Process process = Runtime.getRuntime().exec(cmd, null, workingDir);
+ pendingVMs++;
+ ProcessHolder holder = new ProcessHolder(process);
+ processes.put(vmNum, holder);
+ linkStreams(vmNum, holder, process.getErrorStream(), System.err);
+ linkStreams(vmNum, holder, process.getInputStream(), System.out);
+ }
+
+ public static File getVMDir(int vmNum) {
+ return new File(DUnitLauncher.DUNIT_DIR, "vm" + vmNum);
+ }
+
+ public synchronized void killVMs() {
+ for(ProcessHolder process : processes.values()) {
+ if(process != null) {
+ process.kill();
+ }
+ }
+ }
+
+ public synchronized boolean hasLiveVMs() {
+ for(ProcessHolder process : processes.values()) {
+ if(process != null && process.isAlive()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public synchronized void bounce(int vmNum) {
+ if(!processes.containsKey(vmNum)) {
+ throw new IllegalStateException("No such process " + vmNum);
+ }
+ try {
+ ProcessHolder holder = processes.remove(vmNum);
+ holder.kill();
+ holder.getProcess().waitFor();
+ launchVM(vmNum);
+ } catch (InterruptedException | IOException e) {
+ throw new RuntimeException("Unable to restart VM " + vmNum, e);
+ }
+ }
+
+ private void linkStreams(final int vmNum, final ProcessHolder holder, final InputStream in, final PrintStream out) {
+ Thread ioTransport = new Thread() {
+ public void run() {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+ String vmName = (vmNum==-2)? "[locator]" : "[vm_"+vmNum+"]";
+ 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(!holder.isKilled()) {
+ out.println("Error transporting IO from child process");
+ e.printStackTrace(out);
+ }
+ }
+ }
+ };
+
+ ioTransport.setDaemon(true);
+ ioTransport.start();
+ }
+
+ private String[] buildJavaCommand(int vmNum, int namingPort) {
+ String cmd = System.getProperty( "java.home" ) + File.separator + "bin" + File.separator + "java";
+ String classPath = System.getProperty("java.class.path");
+ //String tmpDir = System.getProperty("java.io.tmpdir");
+ String agent = getAgentString();
+
+ String jdkDebug = "";
+ if (debugPort > 0) {
+ jdkDebug += ",address=" + debugPort;
+ debugPort++;
+ }
+
+ String jdkSuspend = vmNum == suspendVM ? "y" : "n";
+
+ return new String[] {
+ cmd, "-classpath", classPath,
+ "-D" + DUnitLauncher.RMI_PORT_PARAM + "=" + namingPort,
+ "-D" + DUnitLauncher.VM_NUM_PARAM + "=" + vmNum,
+ "-D" + DUnitLauncher.WORKSPACE_DIR_PARAM + "=" + new File(".").getAbsolutePath(),
+ "-DlogLevel=" + DUnitLauncher.LOG_LEVEL,
+ "-Djava.library.path=" + System.getProperty("java.library.path"),
+ "-Xrunjdwp:transport=dt_socket,server=y,suspend=" + jdkSuspend + jdkDebug,
+ "-XX:+HeapDumpOnOutOfMemoryError",
+ "-Xmx512m",
+ "-Dgemfire.DEFAULT_MAX_OPLOG_SIZE=10",
+ "-Dgemfire.disallowMcastDefaults=true",
+ "-ea",
+ agent,
+ "dunit.standalone.ChildVM"
+ };
+ }
+
+ /**
+ * Get the java agent passed to this process and pass it to the child VMs.
+ * This was added to support jacoco code coverage reports
+ */
+ private String getAgentString() {
+ RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
+ if (runtimeBean != null) {
+ for(String arg: runtimeBean.getInputArguments()) {
+ if(arg.contains("-javaagent:")) {
+ //HACK for gradle bug GRADLE-2859. Jacoco is passing a relative path
+ //That won't work when we pass this to dunit VMs in a different
+ //directory
+ arg = arg.replace("-javaagent:..", "-javaagent:" + System.getProperty("user.dir") + File.separator + "..");
+ arg = arg.replace("destfile=..", "destfile=" + System.getProperty("user.dir") + File.separator + "..");
+ return arg;
+ }
+ }
+ }
+
+ return "-DdummyArg=true";
+ }
+
+ synchronized void signalVMReady() {
+ pendingVMs--;
+ this.notifyAll();
+ }
+
+ public synchronized boolean waitForVMs(long timeout) throws InterruptedException {
+ long end = System.currentTimeMillis() + timeout;
+ while(pendingVMs > 0) {
+ long remaining = end - System.currentTimeMillis();
+ if(remaining <= 0) {
+ return false;
+ }
+ this.wait(remaining);
+ }
+
+ return true;
+ }
+
+ private static class ProcessHolder {
+ private final Process process;
+ private volatile boolean killed = false;
+
+ public ProcessHolder(Process process) {
+ this.process = process;
+ }
+
+ public void kill() {
+ this.killed = true;
+ process.destroy();
+
+ }
+
+ public Process getProcess() {
+ return process;
+ }
+
+ public boolean isKilled() {
+ return killed;
+ }
+
+ public boolean isAlive() {
+ return !killed && process.isAlive();
+ }
+ }
+
+ public RemoteDUnitVMIF getStub(int i) throws AccessException, RemoteException, NotBoundException, InterruptedException {
+ waitForVMs(DUnitLauncher.STARTUP_TIMEOUT);
+ return (RemoteDUnitVMIF) registry.lookup("vm" + i);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/dfba327e/gemfire-core/src/test/java/dunit/standalone/RemoteDUnitVM.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/dunit/standalone/RemoteDUnitVM.java b/gemfire-core/src/test/java/dunit/standalone/RemoteDUnitVM.java
new file mode 100644
index 0000000..742dc55
--- /dev/null
+++ b/gemfire-core/src/test/java/dunit/standalone/RemoteDUnitVM.java
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package dunit.standalone;
+
+import hydra.MethExecutor;
+import hydra.MethExecutorResult;
+
+import java.rmi.RemoteException;
+import java.rmi.server.UnicastRemoteObject;
+
+import org.apache.logging.log4j.Logger;
+
+import com.gemstone.gemfire.internal.logging.LogService;
+
+import dunit.RemoteDUnitVMIF;
+
+/**
+ * @author dsmith
+ *
+ */
+public class RemoteDUnitVM extends UnicastRemoteObject implements RemoteDUnitVMIF {
+
+ private static final Logger logger = LogService.getLogger();
+
+ public RemoteDUnitVM() throws RemoteException {
+ super();
+ }
+
+ /**
+ * Called remotely by the master controller to cause the client to execute
+ * the instance method on the object. Does this synchronously (does not spawn
+ * a thread). This method is used by the unit test framework, dunit.
+ *
+ * @param obj the object to execute the method on
+ * @param methodName the name of the method to execute
+ * @return the result of method execution
+ */
+ public MethExecutorResult executeMethodOnObject( Object obj, String methodName ) {
+ String name = obj.getClass().getName() + "." + methodName +
+ " on object: " + obj;
+ logger.info("Received method: " + name);
+ long start = System.currentTimeMillis();
+ MethExecutorResult result = MethExecutor.executeObject( obj, methodName );
+ long delta = System.currentTimeMillis() - start;
+ logger.info( "Got result: " + result.toString().trim() + " from " +
+ name + " (took " + delta + " ms)");
+ return result;
+ }
+
+ /**
+ * Executes a given instance method on a given object with the given
+ * arguments.
+ */
+ public MethExecutorResult executeMethodOnObject(Object obj,
+ String methodName,
+ Object[] args) {
+ String name = obj.getClass().getName() + "." + methodName +
+ (args != null ? " with " + args.length + " args": "") +
+ " on object: " + obj;
+ logger.info("Received method: " + name);
+ long start = System.currentTimeMillis();
+ MethExecutorResult result =
+ MethExecutor.executeObject(obj, methodName, args);
+ long delta = System.currentTimeMillis() - start;
+ logger.info( "Got result: " + result.toString() + " from " + name +
+ " (took " + delta + " ms)");
+ return result;
+ }
+
+ /**
+ * Called remotely by the master controller to cause the client to execute
+ * the method on the class. Does this synchronously (does not spawn a thread).
+ * This method is used by the unit test framework, dunit.
+ *
+ * @param className the name of the class execute
+ * @param methodName the name of the method to execute
+ * @return the result of method execution
+ */
+ public MethExecutorResult executeMethodOnClass( String className, String methodName ) {
+ String name = className + "." + methodName;
+ logger.info("Received method: " + name);
+ long start = System.currentTimeMillis();
+ MethExecutorResult result = MethExecutor.execute( className, methodName );
+ long delta = System.currentTimeMillis() - start;
+ logger.info( "Got result: " + result.toString() + " from " + name +
+ " (took " + delta + " ms)");
+
+ return result;
+ }
+
+ /**
+ * Executes a given static method in a given class with the given
+ * arguments.
+ */
+ public MethExecutorResult executeMethodOnClass(String className,
+ String methodName,
+ Object[] args) {
+ String name = className + "." + methodName +
+ (args != null ? " with " + args.length + " args": "");
+ logger.info("Received method: " + name);
+ long start = System.currentTimeMillis();
+ MethExecutorResult result =
+ MethExecutor.execute(className, methodName, args);
+ long delta = System.currentTimeMillis() - start;
+ logger.info( "Got result: " + result.toString() + " from " + name +
+ " (took " + delta + " ms)");
+ return result;
+ }
+
+ public void executeTask(int tsid, int type, int index) throws RemoteException {
+ throw new UnsupportedOperationException();
+
+ }
+
+ public void runShutdownHook() throws RemoteException {
+
+ }
+
+ public void notifyDynamicActionComplete(int actionId) throws RemoteException {
+ throw new UnsupportedOperationException();
+
+ }
+
+ public void shutDownVM() throws RemoteException {
+ ChildVM.stopVM();
+ }
+
+ public void disconnectVM() throws RemoteException {
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/dfba327e/gemfire-core/src/test/java/dunit/standalone/StandAloneDUnitEnv.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/dunit/standalone/StandAloneDUnitEnv.java b/gemfire-core/src/test/java/dunit/standalone/StandAloneDUnitEnv.java
new file mode 100644
index 0000000..085035d
--- /dev/null
+++ b/gemfire-core/src/test/java/dunit/standalone/StandAloneDUnitEnv.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package dunit.standalone;
+
+import java.io.File;
+import java.rmi.RemoteException;
+import java.util.Properties;
+
+import dunit.BounceResult;
+import dunit.DUnitEnv;
+import dunit.standalone.DUnitLauncher.MasterRemote;
+
+public class StandAloneDUnitEnv extends DUnitEnv {
+
+ private MasterRemote master;
+
+ public StandAloneDUnitEnv(MasterRemote master) {
+ this.master = master;
+ }
+
+ @Override
+ public String getLocatorString() {
+ return DUnitLauncher.getLocatorString();
+ }
+
+ @Override
+ public String getLocatorAddress() {
+ return "localhost";
+ }
+
+ @Override
+ public int getLocatorPort() {
+ return DUnitLauncher.locatorPort;
+ }
+
+ @Override
+ public Properties getDistributedSystemProperties() {
+ return DUnitLauncher.getDistributedSystemProperties();
+ }
+
+ @Override
+ public int getPid() {
+ return Integer.getInteger(DUnitLauncher.VM_NUM_PARAM, -1).intValue();
+ }
+
+ @Override
+ public int getVMID() {
+ return getPid();
+ }
+
+ @Override
+ public BounceResult bounce(int pid) throws RemoteException {
+ return master.bounce(pid);
+ }
+
+ @Override
+ public File getWorkingDirectory(int pid) {
+ return ProcessManager.getVMDir(pid);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/dfba327e/gemfire-core/src/test/java/dunit/tests/BasicDUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/dunit/tests/BasicDUnitTest.java b/gemfire-core/src/test/java/dunit/tests/BasicDUnitTest.java
new file mode 100644
index 0000000..c284b3a
--- /dev/null
+++ b/gemfire-core/src/test/java/dunit/tests/BasicDUnitTest.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package dunit.tests;
+
+import java.util.Properties;
+
+import dunit.AsyncInvocation;
+import dunit.DistributedTestCase;
+import dunit.Host;
+import dunit.RMIException;
+import dunit.VM;
+
+/**
+ * This class tests the basic functionality of the distributed unit
+ * test framework.
+ */
+public class BasicDUnitTest extends DistributedTestCase {
+
+ public BasicDUnitTest(String name) {
+ super(name);
+ }
+
+ //////// Test Methods
+
+ /**
+ * Tests how the Hydra framework handles an error
+ */
+ public void _testDontCatchRemoteException() {
+ Host host = Host.getHost(0);
+ VM vm = host.getVM(0);
+ vm.invoke(this.getClass(), "remoteThrowException");
+ }
+
+ public void testRemoteInvocationWithException() {
+ Host host = Host.getHost(0);
+ VM vm = host.getVM(0);
+ try {
+ vm.invoke(this.getClass(), "remoteThrowException");
+ fail("Should have thrown a BasicTestException");
+
+ } catch (RMIException ex) {
+ assertTrue(ex.getCause() instanceof BasicTestException);
+ }
+ }
+
+ static class BasicTestException extends RuntimeException {
+ BasicTestException() {
+ this("Test exception. Please ignore.");
+ }
+
+ BasicTestException(String s) {
+ super(s);
+ }
+ }
+
+ /**
+ * Accessed via reflection. DO NOT REMOVE
+ *
+ */
+ protected static void remoteThrowException() {
+ String s = "Test exception. Please ignore.";
+ throw new BasicTestException(s);
+ }
+
+ public void _testRemoteInvocationBoolean() {
+
+ }
+
+ public void testRemoteInvokeAsync() throws InterruptedException {
+ Host host = Host.getHost(0);
+ VM vm = host.getVM(0);
+ String name = this.getUniqueName();
+ String value = "Hello";
+
+ AsyncInvocation ai =
+ vm.invokeAsync(this.getClass(), "remoteBind",
+ new Object[] { name, value });
+ ai.join();
+ // TODO shouldn't we call fail() here?
+ if (ai.exceptionOccurred()) {
+ fail("remoteBind failed", ai.getException());
+ }
+
+ ai = vm.invokeAsync(this.getClass(), "remoteValidateBind",
+ new Object[] {name, value });
+ ai.join();
+ if (ai.exceptionOccurred()) {
+ fail("remoteValidateBind failed", ai.getException());
+ }
+ }
+
+ private static Properties bindings = new Properties();
+ private static void remoteBind(String name, String s) {
+ new BasicDUnitTest("bogus").getSystem(); // forces connection
+ bindings.setProperty(name, s);
+ }
+
+ private static void remoteValidateBind(String name, String expected)
+ {
+ assertEquals(expected, bindings.getProperty(name));
+ }
+
+ public void testRemoteInvokeAsyncWithException()
+ throws InterruptedException {
+
+ Host host = Host.getHost(0);
+ VM vm = host.getVM(0);
+// String name = this.getUniqueName();
+// String value = "Hello";
+
+ AsyncInvocation ai =
+ vm.invokeAsync(this.getClass(), "remoteThrowException");
+ ai.join();
+ assertTrue(ai.exceptionOccurred());
+ Throwable ex = ai.getException();
+ assertTrue(ex instanceof BasicTestException);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/dfba327e/gemfire-core/src/test/java/dunit/tests/TestFailure.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/dunit/tests/TestFailure.java b/gemfire-core/src/test/java/dunit/tests/TestFailure.java
new file mode 100644
index 0000000..17a39fa
--- /dev/null
+++ b/gemfire-core/src/test/java/dunit/tests/TestFailure.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package dunit.tests;
+
+import dunit.*;
+
+/**
+ * The tests in this class always fail. It is used when developing
+ * DUnit to give us an idea of how test failure are logged, etc.
+ *
+ * @author David Whitlock
+ *
+ * @since 3.0
+ */
+public class TestFailure extends DistributedTestCase {
+
+ public TestFailure(String name) {
+ super(name);
+ }
+
+ //////// Test Methods
+
+ public void testFailure() {
+ assertTrue("Test Failure", false);
+ }
+
+ public void testError() {
+ String s = "Test Error";
+ throw new Error(s);
+ }
+
+ public void testHang() throws InterruptedException {
+ Thread.sleep(100000 * 1000);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/dfba327e/gemfire-core/src/test/java/dunit/tests/VMDUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/dunit/tests/VMDUnitTest.java b/gemfire-core/src/test/java/dunit/tests/VMDUnitTest.java
new file mode 100644
index 0000000..27736dc
--- /dev/null
+++ b/gemfire-core/src/test/java/dunit/tests/VMDUnitTest.java
@@ -0,0 +1,237 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package dunit.tests;
+
+import dunit.*;
+
+import java.io.Serializable;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * This class tests the functionality of the {@link VM} class.
+ */
+public class VMDUnitTest extends DistributedTestCase {
+
+ private static final boolean BOOLEAN_VALUE = true;
+ private static final byte BYTE_VALUE = (byte) 40;
+ private static final long LONG_VALUE = 42L;
+ private static final String STRING_VALUE = "BLAH BLAH BLAH";
+
+ public VMDUnitTest(String name) {
+ super(name);
+ }
+
+ //////// Test Methods
+
+ public void notestInvokeNonExistentMethod() {
+ Host host = Host.getHost(0);
+ VM vm = host.getVM(0);
+ try {
+ vm.invoke(VMDUnitTest.class, "nonExistentMethod");
+ fail("Should have thrown an RMIException");
+
+ } catch (RMIException ex) {
+ String s = "Excepted a NoSuchMethodException, got a " +
+ ex.getCause();;
+ assertTrue(s, ex.getCause() instanceof NoSuchMethodException);
+ }
+ }
+
+ /**
+ * Accessed via reflection. DO NOT REMOVE
+ * @return
+ */
+ protected static byte remoteByteMethod() {
+ return BYTE_VALUE;
+ }
+
+ public void notestInvokeStaticBoolean() {
+ Host host = Host.getHost(0);
+ VM vm = host.getVM(0);
+ assertEquals(BOOLEAN_VALUE,
+ vm.invokeBoolean(VMDUnitTest.class, "remoteBooleanMethod"));
+ }
+
+ /**
+ * Accessed via reflection. DO NOT REMOVE
+ * @return
+ */
+ protected static boolean remoteBooleanMethod() {
+ return BOOLEAN_VALUE;
+ }
+
+ public void notestInvokeStaticBooleanNotBoolean() {
+ Host host = Host.getHost(0);
+ VM vm = host.getVM(0);
+ try {
+ vm.invokeBoolean(VMDUnitTest.class, "remoteByteMethod");
+ fail("Should have thrown an IllegalArgumentException");
+
+ } catch (IllegalArgumentException ex) {
+
+ }
+ }
+
+ public void notestInvokeStaticLong() {
+ Host host = Host.getHost(0);
+ VM vm = host.getVM(0);
+ assertEquals(LONG_VALUE,
+ vm.invokeLong(VMDUnitTest.class, "remoteLongMethod"));
+ }
+
+ /**
+ * Accessed via reflection. DO NOT REMOVE
+ * @return
+ */
+ protected static long remoteLongMethod() {
+ return LONG_VALUE;
+ }
+
+ public void notestInvokeStaticLongNotLong() {
+ Host host = Host.getHost(0);
+ VM vm = host.getVM(0);
+ try {
+ vm.invokeLong(VMDUnitTest.class, "remoteByteMethod");
+ fail("Should have thrown an IllegalArgumentException");
+
+ } catch (IllegalArgumentException ex) {
+
+ }
+ }
+
+ protected static class ClassWithLong implements Serializable {
+ public long getLong() {
+ return LONG_VALUE;
+ }
+ }
+
+ protected static class ClassWithByte implements Serializable {
+ public byte getByte() {
+ return BYTE_VALUE;
+ }
+ }
+
+ public void notestInvokeInstanceLong() {
+ Host host = Host.getHost(0);
+ VM vm = host.getVM(0);
+ assertEquals(LONG_VALUE,
+ vm.invokeLong(new ClassWithLong(), "getLong"));
+ }
+
+ public void notestInvokeInstanceLongNotLong() {
+ Host host = Host.getHost(0);
+ VM vm = host.getVM(0);
+ try {
+ vm.invokeLong(new ClassWithByte(), "getByte");
+ fail("Should have thrown an IllegalArgumentException");
+
+ } catch (IllegalArgumentException ex) {
+
+ }
+ }
+
+ protected static class InvokeRunnable
+ implements Serializable, Runnable {
+
+ public void run() {
+ throw new BasicDUnitTest.BasicTestException();
+ }
+ }
+
+ protected static class ClassWithString implements Serializable {
+ public String getString() {
+ return STRING_VALUE;
+ }
+ }
+
+ public void notestInvokeInstance() {
+ Host host = Host.getHost(0);
+ VM vm = host.getVM(0);
+ assertEquals(STRING_VALUE,
+ vm.invoke(new ClassWithString(), "getString"));
+ }
+
+ public void notestInvokeRunnable() {
+ Host host = Host.getHost(0);
+ VM vm = host.getVM(0);
+ try {
+ vm.invoke(new InvokeRunnable());
+ fail("Should have thrown a BasicTestException");
+
+ } catch (RMIException ex) {
+ assertTrue(ex.getCause() instanceof BasicDUnitTest.BasicTestException);
+ }
+ }
+
+ private static final AtomicInteger COUNTER = new AtomicInteger();
+ public static Integer getAndIncStaticCount() {
+ return new Integer(COUNTER.getAndIncrement());
+ }
+ public static Integer incrementStaticCount(Integer inc) {
+ return new Integer(COUNTER.addAndGet(inc.intValue()));
+ }
+ public static void incStaticCount() {
+ COUNTER.incrementAndGet();
+ }
+ public static class VMTestObject implements Serializable {
+ private static final long serialVersionUID = 1L;
+ private final AtomicInteger val;
+ public VMTestObject(int init) {
+ this.val = new AtomicInteger(init);
+ }
+ public Integer get() {
+ return new Integer(this.val.get());
+ }
+ public Integer incrementAndGet() {
+ return new Integer(this.val.incrementAndGet());
+ }
+ public void set(Integer newVal) {
+ this.val.set(newVal.intValue());
+ }
+ }
+ public void testReturnValue() throws Exception {
+ final Host host = Host.getHost(0);
+ final VM vm = host.getVM(0);
+ // Assert class static invocation works
+ AsyncInvocation a1 = vm.invokeAsync(getClass(), "getAndIncStaticCount");
+ a1.join();
+ assertEquals(new Integer(0), a1.getReturnValue());
+ // Assert class static invocation with args works
+ a1 = vm.invokeAsync(getClass(), "incrementStaticCount", new Object[] {new Integer(2)});
+ a1.join();
+ assertEquals(new Integer(3), a1.getReturnValue());
+ // Assert that previous values are not returned when invoking method w/ no return val
+ a1 = vm.invokeAsync(getClass(), "incStaticCount");
+ a1.join();
+ assertNull(a1.getReturnValue());
+ // Assert that previous null returns are over-written
+ a1 = vm.invokeAsync(getClass(), "getAndIncStaticCount");
+ a1.join();
+ assertEquals(new Integer(4), a1.getReturnValue());
+
+ // Assert object method invocation works with zero arg method
+ final VMTestObject o = new VMTestObject(0);
+ a1 = vm.invokeAsync(o, "incrementAndGet", new Object[] {});
+ a1.join();
+ assertEquals(new Integer(1), a1.getReturnValue());
+ // Assert object method invocation works with no return
+ a1 = vm.invokeAsync(o, "set", new Object[] {new Integer(3)});
+ a1.join();
+ assertNull(a1.getReturnValue());
+ }
+}