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/26 01:17:48 UTC

[3/3] incubator-geode git commit: New rules and packages for test rules

New rules and packages for test rules


Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/89c0b437
Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/89c0b437
Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/89c0b437

Branch: refs/heads/feature/GEODE-217
Commit: 89c0b43764b2c9847d2096237ac126e839e2bcf1
Parents: b932d8b
Author: Kirk Lund <kl...@pivotal.io>
Authored: Tue Aug 25 16:16:42 2015 -0700
Committer: Kirk Lund <kl...@pivotal.io>
Committed: Tue Aug 25 16:16:42 2015 -0700

----------------------------------------------------------------------
 .../distributed/DistributedMemberDUnitTest.java |  97 +-
 .../distributed/HostedLocatorsDUnitTest.java    |  27 +-
 .../test/assertj/AssertJExampleJUnitTest.java   | 119 ---
 .../CatchExceptionExampleDUnitTest.java         |  62 --
 .../CatchExceptionExampleJUnitTest.java         |  99 --
 .../gemstone/gemfire/test/dunit/DUnitEnv.java   |   2 +-
 .../gemfire/test/dunit/DUnitTestRule.java       | 898 +++++++++----------
 .../DistributedRestoreSystemProperties.java     |  67 ++
 ...ributedRestoreSystemPropertiesDUnitTest.java | 130 +++
 ...ributedRestoreSystemPropertiesJUnitTest.java |  74 ++
 .../dunit/tests/DUnitTestRuleTestSuite.java     |  28 +
 .../gemfire/test/dunit/tests/MyTestSuite.java   |   2 +-
 .../test/examples/AssertJExampleJUnitTest.java  | 119 +++
 .../CatchExceptionExampleDUnitTest.java         |  62 ++
 .../CatchExceptionExampleJUnitTest.java         |  99 ++
 .../gemfire/test/junit/IgnoreUntil.java         |   2 +-
 .../com/gemstone/gemfire/test/junit/Repeat.java |   1 +
 .../test/junit/rules/IgnoreUntilRule.java       |   2 +-
 .../gemfire/test/junit/rules/RepeatRule.java    |  10 +-
 .../rules/SerializableExternalResource.java     |  51 ++
 .../rules/SerializableTemporaryFolder.java      |   6 +
 .../test/junit/rules/SerializableTestName.java  |   6 +
 .../junit/rules/SerializableTestWatcher.java    |   6 +
 .../test/junit/rules/SerializableTimeout.java   |   6 +
 .../RepeatingTestCasesExampleJUnitTest.java     |  75 ++
 .../examples/RetryRuleExampleJUnitTest.java     |  28 +
 .../tests/ExpectedTimeoutRuleJUnitTest.java     |   8 +-
 .../rules/tests/IgnoreUntilRuleJUnitTest.java   | 110 +++
 .../junit/rules/tests/RepeatRuleJUnitTest.java  |  56 +-
 .../RetryRuleGlobalWithErrorJUnitTest.java      |   8 +-
 .../RetryRuleGlobalWithExceptionJUnitTest.java  |   8 +-
 .../tests/RetryRuleLocalWithErrorJUnitTest.java |   8 +-
 .../RetryRuleLocalWithExceptionJUnitTest.java   |  17 +-
 .../gemfire/test/junit/rules/tests/RunTest.java |  21 +
 34 files changed, 1418 insertions(+), 896 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/89c0b437/gemfire-core/src/test/java/com/gemstone/gemfire/distributed/DistributedMemberDUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/distributed/DistributedMemberDUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/distributed/DistributedMemberDUnitTest.java
index 1f6edab..8084e54 100755
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/distributed/DistributedMemberDUnitTest.java
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/distributed/DistributedMemberDUnitTest.java
@@ -7,20 +7,22 @@
  */
 package com.gemstone.gemfire.distributed;
 
+import static com.gemstone.gemfire.test.dunit.DUnitTestRule.*;
+import static com.googlecode.catchexception.CatchException.*;
+import static com.jayway.awaitility.Awaitility.*;
+import static com.jayway.awaitility.Duration.*;
 import static java.util.concurrent.TimeUnit.*;
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.hamcrest.Matchers.*;
 import static org.junit.Assert.*;
-import static org.junit.Assume.*;
-import static com.jayway.awaitility.Awaitility.*;
-import static com.jayway.awaitility.Duration.*;
 
 import com.gemstone.gemfire.IncompatibleSystemException;
 import com.gemstone.gemfire.distributed.internal.DM;
 import com.gemstone.gemfire.distributed.internal.DistributionConfig;
 import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
 import com.gemstone.gemfire.distributed.internal.membership.InternalDistributedMember;
-import com.gemstone.gemfire.internal.lang.SystemUtils;
 
+import java.io.Serializable;
 import java.net.InetAddress;
 import java.util.Arrays;
 import java.util.Collections;
@@ -37,13 +39,10 @@ import org.junit.BeforeClass;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
-import org.junit.rules.ExpectedException;
 
-import com.gemstone.gemfire.test.junit.ConditionalIgnore;
 import com.gemstone.gemfire.test.junit.categories.DistributedTest;
 import com.gemstone.gemfire.test.junit.categories.MembershipTest;
-import com.gemstone.gemfire.test.junit.rules.ConditionalIgnoreRule;
-import com.gemstone.gemfire.test.dunit.DistributedTestCase;
+import com.gemstone.gemfire.test.dunit.DUnitTestRule;
 import com.gemstone.gemfire.test.dunit.Host;
 import com.gemstone.gemfire.test.dunit.RMIException;
 import com.gemstone.gemfire.test.dunit.SerializableCallable;
@@ -58,15 +57,12 @@ import com.gemstone.gemfire.test.dunit.VM;
  */
 @SuppressWarnings("serial")
 @Category({ DistributedTest.class, MembershipTest.class })
