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:30 UTC
[3/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/cache/CacheTestCase.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/cache/CacheTestCase.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/cache/CacheTestCase.java
new file mode 100755
index 0000000..8535d85
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/cache/CacheTestCase.java
@@ -0,0 +1,696 @@
+package com.gemstone.gemfire.test.dunit.cache;
+
+import static com.gemstone.gemfire.test.dunit.Assert.*;
+import static com.gemstone.gemfire.test.dunit.ExpectedExceptionString.*;
+import static com.gemstone.gemfire.test.dunit.Invoke.*;
+import static com.gemstone.gemfire.test.dunit.Wait.*;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+
+import com.gemstone.gemfire.SystemFailure;
+import com.gemstone.gemfire.cache.AttributesFactory;
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.cache.CacheException;
+import com.gemstone.gemfire.cache.CacheExistsException;
+import com.gemstone.gemfire.cache.CacheFactory;
+import com.gemstone.gemfire.cache.CacheTransactionManager;
+import com.gemstone.gemfire.cache.ExpirationAttributes;
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.cache.RegionAttributes;
+import com.gemstone.gemfire.cache.RegionExistsException;
+import com.gemstone.gemfire.cache.TimeoutException;
+import com.gemstone.gemfire.cache.client.ClientCache;
+import com.gemstone.gemfire.cache.client.ClientCacheFactory;
+import com.gemstone.gemfire.cache.client.PoolManager;
+import com.gemstone.gemfire.cache30.CacheSerializableRunnable;
+import com.gemstone.gemfire.distributed.internal.DistributionMessageObserver;
+import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
+import com.gemstone.gemfire.internal.FileUtil;
+import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
+import com.gemstone.gemfire.internal.cache.HARegion;
+import com.gemstone.gemfire.internal.cache.InternalRegionArguments;
+import com.gemstone.gemfire.internal.cache.LocalRegion;
+import com.gemstone.gemfire.internal.cache.PartitionedRegion;
+import com.gemstone.gemfire.internal.cache.xmlcache.CacheCreation;
+import com.gemstone.gemfire.internal.cache.xmlcache.CacheXmlGenerator;
+import com.gemstone.gemfire.test.dunit.DistributedTestCase;
+import com.gemstone.gemfire.test.dunit.Host;
+import com.gemstone.gemfire.test.dunit.VM;
+import com.gemstone.gemfire.test.dunit.WaitCriterion;
+
+/**
+ * The abstract superclass of tests that require the creation of a
+ * {@link Cache}.
+ *
+ * @author David Whitlock
+ * @since 3.0
+ */
+@SuppressWarnings({ "deprecation", "serial", "rawtypes", "unchecked" })
+public abstract class CacheTestCase extends DistributedTestCase {
+
+ /** The Cache from which regions are obtained
+ *
+ * All references synchronized via <code>CacheTestCase.class</code>
+ * */
+ // static so it doesn't get serialized with SerializableRunnable inner classes
+ protected static Cache cache;
+
+ //////// Helper methods
+ /**
+ * Creates the <code>Cache</code> for this test
+ */
+ private void createCache() {
+ createCache(false);
+ }
+
+ private void createCache(boolean client) {
+ createCache(client, null);
+ }
+
+ private void createCache(boolean client, CacheFactory cf) {
+ synchronized(CacheTestCase.class) {
+ try {
+ System.setProperty("gemfire.DISABLE_DISCONNECT_DS_ON_CACHE_CLOSE", "true");
+ Cache c;
+ if (client) {
+ c = (Cache)new ClientCacheFactory(getSystem().getProperties()).create();
+ } else {
+ if(cf == null) {
+ c = CacheFactory.create(getSystem());
+ } else {
+ Properties props = getSystem().getProperties();
+ for(Map.Entry entry : props.entrySet()) {
+ cf.set((String) entry.getKey(), (String)entry.getValue());
+ }
+ c = cf.create();
+ }
+ }
+ cache = c;
+ } catch (CacheExistsException e) {
+ fail("the cache already exists", e);
+
+ } catch (RuntimeException ex) {
+ throw ex;
+
+ } catch (Exception ex) {
+ fail("Checked exception while initializing cache??", ex);
+ } finally {
+ System.clearProperty("gemfire.DISABLE_DISCONNECT_DS_ON_CACHE_CLOSE");
+ }
+ }
+ }
+
+ /**
+ * Creates the <code>Cache</code> for this test that is not connected
+ * to other members
+ */
+ public Cache createLonerCache() {
+ synchronized(CacheTestCase.class) {
+ try {
+ System.setProperty("gemfire.DISABLE_DISCONNECT_DS_ON_CACHE_CLOSE", "true");
+ Cache c = CacheFactory.create(getLonerSystem());
+ cache = c;
+ } catch (CacheExistsException e) {
+ fail("the cache already exists", e);
+
+ } catch (RuntimeException ex) {
+ throw ex;
+
+ } catch (Exception ex) {
+ fail("Checked exception while initializing cache??", ex);
+ } finally {
+ System.clearProperty("gemfire.DISABLE_DISCONNECT_DS_ON_CACHE_CLOSE");
+ }
+ return cache;
+ }
+ }
+
+ /**
+ * Creates the <code>Cache</code> for this test that is not connected
+ * to other members.
+ * Added specifically to test scenario of defect #47181.
+ */
+ public Cache createLonerCacheWithEnforceUniqueHost() {
+ synchronized(CacheTestCase.class) {
+ try {
+ System.setProperty("gemfire.DISABLE_DISCONNECT_DS_ON_CACHE_CLOSE", "true");
+ Cache c = CacheFactory.create(getLonerSystemWithEnforceUniqueHost());
+ cache = c;
+ } catch (CacheExistsException e) {
+ fail("the cache already exists", e);
+
+ } catch (RuntimeException ex) {
+ throw ex;
+
+ } catch (Exception ex) {
+ fail("Checked exception while initializing cache??", ex);
+ } finally {
+ System.clearProperty("gemfire.DISABLE_DISCONNECT_DS_ON_CACHE_CLOSE");
+ }
+ return cache;
+ }
+ }
+
+ /**
+ * Creates the <code>Cache</code> for this test that has its own mcast group
+ */
+ public Cache createMcastCache() {
+ synchronized(CacheTestCase.class) {
+ try {
+ System.setProperty("gemfire.DISABLE_DISCONNECT_DS_ON_CACHE_CLOSE", "true");
+ Cache c = CacheFactory.create(getMcastSystem());
+ cache = c;
+ } catch (CacheExistsException e) {
+ fail("the cache already exists", e);
+
+ } catch (RuntimeException ex) {
+ throw ex;
+
+ } catch (Exception ex) {
+ fail("Checked exception while initializing cache??", ex);
+ } finally {
+ System.clearProperty("gemfire.DISABLE_DISCONNECT_DS_ON_CACHE_CLOSE");
+ }
+ return cache;
+ }
+ }
+
+ /**
+ * Creates the <code>Cache</code> for this test that has its own mcast group
+ */
+ public Cache createMcastCache(int jgroupsPort) {
+ synchronized(CacheTestCase.class) {
+ try {
+ System.setProperty("gemfire.DISABLE_DISCONNECT_DS_ON_CACHE_CLOSE", "true");
+ Cache c = CacheFactory.create(getMcastSystem(jgroupsPort));
+ cache = c;
+ } catch (CacheExistsException e) {
+ fail("the cache already exists", e);
+
+ } catch (RuntimeException ex) {
+ throw ex;
+
+ } catch (Exception ex) {
+ fail("Checked exception while initializing cache??", ex);
+ } finally {
+ System.clearProperty("gemfire.DISABLE_DISCONNECT_DS_ON_CACHE_CLOSE");
+ }
+ return cache;
+ }
+ }
+ /**
+ * Sets this test up with a CacheCreation as its cache.
+ * Any existing cache is closed. Whoever calls this must also call finishCacheXml
+ */
+ public static synchronized void beginCacheXml() {
+// getLogWriter().info("before closeCache");
+ closeCache();
+// getLogWriter().info("before TestCacheCreation");
+ cache = new TestCacheCreation();
+// getLogWriter().info("after TestCacheCreation");
+ }
+ /**
+ * Finish what beginCacheXml started. It does this be generating a cache.xml
+ * file and then creating a real cache using that cache.xml.
+ */
+ public void finishCacheXml(String name) {
+ synchronized(CacheTestCase.class) {
+ File file = new File(name + "-cache.xml");
+ try {
+ PrintWriter pw = new PrintWriter(new FileWriter(file), true);
+ CacheXmlGenerator.generate(cache, pw);
+ pw.close();
+ } catch (IOException ex) {
+ fail("IOException during cache.xml generation to " + file, ex);
+ }
+ cache = null;
+ GemFireCacheImpl.testCacheXml = file;
+ try {
+ createCache();
+ } finally {
+ GemFireCacheImpl.testCacheXml = null;
+ }
+ }
+ }
+
+ /**
+ * Finish what beginCacheXml started. It does this be generating a cache.xml
+ * file and then creating a real cache using that cache.xml.
+ */
+ public void finishCacheXml(String name, boolean useSchema, String xmlVersion) {
+ synchronized(CacheTestCase.class) {
+ File dir = new File("XML_" + xmlVersion);
+ dir.mkdirs();
+ File file = new File(dir, name + ".xml");
+ try {
+ PrintWriter pw = new PrintWriter(new FileWriter(file), true);
+ CacheXmlGenerator.generate(cache, pw, useSchema, xmlVersion);
+ pw.close();
+ } catch (IOException ex) {
+ fail("IOException during cache.xml generation to " + file, ex);
+ }
+ cache = null;
+ GemFireCacheImpl.testCacheXml = file;
+ try {
+ createCache();
+ } finally {
+ GemFireCacheImpl.testCacheXml = null;
+ }
+ }
+ }
+
+ /**
+ * Return a cache for obtaining regions, created lazily.
+ */
+ public final Cache getCache() {
+ return getCache(false);
+ }
+
+ public final Cache getCache(CacheFactory cf) {
+ return getCache(false, cf);
+ }
+
+ public final Cache getCache(boolean client) {
+ return getCache(client, null);
+ }
+
+ public final Cache getCache(boolean client, CacheFactory cf) {
+ synchronized (CacheTestCase.class) {
+ final GemFireCacheImpl gfCache = GemFireCacheImpl.getInstance();
+ if (gfCache != null && !gfCache.isClosed()
+ && gfCache.getCancelCriterion().cancelInProgress() != null) {
+ waitForCriterion(new WaitCriterion() {
+
+ public boolean done() {
+ return gfCache.isClosed();
+ }
+
+ public String description() {
+ return "waiting for cache to close";
+ }
+ }, 30 * 1000, 300, true);
+ }
+ if (cache == null || cache.isClosed()) {
+ cache = null;
+ createCache(client, cf);
+ }
+ if (client && cache != null) {
+ addExpectedExceptionString("java.net.ConnectException");
+ }
+ return cache;
+ }
+ }
+
+ /**
+ * creates a client cache from the factory if one does not already exist
+ * @since 6.5
+ * @param factory
+ * @return the client cache
+ */
+ public final ClientCache getClientCache(ClientCacheFactory factory) {
+ synchronized (CacheTestCase.class) {
+ final GemFireCacheImpl gfCache = GemFireCacheImpl.getInstance();
+ if (gfCache != null && !gfCache.isClosed()
+ && gfCache.getCancelCriterion().cancelInProgress() != null) {
+ waitForCriterion(new WaitCriterion() {
+
+ public boolean done() {
+ return gfCache.isClosed();
+ }
+
+ public String description() {
+ return "waiting for cache to close";
+ }
+ }, 30 * 1000, 300, true);
+ }
+ if (cache == null || cache.isClosed()) {
+ cache = null;
+ disconnectFromDS();
+ cache = (Cache)factory.create();
+ }
+ if (cache != null) {
+ addExpectedExceptionString("java.net.ConnectException");
+ }
+ return (ClientCache)cache;
+ }
+ }
+
+ /**
+ * same as {@link #getCache()} but with casting
+ */
+ public final GemFireCacheImpl getGemfireCache() {
+ return (GemFireCacheImpl)getCache();
+ }
+ public static synchronized final boolean hasCache() {
+ return cache != null;
+ }
+
+ /**
+ * Return current cache without creating one.
+ */
+ public static synchronized final Cache basicGetCache() {
+ return cache;
+ }
+
+ public static synchronized void disconnectFromDS() {
+ closeCache();
+ DistributedTestCase.disconnectFromDS();
+ }
+
+ /** Close the cache */
+ public static synchronized void closeCache() {
+ //Workaround for that fact that some classes are now extending
+ //CacheTestCase but not using it properly.
+ if(cache == null) {
+ cache = GemFireCacheImpl.getInstance();
+ }
+ try {
+ if (cache != null) {
+ try {
+ if (!cache.isClosed()) {
+ if (cache instanceof GemFireCacheImpl) {
+ CacheTransactionManager txMgr = ((GemFireCacheImpl)cache).getTxManager();
+ if (txMgr != null) {
+ if (txMgr.exists()) {
+ try {
+ // make sure we cleanup this threads txid stored in a thread local
+ txMgr.rollback();
+ }catch(Exception ignore) {
+
+ }
+ }
+ }
+ }
+ try {
+ cache.close();
+ }
+ catch (VirtualMachineError e) {
+ SystemFailure.initiateFailure(e);
+ throw e;
+ }
+ catch (Throwable t) {
+ }
+ finally {
+ }
+ }
+ // @todo darrel: destroy DiskStore files
+ }
+ finally {
+ cache = null;
+ }
+ } // cache != null
+ } finally {
+ //Make sure all pools are closed, even if we never
+ //created a cache
+ PoolManager.close(false);
+ }
+ }
+
+ /** Closed the cache in all VMs. */
+ protected void closeAllCache() {
+ closeCache();
+ invokeInEveryVM(CacheTestCase.class, "closeCache");
+ }
+
+ @Override
+ public void tearDown2() throws Exception {
+ // locally destroy all root regions and close the cache
+ remoteTearDown();
+ // Now invoke it in every VM
+ 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(CacheTestCase.class, "remoteTearDown");
+ }
+ }
+ super.tearDown2();
+ }
+
+ /**
+ * Local destroy all root regions and close the cache.
+ */
+ protected synchronized static void remoteTearDown() {
+ try {
+ DistributionMessageObserver.setInstance(null);
+ if (cache != null && !cache.isClosed()) {
+ //try to destroy the root regions first so that
+ //we clean up any persistent files.
+ for (Iterator itr = cache.rootRegions().iterator(); itr.hasNext();) {
+ Region root = (Region)itr.next();
+// String name = root.getName();
+ //for colocated regions you can't locally destroy a partitioned
+ //region.
+ if(root.isDestroyed() || root instanceof HARegion || root instanceof PartitionedRegion) {
+ continue;
+ }
+ try {
+ root.localDestroyRegion("teardown");
+ }
+ catch (VirtualMachineError e) {
+ SystemFailure.initiateFailure(e);
+ throw e;
+ }
+ catch (Throwable t) {
+ getLogWriter().error(t);
+ }
+ }
+ }
+ }
+ finally {
+ try {
+ closeCache();
+ }
+ catch (VirtualMachineError e) {
+ SystemFailure.initiateFailure(e);
+ throw e;
+ }
+ catch (Throwable t) {
+ getLogWriter().error("Error in closing the cache ", t);
+
+ }
+ }
+
+ try {
+ cleanDiskDirs();
+ } catch(IOException e) {
+ getLogWriter().error("Error cleaning disk dirs", e);
+ }
+ }
+
+ /**
+ * Returns a region with the given name and attributes
+ */
+ public final Region createRegion(String name,
+ RegionAttributes attrs)
+ throws CacheException {
+ return createRegion(name, "root", attrs);
+ }
+
+ /**
+ * Provide any internal region arguments, typically required when
+ * internal use (aka meta-data) regions are needed.
+ * @return internal arguements, which may be null. If null, then default
+ * InternalRegionArguments are used to construct the Region
+ */
+ public InternalRegionArguments getInternalRegionArguments()
+ {
+ return null;
+ }
+
+ final public Region createRegion(String name, String rootName,
+ RegionAttributes attrs)
+ throws CacheException {
+ Region root = getRootRegion(rootName);
+ if (root == null) {
+ // don't put listeners on root region
+ RegionAttributes rootAttrs = attrs;
+ AttributesFactory fac = new AttributesFactory(attrs);
+ ExpirationAttributes expiration = ExpirationAttributes.DEFAULT;
+
+ // fac.setCacheListener(null);
+ fac.setCacheLoader(null);
+ fac.setCacheWriter(null);
+ fac.setPoolName(null);
+ fac.setPartitionAttributes(null);
+ fac.setRegionTimeToLive(expiration);
+ fac.setEntryTimeToLive(expiration);
+ fac.setRegionIdleTimeout(expiration);
+ fac.setEntryIdleTimeout(expiration);
+ rootAttrs = fac.create();
+ root = createRootRegion(rootName, rootAttrs);
+ }
+
+ InternalRegionArguments internalArgs = getInternalRegionArguments();
+ if (internalArgs == null) {
+ return root.createSubregion(name, attrs);
+ } else {
+ try {
+ LocalRegion lr = (LocalRegion) root;
+ return lr.createSubregion(name, attrs, internalArgs);
+ } catch (IOException ioe) {
+ AssertionError assErr = new AssertionError("unexpected exception");
+ assErr.initCause(ioe);
+ throw assErr;
+ } catch (ClassNotFoundException cnfe) {
+ AssertionError assErr = new AssertionError("unexpected exception");
+ assErr.initCause(cnfe);
+ throw assErr;
+ }
+ }
+ }
+
+ public final Region getRootRegion() {
+ return getRootRegion("root");
+ }
+
+ public final Region getRootRegion(String rootName) {
+ return getCache().getRegion(rootName);
+ }
+
+ protected final Region createRootRegion(RegionAttributes attrs)
+ throws RegionExistsException, TimeoutException {
+ return createRootRegion("root", attrs);
+ }
+
+ public final Region createRootRegion(String rootName, RegionAttributes attrs)
+ throws RegionExistsException, TimeoutException {
+ return getCache().createRegion(rootName, attrs);
+ }
+
+ /**
+ * send an unordered message requiring an ack to all connected members
+ * in order to flush the unordered communication channel
+ */
+ public void sendUnorderedMessageToAll() {
+ //if (getCache() instanceof distcache.gemfire.GemFireCacheImpl) {
+ try {
+ com.gemstone.gemfire.distributed.internal.HighPriorityAckedMessage msg = new com.gemstone.gemfire.distributed.internal.HighPriorityAckedMessage();
+ msg.send(InternalDistributedSystem.getConnectedInstance().getDM().getNormalDistributionManagerIds(), false);
+ }
+ catch (Exception e) {
+ throw new RuntimeException("Unable to send unordered message due to exception", e);
+ }
+ //}
+ }
+
+ /**
+ * send an unordered message requiring an ack to all connected admin members
+ * in order to flush the unordered communication channel
+ */
+// public void sendUnorderedMessageToAdminMembers() {
+// //if (getCache() instanceof distcache.gemfire.GemFireCacheImpl) {
+// try {
+// com.gemstone.gemfire.distributed.internal.HighPriorityAckedMessage msg = new com.gemstone.gemfire.distributed.internal.HighPriorityAckedMessage();
+// msg.send(DistributedSystemHelper.getAdminMembers(), false);
+// }
+// catch (Exception e) {
+// throw new RuntimeException("Unable to send unordered message due to exception", e);
+// }
+// //}
+// }
+
+ /**
+ * send an ordered message requiring an ack to all connected members
+ * in order to flush the ordered communication channel
+ */
+ public void sendSerialMessageToAll() {
+ if (getCache() instanceof GemFireCacheImpl) {
+ try {
+ com.gemstone.gemfire.distributed.internal.SerialAckedMessage msg = new com.gemstone.gemfire.distributed.internal.SerialAckedMessage();
+ msg.send(InternalDistributedSystem.getConnectedInstance().getDM().getNormalDistributionManagerIds(), false);
+ }
+ catch (Exception e) {
+ throw new RuntimeException("Unable to send serial message due to exception", e);
+ }
+ }
+ }
+
+ /**
+ * @deprecated Use DistributedTestCase.addExpectedException
+ */
+ @Deprecated
+ protected CacheSerializableRunnable addExceptionTag1(final String expectedException) {
+ CacheSerializableRunnable addExceptionTag = new CacheSerializableRunnable(
+ "addExceptionTag") {
+ public void run2()
+ {
+ getCache().getLogger().info(
+ "<ExpectedException action=add>" + expectedException
+ + "</ExpectedException>");
+ }
+ };
+
+ return addExceptionTag;
+ }
+
+ /**
+ * @deprecated Use DistributedTestCase.addExpectedException
+ */
+ @Deprecated
+ protected CacheSerializableRunnable removeExceptionTag1(final String expectedException) {
+ CacheSerializableRunnable removeExceptionTag = new CacheSerializableRunnable(
+ "removeExceptionTag") {
+ public void run2() throws CacheException {
+ getCache().getLogger().info(
+ "<ExpectedException action=remove>" + expectedException
+ + "</ExpectedException>");
+ }
+ };
+ return removeExceptionTag;
+ }
+
+ /**
+ * Used to generate a cache.xml. Basically just a CacheCreation
+ * with a few more methods implemented.
+ */
+ static class TestCacheCreation extends CacheCreation {
+ private boolean closed = false;
+ @Override
+ public void close() {
+ this.closed = true;
+ }
+ @Override
+ public boolean isClosed() {
+ return this.closed;
+ }
+ }
+
+ public static File getDiskDir() {
+ int vmNum = VM.getCurrentVMNum();
+ File dir = new File("diskDir", "disk" + String.valueOf(vmNum)).getAbsoluteFile();
+ dir.mkdirs();
+ return dir;
+ }
+
+ /**
+ * Return a set of disk directories
+ * for persistence tests. These directories
+ * will be automatically cleaned up
+ * on test case closure.
+ */
+ public static File[] getDiskDirs() {
+ return new File[] {getDiskDir()};
+ }
+
+ public static void cleanDiskDirs() throws IOException {
+ FileUtil.delete(getDiskDir());
+ File[] defaultStoreFiles = new File(".").listFiles(new FilenameFilter() {
+
+ public boolean accept(File dir, String name) {
+ return name.startsWith("BACKUPDiskStore-" + System.getProperty("vmid"));
+ }
+ });
+
+ for(File file: defaultStoreFiles) {
+ FileUtil.delete(file);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/standalone/ChildVM.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/standalone/ChildVM.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/standalone/ChildVM.java
new file mode 100644
index 0000000..bbd540d
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/standalone/ChildVM.java
@@ -0,0 +1,62 @@
+/*=========================================================================
+ * Copyright (c) 2002-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
+ * more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.test.dunit.standalone;
+
+import hydra.HydraRuntimeException;
+import hydra.Log;
+
+import java.rmi.Naming;
+
+import org.apache.logging.log4j.Logger;
+
+import com.gemstone.gemfire.internal.OSProcess;
+import com.gemstone.gemfire.internal.logging.LogService;
+
+import com.gemstone.gemfire.test.dunit.standalone.DUnitLauncher.MasterRemote;
+
+/**
+ * @author dsmith
+ *
+ */
+public class ChildVM {
+
+ static {
+ createHydraLogWriter();
+ }
+
+ private final static Logger logger = LogService.getLogger();
+
+ public static void main(String[] args) throws Throwable {
+ try {
+ int namingPort = Integer.getInteger(DUnitLauncher.RMI_PORT_PARAM).intValue();
+ int vmNum = Integer.getInteger(DUnitLauncher.VM_NUM_PARAM).intValue();
+ int pid = OSProcess.getId();
+ logger.info("VM" + vmNum + " is launching" + (pid > 0? " with PID " + pid : ""));
+ MasterRemote holder = (MasterRemote) Naming.lookup("//localhost:" + namingPort + "/" + DUnitLauncher.MASTER_PARAM);
+ DUnitLauncher.init(holder);
+ DUnitLauncher.locatorPort = holder.getLocatorPort();
+ Naming.rebind("//localhost:" + namingPort + "/vm" + vmNum, new RemoteDUnitVM());
+ holder.signalVMReady();
+ //This loop is here so this VM will die even if the master is mean killed.
+ while(true) {
+ holder.ping();
+ Thread.sleep(1000);
+ }
+ } catch (Throwable t) {
+ t.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void createHydraLogWriter() {
+ try {
+ Log.createLogWriter("dunit-childvm", "fine");
+ } catch (HydraRuntimeException ignore) {
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/standalone/DUnitLauncher.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/standalone/DUnitLauncher.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/standalone/DUnitLauncher.java
new file mode 100644
index 0000000..5d27004
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/standalone/DUnitLauncher.java
@@ -0,0 +1,416 @@
+/*=========================================================================
+ * Copyright (c) 2002-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
+ * more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.test.dunit.standalone;
+
+import hydra.Log;
+import hydra.MethExecutorResult;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.net.InetAddress;
+import java.net.URISyntaxException;
+import java.nio.channels.FileChannel;
+import java.nio.charset.Charset;
+import java.rmi.AccessException;
+import java.rmi.AlreadyBoundException;
+import java.rmi.NotBoundException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.registry.Registry;
+import java.rmi.server.UnicastRemoteObject;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.appender.FileAppender;
+import org.apache.logging.log4j.core.config.LoggerConfig;
+import org.apache.logging.log4j.core.layout.PatternLayout;
+import org.junit.Assert;
+
+import batterytest.greplogs.ExpectedStrings;
+import batterytest.greplogs.LogConsumer;
+
+import com.gemstone.gemfire.distributed.Locator;
+import com.gemstone.gemfire.internal.AvailablePortHelper;
+import com.gemstone.gemfire.internal.logging.LogService;
+
+import com.gemstone.gemfire.test.dunit.BounceResult;
+import com.gemstone.gemfire.test.dunit.DUnitEnv;
+import com.gemstone.gemfire.test.dunit.Host;
+import com.gemstone.gemfire.test.dunit.RemoteDUnitVMIF;
+import com.gemstone.gemfire.test.dunit.SerializableCallable;
+import com.gemstone.gemfire.test.dunit.VM;
+
+/**
+ * A class to build a fake test configuration and launch some DUnit VMS.
+ *
+ * For use within eclipse. This class completely skips hydra and just starts
+ * some vms directly, creating a fake test configuration
+ *
+ * Also, it's a good idea to set your working directory, because the test code
+ * a lot of files that it leaves around.
+ *
+ * @author dsmith
+ *
+ */
+public class DUnitLauncher {
+
+ static int locatorPort;
+
+ private static final int NUM_VMS = 4;
+ private static final int DEBUGGING_VM_NUM = -1;
+ private static final int LOCATOR_VM_NUM = -2;
+
+ static final long STARTUP_TIMEOUT = 30 * 1000;
+ private static final String SUSPECT_FILENAME = "dunit_suspect.log";
+ private static File DUNIT_SUSPECT_FILE;
+
+ public static final String DUNIT_DIR = "dunit";
+ public static final String LOG_LEVEL = System.getProperty("logLevel", "config");
+ public static final String WORKSPACE_DIR_PARAM = "WORKSPACE_DIR";
+ public static final boolean LOCATOR_LOG_TO_DISK = Boolean.getBoolean("locatorLogToDisk");
+
+ static final String MASTER_PARAM = "DUNIT_MASTER";
+ static final String RMI_PORT_PARAM = "gemfire.DUnitLauncher.RMI_PORT";
+ static final String VM_NUM_PARAM = "gemfire.DUnitLauncher.VM_NUM";
+
+ private static final String LAUNCHED_PROPERTY = "gemfire.DUnitLauncher.LAUNCHED";
+
+ private DUnitLauncher() {
+ }
+
+ private static boolean isHydra() {
+ try {
+ //TODO - this is hacky way to test for a hydra environment - see
+ //if there is registered test configuration object.
+ Class<?> clazz = Class.forName("hydra.TestConfig");
+ Method getInstance = clazz.getMethod("getInstance", new Class[0]);
+ getInstance.invoke(null, null);
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+ /**
+ * Launch DUnit. If the unit test was launched through
+ * the hydra framework, leave the test alone.
+ */
+ public static void launchIfNeeded() {
+ if(System.getProperties().contains(VM_NUM_PARAM)) {
+ //we're a dunit child vm, do nothing.
+ return;
+ }
+
+ if(!isHydra() &&!isLaunched()) {
+ try {
+ launch();
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to launch dunit VMS", e);
+ }
+ }
+ }
+
+ /**
+ * Test it see if the eclise dunit environment is launched.
+ */
+ public static boolean isLaunched() {
+ return Boolean.getBoolean(LAUNCHED_PROPERTY);
+ }
+
+ public static String getLocatorString() {
+ return "localhost[" + locatorPort + "]";
+ }
+
+
+ private static void launch() throws URISyntaxException, AlreadyBoundException, IOException, InterruptedException, NotBoundException {
+// initialize the log writer that hydra uses
+ Log.createLogWriter( "dunit-master", LOG_LEVEL );
+
+ DUNIT_SUSPECT_FILE = new File(SUSPECT_FILENAME);
+ DUNIT_SUSPECT_FILE.delete();
+ DUNIT_SUSPECT_FILE.deleteOnExit();
+
+ locatorPort = AvailablePortHelper.getRandomAvailableTCPPort();
+
+ //create an RMI registry and add an object to share our tests config
+ int namingPort = AvailablePortHelper.getRandomAvailableTCPPort();
+ Registry registry = LocateRegistry.createRegistry(namingPort);
+
+ final ProcessManager processManager = new ProcessManager(namingPort, registry);
+ Master master = new Master(registry, processManager);
+ registry.bind(MASTER_PARAM, master);
+
+ Runtime.getRuntime().addShutdownHook(new Thread() {
+ public void run() {
+ processManager.killVMs();
+ }
+ });
+
+ //Create a VM for the locator
+ processManager.launchVM(LOCATOR_VM_NUM);
+
+ //Launch an initial set of VMs
+ for(int i=0; i < NUM_VMS; i++) {
+ processManager.launchVM(i);
+ }
+
+ //wait for the VMS to start up
+ if(!processManager.waitForVMs(STARTUP_TIMEOUT)) {
+ throw new RuntimeException("VMs did not start up with 30 seconds");
+ }
+
+ //populate the Host class with our stubs. The tests use this host class
+ DUnitHost host = new DUnitHost(InetAddress.getLocalHost().getCanonicalHostName(), processManager);
+ host.init(registry, NUM_VMS);
+
+ init(master);
+
+ startLocator(registry);
+ }
+
+ public static Properties getDistributedSystemProperties() {
+ Properties p = new Properties();
+ p.setProperty("locators", getLocatorString());
+ p.setProperty("mcast-port", "0");
+ p.setProperty("enable-cluster-configuration", "false");
+ p.setProperty("use-cluster-configuration", "false");
+ p.setProperty("log-level", LOG_LEVEL);
+ return p;
+ }
+
+ /**
+ * Add an appender to Log4j which sends all INFO+ messages to a separate file
+ * which will be used later to scan for suspect strings. The pattern of the
+ * messages conforms to the original log format so that hydra will be able
+ * to parse them.
+ */
+ private static void addSuspectFileAppender(final String workspaceDir) {
+ final String suspectFilename = new File(workspaceDir, SUSPECT_FILENAME).getAbsolutePath();
+
+ final LoggerContext appenderContext = ((org.apache.logging.log4j.core.Logger)
+ LogManager.getLogger(LogService.BASE_LOGGER_NAME)).getContext();
+
+ final PatternLayout layout = PatternLayout.createLayout(
+ "[%level{lowerCase=true} %date{yyyy/MM/dd HH:mm:ss.SSS z} <%thread> tid=%tid] %message%n%throwable%n", null, null,
+ Charset.defaultCharset(), true, false, "", "");
+
+ final FileAppender fileAppender = FileAppender.createAppender(suspectFilename, "true", "false",
+ DUnitLauncher.class.getName(), "true", "false", "false", "0", layout, null, null, null, appenderContext.getConfiguration());
+ fileAppender.start();
+
+ LoggerConfig loggerConfig = appenderContext.getConfiguration().getLoggerConfig(LogService.BASE_LOGGER_NAME);
+ loggerConfig.addAppender(fileAppender, Level.INFO, null);
+ }
+
+ private static void startLocator(Registry registry) throws IOException, NotBoundException {
+ RemoteDUnitVMIF remote = (RemoteDUnitVMIF) registry.lookup("vm" + LOCATOR_VM_NUM);
+ final File locatorLogFile =
+ LOCATOR_LOG_TO_DISK ? new File("locator-" + locatorPort + ".log") : new File("");
+ MethExecutorResult result = remote.executeMethodOnObject(new SerializableCallable() {
+ public Object call() throws IOException {
+ Properties p = getDistributedSystemProperties();
+ // I never want this locator to end up starting a jmx manager
+ // since it is part of the unit test framework
+ p.setProperty("jmx-manager", "false");
+ //Disable the shared configuration on this locator.
+ //Shared configuration tests create their own locator
+ p.setProperty("enable-cluster-configuration", "false");
+ Locator.startLocatorAndDS(locatorPort, locatorLogFile, p);
+ return null;
+ }
+ }, "call");
+ if(result.getException() != null) {
+ RuntimeException ex = new RuntimeException("Failed to start locator", result.getException());
+ ex.printStackTrace();
+ throw ex;
+ }
+ }
+
+ public static void init(MasterRemote master) {
+ DUnitEnv.set(new StandAloneDUnitEnv(master));
+ //fake out tests that are using a bunch of hydra stuff
+ String workspaceDir = System.getProperty(DUnitLauncher.WORKSPACE_DIR_PARAM) ;
+ workspaceDir = workspaceDir == null ? new File(".").getAbsolutePath() : workspaceDir;
+
+ addSuspectFileAppender(workspaceDir);
+
+ //Free off heap memory when disconnecting from the distributed system
+ System.setProperty("gemfire.free-off-heap-memory", "true");
+
+ //indicate that this CM is controlled by the eclipse dunit.
+ System.setProperty(LAUNCHED_PROPERTY, "true");
+ }
+
+ public static void closeAndCheckForSuspects() {
+ if (isLaunched()) {
+ final boolean skipLogMsgs = ExpectedStrings.skipLogMsgs("dunit");
+ final List<?> expectedStrings = ExpectedStrings.create("dunit");
+ final LogConsumer logConsumer = new LogConsumer(skipLogMsgs, expectedStrings, "log4j", 5);
+
+ final StringBuilder suspectStringBuilder = new StringBuilder();
+
+ BufferedReader buffReader = null;
+ FileChannel fileChannel = null;
+ try {
+ fileChannel = new FileOutputStream(DUNIT_SUSPECT_FILE, true).getChannel();
+ buffReader = new BufferedReader(new FileReader(DUNIT_SUSPECT_FILE));
+ } catch (FileNotFoundException e) {
+ System.err.println("Could not find the suspect string output file: " + e);
+ return;
+ }
+ try {
+ String line;
+ try {
+ while ((line = buffReader.readLine()) != null) {
+ final StringBuilder builder = logConsumer.consume(line);
+ if (builder != null) {
+ suspectStringBuilder.append(builder);
+ }
+ }
+ } catch (IOException e) {
+ System.err.println("Could not read the suspect string output file: " + e);
+ }
+
+ try {
+ fileChannel.truncate(0);
+ } catch (IOException e) {
+ System.err.println("Could not truncate the suspect string output file: " + e);
+ }
+
+ } finally {
+ try {
+ buffReader.close();
+ fileChannel.close();
+ } catch (IOException e) {
+ System.err.println("Could not close the suspect string output file: " + e);
+ }
+ }
+
+ if (suspectStringBuilder.length() != 0) {
+ System.err.println("Suspicious strings were written to the log during this run.\n"
+ + "Fix the strings or use DistributedTestCase.addExpectedException to ignore.\n"
+ + suspectStringBuilder);
+
+ Assert.fail("Suspicious strings were written to the log during this run.\n"
+ + "Fix the strings or use DistributedTestCase.addExpectedException to ignore.\n"
+ + suspectStringBuilder);
+ }
+ }
+ }
+
+ public interface MasterRemote extends Remote {
+ public int getLocatorPort() throws RemoteException;
+ public void signalVMReady() throws RemoteException;
+ public void ping() throws RemoteException;
+ public BounceResult bounce(int pid) throws RemoteException;
+ }
+
+ public static class Master extends UnicastRemoteObject implements MasterRemote {
+ private static final long serialVersionUID = 1178600200232603119L;
+
+ private final Registry registry;
+ private final ProcessManager processManager;
+
+
+ public Master(Registry registry, ProcessManager processManager) throws RemoteException {
+ this.processManager = processManager;
+ this.registry = registry;
+ }
+
+ public int getLocatorPort() throws RemoteException{
+ return locatorPort;
+ }
+
+ public synchronized void signalVMReady() {
+ processManager.signalVMReady();
+ }
+
+ public void ping() {
+ //do nothing
+ }
+
+ @Override
+ public BounceResult bounce(int pid) {
+ processManager.bounce(pid);
+
+ try {
+ if(!processManager.waitForVMs(STARTUP_TIMEOUT)) {
+ throw new RuntimeException("VMs did not start up with 30 seconds");
+ }
+ RemoteDUnitVMIF remote = (RemoteDUnitVMIF) registry.lookup("vm" + pid);
+ return new BounceResult(pid, remote);
+ } catch (RemoteException | NotBoundException e) {
+ throw new RuntimeException("could not lookup name", e);
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Failed waiting for VM", e);
+ }
+ }
+ }
+
+ private static class DUnitHost extends Host {
+ private static final long serialVersionUID = -8034165624503666383L;
+
+ private transient final VM debuggingVM;
+
+ private transient ProcessManager processManager;
+
+ public DUnitHost(String hostName, ProcessManager processManager) throws RemoteException {
+ super(hostName);
+ this.debuggingVM = new VM(this, -1, new RemoteDUnitVM());
+ this.processManager = processManager;
+ }
+
+ public void init(Registry registry, int numVMs) throws AccessException, RemoteException, NotBoundException, InterruptedException {
+ for(int i = 0; i < numVMs; i++) {
+ RemoteDUnitVMIF remote = processManager.getStub(i);
+ addVM(i, remote);
+ }
+
+ addLocator(LOCATOR_VM_NUM, processManager.getStub(LOCATOR_VM_NUM));
+
+ addHost(this);
+ }
+
+ @Override
+ public VM getVM(int n) {
+
+ if(n == DEBUGGING_VM_NUM) {
+ //for ease of debugging, pass -1 to get the local VM
+ return debuggingVM;
+ }
+
+ int oldVMCount = getVMCount();
+ if(n >= oldVMCount) {
+ //If we don't have a VM with that number, dynamically create it.
+ try {
+ for(int i = oldVMCount; i <= n; i++) {
+ processManager.launchVM(i);
+ }
+ processManager.waitForVMs(STARTUP_TIMEOUT);
+
+ for(int i = oldVMCount; i <= n; i++) {
+ addVM(i, processManager.getStub(i));
+ }
+
+ } catch (IOException | InterruptedException | NotBoundException e) {
+ throw new RuntimeException("Could not dynamically launch vm + " + n, e);
+ }
+ }
+
+ return super.getVM(n);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/standalone/ProcessManager.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/standalone/ProcessManager.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/standalone/ProcessManager.java
new file mode 100644
index 0000000..d625892
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/standalone/ProcessManager.java
@@ -0,0 +1,228 @@
+/*=========================================================================
+ * Copyright (c) 2002-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
+ * more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.test.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 com.gemstone.gemfire.test.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;
+
+ 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) {
+ //TODO - stop it gracefully? Why bother
+ process.kill();
+ }
+ }
+ }
+
+ 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) {
+ 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();
+ 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=n",
+ "-XX:+HeapDumpOnOutOfMemoryError",
+ "-Xmx512m",
+ "-XX:MaxPermSize=256M",
+ "-Dgemfire.DEFAULT_MAX_OPLOG_SIZE=10",
+ "-Dgemfire.disallowMcastDefaults=true",
+ "-XX:MaxPermSize=256M",
+ "-ea",
+ agent,
+ ChildVM.class.getName()
+ };
+ }
+
+ /**
+ * 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 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/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/standalone/RemoteDUnitVM.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/standalone/RemoteDUnitVM.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/standalone/RemoteDUnitVM.java
new file mode 100644
index 0000000..031b706
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/standalone/RemoteDUnitVM.java
@@ -0,0 +1,136 @@
+/*=========================================================================
+ * Copyright (c) 2002-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
+ * more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.test.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 com.gemstone.gemfire.test.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(boolean disconnect, boolean runShutdownHook)
+ throws RemoteException {
+ }
+
+ public void disconnectVM()
+ throws RemoteException {
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/standalone/StandAloneDUnitEnv.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/standalone/StandAloneDUnitEnv.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/standalone/StandAloneDUnitEnv.java
new file mode 100644
index 0000000..8746a70
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/standalone/StandAloneDUnitEnv.java
@@ -0,0 +1,66 @@
+/*=========================================================================
+ * 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.standalone;
+
+import java.io.File;
+import java.rmi.RemoteException;
+import java.util.Properties;
+
+import com.gemstone.gemfire.test.dunit.BounceResult;
+import com.gemstone.gemfire.test.dunit.DUnitEnv;
+import com.gemstone.gemfire.test.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/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/BasicDUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/BasicDUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/BasicDUnitTest.java
new file mode 100644
index 0000000..d0b1710
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/BasicDUnitTest.java
@@ -0,0 +1,124 @@
+/*=========================================================================
+ * 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.tests;
+
+import static com.gemstone.gemfire.test.dunit.Assert.*;
+import static org.hamcrest.Matchers.*;
+
+import java.util.Properties;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.gemstone.gemfire.test.dunit.AsyncInvocation;
+import com.gemstone.gemfire.test.dunit.DistributedTestCase;
+import com.gemstone.gemfire.test.dunit.Host;
+import com.gemstone.gemfire.test.dunit.RMIException;
+import com.gemstone.gemfire.test.dunit.VM;
+
+/**
+ * This class tests the basic functionality of the distributed unit
+ * test framework.
+ */
+public class BasicDUnitTest extends DistributedTestCase {
+ private static final long serialVersionUID = 1L;
+
+ private static final String REMOTE_THROW_EXCEPTION_MESSAGE = "Throwing remoteThrowException";
+
+ private static Properties bindings = new Properties();
+
+ /**
+ * Tests how the DUnit framework handles an error
+ */
+ @Test(expected = RMIException.class)
+ public void testDontCatchRemoteException() {
+ Host host = Host.getHost(0);
+ VM vm = host.getVM(0);
+ vm.invoke(getClass(), "remoteThrowException");
+ }
+
+ @Test
+ public void testRemoteInvocationWithException() {
+ Host host = Host.getHost(0);
+ VM vm = host.getVM(0);
+ try {
+ vm.invoke(getClass(), "remoteThrowException");
+ fail("Should have thrown a BasicTestException");
+
+ } catch (RMIException expected) {
+ Throwable cause = expected.getCause();
+ assertThat(cause, is(instanceOf(BasicTestException.class)));
+ assertThat(cause.getMessage(), is("Throwing remoteThrowException"));
+ }
+ }
+
+ @Test
+ 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();
+ 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());
+ }
+ }
+
+ @Test
+ public void testRemoteInvokeAsyncWithException() throws InterruptedException {
+ Host host = Host.getHost(0);
+ VM vm = host.getVM(0);
+
+ AsyncInvocation ai = vm.invokeAsync(this.getClass(), "remoteThrowException");
+ ai.join();
+ assertTrue(ai.exceptionOccurred());
+ Throwable ex = ai.getException();
+ assertTrue(ex instanceof BasicTestException);
+ }
+
+ @Test
+ @Ignore("not implemented")
+ public void testRemoteInvocationBoolean() {
+ }
+
+ /**
+ * Accessed via reflection. DO NOT REMOVE
+ */
+ protected static void remoteThrowException() {
+ throw new BasicTestException(REMOTE_THROW_EXCEPTION_MESSAGE);
+ }
+
+ protected static void remoteBind(String name, String s) {
+ new BasicDUnitTest().getSystem(); // forces connection
+ bindings.setProperty(name, s);
+ }
+
+ protected static void remoteValidateBind(String name, String expected) {
+ assertEquals(expected, bindings.getProperty(name));
+ }
+
+ protected static class BasicTestException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ public BasicTestException() {
+ super();
+ }
+
+ public BasicTestException(String message) {
+ super(message);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/DUnitFrameworkTestSuite.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/DUnitFrameworkTestSuite.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/DUnitFrameworkTestSuite.java
new file mode 100755
index 0000000..82664b2
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/DUnitFrameworkTestSuite.java
@@ -0,0 +1,16 @@
+package com.gemstone.gemfire.test.dunit.tests;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ BasicDUnitTest.class,
+ VMDUnitTest.class,
+})
+/**
+ * Suite of tests for the test.dunit DUnit Test framework.
+ */
+public class DUnitFrameworkTestSuite {
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/TestFailure.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/TestFailure.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/TestFailure.java
new file mode 100644
index 0000000..d6d89e3
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/TestFailure.java
@@ -0,0 +1,37 @@
+/*=========================================================================
+ * 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.tests;
+
+import static org.junit.Assert.*;
+
+import com.gemstone.gemfire.test.dunit.DistributedTestCase;
+
+/**
+ * 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 {
+ private static final long serialVersionUID = 1L;
+
+ 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/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/VMDUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/VMDUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/VMDUnitTest.java
new file mode 100644
index 0000000..12faffe
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/VMDUnitTest.java
@@ -0,0 +1,245 @@
+/*=========================================================================
+ * 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.tests;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+import java.io.Serializable;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.junit.Test;
+
+import com.gemstone.gemfire.test.dunit.AsyncInvocation;
+import com.gemstone.gemfire.test.dunit.DistributedTestCase;
+import com.gemstone.gemfire.test.dunit.Host;
+import com.gemstone.gemfire.test.dunit.RMIException;
+import com.gemstone.gemfire.test.dunit.VM;
+
+/**
+ * This class tests the functionality of the {@link VM} class.
+ */
+public class VMDUnitTest extends DistributedTestCase {
+ private static final long serialVersionUID = 1L;
+
+ 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";
+
+ private static final AtomicInteger COUNTER = new AtomicInteger();
+
+ @Test
+ public void testInvokeNonExistentMethod() {
+ 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);
+ }
+ }
+
+ @Test
+ public void testInvokeStaticBoolean() {
+ Host host = Host.getHost(0);
+ VM vm = host.getVM(0);
+ assertEquals(BOOLEAN_VALUE, vm.invokeBoolean(VMDUnitTest.class, "remoteBooleanMethod"));
+ }
+
+ @Test
+ public void testInvokeStaticBooleanNotBoolean() {
+ 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) {
+ String s = "Method \"remoteByteMethod\" in class \"" + getClass().getName() + "\" returned a \"" + Byte.class.getName() + "\" expected a boolean";
+ assertThat(ex.getMessage(), equalTo(s));
+ }
+ }
+
+ @Test
+ public void testInvokeStaticLong() {
+ Host host = Host.getHost(0);
+ VM vm = host.getVM(0);
+ assertEquals(LONG_VALUE, vm.invokeLong(VMDUnitTest.class, "remoteLongMethod"));
+ }
+
+ @Test
+ public void testInvokeStaticLongNotLong() {
+ 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) {
+ String s = "Method \"remoteByteMethod\" in class \"" + getClass().getName() + "\" returned a \"" + Byte.class.getName() + "\" expected a long";
+ assertThat(ex.getMessage(), equalTo(s));
+ }
+ }
+
+ @Test
+ public void testInvokeInstanceLong() {
+ Host host = Host.getHost(0);
+ VM vm = host.getVM(0);
+ assertEquals(LONG_VALUE, vm.invokeLong(new ClassWithLong(), "getLong"));
+ }
+
+ @Test
+ public void testInvokeInstanceLongNotLong() {
+ 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) {
+ String s = "Method \"getByte\" in class \"" + ClassWithByte.class.getName() + "\" returned a \"" + Byte.class.getName() + "\" expected a long";
+ assertThat(ex.getMessage(), equalTo(s));
+ }
+ }
+
+ @Test
+ public void testInvokeInstance() {
+ Host host = Host.getHost(0);
+ VM vm = host.getVM(0);
+ assertEquals(STRING_VALUE, vm.invoke(new ClassWithString(), "getString"));
+ }
+
+ @Test
+ public void testInvokeRunnable() {
+ 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);
+ }
+ }
+
+ @Test
+ 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());
+ }
+
+ protected static Integer getAndIncStaticCount() {
+ return new Integer(COUNTER.getAndIncrement());
+ }
+
+ protected static Integer incrementStaticCount(Integer inc) {
+ return new Integer(COUNTER.addAndGet(inc.intValue()));
+ }
+
+ protected static void incStaticCount() {
+ COUNTER.incrementAndGet();
+ }
+
+ /**
+ * Accessed via reflection. DO NOT REMOVE
+ */
+ protected static byte remoteByteMethod() {
+ return BYTE_VALUE;
+ }
+
+ /**
+ * Accessed via reflection. DO NOT REMOVE
+ */
+ protected static boolean remoteBooleanMethod() {
+ return BOOLEAN_VALUE;
+ }
+
+ /**
+ * Accessed via reflection. DO NOT REMOVE
+ */
+ protected static long remoteLongMethod() {
+ return LONG_VALUE;
+ }
+
+ protected static class InvokeRunnable implements Serializable, Runnable {
+ private static final long serialVersionUID = 1L;
+ @Override
+ public void run() {
+ throw new BasicDUnitTest.BasicTestException();
+ }
+ }
+
+ protected static class ClassWithString implements Serializable {
+ private static final long serialVersionUID = 1L;
+ public String getString() {
+ return STRING_VALUE;
+ }
+ }
+
+ protected 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());
+ }
+ }
+
+ protected static class ClassWithLong implements Serializable {
+ private static final long serialVersionUID = 1L;
+ public long getLong() {
+ return LONG_VALUE;
+ }
+ }
+
+ protected static class ClassWithByte implements Serializable {
+ private static final long serialVersionUID = 1L;
+ public byte getByte() {
+ return BYTE_VALUE;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/dunit/DistributedTestCase.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/dunit/DistributedTestCase.java b/gemfire-core/src/test/java/dunit/DistributedTestCase.java
index 8aa8b6d..d26d3e1 100755
--- a/gemfire-core/src/test/java/dunit/DistributedTestCase.java
+++ b/gemfire-core/src/test/java/dunit/DistributedTestCase.java
@@ -144,7 +144,7 @@ public abstract class DistributedTestCase extends TestCase implements java.io.Se
vm.invoke(new SerializableRunnable("Attach Debugger") {
public void run() {
com.gemstone.gemfire.internal.util.DebuggerSupport.
- waitForJavaDebugger(getSystem().getLogWriter().convertToLogWriterI18n(), msg);
+ waitForJavaDebugger(msg);
}
});
}
@@ -526,7 +526,7 @@ public abstract class DistributedTestCase extends TestCase implements java.io.Se
* NOTE: if you use this method be sure that you clean up the VM before the end of your
* test with disconnectFromDS() or disconnectAllFromDS().
*/
- public boolean crashDistributedSystem(VM vm) {
+ public static boolean crashDistributedSystem(VM vm) {
return (Boolean)vm.invoke(new SerializableCallable("crash distributed system") {
public Object call() throws Exception {
DistributedSystem msys = InternalDistributedSystem.getAnyInstance();
@@ -544,7 +544,7 @@ public abstract class DistributedTestCase extends TestCase implements java.io.Se
* NOTE: if you use this method be sure that you clean up the VM before the end of your
* test with disconnectFromDS() or disconnectAllFromDS().
*/
- public void crashDistributedSystem(final DistributedSystem msys) {
+ public static void crashDistributedSystem(final DistributedSystem msys) {
MembershipManagerHelper.inhibitForcedDisconnectLogging(true);
MembershipManagerHelper.playDead(msys);
JChannel c = MembershipManagerHelper.getJChannel(msys);
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/dunit/VM.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/dunit/VM.java b/gemfire-core/src/test/java/dunit/VM.java
index 323dbfb..537c53b 100644
--- a/gemfire-core/src/test/java/dunit/VM.java
+++ b/gemfire-core/src/test/java/dunit/VM.java
@@ -14,8 +14,6 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.rmi.RemoteException;
import java.util.concurrent.Callable;
-//import java.util.Iterator;
-//import java.util.Vector;
/**
* This class represents a Java Virtual Machine that runs on a host.
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/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
index 5b38816..965b1ab 100644
--- a/gemfire-core/src/test/java/dunit/standalone/ProcessManager.java
+++ b/gemfire-core/src/test/java/dunit/standalone/ProcessManager.java
@@ -157,7 +157,7 @@ public class ProcessManager {
"-XX:MaxPermSize=256M",
"-ea",
agent,
- "dunit.standalone.ChildVM"
+ ChildVM.class.getName()
};
}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/categories/MembershipTest.java
----------------------------------------------------------------------
diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/categories/MembershipTest.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/categories/MembershipTest.java
new file mode 100755
index 0000000..458eaad
--- /dev/null
+++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/categories/MembershipTest.java
@@ -0,0 +1,9 @@
+package com.gemstone.gemfire.test.junit.categories;
+
+/**
+ * JUnit Test Category that specifies a test involving membership in a distributed system.
+ *
+ * @author Kirk Lund
+ */
+public class MembershipTest {
+}