-public class DistributedMemberDUnitTest extends DistributedTestCase {
+public class DistributedMemberDUnitTest implements Serializable {
 
-  private Properties config;
-  
   @Rule
-  public final transient ExpectedException expectedException = ExpectedException.none();
+  public final DUnitTestRule dunitTestRule = new DUnitTestRule();
   
-  @Rule
-  public final transient ConditionalIgnoreRule ignoreRule = new ConditionalIgnoreRule();
+  private Properties config;
   
   @BeforeClass
   public static void beforeClass() {
@@ -154,36 +150,30 @@ public class DistributedMemberDUnitTest extends DistributedTestCase {
 
   @Test
   public void secondMemberUsingSameNameShouldFail() {
-    Host.getHost(0).getVM(0).invoke(new SerializableRunnable() {
-      public void run() {
-        Properties config = createConfig();
-        config.setProperty(DistributionConfig.NAME_NAME, "name0");
-        getSystem(config);
-      }
-    });
-    Host.getHost(0).getVM(1).invoke(new SerializableRunnable() {
-      public void run() {
-        Properties config = createConfig();
-        config.setProperty(DistributionConfig.NAME_NAME, "name1");
-        getSystem(config);
-      }
-    });
+    // arrange
+    Host.getHost(0).getVM(0).invoke(getSystemWithName("name0"));
+    Host.getHost(0).getVM(1).invoke(getSystemWithName("name1"));
     
-    expectedException.expect(RMIException.class);
-    expectedException.expectCause(isA(IncompatibleSystemException.class));
-    //expectedException.expectMessage("used the same name");
+    // act
+    catchException(Host.getHost(0).getVM(2)).invoke(getSystemWithName("name0"));
     
-    Host.getHost(0).getVM(2).invoke(new SerializableRunnable() {
+    // assert
+    assertThat(caughtException())
+        .isInstanceOf(RMIException.class);
+    
+    assertThat(caughtException().getCause())
+        .isInstanceOf(IncompatibleSystemException.class)
+        .hasMessageContaining("used the same name");
+  }
+
+  private SerializableRunnable getSystemWithName(final String name) {
+    return new SerializableRunnable() {
       public void run() {
         Properties config = createConfig();
-        config.setProperty(DistributionConfig.NAME_NAME, "name0");
-//        try {
-          getSystem(config);
-//          fail("expected IncompatibleSystemException");
-//        } catch (IncompatibleSystemException expected) {
-//        }
+        config.setProperty(DistributionConfig.NAME_NAME, name);
+        getSystem(config);
       }
-    });
+    };
   }
   
   /**
@@ -192,7 +182,7 @@ public class DistributedMemberDUnitTest extends DistributedTestCase {
    */
   @Test
   public void allMembersShouldSeeRoles() {
-    // connect all four vms...
+    // arrange
     final String[] vmRoles = new String[] {"VM_A","VM_B","VM_C","VM_D"};
     for (int i = 0; i < vmRoles.length; i++) {
       final int vm = i;
@@ -205,7 +195,7 @@ public class DistributedMemberDUnitTest extends DistributedTestCase {
       });
     }
     
-    // validate roles from each vm...
+    // act (and assert)
     for (int i = 0; i < vmRoles.length; i++) {
       final int vm = i;
       Host.getHost(0).getVM(vm).invoke(new SerializableRunnable() {
@@ -223,7 +213,7 @@ public class DistributedMemberDUnitTest extends DistributedTestCase {
           assertTrue(vmRoles[vm].equals(myRole.getName()));
           
           with().pollInterval(TWO_HUNDRED_MILLISECONDS).await().atMost(60, SECONDS).until( numberOfOtherMembers(), equalTo(3) );
-          // used to have a for-loop here
+          // Awaitility: used to have a for-loop here
           
           Set<InternalDistributedMember> members = sys.getDM().getOtherNormalDistributionManagerIds();
           for (Iterator<InternalDistributedMember> iterMembers = members.iterator(); iterMembers.hasNext();) {
@@ -262,7 +252,7 @@ public class DistributedMemberDUnitTest extends DistributedTestCase {
    */
   @Test
   public void allMembersShouldSeeGroups() {  
-    // connect all four vms...
+    // arrange
     for (int i = 0; i < 4; i++) {
       final int vm = i;
       Host.getHost(0).getVM(vm).invoke(new SerializableRunnable() {
@@ -274,7 +264,7 @@ public class DistributedMemberDUnitTest extends DistributedTestCase {
       });
     }
     
-    // validate group from each vm...
+    // act (and assert)
     for (int i = 0; i < 4; i++) {
       final int vm = i;
       Host.getHost(0).getVM(vm).invoke(new SerializableRunnable() {
@@ -351,12 +341,15 @@ public class DistributedMemberDUnitTest extends DistributedTestCase {
    */
   @Test
   public void getIdShouldIdentifyMember() {
+    // arrange
     this.config.setProperty(DistributionConfig.LOCATORS_NAME, "");
     this.config.setProperty(DistributionConfig.NAME_NAME, "foobar");
 
+    // act
     final InternalDistributedSystem system = getSystem(this.config);
     final DistributedMember member = system.getDistributedMember();
     
+    // assert
     assertThat(system.getMemberId(), is(member.getId()));
     assertThat(member.getId(), containsString("foobar"));
   }
@@ -375,6 +368,7 @@ public class DistributedMemberDUnitTest extends DistributedTestCase {
     final DistributedMember member2 = createSystemAndGetId(vm2, "name2");
     
     vm0.invoke(new SerializableCallable() { // SerializableRunnable
+      @Override
       public Object call() throws Exception { // public void run() 
         DistributedSystem system = getSystem();
         assertEquals(member0, system.findDistributedMember("name0"));
@@ -391,26 +385,11 @@ public class DistributedMemberDUnitTest extends DistributedTestCase {
         // Members will contain the locator as well. Just make sure it has the members we're looking for.
         assertTrue("Expected" + expected + " got " + members, members.containsAll(expected));
         assertEquals(4, members.size());
-//        } catch (UnknownHostException e) {
-//          fail("Unable to get IpAddress", e);
-//        }
         return null;
       }
     });
   }
   
-  @Test
-  public void linuxSpecificTest() {
-    assumeTrue(SystemUtils.isLinux());
-    // do something that is only supported on linux
-  }
-  
-  @Test
-  @ConditionalIgnore(value="#55555: summary of bug #55555", until="2016-01-01")
-  public void someBrokenTest() {
-    throw new Error("Bug #55555");
-  }
-  
   private DistributedMember createSystemAndGetId(final VM vm, final String name) {
     return (DistributedMember) vm.invoke(new SerializableCallable("create system and get member") {
       @Override

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/89c0b437/gemfire-core/src/test/java/com/gemstone/gemfire/distributed/HostedLocatorsDUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/distributed/HostedLocatorsDUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/distributed/HostedLocatorsDUnitTest.java
index f77f50d..8f5c943 100644
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/distributed/HostedLocatorsDUnitTest.java
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/distributed/HostedLocatorsDUnitTest.java
@@ -2,7 +2,6 @@ package com.gemstone.gemfire.distributed;
 
 import static com.jayway.awaitility.Awaitility.*;
 import static java.util.concurrent.TimeUnit.*;
-import static org.hamcrest.Matchers.*;
 import static org.junit.Assert.*;
 
 import java.io.File;
@@ -16,9 +15,7 @@ import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.contrib.java.lang.system.RestoreSystemProperties;
 import org.junit.experimental.categories.Category;
-import org.junit.rules.Timeout;
 
 import com.gemstone.gemfire.distributed.AbstractLauncher.Status;
 import com.gemstone.gemfire.distributed.LocatorLauncher.Builder;
@@ -35,9 +32,9 @@ import com.gemstone.gemfire.test.dunit.DistributedTestCase;
 import com.gemstone.gemfire.test.dunit.Host;
 import com.gemstone.gemfire.test.dunit.SerializableCallable;
 import com.gemstone.gemfire.test.dunit.SerializableRunnable;
+import com.gemstone.gemfire.test.dunit.rules.DistributedRestoreSystemProperties;
 import com.gemstone.gemfire.test.junit.categories.DistributedTest;
 import com.gemstone.gemfire.test.junit.categories.MembershipTest;
-import com.gemstone.gemfire.test.junit.rules.RetryRule;
 
 /**
  * Extracted from LocatorLauncherLocalJUnitTest.
@@ -54,14 +51,8 @@ public class HostedLocatorsDUnitTest extends DistributedTestCase {
   protected transient volatile int locatorPort;
   protected transient volatile LocatorLauncher launcher;
   
-  @Rule // not serializable and yet we're setting/clearing in other JVMs
-  public final transient RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties();
-  
-  @Rule
-  public final transient Timeout globalTimeout = Timeout.seconds(2 * 60 * 1000);
-  
   @Rule
-  public final transient RetryRule retry = new RetryRule(2);
+  public final DistributedRestoreSystemProperties restoreSystemProperties = new DistributedRestoreSystemProperties();
   
   @Before
   public void setUp() throws Exception {
@@ -85,7 +76,7 @@ public class HostedLocatorsDUnitTest extends DistributedTestCase {
     final String uniqueName = getUniqueName();
     for (int i = 0 ; i < 4; i++) {
       final int whichvm = i;
-      Host.getHost(0).getVM(whichvm).invoke(new SerializableCallable() {
+      Host.getHost(0).getVM(whichvm).invoke(new SerializableCallable<Object>() {
         @Override
         public Object call() throws Exception {
           try {
@@ -105,7 +96,7 @@ public class HostedLocatorsDUnitTest extends DistributedTestCase {
     
             launcher = builder.build();
             assertEquals(Status.ONLINE, launcher.start().getStatus());
-            //was: waitForLocatorToStart(launcher, TIMEOUT_MILLISECONDS, 10, true);
+            //was: waitForLocatorToStart(launcher, TIMEOUT_MILLISECONDS, 10, true); --> Awaitility
             with().pollInterval(10, MILLISECONDS).await().atMost(5, MINUTES).until( isLocatorStarted() );
             return null;
           } finally {
@@ -181,14 +172,6 @@ public class HostedLocatorsDUnitTest extends DistributedTestCase {
     }
   }
 
-  @Test
-  public void unreliableTestWithRaceConditions() {
-    count++;
-    if (count < 2) {
-      assertThat(count, is(2)); // doomed to fail
-    }
-  }
-  
   private Callable<Boolean> isLocatorStarted() {
     return new Callable<Boolean>() {
       public Boolean call() throws Exception {
@@ -220,6 +203,4 @@ public class HostedLocatorsDUnitTest extends DistributedTestCase {
     }
     assertTrue(message, done);
   }
-  
-  private static int count = 0;
 }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/89c0b437/gemfire-core/src/test/java/com/gemstone/gemfire/test/assertj/AssertJExampleJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/assertj/AssertJExampleJUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/assertj/AssertJExampleJUnitTest.java
deleted file mode 100755
index aaa6a84..0000000
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/test/assertj/AssertJExampleJUnitTest.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package com.gemstone.gemfire.test.assertj;
-
-import static org.assertj.core.api.Assertions.*;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-import com.gemstone.gemfire.test.junit.categories.UnitTest;
-
-@Category(UnitTest.class)
-public class AssertJExampleJUnitTest {
-
-  private Character aragorn;
-  private Character boromir;
-  private Character elrond;
-  private Character frodo;
-  private Character galadriel;
-  private Character gandalf;
-  private Character gimli;
-  private Character legolas;
-  private Character merry;
-  private Character pippin;
-  private Character sauron;
-  private Character sam;
-  
-  private Ring narya;
-  private Ring nenya;
-  private Ring oneRing;
-  private Ring vilya;
-  
-  private Set<Character> fellowshipOfTheRing;
-  private Map<Ring, Character> ringBearers;
-  
-  @Before
-  public void setUp() {
-    this.aragorn = new Character("Aragorn");
-    this.boromir = new Character("Boromir");
-    this.elrond = new Character("Elrond");
-    this.frodo = new Character("Frodo");
-    this.galadriel = new Character("Galadriel");
-    this.gandalf = new Character("Gandalf");
-    this.gimli = new Character("Gimli");
-    this.legolas = new Character("Legolas");
-    this.merry = new Character("Merry");
-    this.pippin = new Character("Pippin");
-    this.sauron = new Character("Sauron");
-    this.sam = new Character("Sam");
-    
-    this.narya = new Ring();
-    this.nenya = new Ring();
-    this.oneRing = new Ring();
-    this.vilya = new Ring();
-    
-    this.fellowshipOfTheRing = new HashSet<Character>();
-    this.fellowshipOfTheRing.add(this.aragorn);
-    this.fellowshipOfTheRing.add(this.boromir);
-    this.fellowshipOfTheRing.add(this.frodo);
-    this.fellowshipOfTheRing.add(this.gandalf);
-    this.fellowshipOfTheRing.add(this.gimli);
-    this.fellowshipOfTheRing.add(this.legolas);
-    this.fellowshipOfTheRing.add(this.merry);
-    this.fellowshipOfTheRing.add(this.pippin);
-    this.fellowshipOfTheRing.add(this.sam);
-
-    this.ringBearers = new HashMap<Ring, Character>();
-    this.ringBearers.put(this.oneRing, this.frodo);
-    this.ringBearers.put(this.nenya, this.galadriel);
-    this.ringBearers.put(this.narya, this.gandalf);
-    this.ringBearers.put(this.vilya, this.elrond);
-  }
-  
-  @Test
-  public void exampleShouldPass() {
-    // common assertions
-    assertThat(frodo.getName()).isEqualTo("Frodo");
-    assertThat(frodo).isNotEqualTo(sauron)
-                     .isIn(fellowshipOfTheRing);
-
-    // String specific assertions
-    assertThat(frodo.getName()).startsWith("Fro")
-                               .endsWith("do")
-                               .isEqualToIgnoringCase("frodo");
-
-    // collection specific assertions
-    assertThat(fellowshipOfTheRing).hasSize(9)
-                                   .contains(frodo, sam)
-                                   .doesNotContain(sauron);
-
-    // using extracting magical feature to check fellowshipOfTheRing characters name :)
-    assertThat(fellowshipOfTheRing).extracting("name").contains("Boromir", "Gandalf", "Frodo", "Legolas")
-                                                      .doesNotContain("Sauron", "Elrond");
-
-    // map specific assertions, ringBearers initialized with the elves rings and the one ring bearers.
-    assertThat(ringBearers).hasSize(4)
-                           .contains(entry(oneRing, frodo), entry(nenya, galadriel))
-                           .doesNotContainEntry(oneRing, aragorn);  
-  }
-  
-  protected static class Character {
-    private final String name;
-    public Character(final String name) {
-      this.name = name;
-    }
-    public String getName() {
-      return this.name;
-    }
-  }
-  
-  protected static class Ring {
-    public Ring() {
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/89c0b437/gemfire-core/src/test/java/com/gemstone/gemfire/test/catchexception/CatchExceptionExampleDUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/catchexception/CatchExceptionExampleDUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/catchexception/CatchExceptionExampleDUnitTest.java
deleted file mode 100755
index f85018c..0000000
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/test/catchexception/CatchExceptionExampleDUnitTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.gemstone.gemfire.test.catchexception;
-
-import static com.googlecode.catchexception.CatchException.*;
-import static org.assertj.core.api.Assertions.*;
-
-import java.io.Serializable;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-import com.gemstone.gemfire.test.dunit.DUnitTestRule;
-import com.gemstone.gemfire.test.dunit.Host;
-import com.gemstone.gemfire.test.dunit.RMIException;
-import com.gemstone.gemfire.test.dunit.SerializableCallable;
-import com.gemstone.gemfire.test.dunit.VM;
-import com.gemstone.gemfire.test.junit.categories.DistributedTest;
-
-/**
- * Using Catch-Exception works well for remote exceptions and asserting details
- * about root cause of RMIExceptions in DUnit tests.
- */
-@Category(DistributedTest.class)
-@SuppressWarnings("serial")
-public class CatchExceptionExampleDUnitTest implements Serializable {
-
-  private static final String REMOTE_THROW_EXCEPTION_MESSAGE = "Throwing remoteThrowException";
-
-  @Rule
-  public final DUnitTestRule dunitTestRule = new DUnitTestRule();
-  
-  @Test
-  public void testRemoteInvocationWithException() {
-    Host host = Host.getHost(0);
-    VM vm = host.getVM(0);
-
-    catchException(vm).invoke(new ThrowBasicTestException());
-
-    assertThat(caughtException())
-        .isInstanceOf(RMIException.class)
-        .hasCause(new BasicTestException(REMOTE_THROW_EXCEPTION_MESSAGE));
-  }
-  
-  protected static class ThrowBasicTestException extends SerializableCallable<Object> {
-
-    @Override
-    public Object call() throws Exception {
-      throw new BasicTestException(REMOTE_THROW_EXCEPTION_MESSAGE);
-    }
-  }
-  
-  protected static class BasicTestException extends RuntimeException {
-
-    public BasicTestException() {
-      super();
-    }
-    
-    public BasicTestException(String message) {
-      super(message);
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/89c0b437/gemfire-core/src/test/java/com/gemstone/gemfire/test/catchexception/CatchExceptionExampleJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/catchexception/CatchExceptionExampleJUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/catchexception/CatchExceptionExampleJUnitTest.java
deleted file mode 100755
index 73dc361..0000000
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/test/catchexception/CatchExceptionExampleJUnitTest.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package com.gemstone.gemfire.test.catchexception;
-
-import static com.googlecode.catchexception.CatchException.*;
-import static com.googlecode.catchexception.apis.BDDCatchException.when;
-import static com.googlecode.catchexception.apis.CatchExceptionHamcrestMatchers.*;
-import static org.assertj.core.api.BDDAssertions.*;
-import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.*;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-import com.gemstone.gemfire.test.junit.categories.UnitTest;
-
-/**
- * Simple unit tests exercising Catch-Exception with AssertJ, Hamcrest and JUnit.
- */
-@Category(UnitTest.class)
-public class CatchExceptionExampleJUnitTest {
-
-  @Test
-  public void catchExceptionShouldCatchException() {
-    List<?> myList = new ArrayList<Object>();
-
-    // when: we try to get the first element of the list
-    // then: catch the exception if any is thrown
-    catchException(myList).get(1);
-    
-    // then: we expect an IndexOutOfBoundsException
-    assertThat(caughtException(), is(instanceOf(IndexOutOfBoundsException.class)));
-  }
-  
-  @Test
-  public void verifyExceptionShouldCatchException() {
-    List<?> myList = new ArrayList<Object>();
-
-    // when: we try to get the first element of the list
-    // then: catch the exception if any is thrown
-    // then: we expect an IndexOutOfBoundsException
-    verifyException(myList, IndexOutOfBoundsException.class).get(1);
-  }
-  
-  @Test
-  public void whenShouldCatchExceptionAndUseAssertJAssertion() {
-    // given: an empty list
-    List<?> myList = new ArrayList<Object>();
-
-    // when: we try to get the first element of the list
-    when(myList).get(1);
-
-    // then: we expect an IndexOutOfBoundsException
-    then(caughtException())
-            .isInstanceOf(IndexOutOfBoundsException.class)
-            .hasMessage("Index: 1, Size: 0")
-            .hasNoCause();
-  }
-  
-  @Test
-  public void catchExceptionShouldCatchExceptionAndUseHamcrestAssertion() {
-    // given: an empty list
-    List<?> myList = new ArrayList<Object>();
-
-    // when: we try to get the first element of the list
-    catchException(myList).get(1);
-
-    // then: we expect an IndexOutOfBoundsException with message "Index: 1, Size: 0"
-    assertThat(caughtException(),
-      allOf(
-        instanceOf(IndexOutOfBoundsException.class),
-        hasMessage("Index: 1, Size: 0"),
-        hasNoCause()
-      )
-    );
-  }
-  
-  @Test
-  public void shouldCatchFromThrowException() throws Exception {
-    String message = "error message";
-    
-    catchException(this).throwException(message);
-    
-    assertThat(caughtException(), is(instanceOf(Exception.class)));
-  }
-  
-  @Test
-  public void shouldVerifyFromThrowException() throws Exception {
-    String message = "error message";
-
-    verifyException(this).throwException(message);
-  }
-  
-  // fails if private
-  protected void throwException(final String message) throws Exception {
-    throw new Exception(message);
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/89c0b437/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DUnitEnv.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DUnitEnv.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DUnitEnv.java
index 064cde9..e00d4b1 100644
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DUnitEnv.java
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DUnitEnv.java
@@ -78,7 +78,7 @@ public abstract class DUnitEnv {
   // static methods
   //---------------------------------------------------------------------------
   
-  public static final Properties getAllDistributedSystemProperties(Properties props) { // TODO: delete
+  public static final Properties getAllDistributedSystemProperties(final Properties props) { // TODO: delete
     Properties p = DUnitEnv.get().getDistributedSystemProperties();
     
     // our tests do not expect auto-reconnect to be on by default

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/89c0b437/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DUnitTestRule.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DUnitTestRule.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DUnitTestRule.java
index 94f8d91..ee9b841 100755
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DUnitTestRule.java
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DUnitTestRule.java
@@ -38,9 +38,7 @@ import com.gemstone.gemfire.internal.cache.tier.InternalBridgeMembership;
 import com.gemstone.gemfire.internal.cache.tier.sockets.CacheServerTestUtil;
 import com.gemstone.gemfire.internal.cache.tier.sockets.ClientProxyMembershipID;
 import com.gemstone.gemfire.internal.cache.tier.sockets.DataSerializerPropogationDUnitTest;
-import com.gemstone.gemfire.internal.logging.InternalLogWriter;
 import com.gemstone.gemfire.internal.logging.LogService;
-import com.gemstone.gemfire.internal.logging.log4j.LogWriterLogger;
 import com.gemstone.gemfire.management.internal.cli.LogWrapper;
 import com.gemstone.gemfire.test.dunit.standalone.DUnitLauncher;
 import com.gemstone.org.jgroups.stack.IpAddress;
@@ -49,21 +47,31 @@ import com.gemstone.org.jgroups.util.GemFireTracer;
 
 @SuppressWarnings("serial")
 public class DUnitTestRule implements TestRule, Serializable {
+  private static final Logger logger = LogService.getLogger();
+
+  private static final String LOG_PER_TEST_CLASS_PROPERTY = "dunitLogPerTest";
 
-  private static volatile String testClassName;
-  private static volatile String testMethodName;
-  
   private volatile String className;
   private volatile String methodName;
   
-  private final DUnitTestCase distTestCase;
+  private static class StaticContext {
+    private static volatile boolean logPerTestClass;
+    private static volatile boolean logPerTestMethod;
+
+    private static volatile InternalDistributedSystem system;
+    private static volatile String previousSystemCreatedInTestClass;
+    private static volatile Properties previousProperties;
+    
+    private static volatile String testClassName;
+    private static volatile String testMethodName;
+  }
   
-  protected DUnitTestRule(Builder builder) {
-    this.distTestCase = new DUnitTestCase();
+  protected DUnitTestRule(final Builder builder) {
+    this();
   }
   
   public DUnitTestRule() {
-    this.distTestCase = new DUnitTestCase();
+    StaticContext.logPerTestClass = Boolean.getBoolean(LOG_PER_TEST_CLASS_PROPERTY);
   }
   
   @Override
@@ -75,27 +83,22 @@ public class DUnitTestRule implements TestRule, Serializable {
   /**
    * Invoked when a test is about to start
    */
-  protected void starting(Description description) {
+  protected void starting(final Description description) {
     this.className = description.getClassName();
     this.methodName = description.getMethodName();
     
-    testClassName = this.className;
-    testMethodName = this.methodName;
+    StaticContext.testClassName = this.className;
+    StaticContext.testMethodName = this.methodName;
   }
   
   protected void before() throws Throwable {
     DUnitLauncher.launchIfNeeded();
     
-    this.distTestCase.setUpDistributedTestCase();
+    setUpDistributedTestCase();
   }
 
   protected void after() throws Throwable {
-    try {
-      this.distTestCase.tearDownDistributedTestCase();
-    } catch (Exception e) {
-      // TODO Auto-generated catch block
-      e.printStackTrace();
-    }
+    tearDownDistributedTestCase();
   }
   
   public String getClassName() {
@@ -106,16 +109,16 @@ public class DUnitTestRule implements TestRule, Serializable {
     return this.methodName;
   }
   
-  public final String getUniqueName() {
-    return testClassName + "_" + testMethodName;
+  public static String getUniqueName() {
+    return StaticContext.testClassName + "_" + StaticContext.testMethodName;
   }
   
   public static String getTestClassName() {
-    return testClassName;
+    return StaticContext.testClassName;
   }
   
   public static String getTestMethodName() {
-    return testMethodName;
+    return StaticContext.testMethodName;
   }
   
   private Statement statement(final Statement base) {
@@ -132,497 +135,458 @@ public class DUnitTestRule implements TestRule, Serializable {
     };
   }
   
-  public static class Builder {
-    protected Builder() {}
+  //---------------------------------------------------------------------------
+  // customization methods
+  //---------------------------------------------------------------------------
+  
+  /**
+   * Returns a <code>Properties</code> object used to configure a
+   * connection to a {@link
+   * com.gemstone.gemfire.distributed.DistributedSystem}.
+   * Unless overridden, this method will return an empty
+   * <code>Properties</code> object.
+   *
+   * @since 3.0
+   */
+  public static Properties getDistributedSystemProperties() {
+    // TODO: extension point
+    return new Properties();
+  }
 
-    public Builder vmCount(final int vmCount) {
-      return this;
+  /**
+   * Tears down the test. This method is called by the final {@link #tearDown()} method and should be overridden to
+   * perform actual test cleanup and release resources used by the test.  The tasks executed by this method are
+   * performed before the DUnit test framework using Hydra cleans up the client VMs.
+   * <p/>
+   * @throws Exception if the tear down process and test cleanup fails.
+   * @see #tearDown
+   * @see #tearDownAfter()
+   */
+  protected void tearDownBefore() throws Exception {
+    // TODO: extension point
+  }
+
+  /**
+   * Tears down the test.  Performs additional tear down tasks after the DUnit tests framework using Hydra cleans up
+   * the client VMs.  This method is called by the final {@link #tearDown()} method and should be overridden to perform
+   * post tear down activities.
+   * <p/>
+   * @throws Exception if the test tear down process fails.
+   * @see #tearDown()
+   * @see #tearDownBefore()
+   */
+  protected void tearDownAfter() throws Exception {
+    // TODO: extension point
+  }
+
+  //---------------------------------------------------------------------------
+  // public getSystem methods
+  //---------------------------------------------------------------------------
+  
+  /**
+   * Returns this VM's connection to the distributed system.  If
+   * necessary, the connection will be lazily created using the given
+   * <code>Properties</code>.  Note that this method uses hydra's
+   * configuration to determine the location of log files, etc.
+   * Note: "final" was removed so that WANTestBase can override this method.
+   * This was part of the xd offheap merge.
+   *
+   * @see hydra.DistributedConnectionMgr#connect
+   * @since 3.0
+   */
+  public static InternalDistributedSystem getSystem(final Properties properties) {
+    if (!hasPreviousSystem()) {
+      final Properties newProperties = getAllDistributedSystemProperties(properties);
+      if (StaticContext.logPerTestClass) {
+        newProperties.put(DistributionConfig.LOG_FILE_NAME, getUniqueName() + ".log");
+        newProperties.put(DistributionConfig.STATISTIC_ARCHIVE_FILE_NAME, getUniqueName() + ".gfs");
+      }
+      StaticContext.system = (InternalDistributedSystem)DistributedSystem.connect(newProperties);
+
+      StaticContext.previousSystemCreatedInTestClass = getTestClassName();
+      StaticContext.previousProperties = newProperties;
+      
+    } else {
+      boolean needNewSystem = previousPropertiesAreDifferentThan(properties);
+        
+      needNewSystem = needNewSystem || propertiesAreDifferentThanCurrentSystem(properties);
+      
+      if (needNewSystem) {
+        // the current system does not meet our needs to disconnect and
+        // call recursively to get a new system.
+        logger.info("Disconnecting from current DS in order to make a new one");
+        disconnectFromDS();
+        getSystem(properties);
+      }
     }
-    
-    public Builder logPerTest(final boolean logPerTest) {
-      return this;
+    return StaticContext.system;
+  }
+  
+  private static boolean hasPreviousSystem() {
+    if (StaticContext.system == null) {
+      StaticContext.system = InternalDistributedSystem.getAnyInstance();
     }
     
-    public Builder logPerTestClass(final boolean logPerTestClass) {
-      return this;
+    return StaticContext.system != null && StaticContext.system.isConnected();
+  }
+  
+  private static boolean previousPropertiesAreDifferentThan(final Properties properties) {
+    boolean needNewSystem = false;
+    if (!getTestClassName().equals(StaticContext.previousSystemCreatedInTestClass)) {
+      // previous system was created in a previous test class
+      final Properties newProperties = getAllDistributedSystemProperties(properties);
+      needNewSystem = !newProperties.equals(StaticContext.previousProperties);
+      if (needNewSystem) {
+        logger.info(
+            "Test class has changed and the new DS properties are not an exact match. "
+                + "Forcing DS disconnect. Old props = "
+                + StaticContext.previousProperties + "new props=" + newProperties);
+      }
     }
-    
-    public DUnitTestRule build() {
-      return new DUnitTestRule(this);
+    return needNewSystem;
+  }
+  
+  private static boolean propertiesAreDifferentThanCurrentSystem(final Properties properties) {
+    // previous system was created in this test class
+    final Properties currentProperties = StaticContext.system.getProperties();
+    for (Iterator<Map.Entry<Object,Object>> iter = properties.entrySet().iterator(); iter.hasNext(); ) {
+      final Map.Entry<Object,Object> entry = iter.next();
+      final String key = (String) entry.getKey();
+      final String value = (String) entry.getValue();
+      if (!value.equals(currentProperties.getProperty(key))) {
+        logger.info("Forcing DS disconnect. For property " + key
+                            + " old value = " + currentProperties.getProperty(key)
+                            + " new value = " + value);
+        return true;
+      }
     }
+    return false;
   }
   
-  public static class DUnitTestCase implements Serializable {
-    private static final long serialVersionUID = 1L;
-    private static final Logger logger = LogService.getLogger();
-    private static final LogWriterLogger oldLogger = LogWriterLogger.create(logger);
+  /**
+   * Returns this VM's connection to the distributed system.  If
+   * necessary, the connection will be lazily created using the
+   * <code>Properties</code> returned by {@link
+   * #getDistributedSystemProperties}.
+   *
+   * @see #getSystem(Properties)
+   *
+   * @since 3.0
+   */
+  public static InternalDistributedSystem getSystem() {
+    return getSystem(getDistributedSystemProperties());
+  }
 
-    private static InternalDistributedSystem system;
-    protected static String previousSystemCreatedInTestClass;
-    protected static Properties previousProperties;
-    
-    protected volatile boolean logPerTest = Boolean.getBoolean("dunitLogPerTest");
+  /**
+   * Returns a loner distributed system that isn't connected to other
+   * vms
+   * 
+   * @since 6.5
+   */
+  public static InternalDistributedSystem getLonerSystem() {
+    Properties props = getDistributedSystemProperties();
+    props.put(DistributionConfig.MCAST_PORT_NAME, "0");
+    props.put(DistributionConfig.LOCATORS_NAME, "");
+    return getSystem(props);
+  }
+  
+  /**
+   * Returns a loner distributed system in combination with enforceUniqueHost
+   * and redundancyZone properties.
+   * Added specifically to test scenario of defect #47181.
+   */
+  public static InternalDistributedSystem getLonerSystemWithEnforceUniqueHost() {
+    Properties props = getDistributedSystemProperties();
+    props.put(DistributionConfig.MCAST_PORT_NAME, "0");
+    props.put(DistributionConfig.LOCATORS_NAME, "");
+    props.put(DistributionConfig.ENFORCE_UNIQUE_HOST_NAME, "true");
+    props.put(DistributionConfig.REDUNDANCY_ZONE_NAME, "zone1");
+    return getSystem(props);
+  }
 
-    /**
-     * Creates a new <code>DistributedTestCase</code> test.
-     */
-    public DUnitTestCase() {
-      DUnitLauncher.launchIfNeeded();
-    }
+  /**
+   * Returns an mcast distributed system that is connected to other
+   * vms using a random mcast port.
+   */
+  public static InternalDistributedSystem getMcastSystem() {
+    Properties props = getDistributedSystemProperties();
+    int port = AvailablePort.getRandomAvailablePort(AvailablePort.JGROUPS);
+    props.put(DistributionConfig.MCAST_PORT_NAME, ""+port);
+    props.put(DistributionConfig.MCAST_TTL_NAME, "0");
+    props.put(DistributionConfig.LOCATORS_NAME, "");
+    return getSystem(props);
+  }
 
-    //---------------------------------------------------------------------------
-    // setUp methods
-    //---------------------------------------------------------------------------
-    
-    public final void setUpDistributedTestCase() throws Exception {
-      setUpCreationStackGenerator();
-      
-      System.setProperty(HoplogConfig.ALLOW_LOCAL_HDFS_PROP, "true");
-      GemFireCacheImpl.setDefaultDiskStoreName(getDefaultDiskStoreName()); // TODO: not thread safe
-      
-      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);
-          final String vmDefaultDiskStoreName = "DiskStore-" + h + "-" + v + "-" + testClassName + "." + testMethodName;
-          setUpInVM(vm, testClassName, testMethodName, vmDefaultDiskStoreName);
-        }
-      }
-      //System.out.println("\n\n[setup] START TEST " + getClass().getSimpleName()+"."+testName+"\n\n");
-    }
+  /**
+   * Returns an mcast distributed system that is connected to other
+   * vms using the given mcast port.
+   */
+  public static InternalDistributedSystem getMcastSystem(int jgroupsPort) {
+    Properties props = getDistributedSystemProperties();
+    props.put(DistributionConfig.MCAST_PORT_NAME, ""+jgroupsPort);
+    props.put(DistributionConfig.MCAST_TTL_NAME, "0");
+    props.put(DistributionConfig.LOCATORS_NAME, "");
+    return getSystem(props);
+  }
 
-    private static void setUpInVM(final VM vm, final String testClassNameToUse, final String testMethodNameToUse, final String diskStoreNameToUse) {
-      vm.invoke(new SerializableRunnable() {
-        private static final long serialVersionUID = 1L;
+  /**
+   * Returns whether or this VM is connected to a {@link
+   * DistributedSystem}.
+   */
+  public static boolean isConnectedToDS() {
+    return StaticContext.system != null && StaticContext.system.isConnected();
+  }
 
-        @Override
-        public void run() {
-          setUpCreationStackGenerator();
-          testClassName = testClassNameToUse;
-          testMethodName = testMethodNameToUse;
-          System.setProperty(HoplogConfig.ALLOW_LOCAL_HDFS_PROP, "true");    
-          GemFireCacheImpl.setDefaultDiskStoreName(diskStoreNameToUse); // TODO: not thread safe
-        }
-      });
-    }
+  //---------------------------------------------------------------------------
+  // public cleanup methods
+  //---------------------------------------------------------------------------
+  
+  public static void cleanupAllVms() {
+    cleanupThisVM();
+
+    invokeInEveryVM(new SerializableRunnable() {
+      @Override
+      public void run() {
+        cleanupThisVM();
+      }
+    });
     
-    //---------------------------------------------------------------------------
-    // tearDown methods
-    //---------------------------------------------------------------------------
+    invokeInLocator(new SerializableRunnable() {
+      @Override
+      public void run() {
+        DistributionMessageObserver.setInstance(null);
+        unregisterInstantiatorsInThisVM();
+      }
+    });
     
-    /**
-     * For logPerTest to work, we have to disconnect from the DS, but all
-     * subclasses do not call super.tearDown(). To prevent this scenario
-     * this method has been declared final. Subclasses must now override
-     * {@link #tearDownBefore()} instead.
-     * @throws Exception
-     */
-    public final void tearDownDistributedTestCase() throws Exception {
-      tearDownBefore();
-      realTearDown();
-      tearDownAfter();
-      
-      tearDownCreationStackGenerator();
-
-      tearDownInEveryVM();
-    }
-
-    private static void tearDownInEveryVM() {
-      invokeInEveryVM(new SerializableRunnable() {
-        private static final long serialVersionUID = 1L;
+    DUnitLauncher.closeAndCheckForSuspects();
+  }
 
-        @Override
-        public void run() {    
-          tearDownCreationStackGenerator();
-          testClassName = null;
-          testMethodName = null;
-        }
-      });
-    }
+  public static void unregisterAllDataSerializersFromAllVms() {
+    unregisterDataSerializerInThisVM();
     
-    protected void realTearDown() throws Exception {
-      if (logPerTest) {
-        disconnectFromDS();
-        invokeInEveryVM(DistributedTestCase.class, "disconnectFromDS");
+    invokeInEveryVM(new SerializableRunnable() {
+      @Override
+      public void run() {
+        unregisterDataSerializerInThisVM();
       }
-      cleanupAllVms();
-    }
+    });
     
-    /**
-     * Tears down the test. This method is called by the final {@link #tearDown()} method and should be overridden to
-     * perform actual test cleanup and release resources used by the test.  The tasks executed by this method are
-     * performed before the DUnit test framework using Hydra cleans up the client VMs.
-     * <p/>
-     * @throws Exception if the tear down process and test cleanup fails.
-     * @see #tearDown
-     * @see #tearDownAfter()
-     */
-    protected void tearDownBefore() throws Exception {
-    }
+    invokeInLocator(new SerializableRunnable() {
+      @Override
+      public void run() {
+        unregisterDataSerializerInThisVM();
+      }
+    });
+  }
 
-    /**
-     * Tears down the test.  Performs additional tear down tasks after the DUnit tests framework using Hydra cleans up
-     * the client VMs.  This method is called by the final {@link #tearDown()} method and should be overridden to perform
-     * post tear down activities.
-     * <p/>
-     * @throws Exception if the test tear down process fails.
-     * @see #tearDown()
-     * @see #tearDownBefore()
-     */
-    protected void tearDownAfter() throws Exception {
-    }
+  public static void unregisterInstantiatorsInThisVM() {
+    // unregister all the instantiators
+    InternalInstantiator.reinitialize();
+    assertEquals(0, InternalInstantiator.getInstantiators().length);
+  }
+  
+  public static void unregisterDataSerializerInThisVM() {
+    DataSerializerPropogationDUnitTest.successfullyLoadedTestDataSerializer = false;
+    // unregister all the Dataserializers
+    InternalDataSerializer.reinitialize();
+    // ensure that all are unregistered
+    assertEquals(0, InternalDataSerializer.getSerializers().length);
+  }
 
-    //---------------------------------------------------------------------------
-    // test name methods
-    //---------------------------------------------------------------------------
-    
-    /**
-     * Returns a unique name for this test method.  It is based on the
-     * name of the class as well as the name of the method.
-     */
-    public final String getUniqueName() { // TODO: consider using FQCN
-      return testClassName + "_" + testMethodName;
-    }
+  public static void disconnectAllFromDS() {
+    disconnectFromDS();
+    invokeInEveryVM(new SerializableRunnable() {
+      @Override
+      public void run() { 
+        disconnectFromDS();
+      }
+    });
+  }
 
-    protected static String getTestName() {
-      return testMethodName;
+  /**
+   * Disconnects this VM from the distributed system
+   */
+  public static void disconnectFromDS() {
+    GemFireCacheImpl.testCacheXml = null;
+    
+    if (StaticContext.system != null) {
+      StaticContext.system.disconnect();
+      StaticContext.system = null;
     }
-
-    //---------------------------------------------------------------------------
-    // public final methods
-    //---------------------------------------------------------------------------
     
-    /**
-     * Returns this VM's connection to the distributed system.  If
-     * necessary, the connection will be lazily created using the given
-     * <code>Properties</code>.  Note that this method uses hydra's
-     * configuration to determine the location of log files, etc.
-     * Note: "final" was removed so that WANTestBase can override this method.
-     * This was part of the xd offheap merge.
-     *
-     * @see hydra.DistributedConnectionMgr#connect
-     * @since 3.0
-     */
-    public final InternalDistributedSystem getSystem(Properties properties) {
-      if (system == null) {
-        system = InternalDistributedSystem.getAnyInstance();
+    for (;;) {
+      DistributedSystem ds = InternalDistributedSystem.getConnectedInstance();
+      if (ds == null) {
+        break;
       }
-      
-      if (system == null || !system.isConnected()) {
-        // there is no previous system yet
-        final Properties newProperties = getAllDistributedSystemProperties(properties);
-        previousSystemCreatedInTestClass = getTestClassName();
-        if (logPerTest) {
-          newProperties.put(DistributionConfig.LOG_FILE_NAME, getUniqueName() + ".log");
-          newProperties.put(DistributionConfig.STATISTIC_ARCHIVE_FILE_NAME, getUniqueName() + ".gfs");
-        }
-        system = (InternalDistributedSystem)DistributedSystem.connect(newProperties);
-        previousProperties = newProperties;
-        
-      } else {
-        // there is a previous system
-        boolean needNewSystem = false;
-        //if (!getUniqueName().equals(previousTestName)) {
-        if (!getTestClassName().equals(previousSystemCreatedInTestClass)) {
-          // previous system was created in a previous test class
-          final Properties newProperties = getAllDistributedSystemProperties(properties);
-          needNewSystem = !newProperties.equals(previousProperties);
-          if (needNewSystem) {
-            logger.info(
-                "Test class has changed and the new DS properties are not an exact match. "
-                    + "Forcing DS disconnect. Old props = "
-                    + previousProperties + "new props=" + newProperties);
-          }
-          
-        } else {
-          // previous system was created in this test class
-          final Properties currentProperties = system.getProperties();
-          for (Iterator iter = properties.entrySet().iterator(); iter.hasNext(); ) {
-            final Map.Entry entry = (Map.Entry) iter.next();
-            final String key = (String) entry.getKey();
-            final String value = (String) entry.getValue();
-            if (!value.equals(currentProperties.getProperty(key))) {
-              needNewSystem = true;
-              logger.info("Forcing DS disconnect. For property " + key
-                                  + " old value = " + currentProperties.getProperty(key)
-                                  + " new value = " + value);
-              break;
-            }
-          }
-        }
-        
-        if (needNewSystem) {
-          // the current system does not meet our needs to disconnect and
-          // call recursively to get a new system.
-          logger.info("Disconnecting from current DS in order to make a new one");
-          disconnectFromDS();
-          getSystem(properties);
-        }
+      try {
+        ds.disconnect();
+      }
+      catch (Exception e) {
+        // ignore
       }
-      return system;
     }
     
-    /**
-     * Returns this VM's connection to the distributed system.  If
-     * necessary, the connection will be lazily created using the
-     * <code>Properties</code> returned by {@link
-     * #getDistributedSystemProperties}.
-     *
-     * @see #getSystem(Properties)
-     *
-     * @since 3.0
-     */
-    public final InternalDistributedSystem getSystem() {
-      return getSystem(this.getDistributedSystemProperties());
+    AdminDistributedSystemImpl ads = AdminDistributedSystemImpl.getConnectedInstance();
+    if (ads != null) {
+      ads.disconnect();
     }
+  }
 
-    /**
-     * Returns a loner distributed system that isn't connected to other
-     * vms
-     * 
-     * @since 6.5
-     */
-    public final InternalDistributedSystem getLonerSystem() {
-      Properties props = this.getDistributedSystemProperties();
-      props.put(DistributionConfig.MCAST_PORT_NAME, "0");
-      props.put(DistributionConfig.LOCATORS_NAME, "");
-      return getSystem(props);
-    }
+  //---------------------------------------------------------------------------
+  // private static methods
+  //---------------------------------------------------------------------------
+  
+  private static void setUpDistributedTestCase() throws Exception {
+    setUpCreationStackGenerator();
     
-    /**
-     * Returns a loner distributed system in combination with enforceUniqueHost
-     * and redundancyZone properties.
-     * Added specifically to test scenario of defect #47181.
-     */
-    public final InternalDistributedSystem getLonerSystemWithEnforceUniqueHost() {
-      Properties props = this.getDistributedSystemProperties();
-      props.put(DistributionConfig.MCAST_PORT_NAME, "0");
-      props.put(DistributionConfig.LOCATORS_NAME, "");
-      props.put(DistributionConfig.ENFORCE_UNIQUE_HOST_NAME, "true");
-      props.put(DistributionConfig.REDUNDANCY_ZONE_NAME, "zone1");
-      return getSystem(props);
-    }
+    System.setProperty(HoplogConfig.ALLOW_LOCAL_HDFS_PROP, "true");
 
-    /**
-     * Returns an mcast distributed system that is connected to other
-     * vms using a random mcast port.
-     */
-    public final InternalDistributedSystem getMcastSystem() {
-      Properties props = this.getDistributedSystemProperties();
-      int port = AvailablePort.getRandomAvailablePort(AvailablePort.JGROUPS);
-      props.put(DistributionConfig.MCAST_PORT_NAME, ""+port);
-      props.put(DistributionConfig.MCAST_TTL_NAME, "0");
-      props.put(DistributionConfig.LOCATORS_NAME, "");
-      return getSystem(props);
-    }
-
-    /**
-     * Returns an mcast distributed system that is connected to other
-     * vms using the given mcast port.
-     */
-    public final InternalDistributedSystem getMcastSystem(int jgroupsPort) {
-      Properties props = this.getDistributedSystemProperties();
-      props.put(DistributionConfig.MCAST_PORT_NAME, ""+jgroupsPort);
-      props.put(DistributionConfig.MCAST_TTL_NAME, "0");
-      props.put(DistributionConfig.LOCATORS_NAME, "");
-      return getSystem(props);
-    }
-
-    /**
-     * Returns whether or this VM is connected to a {@link
-     * DistributedSystem}.
-     */
-    public final boolean isConnectedToDS() {
-      return system != null && system.isConnected();
-    }
-
-    //---------------------------------------------------------------------------
-    // public methods
-    //---------------------------------------------------------------------------
+    final String vmid = System.getProperty("vmid");
+    final String defaultDiskStoreName = "DiskStore-"  + vmid + "-"+ StaticContext.testClassName + "." + getTestMethodName();
+    GemFireCacheImpl.setDefaultDiskStoreName(defaultDiskStoreName); // TODO: not thread safe
     
-    /**
-     * Returns a <code>Properties</code> object used to configure a
-     * connection to a {@link
-     * com.gemstone.gemfire.distributed.DistributedSystem}.
-     * Unless overridden, this method will return an empty
-     * <code>Properties</code> object.
-     *
-     * @since 3.0
-     */
-    public Properties getDistributedSystemProperties() {
-      return new Properties();
+    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);
+        final String vmDefaultDiskStoreName = "DiskStore-" + h + "-" + v + "-" + StaticContext.testClassName + "." + StaticContext.testMethodName;
+        setUpInVM(vm, StaticContext.testClassName, StaticContext.testMethodName, vmDefaultDiskStoreName);
+      }
     }
+    //System.out.println("\n\n[setup] START TEST " + getClass().getSimpleName()+"."+testName+"\n\n");
+  }
+  
+  private static void setUpInVM(final VM vm, final String testClassNameToUse, final String testMethodNameToUse, final String diskStoreNameToUse) {
+    vm.invoke(new SerializableRunnable() {
+      @Override
+      public void run() {
+        setUpCreationStackGenerator();
+        StaticContext.testClassName = testClassNameToUse;
+        StaticContext.testMethodName = testMethodNameToUse;
+        System.setProperty(HoplogConfig.ALLOW_LOCAL_HDFS_PROP, "true");    
+        GemFireCacheImpl.setDefaultDiskStoreName(diskStoreNameToUse); // TODO: not thread safe
+      }
+    });
+  }
+    
+  /**
+   * For logPerTest to work, we have to disconnect from the DS, but all
+   * subclasses do not call super.tearDown(). To prevent this scenario
+   * this method has been declared final. Subclasses must now override
+   * {@link #tearDownBefore()} instead.
+   * @throws Exception
+   */
+  private final void tearDownDistributedTestCase() throws Exception {
+    tearDownBefore();
+    realTearDown();
+    tearDownAfter();
+    
+    tearDownCreationStackGenerator();
 
-    //---------------------------------------------------------------------------
-    // private
-    //---------------------------------------------------------------------------
-
-    private String getDefaultDiskStoreName() { // TODO: move
-      String vmid = System.getProperty("vmid");
-      return "DiskStore-"  + vmid + "-"+ testClassName + "." + getTestName();
-    }
+    tearDownInEveryVM();
+  }
 
-    //---------------------------------------------------------------------------
-    // deprecated static methods
-    //---------------------------------------------------------------------------
-    
-    /**
-     * Returns a <code>LogWriter</code> for logging information
-     * @deprecated Use a static logger from the log4j2 LogService.getLogger instead.
-     */
-    @Deprecated
-    public static InternalLogWriter getLogWriter() { // TODO: delete
-      return oldLogger;
+  private static void realTearDown() throws Exception {
+    if (StaticContext.logPerTestClass) {
+      disconnectAllFromDS();
     }
-
-    //---------------------------------------------------------------------------
-    // private static methods
-    //---------------------------------------------------------------------------
+    cleanupAllVms();
+  }
     
-    private static void setUpCreationStackGenerator() {
-      // the following is moved from InternalDistributedSystem to fix #51058
-      InternalDistributedSystem.TEST_CREATION_STACK_GENERATOR.set(
-      new CreationStackGenerator() {
-        @Override
-        public Throwable generateCreationStack(final DistributionConfig config) {
-          final StringBuilder sb = new StringBuilder();
-          final String[] validAttributeNames = config.getAttributeNames();
-          for (int i = 0; i < validAttributeNames.length; i++) {
-            final String attName = validAttributeNames[i];
-            final Object actualAtt = config.getAttributeObject(attName);
-            String actualAttStr = actualAtt.toString();
-            sb.append("  ");
-            sb.append(attName);
-            sb.append("=\"");
-            if (actualAtt.getClass().isArray()) {
-              actualAttStr = InternalDistributedSystem.arrayToString(actualAtt);
-            }
-            sb.append(actualAttStr);
-            sb.append("\"");
-            sb.append("\n");
+  private static void tearDownInEveryVM() {
+    invokeInEveryVM(new SerializableRunnable() {
+      @Override
+      public void run() {    
+        tearDownCreationStackGenerator();
+        StaticContext.testClassName = null;
+        StaticContext.testMethodName = null;
+      }
+    });
+  }
+  
+  private static void setUpCreationStackGenerator() {
+    // the following is moved from InternalDistributedSystem to fix #51058
+    InternalDistributedSystem.TEST_CREATION_STACK_GENERATOR.set(
+    new CreationStackGenerator() {
+      @Override
+      public Throwable generateCreationStack(final DistributionConfig config) {
+        final StringBuilder sb = new StringBuilder();
+        final String[] validAttributeNames = config.getAttributeNames();
+        for (int i = 0; i < validAttributeNames.length; i++) {
+          final String attName = validAttributeNames[i];
+          final Object actualAtt = config.getAttributeObject(attName);
+          String actualAttStr = actualAtt.toString();
+          sb.append("  ");
+          sb.append(attName);
+          sb.append("=\"");
+          if (actualAtt.getClass().isArray()) {
+            actualAttStr = InternalDistributedSystem.arrayToString(actualAtt);
           }
-          return new Throwable("Creating distributed system with the following configuration:\n" + sb.toString());
+          sb.append(actualAttStr);
+          sb.append("\"");
+          sb.append("\n");
         }
-      });
-    }
-    
-    private static void tearDownCreationStackGenerator() {
-      InternalDistributedSystem.TEST_CREATION_STACK_GENERATOR.set(InternalDistributedSystem.DEFAULT_CREATION_STACK_GENERATOR);
-    }
-    
-    //---------------------------------------------------------------------------
-    // tearDown methods
-    //---------------------------------------------------------------------------
-    
-    public static void cleanupAllVms() {
-      cleanupThisVM();
-      invokeInEveryVM(DistributedTestCase.class, "cleanupThisVM");
-      invokeInLocator(new SerializableRunnable() {
-        private static final long serialVersionUID = 1L;
-
-        @Override
-        public void run() {
-          DistributionMessageObserver.setInstance(null);
-          unregisterInstantiatorsInThisVM();
-        }
-      });
-      DUnitLauncher.closeAndCheckForSuspects();
+        return new Throwable("Creating distributed system with the following configuration:\n" + sb.toString());
+      }
+    });
+  }
+  
+  private static void tearDownCreationStackGenerator() {
+    InternalDistributedSystem.TEST_CREATION_STACK_GENERATOR.set(InternalDistributedSystem.DEFAULT_CREATION_STACK_GENERATOR);
+  }
+  
+  private static void cleanupThisVM() {
+    IpAddress.resolve_dns = true;
+    SocketCreator.resolve_dns = true;
+    InitialImageOperation.slowImageProcessing = 0;
+    DistributionMessageObserver.setInstance(null);
+    QueryTestUtils.setCache(null);
+    CacheServerTestUtil.clearCacheReference();
+    RegionTestCase.preSnapshotRegion = null;
+    GlobalLockingDUnitTest.region_testBug32356 = null;
+    LogWrapper.close();
+    ClientProxyMembershipID.system = null;
+    MultiVMRegionTestCase.CCRegion = null;
+    InternalBridgeMembership.unregisterAllListeners();
+    ClientStatsManager.cleanupForTests();
+    unregisterInstantiatorsInThisVM();
+    GemFireTracer.DEBUG = Boolean.getBoolean("DistributionManager.DEBUG_JAVAGROUPS");
+    Protocol.trace = GemFireTracer.DEBUG;
+    DistributionMessageObserver.setInstance(null);
+    QueryObserverHolder.reset();
+    if (InternalDistributedSystem.systemAttemptingReconnect != null) {
+      InternalDistributedSystem.systemAttemptingReconnect.stopReconnecting();
+    }
+    ExpectedExceptionString ex;
+    while((ex = ExpectedExceptionString.poll()) != null) {
+      ex.remove();
     }
+  }
 
-    public static void unregisterAllDataSerializersFromAllVms() {
-      unregisterDataSerializerInThisVM();
-      invokeInEveryVM(new SerializableRunnable() {
-        private static final long serialVersionUID = 1L;
-
-        @Override
-        public void run() {
-          unregisterDataSerializerInThisVM();
-        }
-      });
-      invokeInLocator(new SerializableRunnable() {
-        private static final long serialVersionUID = 1L;
-
-        @Override
-        public void run() {
-          unregisterDataSerializerInThisVM();
-        }
-      });
-    }
+  /**
+   * Builds an instance of DUnitTestRule
+   * 
+   * @author Kirk Lund
+   */
+  public static class Builder {
+    protected Builder() {}
 
-    public static void unregisterInstantiatorsInThisVM() {
-      // unregister all the instantiators
-      InternalInstantiator.reinitialize();
-      assertEquals(0, InternalInstantiator.getInstantiators().length);
+    public Builder vmCount(final int vmCount) {
+      return this;
     }
     
-    public static void unregisterDataSerializerInThisVM() {
-      DataSerializerPropogationDUnitTest.successfullyLoadedTestDataSerializer = false;
-      // unregister all the Dataserializers
-      InternalDataSerializer.reinitialize();
-      // ensure that all are unregistered
-      assertEquals(0, InternalDataSerializer.getSerializers().length);
-    }
-
-    protected static void disconnectAllFromDS() {
-      disconnectFromDS();
-      invokeInEveryVM(DistributedTestCase.class, "disconnectFromDS");
+    public Builder logPerTest(final boolean logPerTest) {
+      return this;
     }
-
-    /**
-     * Disconnects this VM from the distributed system
-     */
-    public static void disconnectFromDS() {
-      GemFireCacheImpl.testCacheXml = null;
-      if (system != null) {
-        system.disconnect();
-        system = null;
-      }
-      
-      for (;;) {
-        DistributedSystem ds = InternalDistributedSystem.getConnectedInstance();
-        if (ds == null) {
-          break;
-        }
-        try {
-          ds.disconnect();
-        }
-        catch (Exception e) {
-          // ignore
-        }
-      }
-      
-      AdminDistributedSystemImpl ads = AdminDistributedSystemImpl.getConnectedInstance();
-      if (ads != null) {// && ads.isConnected()) {
-        ads.disconnect();
-      }
+    
+    public Builder logPerTestClass(final boolean logPerTestClass) {
+      return this;
     }
-
-    private static void cleanupThisVM() {
-      IpAddress.resolve_dns = true;
-      SocketCreator.resolve_dns = true;
-      InitialImageOperation.slowImageProcessing = 0;
-      DistributionMessageObserver.setInstance(null);
-      QueryTestUtils.setCache(null);
-      CacheServerTestUtil.clearCacheReference();
-      RegionTestCase.preSnapshotRegion = null;
-      GlobalLockingDUnitTest.region_testBug32356 = null;
-      LogWrapper.close();
-      ClientProxyMembershipID.system = null;
-      MultiVMRegionTestCase.CCRegion = null;
-      InternalBridgeMembership.unregisterAllListeners();
-      ClientStatsManager.cleanupForTests();
-      unregisterInstantiatorsInThisVM();
-      GemFireTracer.DEBUG = Boolean.getBoolean("DistributionManager.DEBUG_JAVAGROUPS");
-      Protocol.trace = GemFireTracer.DEBUG;
-      DistributionMessageObserver.setInstance(null);
-      QueryObserverHolder.reset();
-      if (InternalDistributedSystem.systemAttemptingReconnect != null) {
-        InternalDistributedSystem.systemAttemptingReconnect.stopReconnecting();
-      }
-      ExpectedExceptionString ex;
-      while((ex = ExpectedExceptionString.poll()) != null) {
-        ex.remove();
-      }
+    
+    public DUnitTestRule build() {
+      return new DUnitTestRule(this);
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/89c0b437/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/DistributedRestoreSystemProperties.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/DistributedRestoreSystemProperties.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/DistributedRestoreSystemProperties.java
new file mode 100755
index 0000000..ca022b9
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/DistributedRestoreSystemProperties.java
@@ -0,0 +1,67 @@
+package com.gemstone.gemfire.test.dunit.rules;
+
+import static com.gemstone.gemfire.test.dunit.Invoke.*;
+import static java.lang.System.getProperties;
+import static java.lang.System.setProperties;
+
+import java.io.Serializable;
+import java.util.Properties;
+
+import org.junit.contrib.java.lang.system.RestoreSystemProperties;
+
+import com.gemstone.gemfire.test.dunit.SerializableRunnable;
+
+/**
+ * Distributed version of RestoreSystemProperties which affects all DUnit 
+ * JVMs including the Locator JVM.
+ * 
+ * @author Kirk Lund
+ */
+@SuppressWarnings("serial")
+public class DistributedRestoreSystemProperties extends RestoreSystemProperties implements Serializable {
+  
+  private static volatile Properties originalProperties;
+
+  private final RemoteInvoker invoker;
+  
+  public DistributedRestoreSystemProperties() {
+   this(new RemoteInvoker());
+  }
+  
+  public DistributedRestoreSystemProperties(final RemoteInvoker invoker) {
+    super();
+    this.invoker = invoker;
+  }
+  
+  
+  @Override
+  protected void before() throws Throwable {
+    super.before();
+    this.invoker.remoteInvokeInEveryVMAndLocator(new SerializableRunnable() {
+      @Override
+      public void run() { 
+        originalProperties = getProperties();
+        setProperties(new Properties(originalProperties));
+      }
+    });
+  }
+
+  @Override
+  protected void after() {
+    super.after();
+    this.invoker.remoteInvokeInEveryVMAndLocator(new SerializableRunnable() {
+      @Override
+      public void run() { 
+        setProperties(originalProperties);
+        originalProperties = null;
+      }
+    });
+  }
+  
+  public static class RemoteInvoker implements Serializable {
+    public void remoteInvokeInEveryVMAndLocator(final SerializableRunnable runnable) {
+      invokeInEveryVM(runnable);
+      invokeInLocator(runnable);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/89c0b437/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/tests/DistributedRestoreSystemPropertiesDUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/tests/DistributedRestoreSystemPropertiesDUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/tests/DistributedRestoreSystemPropertiesDUnitTest.java
new file mode 100755
index 0000000..9164413
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/tests/DistributedRestoreSystemPropertiesDUnitTest.java
@@ -0,0 +1,130 @@
+package com.gemstone.gemfire.test.dunit.rules.tests;
+
+import static com.gemstone.gemfire.test.dunit.Invoke.*;
+import static java.lang.System.*;
+import static org.assertj.core.api.Assertions.*;
+
+import java.io.Serializable;
+import java.util.Properties;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.RuleChain;
+
+import com.gemstone.gemfire.test.dunit.DUnitTestRule;
+import com.gemstone.gemfire.test.dunit.Host;
+import com.gemstone.gemfire.test.dunit.SerializableRunnable;
+import com.gemstone.gemfire.test.dunit.rules.DistributedRestoreSystemProperties;
+import com.gemstone.gemfire.test.junit.categories.DistributedTest;
+import com.gemstone.gemfire.test.junit.rules.SerializableExternalResource;
+
+/**
+ * Distributed tests for DistributedRestoreSystemProperties
+ * 
+ * @author Kirk Lund
+ */
+@Category(DistributedTest.class)
+@SuppressWarnings("serial")
+public class DistributedRestoreSystemPropertiesDUnitTest implements Serializable {
+
+  private static final String PROPERTY_NAME = "PROPERTY_NAME"; 
+  private static final String ORIGINAL_VALUE = "ORIGINAL_VALUE"; 
+  private static final String NEW_VALUE = "NEW_VALUE"; 
+
+  @Rule
+  public transient RuleChain chain = RuleChain
+      .outerRule(new SetUp())
+      .around(new Restore())
+      .around(new Verify())
+      .around(new DistributedRestoreSystemProperties());
+      
+  @Rule
+  public final DUnitTestRule dunitTestRule = new DUnitTestRule();
+  
+  @Test
+  public void shouldRestoreInAllVMs() {
+    invokeInEveryVMAndLocator(new SerializableRunnable("shouldRestoreInAllVMs:setProperty") {
+      @Override
+      public void run() { 
+        setProperty(PROPERTY_NAME, NEW_VALUE);
+      }
+    });
+    
+    invokeInEveryVMAndLocator(new SerializableRunnable("shouldRestoreInAllVMs:assertion") {
+      @Override
+      public void run() { 
+        assertThat(getProperty(PROPERTY_NAME)).isEqualTo(NEW_VALUE);
+      }
+    });
+  }
+  
+  protected static class SetUp extends SerializableExternalResource {
+    
+    @Override
+    protected void before() throws Throwable {
+      assertThat(Host.getHostCount()).isEqualTo(1);
+      assertThat(Host.getHost(0).getVMCount()).isEqualTo(4);
+
+      invokeInEveryVMAndLocator(new SerializableRunnable("SetUp:before") {
+        @Override
+        public void run() { 
+          setProperty(PROPERTY_NAME, ORIGINAL_VALUE);
+        }
+      });
+    }
+
+    @Override
+    protected void after() throws Throwable {
+      invokeInEveryVMAndLocator(new SerializableRunnable("SetUp:after") {
+        @Override
+        public void run() { 
+          clearProperty(PROPERTY_NAME);
+        }
+      });
+    }
+  }
+  
+  protected static class Verify extends SerializableExternalResource {
+    
+    @Override
+    protected void before() throws Throwable {
+      invokeInEveryVMAndLocator(new SerializableRunnable("Verify:before") {
+        @Override
+        public void run() { 
+          assertThat(getProperty(PROPERTY_NAME)).isEqualTo(ORIGINAL_VALUE);
+        }
+      });
+    }
+    
+    @Override
+    protected void after() {
+      invokeInEveryVMAndLocator(new SerializableRunnable("Verify:after") {
+        @Override
+        public void run() { 
+          assertThat(getProperty(PROPERTY_NAME)).isEqualTo(ORIGINAL_VALUE);
+        }
+      });
+    }
+  }
+  
+  private static void invokeInEveryVMAndLocator(final SerializableRunnable runnable) {
+    runnable.run();
+    invokeInEveryVM(runnable);
+    invokeInLocator(runnable);
+  }
+  
+  protected static class Restore extends SerializableExternalResource {
+    private Properties originalProperties;
+    
+    @Override
+    protected void before() throws Throwable {
+      originalProperties = System.getProperties();
+    }
+    
+    @Override
+    protected void after() {
+      setProperties(originalProperties);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/89c0b437/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/tests/DistributedRestoreSystemPropertiesJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/tests/DistributedRestoreSystemPropertiesJUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/tests/DistributedRestoreSystemPropertiesJUnitTest.java
new file mode 100755
index 0000000..edd2ad7
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/tests/DistributedRestoreSystemPropertiesJUnitTest.java
@@ -0,0 +1,74 @@
+package com.gemstone.gemfire.test.dunit.rules.tests;
+
+import static com.gemstone.gemfire.test.junit.rules.tests.RunTest.*;
+import static com.gemstone.gemfire.test.dunit.rules.DistributedRestoreSystemProperties.*;
+import static java.lang.System.*;
+import static org.assertj.core.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.Result;
+
+import com.gemstone.gemfire.test.dunit.SerializableRunnable;
+import com.gemstone.gemfire.test.dunit.rules.DistributedRestoreSystemProperties;
+import com.gemstone.gemfire.test.junit.categories.UnitTest;
+
+/**
+ * Unit tests for DistributedRestoreSystemProperties
+ * 
+ * @author Kirk Lund
+ */
+@Category(UnitTest.class)
+public class DistributedRestoreSystemPropertiesJUnitTest {
+
+  private static final String SOME_PROPERTY = "SOME_PROPERTY"; 
+  private static final String SOME_PROPERTY_ORIG_VALUE = "SOME_PROPERTY_ORIG_VALUE"; 
+  private static final String SOME_PROPERTY_NEW_VALUE = "SOME_PROPERTY_NEW_VALUE"; 
+
+  private static final AtomicReference<RemoteInvoker> remoteInvokerRef = new AtomicReference<RemoteInvoker>();
+  
+  @Before
+  public void before() {
+    setProperty(SOME_PROPERTY, SOME_PROPERTY_ORIG_VALUE);
+    remoteInvokerRef.set(mock(RemoteInvoker.class));
+  }
+  
+  @After
+  public void after() {
+    clearProperty(SOME_PROPERTY);
+  }
+  
+  @Test
+  public void shouldResetOriginalValue() {
+    Result result = runTest(SetProperty.class);
+    
+    assertThat(result.wasSuccessful()).isTrue();
+    assertThat(getProperty(SOME_PROPERTY)).isEqualTo(SOME_PROPERTY_ORIG_VALUE);
+  }
+  
+  @Test
+  public void shouldInvokeRemoteInvoker() {
+    Result result = runTest(SetProperty.class);
+    
+    assertThat(result.wasSuccessful()).isTrue();
+    verify(remoteInvokerRef.get(), times(2)).remoteInvokeInEveryVMAndLocator(isA(SerializableRunnable.class));
+  }
+  
+  public static class SetProperty {
+    
+    @Rule
+    public final DistributedRestoreSystemProperties ruleChain = new DistributedRestoreSystemProperties(remoteInvokerRef.get());
+
+    @Test
+    public void doTest() throws Exception {
+      setProperty(SOME_PROPERTY, SOME_PROPERTY_NEW_VALUE);
+    }
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/89c0b437/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/DUnitTestRuleTestSuite.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/DUnitTestRuleTestSuite.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/DUnitTestRuleTestSuite.java
new file mode 100755
index 0000000..2153b8e
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/DUnitTestRuleTestSuite.java
@@ -0,0 +1,28 @@
+package com.gemstone.gemfire.test.dunit.tests;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+import com.gemstone.gemfire.distributed.DistributedMemberDUnitTest;
+import com.gemstone.gemfire.distributed.HostedLocatorsDUnitTest;
+import com.gemstone.gemfire.internal.offheap.OutOfOffHeapMemoryDUnitTest;
+import com.gemstone.gemfire.test.examples.CatchExceptionExampleDUnitTest;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+//  BasicDUnitTest.class,
+//  DistributedTestNameDUnitTest.class,
+  DistributedTestNameWithRuleDUnitTest.class,
+  SerializableTemporaryFolderDUnitTest.class,
+  SerializableTestNameDUnitTest.class,
+  SerializableTestWatcherDUnitTest.class,
+//  VMDUnitTest.class,
+//  VMMoreDUnitTest.class,
+  
+  CatchExceptionExampleDUnitTest.class,
+  DistributedMemberDUnitTest.class,
+//  HostedLocatorsDUnitTest.class,
+//  OutOfOffHeapMemoryDUnitTest.class,
+})
+public class DUnitTestRuleTestSuite {
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/89c0b437/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/MyTestSuite.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/MyTestSuite.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/MyTestSuite.java
index 9d9b2a4..e0411e2 100755
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/MyTestSuite.java
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/MyTestSuite.java
@@ -6,7 +6,7 @@ import org.junit.runners.Suite;
 import com.gemstone.gemfire.distributed.DistributedMemberDUnitTest;
 import com.gemstone.gemfire.distributed.HostedLocatorsDUnitTest;
 import com.gemstone.gemfire.internal.offheap.OutOfOffHeapMemoryDUnitTest;
-import com.gemstone.gemfire.test.catchexception.CatchExceptionExampleDUnitTest;
+import com.gemstone.gemfire.test.examples.CatchExceptionExampleDUnitTest;
 
 @RunWith(Suite.class)
 @Suite.SuiteClasses({

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/89c0b437/gemfire-core/src/test/java/com/gemstone/gemfire/test/examples/AssertJExampleJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/examples/AssertJExampleJUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/examples/AssertJExampleJUnitTest.java
new file mode 100755
index 0000000..2f97cef
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/examples/AssertJExampleJUnitTest.java
@@ -0,0 +1,119 @@
+package com.gemstone.gemfire.test.examples;
+
+import static org.assertj.core.api.Assertions.*;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import com.gemstone.gemfire.test.junit.categories.UnitTest;
+
+@Category(UnitTest.class)
+public class AssertJExampleJUnitTest {
+
+  private Character aragorn;
+  private Character boromir;
+  private Character elrond;
+  private Character frodo;
+  private Character galadriel;
+  private Character gandalf;
+  private Character gimli;
+  private Character legolas;
+  private Character merry;
+  private Character pippin;
+  private Character sauron;
+  private Character sam;
+  
+  private Ring narya;
+  private Ring nenya;
+  private Ring oneRing;
+  private Ring vilya;
+  
+  private Set<Character> fellowshipOfTheRing;
+  private Map<Ring, Character> ringBearers;
+  
+  @Before
+  public void setUp() {
+    this.aragorn = new Character("Aragorn");
+    this.boromir = new Character("Boromir");
+    this.elrond = new Character("Elrond");
+    this.frodo = new Character("Frodo");
+    this.galadriel = new Character("Galadriel");
+    this.gandalf = new Character("Gandalf");
+    this.gimli = new Character("Gimli");
+    this.legolas = new Character("Legolas");
+    this.merry = new Character("Merry");
+    this.pippin = new Character("Pippin");
+    this.sauron = new Character("Sauron");
+    this.sam = new Character("Sam");
+    
+    this.narya = new Ring();
+    this.nenya = new Ring();
+    this.oneRing = new Ring();
+    this.vilya = new Ring();
+    
+    this.fellowshipOfTheRing = new HashSet<Character>();
+    this.fellowshipOfTheRing.add(this.aragorn);
+    this.fellowshipOfTheRing.add(this.boromir);
+    this.fellowshipOfTheRing.add(this.frodo);
+    this.fellowshipOfTheRing.add(this.gandalf);
+    this.fellowshipOfTheRing.add(this.gimli);
+    this.fellowshipOfTheRing.add(this.legolas);
+    this.fellowshipOfTheRing.add(this.merry);
+    this.fellowshipOfTheRing.add(this.pippin);
+    this.fellowshipOfTheRing.add(this.sam);
+
+    this.ringBearers = new HashMap<Ring, Character>();
+    this.ringBearers.put(this.oneRing, this.frodo);
+    this.ringBearers.put(this.nenya, this.galadriel);
+    this.ringBearers.put(this.narya, this.gandalf);
+    this.ringBearers.put(this.vilya, this.elrond);
+  }
+  
+  @Test
+  public void exampleShouldPass() {
+    // common assertions
+    assertThat(frodo.getName()).isEqualTo("Frodo");
+    assertThat(frodo).isNotEqualTo(sauron)
+                     .isIn(fellowshipOfTheRing);
+
+    // String specific assertions
+    assertThat(frodo.getName()).startsWith("Fro")
+                               .endsWith("do")
+                               .isEqualToIgnoringCase("frodo");
+
+    // collection specific assertions
+    assertThat(fellowshipOfTheRing).hasSize(9)
+                                   .contains(frodo, sam)
+                                   .doesNotContain(sauron);
+
+    // using extracting magical feature to check fellowshipOfTheRing characters name :)
+    assertThat(fellowshipOfTheRing).extracting("name").contains("Boromir", "Gandalf", "Frodo", "Legolas")
+                                                      .doesNotContain("Sauron", "Elrond");
+
+    // map specific assertions, ringBearers initialized with the elves rings and the one ring bearers.
+    assertThat(ringBearers).hasSize(4)
+                           .contains(entry(oneRing, frodo), entry(nenya, galadriel))
+                           .doesNotContainEntry(oneRing, aragorn);  
+  }
+  
+  protected static class Character {
+    private final String name;
+    public Character(final String name) {
+      this.name = name;
+    }
+    public String getName() {
+      return this.name;
+    }
+  }
+  
+  protected static class Ring {
+    public Ring() {
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/89c0b437/gemfire-core/src/test/java/com/gemstone/gemfire/test/examples/CatchExceptionExampleDUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/examples/CatchExceptionExampleDUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/examples/CatchExceptionExampleDUnitTest.java
new file mode 100755
index 0000000..04a45c5
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/examples/CatchExceptionExampleDUnitTest.java
@@ -0,0 +1,62 @@
+package com.gemstone.gemfire.test.examples;
+
+import static com.googlecode.catchexception.CatchException.*;
+import static org.assertj.core.api.Assertions.*;
+
+import java.io.Serializable;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import com.gemstone.gemfire.test.dunit.DUnitTestRule;
+import com.gemstone.gemfire.test.dunit.Host;
+import com.gemstone.gemfire.test.dunit.RMIException;
+import com.gemstone.gemfire.test.dunit.SerializableCallable;
+import com.gemstone.gemfire.test.dunit.VM;
+import com.gemstone.gemfire.test.junit.categories.DistributedTest;
+
+/**
+ * Using Catch-Exception works well for remote exceptions and asserting details
+ * about root cause of RMIExceptions in DUnit tests.
+ */
+@Category(DistributedTest.class)
+@SuppressWarnings("serial")
+public class CatchExceptionExampleDUnitTest implements Serializable {
+
+  private static final String REMOTE_THROW_EXCEPTION_MESSAGE = "Throwing remoteThrowException";
+
+  @Rule
+  public final DUnitTestRule dunitTestRule = new DUnitTestRule();
+  
+  @Test
+  public void testRemoteInvocationWithException() {
+    Host host = Host.getHost(0);
+    VM vm = host.getVM(0);
+
+    catchException(vm).invoke(new ThrowBasicTestException());
+
+    assertThat(caughtException())
+        .isInstanceOf(RMIException.class)
+        .hasCause(new BasicTestException(REMOTE_THROW_EXCEPTION_MESSAGE));
+  }
+  
+  protected static class ThrowBasicTestException extends SerializableCallable<Object> {
+
+    @Override
+    public Object call() throws Exception {
+      throw new BasicTestException(REMOTE_THROW_EXCEPTION_MESSAGE);
+    }
+  }
+  
+  protected static class BasicTestException extends RuntimeException {
+
+    public BasicTestException() {
+      super();
+    }
+    
+    public BasicTestException(String message) {
+      super(message);
+    }
+  }
+}